[PATCH] PPC64 iSeries virtual cdrom module fix

From: Stephen Rothwell
Date: Wed Apr 21 2004 - 20:01:31 EST


Hi Andrew,

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.

Please apply to your tree and send upstream.

--
Cheers,
Stephen Rothwell sfr@xxxxxxxxxxxxxxxx
http://www.canb.auug.org.au/~sfr/

diff -ruN 2.6.6-rc2/drivers/cdrom/viocd.c 2.6.6-rc2.viocd/drivers/cdrom/viocd.c
--- 2.6.6-rc2/drivers/cdrom/viocd.c 2004-04-05 10:22:34.000000000 +1000
+++ 2.6.6-rc2.viocd/drivers/cdrom/viocd.c 2004-04-22 02:14:07.000000000 +1000
@@ -132,7 +132,12 @@
char type[4];
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 gendisk *viocd_disk;
@@ -141,7 +146,6 @@
static struct disk_info viocd_diskinfo[VIOCD_MAX_CD];

#define DEVICE_NR(di) ((di) - &viocd_diskinfo[0])
-#define VIOCDI viocd_diskinfo[deviceno].viocd_info

static request_queue_t *viocd_queue;
static spinlock_t viocd_reqlock;
@@ -184,18 +188,20 @@
/* Get info on CD devices from OS/400 */
static void __init get_viocd_info(void)
{
- dma_addr_t dmaaddr;
HvLpEvent_Rc hvrc;
int i;
struct viocd_waitevent we;

- dmaaddr = dma_map_single(iSeries_vio_dev, viocd_unitinfo,
- sizeof(viocd_unitinfo), DMA_FROM_DEVICE);
- if (dmaaddr == (dma_addr_t)-1) {
- printk(VIOCD_KERN_WARNING "error allocating tce\n");
+ viocd_unitinfo = dma_alloc_coherent(iSeries_vio_dev,
+ sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
+ &unitinfo_dmaaddr, GFP_ATOMIC);
+ if (viocd_unitinfo == NULL) {
+ printk(VIOCD_KERN_WARNING "error allocating unitinfo\n");
return;
}

+ memset(viocd_unitinfo, 0, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD);
+
init_completion(&we.com);

hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
@@ -204,29 +210,34 @@
HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
viopath_sourceinst(viopath_hostLp),
viopath_targetinst(viopath_hostLp),
- (u64)&we, VIOVERSION << 16, dmaaddr, 0,
- sizeof(viocd_unitinfo), 0);
+ (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
+ sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, 0);
if (hvrc != HvLpEvent_Rc_Good) {
printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n",
(int)hvrc);
- return;
+ goto error_ret;
}

wait_for_completion(&we.com);

- dma_unmap_single(iSeries_vio_dev, dmaaddr, sizeof(viocd_unitinfo),
- DMA_FROM_DEVICE);
-
if (we.rc) {
const struct vio_error_entry *err =
vio_lookup_rc(viocd_err_table, we.sub_result);
printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n",
we.rc, we.sub_result, err->msg);
- return;
+ goto error_ret;
}

for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++)
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)
@@ -307,10 +318,6 @@
}
dmaaddr = sg_dma_address(&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,
HvLpEvent_Type_VirtualIo,
@@ -604,7 +611,7 @@
printk(VIOCD_KERN_WARNING
"Cannot create gendisk for %s!\n",
c->name);
- unregister_cdrom(&VIOCDI);
+ unregister_cdrom(c);
continue;
}
gendisk->major = VIOCD_MAJOR;
@@ -646,7 +653,10 @@
put_disk(d->viocd_disk);
}
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);
vio_clearHandler(viomajorsubtype_cdio);
unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE);

Attachment: pgp00000.pgp
Description: PGP signature