From 4925c7e22293dbf2b85351e8c2323ad8282396b3 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Mon, 5 Mar 2007 23:35:47 +0100 Subject: [S390] tape: Compression overwrites crypto setting After switching compression on/off with the mt command, tape encryption is no longer working. The reason for that is, that the modeset_byte is set to the compression value instead of using bitwise and/or bit operations to enable/disable the corresponding bit. Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- drivers/s390/char/tape_std.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index 7a76ec4..2a1af4e 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c @@ -647,7 +647,10 @@ tape_std_mtcompression(struct tape_device *device, int mt_count) return PTR_ERR(request); request->op = TO_NOP; /* setup ccws */ - *device->modeset_byte = (mt_count == 0) ? 0x00 : 0x08; + if (mt_count == 0) + *device->modeset_byte &= ~0x08; + else + *device->modeset_byte |= 0x08; tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL); /* execute it */ -- cgit v1.1 From 046f3e821f146d6c473edb033af15a0604957af8 Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Mon, 5 Mar 2007 23:35:52 +0100 Subject: [S390] dasd: Use default recovery for SNSS requests For extended error reporting we sometimes have to start an Sense Subsystem Status request (SNSS). When this request needs to be recovered for some reason, the recovery request will fail with 'command reject'. Our usual recovery procedure will retry the failed request by creating a new request and chaining the failed request from that one. SNSS requests, though, must not be chained from anything, so the recovery request will fail permanently. Use the default recovery for SNSS request, which will just restart the original request without further ado. Signed-off-by: Stefan Weinhuber Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_eer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index 4b8a95f..a1dc8c4 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c @@ -461,6 +461,7 @@ int dasd_eer_enable(struct dasd_device *device) cqr->device = device; cqr->retries = 255; cqr->expires = 10 * HZ; + clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SNSS; cqr->cpaddr->count = SNSS_DATA_SIZE; -- cgit v1.1 From ee04bbccdeb11bdbc54015be8dca30a0deeca5e4 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 5 Mar 2007 23:35:56 +0100 Subject: [S390] cio: Fix locking when calling notify function. Make sure we hold the device lock when we modify the ccw device structure but always call the notify function without the lock held. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device_fsm.c | 67 ++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 51238e7..8baa9cd 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -334,20 +334,29 @@ ccw_device_oper_notify(struct work_struct *work) struct ccw_device *cdev; struct subchannel *sch; int ret; + unsigned long flags; priv = container_of(work, struct ccw_device_private, kick_work); cdev = priv->cdev; + spin_lock_irqsave(cdev->ccwlock, flags); sch = to_subchannel(cdev->dev.parent); - ret = (sch->driver && sch->driver->notify) ? - sch->driver->notify(&sch->dev, CIO_OPER) : 0; - if (!ret) - /* Driver doesn't want device back. */ - ccw_device_do_unreg_rereg(work); - else { + if (sch->driver && sch->driver->notify) { + spin_unlock_irqrestore(cdev->ccwlock, flags); + ret = sch->driver->notify(&sch->dev, CIO_OPER); + spin_lock_irqsave(cdev->ccwlock, flags); + } else + ret = 0; + if (ret) { /* Reenable channel measurements, if needed. */ + spin_unlock_irqrestore(cdev->ccwlock, flags); cmf_reenable(cdev); + spin_lock_irqsave(cdev->ccwlock, flags); wake_up(&cdev->private->wait_q); } + spin_unlock_irqrestore(cdev->ccwlock, flags); + if (!ret) + /* Driver doesn't want device back. */ + ccw_device_do_unreg_rereg(work); } /* @@ -534,15 +543,21 @@ ccw_device_nopath_notify(struct work_struct *work) struct ccw_device *cdev; struct subchannel *sch; int ret; + unsigned long flags; priv = container_of(work, struct ccw_device_private, kick_work); cdev = priv->cdev; + spin_lock_irqsave(cdev->ccwlock, flags); sch = to_subchannel(cdev->dev.parent); /* Extra sanity. */ if (sch->lpm) - return; - ret = (sch->driver && sch->driver->notify) ? - sch->driver->notify(&sch->dev, CIO_NO_PATH) : 0; + goto out_unlock; + if (sch->driver && sch->driver->notify) { + spin_unlock_irqrestore(cdev->ccwlock, flags); + ret = sch->driver->notify(&sch->dev, CIO_NO_PATH); + spin_lock_irqsave(cdev->ccwlock, flags); + } else + ret = 0; if (!ret) { if (get_device(&sch->dev)) { /* Driver doesn't want to keep device. */ @@ -562,6 +577,8 @@ ccw_device_nopath_notify(struct work_struct *work) cdev->private->state = DEV_STATE_DISCONNECTED; wake_up(&cdev->private->wait_q); } +out_unlock: + spin_unlock_irqrestore(cdev->ccwlock, flags); } void @@ -607,10 +624,13 @@ ccw_device_verify_done(struct ccw_device *cdev, int err) default: /* Reset oper notify indication after verify error. */ cdev->private->flags.donotify = 0; - PREPARE_WORK(&cdev->private->kick_work, - ccw_device_nopath_notify); - queue_work(ccw_device_notify_work, &cdev->private->kick_work); - ccw_device_done(cdev, DEV_STATE_NOT_OPER); + if (cdev->online) { + PREPARE_WORK(&cdev->private->kick_work, + ccw_device_nopath_notify); + queue_work(ccw_device_notify_work, + &cdev->private->kick_work); + } else + ccw_device_done(cdev, DEV_STATE_NOT_OPER); break; } } @@ -756,15 +776,22 @@ static void ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event) { struct subchannel *sch; + int ret; sch = to_subchannel(cdev->dev.parent); - if (sch->driver->notify && - sch->driver->notify(&sch->dev, sch->lpm ? CIO_GONE : CIO_NO_PATH)) { - ccw_device_set_timeout(cdev, 0); - cdev->private->flags.fake_irb = 0; - cdev->private->state = DEV_STATE_DISCONNECTED; - wake_up(&cdev->private->wait_q); - return; + if (sch->driver->notify) { + spin_unlock_irq(cdev->ccwlock); + ret = sch->driver->notify(&sch->dev, + sch->lpm ? CIO_GONE : CIO_NO_PATH); + spin_lock_irq(cdev->ccwlock); + } else + ret = 0; + if (ret) { + ccw_device_set_timeout(cdev, 0); + cdev->private->flags.fake_irb = 0; + cdev->private->state = DEV_STATE_DISCONNECTED; + wake_up(&cdev->private->wait_q); + return; } cdev->private->state = DEV_STATE_NOT_OPER; cio_disable_subchannel(sch); -- cgit v1.1 From 7c8427c3fa1b2e77c5bd8cf219c1d55dccd0f167 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 5 Mar 2007 23:35:59 +0100 Subject: [S390] cio: Use path verification to check for path state. After I/O has been killed by the common I/O layer, trigger path verification which will queue cio_device_nopath_notify itself if it finds a device to be without paths. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device_fsm.c | 46 ++++++------------------------------------- 1 file changed, 6 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 8baa9cd..5172060 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -996,18 +996,12 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event) sch = to_subchannel(cdev->dev.parent); ccw_device_set_timeout(cdev, 0); + /* Start delayed path verification. */ + ccw_device_online_verify(cdev, 0); /* OK, i/o is dead now. Call interrupt handler. */ - cdev->private->state = DEV_STATE_ONLINE; if (cdev->handler) cdev->handler(cdev, cdev->private->intparm, ERR_PTR(-EIO)); - if (!sch->lpm) { - PREPARE_WORK(&cdev->private->kick_work, - ccw_device_nopath_notify); - queue_work(ccw_device_notify_work, &cdev->private->kick_work); - } else if (cdev->private->flags.doverify) - /* Start delayed path verification. */ - ccw_device_online_verify(cdev, 0); } static void @@ -1020,21 +1014,8 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event) ccw_device_set_timeout(cdev, 3*HZ); return; } - if (ret == -ENODEV) { - struct subchannel *sch; - - sch = to_subchannel(cdev->dev.parent); - if (!sch->lpm) { - PREPARE_WORK(&cdev->private->kick_work, - ccw_device_nopath_notify); - queue_work(ccw_device_notify_work, - &cdev->private->kick_work); - } else - dev_fsm_event(cdev, DEV_EVENT_NOTOPER); - return; - } - //FIXME: Can we get here? - cdev->private->state = DEV_STATE_ONLINE; + /* Start delayed path verification. */ + ccw_device_online_verify(cdev, 0); if (cdev->handler) cdev->handler(cdev, cdev->private->intparm, ERR_PTR(-EIO)); @@ -1052,26 +1033,11 @@ void device_kill_io(struct subchannel *sch) cdev->private->state = DEV_STATE_TIMEOUT_KILL; return; } - if (ret == -ENODEV) { - if (!sch->lpm) { - PREPARE_WORK(&cdev->private->kick_work, - ccw_device_nopath_notify); - queue_work(ccw_device_notify_work, - &cdev->private->kick_work); - } else - dev_fsm_event(cdev, DEV_EVENT_NOTOPER); - return; - } + /* Start delayed path verification. */ + ccw_device_online_verify(cdev, 0); if (cdev->handler) cdev->handler(cdev, cdev->private->intparm, ERR_PTR(-EIO)); - if (!sch->lpm) { - PREPARE_WORK(&cdev->private->kick_work, - ccw_device_nopath_notify); - queue_work(ccw_device_notify_work, &cdev->private->kick_work); - } else - /* Start delayed path verification. */ - ccw_device_online_verify(cdev, 0); } static void -- cgit v1.1 From 2470b648e17e0216922bb78c7f05b4668402459a Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 5 Mar 2007 23:36:02 +0100 Subject: [S390] cio: Call cancel_halt_clear even when actl == 0. The subchannel may just be status pending, even with actl == 0. We must go through the cancel_halt_clear procedure to put the subchannel into a defined state. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device_fsm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 5172060..089a3dd 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -144,8 +144,8 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev) ret = stsch(sch->schid, &sch->schib); if (ret || !sch->schib.pmcw.dnv) return -ENODEV; - if (!sch->schib.pmcw.ena || sch->schib.scsw.actl == 0) - /* Not operational or no activity -> done. */ + if (!sch->schib.pmcw.ena) + /* Not operational -> done. */ return 0; /* Stage 1: cancel io. */ if (!(sch->schib.scsw.actl & SCSW_ACTL_HALT_PEND) && -- cgit v1.1