Commit bb0ca330 authored by Ursula Braun's avatar Ursula Braun Committed by Heiko Carstens

[S390] qdio: Repair timeout handling for qdio_shutdown

If qdio shutdown runs in parallel with a channel error,
the qdio_timeout_handler might not be triggered.
In this case neither state INACTIVE nor state ERR
is reached and the following wait_event hangs forever.
Solution: do not make use of ccw_device_set_timeout(),
but add a timeout to the following wait_event.
And make sure, wake_up is called in case of an
i/o error on the qdio-device.
Signed-off-by: default avatarUrsula Braun <braunu@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
parent b1c02d91
...@@ -2082,7 +2082,6 @@ qdio_timeout_handler(struct ccw_device *cdev) ...@@ -2082,7 +2082,6 @@ qdio_timeout_handler(struct ccw_device *cdev)
default: default:
BUG(); BUG();
} }
ccw_device_set_timeout(cdev, 0);
wake_up(&cdev->private->wait_q); wake_up(&cdev->private->wait_q);
} }
...@@ -2121,6 +2120,8 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) ...@@ -2121,6 +2120,8 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
case -EIO: case -EIO:
QDIO_PRINT_ERR("i/o error on device %s\n", QDIO_PRINT_ERR("i/o error on device %s\n",
cdev->dev.bus_id); cdev->dev.bus_id);
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
wake_up(&cdev->private->wait_q);
return; return;
case -ETIMEDOUT: case -ETIMEDOUT:
qdio_timeout_handler(cdev); qdio_timeout_handler(cdev);
...@@ -2667,12 +2668,12 @@ qdio_shutdown(struct ccw_device *cdev, int how) ...@@ -2667,12 +2668,12 @@ qdio_shutdown(struct ccw_device *cdev, int how)
spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
} else if (rc == 0) { } else if (rc == 0) {
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_CLEANUP); qdio_set_state(irq_ptr, QDIO_IRQ_STATE_CLEANUP);
ccw_device_set_timeout(cdev, timeout);
spin_unlock_irqrestore(get_ccwdev_lock(cdev),flags); spin_unlock_irqrestore(get_ccwdev_lock(cdev),flags);
wait_event(cdev->private->wait_q, wait_event_interruptible_timeout(cdev->private->wait_q,
irq_ptr->state == QDIO_IRQ_STATE_INACTIVE || irq_ptr->state == QDIO_IRQ_STATE_INACTIVE ||
irq_ptr->state == QDIO_IRQ_STATE_ERR); irq_ptr->state == QDIO_IRQ_STATE_ERR,
timeout);
} else { } else {
QDIO_PRINT_INFO("ccw_device_{halt,clear} returned %d for " QDIO_PRINT_INFO("ccw_device_{halt,clear} returned %d for "
"device %s\n", result, cdev->dev.bus_id); "device %s\n", result, cdev->dev.bus_id);
...@@ -2692,7 +2693,6 @@ qdio_shutdown(struct ccw_device *cdev, int how) ...@@ -2692,7 +2693,6 @@ qdio_shutdown(struct ccw_device *cdev, int how)
/* Ignore errors. */ /* Ignore errors. */
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE); qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
ccw_device_set_timeout(cdev, 0);
out: out:
up(&irq_ptr->setting_up_sema); up(&irq_ptr->setting_up_sema);
return result; return result;
...@@ -2907,13 +2907,10 @@ qdio_establish_handle_irq(struct ccw_device *cdev, int cstat, int dstat) ...@@ -2907,13 +2907,10 @@ qdio_establish_handle_irq(struct ccw_device *cdev, int cstat, int dstat)
QDIO_DBF_TEXT0(0,setup,dbf_text); QDIO_DBF_TEXT0(0,setup,dbf_text);
QDIO_DBF_TEXT0(0,trace,dbf_text); QDIO_DBF_TEXT0(0,trace,dbf_text);
if (qdio_establish_irq_check_for_errors(cdev, cstat, dstat)) { if (qdio_establish_irq_check_for_errors(cdev, cstat, dstat))
ccw_device_set_timeout(cdev, 0);
return; return;
}
qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ESTABLISHED); qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ESTABLISHED);
ccw_device_set_timeout(cdev, 0);
} }
int int
...@@ -3196,8 +3193,6 @@ qdio_establish(struct qdio_initialize *init_data) ...@@ -3196,8 +3193,6 @@ qdio_establish(struct qdio_initialize *init_data)
irq_ptr->schid.ssid, irq_ptr->schid.sch_no, irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
result, result2); result, result2);
result=result2; result=result2;
if (result)
ccw_device_set_timeout(cdev, 0);
} }
spin_unlock_irqrestore(get_ccwdev_lock(cdev),saveflags); spin_unlock_irqrestore(get_ccwdev_lock(cdev),saveflags);
...@@ -3279,7 +3274,6 @@ qdio_activate(struct ccw_device *cdev, int flags) ...@@ -3279,7 +3274,6 @@ qdio_activate(struct ccw_device *cdev, int flags)
spin_lock_irqsave(get_ccwdev_lock(cdev),saveflags); spin_lock_irqsave(get_ccwdev_lock(cdev),saveflags);
ccw_device_set_timeout(cdev, 0);
ccw_device_set_options(cdev, CCWDEV_REPORT_ALL); ccw_device_set_options(cdev, CCWDEV_REPORT_ALL);
result=ccw_device_start(cdev,&irq_ptr->ccw,QDIO_DOING_ACTIVATE, result=ccw_device_start(cdev,&irq_ptr->ccw,QDIO_DOING_ACTIVATE,
0, DOIO_DENY_PREFETCH); 0, DOIO_DENY_PREFETCH);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment