aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/cio/device_fsm.c30
-rw-r--r--drivers/s390/cio/device_ops.c12
-rw-r--r--drivers/s390/cio/io_sch.h5
3 files changed, 37 insertions, 10 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 52c233fa2b12..1b853513c891 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -496,8 +496,26 @@ static void ccw_device_reset_path_events(struct ccw_device *cdev)
496 cdev->private->pgid_reset_mask = 0; 496 cdev->private->pgid_reset_mask = 0;
497} 497}
498 498
499void 499static void create_fake_irb(struct irb *irb, int type)
500ccw_device_verify_done(struct ccw_device *cdev, int err) 500{
501 memset(irb, 0, sizeof(*irb));
502 if (type == FAKE_CMD_IRB) {
503 struct cmd_scsw *scsw = &irb->scsw.cmd;
504 scsw->cc = 1;
505 scsw->fctl = SCSW_FCTL_START_FUNC;
506 scsw->actl = SCSW_ACTL_START_PEND;
507 scsw->stctl = SCSW_STCTL_STATUS_PEND;
508 } else if (type == FAKE_TM_IRB) {
509 struct tm_scsw *scsw = &irb->scsw.tm;
510 scsw->x = 1;
511 scsw->cc = 1;
512 scsw->fctl = SCSW_FCTL_START_FUNC;
513 scsw->actl = SCSW_ACTL_START_PEND;
514 scsw->stctl = SCSW_STCTL_STATUS_PEND;
515 }
516}
517
518void ccw_device_verify_done(struct ccw_device *cdev, int err)
501{ 519{
502 struct subchannel *sch; 520 struct subchannel *sch;
503 521
@@ -520,12 +538,8 @@ callback:
520 ccw_device_done(cdev, DEV_STATE_ONLINE); 538 ccw_device_done(cdev, DEV_STATE_ONLINE);
521 /* Deliver fake irb to device driver, if needed. */ 539 /* Deliver fake irb to device driver, if needed. */
522 if (cdev->private->flags.fake_irb) { 540 if (cdev->private->flags.fake_irb) {
523 memset(&cdev->private->irb, 0, sizeof(struct irb)); 541 create_fake_irb(&cdev->private->irb,
524 cdev->private->irb.scsw.cmd.cc = 1; 542 cdev->private->flags.fake_irb);
525 cdev->private->irb.scsw.cmd.fctl = SCSW_FCTL_START_FUNC;
526 cdev->private->irb.scsw.cmd.actl = SCSW_ACTL_START_PEND;
527 cdev->private->irb.scsw.cmd.stctl =
528 SCSW_STCTL_STATUS_PEND;
529 cdev->private->flags.fake_irb = 0; 543 cdev->private->flags.fake_irb = 0;
530 if (cdev->handler) 544 if (cdev->handler)
531 cdev->handler(cdev, cdev->private->intparm, 545 cdev->handler(cdev, cdev->private->intparm,
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 41c21ad0d5f2..ec7fb6d3b479 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -198,7 +198,7 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
198 if (cdev->private->state == DEV_STATE_VERIFY) { 198 if (cdev->private->state == DEV_STATE_VERIFY) {
199 /* Remember to fake irb when finished. */ 199 /* Remember to fake irb when finished. */
200 if (!cdev->private->flags.fake_irb) { 200 if (!cdev->private->flags.fake_irb) {
201 cdev->private->flags.fake_irb = 1; 201 cdev->private->flags.fake_irb = FAKE_CMD_IRB;
202 cdev->private->intparm = intparm; 202 cdev->private->intparm = intparm;
203 return 0; 203 return 0;
204 } else 204 } else
@@ -605,6 +605,16 @@ int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,
605 sch = to_subchannel(cdev->dev.parent); 605 sch = to_subchannel(cdev->dev.parent);
606 if (!sch->schib.pmcw.ena) 606 if (!sch->schib.pmcw.ena)
607 return -EINVAL; 607 return -EINVAL;
608 if (cdev->private->state == DEV_STATE_VERIFY) {
609 /* Remember to fake irb when finished. */
610 if (!cdev->private->flags.fake_irb) {
611 cdev->private->flags.fake_irb = FAKE_TM_IRB;
612 cdev->private->intparm = intparm;
613 return 0;
614 } else
615 /* There's already a fake I/O around. */
616 return -EBUSY;
617 }
608 if (cdev->private->state != DEV_STATE_ONLINE) 618 if (cdev->private->state != DEV_STATE_ONLINE)
609 return -EIO; 619 return -EIO;
610 /* Adjust requested path mask to exclude unusable paths. */ 620 /* Adjust requested path mask to exclude unusable paths. */
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h
index 2ebb492a5c17..76253dfcc1be 100644
--- a/drivers/s390/cio/io_sch.h
+++ b/drivers/s390/cio/io_sch.h
@@ -111,6 +111,9 @@ enum cdev_todo {
111 CDEV_TODO_UNREG_EVAL, 111 CDEV_TODO_UNREG_EVAL,
112}; 112};
113 113
114#define FAKE_CMD_IRB 1
115#define FAKE_TM_IRB 2
116
114struct ccw_device_private { 117struct ccw_device_private {
115 struct ccw_device *cdev; 118 struct ccw_device *cdev;
116 struct subchannel *sch; 119 struct subchannel *sch;
@@ -138,7 +141,7 @@ struct ccw_device_private {
138 unsigned int doverify:1; /* delayed path verification */ 141 unsigned int doverify:1; /* delayed path verification */
139 unsigned int donotify:1; /* call notify function */ 142 unsigned int donotify:1; /* call notify function */
140 unsigned int recog_done:1; /* dev. recog. complete */ 143 unsigned int recog_done:1; /* dev. recog. complete */
141 unsigned int fake_irb:1; /* deliver faked irb */ 144 unsigned int fake_irb:2; /* deliver faked irb */
142 unsigned int resuming:1; /* recognition while resume */ 145 unsigned int resuming:1; /* recognition while resume */
143 unsigned int pgroup:1; /* pathgroup is set up */ 146 unsigned int pgroup:1; /* pathgroup is set up */
144 unsigned int mpath:1; /* multipathing is set up */ 147 unsigned int mpath:1; /* multipathing is set up */