[S390] cio: make steal lock procedure more robust
An Unconditional Reserve + Release operation (steal lock) for a boxed device may fail when encountering special error cases (e.g. unit checks or path errors). Fix this by using the more robust ccw_request infrastructure for performing the steal lock CCW program. Signed-off-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Esse commit está contido em:

commit de
Martin Schwidefsky

pai
52ef0608e3
commit
d7d12ef2be
@@ -640,6 +640,23 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event)
|
||||
ccw_device_verify_start(cdev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle path verification event in boxed state.
|
||||
*/
|
||||
static void ccw_device_boxed_verify(struct ccw_device *cdev,
|
||||
enum dev_event dev_event)
|
||||
{
|
||||
struct subchannel *sch = to_subchannel(cdev->dev.parent);
|
||||
|
||||
if (cdev->online) {
|
||||
if (cio_enable_subchannel(sch, (u32) (addr_t) sch))
|
||||
ccw_device_done(cdev, DEV_STATE_NOT_OPER);
|
||||
else
|
||||
ccw_device_online_verify(cdev, dev_event);
|
||||
} else
|
||||
css_schedule_eval(sch->schid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Got an interrupt for a normal io (state online).
|
||||
*/
|
||||
@@ -816,32 +833,6 @@ ccw_device_delay_verify(struct ccw_device *cdev, enum dev_event dev_event)
|
||||
cdev->private->flags.doverify = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ccw_device_stlck_done(struct ccw_device *cdev, enum dev_event dev_event)
|
||||
{
|
||||
struct irb *irb;
|
||||
|
||||
switch (dev_event) {
|
||||
case DEV_EVENT_INTERRUPT:
|
||||
irb = (struct irb *) __LC_IRB;
|
||||
/* Check for unsolicited interrupt. */
|
||||
if ((scsw_stctl(&irb->scsw) ==
|
||||
(SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) &&
|
||||
(!scsw_cc(&irb->scsw)))
|
||||
/* FIXME: we should restart stlck here, but this
|
||||
* is extremely unlikely ... */
|
||||
goto out_wakeup;
|
||||
|
||||
ccw_device_accumulate_irb(cdev, irb);
|
||||
/* We don't care about basic sense etc. */
|
||||
break;
|
||||
default: /* timeout */
|
||||
break;
|
||||
}
|
||||
out_wakeup:
|
||||
wake_up(&cdev->private->wait_q);
|
||||
}
|
||||
|
||||
static void
|
||||
ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event)
|
||||
{
|
||||
@@ -1010,9 +1001,9 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
|
||||
},
|
||||
[DEV_STATE_BOXED] = {
|
||||
[DEV_EVENT_NOTOPER] = ccw_device_generic_notoper,
|
||||
[DEV_EVENT_INTERRUPT] = ccw_device_stlck_done,
|
||||
[DEV_EVENT_TIMEOUT] = ccw_device_stlck_done,
|
||||
[DEV_EVENT_VERIFY] = ccw_device_nop,
|
||||
[DEV_EVENT_INTERRUPT] = ccw_device_nop,
|
||||
[DEV_EVENT_TIMEOUT] = ccw_device_nop,
|
||||
[DEV_EVENT_VERIFY] = ccw_device_boxed_verify,
|
||||
},
|
||||
/* states to wait for i/o completion before doing something */
|
||||
[DEV_STATE_TIMEOUT_KILL] = {
|
||||
@@ -1052,6 +1043,12 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
|
||||
[DEV_EVENT_TIMEOUT] = ccw_device_update_cmfblock,
|
||||
[DEV_EVENT_VERIFY] = ccw_device_update_cmfblock,
|
||||
},
|
||||
[DEV_STATE_STEAL_LOCK] = {
|
||||
[DEV_EVENT_NOTOPER] = ccw_device_request_event,
|
||||
[DEV_EVENT_INTERRUPT] = ccw_device_request_event,
|
||||
[DEV_EVENT_TIMEOUT] = ccw_device_request_event,
|
||||
[DEV_EVENT_VERIFY] = ccw_device_nop,
|
||||
},
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(ccw_device_set_timeout);
|
||||
|
Referência em uma nova issue
Block a user