diff options
| -rw-r--r-- | drivers/s390/cio/blacklist.c | 35 | ||||
| -rw-r--r-- | drivers/s390/cio/css.c | 63 | ||||
| -rw-r--r-- | drivers/s390/cio/device.c | 4 | ||||
| -rw-r--r-- | drivers/s390/cio/device.h | 6 | ||||
| -rw-r--r-- | include/asm-s390/cio.h | 2 |
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 |
| 227 | static 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 */ | ||
| 252 | static inline void | ||
| 253 | s390_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 | ||
| 23 | int need_rescan = 0; | 24 | int need_rescan = 0; |
| 24 | int css_init_done = 0; | 25 | int css_init_done = 0; |
| 26 | static int need_reprobe = 0; | ||
| 25 | static int max_ssid = 0; | 27 | static int max_ssid = 0; |
| 26 | 28 | ||
| 27 | struct channel_subsystem *css[__MAX_CSSID + 1]; | 29 | struct channel_subsystem *css[__MAX_CSSID + 1]; |
| @@ -339,6 +341,67 @@ typedef void (*workfunc)(void *); | |||
| 339 | DECLARE_WORK(slow_path_work, (workfunc)css_trigger_slow_path, NULL); | 341 | DECLARE_WORK(slow_path_work, (workfunc)css_trigger_slow_path, NULL); |
| 340 | struct workqueue_struct *slow_path_wq; | 342 | struct workqueue_struct *slow_path_wq; |
| 341 | 343 | ||
| 344 | /* Reprobe subchannel if unregistered. */ | ||
| 345 | static 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. */ | ||
| 378 | static 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 | |||
| 394 | DECLARE_WORK(css_reprobe_work, reprobe_all, NULL); | ||
| 395 | |||
| 396 | /* Schedule reprobing of all unregistered subchannels. */ | ||
| 397 | void css_schedule_reprobe(void) | ||
| 398 | { | ||
| 399 | need_reprobe = 1; | ||
| 400 | queue_work(ccw_device_work, &css_reprobe_work); | ||
| 401 | } | ||
| 402 | |||
| 403 | EXPORT_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 | ||
| 134 | struct workqueue_struct *ccw_device_work; | 134 | struct workqueue_struct *ccw_device_work; |
| 135 | struct workqueue_struct *ccw_device_notify_work; | 135 | struct workqueue_struct *ccw_device_notify_work; |
| 136 | static wait_queue_head_t ccw_device_init_wq; | 136 | wait_queue_head_t ccw_device_init_wq; |
| 137 | static atomic_t ccw_device_init_count; | 137 | atomic_t ccw_device_init_count; |
| 138 | 138 | ||
| 139 | static int __init | 139 | static int __init |
| 140 | init_ccw_bus_type (void) | 140 | init_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 | ||
| 68 | extern struct workqueue_struct *ccw_device_work; | 72 | extern struct workqueue_struct *ccw_device_work; |
| 69 | extern struct workqueue_struct *ccw_device_notify_work; | 73 | extern struct workqueue_struct *ccw_device_notify_work; |
| 74 | extern wait_queue_head_t ccw_device_init_wq; | ||
| 75 | extern atomic_t ccw_device_init_count; | ||
| 70 | 76 | ||
| 71 | void io_subchannel_recog_done(struct ccw_device *cdev); | 77 | void 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 | ||
| 277 | extern void clear_all_subchannels(void); | 277 | extern void clear_all_subchannels(void); |
| 278 | 278 | ||
| 279 | extern void css_schedule_reprobe(void); | ||
| 280 | |||
| 279 | #endif | 281 | #endif |
| 280 | 282 | ||
| 281 | #endif | 283 | #endif |
