aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/qdio.c
diff options
context:
space:
mode:
authorUrsula Braun <braunu@de.ibm.com>2008-07-14 03:57:25 -0400
committerHeiko Carstens <heiko.carstens@de.ibm.com>2008-07-14 04:01:59 -0400
commitbb0ca330a7e273cdecebae0283c9d267f60fe363 (patch)
treed5d1c3fb50c9ef53dedf5cafcd69b7b0214176be /drivers/s390/cio/qdio.c
parentb1c02d9110e72ec510ec9b038f9564e3c0d87384 (diff)
[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: Ursula Braun <braunu@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/qdio.c')
-rw-r--r--drivers/s390/cio/qdio.c20
1 files changed, 7 insertions, 13 deletions
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 445cf364e461..17df222dea80 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -2082,7 +2082,6 @@ qdio_timeout_handler(struct ccw_device *cdev)
2082 default: 2082 default:
2083 BUG(); 2083 BUG();
2084 } 2084 }
2085 ccw_device_set_timeout(cdev, 0);
2086 wake_up(&cdev->private->wait_q); 2085 wake_up(&cdev->private->wait_q);
2087} 2086}
2088 2087
@@ -2121,6 +2120,8 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
2121 case -EIO: 2120 case -EIO:
2122 QDIO_PRINT_ERR("i/o error on device %s\n", 2121 QDIO_PRINT_ERR("i/o error on device %s\n",
2123 cdev->dev.bus_id); 2122 cdev->dev.bus_id);
2123 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
2124 wake_up(&cdev->private->wait_q);
2124 return; 2125 return;
2125 case -ETIMEDOUT: 2126 case -ETIMEDOUT:
2126 qdio_timeout_handler(cdev); 2127 qdio_timeout_handler(cdev);
@@ -2667,12 +2668,12 @@ qdio_shutdown(struct ccw_device *cdev, int how)
2667 spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); 2668 spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
2668 } else if (rc == 0) { 2669 } else if (rc == 0) {
2669 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_CLEANUP); 2670 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_CLEANUP);
2670 ccw_device_set_timeout(cdev, timeout);
2671 spin_unlock_irqrestore(get_ccwdev_lock(cdev),flags); 2671 spin_unlock_irqrestore(get_ccwdev_lock(cdev),flags);
2672 2672
2673 wait_event(cdev->private->wait_q, 2673 wait_event_interruptible_timeout(cdev->private->wait_q,
2674 irq_ptr->state == QDIO_IRQ_STATE_INACTIVE || 2674 irq_ptr->state == QDIO_IRQ_STATE_INACTIVE ||
2675 irq_ptr->state == QDIO_IRQ_STATE_ERR); 2675 irq_ptr->state == QDIO_IRQ_STATE_ERR,
2676 timeout);
2676 } else { 2677 } else {
2677 QDIO_PRINT_INFO("ccw_device_{halt,clear} returned %d for " 2678 QDIO_PRINT_INFO("ccw_device_{halt,clear} returned %d for "
2678 "device %s\n", result, cdev->dev.bus_id); 2679 "device %s\n", result, cdev->dev.bus_id);
@@ -2692,7 +2693,6 @@ qdio_shutdown(struct ccw_device *cdev, int how)
2692 2693
2693 /* Ignore errors. */ 2694 /* Ignore errors. */
2694 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE); 2695 qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
2695 ccw_device_set_timeout(cdev, 0);
2696out: 2696out:
2697 up(&irq_ptr->setting_up_sema); 2697 up(&irq_ptr->setting_up_sema);
2698 return result; 2698 return result;
@@ -2907,13 +2907,10 @@ qdio_establish_handle_irq(struct ccw_device *cdev, int cstat, int dstat)
2907 QDIO_DBF_TEXT0(0,setup,dbf_text); 2907 QDIO_DBF_TEXT0(0,setup,dbf_text);
2908 QDIO_DBF_TEXT0(0,trace,dbf_text); 2908 QDIO_DBF_TEXT0(0,trace,dbf_text);
2909 2909
2910 if (qdio_establish_irq_check_for_errors(cdev, cstat, dstat)) { 2910 if (qdio_establish_irq_check_for_errors(cdev, cstat, dstat))
2911 ccw_device_set_timeout(cdev, 0);
2912 return; 2911 return;
2913 }
2914 2912
2915 qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ESTABLISHED); 2913 qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ESTABLISHED);
2916 ccw_device_set_timeout(cdev, 0);
2917} 2914}
2918 2915
2919int 2916int
@@ -3196,8 +3193,6 @@ qdio_establish(struct qdio_initialize *init_data)
3196 irq_ptr->schid.ssid, irq_ptr->schid.sch_no, 3193 irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
3197 result, result2); 3194 result, result2);
3198 result=result2; 3195 result=result2;
3199 if (result)
3200 ccw_device_set_timeout(cdev, 0);
3201 } 3196 }
3202 3197
3203 spin_unlock_irqrestore(get_ccwdev_lock(cdev),saveflags); 3198 spin_unlock_irqrestore(get_ccwdev_lock(cdev),saveflags);
@@ -3279,7 +3274,6 @@ qdio_activate(struct ccw_device *cdev, int flags)
3279 3274
3280 spin_lock_irqsave(get_ccwdev_lock(cdev),saveflags); 3275 spin_lock_irqsave(get_ccwdev_lock(cdev),saveflags);
3281 3276
3282 ccw_device_set_timeout(cdev, 0);
3283 ccw_device_set_options(cdev, CCWDEV_REPORT_ALL); 3277 ccw_device_set_options(cdev, CCWDEV_REPORT_ALL);
3284 result=ccw_device_start(cdev,&irq_ptr->ccw,QDIO_DOING_ACTIVATE, 3278 result=ccw_device_start(cdev,&irq_ptr->ccw,QDIO_DOING_ACTIVATE,
3285 0, DOIO_DENY_PREFETCH); 3279 0, DOIO_DENY_PREFETCH);