Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 173242
b: refs/heads/master
c: 52ef060
h: refs/heads/master
v: v3
  • Loading branch information
Peter Oberparleiter authored and Martin Schwidefsky committed Dec 7, 2009
1 parent 3a76a1a commit a80738a
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 95 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: 454e1fa1ebae7cff707b2e3f12b775c263c8408b
refs/heads/master: 52ef0608e3ee4a511725e443c4b572fece22b353
3 changes: 0 additions & 3 deletions trunk/drivers/s390/cio/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,6 @@ void ccw_device_sense_id_start(struct ccw_device *);
void ccw_device_sense_id_done(struct ccw_device *, int);

/* Function prototypes for path grouping stuff. */
void ccw_device_sense_pgid_start(struct ccw_device *);
void ccw_device_sense_pgid_done(struct ccw_device *, int);

void ccw_device_verify_start(struct ccw_device *);
void ccw_device_verify_done(struct ccw_device *, int);

Expand Down
41 changes: 4 additions & 37 deletions trunk/drivers/s390/cio/device_fsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,33 +394,6 @@ ccw_device_done(struct ccw_device *cdev, int state)
wake_up(&cdev->private->wait_q);
}

/*
* Function called from device_pgid.c after sense path ground has completed.
*/
void
ccw_device_sense_pgid_done(struct ccw_device *cdev, int err)
{
struct subchannel *sch;

sch = to_subchannel(cdev->dev.parent);
switch (err) {
case -EOPNOTSUPP: /* path grouping not supported, use nop instead. */
case 0: /* success */
case -EACCES: /* partial success, some paths not operational */
break;
case -ETIME: /* Sense path group id stopped by timeout. */
case -EUSERS: /* device is reserved for someone else. */
ccw_device_done(cdev, DEV_STATE_BOXED);
return;
default:
ccw_device_done(cdev, DEV_STATE_NOT_OPER);
return;
}
/* Start Path Group verification. */
cdev->private->state = DEV_STATE_VERIFY;
ccw_device_verify_start(cdev);
}

/*
* Start device recognition.
*/
Expand Down Expand Up @@ -503,6 +476,7 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
}
break;
case -ETIME:
case -EUSERS:
/* Reset oper notify indication after verify error. */
cdev->private->flags.donotify = 0;
ccw_device_done(cdev, DEV_STATE_BOXED);
Expand Down Expand Up @@ -540,16 +514,9 @@ ccw_device_online(struct ccw_device *cdev)
dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
return ret;
}
/* Do we want to do path grouping? */
if (!cdev->private->options.pgroup) {
/* Start initial path verification. */
cdev->private->state = DEV_STATE_VERIFY;
ccw_device_verify_start(cdev);
return 0;
}
/* Do a SensePGID first. */
cdev->private->state = DEV_STATE_SENSE_PGID;
ccw_device_sense_pgid_start(cdev);
/* Start initial path verification. */
cdev->private->state = DEV_STATE_VERIFY;
ccw_device_verify_start(cdev);
return 0;
}

Expand Down
148 changes: 95 additions & 53 deletions trunk/drivers/s390/cio/device_pgid.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ static void spid_do(struct ccw_device *cdev)
struct ccw_request *req = &cdev->private->req;
u8 fn;

/* Adjust lpm if paths are not set in pam. */
req->lpm = lpm_adjust(req->lpm, sch->schib.pmcw.pam);
/* Use next available path that is not already in correct state. */
req->lpm = lpm_adjust(req->lpm, sch->schib.pmcw.pam & ~sch->vpm);
if (!req->lpm)
goto out_nopath;
/* Channel program setup. */
Expand Down Expand Up @@ -199,6 +199,19 @@ static void spid_callback(struct ccw_device *cdev, void *data, int rc)
verify_done(cdev, rc);
}

static void spid_start(struct ccw_device *cdev)
{
struct ccw_request *req = &cdev->private->req;

/* Initialize request data. */
memset(req, 0, sizeof(*req));
req->timeout = PGID_TIMEOUT;
req->maxretries = PGID_RETRIES;
req->lpm = 0x80;
req->callback = spid_callback;
spid_do(cdev);
}

static int pgid_cmp(struct pgid *p1, struct pgid *p2)
{
return memcmp((char *) p1 + 1, (char *) p2 + 1,
Expand Down Expand Up @@ -241,6 +254,40 @@ static void pgid_analyze(struct ccw_device *cdev, struct pgid **p,
*p = first;
}

static u8 pgid_to_vpm(struct ccw_device *cdev)
{
struct subchannel *sch = to_subchannel(cdev->dev.parent);
struct pgid *pgid;
int i;
int lpm;
u8 vpm = 0;

/* Set VPM bits for paths which are already in the target state. */
for (i = 0; i < 8; i++) {
lpm = 0x80 >> i;
if ((cdev->private->pgid_valid_mask & lpm) == 0)
continue;
pgid = &cdev->private->pgid[i];
if (sch->opm & lpm) {
if (pgid->inf.ps.state1 != SNID_STATE1_GROUPED)
continue;
} else {
if (pgid->inf.ps.state1 != SNID_STATE1_UNGROUPED)
continue;
}
if (cdev->private->flags.mpath) {
if (pgid->inf.ps.state3 != SNID_STATE3_MULTI_PATH)
continue;
} else {
if (pgid->inf.ps.state3 != SNID_STATE3_SINGLE_PATH)
continue;
}
vpm |= lpm;
}

return vpm;
}

static void pgid_fill(struct ccw_device *cdev, struct pgid *pgid)
{
int i;
Expand All @@ -255,6 +302,7 @@ static void pgid_fill(struct ccw_device *cdev, struct pgid *pgid)
static void snid_done(struct ccw_device *cdev, int rc)
{
struct ccw_dev_id *id = &cdev->private->dev_id;
struct subchannel *sch = to_subchannel(cdev->dev.parent);
struct pgid *pgid;
int mismatch = 0;
int reserved = 0;
Expand All @@ -263,18 +311,38 @@ static void snid_done(struct ccw_device *cdev, int rc)
if (rc)
goto out;
pgid_analyze(cdev, &pgid, &mismatch, &reserved, &reset);
if (!mismatch) {
pgid_fill(cdev, pgid);
cdev->private->flags.pgid_rdy = 1;
}
if (reserved)
rc = -EUSERS;
else if (mismatch)
rc = -EOPNOTSUPP;
else {
sch->vpm = pgid_to_vpm(cdev);
pgid_fill(cdev, pgid);
}
out:
CIO_MSG_EVENT(2, "snid: device 0.%x.%04x: rc=%d pvm=%02x mism=%d "
"rsvd=%d reset=%d\n", id->ssid, id->devno, rc,
cdev->private->pgid_valid_mask, mismatch, reserved,
reset);
ccw_device_sense_pgid_done(cdev, rc);
CIO_MSG_EVENT(2, "snid: device 0.%x.%04x: rc=%d pvm=%02x vpm=%02x "
"mism=%d rsvd=%d reset=%d\n", id->ssid, id->devno, rc,
cdev->private->pgid_valid_mask, sch->vpm, mismatch,
reserved, reset);
switch (rc) {
case 0:
/* Anything left to do? */
if (sch->vpm == sch->schib.pmcw.pam) {
verify_done(cdev, sch->vpm == 0 ? -EACCES : 0);
return;
}
/* Perform path-grouping. */
spid_start(cdev);
break;
case -EOPNOTSUPP:
/* Path-grouping not supported. */
cdev->private->flags.pgroup = 0;
cdev->private->flags.mpath = 0;
verify_start(cdev);
break;
default:
verify_done(cdev, rc);
}
}

/*
Expand Down Expand Up @@ -333,40 +401,14 @@ static void snid_callback(struct ccw_device *cdev, void *data, int rc)
snid_done(cdev, rc);
}

/**
* ccw_device_sense_pgid_start - perform SENSE PGID
* @cdev: ccw device
*
* Execute a SENSE PGID channel program on each path to @cdev to update its
* PGID information. When finished, call ccw_device_sense_id_done with a
* return code specifying the result.
*/
void ccw_device_sense_pgid_start(struct ccw_device *cdev)
{
struct ccw_request *req = &cdev->private->req;

CIO_TRACE_EVENT(4, "snid");
CIO_HEX_EVENT(4, &cdev->private->dev_id, sizeof(cdev->private->dev_id));
/* Initialize PGID data. */
memset(cdev->private->pgid, 0, sizeof(cdev->private->pgid));
cdev->private->flags.pgid_rdy = 0;
cdev->private->pgid_valid_mask = 0;
/* Initialize request data. */
memset(req, 0, sizeof(*req));
req->timeout = PGID_TIMEOUT;
req->maxretries = PGID_RETRIES;
req->callback = snid_callback;
req->lpm = 0x80;
snid_do(cdev);
}

/*
* Perform path verification.
*/
static void verify_start(struct ccw_device *cdev)
{
struct subchannel *sch = to_subchannel(cdev->dev.parent);
struct ccw_request *req = &cdev->private->req;
struct ccw_dev_id *devid = &cdev->private->dev_id;

sch->vpm = 0;
/* Initialize request data. */
Expand All @@ -375,9 +417,13 @@ static void verify_start(struct ccw_device *cdev)
req->maxretries = PGID_RETRIES;
req->lpm = 0x80;
if (cdev->private->flags.pgroup) {
req->callback = spid_callback;
spid_do(cdev);
CIO_TRACE_EVENT(4, "snid");
CIO_HEX_EVENT(4, devid, sizeof(*devid));
req->callback = snid_callback;
snid_do(cdev);
} else {
CIO_TRACE_EVENT(4, "nop");
CIO_HEX_EVENT(4, devid, sizeof(*devid));
req->filter = nop_filter;
req->callback = nop_callback;
nop_do(cdev);
Expand All @@ -398,19 +444,15 @@ void ccw_device_verify_start(struct ccw_device *cdev)
{
CIO_TRACE_EVENT(4, "vrfy");
CIO_HEX_EVENT(4, &cdev->private->dev_id, sizeof(cdev->private->dev_id));
if (!cdev->private->flags.pgid_rdy) {
/* No pathgrouping possible. */
cdev->private->flags.pgroup = 0;
cdev->private->flags.mpath = 0;
} else {
/*
* Initialize pathgroup and multipath state with target values.
* They may change in the course of path verification.
*/
cdev->private->flags.pgroup = cdev->private->options.pgroup;
cdev->private->flags.mpath = cdev->private->options.mpath;

}
/* Initialize PGID data. */
memset(cdev->private->pgid, 0, sizeof(cdev->private->pgid));
cdev->private->pgid_valid_mask = 0;
/*
* Initialize pathgroup and multipath state with target values.
* They may change in the course of path verification.
*/
cdev->private->flags.pgroup = cdev->private->options.pgroup;
cdev->private->flags.mpath = cdev->private->options.mpath;
cdev->private->flags.doverify = 0;
verify_start(cdev);
}
Expand Down
1 change: 0 additions & 1 deletion trunk/drivers/s390/cio/io_sch.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ struct ccw_device_private {
unsigned int recog_done:1; /* dev. recog. complete */
unsigned int fake_irb:1; /* deliver faked irb */
unsigned int resuming:1; /* recognition while resume */
unsigned int pgid_rdy:1; /* pgids are ready */
unsigned int pgroup:1; /* pathgroup is set up */
unsigned int mpath:1; /* multipathing is set up */
} __attribute__((packed)) flags;
Expand Down

0 comments on commit a80738a

Please sign in to comment.