X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fviotape.c;h=34a48d2f277fe268bd20117ae81178e070909afc;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=a5915c1e764b0b9eb34030ac067e8dcacb8aaaa4;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index a5915c1e7..34a48d2f2 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -53,6 +53,7 @@ #include #include +#include #include #include #include @@ -216,7 +217,7 @@ static const struct vio_error_entry viotape_err_table[] = { }; /* Maximum number of tapes we support */ -#define VIOTAPE_MAX_TAPE 8 +#define VIOTAPE_MAX_TAPE HVMAXARCHITECTEDVIRTUALTAPES #define MAX_PARTITIONS 4 /* defines for current tape state */ @@ -238,6 +239,8 @@ static struct mtget viomtget[VIOTAPE_MAX_TAPE]; static struct class_simple *tape_class; +static struct device *tape_device[VIOTAPE_MAX_TAPE]; + /* * maintain the current state of each tape (and partition) * so that we know when to write EOF marks. @@ -262,6 +265,7 @@ struct op_struct { int rc; int non_blocking; struct completion com; + struct device *dev; struct op_struct *next; }; @@ -459,7 +463,8 @@ static ssize_t viotap_write(struct file *file, const char *buf, down(&reqSem); /* Allocate a DMA buffer */ - op->buffer = dma_alloc_coherent(iSeries_vio_dev, count, &op->dmaaddr, + op->dev = tape_device[devi.devno]; + op->buffer = dma_alloc_coherent(op->dev, count, &op->dmaaddr, GFP_ATOMIC); if (op->buffer == NULL) { @@ -509,7 +514,7 @@ static ssize_t viotap_write(struct file *file, const char *buf, } free_dma: - dma_free_coherent(iSeries_vio_dev, count, op->buffer, op->dmaaddr); + dma_free_coherent(op->dev, count, op->buffer, op->dmaaddr); up_sem: up(&reqSem); free_op: @@ -550,7 +555,8 @@ static ssize_t viotap_read(struct file *file, char *buf, size_t count, chg_state(devi.devno, VIOT_READING, file); /* Allocate a DMA buffer */ - op->buffer = dma_alloc_coherent(iSeries_vio_dev, count, &op->dmaaddr, + op->dev = tape_device[devi.devno]; + op->buffer = dma_alloc_coherent(op->dev, count, &op->dmaaddr, GFP_ATOMIC); if (op->buffer == NULL) { ret = -EFAULT; @@ -588,7 +594,7 @@ static ssize_t viotap_read(struct file *file, char *buf, size_t count, } free_dma: - dma_free_coherent(iSeries_vio_dev, count, op->buffer, op->dmaaddr); + dma_free_coherent(op->dev, count, op->buffer, op->dmaaddr); up_sem: up(&reqSem); free_op: @@ -910,7 +916,7 @@ static void vioHandleTapeEvent(struct HvLpEvent *event) break; case viotapewrite: if (op->non_blocking) { - dma_free_coherent(iSeries_vio_dev, op->count, + dma_free_coherent(op->dev, op->count, op->buffer, op->dmaaddr); free_op_struct(op); up(&reqSem); @@ -936,12 +942,70 @@ static void vioHandleTapeEvent(struct HvLpEvent *event) } } +static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id) +{ + char tapename[32]; + int i = vdev->unit_address; + int j; + + if (i >= viotape_numdev) + return -ENODEV; + + tape_device[i] = &vdev->dev; + + state[i].cur_part = 0; + for (j = 0; j < MAX_PARTITIONS; ++j) + state[i].part_stat_rwi[j] = VIOT_IDLE; + class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL, + "iseries!vt%d", i); + class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80), + NULL, "iseries!nvt%d", i); + devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR, + "iseries/vt%d", i); + devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i | 0x80), + S_IFCHR | S_IRUSR | S_IWUSR, "iseries/nvt%d", i); + sprintf(tapename, "iseries/vt%d", i); + state[i].dev_handle = devfs_register_tape(tapename); + printk(VIOTAPE_KERN_INFO "tape %s is iSeries " + "resource %10.10s type %4.4s, model %3.3s\n", + tapename, viotape_unitinfo[i].rsrcname, + viotape_unitinfo[i].type, viotape_unitinfo[i].model); + return 0; +} + +static int viotape_remove(struct vio_dev *vdev) +{ + int i = vdev->unit_address; + + devfs_remove("iseries/nvt%d", i); + devfs_remove("iseries/vt%d", i); + devfs_unregister_tape(state[i].dev_handle); + class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i | 0x80)); + class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i)); + return 0; +} + +/** + * viotape_device_table: Used by vio.c to match devices that we + * support. + */ +static struct vio_device_id viotape_device_table[] __devinitdata = { + { "viotape", "" }, + { 0, } +}; + +MODULE_DEVICE_TABLE(vio, viotape_device_table); +static struct vio_driver viotape_driver = { + .name = "viotape", + .id_table = viotape_device_table, + .probe = viotape_probe, + .remove = viotape_remove +}; + int __init viotap_init(void) { int ret; - char tapename[32]; - int i; struct proc_dir_entry *e; op_struct_list = NULL; @@ -993,31 +1057,9 @@ int __init viotap_init(void) goto unreg_class; } - for (i = 0; i < viotape_numdev; i++) { - int j; - - state[i].cur_part = 0; - for (j = 0; j < MAX_PARTITIONS; ++j) - state[i].part_stat_rwi[j] = VIOT_IDLE; - class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i), - NULL, "iseries!vt%d", i); - class_simple_device_add(tape_class, - MKDEV(VIOTAPE_MAJOR, i | 0x80), - NULL, "iseries!nvt%d", i); - devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), - S_IFCHR | S_IRUSR | S_IWUSR, - "iseries/vt%d", i); - devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i | 0x80), - S_IFCHR | S_IRUSR | S_IWUSR, - "iseries/nvt%d", i); - sprintf(tapename, "iseries/vt%d", i); - state[i].dev_handle = devfs_register_tape(tapename); - printk(VIOTAPE_KERN_INFO "tape %s is iSeries " - "resource %10.10s type %4.4s, model %3.3s\n", - tapename, viotape_unitinfo[i].rsrcname, - viotape_unitinfo[i].type, - viotape_unitinfo[i].model); - } + ret = vio_register_driver(&viotape_driver); + if (ret) + goto unreg_class; e = create_proc_entry("iSeries/viotape", S_IFREG|S_IRUGO, NULL); if (e) { @@ -1064,17 +1106,10 @@ static int chg_state(int index, unsigned char new_state, struct file *file) /* Cleanup */ static void __exit viotap_exit(void) { - int i, ret; + int ret; remove_proc_entry("iSeries/viotape", NULL); - - for (i = 0; i < viotape_numdev; ++i) { - devfs_remove("iseries/nvt%d", i); - devfs_remove("iseries/vt%d", i); - devfs_unregister_tape(state[i].dev_handle); - class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i | 0x80)); - class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i)); - } + vio_unregister_driver(&viotape_driver); class_simple_destroy(tape_class); ret = unregister_chrdev(VIOTAPE_MAJOR, "viotape"); if (ret < 0)