diff options
author | Peter Oberparleiter <peter.oberparleiter@de.ibm.com> | 2009-12-07 06:51:32 -0500 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2009-12-07 06:51:32 -0500 |
commit | d7d12ef2befac4fed0dccaddff11338b654804df (patch) | |
tree | 1563b299e609024844affbc3ebba99c0718db238 /drivers/s390/cio/device_pgid.c | |
parent | 52ef0608e3ee4a511725e443c4b572fece22b353 (diff) |
[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>
Diffstat (limited to 'drivers/s390/cio/device_pgid.c')
-rw-r--r-- | drivers/s390/cio/device_pgid.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c index 4d54abd82b8c..5bcefeaff744 100644 --- a/drivers/s390/cio/device_pgid.c +++ b/drivers/s390/cio/device_pgid.c | |||
@@ -507,3 +507,55 @@ void ccw_device_disband_start(struct ccw_device *cdev) | |||
507 | spid_build_cp(cdev, fn); | 507 | spid_build_cp(cdev, fn); |
508 | ccw_request_start(cdev); | 508 | ccw_request_start(cdev); |
509 | } | 509 | } |
510 | |||
511 | static void stlck_build_cp(struct ccw_device *cdev, void *buf1, void *buf2) | ||
512 | { | ||
513 | struct ccw_request *req = &cdev->private->req; | ||
514 | struct ccw1 *cp = cdev->private->iccws; | ||
515 | |||
516 | cp[0].cmd_code = CCW_CMD_STLCK; | ||
517 | cp[0].cda = (u32) (addr_t) buf1; | ||
518 | cp[0].count = 32; | ||
519 | cp[0].flags = CCW_FLAG_CC; | ||
520 | cp[1].cmd_code = CCW_CMD_RELEASE; | ||
521 | cp[1].cda = (u32) (addr_t) buf2; | ||
522 | cp[1].count = 32; | ||
523 | cp[1].flags = 0; | ||
524 | req->cp = cp; | ||
525 | } | ||
526 | |||
527 | static void stlck_callback(struct ccw_device *cdev, void *data, int rc) | ||
528 | { | ||
529 | ccw_device_stlck_done(cdev, data, rc); | ||
530 | } | ||
531 | |||
532 | /** | ||
533 | * ccw_device_stlck_start - perform unconditional release | ||
534 | * @cdev: ccw device | ||
535 | * @data: data pointer to be passed to ccw_device_stlck_done | ||
536 | * @buf1: data pointer used in channel program | ||
537 | * @buf2: data pointer used in channel program | ||
538 | * | ||
539 | * Execute a channel program on @cdev to release an existing PGID reservation. | ||
540 | * When finished, call ccw_device_stlck_done with a return code specifying the | ||
541 | * result. | ||
542 | */ | ||
543 | void ccw_device_stlck_start(struct ccw_device *cdev, void *data, void *buf1, | ||
544 | void *buf2) | ||
545 | { | ||
546 | struct subchannel *sch = to_subchannel(cdev->dev.parent); | ||
547 | struct ccw_request *req = &cdev->private->req; | ||
548 | |||
549 | CIO_TRACE_EVENT(4, "stlck"); | ||
550 | CIO_HEX_EVENT(4, &cdev->private->dev_id, sizeof(cdev->private->dev_id)); | ||
551 | /* Request setup. */ | ||
552 | memset(req, 0, sizeof(*req)); | ||
553 | req->timeout = PGID_TIMEOUT; | ||
554 | req->maxretries = PGID_RETRIES; | ||
555 | req->lpm = sch->schib.pmcw.pam & sch->opm; | ||
556 | req->data = data; | ||
557 | req->callback = stlck_callback; | ||
558 | stlck_build_cp(cdev, buf1, buf2); | ||
559 | ccw_request_start(cdev); | ||
560 | } | ||
561 | |||