Commit ff15d3ec authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: iSeries virtual cdrom module fix

From: Stephen Rothwell <sfr@canb.auug.org.au>

This patch fixes loading viocd as a module.  It would oops because I was
passing the address of a static buffer to dma_map_single and when loaded as
a module, this address is not valid for that purpose.

There are a couple of simple cleanups here as well.
parent d8932719
...@@ -132,7 +132,12 @@ struct cdrom_info { ...@@ -132,7 +132,12 @@ struct cdrom_info {
char type[4]; char type[4];
char model[3]; char model[3];
}; };
static struct cdrom_info viocd_unitinfo[VIOCD_MAX_CD]; /*
* This needs to be allocated since it is passed to the
* Hypervisor and we may be a module.
*/
static struct cdrom_info *viocd_unitinfo;
static dma_addr_t unitinfo_dmaaddr;
struct disk_info { struct disk_info {
struct gendisk *viocd_disk; struct gendisk *viocd_disk;
...@@ -141,7 +146,6 @@ struct disk_info { ...@@ -141,7 +146,6 @@ struct disk_info {
static struct disk_info viocd_diskinfo[VIOCD_MAX_CD]; static struct disk_info viocd_diskinfo[VIOCD_MAX_CD];
#define DEVICE_NR(di) ((di) - &viocd_diskinfo[0]) #define DEVICE_NR(di) ((di) - &viocd_diskinfo[0])
#define VIOCDI viocd_diskinfo[deviceno].viocd_info
static request_queue_t *viocd_queue; static request_queue_t *viocd_queue;
static spinlock_t viocd_reqlock; static spinlock_t viocd_reqlock;
...@@ -184,18 +188,20 @@ struct block_device_operations viocd_fops = { ...@@ -184,18 +188,20 @@ struct block_device_operations viocd_fops = {
/* Get info on CD devices from OS/400 */ /* Get info on CD devices from OS/400 */
static void __init get_viocd_info(void) static void __init get_viocd_info(void)
{ {
dma_addr_t dmaaddr;
HvLpEvent_Rc hvrc; HvLpEvent_Rc hvrc;
int i; int i;
struct viocd_waitevent we; struct viocd_waitevent we;
dmaaddr = dma_map_single(iSeries_vio_dev, viocd_unitinfo, viocd_unitinfo = dma_alloc_coherent(iSeries_vio_dev,
sizeof(viocd_unitinfo), DMA_FROM_DEVICE); sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
if (dmaaddr == (dma_addr_t)-1) { &unitinfo_dmaaddr, GFP_ATOMIC);
printk(VIOCD_KERN_WARNING "error allocating tce\n"); if (viocd_unitinfo == NULL) {
printk(VIOCD_KERN_WARNING "error allocating unitinfo\n");
return; return;
} }
memset(viocd_unitinfo, 0, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD);
init_completion(&we.com); init_completion(&we.com);
hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
...@@ -204,29 +210,34 @@ static void __init get_viocd_info(void) ...@@ -204,29 +210,34 @@ static void __init get_viocd_info(void)
HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
viopath_sourceinst(viopath_hostLp), viopath_sourceinst(viopath_hostLp),
viopath_targetinst(viopath_hostLp), viopath_targetinst(viopath_hostLp),
(u64)&we, VIOVERSION << 16, dmaaddr, 0, (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
sizeof(viocd_unitinfo), 0); sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, 0);
if (hvrc != HvLpEvent_Rc_Good) { if (hvrc != HvLpEvent_Rc_Good) {
printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n", printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n",
(int)hvrc); (int)hvrc);
return; goto error_ret;
} }
wait_for_completion(&we.com); wait_for_completion(&we.com);
dma_unmap_single(iSeries_vio_dev, dmaaddr, sizeof(viocd_unitinfo),
DMA_FROM_DEVICE);
if (we.rc) { if (we.rc) {
const struct vio_error_entry *err = const struct vio_error_entry *err =
vio_lookup_rc(viocd_err_table, we.sub_result); vio_lookup_rc(viocd_err_table, we.sub_result);
printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n", printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n",
we.rc, we.sub_result, err->msg); we.rc, we.sub_result, err->msg);
return; goto error_ret;
} }
for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++) for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++)
viocd_numdev++; viocd_numdev++;
return;
error_ret:
dma_free_coherent(iSeries_vio_dev,
sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
viocd_unitinfo, unitinfo_dmaaddr);
viocd_unitinfo = NULL;
} }
static int viocd_open(struct cdrom_device_info *cdi, int purpose) static int viocd_open(struct cdrom_device_info *cdi, int purpose)
...@@ -307,10 +318,6 @@ static int send_request(struct request *req) ...@@ -307,10 +318,6 @@ static int send_request(struct request *req)
} }
dmaaddr = sg_dma_address(&sg); dmaaddr = sg_dma_address(&sg);
len = sg_dma_len(&sg); len = sg_dma_len(&sg);
if (dmaaddr == (dma_addr_t)-1) {
printk(VIOCD_KERN_WARNING "error allocating tce\n");
return -1;
}
hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
HvLpEvent_Type_VirtualIo, HvLpEvent_Type_VirtualIo,
...@@ -604,7 +611,7 @@ static int __init viocd_init(void) ...@@ -604,7 +611,7 @@ static int __init viocd_init(void)
printk(VIOCD_KERN_WARNING printk(VIOCD_KERN_WARNING
"Cannot create gendisk for %s!\n", "Cannot create gendisk for %s!\n",
c->name); c->name);
unregister_cdrom(&VIOCDI); unregister_cdrom(c);
continue; continue;
} }
gendisk->major = VIOCD_MAJOR; gendisk->major = VIOCD_MAJOR;
...@@ -646,7 +653,10 @@ static void __exit viocd_exit(void) ...@@ -646,7 +653,10 @@ static void __exit viocd_exit(void)
put_disk(d->viocd_disk); put_disk(d->viocd_disk);
} }
blk_cleanup_queue(viocd_queue); blk_cleanup_queue(viocd_queue);
if (viocd_unitinfo != NULL)
dma_free_coherent(iSeries_vio_dev,
sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
viocd_unitinfo, unitinfo_dmaaddr);
viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2); viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2);
vio_clearHandler(viomajorsubtype_cdio); vio_clearHandler(viomajorsubtype_cdio);
unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE); unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment