aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorStefan Bader <shbader@de.ibm.com>2006-08-30 08:33:39 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-08-30 08:33:39 -0400
commit7b7db1b59563aebe2f4d2ba850468afb2c87c82a (patch)
tree13906695f3afecc6329a2859fd8cdc54af099946 /drivers/s390/cio
parent3b88508a31a77eb3487154922e1eff282dc1d863 (diff)
[S390] cio: unsolicited interrupts during sense pgid.
Calls to set a device online with path grouping may get stuck in some cases because certain device conditions where discarded after unsolicited interrupts. Check subchannel activity after unsolicited interrupts and retry the operation if the subchannel is idle. Signed-off-by: Stefan Bader <shbader@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/device_pgid.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 32610fd8868e..1693a102dcfe 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -24,6 +24,21 @@
24#include "ioasm.h" 24#include "ioasm.h"
25 25
26/* 26/*
27 * Helper function called from interrupt context to decide whether an
28 * operation should be tried again.
29 */
30static int __ccw_device_should_retry(struct scsw *scsw)
31{
32 /* CC is only valid if start function bit is set. */
33 if ((scsw->fctl & SCSW_FCTL_START_FUNC) && scsw->cc == 1)
34 return 1;
35 /* No more activity. For sense and set PGID we stubbornly try again. */
36 if (!scsw->actl)
37 return 1;
38 return 0;
39}
40
41/*
27 * Start Sense Path Group ID helper function. Used in ccw_device_recog 42 * Start Sense Path Group ID helper function. Used in ccw_device_recog
28 * and ccw_device_sense_pgid. 43 * and ccw_device_sense_pgid.
29 */ 44 */
@@ -155,10 +170,10 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event)
155 int ret; 170 int ret;
156 171
157 irb = (struct irb *) __LC_IRB; 172 irb = (struct irb *) __LC_IRB;
158 /* Retry sense pgid for cc=1. */ 173
159 if (irb->scsw.stctl == 174 if (irb->scsw.stctl ==
160 (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { 175 (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
161 if (irb->scsw.cc == 1) { 176 if (__ccw_device_should_retry(&irb->scsw)) {
162 ret = __ccw_device_sense_pgid_start(cdev); 177 ret = __ccw_device_sense_pgid_start(cdev);
163 if (ret && ret != -EBUSY) 178 if (ret && ret != -EBUSY)
164 ccw_device_sense_pgid_done(cdev, ret); 179 ccw_device_sense_pgid_done(cdev, ret);
@@ -391,10 +406,10 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event)
391 int ret; 406 int ret;
392 407
393 irb = (struct irb *) __LC_IRB; 408 irb = (struct irb *) __LC_IRB;
394 /* Retry set pgid for cc=1. */ 409
395 if (irb->scsw.stctl == 410 if (irb->scsw.stctl ==
396 (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { 411 (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
397 if (irb->scsw.cc == 1) 412 if (__ccw_device_should_retry(&irb->scsw))
398 __ccw_device_verify_start(cdev); 413 __ccw_device_verify_start(cdev);
399 return; 414 return;
400 } 415 }
@@ -494,10 +509,10 @@ ccw_device_disband_irq(struct ccw_device *cdev, enum dev_event dev_event)
494 int ret; 509 int ret;
495 510
496 irb = (struct irb *) __LC_IRB; 511 irb = (struct irb *) __LC_IRB;
497 /* Retry set pgid for cc=1. */ 512
498 if (irb->scsw.stctl == 513 if (irb->scsw.stctl ==
499 (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { 514 (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
500 if (irb->scsw.cc == 1) 515 if (__ccw_device_should_retry(&irb->scsw))
501 __ccw_device_disband_start(cdev); 516 __ccw_device_disband_start(cdev);
502 return; 517 return;
503 } 518 }