Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 69f5576f authored by Sebastian Ott's avatar Sebastian Ott Committed by Martin Schwidefsky
Browse files

s390/cio: dont abort verification after missing irq



Do not abort path verification when waiting for an interrupt timed out.
Use path_noirq_mask to keep track of the paths used for this (also
maintain a path_notoper_mask for debugging purposes). If the timeout
happend to be during an operation where we query or alter the state of
path groups set the pgid_unknown flag.

With this change we allow usage of devices which have such ill-behaved
paths (if at least one path is operational).

Reviewed-by: default avatarPeter Oberparleiter <peter.oberparleiter@de.ibm.com>
Signed-off-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent b4b3d128
Loading
Loading
Loading
Loading
+38 −10
Original line number Diff line number Diff line
@@ -102,10 +102,20 @@ static void nop_callback(struct ccw_device *cdev, void *data, int rc)
	struct subchannel *sch = to_subchannel(cdev->dev.parent);
	struct ccw_request *req = &cdev->private->req;

	if (rc == 0)
	switch (rc) {
	case 0:
		sch->vpm |= req->lpm;
	else if (rc != -EACCES)
		break;
	case -ETIME:
		cdev->private->path_noirq_mask |= req->lpm;
		break;
	case -EACCES:
		cdev->private->path_notoper_mask |= req->lpm;
		break;
	default:
		goto err;
	}
	/* Continue on the next path. */
	req->lpm >>= 1;
	nop_do(cdev);
	return;
@@ -174,7 +184,12 @@ static void spid_callback(struct ccw_device *cdev, void *data, int rc)
	case 0:
		sch->vpm |= req->lpm & sch->opm;
		break;
	case -ETIME:
		cdev->private->flags.pgid_unknown = 1;
		cdev->private->path_noirq_mask |= req->lpm;
		break;
	case -EACCES:
		cdev->private->path_notoper_mask |= req->lpm;
		break;
	case -EOPNOTSUPP:
		if (cdev->private->flags.mpath) {
@@ -404,10 +419,21 @@ static void snid_callback(struct ccw_device *cdev, void *data, int rc)
{
	struct ccw_request *req = &cdev->private->req;

	if (rc == 0)
	switch (rc) {
	case 0:
		cdev->private->pgid_valid_mask |= req->lpm;
	else if (rc != -EACCES)
		break;
	case -ETIME:
		cdev->private->flags.pgid_unknown = 1;
		cdev->private->path_noirq_mask |= req->lpm;
		break;
	case -EACCES:
		cdev->private->path_notoper_mask |= req->lpm;
		break;
	default:
		goto err;
	}
	/* Continue on the next path. */
	req->lpm >>= 1;
	snid_do(cdev);
	return;
@@ -427,6 +453,13 @@ static void verify_start(struct ccw_device *cdev)

	sch->vpm = 0;
	sch->lpm = sch->schib.pmcw.pam;

	/* Initialize PGID data. */
	memset(cdev->private->pgid, 0, sizeof(cdev->private->pgid));
	cdev->private->pgid_valid_mask = 0;
	cdev->private->pgid_todo_mask = sch->schib.pmcw.pam;
	cdev->private->path_notoper_mask = 0;

	/* Initialize request data. */
	memset(req, 0, sizeof(*req));
	req->timeout	= PGID_TIMEOUT;
@@ -459,14 +492,8 @@ static void verify_start(struct ccw_device *cdev)
 */
void ccw_device_verify_start(struct ccw_device *cdev)
{
	struct subchannel *sch = to_subchannel(cdev->dev.parent);

	CIO_TRACE_EVENT(4, "vrfy");
	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->pgid_valid_mask = 0;
	cdev->private->pgid_todo_mask = sch->schib.pmcw.pam;
	/*
	 * Initialize pathgroup and multipath state with target values.
	 * They may change in the course of path verification.
@@ -474,6 +501,7 @@ void ccw_device_verify_start(struct ccw_device *cdev)
	cdev->private->flags.pgroup = cdev->private->options.pgroup;
	cdev->private->flags.mpath = cdev->private->options.mpath;
	cdev->private->flags.doverify = 0;
	cdev->private->path_noirq_mask = 0;
	verify_start(cdev);
}

+5 −0
Original line number Diff line number Diff line
@@ -126,6 +126,10 @@ struct ccw_device_private {
	u8 pgid_valid_mask;	/* mask of valid PGIDs */
	u8 pgid_todo_mask;	/* mask of PGIDs to be adjusted */
	u8 pgid_reset_mask;	/* mask of PGIDs which were reset */
	u8 path_noirq_mask;	/* mask of paths for which no irq was
				   received */
	u8 path_notoper_mask;	/* mask of paths which were found
				   not operable */
	u8 path_gone_mask;	/* mask of paths, that became unavailable */
	u8 path_new_mask;	/* mask of paths, that became available */
	struct {
@@ -145,6 +149,7 @@ struct ccw_device_private {
		unsigned int resuming:1;    /* recognition while resume */
		unsigned int pgroup:1;	    /* pathgroup is set up */
		unsigned int mpath:1;	    /* multipathing is set up */
		unsigned int pgid_unknown:1;/* unknown pgid state */
		unsigned int initialized:1; /* set if initial reference held */
	} __attribute__((packed)) flags;
	unsigned long intparm;	/* user interruption parameter */