diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/viodasd.c | 77 | ||||
-rw-r--r-- | drivers/cdrom/viocd.c | 128 | ||||
-rw-r--r-- | drivers/char/viotape.c | 125 |
3 files changed, 62 insertions, 268 deletions
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index af3969a9c963..e824b672e05a 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c | |||
@@ -74,53 +74,9 @@ enum { | |||
74 | static DEFINE_SPINLOCK(viodasd_spinlock); | 74 | static DEFINE_SPINLOCK(viodasd_spinlock); |
75 | 75 | ||
76 | #define VIOMAXREQ 16 | 76 | #define VIOMAXREQ 16 |
77 | #define VIOMAXBLOCKDMA 12 | ||
78 | 77 | ||
79 | #define DEVICE_NO(cell) ((struct viodasd_device *)(cell) - &viodasd_devices[0]) | 78 | #define DEVICE_NO(cell) ((struct viodasd_device *)(cell) - &viodasd_devices[0]) |
80 | 79 | ||
81 | struct open_data { | ||
82 | u64 disk_size; | ||
83 | u16 max_disk; | ||
84 | u16 cylinders; | ||
85 | u16 tracks; | ||
86 | u16 sectors; | ||
87 | u16 bytes_per_sector; | ||
88 | }; | ||
89 | |||
90 | struct rw_data { | ||
91 | u64 offset; | ||
92 | struct { | ||
93 | u32 token; | ||
94 | u32 reserved; | ||
95 | u64 len; | ||
96 | } dma_info[VIOMAXBLOCKDMA]; | ||
97 | }; | ||
98 | |||
99 | struct vioblocklpevent { | ||
100 | struct HvLpEvent event; | ||
101 | u32 reserved; | ||
102 | u16 version; | ||
103 | u16 sub_result; | ||
104 | u16 disk; | ||
105 | u16 flags; | ||
106 | union { | ||
107 | struct open_data open_data; | ||
108 | struct rw_data rw_data; | ||
109 | u64 changed; | ||
110 | } u; | ||
111 | }; | ||
112 | |||
113 | #define vioblockflags_ro 0x0001 | ||
114 | |||
115 | enum vioblocksubtype { | ||
116 | vioblockopen = 0x0001, | ||
117 | vioblockclose = 0x0002, | ||
118 | vioblockread = 0x0003, | ||
119 | vioblockwrite = 0x0004, | ||
120 | vioblockflush = 0x0005, | ||
121 | vioblockcheck = 0x0007 | ||
122 | }; | ||
123 | |||
124 | struct viodasd_waitevent { | 80 | struct viodasd_waitevent { |
125 | struct completion com; | 81 | struct completion com; |
126 | int rc; | 82 | int rc; |
@@ -429,7 +385,7 @@ static void do_viodasd_request(struct request_queue *q) | |||
429 | * Probe a single disk and fill in the viodasd_device structure | 385 | * Probe a single disk and fill in the viodasd_device structure |
430 | * for it. | 386 | * for it. |
431 | */ | 387 | */ |
432 | static void probe_disk(struct viodasd_device *d) | 388 | static int probe_disk(struct viodasd_device *d) |
433 | { | 389 | { |
434 | HvLpEvent_Rc hvrc; | 390 | HvLpEvent_Rc hvrc; |
435 | struct viodasd_waitevent we; | 391 | struct viodasd_waitevent we; |
@@ -453,14 +409,14 @@ retry: | |||
453 | 0, 0, 0); | 409 | 0, 0, 0); |
454 | if (hvrc != 0) { | 410 | if (hvrc != 0) { |
455 | printk(VIOD_KERN_WARNING "bad rc on HV open %d\n", (int)hvrc); | 411 | printk(VIOD_KERN_WARNING "bad rc on HV open %d\n", (int)hvrc); |
456 | return; | 412 | return 0; |
457 | } | 413 | } |
458 | 414 | ||
459 | wait_for_completion(&we.com); | 415 | wait_for_completion(&we.com); |
460 | 416 | ||
461 | if (we.rc != 0) { | 417 | if (we.rc != 0) { |
462 | if (flags != 0) | 418 | if (flags != 0) |
463 | return; | 419 | return 0; |
464 | /* try again with read only flag set */ | 420 | /* try again with read only flag set */ |
465 | flags = vioblockflags_ro; | 421 | flags = vioblockflags_ro; |
466 | goto retry; | 422 | goto retry; |
@@ -490,15 +446,32 @@ retry: | |||
490 | if (hvrc != 0) { | 446 | if (hvrc != 0) { |
491 | printk(VIOD_KERN_WARNING | 447 | printk(VIOD_KERN_WARNING |
492 | "bad rc sending event to OS/400 %d\n", (int)hvrc); | 448 | "bad rc sending event to OS/400 %d\n", (int)hvrc); |
493 | return; | 449 | return 0; |
494 | } | 450 | } |
451 | |||
452 | if (d->dev == NULL) { | ||
453 | /* this is when we reprobe for new disks */ | ||
454 | if (vio_create_viodasd(dev_no) == NULL) { | ||
455 | printk(VIOD_KERN_WARNING | ||
456 | "cannot allocate virtual device for disk %d\n", | ||
457 | dev_no); | ||
458 | return 0; | ||
459 | } | ||
460 | /* | ||
461 | * The vio_create_viodasd will have recursed into this | ||
462 | * routine with d->dev set to the new vio device and | ||
463 | * will finish the setup of the disk below. | ||
464 | */ | ||
465 | return 1; | ||
466 | } | ||
467 | |||
495 | /* create the request queue for the disk */ | 468 | /* create the request queue for the disk */ |
496 | spin_lock_init(&d->q_lock); | 469 | spin_lock_init(&d->q_lock); |
497 | q = blk_init_queue(do_viodasd_request, &d->q_lock); | 470 | q = blk_init_queue(do_viodasd_request, &d->q_lock); |
498 | if (q == NULL) { | 471 | if (q == NULL) { |
499 | printk(VIOD_KERN_WARNING "cannot allocate queue for disk %d\n", | 472 | printk(VIOD_KERN_WARNING "cannot allocate queue for disk %d\n", |
500 | dev_no); | 473 | dev_no); |
501 | return; | 474 | return 0; |
502 | } | 475 | } |
503 | g = alloc_disk(1 << PARTITION_SHIFT); | 476 | g = alloc_disk(1 << PARTITION_SHIFT); |
504 | if (g == NULL) { | 477 | if (g == NULL) { |
@@ -506,7 +479,7 @@ retry: | |||
506 | "cannot allocate disk structure for disk %d\n", | 479 | "cannot allocate disk structure for disk %d\n", |
507 | dev_no); | 480 | dev_no); |
508 | blk_cleanup_queue(q); | 481 | blk_cleanup_queue(q); |
509 | return; | 482 | return 0; |
510 | } | 483 | } |
511 | 484 | ||
512 | d->disk = g; | 485 | d->disk = g; |
@@ -538,6 +511,7 @@ retry: | |||
538 | 511 | ||
539 | /* register us in the global list */ | 512 | /* register us in the global list */ |
540 | add_disk(g); | 513 | add_disk(g); |
514 | return 1; | ||
541 | } | 515 | } |
542 | 516 | ||
543 | /* returns the total number of scatterlist elements converted */ | 517 | /* returns the total number of scatterlist elements converted */ |
@@ -718,8 +692,7 @@ static int viodasd_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
718 | struct viodasd_device *d = &viodasd_devices[vdev->unit_address]; | 692 | struct viodasd_device *d = &viodasd_devices[vdev->unit_address]; |
719 | 693 | ||
720 | d->dev = &vdev->dev; | 694 | d->dev = &vdev->dev; |
721 | probe_disk(d); | 695 | if (!probe_disk(d)) |
722 | if (d->disk == NULL) | ||
723 | return -ENODEV; | 696 | return -ENODEV; |
724 | return 0; | 697 | return 0; |
725 | } | 698 | } |
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index e51550db1575..880b5dce3a62 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c | |||
@@ -56,30 +56,6 @@ | |||
56 | #define VIOCD_KERN_WARNING KERN_WARNING "viocd: " | 56 | #define VIOCD_KERN_WARNING KERN_WARNING "viocd: " |
57 | #define VIOCD_KERN_INFO KERN_INFO "viocd: " | 57 | #define VIOCD_KERN_INFO KERN_INFO "viocd: " |
58 | 58 | ||
59 | struct viocdlpevent { | ||
60 | struct HvLpEvent event; | ||
61 | u32 reserved; | ||
62 | u16 version; | ||
63 | u16 sub_result; | ||
64 | u16 disk; | ||
65 | u16 flags; | ||
66 | u32 token; | ||
67 | u64 offset; /* On open, max number of disks */ | ||
68 | u64 len; /* On open, size of the disk */ | ||
69 | u32 block_size; /* Only set on open */ | ||
70 | u32 media_size; /* Only set on open */ | ||
71 | }; | ||
72 | |||
73 | enum viocdsubtype { | ||
74 | viocdopen = 0x0001, | ||
75 | viocdclose = 0x0002, | ||
76 | viocdread = 0x0003, | ||
77 | viocdwrite = 0x0004, | ||
78 | viocdlockdoor = 0x0005, | ||
79 | viocdgetinfo = 0x0006, | ||
80 | viocdcheck = 0x0007 | ||
81 | }; | ||
82 | |||
83 | /* | 59 | /* |
84 | * Should probably make this a module parameter....sigh | 60 | * Should probably make this a module parameter....sigh |
85 | */ | 61 | */ |
@@ -131,22 +107,13 @@ static struct capability_entry capability_table[] __initdata = { | |||
131 | /* These are our internal structures for keeping track of devices */ | 107 | /* These are our internal structures for keeping track of devices */ |
132 | static int viocd_numdev; | 108 | static int viocd_numdev; |
133 | 109 | ||
134 | struct cdrom_info { | ||
135 | char rsrcname[10]; | ||
136 | char type[4]; | ||
137 | char model[3]; | ||
138 | }; | ||
139 | /* | ||
140 | * This needs to be allocated since it is passed to the | ||
141 | * Hypervisor and we may be a module. | ||
142 | */ | ||
143 | static struct cdrom_info *viocd_unitinfo; | ||
144 | static dma_addr_t unitinfo_dmaaddr; | ||
145 | |||
146 | struct disk_info { | 110 | struct disk_info { |
147 | struct gendisk *viocd_disk; | 111 | struct gendisk *viocd_disk; |
148 | struct cdrom_device_info viocd_info; | 112 | struct cdrom_device_info viocd_info; |
149 | struct device *dev; | 113 | struct device *dev; |
114 | const char *rsrcname; | ||
115 | const char *type; | ||
116 | const char *model; | ||
150 | }; | 117 | }; |
151 | static struct disk_info viocd_diskinfo[VIOCD_MAX_CD]; | 118 | static struct disk_info viocd_diskinfo[VIOCD_MAX_CD]; |
152 | 119 | ||
@@ -164,9 +131,9 @@ static int proc_viocd_show(struct seq_file *m, void *v) | |||
164 | for (i = 0; i < viocd_numdev; i++) { | 131 | for (i = 0; i < viocd_numdev; i++) { |
165 | seq_printf(m, "viocd device %d is iSeries resource %10.10s" | 132 | seq_printf(m, "viocd device %d is iSeries resource %10.10s" |
166 | "type %4.4s, model %3.3s\n", | 133 | "type %4.4s, model %3.3s\n", |
167 | i, viocd_unitinfo[i].rsrcname, | 134 | i, viocd_diskinfo[i].rsrcname, |
168 | viocd_unitinfo[i].type, | 135 | viocd_diskinfo[i].type, |
169 | viocd_unitinfo[i].model); | 136 | viocd_diskinfo[i].model); |
170 | } | 137 | } |
171 | return 0; | 138 | return 0; |
172 | } | 139 | } |
@@ -216,61 +183,6 @@ struct block_device_operations viocd_fops = { | |||
216 | .media_changed = viocd_blk_media_changed, | 183 | .media_changed = viocd_blk_media_changed, |
217 | }; | 184 | }; |
218 | 185 | ||
219 | /* Get info on CD devices from OS/400 */ | ||
220 | static void __init get_viocd_info(void) | ||
221 | { | ||
222 | HvLpEvent_Rc hvrc; | ||
223 | int i; | ||
224 | struct viocd_waitevent we; | ||
225 | |||
226 | viocd_unitinfo = dma_alloc_coherent(iSeries_vio_dev, | ||
227 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, | ||
228 | &unitinfo_dmaaddr, GFP_ATOMIC); | ||
229 | if (viocd_unitinfo == NULL) { | ||
230 | printk(VIOCD_KERN_WARNING "error allocating unitinfo\n"); | ||
231 | return; | ||
232 | } | ||
233 | |||
234 | memset(viocd_unitinfo, 0, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD); | ||
235 | |||
236 | init_completion(&we.com); | ||
237 | |||
238 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, | ||
239 | HvLpEvent_Type_VirtualIo, | ||
240 | viomajorsubtype_cdio | viocdgetinfo, | ||
241 | HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, | ||
242 | viopath_sourceinst(viopath_hostLp), | ||
243 | viopath_targetinst(viopath_hostLp), | ||
244 | (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0, | ||
245 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, 0); | ||
246 | if (hvrc != HvLpEvent_Rc_Good) { | ||
247 | printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n", | ||
248 | (int)hvrc); | ||
249 | goto error_ret; | ||
250 | } | ||
251 | |||
252 | wait_for_completion(&we.com); | ||
253 | |||
254 | if (we.rc) { | ||
255 | const struct vio_error_entry *err = | ||
256 | vio_lookup_rc(viocd_err_table, we.sub_result); | ||
257 | printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n", | ||
258 | we.rc, we.sub_result, err->msg); | ||
259 | goto error_ret; | ||
260 | } | ||
261 | |||
262 | for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++) | ||
263 | viocd_numdev++; | ||
264 | |||
265 | error_ret: | ||
266 | if (viocd_numdev == 0) { | ||
267 | dma_free_coherent(iSeries_vio_dev, | ||
268 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, | ||
269 | viocd_unitinfo, unitinfo_dmaaddr); | ||
270 | viocd_unitinfo = NULL; | ||
271 | } | ||
272 | } | ||
273 | |||
274 | static int viocd_open(struct cdrom_device_info *cdi, int purpose) | 186 | static int viocd_open(struct cdrom_device_info *cdi, int purpose) |
275 | { | 187 | { |
276 | struct disk_info *diskinfo = cdi->handle; | 188 | struct disk_info *diskinfo = cdi->handle; |
@@ -581,7 +493,6 @@ static void vio_handle_cd_event(struct HvLpEvent *event) | |||
581 | bevent->block_size / 512); | 493 | bevent->block_size / 512); |
582 | } | 494 | } |
583 | /* FALLTHROUGH !! */ | 495 | /* FALLTHROUGH !! */ |
584 | case viocdgetinfo: | ||
585 | case viocdlockdoor: | 496 | case viocdlockdoor: |
586 | pwe = (struct viocd_waitevent *)event->xCorrelationToken; | 497 | pwe = (struct viocd_waitevent *)event->xCorrelationToken; |
587 | return_complete: | 498 | return_complete: |
@@ -665,22 +576,30 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
665 | int deviceno; | 576 | int deviceno; |
666 | struct disk_info *d; | 577 | struct disk_info *d; |
667 | struct cdrom_device_info *c; | 578 | struct cdrom_device_info *c; |
668 | struct cdrom_info *ci; | ||
669 | struct request_queue *q; | 579 | struct request_queue *q; |
580 | struct device_node *node = vdev->dev.archdata.of_node; | ||
670 | 581 | ||
671 | deviceno = vdev->unit_address; | 582 | deviceno = vdev->unit_address; |
672 | if (deviceno >= viocd_numdev) | 583 | if (deviceno > VIOCD_MAX_CD) |
673 | return -ENODEV; | 584 | return -ENODEV; |
585 | if (!node) | ||
586 | return -ENODEV; | ||
587 | |||
588 | if (deviceno >= viocd_numdev) | ||
589 | viocd_numdev = deviceno + 1; | ||
674 | 590 | ||
675 | d = &viocd_diskinfo[deviceno]; | 591 | d = &viocd_diskinfo[deviceno]; |
592 | d->rsrcname = of_get_property(node, "linux,vio_rsrcname", NULL); | ||
593 | d->type = of_get_property(node, "linux,vio_type", NULL); | ||
594 | d->model = of_get_property(node, "linux,vio_model", NULL); | ||
595 | |||
676 | c = &d->viocd_info; | 596 | c = &d->viocd_info; |
677 | ci = &viocd_unitinfo[deviceno]; | ||
678 | 597 | ||
679 | c->ops = &viocd_dops; | 598 | c->ops = &viocd_dops; |
680 | c->speed = 4; | 599 | c->speed = 4; |
681 | c->capacity = 1; | 600 | c->capacity = 1; |
682 | c->handle = d; | 601 | c->handle = d; |
683 | c->mask = ~find_capability(ci->type); | 602 | c->mask = ~find_capability(d->type); |
684 | sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno); | 603 | sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno); |
685 | 604 | ||
686 | if (register_cdrom(c) != 0) { | 605 | if (register_cdrom(c) != 0) { |
@@ -690,7 +609,7 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
690 | } | 609 | } |
691 | printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s " | 610 | printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s " |
692 | "type %4.4s, model %3.3s\n", | 611 | "type %4.4s, model %3.3s\n", |
693 | c->name, ci->rsrcname, ci->type, ci->model); | 612 | c->name, d->rsrcname, d->type, d->model); |
694 | q = blk_init_queue(do_viocd_request, &viocd_reqlock); | 613 | q = blk_init_queue(do_viocd_request, &viocd_reqlock); |
695 | if (q == NULL) { | 614 | if (q == NULL) { |
696 | printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n", | 615 | printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n", |
@@ -799,8 +718,6 @@ static int __init viocd_init(void) | |||
799 | /* Initialize our request handler */ | 718 | /* Initialize our request handler */ |
800 | vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event); | 719 | vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event); |
801 | 720 | ||
802 | get_viocd_info(); | ||
803 | |||
804 | spin_lock_init(&viocd_reqlock); | 721 | spin_lock_init(&viocd_reqlock); |
805 | 722 | ||
806 | ret = vio_register_driver(&viocd_driver); | 723 | ret = vio_register_driver(&viocd_driver); |
@@ -816,9 +733,6 @@ static int __init viocd_init(void) | |||
816 | return 0; | 733 | return 0; |
817 | 734 | ||
818 | out_free_info: | 735 | out_free_info: |
819 | dma_free_coherent(iSeries_vio_dev, | ||
820 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, | ||
821 | viocd_unitinfo, unitinfo_dmaaddr); | ||
822 | vio_clearHandler(viomajorsubtype_cdio); | 736 | vio_clearHandler(viomajorsubtype_cdio); |
823 | viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2); | 737 | viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2); |
824 | out_unregister: | 738 | out_unregister: |
@@ -830,10 +744,6 @@ static void __exit viocd_exit(void) | |||
830 | { | 744 | { |
831 | remove_proc_entry("iSeries/viocd", NULL); | 745 | remove_proc_entry("iSeries/viocd", NULL); |
832 | vio_unregister_driver(&viocd_driver); | 746 | vio_unregister_driver(&viocd_driver); |
833 | if (viocd_unitinfo != NULL) | ||
834 | dma_free_coherent(iSeries_vio_dev, | ||
835 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, | ||
836 | viocd_unitinfo, unitinfo_dmaaddr); | ||
837 | viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2); | 747 | viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2); |
838 | vio_clearHandler(viomajorsubtype_cdio); | 748 | vio_clearHandler(viomajorsubtype_cdio); |
839 | unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE); | 749 | unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE); |
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index e12275df6ea2..f1d60f0cef8f 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c | |||
@@ -92,47 +92,6 @@ struct viot_devinfo_struct { | |||
92 | #define VIOTAPOP_SETPART 14 | 92 | #define VIOTAPOP_SETPART 14 |
93 | #define VIOTAPOP_UNLOAD 15 | 93 | #define VIOTAPOP_UNLOAD 15 |
94 | 94 | ||
95 | struct viotapelpevent { | ||
96 | struct HvLpEvent event; | ||
97 | u32 reserved; | ||
98 | u16 version; | ||
99 | u16 sub_type_result; | ||
100 | u16 tape; | ||
101 | u16 flags; | ||
102 | u32 token; | ||
103 | u64 len; | ||
104 | union { | ||
105 | struct { | ||
106 | u32 tape_op; | ||
107 | u32 count; | ||
108 | } op; | ||
109 | struct { | ||
110 | u32 type; | ||
111 | u32 resid; | ||
112 | u32 dsreg; | ||
113 | u32 gstat; | ||
114 | u32 erreg; | ||
115 | u32 file_no; | ||
116 | u32 block_no; | ||
117 | } get_status; | ||
118 | struct { | ||
119 | u32 block_no; | ||
120 | } get_pos; | ||
121 | } u; | ||
122 | }; | ||
123 | |||
124 | enum viotapesubtype { | ||
125 | viotapeopen = 0x0001, | ||
126 | viotapeclose = 0x0002, | ||
127 | viotaperead = 0x0003, | ||
128 | viotapewrite = 0x0004, | ||
129 | viotapegetinfo = 0x0005, | ||
130 | viotapeop = 0x0006, | ||
131 | viotapegetpos = 0x0007, | ||
132 | viotapesetpos = 0x0008, | ||
133 | viotapegetstatus = 0x0009 | ||
134 | }; | ||
135 | |||
136 | enum viotaperc { | 95 | enum viotaperc { |
137 | viotape_InvalidRange = 0x0601, | 96 | viotape_InvalidRange = 0x0601, |
138 | viotape_InvalidToken = 0x0602, | 97 | viotape_InvalidToken = 0x0602, |
@@ -223,14 +182,11 @@ static const struct vio_error_entry viotape_err_table[] = { | |||
223 | #define VIOT_WRITING 2 | 182 | #define VIOT_WRITING 2 |
224 | 183 | ||
225 | /* Our info on the tapes */ | 184 | /* Our info on the tapes */ |
226 | struct tape_descr { | 185 | static struct { |
227 | char rsrcname[10]; | 186 | const char *rsrcname; |
228 | char type[4]; | 187 | const char *type; |
229 | char model[3]; | 188 | const char *model; |
230 | }; | 189 | } viotape_unitinfo[VIOTAPE_MAX_TAPE]; |
231 | |||
232 | static struct tape_descr *viotape_unitinfo; | ||
233 | static dma_addr_t viotape_unitinfo_token; | ||
234 | 190 | ||
235 | static struct mtget viomtget[VIOTAPE_MAX_TAPE]; | 191 | static struct mtget viomtget[VIOTAPE_MAX_TAPE]; |
236 | 192 | ||
@@ -381,53 +337,6 @@ int tape_rc_to_errno(int tape_rc, char *operation, int tapeno) | |||
381 | return -err->errno; | 337 | return -err->errno; |
382 | } | 338 | } |
383 | 339 | ||
384 | /* Get info on all tapes from OS/400 */ | ||
385 | static int get_viotape_info(void) | ||
386 | { | ||
387 | HvLpEvent_Rc hvrc; | ||
388 | int i; | ||
389 | size_t len = sizeof(*viotape_unitinfo) * VIOTAPE_MAX_TAPE; | ||
390 | struct op_struct *op = get_op_struct(); | ||
391 | |||
392 | if (op == NULL) | ||
393 | return -ENOMEM; | ||
394 | |||
395 | viotape_unitinfo = dma_alloc_coherent(iSeries_vio_dev, len, | ||
396 | &viotape_unitinfo_token, GFP_ATOMIC); | ||
397 | if (viotape_unitinfo == NULL) { | ||
398 | free_op_struct(op); | ||
399 | return -ENOMEM; | ||
400 | } | ||
401 | |||
402 | memset(viotape_unitinfo, 0, len); | ||
403 | |||
404 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, | ||
405 | HvLpEvent_Type_VirtualIo, | ||
406 | viomajorsubtype_tape | viotapegetinfo, | ||
407 | HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, | ||
408 | viopath_sourceinst(viopath_hostLp), | ||
409 | viopath_targetinst(viopath_hostLp), | ||
410 | (u64) (unsigned long) op, VIOVERSION << 16, | ||
411 | viotape_unitinfo_token, len, 0, 0); | ||
412 | if (hvrc != HvLpEvent_Rc_Good) { | ||
413 | printk(VIOTAPE_KERN_WARN "hv error on op %d\n", | ||
414 | (int)hvrc); | ||
415 | free_op_struct(op); | ||
416 | return -EIO; | ||
417 | } | ||
418 | |||
419 | wait_for_completion(&op->com); | ||
420 | |||
421 | free_op_struct(op); | ||
422 | |||
423 | for (i = 0; | ||
424 | ((i < VIOTAPE_MAX_TAPE) && (viotape_unitinfo[i].rsrcname[0])); | ||
425 | i++) | ||
426 | viotape_numdev++; | ||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | |||
431 | /* Write */ | 340 | /* Write */ |
432 | static ssize_t viotap_write(struct file *file, const char *buf, | 341 | static ssize_t viotap_write(struct file *file, const char *buf, |
433 | size_t count, loff_t * ppos) | 342 | size_t count, loff_t * ppos) |
@@ -899,7 +808,6 @@ static void vioHandleTapeEvent(struct HvLpEvent *event) | |||
899 | tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK; | 808 | tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK; |
900 | op = (struct op_struct *)event->xCorrelationToken; | 809 | op = (struct op_struct *)event->xCorrelationToken; |
901 | switch (tapeminor) { | 810 | switch (tapeminor) { |
902 | case viotapegetinfo: | ||
903 | case viotapeopen: | 811 | case viotapeopen: |
904 | case viotapeclose: | 812 | case viotapeclose: |
905 | op->rc = tevent->sub_type_result; | 813 | op->rc = tevent->sub_type_result; |
@@ -942,11 +850,23 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
942 | { | 850 | { |
943 | int i = vdev->unit_address; | 851 | int i = vdev->unit_address; |
944 | int j; | 852 | int j; |
853 | struct device_node *node = vdev->dev.archdata.of_node; | ||
945 | 854 | ||
946 | if (i >= viotape_numdev) | 855 | if (i > VIOTAPE_MAX_TAPE) |
856 | return -ENODEV; | ||
857 | if (!node) | ||
947 | return -ENODEV; | 858 | return -ENODEV; |
948 | 859 | ||
860 | if (i >= viotape_numdev) | ||
861 | viotape_numdev = i + 1; | ||
862 | |||
949 | tape_device[i] = &vdev->dev; | 863 | tape_device[i] = &vdev->dev; |
864 | viotape_unitinfo[i].rsrcname = of_get_property(node, | ||
865 | "linux,vio_rsrcname", NULL); | ||
866 | viotape_unitinfo[i].type = of_get_property(node, "linux,vio_type", | ||
867 | NULL); | ||
868 | viotape_unitinfo[i].model = of_get_property(node, "linux,vio_model", | ||
869 | NULL); | ||
950 | 870 | ||
951 | state[i].cur_part = 0; | 871 | state[i].cur_part = 0; |
952 | for (j = 0; j < MAX_PARTITIONS; ++j) | 872 | for (j = 0; j < MAX_PARTITIONS; ++j) |
@@ -1044,11 +964,6 @@ int __init viotap_init(void) | |||
1044 | goto unreg_chrdev; | 964 | goto unreg_chrdev; |
1045 | } | 965 | } |
1046 | 966 | ||
1047 | if ((ret = get_viotape_info()) < 0) { | ||
1048 | printk(VIOTAPE_KERN_WARN "Unable to obtain virtual device information"); | ||
1049 | goto unreg_class; | ||
1050 | } | ||
1051 | |||
1052 | ret = vio_register_driver(&viotape_driver); | 967 | ret = vio_register_driver(&viotape_driver); |
1053 | if (ret) | 968 | if (ret) |
1054 | goto unreg_class; | 969 | goto unreg_class; |
@@ -1102,10 +1017,6 @@ static void __exit viotap_exit(void) | |||
1102 | vio_unregister_driver(&viotape_driver); | 1017 | vio_unregister_driver(&viotape_driver); |
1103 | class_destroy(tape_class); | 1018 | class_destroy(tape_class); |
1104 | unregister_chrdev(VIOTAPE_MAJOR, "viotape"); | 1019 | unregister_chrdev(VIOTAPE_MAJOR, "viotape"); |
1105 | if (viotape_unitinfo) | ||
1106 | dma_free_coherent(iSeries_vio_dev, | ||
1107 | sizeof(viotape_unitinfo[0]) * VIOTAPE_MAX_TAPE, | ||
1108 | viotape_unitinfo, viotape_unitinfo_token); | ||
1109 | viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2); | 1020 | viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2); |
1110 | vio_clearHandler(viomajorsubtype_tape); | 1021 | vio_clearHandler(viomajorsubtype_tape); |
1111 | clear_op_struct_pool(); | 1022 | clear_op_struct_pool(); |