Skip to content

Commit

Permalink
[S390] cio: fix I/O cancel function
Browse files Browse the repository at this point in the history
Function ccw_device_cancel_halt_clear may cause an unexpected kernel
panic if a clear function is currently active at the subchannel for
which it is called. In that case, the iretry counter used to determine
the number of retries is never initialized, leading to an immediate
failure of the function which results in a kernel panic.

Fix this by initializing the iretry counter when the function is
first called. Also replace the kernel panic with a return code: a
single malfunctioning I/O device should not automatically cause a
system-wide kernel panic.

Signed-off-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Peter Oberparleiter authored and Martin Schwidefsky committed Oct 25, 2010
1 parent c9af3fa commit 376ae47
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 2 deletions.
1 change: 1 addition & 0 deletions drivers/s390/cio/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,7 @@ static void io_subchannel_quiesce(struct subchannel *sch)
cdev->handler(cdev, cdev->private->intparm, ERR_PTR(-EIO));
while (ret == -EBUSY) {
cdev->private->state = DEV_STATE_QUIESCE;
cdev->private->iretry = 255;
ret = ccw_device_cancel_halt_clear(cdev);
if (ret == -EBUSY) {
ccw_device_set_timeout(cdev, HZ/10);
Expand Down
9 changes: 7 additions & 2 deletions drivers/s390/cio/device_fsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,10 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
ret = cio_clear (sch);
return (ret == 0) ? -EBUSY : ret;
}
panic("Can't stop i/o on subchannel.\n");
/* Function was unsuccessful */
CIO_MSG_EVENT(0, "0.%x.%04x: could not stop I/O\n",
cdev->private->dev_id.ssid, cdev->private->dev_id.devno);
return -EIO;
}

void ccw_device_update_sense_data(struct ccw_device *cdev)
Expand Down Expand Up @@ -766,13 +769,14 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event)
int ret;

ccw_device_set_timeout(cdev, 0);
cdev->private->iretry = 255;
ret = ccw_device_cancel_halt_clear(cdev);
if (ret == -EBUSY) {
ccw_device_set_timeout(cdev, 3*HZ);
cdev->private->state = DEV_STATE_TIMEOUT_KILL;
return;
}
if (ret == -ENODEV)
if (ret)
dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
else if (cdev->handler)
cdev->handler(cdev, cdev->private->intparm,
Expand Down Expand Up @@ -869,6 +873,7 @@ void ccw_device_kill_io(struct ccw_device *cdev)
{
int ret;

cdev->private->iretry = 255;
ret = ccw_device_cancel_halt_clear(cdev);
if (ret == -EBUSY) {
ccw_device_set_timeout(cdev, 3*HZ);
Expand Down

0 comments on commit 376ae47

Please sign in to comment.