aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device_fsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/device_fsm.c')
-rw-r--r--drivers/s390/cio/device_fsm.c58
1 files changed, 35 insertions, 23 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 09c7672eb3f3..eed14572fc3b 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -186,15 +186,14 @@ ccw_device_handle_oper(struct ccw_device *cdev)
186 /* 186 /*
187 * Check if cu type and device type still match. If 187 * Check if cu type and device type still match. If
188 * not, it is certainly another device and we have to 188 * not, it is certainly another device and we have to
189 * de- and re-register. Also check here for non-matching devno. 189 * de- and re-register.
190 */ 190 */
191 if (cdev->id.cu_type != cdev->private->senseid.cu_type || 191 if (cdev->id.cu_type != cdev->private->senseid.cu_type ||
192 cdev->id.cu_model != cdev->private->senseid.cu_model || 192 cdev->id.cu_model != cdev->private->senseid.cu_model ||
193 cdev->id.dev_type != cdev->private->senseid.dev_type || 193 cdev->id.dev_type != cdev->private->senseid.dev_type ||
194 cdev->id.dev_model != cdev->private->senseid.dev_model || 194 cdev->id.dev_model != cdev->private->senseid.dev_model) {
195 cdev->private->dev_id.devno != sch->schib.pmcw.dev) {
196 PREPARE_WORK(&cdev->private->kick_work, 195 PREPARE_WORK(&cdev->private->kick_work,
197 ccw_device_do_unreg_rereg, cdev); 196 ccw_device_do_unreg_rereg);
198 queue_work(ccw_device_work, &cdev->private->kick_work); 197 queue_work(ccw_device_work, &cdev->private->kick_work);
199 return 0; 198 return 0;
200 } 199 }
@@ -329,19 +328,21 @@ ccw_device_sense_id_done(struct ccw_device *cdev, int err)
329} 328}
330 329
331static void 330static void
332ccw_device_oper_notify(void *data) 331ccw_device_oper_notify(struct work_struct *work)
333{ 332{
333 struct ccw_device_private *priv;
334 struct ccw_device *cdev; 334 struct ccw_device *cdev;
335 struct subchannel *sch; 335 struct subchannel *sch;
336 int ret; 336 int ret;
337 337
338 cdev = data; 338 priv = container_of(work, struct ccw_device_private, kick_work);
339 cdev = priv->cdev;
339 sch = to_subchannel(cdev->dev.parent); 340 sch = to_subchannel(cdev->dev.parent);
340 ret = (sch->driver && sch->driver->notify) ? 341 ret = (sch->driver && sch->driver->notify) ?
341 sch->driver->notify(&sch->dev, CIO_OPER) : 0; 342 sch->driver->notify(&sch->dev, CIO_OPER) : 0;
342 if (!ret) 343 if (!ret)
343 /* Driver doesn't want device back. */ 344 /* Driver doesn't want device back. */
344 ccw_device_do_unreg_rereg(cdev); 345 ccw_device_do_unreg_rereg(work);
345 else { 346 else {
346 /* Reenable channel measurements, if needed. */ 347 /* Reenable channel measurements, if needed. */
347 cmf_reenable(cdev); 348 cmf_reenable(cdev);
@@ -377,8 +378,7 @@ ccw_device_done(struct ccw_device *cdev, int state)
377 378
378 if (cdev->private->flags.donotify) { 379 if (cdev->private->flags.donotify) {
379 cdev->private->flags.donotify = 0; 380 cdev->private->flags.donotify = 0;
380 PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify, 381 PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify);
381 cdev);
382 queue_work(ccw_device_notify_work, &cdev->private->kick_work); 382 queue_work(ccw_device_notify_work, &cdev->private->kick_work);
383 } 383 }
384 wake_up(&cdev->private->wait_q); 384 wake_up(&cdev->private->wait_q);
@@ -528,13 +528,15 @@ ccw_device_recog_timeout(struct ccw_device *cdev, enum dev_event dev_event)
528 528
529 529
530static void 530static void
531ccw_device_nopath_notify(void *data) 531ccw_device_nopath_notify(struct work_struct *work)
532{ 532{
533 struct ccw_device_private *priv;
533 struct ccw_device *cdev; 534 struct ccw_device *cdev;
534 struct subchannel *sch; 535 struct subchannel *sch;
535 int ret; 536 int ret;
536 537
537 cdev = data; 538 priv = container_of(work, struct ccw_device_private, kick_work);
539 cdev = priv->cdev;
538 sch = to_subchannel(cdev->dev.parent); 540 sch = to_subchannel(cdev->dev.parent);
539 /* Extra sanity. */ 541 /* Extra sanity. */
540 if (sch->lpm) 542 if (sch->lpm)
@@ -547,8 +549,7 @@ ccw_device_nopath_notify(void *data)
547 cio_disable_subchannel(sch); 549 cio_disable_subchannel(sch);
548 if (get_device(&cdev->dev)) { 550 if (get_device(&cdev->dev)) {
549 PREPARE_WORK(&cdev->private->kick_work, 551 PREPARE_WORK(&cdev->private->kick_work,
550 ccw_device_call_sch_unregister, 552 ccw_device_call_sch_unregister);
551 cdev);
552 queue_work(ccw_device_work, 553 queue_work(ccw_device_work,
553 &cdev->private->kick_work); 554 &cdev->private->kick_work);
554 } else 555 } else
@@ -607,7 +608,7 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
607 /* Reset oper notify indication after verify error. */ 608 /* Reset oper notify indication after verify error. */
608 cdev->private->flags.donotify = 0; 609 cdev->private->flags.donotify = 0;
609 PREPARE_WORK(&cdev->private->kick_work, 610 PREPARE_WORK(&cdev->private->kick_work,
610 ccw_device_nopath_notify, cdev); 611 ccw_device_nopath_notify);
611 queue_work(ccw_device_notify_work, &cdev->private->kick_work); 612 queue_work(ccw_device_notify_work, &cdev->private->kick_work);
612 ccw_device_done(cdev, DEV_STATE_NOT_OPER); 613 ccw_device_done(cdev, DEV_STATE_NOT_OPER);
613 break; 614 break;
@@ -674,6 +675,10 @@ ccw_device_offline(struct ccw_device *cdev)
674{ 675{
675 struct subchannel *sch; 676 struct subchannel *sch;
676 677
678 if (ccw_device_is_orphan(cdev)) {
679 ccw_device_done(cdev, DEV_STATE_OFFLINE);
680 return 0;
681 }
677 sch = to_subchannel(cdev->dev.parent); 682 sch = to_subchannel(cdev->dev.parent);
678 if (stsch(sch->schid, &sch->schib) || !sch->schib.pmcw.dnv) 683 if (stsch(sch->schid, &sch->schib) || !sch->schib.pmcw.dnv)
679 return -ENODEV; 684 return -ENODEV;
@@ -738,7 +743,7 @@ ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event)
738 sch = to_subchannel(cdev->dev.parent); 743 sch = to_subchannel(cdev->dev.parent);
739 if (get_device(&cdev->dev)) { 744 if (get_device(&cdev->dev)) {
740 PREPARE_WORK(&cdev->private->kick_work, 745 PREPARE_WORK(&cdev->private->kick_work,
741 ccw_device_call_sch_unregister, cdev); 746 ccw_device_call_sch_unregister);
742 queue_work(ccw_device_work, &cdev->private->kick_work); 747 queue_work(ccw_device_work, &cdev->private->kick_work);
743 } 748 }
744 wake_up(&cdev->private->wait_q); 749 wake_up(&cdev->private->wait_q);
@@ -769,7 +774,7 @@ ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event)
769 } 774 }
770 if (get_device(&cdev->dev)) { 775 if (get_device(&cdev->dev)) {
771 PREPARE_WORK(&cdev->private->kick_work, 776 PREPARE_WORK(&cdev->private->kick_work,
772 ccw_device_call_sch_unregister, cdev); 777 ccw_device_call_sch_unregister);
773 queue_work(ccw_device_work, &cdev->private->kick_work); 778 queue_work(ccw_device_work, &cdev->private->kick_work);
774 } 779 }
775 wake_up(&cdev->private->wait_q); 780 wake_up(&cdev->private->wait_q);
@@ -874,7 +879,7 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event)
874 sch = to_subchannel(cdev->dev.parent); 879 sch = to_subchannel(cdev->dev.parent);
875 if (!sch->lpm) { 880 if (!sch->lpm) {
876 PREPARE_WORK(&cdev->private->kick_work, 881 PREPARE_WORK(&cdev->private->kick_work,
877 ccw_device_nopath_notify, cdev); 882 ccw_device_nopath_notify);
878 queue_work(ccw_device_notify_work, 883 queue_work(ccw_device_notify_work,
879 &cdev->private->kick_work); 884 &cdev->private->kick_work);
880 } else 885 } else
@@ -969,7 +974,7 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
969 ERR_PTR(-EIO)); 974 ERR_PTR(-EIO));
970 if (!sch->lpm) { 975 if (!sch->lpm) {
971 PREPARE_WORK(&cdev->private->kick_work, 976 PREPARE_WORK(&cdev->private->kick_work,
972 ccw_device_nopath_notify, cdev); 977 ccw_device_nopath_notify);
973 queue_work(ccw_device_notify_work, &cdev->private->kick_work); 978 queue_work(ccw_device_notify_work, &cdev->private->kick_work);
974 } else if (cdev->private->flags.doverify) 979 } else if (cdev->private->flags.doverify)
975 /* Start delayed path verification. */ 980 /* Start delayed path verification. */
@@ -992,7 +997,7 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
992 sch = to_subchannel(cdev->dev.parent); 997 sch = to_subchannel(cdev->dev.parent);
993 if (!sch->lpm) { 998 if (!sch->lpm) {
994 PREPARE_WORK(&cdev->private->kick_work, 999 PREPARE_WORK(&cdev->private->kick_work,
995 ccw_device_nopath_notify, cdev); 1000 ccw_device_nopath_notify);
996 queue_work(ccw_device_notify_work, 1001 queue_work(ccw_device_notify_work,
997 &cdev->private->kick_work); 1002 &cdev->private->kick_work);
998 } else 1003 } else
@@ -1021,7 +1026,7 @@ void device_kill_io(struct subchannel *sch)
1021 if (ret == -ENODEV) { 1026 if (ret == -ENODEV) {
1022 if (!sch->lpm) { 1027 if (!sch->lpm) {
1023 PREPARE_WORK(&cdev->private->kick_work, 1028 PREPARE_WORK(&cdev->private->kick_work,
1024 ccw_device_nopath_notify, cdev); 1029 ccw_device_nopath_notify);
1025 queue_work(ccw_device_notify_work, 1030 queue_work(ccw_device_notify_work,
1026 &cdev->private->kick_work); 1031 &cdev->private->kick_work);
1027 } else 1032 } else
@@ -1033,7 +1038,7 @@ void device_kill_io(struct subchannel *sch)
1033 ERR_PTR(-EIO)); 1038 ERR_PTR(-EIO));
1034 if (!sch->lpm) { 1039 if (!sch->lpm) {
1035 PREPARE_WORK(&cdev->private->kick_work, 1040 PREPARE_WORK(&cdev->private->kick_work,
1036 ccw_device_nopath_notify, cdev); 1041 ccw_device_nopath_notify);
1037 queue_work(ccw_device_notify_work, &cdev->private->kick_work); 1042 queue_work(ccw_device_notify_work, &cdev->private->kick_work);
1038 } else 1043 } else
1039 /* Start delayed path verification. */ 1044 /* Start delayed path verification. */
@@ -1104,7 +1109,8 @@ device_trigger_reprobe(struct subchannel *sch)
1104 /* Update some values. */ 1109 /* Update some values. */
1105 if (stsch(sch->schid, &sch->schib)) 1110 if (stsch(sch->schid, &sch->schib))
1106 return; 1111 return;
1107 1112 if (!sch->schib.pmcw.dnv)
1113 return;
1108 /* 1114 /*
1109 * The pim, pam, pom values may not be accurate, but they are the best 1115 * The pim, pam, pom values may not be accurate, but they are the best
1110 * we have before performing device selection :/ 1116 * we have before performing device selection :/
@@ -1118,7 +1124,13 @@ device_trigger_reprobe(struct subchannel *sch)
1118 sch->schib.pmcw.mp = 1; 1124 sch->schib.pmcw.mp = 1;
1119 sch->schib.pmcw.intparm = (__u32)(unsigned long)sch; 1125 sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
1120 /* We should also udate ssd info, but this has to wait. */ 1126 /* We should also udate ssd info, but this has to wait. */
1121 ccw_device_start_id(cdev, 0); 1127 /* Check if this is another device which appeared on the same sch. */
1128 if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {
1129 PREPARE_WORK(&cdev->private->kick_work,
1130 ccw_device_move_to_orphanage);
1131 queue_work(ccw_device_work, &cdev->private->kick_work);
1132 } else
1133 ccw_device_start_id(cdev, 0);
1122} 1134}
1123 1135
1124static void 1136static void