X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=drivers%2Fblock%2Fviodasd.c;h=68592c3360111ef47de71cb88858bfb25d5b8a31;hb=5351fb106a84d6ac584c2501e3b335093d38a58c;hp=2d518aa2720a517f3c3c292550dc18abfedb6e1e;hpb=3d5271f9883cba7b54762bc4fe027d4172f06db7;p=powerpc.git diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 2d518aa272..68592c3360 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -49,6 +49,7 @@ #include #include #include +#include MODULE_DESCRIPTION("iSeries Virtual DASD"); MODULE_AUTHOR("Dave Boutcher"); @@ -59,7 +60,6 @@ MODULE_LICENSE("GPL"); * numbers 0-255 we get a maximum of 32 disks. */ #define VIOD_GENHD_NAME "iseries/vd" -#define VIOD_GENHD_DEVFS_NAME "iseries/disc" #define VIOD_VERS "1.64" @@ -247,43 +247,17 @@ static int viodasd_release(struct inode *ino, struct file *fil) /* External ioctl entry point. */ -static int viodasd_ioctl(struct inode *ino, struct file *fil, - unsigned int cmd, unsigned long arg) +static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) { - unsigned char sectors; - unsigned char heads; - unsigned short cylinders; - struct hd_geometry *geo; - struct gendisk *gendisk; - struct viodasd_device *d; + struct gendisk *disk = bdev->bd_disk; + struct viodasd_device *d = disk->private_data; - switch (cmd) { - case HDIO_GETGEO: - geo = (struct hd_geometry *)arg; - if (geo == NULL) - return -EINVAL; - if (!access_ok(VERIFY_WRITE, geo, sizeof(*geo))) - return -EFAULT; - gendisk = ino->i_bdev->bd_disk; - d = gendisk->private_data; - sectors = d->sectors; - if (sectors == 0) - sectors = 32; - heads = d->tracks; - if (heads == 0) - heads = 64; - cylinders = d->cylinders; - if (cylinders == 0) - cylinders = get_capacity(gendisk) / (sectors * heads); - if (__put_user(sectors, &geo->sectors) || - __put_user(heads, &geo->heads) || - __put_user(cylinders, &geo->cylinders) || - __put_user(get_start_sect(ino->i_bdev), &geo->start)) - return -EFAULT; - return 0; - } + geo->sectors = d->sectors ? d->sectors : 0; + geo->heads = d->tracks ? d->tracks : 64; + geo->cylinders = d->cylinders ? d->cylinders : + get_capacity(disk) / (geo->cylinders * geo->heads); - return -EINVAL; + return 0; } /* @@ -293,7 +267,7 @@ static struct block_device_operations viodasd_fops = { .owner = THIS_MODULE, .open = viodasd_open, .release = viodasd_release, - .ioctl = viodasd_ioctl, + .getgeo = viodasd_getgeo, }; /* @@ -305,7 +279,7 @@ static void viodasd_end_request(struct request *req, int uptodate, if (end_that_request_first(req, uptodate, num_sectors)) return; add_disk_randomness(req->rq_disk); - end_that_request_last(req); + end_that_request_last(req, uptodate); } /* @@ -319,6 +293,7 @@ static int send_request(struct request *req) u16 viocmd; HvLpEvent_Rc hvrc; struct vioblocklpevent *bevent; + struct HvLpEvent *hev; struct scatterlist sg[VIOMAXBLOCKDMA]; int sgindex; int statindex; @@ -373,22 +348,19 @@ static int send_request(struct request *req) * token so we can match the response up later */ memset(bevent, 0, sizeof(struct vioblocklpevent)); - bevent->event.xFlags.xValid = 1; - bevent->event.xFlags.xFunction = HvLpEvent_Function_Int; - bevent->event.xFlags.xAckInd = HvLpEvent_AckInd_DoAck; - bevent->event.xFlags.xAckType = HvLpEvent_AckType_ImmediateAck; - bevent->event.xType = HvLpEvent_Type_VirtualIo; - bevent->event.xSubtype = viocmd; - bevent->event.xSourceLp = HvLpConfig_getLpIndex(); - bevent->event.xTargetLp = viopath_hostLp; - bevent->event.xSizeMinus1 = + hev = &bevent->event; + hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DO_ACK | + HV_LP_EVENT_INT; + hev->xType = HvLpEvent_Type_VirtualIo; + hev->xSubtype = viocmd; + hev->xSourceLp = HvLpConfig_getLpIndex(); + hev->xTargetLp = viopath_hostLp; + hev->xSizeMinus1 = offsetof(struct vioblocklpevent, u.rw_data.dma_info) + (sizeof(bevent->u.rw_data.dma_info[0]) * nsg) - 1; - bevent->event.xSourceInstanceId = - viopath_sourceinst(viopath_hostLp); - bevent->event.xTargetInstanceId = - viopath_targetinst(viopath_hostLp); - bevent->event.xCorrelationToken = (u64)req; + hev->xSourceInstanceId = viopath_sourceinst(viopath_hostLp); + hev->xTargetInstanceId = viopath_targetinst(viopath_hostLp); + hev->xCorrelationToken = (u64)req; bevent->version = VIOVERSION; bevent->disk = DEVICE_NO(d); bevent->u.rw_data.offset = start; @@ -551,8 +523,6 @@ retry: else snprintf(g->disk_name, sizeof(g->disk_name), VIOD_GENHD_NAME "%c", 'a' + (dev_no % 26)); - snprintf(g->devfs_name, sizeof(g->devfs_name), - "%s%d", VIOD_GENHD_DEVFS_NAME, dev_no); g->fops = &viodasd_fops; g->queue = q; g->private_data = d; @@ -675,10 +645,10 @@ static void handle_block_event(struct HvLpEvent *event) /* Notification that a partition went away! */ return; /* First, we should NEVER get an int here...only acks */ - if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + if (hvlpevent_is_int(event)) { printk(VIOD_KERN_WARNING "Yikes! got an int in viodasd event handler!\n"); - if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { + if (hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); } @@ -721,7 +691,7 @@ static void handle_block_event(struct HvLpEvent *event) default: printk(VIOD_KERN_WARNING "invalid subtype!"); - if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { + if (hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); } @@ -775,7 +745,7 @@ static int viodasd_remove(struct vio_dev *vdev) * support. */ static struct vio_device_id viodasd_device_table[] __devinitdata = { - { "viodasd", "" }, + { "block", "IBM,iSeries-viodasd" }, { "", "" } }; MODULE_DEVICE_TABLE(vio, viodasd_device_table); @@ -790,6 +760,8 @@ static struct vio_driver viodasd_driver = { } }; +static int need_delete_probe; + /* * Initialize the whole device driver. Handle module and non-module * versions @@ -798,52 +770,78 @@ static int __init viodasd_init(void) { int rc; + if (!firmware_has_feature(FW_FEATURE_ISERIES)) { + rc = -ENODEV; + goto early_fail; + } + /* Try to open to our host lp */ if (viopath_hostLp == HvLpIndexInvalid) vio_set_hostlp(); if (viopath_hostLp == HvLpIndexInvalid) { printk(VIOD_KERN_WARNING "invalid hosting partition\n"); - return -EIO; + rc = -EIO; + goto early_fail; } printk(VIOD_KERN_INFO "vers " VIOD_VERS ", hosting partition %d\n", viopath_hostLp); /* register the block device */ - if (register_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME)) { + rc = register_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME); + if (rc) { printk(VIOD_KERN_WARNING "Unable to get major number %d for %s\n", VIODASD_MAJOR, VIOD_GENHD_NAME); - return -EIO; + goto early_fail; } /* Actually open the path to the hosting partition */ - if (viopath_open(viopath_hostLp, viomajorsubtype_blockio, - VIOMAXREQ + 2)) { + rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio, + VIOMAXREQ + 2); + if (rc) { printk(VIOD_KERN_WARNING "error opening path to host partition %d\n", viopath_hostLp); - unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME); - return -EIO; + goto unregister_blk; } /* Initialize our request handler */ vio_setHandler(viomajorsubtype_blockio, handle_block_event); rc = vio_register_driver(&viodasd_driver); - if (rc == 0) - driver_create_file(&viodasd_driver.driver, &driver_attr_probe); + if (rc) { + printk(VIOD_KERN_WARNING "vio_register_driver failed\n"); + goto unset_handler; + } + + /* + * If this call fails, it just means that we cannot dynamically + * add virtual disks, but the driver will still work fine for + * all existing disk, so ignore the failure. + */ + if (!driver_create_file(&viodasd_driver.driver, &driver_attr_probe)) + need_delete_probe = 1; + + return 0; + +unset_handler: + vio_clearHandler(viomajorsubtype_blockio); + viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2); +unregister_blk: + unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME); +early_fail: return rc; } module_init(viodasd_init); -void viodasd_exit(void) +void __exit viodasd_exit(void) { - driver_remove_file(&viodasd_driver.driver, &driver_attr_probe); + if (need_delete_probe) + driver_remove_file(&viodasd_driver.driver, &driver_attr_probe); vio_unregister_driver(&viodasd_driver); vio_clearHandler(viomajorsubtype_blockio); - unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME); viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2); + unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME); } - module_exit(viodasd_exit);