aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
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 }