summaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/device.c')
-rw-r--r--drivers/s390/cio/device.c79
1 files changed, 41 insertions, 38 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 4ca5adce91..34b2567b8d 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -363,10 +363,8 @@ int ccw_device_set_online(struct ccw_device *cdev)
spin_lock_irq(cdev->ccwlock);
ret = ccw_device_online(cdev);
- spin_unlock_irq(cdev->ccwlock);
- if (ret == 0)
- wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
- else {
+ if (ret) {
+ spin_unlock_irq(cdev->ccwlock);
CIO_MSG_EVENT(0, "ccw_device_online returned %d, "
"device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid,
@@ -375,7 +373,12 @@ int ccw_device_set_online(struct ccw_device *cdev)
put_device(&cdev->dev);
return ret;
}
- spin_lock_irq(cdev->ccwlock);
+ /* Wait until a final state is reached */
+ while (!dev_fsm_final_state(cdev)) {
+ spin_unlock_irq(cdev->ccwlock);
+ wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
+ spin_lock_irq(cdev->ccwlock);
+ }
/* Check if online processing was successful */
if ((cdev->private->state != DEV_STATE_ONLINE) &&
(cdev->private->state != DEV_STATE_W4SENSE)) {
@@ -748,7 +751,7 @@ static int io_subchannel_initialize_dev(struct subchannel *sch,
mutex_init(&cdev->reg_mutex);
atomic_set(&priv->onoff, 0);
- cdev->ccwlock = sch->lock;
+ cdev->ccwlock = &sch->lock;
cdev->dev.parent = &sch->dev;
cdev->dev.release = ccw_device_release;
cdev->dev.bus = &ccw_bus_type;
@@ -764,9 +767,9 @@ static int io_subchannel_initialize_dev(struct subchannel *sch,
goto out_put;
}
priv->flags.initialized = 1;
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
sch_set_cdev(sch, cdev);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
return 0;
out_put:
@@ -851,9 +854,9 @@ static void io_subchannel_register(struct ccw_device *cdev)
CIO_MSG_EVENT(0, "Could not register ccw dev 0.%x.%04x: %d\n",
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno, ret);
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
sch_set_cdev(sch, NULL);
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
mutex_unlock(&cdev->reg_mutex);
/* Release initial device reference. */
put_device(&cdev->dev);
@@ -904,9 +907,9 @@ static void io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
atomic_inc(&ccw_device_init_count);
/* Start async. device sensing. */
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
ccw_device_recognition(cdev);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
}
static int ccw_device_move_to_sch(struct ccw_device *cdev,
@@ -921,12 +924,12 @@ static int ccw_device_move_to_sch(struct ccw_device *cdev,
return -ENODEV;
if (!sch_is_pseudo_sch(old_sch)) {
- spin_lock_irq(old_sch->lock);
+ spin_lock_irq(&old_sch->lock);
old_enabled = old_sch->schib.pmcw.ena;
rc = 0;
if (old_enabled)
rc = cio_disable_subchannel(old_sch);
- spin_unlock_irq(old_sch->lock);
+ spin_unlock_irq(&old_sch->lock);
if (rc == -EBUSY) {
/* Release child reference for new parent. */
put_device(&sch->dev);
@@ -944,9 +947,9 @@ static int ccw_device_move_to_sch(struct ccw_device *cdev,
sch->schib.pmcw.dev, rc);
if (old_enabled) {
/* Try to re-enable the old subchannel. */
- spin_lock_irq(old_sch->lock);
+ spin_lock_irq(&old_sch->lock);
cio_enable_subchannel(old_sch, (u32)virt_to_phys(old_sch));
- spin_unlock_irq(old_sch->lock);
+ spin_unlock_irq(&old_sch->lock);
}
/* Release child reference for new parent. */
put_device(&sch->dev);
@@ -954,19 +957,19 @@ static int ccw_device_move_to_sch(struct ccw_device *cdev,
}
/* Clean up old subchannel. */
if (!sch_is_pseudo_sch(old_sch)) {
- spin_lock_irq(old_sch->lock);
+ spin_lock_irq(&old_sch->lock);
sch_set_cdev(old_sch, NULL);
- spin_unlock_irq(old_sch->lock);
+ spin_unlock_irq(&old_sch->lock);
css_schedule_eval(old_sch->schid);
}
/* Release child reference for old parent. */
put_device(&old_sch->dev);
/* Initialize new subchannel. */
- spin_lock_irq(sch->lock);
- cdev->ccwlock = sch->lock;
+ spin_lock_irq(&sch->lock);
+ cdev->ccwlock = &sch->lock;
if (!sch_is_pseudo_sch(sch))
sch_set_cdev(sch, cdev);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
if (!sch_is_pseudo_sch(sch))
css_update_ssd_info(sch);
return 0;
@@ -1077,9 +1080,9 @@ static int io_subchannel_probe(struct subchannel *sch)
return 0;
out_schedule:
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
css_sched_sch_todo(sch, SCH_TODO_UNREG);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
return 0;
}
@@ -1093,10 +1096,10 @@ static void io_subchannel_remove(struct subchannel *sch)
goto out_free;
ccw_device_unregister(cdev);
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
sch_set_cdev(sch, NULL);
set_io_private(sch, NULL);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
out_free:
dma_free_coherent(&sch->dev, sizeof(*io_priv->dma_area),
io_priv->dma_area, io_priv->dma_area_dma);
@@ -1203,7 +1206,7 @@ static void io_subchannel_quiesce(struct subchannel *sch)
struct ccw_device *cdev;
int ret;
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
cdev = sch_get_cdev(sch);
if (cio_is_console(sch->schid))
goto out_unlock;
@@ -1220,15 +1223,15 @@ static void io_subchannel_quiesce(struct subchannel *sch)
ret = ccw_device_cancel_halt_clear(cdev);
if (ret == -EBUSY) {
ccw_device_set_timeout(cdev, HZ/10);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
wait_event(cdev->private->wait_q,
cdev->private->state != DEV_STATE_QUIESCE);
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
}
ret = cio_disable_subchannel(sch);
}
out_unlock:
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
}
static void io_subchannel_shutdown(struct subchannel *sch)
@@ -1439,7 +1442,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
enum io_sch_action action;
int rc = -EAGAIN;
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
if (!device_is_registered(&sch->dev))
goto out_unlock;
if (work_pending(&sch->todo_work))
@@ -1492,7 +1495,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
default:
break;
}
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
/* All other actions require process context. */
if (!process)
goto out;
@@ -1507,9 +1510,9 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
break;
case IO_SCH_UNREG_CDEV:
case IO_SCH_UNREG_ATTACH:
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
sch_set_cdev(sch, NULL);
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
/* Unregister ccw device. */
ccw_device_unregister(cdev);
break;
@@ -1538,9 +1541,9 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
put_device(&cdev->dev);
goto out;
}
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
ccw_device_trigger_reprobe(cdev);
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
/* Release reference from get_ccwdev_by_dev_id() */
put_device(&cdev->dev);
break;
@@ -1550,7 +1553,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
return 0;
out_unlock:
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
out:
return rc;
}
@@ -1846,9 +1849,9 @@ static void ccw_device_todo(struct work_struct *work)
css_schedule_eval(sch->schid);
fallthrough;
case CDEV_TODO_UNREG:
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
sch_set_cdev(sch, NULL);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
ccw_device_unregister(cdev);
break;
default: