Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 1949

kernel-2.6.18-128.1.10.el5.src.rpm

From: Hans-Joachim Picht <hpicht@redhat.com>
Date: Thu, 3 Apr 2008 15:36:03 +0200
Subject: [s390] dasd: fix ifcc handling
Message-id: 20080403133603.GC10542@redhat.com
O-Subject: [RHEL5 U3 PATCH 1/7] s390 - dasd: fix ifcc handling
Bugzilla: 431592
RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com>

Description
============

There is no correct handling of Interface Control Checks (ifcc).
This is fixed by implementing the correct handling of ifcc's.

First retry the request up to 255 times and when all retries fail,
try an alternate path if  available.

Bugzilla
=========

BZ 431592
https://bugzilla.redhat.com/show_bug.cgi?id=431592

Upstream status of the patch:
=============================

The Patch will not go upstream  in this form because the code of the actual DASD
driver has changed heavily.

A different patch which fixes the problem  upstream was posted upstream
http://article.gmane.org/gmane.linux.kernel/634769 and is included as git
commit 6c5f57c7884a7e0806ae9af86de243321cab4953

Test status:
============

The patch has been tested and fixes the problem.
The fix was verified by our Test department.

Please ACK.

With best regards,

Hans

diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 1e033b8..e707723 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1104,6 +1104,18 @@ __dasd_process_erp(struct dasd_device *device, struct dasd_ccw_req *cqr)
 }
 
 /*
+ * check if specific recovery is possible
+ */
+static inline int
+generic_check_erp(struct dasd_ccw_req *cqr)
+{
+	return ((cqr->irb.esw.esw0.erw.cons &&
+		 test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags))
+		|| (cqr->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK
+					   | SCHN_STAT_CHN_CTRL_CHK)));
+}
+
+/*
  * Process ccw request queue.
  */
 static inline void
@@ -1129,9 +1141,7 @@ restart:
 				cqr->status = DASD_CQR_FAILED;
 				cqr->stopclk = get_clock();
 			} else {
-				if (cqr->irb.esw.esw0.erw.cons &&
-				    test_bit(DASD_CQR_FLAGS_USE_ERP,
-					     &cqr->flags)) {
+				if (generic_check_erp(cqr)) {
 					erp_fn = device->discipline->
 						erp_action(cqr);
 					erp_fn(cqr);
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 4d01040..98f7311 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -313,7 +313,7 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
 		/* reset status to queued to handle the request again... */
 		if (erp->status > DASD_CQR_QUEUED)
 			erp->status = DASD_CQR_QUEUED;
-		erp->retries = 1;
+		erp->retries = 10;
 	} else {
 		DEV_MESSAGE(KERN_ERR, device,
 			    "No alternate channel path left (lpum=%x / "
@@ -2234,6 +2234,34 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
  */
 
 /*
+ * DASD_3990_ERP_CONTROL_CHECK
+ *
+ * DESCRIPTION
+ *   Does a generic inspection if a control check occurs and set up
+ *   the related error recovery procedure
+ *
+ * PARAMETER
+ *   erp		pointer to the currently created default ERP
+ *   sense              sense data of the actual error
+ * RETURN VALUES
+ *   erp_filled		pointer to the erp
+ */
+
+static struct dasd_ccw_req *
+dasd_3990_erp_control_check(struct dasd_ccw_req *erp)
+{
+	struct dasd_device *device = erp->device;
+
+	if (erp->refers->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK
+					   | SCHN_STAT_CHN_CTRL_CHK)) {
+		DEV_MESSAGE(KERN_DEBUG, device, "%s",
+			    "channel or interface control check");
+		erp = dasd_3990_erp_action_4(erp, NULL);
+	}
+	return erp;
+}
+
+/*
  * DASD_3990_ERP_INSPECT
  *
  * DESCRIPTION
@@ -2254,8 +2282,11 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp)
 	/* already set up new ERP !			      */
 	char *sense = erp->refers->irb.ecw;
 
+	/* check if no concurrent sens is available */
+	if (!erp->refers->irb.esw.esw0.erw.cons)
+		erp_new = dasd_3990_erp_control_check(erp);
 	/* distinguish between 24 and 32 byte sense data */
-	if (sense[27] & DASD_SENSE_BIT_0) {
+	else if (sense[27] & DASD_SENSE_BIT_0) {
 
 		/* inspect the 24 byte sense data */
 		erp_new = dasd_3990_erp_inspect_24(erp, sense);