aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/sysrq.c2
-rw-r--r--drivers/s390/block/dasd.c1
-rw-r--r--drivers/s390/cio/device.c43
-rw-r--r--drivers/s390/cio/device.h1
-rw-r--r--drivers/s390/cio/device_fsm.c31
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c5
6 files changed, 54 insertions, 29 deletions
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 5afe7316c72e..ebea9b2c30a5 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -35,7 +35,7 @@
35#include <linux/vt_kern.h> 35#include <linux/vt_kern.h>
36#include <linux/workqueue.h> 36#include <linux/workqueue.h>
37#include <linux/kexec.h> 37#include <linux/kexec.h>
38#include <linux/irq.h> 38#include <linux/interrupt.h>
39#include <linux/hrtimer.h> 39#include <linux/hrtimer.h>
40#include <linux/oom.h> 40#include <linux/oom.h>
41 41
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 2fd64e5a9ab2..0570794ccf1c 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -2363,6 +2363,7 @@ int dasd_generic_notify(struct ccw_device *cdev, int event)
2363 ret = 0; 2363 ret = 0;
2364 switch (event) { 2364 switch (event) {
2365 case CIO_GONE: 2365 case CIO_GONE:
2366 case CIO_BOXED:
2366 case CIO_NO_PATH: 2367 case CIO_NO_PATH:
2367 /* First of all call extended error reporting. */ 2368 /* First of all call extended error reporting. */
2368 dasd_eer_write(device, NULL, DASD_EER_NOPATH); 2369 dasd_eer_write(device, NULL, DASD_EER_NOPATH);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index c4d2f667a2f6..35441fa16be1 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -310,8 +310,6 @@ static void ccw_device_remove_orphan_cb(struct work_struct *work)
310 put_device(&cdev->dev); 310 put_device(&cdev->dev);
311} 311}
312 312
313static void ccw_device_call_sch_unregister(struct work_struct *work);
314
315static void 313static void
316ccw_device_remove_disconnected(struct ccw_device *cdev) 314ccw_device_remove_disconnected(struct ccw_device *cdev)
317{ 315{
@@ -335,11 +333,10 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
335 spin_unlock_irqrestore(cdev->ccwlock, flags); 333 spin_unlock_irqrestore(cdev->ccwlock, flags);
336 PREPARE_WORK(&cdev->private->kick_work, 334 PREPARE_WORK(&cdev->private->kick_work,
337 ccw_device_remove_orphan_cb); 335 ccw_device_remove_orphan_cb);
336 queue_work(slow_path_wq, &cdev->private->kick_work);
338 } else 337 } else
339 /* Deregister subchannel, which will kill the ccw device. */ 338 /* Deregister subchannel, which will kill the ccw device. */
340 PREPARE_WORK(&cdev->private->kick_work, 339 ccw_device_schedule_sch_unregister(cdev);
341 ccw_device_call_sch_unregister);
342 queue_work(slow_path_wq, &cdev->private->kick_work);
343} 340}
344 341
345/** 342/**
@@ -471,7 +468,7 @@ static int online_store_recog_and_online(struct ccw_device *cdev)
471 int ret; 468 int ret;
472 469
473 /* Do device recognition, if needed. */ 470 /* Do device recognition, if needed. */
474 if (cdev->id.cu_type == 0) { 471 if (cdev->private->state == DEV_STATE_BOXED) {
475 ret = ccw_device_recognition(cdev); 472 ret = ccw_device_recognition(cdev);
476 if (ret) { 473 if (ret) {
477 CIO_MSG_EVENT(0, "Couldn't start recognition " 474 CIO_MSG_EVENT(0, "Couldn't start recognition "
@@ -482,17 +479,21 @@ static int online_store_recog_and_online(struct ccw_device *cdev)
482 } 479 }
483 wait_event(cdev->private->wait_q, 480 wait_event(cdev->private->wait_q,
484 cdev->private->flags.recog_done); 481 cdev->private->flags.recog_done);
482 if (cdev->private->state != DEV_STATE_OFFLINE)
483 /* recognition failed */
484 return -EAGAIN;
485 } 485 }
486 if (cdev->drv && cdev->drv->set_online) 486 if (cdev->drv && cdev->drv->set_online)
487 ccw_device_set_online(cdev); 487 ccw_device_set_online(cdev);
488 return 0; 488 return 0;
489} 489}
490
490static int online_store_handle_online(struct ccw_device *cdev, int force) 491static int online_store_handle_online(struct ccw_device *cdev, int force)
491{ 492{
492 int ret; 493 int ret;
493 494
494 ret = online_store_recog_and_online(cdev); 495 ret = online_store_recog_and_online(cdev);
495 if (ret) 496 if (ret && !force)
496 return ret; 497 return ret;
497 if (force && cdev->private->state == DEV_STATE_BOXED) { 498 if (force && cdev->private->state == DEV_STATE_BOXED) {
498 ret = ccw_device_stlck(cdev); 499 ret = ccw_device_stlck(cdev);
@@ -500,7 +501,9 @@ static int online_store_handle_online(struct ccw_device *cdev, int force)
500 return ret; 501 return ret;
501 if (cdev->id.cu_type == 0) 502 if (cdev->id.cu_type == 0)
502 cdev->private->state = DEV_STATE_NOT_OPER; 503 cdev->private->state = DEV_STATE_NOT_OPER;
503 online_store_recog_and_online(cdev); 504 ret = online_store_recog_and_online(cdev);
505 if (ret)
506 return ret;
504 } 507 }
505 return 0; 508 return 0;
506} 509}
@@ -512,7 +515,11 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
512 int force, ret; 515 int force, ret;
513 unsigned long i; 516 unsigned long i;
514 517
515 if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0) 518 if ((cdev->private->state != DEV_STATE_OFFLINE &&
519 cdev->private->state != DEV_STATE_ONLINE &&
520 cdev->private->state != DEV_STATE_BOXED &&
521 cdev->private->state != DEV_STATE_DISCONNECTED) ||
522 atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0)
516 return -EAGAIN; 523 return -EAGAIN;
517 524
518 if (cdev->drv && !try_module_get(cdev->drv->owner)) { 525 if (cdev->drv && !try_module_get(cdev->drv->owner)) {
@@ -1014,6 +1021,13 @@ static void ccw_device_call_sch_unregister(struct work_struct *work)
1014 put_device(&sch->dev); 1021 put_device(&sch->dev);
1015} 1022}
1016 1023
1024void ccw_device_schedule_sch_unregister(struct ccw_device *cdev)
1025{
1026 PREPARE_WORK(&cdev->private->kick_work,
1027 ccw_device_call_sch_unregister);
1028 queue_work(slow_path_wq, &cdev->private->kick_work);
1029}
1030
1017/* 1031/*
1018 * subchannel recognition done. Called from the state machine. 1032 * subchannel recognition done. Called from the state machine.
1019 */ 1033 */
@@ -1025,19 +1039,17 @@ io_subchannel_recog_done(struct ccw_device *cdev)
1025 return; 1039 return;
1026 } 1040 }
1027 switch (cdev->private->state) { 1041 switch (cdev->private->state) {
1042 case DEV_STATE_BOXED:
1043 /* Device did not respond in time. */
1028 case DEV_STATE_NOT_OPER: 1044 case DEV_STATE_NOT_OPER:
1029 cdev->private->flags.recog_done = 1; 1045 cdev->private->flags.recog_done = 1;
1030 /* Remove device found not operational. */ 1046 /* Remove device found not operational. */
1031 if (!get_device(&cdev->dev)) 1047 if (!get_device(&cdev->dev))
1032 break; 1048 break;
1033 PREPARE_WORK(&cdev->private->kick_work, 1049 ccw_device_schedule_sch_unregister(cdev);
1034 ccw_device_call_sch_unregister);
1035 queue_work(slow_path_wq, &cdev->private->kick_work);
1036 if (atomic_dec_and_test(&ccw_device_init_count)) 1050 if (atomic_dec_and_test(&ccw_device_init_count))
1037 wake_up(&ccw_device_init_wq); 1051 wake_up(&ccw_device_init_wq);
1038 break; 1052 break;
1039 case DEV_STATE_BOXED:
1040 /* Device did not respond in time. */
1041 case DEV_STATE_OFFLINE: 1053 case DEV_STATE_OFFLINE:
1042 /* 1054 /*
1043 * We can't register the device in interrupt context so 1055 * We can't register the device in interrupt context so
@@ -1551,8 +1563,7 @@ static int purge_fn(struct device *dev, void *data)
1551 goto out; 1563 goto out;
1552 CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", priv->dev_id.ssid, 1564 CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", priv->dev_id.ssid,
1553 priv->dev_id.devno); 1565 priv->dev_id.devno);
1554 PREPARE_WORK(&cdev->private->kick_work, ccw_device_call_sch_unregister); 1566 ccw_device_schedule_sch_unregister(cdev);
1555 queue_work(slow_path_wq, &cdev->private->kick_work);
1556 1567
1557out: 1568out:
1558 /* Abort loop in case of pending signal. */ 1569 /* Abort loop in case of pending signal. */
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 85e01846ca65..f1cbbd94ad4e 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -87,6 +87,7 @@ int ccw_device_is_orphan(struct ccw_device *);
87int ccw_device_recognition(struct ccw_device *); 87int ccw_device_recognition(struct ccw_device *);
88int ccw_device_online(struct ccw_device *); 88int ccw_device_online(struct ccw_device *);
89int ccw_device_offline(struct ccw_device *); 89int ccw_device_offline(struct ccw_device *);
90void ccw_device_schedule_sch_unregister(struct ccw_device *);
90int ccw_purge_blacklisted(void); 91int ccw_purge_blacklisted(void);
91 92
92/* Function prototypes for device status and basic sense stuff. */ 93/* Function prototypes for device status and basic sense stuff. */
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 87b4bfca080f..e46049261561 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -256,13 +256,12 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
256 old_lpm = 0; 256 old_lpm = 0;
257 if (sch->lpm != old_lpm) 257 if (sch->lpm != old_lpm)
258 __recover_lost_chpids(sch, old_lpm); 258 __recover_lost_chpids(sch, old_lpm);
259 if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) { 259 if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID &&
260 if (state == DEV_STATE_NOT_OPER) { 260 (state == DEV_STATE_NOT_OPER || state == DEV_STATE_BOXED)) {
261 cdev->private->flags.recog_done = 1; 261 cdev->private->flags.recog_done = 1;
262 cdev->private->state = DEV_STATE_DISCONNECTED; 262 cdev->private->state = DEV_STATE_DISCONNECTED;
263 return; 263 wake_up(&cdev->private->wait_q);
264 } 264 return;
265 /* Boxed devices don't need extra treatment. */
266 } 265 }
267 notify = 0; 266 notify = 0;
268 same_dev = 0; /* Keep the compiler quiet... */ 267 same_dev = 0; /* Keep the compiler quiet... */
@@ -274,7 +273,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
274 sch->schid.ssid, sch->schid.sch_no); 273 sch->schid.ssid, sch->schid.sch_no);
275 break; 274 break;
276 case DEV_STATE_OFFLINE: 275 case DEV_STATE_OFFLINE:
277 if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) { 276 if (cdev->online) {
278 same_dev = ccw_device_handle_oper(cdev); 277 same_dev = ccw_device_handle_oper(cdev);
279 notify = 1; 278 notify = 1;
280 } 279 }
@@ -307,12 +306,17 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
307 " subchannel 0.%x.%04x\n", 306 " subchannel 0.%x.%04x\n",
308 cdev->private->dev_id.devno, 307 cdev->private->dev_id.devno,
309 sch->schid.ssid, sch->schid.sch_no); 308 sch->schid.ssid, sch->schid.sch_no);
309 if (cdev->id.cu_type != 0) { /* device was recognized before */
310 cdev->private->flags.recog_done = 1;
311 cdev->private->state = DEV_STATE_BOXED;
312 wake_up(&cdev->private->wait_q);
313 return;
314 }
310 break; 315 break;
311 } 316 }
312 cdev->private->state = state; 317 cdev->private->state = state;
313 io_subchannel_recog_done(cdev); 318 io_subchannel_recog_done(cdev);
314 if (state != DEV_STATE_NOT_OPER) 319 wake_up(&cdev->private->wait_q);
315 wake_up(&cdev->private->wait_q);
316} 320}
317 321
318/* 322/*
@@ -390,10 +394,13 @@ ccw_device_done(struct ccw_device *cdev, int state)
390 394
391 cdev->private->state = state; 395 cdev->private->state = state;
392 396
393 397 if (state == DEV_STATE_BOXED) {
394 if (state == DEV_STATE_BOXED)
395 CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n", 398 CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n",
396 cdev->private->dev_id.devno, sch->schid.sch_no); 399 cdev->private->dev_id.devno, sch->schid.sch_no);
400 if (cdev->online && !ccw_device_notify(cdev, CIO_BOXED))
401 ccw_device_schedule_sch_unregister(cdev);
402 cdev->private->flags.donotify = 0;
403 }
397 404
398 if (cdev->private->flags.donotify) { 405 if (cdev->private->flags.donotify) {
399 cdev->private->flags.donotify = 0; 406 cdev->private->flags.donotify = 0;
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index 1fe1e2eda512..cfb0dcb6e3ff 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -176,6 +176,11 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
176 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 176 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
177 "ccnoti4", NULL); 177 "ccnoti4", NULL);
178 break; 178 break;
179 case CIO_BOXED:
180 dev_warn(&adapter->ccw_device->dev,
181 "The ccw device did not respond in time.\n");
182 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5", NULL);
183 break;
179 } 184 }
180 return 1; 185 return 1;
181} 186}