aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device_fsm.c
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2009-06-16 10:30:20 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-16 10:31:08 +0200
commit823d494ac11111064cf39abd4178ce299414c771 (patch)
treeede15540ad89c3412f16c24770408a4c34cc032c /drivers/s390/cio/device_fsm.c
parentMerge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6 (diff)
downloadlinux-dev-823d494ac11111064cf39abd4178ce299414c771.tar.xz
linux-dev-823d494ac11111064cf39abd4178ce299414c771.zip
[S390] pm: ccw bus power management callbacks
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/device_fsm.c')
-rw-r--r--drivers/s390/cio/device_fsm.c96
1 files changed, 43 insertions, 53 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index e46049261561..3db88c52d287 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -177,29 +177,21 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
panic("Can't stop i/o on subchannel.\n");
}
-static int
-ccw_device_handle_oper(struct ccw_device *cdev)
+void ccw_device_update_sense_data(struct ccw_device *cdev)
{
- struct subchannel *sch;
+ memset(&cdev->id, 0, sizeof(cdev->id));
+ cdev->id.cu_type = cdev->private->senseid.cu_type;
+ cdev->id.cu_model = cdev->private->senseid.cu_model;
+ cdev->id.dev_type = cdev->private->senseid.dev_type;
+ cdev->id.dev_model = cdev->private->senseid.dev_model;
+}
- sch = to_subchannel(cdev->dev.parent);
- cdev->private->flags.recog_done = 1;
- /*
- * Check if cu type and device type still match. If
- * not, it is certainly another device and we have to
- * de- and re-register.
- */
- if (cdev->id.cu_type != cdev->private->senseid.cu_type ||
- cdev->id.cu_model != cdev->private->senseid.cu_model ||
- cdev->id.dev_type != cdev->private->senseid.dev_type ||
- cdev->id.dev_model != cdev->private->senseid.dev_model) {
- PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_do_unbind_bind);
- queue_work(ccw_device_work, &cdev->private->kick_work);
- return 0;
- }
- cdev->private->flags.donotify = 1;
- return 1;
+int ccw_device_test_sense_data(struct ccw_device *cdev)
+{
+ return cdev->id.cu_type == cdev->private->senseid.cu_type &&
+ cdev->id.cu_model == cdev->private->senseid.cu_model &&
+ cdev->id.dev_type == cdev->private->senseid.dev_type &&
+ cdev->id.dev_model == cdev->private->senseid.dev_model;
}
/*
@@ -233,7 +225,7 @@ static void
ccw_device_recog_done(struct ccw_device *cdev, int state)
{
struct subchannel *sch;
- int notify, old_lpm, same_dev;
+ int old_lpm;
sch = to_subchannel(cdev->dev.parent);
@@ -263,8 +255,12 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
wake_up(&cdev->private->wait_q);
return;
}
- notify = 0;
- same_dev = 0; /* Keep the compiler quiet... */
+ if (cdev->private->flags.resuming) {
+ cdev->private->state = state;
+ cdev->private->flags.recog_done = 1;
+ wake_up(&cdev->private->wait_q);
+ return;
+ }
switch (state) {
case DEV_STATE_NOT_OPER:
CIO_MSG_EVENT(2, "SenseID : unknown device %04x on "
@@ -273,34 +269,31 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
sch->schid.ssid, sch->schid.sch_no);
break;
case DEV_STATE_OFFLINE:
- if (cdev->online) {
- same_dev = ccw_device_handle_oper(cdev);
- notify = 1;
+ if (!cdev->online) {
+ ccw_device_update_sense_data(cdev);
+ /* Issue device info message. */
+ CIO_MSG_EVENT(4, "SenseID : device 0.%x.%04x reports: "
+ "CU Type/Mod = %04X/%02X, Dev Type/Mod "
+ "= %04X/%02X\n",
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno,
+ cdev->id.cu_type, cdev->id.cu_model,
+ cdev->id.dev_type, cdev->id.dev_model);
+ break;
}
- /* fill out sense information */
- memset(&cdev->id, 0, sizeof(cdev->id));
- cdev->id.cu_type = cdev->private->senseid.cu_type;
- cdev->id.cu_model = cdev->private->senseid.cu_model;
- cdev->id.dev_type = cdev->private->senseid.dev_type;
- cdev->id.dev_model = cdev->private->senseid.dev_model;
- if (notify) {
- cdev->private->state = DEV_STATE_OFFLINE;
- if (same_dev) {
- /* Get device online again. */
- ccw_device_online(cdev);
- wake_up(&cdev->private->wait_q);
- }
- return;
+ cdev->private->state = DEV_STATE_OFFLINE;
+ cdev->private->flags.recog_done = 1;
+ if (ccw_device_test_sense_data(cdev)) {
+ cdev->private->flags.donotify = 1;
+ ccw_device_online(cdev);
+ wake_up(&cdev->private->wait_q);
+ } else {
+ ccw_device_update_sense_data(cdev);
+ PREPARE_WORK(&cdev->private->kick_work,
+ ccw_device_do_unbind_bind);
+ queue_work(ccw_device_work, &cdev->private->kick_work);
}
- /* Issue device info message. */
- CIO_MSG_EVENT(4, "SenseID : device 0.%x.%04x reports: "
- "CU Type/Mod = %04X/%02X, Dev Type/Mod = "
- "%04X/%02X\n",
- cdev->private->dev_id.ssid,
- cdev->private->dev_id.devno,
- cdev->id.cu_type, cdev->id.cu_model,
- cdev->id.dev_type, cdev->id.dev_model);
- break;
+ return;
case DEV_STATE_BOXED:
CIO_MSG_EVENT(0, "SenseID : boxed device %04x on "
" subchannel 0.%x.%04x\n",
@@ -502,9 +495,6 @@ ccw_device_recognition(struct ccw_device *cdev)
struct subchannel *sch;
int ret;
- if ((cdev->private->state != DEV_STATE_NOT_OPER) &&
- (cdev->private->state != DEV_STATE_BOXED))
- return -EINVAL;
sch = to_subchannel(cdev->dev.parent);
ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
if (ret != 0)