aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Oberparleiter <peter.oberparleiter@de.ibm.com>2008-10-10 15:33:06 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-10-10 15:33:47 -0400
commitecf5d9ef68b868b293b40b89615a92de7310d065 (patch)
treeec92f05f79e222075e2425129e15b0ee9131364e
parent46fbe4e46ddb88805245a24f684400b50ead68a7 (diff)
[S390] cio: introduce purge function for /proc/cio_ignore
Allow users to remove blacklisted ccw devices by using the /proc/cio_ignore interface: echo purge > /proc/cio_ignore will remove all devices which are offline and blacklisted. Signed-off-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--drivers/s390/cio/blacklist.c11
-rw-r--r--drivers/s390/cio/device.c40
-rw-r--r--drivers/s390/cio/device.h1
3 files changed, 48 insertions, 4 deletions
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index 0bfcbbe375c4..2f547b840ef0 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -24,6 +24,7 @@
24#include "cio.h" 24#include "cio.h"
25#include "cio_debug.h" 25#include "cio_debug.h"
26#include "css.h" 26#include "css.h"
27#include "device.h"
27 28
28/* 29/*
29 * "Blacklisting" of certain devices: 30 * "Blacklisting" of certain devices:
@@ -191,9 +192,9 @@ static int blacklist_parse_parameters(char *str, range_action action,
191 rc = blacklist_range(ra, from_ssid, to_ssid, from, to, 192 rc = blacklist_range(ra, from_ssid, to_ssid, from, to,
192 msgtrigger); 193 msgtrigger);
193 if (rc) 194 if (rc)
194 totalrc = 1; 195 totalrc = -EINVAL;
195 } else 196 } else
196 totalrc = 1; 197 totalrc = -EINVAL;
197 } 198 }
198 199
199 return totalrc; 200 return totalrc;
@@ -240,8 +241,10 @@ static int blacklist_parse_proc_parameters(char *buf)
240 rc = blacklist_parse_parameters(buf, free, 0); 241 rc = blacklist_parse_parameters(buf, free, 0);
241 else if (strcmp("add", parm) == 0) 242 else if (strcmp("add", parm) == 0)
242 rc = blacklist_parse_parameters(buf, add, 0); 243 rc = blacklist_parse_parameters(buf, add, 0);
244 else if (strcmp("purge", parm) == 0)
245 return ccw_purge_blacklisted();
243 else 246 else
244 return 1; 247 return -EINVAL;
245 248
246 css_schedule_reprobe(); 249 css_schedule_reprobe();
247 250
@@ -353,7 +356,7 @@ cio_ignore_write(struct file *file, const char __user *user_buf,
353 } 356 }
354 ret = blacklist_parse_proc_parameters(buf); 357 ret = blacklist_parse_proc_parameters(buf);
355 if (ret) 358 if (ret)
356 rc = -EINVAL; 359 rc = ret;
357 else 360 else
358 rc = user_len; 361 rc = user_len;
359 362
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 38a79ecfc743..8575d263b13e 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);
@@ -1470,6 +1471,45 @@ static void ccw_device_schedule_recovery(void)
1470 spin_unlock_irqrestore(&recovery_lock, flags); 1471 spin_unlock_irqrestore(&recovery_lock, flags);
1471} 1472}
1472 1473
1474static int purge_fn(struct device *dev, void *data)
1475{
1476 struct ccw_device *cdev = to_ccwdev(dev);
1477 struct ccw_device_private *priv = cdev->private;
1478 int unreg;
1479
1480 spin_lock_irq(cdev->ccwlock);
1481 unreg = is_blacklisted(priv->dev_id.ssid, priv->dev_id.devno) &&
1482 (priv->state == DEV_STATE_OFFLINE);
1483 spin_unlock_irq(cdev->ccwlock);
1484 if (!unreg)
1485 goto out;
1486 if (!get_device(&cdev->dev))
1487 goto out;
1488 CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", priv->dev_id.ssid,
1489 priv->dev_id.devno);
1490 PREPARE_WORK(&cdev->private->kick_work, ccw_device_call_sch_unregister);
1491 queue_work(slow_path_wq, &cdev->private->kick_work);
1492
1493out:
1494 /* Abort loop in case of pending signal. */
1495 if (signal_pending(current))
1496 return -EINTR;
1497
1498 return 0;
1499}
1500
1501/**
1502 * ccw_purge_blacklisted - purge unused, blacklisted devices
1503 *
1504 * Unregister all ccw devices that are offline and on the blacklist.
1505 */
1506int ccw_purge_blacklisted(void)
1507{
1508 CIO_MSG_EVENT(2, "ccw: purging blacklisted devices\n");
1509 bus_for_each_dev(&ccw_bus_type, NULL, NULL, purge_fn);
1510 return 0;
1511}
1512
1473static void device_set_disconnected(struct ccw_device *cdev) 1513static void device_set_disconnected(struct ccw_device *cdev)
1474{ 1514{
1475 if (!cdev) 1515 if (!cdev)
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 6f5c3f2b3587..104ed669db43 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -86,6 +86,7 @@ int ccw_device_is_orphan(struct ccw_device *);
86int ccw_device_recognition(struct ccw_device *); 86int ccw_device_recognition(struct ccw_device *);
87int ccw_device_online(struct ccw_device *); 87int ccw_device_online(struct ccw_device *);
88int ccw_device_offline(struct ccw_device *); 88int ccw_device_offline(struct ccw_device *);
89int ccw_purge_blacklisted(void);
89 90
90/* Function prototypes for device status and basic sense stuff. */ 91/* Function prototypes for device status and basic sense stuff. */
91void ccw_device_accumulate_irb(struct ccw_device *, struct irb *); 92void ccw_device_accumulate_irb(struct ccw_device *, struct irb *);