Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 356113
b: refs/heads/master
c: 88e7616
h: refs/heads/master
i:
  356111: 1f18a84
v: v3
  • Loading branch information
Sebastian Ott authored and Martin Schwidefsky committed Feb 14, 2013
1 parent 28dc251 commit 8849ddd
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 84c57ad5d938ff28d85ac93b79c1f918a767a23e
refs/heads/master: 88e7616e407fd60ad96e71349393397cf72f8b8d
64 changes: 61 additions & 3 deletions trunk/drivers/s390/cio/device_pgid.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#define PGID_RETRIES 256
#define PGID_TIMEOUT (10 * HZ)

static void verify_start(struct ccw_device *cdev);

/*
* Process path verification data and report result.
*/
Expand Down Expand Up @@ -142,6 +144,48 @@ static void spid_build_cp(struct ccw_device *cdev, u8 fn)
req->cp = cp;
}

static void pgid_wipeout_callback(struct ccw_device *cdev, void *data, int rc)
{
if (rc) {
/* We don't know the path groups' state. Abort. */
verify_done(cdev, rc);
return;
}
/*
* Path groups have been reset. Restart path verification but
* leave paths in path_noirq_mask out.
*/
cdev->private->flags.pgid_unknown = 0;
verify_start(cdev);
}

/*
* Reset pathgroups and restart path verification, leave unusable paths out.
*/
static void pgid_wipeout_start(struct ccw_device *cdev)
{
struct subchannel *sch = to_subchannel(cdev->dev.parent);
struct ccw_dev_id *id = &cdev->private->dev_id;
struct ccw_request *req = &cdev->private->req;
u8 fn;

CIO_MSG_EVENT(2, "wipe: device 0.%x.%04x: pvm=%02x nim=%02x\n",
id->ssid, id->devno, cdev->private->pgid_valid_mask,
cdev->private->path_noirq_mask);

/* Initialize request data. */
memset(req, 0, sizeof(*req));
req->timeout = PGID_TIMEOUT;
req->maxretries = PGID_RETRIES;
req->lpm = sch->schib.pmcw.pam;
req->callback = pgid_wipeout_callback;
fn = SPID_FUNC_DISBAND;
if (cdev->private->flags.mpath)
fn |= SPID_FUNC_MULTI_PATH;
spid_build_cp(cdev, fn);
ccw_request_start(cdev);
}

/*
* Perform establish/resign SET PGID on a single path.
*/
Expand All @@ -167,11 +211,14 @@ static void spid_do(struct ccw_device *cdev)
return;

out_nopath:
if (cdev->private->flags.pgid_unknown) {
/* At least one SPID could be partially done. */
pgid_wipeout_start(cdev);
return;
}
verify_done(cdev, sch->vpm ? 0 : -EACCES);
}

static void verify_start(struct ccw_device *cdev);

/*
* Process SET PGID request result for a single path.
*/
Expand Down Expand Up @@ -357,6 +404,10 @@ static void snid_done(struct ccw_device *cdev, int rc)
cdev->private->pgid_todo_mask, mismatch, reserved, reset);
switch (rc) {
case 0:
if (cdev->private->flags.pgid_unknown) {
pgid_wipeout_start(cdev);
return;
}
/* Anything left to do? */
if (cdev->private->pgid_todo_mask == 0) {
verify_done(cdev, sch->vpm == 0 ? -EACCES : 0);
Expand Down Expand Up @@ -400,6 +451,7 @@ static void snid_do(struct ccw_device *cdev)
{
struct subchannel *sch = to_subchannel(cdev->dev.parent);
struct ccw_request *req = &cdev->private->req;
int ret;

req->lpm = lpm_adjust(req->lpm, sch->schib.pmcw.pam &
~cdev->private->path_noirq_mask);
Expand All @@ -410,7 +462,13 @@ static void snid_do(struct ccw_device *cdev)
return;

out_nopath:
snid_done(cdev, cdev->private->pgid_valid_mask ? 0 : -EACCES);
if (cdev->private->pgid_valid_mask)
ret = 0;
else if (cdev->private->path_noirq_mask)
ret = -ETIME;
else
ret = -EACCES;
snid_done(cdev, ret);
}

/*
Expand Down

0 comments on commit 8849ddd

Please sign in to comment.