X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=drivers%2Fs390%2Fblock%2Fdasd.c;h=041e1a621885803b1d6bba97f0194c5703a92841;hb=347a8dc3b815f0c0fa62a1df075184ffe4cbdcf1;hp=d5f53980749b5cabf8f9ba4dc4d8120e0d0d79b9;hpb=e0d7ff168a71299919f01500b3d507aae0c67513;p=mirror_ubuntu-artful-kernel.git diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index d5f53980749b..041e1a621885 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -7,7 +7,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.165 $ + * $Revision: 1.172 $ */ #include @@ -115,8 +115,7 @@ dasd_alloc_device(void) void dasd_free_device(struct dasd_device *device) { - if (device->private) - kfree(device->private); + kfree(device->private); free_page((unsigned long) device->erp_mem); free_pages((unsigned long) device->ccw_mem, 1); kfree(device); @@ -539,8 +538,7 @@ dasd_kmalloc_request(char *magic, int cplength, int datasize, if (datasize > 0) { cqr->data = kmalloc(datasize, GFP_ATOMIC | GFP_DMA); if (cqr->data == NULL) { - if (cqr->cpaddr != NULL) - kfree(cqr->cpaddr); + kfree(cqr->cpaddr); kfree(cqr); return ERR_PTR(-ENOMEM); } @@ -606,7 +604,7 @@ dasd_smalloc_request(char *magic, int cplength, int datasize, void dasd_kfree_request(struct dasd_ccw_req * cqr, struct dasd_device * device) { -#ifdef CONFIG_ARCH_S390X +#ifdef CONFIG_64BIT struct ccw1 *ccw; /* Clear any idals used for the request. */ @@ -615,10 +613,8 @@ dasd_kfree_request(struct dasd_ccw_req * cqr, struct dasd_device * device) clear_normalized_cda(ccw); } while (ccw++->flags & (CCW_FLAG_CC | CCW_FLAG_DC)); #endif - if (cqr->cpaddr != NULL) - kfree(cqr->cpaddr); - if (cqr->data != NULL) - kfree(cqr->data); + kfree(cqr->cpaddr); + kfree(cqr->data); kfree(cqr); dasd_put_device(device); } @@ -1131,17 +1127,13 @@ __dasd_process_blk_queue(struct dasd_device * device) request_queue_t *queue; struct request *req; struct dasd_ccw_req *cqr; - int nr_queued, feature_ro; + int nr_queued; queue = device->request_queue; /* No queue ? Then there is nothing to do. */ if (queue == NULL) return; - feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY); - if (feature_ro < 0) /* no devmap */ - return; - /* * We requeue request from the block device queue to the ccw * queue only in two states. In state DASD_STATE_READY the @@ -1162,7 +1154,8 @@ __dasd_process_blk_queue(struct dasd_device * device) nr_queued < DASD_CHANQ_MAX_SIZE) { req = elv_next_request(queue); - if (feature_ro && rq_data_dir(req) == WRITE) { + if (device->features & DASD_FEATURE_READONLY && + rq_data_dir(req) == WRITE) { DBF_DEV_EVENT(DBF_ERR, device, "Rejecting write request %p", req); @@ -1231,6 +1224,12 @@ __dasd_start_head(struct dasd_device * device) if (list_empty(&device->ccw_queue)) return; cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); + /* check FAILFAST */ + if (device->stopped & ~DASD_STOPPED_PENDING && + test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) { + cqr->status = DASD_CQR_FAILED; + dasd_schedule_bh(device); + } if ((cqr->status == DASD_CQR_QUEUED) && (!device->stopped)) { /* try to start the first I/O that can be started */ @@ -1330,7 +1329,7 @@ void dasd_schedule_bh(struct dasd_device * device) { /* Protect against rescheduling. */ - if (atomic_compare_and_swap (0, 1, &device->tasklet_scheduled)) + if (atomic_cmpxchg (&device->tasklet_scheduled, 0, 1) != 0) return; dasd_get_device(device); tasklet_hi_schedule(&device->tasklet); @@ -1757,8 +1756,10 @@ dasd_exit(void) * SECTION: common functions for ccw_driver use */ -/* initial attempt at a probe function. this can be simplified once - * the other detection code is gone */ +/* + * Initial attempt at a probe function. this can be simplified once + * the other detection code is gone. + */ int dasd_generic_probe (struct ccw_device *cdev, struct dasd_discipline *discipline) @@ -1777,8 +1778,10 @@ dasd_generic_probe (struct ccw_device *cdev, return ret; } -/* this will one day be called from a global not_oper handler. - * It is also used by driver_unregister during module unload */ +/* + * This will one day be called from a global not_oper handler. + * It is also used by driver_unregister during module unload. + */ void dasd_generic_remove (struct ccw_device *cdev) { @@ -1805,26 +1808,24 @@ dasd_generic_remove (struct ccw_device *cdev) dasd_delete_device(device); } -/* activate a device. This is called from dasd_{eckd,fba}_probe() when either +/* + * Activate a device. This is called from dasd_{eckd,fba}_probe() when either * the device is detected for the first time and is supposed to be used - * or the user has started activation through sysfs */ + * or the user has started activation through sysfs. + */ int dasd_generic_set_online (struct ccw_device *cdev, struct dasd_discipline *discipline) { struct dasd_device *device; - int feature_diag, rc; + int rc; device = dasd_create_device(cdev); if (IS_ERR(device)) return PTR_ERR(device); - feature_diag = dasd_get_feature(cdev, DASD_FEATURE_USEDIAG); - if (feature_diag < 0) - return feature_diag; - - if (feature_diag) { + if (device->features & DASD_FEATURE_USEDIAG) { if (!dasd_diag_discipline_pointer) { printk (KERN_WARNING "dasd_generic couldn't online device %s " @@ -1928,7 +1929,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event) if (cqr->status == DASD_CQR_IN_IO) cqr->status = DASD_CQR_FAILED; device->stopped |= DASD_STOPPED_DC_EIO; - dasd_schedule_bh(device); } else { list_for_each_entry(cqr, &device->ccw_queue, list) if (cqr->status == DASD_CQR_IN_IO) { @@ -1938,6 +1938,7 @@ dasd_generic_notify(struct ccw_device *cdev, int event) device->stopped |= DASD_STOPPED_DC_WAIT; dasd_set_timer(device, 0); } + dasd_schedule_bh(device); ret = 1; break; case CIO_OPER: