diff options
| author | Stephen Rothwell <sfr@canb.auug.org.au> | 2007-10-11 00:57:26 -0400 |
|---|---|---|
| committer | Paul Mackerras <paulus@samba.org> | 2007-10-11 06:40:47 -0400 |
| commit | b833b481c10cf591b15cc674948cc514e55d3b94 (patch) | |
| tree | 6e02bb29bff6eea2716c0b02c0a2779d2b80480c /drivers/cdrom | |
| parent | dd9b67ab37d57da67840276d28957498512d4dd8 (diff) | |
[POWERPC] iSeries: Move detection of virtual cdroms
Now we will only have entries in the device tree for the actual existing
devices (including their OS/400 properties). This way viocd.c gets all
the information about the devices from the device tree.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Acked-by: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'drivers/cdrom')
| -rw-r--r-- | drivers/cdrom/viocd.c | 116 |
1 files changed, 19 insertions, 97 deletions
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index c081e5400ce0..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,17 +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 | struct disk_info { | 110 | struct disk_info { |
| 141 | struct gendisk *viocd_disk; | 111 | struct gendisk *viocd_disk; |
| 142 | struct cdrom_device_info viocd_info; | 112 | struct cdrom_device_info viocd_info; |
| 143 | struct device *dev; | 113 | struct device *dev; |
| 144 | struct cdrom_info unitinfo; | 114 | const char *rsrcname; |
| 115 | const char *type; | ||
| 116 | const char *model; | ||
| 145 | }; | 117 | }; |
| 146 | static struct disk_info viocd_diskinfo[VIOCD_MAX_CD]; | 118 | static struct disk_info viocd_diskinfo[VIOCD_MAX_CD]; |
| 147 | 119 | ||
| @@ -159,9 +131,9 @@ static int proc_viocd_show(struct seq_file *m, void *v) | |||
| 159 | for (i = 0; i < viocd_numdev; i++) { | 131 | for (i = 0; i < viocd_numdev; i++) { |
| 160 | seq_printf(m, "viocd device %d is iSeries resource %10.10s" | 132 | seq_printf(m, "viocd device %d is iSeries resource %10.10s" |
| 161 | "type %4.4s, model %3.3s\n", | 133 | "type %4.4s, model %3.3s\n", |
| 162 | i, viocd_diskinfo[i].unitinfo.rsrcname, | 134 | i, viocd_diskinfo[i].rsrcname, |
| 163 | viocd_diskinfo[i].unitinfo.type, | 135 | viocd_diskinfo[i].type, |
| 164 | viocd_diskinfo[i].unitinfo.model); | 136 | viocd_diskinfo[i].model); |
| 165 | } | 137 | } |
| 166 | return 0; | 138 | return 0; |
| 167 | } | 139 | } |
| @@ -211,61 +183,6 @@ struct block_device_operations viocd_fops = { | |||
| 211 | .media_changed = viocd_blk_media_changed, | 183 | .media_changed = viocd_blk_media_changed, |
| 212 | }; | 184 | }; |
| 213 | 185 | ||
| 214 | /* Get info on CD devices from OS/400 */ | ||
| 215 | static void __init get_viocd_info(void) | ||
| 216 | { | ||
| 217 | HvLpEvent_Rc hvrc; | ||
| 218 | int i; | ||
| 219 | struct viocd_waitevent we; | ||
| 220 | struct cdrom_info *viocd_unitinfo; | ||
| 221 | dma_addr_t unitinfo_dmaaddr; | ||
| 222 | |||
| 223 | viocd_unitinfo = iseries_hv_alloc( | ||
| 224 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, | ||
| 225 | &unitinfo_dmaaddr, GFP_ATOMIC); | ||
| 226 | if (viocd_unitinfo == NULL) { | ||
| 227 | printk(VIOCD_KERN_WARNING "error allocating unitinfo\n"); | ||
| 228 | return; | ||
| 229 | } | ||
| 230 | |||
| 231 | memset(viocd_unitinfo, 0, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD); | ||
| 232 | |||
| 233 | init_completion(&we.com); | ||
| 234 | |||
| 235 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, | ||
| 236 | HvLpEvent_Type_VirtualIo, | ||
| 237 | viomajorsubtype_cdio | viocdgetinfo, | ||
| 238 | HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, | ||
| 239 | viopath_sourceinst(viopath_hostLp), | ||
| 240 | viopath_targetinst(viopath_hostLp), | ||
| 241 | (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0, | ||
| 242 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, 0); | ||
| 243 | if (hvrc != HvLpEvent_Rc_Good) { | ||
| 244 | printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n", | ||
| 245 | (int)hvrc); | ||
| 246 | goto error_ret; | ||
| 247 | } | ||
| 248 | |||
| 249 | wait_for_completion(&we.com); | ||
| 250 | |||
| 251 | if (we.rc) { | ||
| 252 | const struct vio_error_entry *err = | ||
| 253 | vio_lookup_rc(viocd_err_table, we.sub_result); | ||
| 254 | printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n", | ||
| 255 | we.rc, we.sub_result, err->msg); | ||
| 256 | goto error_ret; | ||
| 257 | } | ||
| 258 | |||
| 259 | for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++) { | ||
| 260 | viocd_diskinfo[viocd_numdev].unitinfo = viocd_unitinfo[i]; | ||
| 261 | viocd_numdev++; | ||
| 262 | } | ||
| 263 | |||
| 264 | error_ret: | ||
| 265 | iseries_hv_free(sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, | ||
| 266 | viocd_unitinfo, unitinfo_dmaaddr); | ||
| 267 | } | ||
| 268 | |||
| 269 | static int viocd_open(struct cdrom_device_info *cdi, int purpose) | 186 | static int viocd_open(struct cdrom_device_info *cdi, int purpose) |
| 270 | { | 187 | { |
| 271 | struct disk_info *diskinfo = cdi->handle; | 188 | struct disk_info *diskinfo = cdi->handle; |
| @@ -576,7 +493,6 @@ static void vio_handle_cd_event(struct HvLpEvent *event) | |||
| 576 | bevent->block_size / 512); | 493 | bevent->block_size / 512); |
| 577 | } | 494 | } |
| 578 | /* FALLTHROUGH !! */ | 495 | /* FALLTHROUGH !! */ |
| 579 | case viocdgetinfo: | ||
| 580 | case viocdlockdoor: | 496 | case viocdlockdoor: |
| 581 | pwe = (struct viocd_waitevent *)event->xCorrelationToken; | 497 | pwe = (struct viocd_waitevent *)event->xCorrelationToken; |
| 582 | return_complete: | 498 | return_complete: |
| @@ -660,22 +576,30 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
| 660 | int deviceno; | 576 | int deviceno; |
| 661 | struct disk_info *d; | 577 | struct disk_info *d; |
| 662 | struct cdrom_device_info *c; | 578 | struct cdrom_device_info *c; |
| 663 | struct cdrom_info *ci; | ||
| 664 | struct request_queue *q; | 579 | struct request_queue *q; |
| 580 | struct device_node *node = vdev->dev.archdata.of_node; | ||
| 665 | 581 | ||
| 666 | deviceno = vdev->unit_address; | 582 | deviceno = vdev->unit_address; |
| 667 | if (deviceno >= viocd_numdev) | 583 | if (deviceno > VIOCD_MAX_CD) |
| 668 | return -ENODEV; | 584 | return -ENODEV; |
| 585 | if (!node) | ||
| 586 | return -ENODEV; | ||
| 587 | |||
| 588 | if (deviceno >= viocd_numdev) | ||
| 589 | viocd_numdev = deviceno + 1; | ||
| 669 | 590 | ||
| 670 | 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 | |||
| 671 | c = &d->viocd_info; | 596 | c = &d->viocd_info; |
| 672 | ci = &d->unitinfo; | ||
| 673 | 597 | ||
| 674 | c->ops = &viocd_dops; | 598 | c->ops = &viocd_dops; |
| 675 | c->speed = 4; | 599 | c->speed = 4; |
| 676 | c->capacity = 1; | 600 | c->capacity = 1; |
| 677 | c->handle = d; | 601 | c->handle = d; |
| 678 | c->mask = ~find_capability(ci->type); | 602 | c->mask = ~find_capability(d->type); |
| 679 | sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno); | 603 | sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno); |
| 680 | 604 | ||
| 681 | if (register_cdrom(c) != 0) { | 605 | if (register_cdrom(c) != 0) { |
| @@ -685,7 +609,7 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
| 685 | } | 609 | } |
| 686 | printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s " | 610 | printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s " |
| 687 | "type %4.4s, model %3.3s\n", | 611 | "type %4.4s, model %3.3s\n", |
| 688 | c->name, ci->rsrcname, ci->type, ci->model); | 612 | c->name, d->rsrcname, d->type, d->model); |
| 689 | q = blk_init_queue(do_viocd_request, &viocd_reqlock); | 613 | q = blk_init_queue(do_viocd_request, &viocd_reqlock); |
| 690 | if (q == NULL) { | 614 | if (q == NULL) { |
| 691 | printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n", | 615 | printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n", |
| @@ -794,8 +718,6 @@ static int __init viocd_init(void) | |||
| 794 | /* Initialize our request handler */ | 718 | /* Initialize our request handler */ |
| 795 | vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event); | 719 | vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event); |
| 796 | 720 | ||
| 797 | get_viocd_info(); | ||
| 798 | |||
| 799 | spin_lock_init(&viocd_reqlock); | 721 | spin_lock_init(&viocd_reqlock); |
| 800 | 722 | ||
| 801 | ret = vio_register_driver(&viocd_driver); | 723 | ret = vio_register_driver(&viocd_driver); |
