aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device.c
diff options
context:
space:
mode:
authorPeter Oberparleiter <peter.oberparleiter@de.ibm.com>2009-12-07 06:51:17 -0500
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2009-12-07 06:51:29 -0500
commit5d6e6b6f6f3eac10a7f5a15e961bac3b36824d9d (patch)
treeb64af704c59b0820c0537bd0bed45caa0d5e26b7 /drivers/s390/cio/device.c
parent60e4dac1abdf49ccdb7545ec406325f08423d848 (diff)
[S390] cio: introduce parent-initiated device move
Change the initiative to update subchannel-ccw device associations to the subchannel: when there is an indication that the internal association no longer reflects the current hardware state, mark each affected subchannel as requiring attention. Once processing reaches a subchannel, determine the correct association for that subchannel at that time and perform the necessary device_move operations. This change fixes problems with the previous approach which would leave devices in an inconsistent state when a new hardware change occurred while a device_move was already scheduled. Signed-off-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/device.c')
-rw-r--r--drivers/s390/cio/device.c513
1 files changed, 182 insertions, 331 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 0efecefdb83a..6097763f1035 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -673,57 +673,19 @@ static int ccw_device_register(struct ccw_device *cdev)
673 return ret; 673 return ret;
674} 674}
675 675
676struct match_data { 676static int match_dev_id(struct device *dev, void *data)
677 struct ccw_dev_id dev_id;
678 struct ccw_device * sibling;
679};
680
681static int
682match_devno(struct device * dev, void * data)
683{
684 struct match_data * d = data;
685 struct ccw_device * cdev;
686
687 cdev = to_ccwdev(dev);
688 if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
689 !ccw_device_is_orphan(cdev) &&
690 ccw_dev_id_is_equal(&cdev->private->dev_id, &d->dev_id) &&
691 (cdev != d->sibling))
692 return 1;
693 return 0;
694}
695
696static struct ccw_device * get_disc_ccwdev_by_dev_id(struct ccw_dev_id *dev_id,
697 struct ccw_device *sibling)
698{ 677{
699 struct device *dev; 678 struct ccw_device *cdev = to_ccwdev(dev);
700 struct match_data data; 679 struct ccw_dev_id *dev_id = data;
701
702 data.dev_id = *dev_id;
703 data.sibling = sibling;
704 dev = bus_find_device(&ccw_bus_type, NULL, &data, match_devno);
705
706 return dev ? to_ccwdev(dev) : NULL;
707}
708
709static int match_orphan(struct device *dev, void *data)
710{
711 struct ccw_dev_id *dev_id;
712 struct ccw_device *cdev;
713 680
714 dev_id = data;
715 cdev = to_ccwdev(dev);
716 return ccw_dev_id_is_equal(&cdev->private->dev_id, dev_id); 681 return ccw_dev_id_is_equal(&cdev->private->dev_id, dev_id);
717} 682}
718 683
719static struct ccw_device * 684static struct ccw_device *get_ccwdev_by_dev_id(struct ccw_dev_id *dev_id)
720get_orphaned_ccwdev_by_dev_id(struct channel_subsystem *css,
721 struct ccw_dev_id *dev_id)
722{ 685{
723 struct device *dev; 686 struct device *dev;
724 687
725 dev = device_find_child(&css->pseudo_subchannel->dev, dev_id, 688 dev = bus_find_device(&ccw_bus_type, NULL, dev_id, match_dev_id);
726 match_orphan);
727 689
728 return dev ? to_ccwdev(dev) : NULL; 690 return dev ? to_ccwdev(dev) : NULL;
729} 691}
@@ -808,75 +770,6 @@ static struct ccw_device * io_subchannel_create_ccwdev(struct subchannel *sch)
808 770
809static int io_subchannel_recog(struct ccw_device *, struct subchannel *); 771static int io_subchannel_recog(struct ccw_device *, struct subchannel *);
810 772
811static void sch_attach_device(struct subchannel *sch,
812 struct ccw_device *cdev)
813{
814 css_update_ssd_info(sch);
815 spin_lock_irq(sch->lock);
816 sch_set_cdev(sch, cdev);
817 cdev->private->schid = sch->schid;
818 cdev->ccwlock = sch->lock;
819 ccw_device_trigger_reprobe(cdev);
820 spin_unlock_irq(sch->lock);
821}
822
823static void sch_attach_disconnected_device(struct subchannel *sch,
824 struct ccw_device *cdev)
825{
826 struct subchannel *other_sch;
827 int ret;
828
829 /* Get reference for new parent. */
830 if (!get_device(&sch->dev))
831 return;
832 other_sch = to_subchannel(cdev->dev.parent);
833 /* Note: device_move() changes cdev->dev.parent */
834 ret = device_move(&cdev->dev, &sch->dev, DPM_ORDER_PARENT_BEFORE_DEV);
835 if (ret) {
836 CIO_MSG_EVENT(0, "Moving disconnected device 0.%x.%04x failed "
837 "(ret=%d)!\n", cdev->private->dev_id.ssid,
838 cdev->private->dev_id.devno, ret);
839 /* Put reference for new parent. */
840 put_device(&sch->dev);
841 return;
842 }
843 sch_set_cdev(other_sch, NULL);
844 /* No need to keep a subchannel without ccw device around. */
845 css_sch_device_unregister(other_sch);
846 sch_attach_device(sch, cdev);
847 /* Put reference for old parent. */
848 put_device(&other_sch->dev);
849}
850
851static void sch_attach_orphaned_device(struct subchannel *sch,
852 struct ccw_device *cdev)
853{
854 int ret;
855 struct subchannel *pseudo_sch;
856
857 /* Get reference for new parent. */
858 if (!get_device(&sch->dev))
859 return;
860 pseudo_sch = to_subchannel(cdev->dev.parent);
861 /*
862 * Try to move the ccw device to its new subchannel.
863 * Note: device_move() changes cdev->dev.parent
864 */
865 ret = device_move(&cdev->dev, &sch->dev, DPM_ORDER_PARENT_BEFORE_DEV);
866 if (ret) {
867 CIO_MSG_EVENT(0, "Moving device 0.%x.%04x from orphanage "
868 "failed (ret=%d)!\n",
869 cdev->private->dev_id.ssid,
870 cdev->private->dev_id.devno, ret);
871 /* Put reference for new parent. */
872 put_device(&sch->dev);
873 return;
874 }
875 sch_attach_device(sch, cdev);
876 /* Put reference on pseudo subchannel. */
877 put_device(&pseudo_sch->dev);
878}
879
880static void sch_create_and_recog_new_device(struct subchannel *sch) 773static void sch_create_and_recog_new_device(struct subchannel *sch)
881{ 774{
882 struct ccw_device *cdev; 775 struct ccw_device *cdev;
@@ -901,70 +794,6 @@ static void sch_create_and_recog_new_device(struct subchannel *sch)
901 } 794 }
902} 795}
903 796
904
905void ccw_device_move_to_orphanage(struct work_struct *work)
906{
907 struct ccw_device_private *priv;
908 struct ccw_device *cdev;
909 struct ccw_device *replacing_cdev;
910 struct subchannel *sch;
911 int ret;
912 struct channel_subsystem *css;
913 struct ccw_dev_id dev_id;
914
915 priv = container_of(work, struct ccw_device_private, kick_work);
916 cdev = priv->cdev;
917 sch = to_subchannel(cdev->dev.parent);
918 css = to_css(sch->dev.parent);
919 dev_id.devno = sch->schib.pmcw.dev;
920 dev_id.ssid = sch->schid.ssid;
921
922 /* Increase refcount for pseudo subchannel. */
923 get_device(&css->pseudo_subchannel->dev);
924 /*
925 * Move the orphaned ccw device to the orphanage so the replacing
926 * ccw device can take its place on the subchannel.
927 * Note: device_move() changes cdev->dev.parent
928 */
929 ret = device_move(&cdev->dev, &css->pseudo_subchannel->dev,
930 DPM_ORDER_NONE);
931 if (ret) {
932 CIO_MSG_EVENT(0, "Moving device 0.%x.%04x to orphanage failed "
933 "(ret=%d)!\n", cdev->private->dev_id.ssid,
934 cdev->private->dev_id.devno, ret);
935 /* Decrease refcount for pseudo subchannel again. */
936 put_device(&css->pseudo_subchannel->dev);
937 return;
938 }
939 cdev->ccwlock = css->pseudo_subchannel->lock;
940 /*
941 * Search for the replacing ccw device
942 * - among the disconnected devices
943 * - in the orphanage
944 */
945 replacing_cdev = get_disc_ccwdev_by_dev_id(&dev_id, cdev);
946 if (replacing_cdev) {
947 sch_attach_disconnected_device(sch, replacing_cdev);
948 /* Release reference from get_disc_ccwdev_by_dev_id() */
949 put_device(&replacing_cdev->dev);
950 /* Release reference of subchannel from old cdev. */
951 put_device(&sch->dev);
952 return;
953 }
954 replacing_cdev = get_orphaned_ccwdev_by_dev_id(css, &dev_id);
955 if (replacing_cdev) {
956 sch_attach_orphaned_device(sch, replacing_cdev);
957 /* Release reference from get_orphaned_ccwdev_by_dev_id() */
958 put_device(&replacing_cdev->dev);
959 /* Release reference of subchannel from old cdev. */
960 put_device(&sch->dev);
961 return;
962 }
963 sch_create_and_recog_new_device(sch);
964 /* Release reference of subchannel from old cdev. */
965 put_device(&sch->dev);
966}
967
968/* 797/*
969 * Register recognized device. 798 * Register recognized device.
970 */ 799 */
@@ -1131,53 +960,56 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
1131 return rc; 960 return rc;
1132} 961}
1133 962
1134static void ccw_device_move_to_sch(struct work_struct *work) 963static int ccw_device_move_to_sch(struct ccw_device *cdev,
964 struct subchannel *sch)
1135{ 965{
1136 struct ccw_device_private *priv; 966 struct subchannel *old_sch;
1137 int rc; 967 int rc;
1138 struct subchannel *sch;
1139 struct ccw_device *cdev;
1140 struct subchannel *former_parent;
1141 968
1142 priv = container_of(work, struct ccw_device_private, kick_work); 969 old_sch = to_subchannel(cdev->dev.parent);
1143 sch = priv->sch; 970 /* Obtain child reference for new parent. */
1144 cdev = priv->cdev;
1145 former_parent = to_subchannel(cdev->dev.parent);
1146 /* Get reference for new parent. */
1147 if (!get_device(&sch->dev)) 971 if (!get_device(&sch->dev))
1148 return; 972 return -ENODEV;
1149 mutex_lock(&sch->reg_mutex); 973 mutex_lock(&sch->reg_mutex);
1150 /*
1151 * Try to move the ccw device to its new subchannel.
1152 * Note: device_move() changes cdev->dev.parent
1153 */
1154 rc = device_move(&cdev->dev, &sch->dev, DPM_ORDER_PARENT_BEFORE_DEV); 974 rc = device_move(&cdev->dev, &sch->dev, DPM_ORDER_PARENT_BEFORE_DEV);
1155 mutex_unlock(&sch->reg_mutex); 975 mutex_unlock(&sch->reg_mutex);
1156 if (rc) { 976 if (rc) {
1157 CIO_MSG_EVENT(0, "Moving device 0.%x.%04x to subchannel " 977 CIO_MSG_EVENT(0, "device_move(0.%x.%04x,0.%x.%04x)=%d\n",
1158 "0.%x.%04x failed (ret=%d)!\n",
1159 cdev->private->dev_id.ssid, 978 cdev->private->dev_id.ssid,
1160 cdev->private->dev_id.devno, sch->schid.ssid, 979 cdev->private->dev_id.devno, sch->schid.ssid,
1161 sch->schid.sch_no, rc); 980 sch->schib.pmcw.dev, rc);
1162 css_sch_device_unregister(sch); 981 /* Release child reference for new parent. */
1163 /* Put reference for new parent again. */
1164 put_device(&sch->dev); 982 put_device(&sch->dev);
1165 goto out; 983 return rc;
1166 } 984 }
1167 if (!sch_is_pseudo_sch(former_parent)) { 985 /* Clean up old subchannel. */
1168 spin_lock_irq(former_parent->lock); 986 if (!sch_is_pseudo_sch(old_sch)) {
1169 sch_set_cdev(former_parent, NULL); 987 spin_lock_irq(old_sch->lock);
1170 spin_unlock_irq(former_parent->lock); 988 sch_set_cdev(old_sch, NULL);
1171 css_sch_device_unregister(former_parent); 989 cio_disable_subchannel(old_sch);
1172 /* Reset intparm to zeroes. */ 990 spin_unlock_irq(old_sch->lock);
1173 former_parent->config.intparm = 0; 991 css_schedule_eval(old_sch->schid);
1174 cio_commit_config(former_parent);
1175 } 992 }
1176 sch_attach_device(sch, cdev); 993 /* Release child reference for old parent. */
1177out: 994 put_device(&old_sch->dev);
1178 /* Put reference for old parent. */ 995 /* Initialize new subchannel. */
1179 put_device(&former_parent->dev); 996 spin_lock_irq(sch->lock);
1180 put_device(&cdev->dev); 997 cdev->private->schid = sch->schid;
998 cdev->ccwlock = sch->lock;
999 if (!sch_is_pseudo_sch(sch))
1000 sch_set_cdev(sch, cdev);
1001 spin_unlock_irq(sch->lock);
1002 if (!sch_is_pseudo_sch(sch))
1003 css_update_ssd_info(sch);
1004 return 0;
1005}
1006
1007static int ccw_device_move_to_orph(struct ccw_device *cdev)
1008{
1009 struct subchannel *sch = to_subchannel(cdev->dev.parent);
1010 struct channel_subsystem *css = to_css(sch->dev.parent);
1011
1012 return ccw_device_move_to_sch(cdev, css->pseudo_subchannel);
1181} 1013}
1182 1014
1183static void io_subchannel_irq(struct subchannel *sch) 1015static void io_subchannel_irq(struct subchannel *sch)
@@ -1244,8 +1076,6 @@ static int io_subchannel_probe(struct subchannel *sch)
1244{ 1076{
1245 struct ccw_device *cdev; 1077 struct ccw_device *cdev;
1246 int rc; 1078 int rc;
1247 unsigned long flags;
1248 struct ccw_dev_id dev_id;
1249 1079
1250 if (cio_is_console(sch->schid)) { 1080 if (cio_is_console(sch->schid)) {
1251 rc = sysfs_create_group(&sch->dev.kobj, 1081 rc = sysfs_create_group(&sch->dev.kobj,
@@ -1290,37 +1120,7 @@ static int io_subchannel_probe(struct subchannel *sch)
1290 GFP_KERNEL | GFP_DMA); 1120 GFP_KERNEL | GFP_DMA);
1291 if (!sch->private) 1121 if (!sch->private)
1292 goto out_schedule; 1122 goto out_schedule;
1293 /* 1123 css_schedule_eval(sch->schid);
1294 * First check if a fitting device may be found amongst the
1295 * disconnected devices or in the orphanage.
1296 */
1297 dev_id.devno = sch->schib.pmcw.dev;
1298 dev_id.ssid = sch->schid.ssid;
1299 cdev = get_disc_ccwdev_by_dev_id(&dev_id, NULL);
1300 if (!cdev)
1301 cdev = get_orphaned_ccwdev_by_dev_id(to_css(sch->dev.parent),
1302 &dev_id);
1303 if (cdev) {
1304 /*
1305 * Schedule moving the device until when we have a registered
1306 * subchannel to move to and succeed the probe. We can
1307 * unregister later again, when the probe is through.
1308 */
1309 cdev->private->sch = sch;
1310 PREPARE_WORK(&cdev->private->kick_work,
1311 ccw_device_move_to_sch);
1312 queue_work(slow_path_wq, &cdev->private->kick_work);
1313 return 0;
1314 }
1315 cdev = io_subchannel_create_ccwdev(sch);
1316 if (IS_ERR(cdev))
1317 goto out_schedule;
1318 rc = io_subchannel_recog(cdev, sch);
1319 if (rc) {
1320 spin_lock_irqsave(sch->lock, flags);
1321 io_subchannel_recog_done(cdev);
1322 spin_unlock_irqrestore(sch->lock, flags);
1323 }
1324 return 0; 1124 return 0;
1325 1125
1326out_schedule: 1126out_schedule:
@@ -1349,16 +1149,6 @@ out_free:
1349 return 0; 1149 return 0;
1350} 1150}
1351 1151
1352static int io_subchannel_notify(struct subchannel *sch, int event)
1353{
1354 struct ccw_device *cdev;
1355
1356 cdev = sch_get_cdev(sch);
1357 if (!cdev)
1358 return 0;
1359 return ccw_device_notify(cdev, event);
1360}
1361
1362static void io_subchannel_verify(struct subchannel *sch) 1152static void io_subchannel_verify(struct subchannel *sch)
1363{ 1153{
1364 struct ccw_device *cdev; 1154 struct ccw_device *cdev;
@@ -1482,19 +1272,6 @@ io_subchannel_shutdown(struct subchannel *sch)
1482 cio_disable_subchannel(sch); 1272 cio_disable_subchannel(sch);
1483} 1273}
1484 1274
1485static int io_subchannel_get_status(struct subchannel *sch)
1486{
1487 struct schib schib;
1488
1489 if (stsch(sch->schid, &schib) || !schib.pmcw.dnv)
1490 return CIO_GONE;
1491 if (sch->schib.pmcw.dnv && (schib.pmcw.dev != sch->schib.pmcw.dev))
1492 return CIO_REVALIDATE;
1493 if (!sch->lpm)
1494 return CIO_NO_PATH;
1495 return CIO_OPER;
1496}
1497
1498static int device_is_disconnected(struct ccw_device *cdev) 1275static int device_is_disconnected(struct ccw_device *cdev)
1499{ 1276{
1500 if (!cdev) 1277 if (!cdev)
@@ -1626,91 +1403,165 @@ void ccw_device_set_notoper(struct ccw_device *cdev)
1626 cdev->private->state = DEV_STATE_NOT_OPER; 1403 cdev->private->state = DEV_STATE_NOT_OPER;
1627} 1404}
1628 1405
1629static int io_subchannel_sch_event(struct subchannel *sch, int slow) 1406enum io_sch_action {
1407 IO_SCH_UNREG,
1408 IO_SCH_ORPH_UNREG,
1409 IO_SCH_ATTACH,
1410 IO_SCH_UNREG_ATTACH,
1411 IO_SCH_ORPH_ATTACH,
1412 IO_SCH_REPROBE,
1413 IO_SCH_VERIFY,
1414 IO_SCH_DISC,
1415 IO_SCH_NOP,
1416};
1417
1418static enum io_sch_action sch_get_action(struct subchannel *sch)
1419{
1420 struct ccw_device *cdev;
1421
1422 cdev = sch_get_cdev(sch);
1423 if (cio_update_schib(sch)) {
1424 /* Not operational. */
1425 if (!cdev)
1426 return IO_SCH_UNREG;
1427 if (!ccw_device_notify(cdev, CIO_GONE))
1428 return IO_SCH_UNREG;
1429 return IO_SCH_ORPH_UNREG;
1430 }
1431 /* Operational. */
1432 if (!cdev)
1433 return IO_SCH_ATTACH;
1434 if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {
1435 if (!ccw_device_notify(cdev, CIO_GONE))
1436 return IO_SCH_UNREG_ATTACH;
1437 return IO_SCH_ORPH_ATTACH;
1438 }
1439 if ((sch->schib.pmcw.pam & sch->opm) == 0) {
1440 if (!ccw_device_notify(cdev, CIO_NO_PATH))
1441 return IO_SCH_UNREG;
1442 return IO_SCH_DISC;
1443 }
1444 if (device_is_disconnected(cdev))
1445 return IO_SCH_REPROBE;
1446 if (cdev->online)
1447 return IO_SCH_VERIFY;
1448 return IO_SCH_NOP;
1449}
1450
1451/**
1452 * io_subchannel_sch_event - process subchannel event
1453 * @sch: subchannel
1454 * @process: non-zero if function is called in process context
1455 *
1456 * An unspecified event occurred for this subchannel. Adjust data according
1457 * to the current operational state of the subchannel and device. Return
1458 * zero when the event has been handled sufficiently or -EAGAIN when this
1459 * function should be called again in process context.
1460 */
1461static int io_subchannel_sch_event(struct subchannel *sch, int process)
1630{ 1462{
1631 int event, ret, disc;
1632 unsigned long flags; 1463 unsigned long flags;
1633 enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE, DISC } action;
1634 struct ccw_device *cdev; 1464 struct ccw_device *cdev;
1465 struct ccw_dev_id dev_id;
1466 enum io_sch_action action;
1467 int rc = -EAGAIN;
1635 1468
1636 spin_lock_irqsave(sch->lock, flags); 1469 spin_lock_irqsave(sch->lock, flags);
1470 if (!device_is_registered(&sch->dev))
1471 goto out_unlock;
1472 action = sch_get_action(sch);
1473 CIO_MSG_EVENT(2, "event: sch 0.%x.%04x, process=%d, action=%d\n",
1474 sch->schid.ssid, sch->schid.sch_no, process,
1475 action);
1476 /* Perform immediate actions while holding the lock. */
1637 cdev = sch_get_cdev(sch); 1477 cdev = sch_get_cdev(sch);
1638 disc = device_is_disconnected(cdev); 1478 switch (action) {
1639 if (disc && slow) { 1479 case IO_SCH_REPROBE:
1640 /* Disconnected devices are evaluated directly only.*/ 1480 /* Trigger device recognition. */
1641 spin_unlock_irqrestore(sch->lock, flags); 1481 ccw_device_trigger_reprobe(cdev);
1642 return 0; 1482 rc = 0;
1643 } 1483 goto out_unlock;
1644 /* No interrupt after machine check - kill pending timers. */ 1484 case IO_SCH_VERIFY:
1645 if (cdev) 1485 /* Trigger path verification. */
1646 ccw_device_set_timeout(cdev, 0); 1486 io_subchannel_verify(sch);
1647 if (!disc && !slow) { 1487 rc = 0;
1648 /* Non-disconnected devices are evaluated on the slow path. */ 1488 goto out_unlock;
1649 spin_unlock_irqrestore(sch->lock, flags); 1489 case IO_SCH_DISC:
1650 return -EAGAIN; 1490 ccw_device_set_disconnected(cdev);
1491 rc = 0;
1492 goto out_unlock;
1493 case IO_SCH_ORPH_UNREG:
1494 case IO_SCH_ORPH_ATTACH:
1495 ccw_device_set_disconnected(cdev);
1496 break;
1497 case IO_SCH_UNREG_ATTACH:
1498 case IO_SCH_UNREG:
1499 if (cdev)
1500 ccw_device_set_notoper(cdev);
1501 break;
1502 case IO_SCH_NOP:
1503 rc = 0;
1504 goto out_unlock;
1505 default:
1506 break;
1651 } 1507 }
1652 event = io_subchannel_get_status(sch); 1508 spin_unlock_irqrestore(sch->lock, flags);
1653 CIO_MSG_EVENT(4, "Evaluating schid 0.%x.%04x, event %d, %s, %s path.\n", 1509 /* All other actions require process context. */
1654 sch->schid.ssid, sch->schid.sch_no, event, 1510 if (!process)
1655 disc ? "disconnected" : "normal", 1511 goto out;
1656 slow ? "slow" : "fast"); 1512 /* Handle attached ccw device. */
1657 /* Analyze subchannel status. */ 1513 switch (action) {
1658 action = NONE; 1514 case IO_SCH_ORPH_UNREG:
1659 switch (event) { 1515 case IO_SCH_ORPH_ATTACH:
1660 case CIO_NO_PATH: 1516 /* Move ccw device to orphanage. */
1661 if (disc) { 1517 rc = ccw_device_move_to_orph(cdev);
1662 /* Check if paths have become available. */ 1518 if (rc)
1663 action = REPROBE; 1519 goto out;
1664 break;
1665 }
1666 /* fall through */
1667 case CIO_GONE:
1668 /* Ask driver what to do with device. */
1669 if (io_subchannel_notify(sch, event))
1670 action = DISC;
1671 else
1672 action = UNREGISTER;
1673 break; 1520 break;
1674 case CIO_REVALIDATE: 1521 case IO_SCH_UNREG_ATTACH:
1675 /* Device will be removed, so no notify necessary. */ 1522 /* Unregister ccw device. */
1676 if (disc) 1523 ccw_device_unregister(cdev);
1677 /* Reprobe because immediate unregister might block. */
1678 action = REPROBE;
1679 else
1680 action = UNREGISTER_PROBE;
1681 break; 1524 break;
1682 case CIO_OPER: 1525 default:
1683 if (disc)
1684 /* Get device operational again. */
1685 action = REPROBE;
1686 break; 1526 break;
1687 } 1527 }
1688 /* Perform action. */ 1528 /* Handle subchannel. */
1689 ret = 0;
1690 switch (action) { 1529 switch (action) {
1691 case UNREGISTER: 1530 case IO_SCH_ORPH_UNREG:
1692 case UNREGISTER_PROBE: 1531 case IO_SCH_UNREG:
1693 ccw_device_set_notoper(cdev);
1694 /* Unregister device (will use subchannel lock). */
1695 spin_unlock_irqrestore(sch->lock, flags);
1696 css_sch_device_unregister(sch); 1532 css_sch_device_unregister(sch);
1697 spin_lock_irqsave(sch->lock, flags);
1698 break; 1533 break;
1699 case REPROBE: 1534 case IO_SCH_ORPH_ATTACH:
1535 case IO_SCH_UNREG_ATTACH:
1536 case IO_SCH_ATTACH:
1537 dev_id.ssid = sch->schid.ssid;
1538 dev_id.devno = sch->schib.pmcw.dev;
1539 cdev = get_ccwdev_by_dev_id(&dev_id);
1540 if (!cdev) {
1541 sch_create_and_recog_new_device(sch);
1542 break;
1543 }
1544 rc = ccw_device_move_to_sch(cdev, sch);
1545 if (rc) {
1546 /* Release reference from get_ccwdev_by_dev_id() */
1547 put_device(&cdev->dev);
1548 goto out;
1549 }
1550 spin_lock_irqsave(sch->lock, flags);
1700 ccw_device_trigger_reprobe(cdev); 1551 ccw_device_trigger_reprobe(cdev);
1701 break; 1552 spin_unlock_irqrestore(sch->lock, flags);
1702 case DISC: 1553 /* Release reference from get_ccwdev_by_dev_id() */
1703 ccw_device_set_disconnected(cdev); 1554 put_device(&cdev->dev);
1704 break; 1555 break;
1705 default: 1556 default:
1706 break; 1557 break;
1707 } 1558 }
1708 spin_unlock_irqrestore(sch->lock, flags); 1559 return 0;
1709 /* Probe if necessary. */
1710 if (action == UNREGISTER_PROBE)
1711 ret = css_probe_device(sch->schid);
1712 1560
1713 return ret; 1561out_unlock:
1562 spin_unlock_irqrestore(sch->lock, flags);
1563out:
1564 return rc;
1714} 1565}
1715 1566
1716#ifdef CONFIG_CCW_CONSOLE 1567#ifdef CONFIG_CCW_CONSOLE