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.c118
1 files changed, 82 insertions, 36 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 28221030b886..4e78c82194b4 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -31,6 +31,7 @@
31#include "device.h" 31#include "device.h"
32#include "ioasm.h" 32#include "ioasm.h"
33#include "io_sch.h" 33#include "io_sch.h"
34#include "blacklist.h"
34 35
35static struct timer_list recovery_timer; 36static struct timer_list recovery_timer;
36static DEFINE_SPINLOCK(recovery_lock); 37static DEFINE_SPINLOCK(recovery_lock);
@@ -296,36 +297,33 @@ static void ccw_device_unregister(struct ccw_device *cdev)
296 device_del(&cdev->dev); 297 device_del(&cdev->dev);
297} 298}
298 299
299static void ccw_device_remove_orphan_cb(struct device *dev) 300static void ccw_device_remove_orphan_cb(struct work_struct *work)
300{ 301{
301 struct ccw_device *cdev = to_ccwdev(dev); 302 struct ccw_device_private *priv;
303 struct ccw_device *cdev;
302 304
305 priv = container_of(work, struct ccw_device_private, kick_work);
306 cdev = priv->cdev;
303 ccw_device_unregister(cdev); 307 ccw_device_unregister(cdev);
304 put_device(&cdev->dev); 308 put_device(&cdev->dev);
309 /* Release cdev reference for workqueue processing. */
310 put_device(&cdev->dev);
305} 311}
306 312
307static void ccw_device_remove_sch_cb(struct device *dev) 313static void ccw_device_call_sch_unregister(struct work_struct *work);
308{
309 struct subchannel *sch;
310
311 sch = to_subchannel(dev);
312 css_sch_device_unregister(sch);
313 /* Reset intparm to zeroes. */
314 sch->schib.pmcw.intparm = 0;
315 cio_modify(sch);
316 put_device(&sch->dev);
317}
318 314
319static void 315static void
320ccw_device_remove_disconnected(struct ccw_device *cdev) 316ccw_device_remove_disconnected(struct ccw_device *cdev)
321{ 317{
322 unsigned long flags; 318 unsigned long flags;
323 int rc;
324 319
325 /* 320 /*
326 * Forced offline in disconnected state means 321 * Forced offline in disconnected state means
327 * 'throw away device'. 322 * 'throw away device'.
328 */ 323 */
324 /* Get cdev reference for workqueue processing. */
325 if (!get_device(&cdev->dev))
326 return;
329 if (ccw_device_is_orphan(cdev)) { 327 if (ccw_device_is_orphan(cdev)) {
330 /* 328 /*
331 * Deregister ccw device. 329 * Deregister ccw device.
@@ -335,23 +333,13 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
335 spin_lock_irqsave(cdev->ccwlock, flags); 333 spin_lock_irqsave(cdev->ccwlock, flags);
336 cdev->private->state = DEV_STATE_NOT_OPER; 334 cdev->private->state = DEV_STATE_NOT_OPER;
337 spin_unlock_irqrestore(cdev->ccwlock, flags); 335 spin_unlock_irqrestore(cdev->ccwlock, flags);
338 rc = device_schedule_callback(&cdev->dev, 336 PREPARE_WORK(&cdev->private->kick_work,
339 ccw_device_remove_orphan_cb); 337 ccw_device_remove_orphan_cb);
340 if (rc) 338 } else
341 CIO_MSG_EVENT(0, "Couldn't unregister orphan " 339 /* Deregister subchannel, which will kill the ccw device. */
342 "0.%x.%04x\n", 340 PREPARE_WORK(&cdev->private->kick_work,
343 cdev->private->dev_id.ssid, 341 ccw_device_call_sch_unregister);
344 cdev->private->dev_id.devno); 342 queue_work(slow_path_wq, &cdev->private->kick_work);
345 return;
346 }
347 /* Deregister subchannel, which will kill the ccw device. */
348 rc = device_schedule_callback(cdev->dev.parent,
349 ccw_device_remove_sch_cb);
350 if (rc)
351 CIO_MSG_EVENT(0, "Couldn't unregister disconnected device "
352 "0.%x.%04x\n",
353 cdev->private->dev_id.ssid,
354 cdev->private->dev_id.devno);
355} 343}
356 344
357/** 345/**
@@ -970,12 +958,17 @@ static void ccw_device_call_sch_unregister(struct work_struct *work)
970 958
971 priv = container_of(work, struct ccw_device_private, kick_work); 959 priv = container_of(work, struct ccw_device_private, kick_work);
972 cdev = priv->cdev; 960 cdev = priv->cdev;
961 /* Get subchannel reference for local processing. */
962 if (!get_device(cdev->dev.parent))
963 return;
973 sch = to_subchannel(cdev->dev.parent); 964 sch = to_subchannel(cdev->dev.parent);
974 css_sch_device_unregister(sch); 965 css_sch_device_unregister(sch);
975 /* Reset intparm to zeroes. */ 966 /* Reset intparm to zeroes. */
976 sch->schib.pmcw.intparm = 0; 967 sch->schib.pmcw.intparm = 0;
977 cio_modify(sch); 968 cio_modify(sch);
969 /* Release cdev reference for workqueue processing.*/
978 put_device(&cdev->dev); 970 put_device(&cdev->dev);
971 /* Release subchannel reference for local processing. */
979 put_device(&sch->dev); 972 put_device(&sch->dev);
980} 973}
981 974
@@ -1001,6 +994,8 @@ io_subchannel_recog_done(struct ccw_device *cdev)
1001 PREPARE_WORK(&cdev->private->kick_work, 994 PREPARE_WORK(&cdev->private->kick_work,
1002 ccw_device_call_sch_unregister); 995 ccw_device_call_sch_unregister);
1003 queue_work(slow_path_wq, &cdev->private->kick_work); 996 queue_work(slow_path_wq, &cdev->private->kick_work);
997 /* Release subchannel reference for asynchronous recognition. */
998 put_device(&sch->dev);
1004 if (atomic_dec_and_test(&ccw_device_init_count)) 999 if (atomic_dec_and_test(&ccw_device_init_count))
1005 wake_up(&ccw_device_init_wq); 1000 wake_up(&ccw_device_init_wq);
1006 break; 1001 break;
@@ -1040,8 +1035,11 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
1040 init_timer(&priv->timer); 1035 init_timer(&priv->timer);
1041 1036
1042 /* Set an initial name for the device. */ 1037 /* Set an initial name for the device. */
1043 snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", 1038 if (cio_is_console(sch->schid))
1044 sch->schid.ssid, sch->schib.pmcw.dev); 1039 cdev->dev.init_name = cio_get_console_cdev_name(sch);
1040 else
1041 dev_set_name(&cdev->dev, "0.%x.%04x",
1042 sch->schid.ssid, sch->schib.pmcw.dev);
1045 1043
1046 /* Increase counter of devices currently in recognition. */ 1044 /* Increase counter of devices currently in recognition. */
1047 atomic_inc(&ccw_device_init_count); 1045 atomic_inc(&ccw_device_init_count);
@@ -1106,7 +1104,7 @@ static void io_subchannel_irq(struct subchannel *sch)
1106 cdev = sch_get_cdev(sch); 1104 cdev = sch_get_cdev(sch);
1107 1105
1108 CIO_TRACE_EVENT(3, "IRQ"); 1106 CIO_TRACE_EVENT(3, "IRQ");
1109 CIO_TRACE_EVENT(3, sch->dev.bus_id); 1107 CIO_TRACE_EVENT(3, dev_name(&sch->dev));
1110 if (cdev) 1108 if (cdev)
1111 dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); 1109 dev_fsm_event(cdev, DEV_EVENT_INTERRUPT);
1112} 1110}
@@ -1476,6 +1474,45 @@ static void ccw_device_schedule_recovery(void)
1476 spin_unlock_irqrestore(&recovery_lock, flags); 1474 spin_unlock_irqrestore(&recovery_lock, flags);
1477} 1475}
1478 1476
1477static int purge_fn(struct device *dev, void *data)
1478{
1479 struct ccw_device *cdev = to_ccwdev(dev);
1480 struct ccw_device_private *priv = cdev->private;
1481 int unreg;
1482
1483 spin_lock_irq(cdev->ccwlock);
1484 unreg = is_blacklisted(priv->dev_id.ssid, priv->dev_id.devno) &&
1485 (priv->state == DEV_STATE_OFFLINE);
1486 spin_unlock_irq(cdev->ccwlock);
1487 if (!unreg)
1488 goto out;
1489 if (!get_device(&cdev->dev))
1490 goto out;
1491 CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", priv->dev_id.ssid,
1492 priv->dev_id.devno);
1493 PREPARE_WORK(&cdev->private->kick_work, ccw_device_call_sch_unregister);
1494 queue_work(slow_path_wq, &cdev->private->kick_work);
1495
1496out:
1497 /* Abort loop in case of pending signal. */
1498 if (signal_pending(current))
1499 return -EINTR;
1500
1501 return 0;
1502}
1503
1504/**
1505 * ccw_purge_blacklisted - purge unused, blacklisted devices
1506 *
1507 * Unregister all ccw devices that are offline and on the blacklist.
1508 */
1509int ccw_purge_blacklisted(void)
1510{
1511 CIO_MSG_EVENT(2, "ccw: purging blacklisted devices\n");
1512 bus_for_each_dev(&ccw_bus_type, NULL, NULL, purge_fn);
1513 return 0;
1514}
1515
1479static void device_set_disconnected(struct ccw_device *cdev) 1516static void device_set_disconnected(struct ccw_device *cdev)
1480{ 1517{
1481 if (!cdev) 1518 if (!cdev)
@@ -1492,7 +1529,7 @@ void ccw_device_set_notoper(struct ccw_device *cdev)
1492 struct subchannel *sch = to_subchannel(cdev->dev.parent); 1529 struct subchannel *sch = to_subchannel(cdev->dev.parent);
1493 1530
1494 CIO_TRACE_EVENT(2, "notoper"); 1531 CIO_TRACE_EVENT(2, "notoper");
1495 CIO_TRACE_EVENT(2, sch->dev.bus_id); 1532 CIO_TRACE_EVENT(2, dev_name(&sch->dev));
1496 ccw_device_set_timeout(cdev, 0); 1533 ccw_device_set_timeout(cdev, 0);
1497 cio_disable_subchannel(sch); 1534 cio_disable_subchannel(sch);
1498 cdev->private->state = DEV_STATE_NOT_OPER; 1535 cdev->private->state = DEV_STATE_NOT_OPER;
@@ -1591,6 +1628,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow)
1591 1628
1592#ifdef CONFIG_CCW_CONSOLE 1629#ifdef CONFIG_CCW_CONSOLE
1593static struct ccw_device console_cdev; 1630static struct ccw_device console_cdev;
1631static char console_cdev_name[10] = "0.x.xxxx";
1594static struct ccw_device_private console_private; 1632static struct ccw_device_private console_private;
1595static int console_cdev_in_use; 1633static int console_cdev_in_use;
1596 1634
@@ -1661,6 +1699,14 @@ ccw_device_probe_console(void)
1661 console_cdev.online = 1; 1699 console_cdev.online = 1;
1662 return &console_cdev; 1700 return &console_cdev;
1663} 1701}
1702
1703
1704const char *cio_get_console_cdev_name(struct subchannel *sch)
1705{
1706 snprintf(console_cdev_name, 10, "0.%x.%04x",
1707 sch->schid.ssid, sch->schib.pmcw.dev);
1708 return (const char *)console_cdev_name;
1709}
1664#endif 1710#endif
1665 1711
1666/* 1712/*
@@ -1673,7 +1719,7 @@ __ccwdev_check_busid(struct device *dev, void *id)
1673 1719
1674 bus_id = id; 1720 bus_id = id;
1675 1721
1676 return (strncmp(bus_id, dev->bus_id, BUS_ID_SIZE) == 0); 1722 return (strncmp(bus_id, dev_name(dev), BUS_ID_SIZE) == 0);
1677} 1723}
1678 1724
1679 1725