aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/device.c')
-rw-r--r--drivers/s390/cio/device.c88
1 files changed, 64 insertions, 24 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 51bd3687d163..8e04c00cf0ad 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -127,7 +127,7 @@ static int ccw_uevent(struct device *dev, struct kobj_uevent_env *env)
127 return ret; 127 return ret;
128} 128}
129 129
130struct bus_type ccw_bus_type; 130static struct bus_type ccw_bus_type;
131 131
132static void io_subchannel_irq(struct subchannel *); 132static void io_subchannel_irq(struct subchannel *);
133static int io_subchannel_probe(struct subchannel *); 133static int io_subchannel_probe(struct subchannel *);
@@ -172,9 +172,11 @@ static int io_subchannel_settle(void)
172} 172}
173 173
174static struct css_driver io_subchannel_driver = { 174static struct css_driver io_subchannel_driver = {
175 .owner = THIS_MODULE, 175 .drv = {
176 .owner = THIS_MODULE,
177 .name = "io_subchannel",
178 },
176 .subchannel_type = io_subchannel_ids, 179 .subchannel_type = io_subchannel_ids,
177 .name = "io_subchannel",
178 .irq = io_subchannel_irq, 180 .irq = io_subchannel_irq,
179 .sch_event = io_subchannel_sch_event, 181 .sch_event = io_subchannel_sch_event,
180 .chp_event = io_subchannel_chp_event, 182 .chp_event = io_subchannel_chp_event,
@@ -539,15 +541,24 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
539 int force, ret; 541 int force, ret;
540 unsigned long i; 542 unsigned long i;
541 543
542 if (!dev_fsm_final_state(cdev) && 544 /* Prevent conflict between multiple on-/offline processing requests. */
543 cdev->private->state != DEV_STATE_DISCONNECTED)
544 return -EAGAIN;
545 if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0) 545 if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0)
546 return -EAGAIN; 546 return -EAGAIN;
547 /* Prevent conflict between internal I/Os and on-/offline processing. */
548 if (!dev_fsm_final_state(cdev) &&
549 cdev->private->state != DEV_STATE_DISCONNECTED) {
550 ret = -EAGAIN;
551 goto out_onoff;
552 }
553 /* Prevent conflict between pending work and on-/offline processing.*/
554 if (work_pending(&cdev->private->todo_work)) {
555 ret = -EAGAIN;
556 goto out_onoff;
557 }
547 558
548 if (cdev->drv && !try_module_get(cdev->drv->owner)) { 559 if (cdev->drv && !try_module_get(cdev->drv->driver.owner)) {
549 atomic_set(&cdev->private->onoff, 0); 560 ret = -EINVAL;
550 return -EINVAL; 561 goto out_onoff;
551 } 562 }
552 if (!strncmp(buf, "force\n", count)) { 563 if (!strncmp(buf, "force\n", count)) {
553 force = 1; 564 force = 1;
@@ -571,7 +582,8 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
571 } 582 }
572out: 583out:
573 if (cdev->drv) 584 if (cdev->drv)
574 module_put(cdev->drv->owner); 585 module_put(cdev->drv->driver.owner);
586out_onoff:
575 atomic_set(&cdev->private->onoff, 0); 587 atomic_set(&cdev->private->onoff, 0);
576 return (ret < 0) ? ret : count; 588 return (ret < 0) ? ret : count;
577} 589}
@@ -1030,6 +1042,7 @@ static void io_subchannel_init_fields(struct subchannel *sch)
1030 */ 1042 */
1031static int io_subchannel_probe(struct subchannel *sch) 1043static int io_subchannel_probe(struct subchannel *sch)
1032{ 1044{
1045 struct io_subchannel_private *io_priv;
1033 struct ccw_device *cdev; 1046 struct ccw_device *cdev;
1034 int rc; 1047 int rc;
1035 1048
@@ -1073,10 +1086,11 @@ static int io_subchannel_probe(struct subchannel *sch)
1073 if (rc) 1086 if (rc)
1074 goto out_schedule; 1087 goto out_schedule;
1075 /* Allocate I/O subchannel private data. */ 1088 /* Allocate I/O subchannel private data. */
1076 sch->private = kzalloc(sizeof(struct io_subchannel_private), 1089 io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA);
1077 GFP_KERNEL | GFP_DMA); 1090 if (!io_priv)
1078 if (!sch->private)
1079 goto out_schedule; 1091 goto out_schedule;
1092
1093 set_io_private(sch, io_priv);
1080 css_schedule_eval(sch->schid); 1094 css_schedule_eval(sch->schid);
1081 return 0; 1095 return 0;
1082 1096
@@ -1090,6 +1104,7 @@ out_schedule:
1090static int 1104static int
1091io_subchannel_remove (struct subchannel *sch) 1105io_subchannel_remove (struct subchannel *sch)
1092{ 1106{
1107 struct io_subchannel_private *io_priv = to_io_private(sch);
1093 struct ccw_device *cdev; 1108 struct ccw_device *cdev;
1094 1109
1095 cdev = sch_get_cdev(sch); 1110 cdev = sch_get_cdev(sch);
@@ -1099,11 +1114,12 @@ io_subchannel_remove (struct subchannel *sch)
1099 /* Set ccw device to not operational and drop reference. */ 1114 /* Set ccw device to not operational and drop reference. */
1100 spin_lock_irq(cdev->ccwlock); 1115 spin_lock_irq(cdev->ccwlock);
1101 sch_set_cdev(sch, NULL); 1116 sch_set_cdev(sch, NULL);
1117 set_io_private(sch, NULL);
1102 cdev->private->state = DEV_STATE_NOT_OPER; 1118 cdev->private->state = DEV_STATE_NOT_OPER;
1103 spin_unlock_irq(cdev->ccwlock); 1119 spin_unlock_irq(cdev->ccwlock);
1104 ccw_device_unregister(cdev); 1120 ccw_device_unregister(cdev);
1105out_free: 1121out_free:
1106 kfree(sch->private); 1122 kfree(io_priv);
1107 sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group); 1123 sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
1108 return 0; 1124 return 0;
1109} 1125}
@@ -1147,6 +1163,7 @@ err:
1147static int io_subchannel_chp_event(struct subchannel *sch, 1163static int io_subchannel_chp_event(struct subchannel *sch,
1148 struct chp_link *link, int event) 1164 struct chp_link *link, int event)
1149{ 1165{
1166 struct ccw_device *cdev = sch_get_cdev(sch);
1150 int mask; 1167 int mask;
1151 1168
1152 mask = chp_ssd_get_mask(&sch->ssd_info, link); 1169 mask = chp_ssd_get_mask(&sch->ssd_info, link);
@@ -1156,22 +1173,30 @@ static int io_subchannel_chp_event(struct subchannel *sch,
1156 case CHP_VARY_OFF: 1173 case CHP_VARY_OFF:
1157 sch->opm &= ~mask; 1174 sch->opm &= ~mask;
1158 sch->lpm &= ~mask; 1175 sch->lpm &= ~mask;
1176 if (cdev)
1177 cdev->private->path_gone_mask |= mask;
1159 io_subchannel_terminate_path(sch, mask); 1178 io_subchannel_terminate_path(sch, mask);
1160 break; 1179 break;
1161 case CHP_VARY_ON: 1180 case CHP_VARY_ON:
1162 sch->opm |= mask; 1181 sch->opm |= mask;
1163 sch->lpm |= mask; 1182 sch->lpm |= mask;
1183 if (cdev)
1184 cdev->private->path_new_mask |= mask;
1164 io_subchannel_verify(sch); 1185 io_subchannel_verify(sch);
1165 break; 1186 break;
1166 case CHP_OFFLINE: 1187 case CHP_OFFLINE:
1167 if (cio_update_schib(sch)) 1188 if (cio_update_schib(sch))
1168 return -ENODEV; 1189 return -ENODEV;
1190 if (cdev)
1191 cdev->private->path_gone_mask |= mask;
1169 io_subchannel_terminate_path(sch, mask); 1192 io_subchannel_terminate_path(sch, mask);
1170 break; 1193 break;
1171 case CHP_ONLINE: 1194 case CHP_ONLINE:
1172 if (cio_update_schib(sch)) 1195 if (cio_update_schib(sch))
1173 return -ENODEV; 1196 return -ENODEV;
1174 sch->lpm |= mask & sch->opm; 1197 sch->lpm |= mask & sch->opm;
1198 if (cdev)
1199 cdev->private->path_new_mask |= mask;
1175 io_subchannel_verify(sch); 1200 io_subchannel_verify(sch);
1176 break; 1201 break;
1177 } 1202 }
@@ -1196,6 +1221,7 @@ static void io_subchannel_quiesce(struct subchannel *sch)
1196 cdev->handler(cdev, cdev->private->intparm, ERR_PTR(-EIO)); 1221 cdev->handler(cdev, cdev->private->intparm, ERR_PTR(-EIO));
1197 while (ret == -EBUSY) { 1222 while (ret == -EBUSY) {
1198 cdev->private->state = DEV_STATE_QUIESCE; 1223 cdev->private->state = DEV_STATE_QUIESCE;
1224 cdev->private->iretry = 255;
1199 ret = ccw_device_cancel_halt_clear(cdev); 1225 ret = ccw_device_cancel_halt_clear(cdev);
1200 if (ret == -EBUSY) { 1226 if (ret == -EBUSY) {
1201 ccw_device_set_timeout(cdev, HZ/10); 1227 ccw_device_set_timeout(cdev, HZ/10);
@@ -1295,10 +1321,12 @@ static int purge_fn(struct device *dev, void *data)
1295 1321
1296 spin_lock_irq(cdev->ccwlock); 1322 spin_lock_irq(cdev->ccwlock);
1297 if (is_blacklisted(id->ssid, id->devno) && 1323 if (is_blacklisted(id->ssid, id->devno) &&
1298 (cdev->private->state == DEV_STATE_OFFLINE)) { 1324 (cdev->private->state == DEV_STATE_OFFLINE) &&
1325 (atomic_cmpxchg(&cdev->private->onoff, 0, 1) == 0)) {
1299 CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", id->ssid, 1326 CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", id->ssid,
1300 id->devno); 1327 id->devno);
1301 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); 1328 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
1329 atomic_set(&cdev->private->onoff, 0);
1302 } 1330 }
1303 spin_unlock_irq(cdev->ccwlock); 1331 spin_unlock_irq(cdev->ccwlock);
1304 /* Abort loop in case of pending signal. */ 1332 /* Abort loop in case of pending signal. */
@@ -1445,7 +1473,16 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
1445 break; 1473 break;
1446 case IO_SCH_UNREG_ATTACH: 1474 case IO_SCH_UNREG_ATTACH:
1447 case IO_SCH_UNREG: 1475 case IO_SCH_UNREG:
1448 if (cdev) 1476 if (!cdev)
1477 break;
1478 if (cdev->private->state == DEV_STATE_SENSE_ID) {
1479 /*
1480 * Note: delayed work triggered by this event
1481 * and repeated calls to sch_event are synchronized
1482 * by the above check for work_pending(cdev).
1483 */
1484 dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
1485 } else
1449 ccw_device_set_notoper(cdev); 1486 ccw_device_set_notoper(cdev);
1450 break; 1487 break;
1451 case IO_SCH_NOP: 1488 case IO_SCH_NOP:
@@ -1468,9 +1505,13 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
1468 goto out; 1505 goto out;
1469 break; 1506 break;
1470 case IO_SCH_UNREG_ATTACH: 1507 case IO_SCH_UNREG_ATTACH:
1508 if (cdev->private->flags.resuming) {
1509 /* Device will be handled later. */
1510 rc = 0;
1511 goto out;
1512 }
1471 /* Unregister ccw device. */ 1513 /* Unregister ccw device. */
1472 if (!cdev->private->flags.resuming) 1514 ccw_device_unregister(cdev);
1473 ccw_device_unregister(cdev);
1474 break; 1515 break;
1475 default: 1516 default:
1476 break; 1517 break;
@@ -1530,11 +1571,12 @@ spinlock_t * cio_get_console_lock(void)
1530static int ccw_device_console_enable(struct ccw_device *cdev, 1571static int ccw_device_console_enable(struct ccw_device *cdev,
1531 struct subchannel *sch) 1572 struct subchannel *sch)
1532{ 1573{
1574 struct io_subchannel_private *io_priv = cio_get_console_priv();
1533 int rc; 1575 int rc;
1534 1576
1535 /* Attach subchannel private data. */ 1577 /* Attach subchannel private data. */
1536 sch->private = cio_get_console_priv(); 1578 memset(io_priv, 0, sizeof(*io_priv));
1537 memset(sch->private, 0, sizeof(struct io_subchannel_private)); 1579 set_io_private(sch, io_priv);
1538 io_subchannel_init_fields(sch); 1580 io_subchannel_init_fields(sch);
1539 rc = cio_commit_config(sch); 1581 rc = cio_commit_config(sch);
1540 if (rc) 1582 if (rc)
@@ -1812,6 +1854,7 @@ static void __ccw_device_pm_restore(struct ccw_device *cdev)
1812 * available again. Kick re-detection. 1854 * available again. Kick re-detection.
1813 */ 1855 */
1814 cdev->private->flags.resuming = 1; 1856 cdev->private->flags.resuming = 1;
1857 cdev->private->path_new_mask = LPM_ANYPATH;
1815 css_schedule_eval(sch->schid); 1858 css_schedule_eval(sch->schid);
1816 spin_unlock_irq(sch->lock); 1859 spin_unlock_irq(sch->lock);
1817 css_complete_work(); 1860 css_complete_work();
@@ -1939,7 +1982,7 @@ static const struct dev_pm_ops ccw_pm_ops = {
1939 .restore = ccw_device_pm_restore, 1982 .restore = ccw_device_pm_restore,
1940}; 1983};
1941 1984
1942struct bus_type ccw_bus_type = { 1985static struct bus_type ccw_bus_type = {
1943 .name = "ccw", 1986 .name = "ccw",
1944 .match = ccw_bus_match, 1987 .match = ccw_bus_match,
1945 .uevent = ccw_uevent, 1988 .uevent = ccw_uevent,
@@ -1962,8 +2005,6 @@ int ccw_driver_register(struct ccw_driver *cdriver)
1962 struct device_driver *drv = &cdriver->driver; 2005 struct device_driver *drv = &cdriver->driver;
1963 2006
1964 drv->bus = &ccw_bus_type; 2007 drv->bus = &ccw_bus_type;
1965 drv->name = cdriver->name;
1966 drv->owner = cdriver->owner;
1967 2008
1968 return driver_register(drv); 2009 return driver_register(drv);
1969} 2010}
@@ -2081,5 +2122,4 @@ EXPORT_SYMBOL(ccw_device_set_offline);
2081EXPORT_SYMBOL(ccw_driver_register); 2122EXPORT_SYMBOL(ccw_driver_register);
2082EXPORT_SYMBOL(ccw_driver_unregister); 2123EXPORT_SYMBOL(ccw_driver_unregister);
2083EXPORT_SYMBOL(get_ccwdev_by_busid); 2124EXPORT_SYMBOL(get_ccwdev_by_busid);
2084EXPORT_SYMBOL(ccw_bus_type);
2085EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id); 2125EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id);