aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/cio/blacklist.c35
-rw-r--r--drivers/s390/cio/css.c63
-rw-r--r--drivers/s390/cio/device.c4
-rw-r--r--drivers/s390/cio/device.h6
-rw-r--r--include/asm-s390/cio.h2
5 files changed, 74 insertions, 36 deletions
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index 0960bef7b199..15b895496a45 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -224,39 +224,6 @@ is_blacklisted (int ssid, int devno)
224} 224}
225 225
226#ifdef CONFIG_PROC_FS 226#ifdef CONFIG_PROC_FS
227static int
228__s390_redo_validation(struct subchannel_id schid, void *data)
229{
230 int ret;
231 struct subchannel *sch;
232
233 sch = get_subchannel_by_schid(schid);
234 if (sch) {
235 /* Already known. */
236 put_device(&sch->dev);
237 return 0;
238 }
239 ret = css_probe_device(schid);
240 if (ret == -ENXIO)
241 return ret; /* We're through. */
242 if (ret == -ENOMEM)
243 /* Stop validation for now. Bad, but no need for a panic. */
244 return ret;
245 return 0;
246}
247
248/*
249 * Function: s390_redo_validation
250 * Look for no longer blacklisted devices
251 * FIXME: there must be a better way to do this */
252static inline void
253s390_redo_validation (void)
254{
255 CIO_TRACE_EVENT (0, "redoval");
256
257 for_each_subchannel(__s390_redo_validation, NULL);
258}
259
260/* 227/*
261 * Function: blacklist_parse_proc_parameters 228 * Function: blacklist_parse_proc_parameters
262 * parse the stuff which is piped to /proc/cio_ignore 229 * parse the stuff which is piped to /proc/cio_ignore
@@ -281,7 +248,7 @@ blacklist_parse_proc_parameters (char *buf)
281 return; 248 return;
282 } 249 }
283 250
284 s390_redo_validation (); 251 css_schedule_reprobe();
285} 252}
286 253
287/* Iterator struct for all devices. */ 254/* Iterator struct for all devices. */
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 74ea8aac4b7d..1d3be80797f8 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -19,9 +19,11 @@
19#include "cio_debug.h" 19#include "cio_debug.h"
20#include "ioasm.h" 20#include "ioasm.h"
21#include "chsc.h" 21#include "chsc.h"
22#include "device.h"
22 23
23int need_rescan = 0; 24int need_rescan = 0;
24int css_init_done = 0; 25int css_init_done = 0;
26static int need_reprobe = 0;
25static int max_ssid = 0; 27static int max_ssid = 0;
26 28
27struct channel_subsystem *css[__MAX_CSSID + 1]; 29struct channel_subsystem *css[__MAX_CSSID + 1];
@@ -339,6 +341,67 @@ typedef void (*workfunc)(void *);
339DECLARE_WORK(slow_path_work, (workfunc)css_trigger_slow_path, NULL); 341DECLARE_WORK(slow_path_work, (workfunc)css_trigger_slow_path, NULL);
340struct workqueue_struct *slow_path_wq; 342struct workqueue_struct *slow_path_wq;
341 343
344/* Reprobe subchannel if unregistered. */
345static int reprobe_subchannel(struct subchannel_id schid, void *data)
346{
347 struct subchannel *sch;
348 int ret;
349
350 CIO_DEBUG(KERN_INFO, 6, "cio: reprobe 0.%x.%04x\n",
351 schid.ssid, schid.sch_no);
352 if (need_reprobe)
353 return -EAGAIN;
354
355 sch = get_subchannel_by_schid(schid);
356 if (sch) {
357 /* Already known. */
358 put_device(&sch->dev);
359 return 0;
360 }
361
362 ret = css_probe_device(schid);
363 switch (ret) {
364 case 0:
365 break;
366 case -ENXIO:
367 case -ENOMEM:
368 /* These should abort looping */
369 break;
370 default:
371 ret = 0;
372 }
373
374 return ret;
375}
376
377/* Work function used to reprobe all unregistered subchannels. */
378static void reprobe_all(void *data)
379{
380 int ret;
381
382 CIO_MSG_EVENT(2, "reprobe start\n");
383
384 need_reprobe = 0;
385 /* Make sure initial subchannel scan is done. */
386 wait_event(ccw_device_init_wq,
387 atomic_read(&ccw_device_init_count) == 0);
388 ret = for_each_subchannel(reprobe_subchannel, NULL);
389
390 CIO_MSG_EVENT(2, "reprobe done (rc=%d, need_reprobe=%d)\n", ret,
391 need_reprobe);
392}
393
394DECLARE_WORK(css_reprobe_work, reprobe_all, NULL);
395
396/* Schedule reprobing of all unregistered subchannels. */
397void css_schedule_reprobe(void)
398{
399 need_reprobe = 1;
400 queue_work(ccw_device_work, &css_reprobe_work);
401}
402
403EXPORT_SYMBOL_GPL(css_schedule_reprobe);
404
342/* 405/*
343 * Rescan for new devices. FIXME: This is slow. 406 * Rescan for new devices. FIXME: This is slow.
344 * This function is called when we have lost CRWs due to overflows and we have 407 * This function is called when we have lost CRWs due to overflows and we have
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 8e3053c2a451..eafde43e8410 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -133,8 +133,8 @@ struct css_driver io_subchannel_driver = {
133 133
134struct workqueue_struct *ccw_device_work; 134struct workqueue_struct *ccw_device_work;
135struct workqueue_struct *ccw_device_notify_work; 135struct workqueue_struct *ccw_device_notify_work;
136static wait_queue_head_t ccw_device_init_wq; 136wait_queue_head_t ccw_device_init_wq;
137static atomic_t ccw_device_init_count; 137atomic_t ccw_device_init_count;
138 138
139static int __init 139static int __init
140init_ccw_bus_type (void) 140init_ccw_bus_type (void)
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 11587ebb7289..8e0d1db3dd4e 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -1,6 +1,10 @@
1#ifndef S390_DEVICE_H 1#ifndef S390_DEVICE_H
2#define S390_DEVICE_H 2#define S390_DEVICE_H
3 3
4#include <asm/ccwdev.h>
5#include <asm/atomic.h>
6#include <linux/wait.h>
7
4/* 8/*
5 * states of the device statemachine 9 * states of the device statemachine
6 */ 10 */
@@ -67,6 +71,8 @@ dev_fsm_final_state(struct ccw_device *cdev)
67 71
68extern struct workqueue_struct *ccw_device_work; 72extern struct workqueue_struct *ccw_device_work;
69extern struct workqueue_struct *ccw_device_notify_work; 73extern struct workqueue_struct *ccw_device_notify_work;
74extern wait_queue_head_t ccw_device_init_wq;
75extern atomic_t ccw_device_init_count;
70 76
71void io_subchannel_recog_done(struct ccw_device *cdev); 77void io_subchannel_recog_done(struct ccw_device *cdev);
72 78
diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h
index 089cf567c317..2b1619306351 100644
--- a/include/asm-s390/cio.h
+++ b/include/asm-s390/cio.h
@@ -276,6 +276,8 @@ extern void wait_cons_dev(void);
276 276
277extern void clear_all_subchannels(void); 277extern void clear_all_subchannels(void);
278 278
279extern void css_schedule_reprobe(void);
280
279#endif 281#endif
280 282
281#endif 283#endif