[Midnightbsd-cvs] src [9451] trunk/sys/cam/ata/ata_pmp.c: Disable sending Early R_OK on SiI3726/SiI3826 port multipliers.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sun Mar 5 14:32:12 EST 2017


Revision: 9451
          http://svnweb.midnightbsd.org/src/?rev=9451
Author:   laffer1
Date:     2017-03-05 14:32:12 -0500 (Sun, 05 Mar 2017)
Log Message:
-----------
Disable sending Early R_OK on SiI3726/SiI3826 port multipliers.
With "cached read" HDD testing and multiple ports busy on a SATA
host controller, 3726/3826 PMP will very rarely drop a deferred
R_OK that was intended for the host. Symptom will be all 5 drives
under test will timeout, get reset, and recover.

Modified Paths:
--------------
    trunk/sys/cam/ata/ata_pmp.c

Modified: trunk/sys/cam/ata/ata_pmp.c
===================================================================
--- trunk/sys/cam/ata/ata_pmp.c	2017-03-05 19:31:51 UTC (rev 9450)
+++ trunk/sys/cam/ata/ata_pmp.c	2017-03-05 19:32:12 UTC (rev 9451)
@@ -64,6 +64,9 @@
 typedef enum {
 	PMP_STATE_NORMAL,
 	PMP_STATE_PORTS,
+	PMP_STATE_PM_QUIRKS_1,
+	PMP_STATE_PM_QUIRKS_2,
+	PMP_STATE_PM_QUIRKS_3,
 	PMP_STATE_PRECONFIG,
 	PMP_STATE_RESET,
 	PMP_STATE_CONNECT,
@@ -319,7 +322,11 @@
 		if (code == AC_SENT_BDR || code == AC_BUS_RESET)
 			softc->found = 0; /* We have to reset everything. */
 		if (softc->state == PMP_STATE_NORMAL) {
-			softc->state = PMP_STATE_PRECONFIG;
+			if (softc->pm_pid == 0x37261095 ||
+			    softc->pm_pid == 0x38261095)
+				softc->state = PMP_STATE_PM_QUIRKS_1;
+			else
+				softc->state = PMP_STATE_PRECONFIG;
 			cam_periph_acquire(periph);
 			xpt_schedule(periph, CAM_PRIORITY_DEV);
 		} else
@@ -429,7 +436,10 @@
 
 	if (softc->restart) {
 		softc->restart = 0;
-		softc->state = min(softc->state, PMP_STATE_PRECONFIG);
+		if (softc->pm_pid == 0x37261095 || softc->pm_pid == 0x38261095)
+			softc->state = min(softc->state, PMP_STATE_PM_QUIRKS_1);
+		else
+			softc->state = min(softc->state, PMP_STATE_PRECONFIG);
 	}
 	/* Fetch user wanted device speed. */
 	if (softc->state == PMP_STATE_RESET ||
@@ -459,6 +469,32 @@
 		      pmp_default_timeout * 1000);
 		ata_pm_read_cmd(ataio, 2, 15);
 		break;
+
+	case PMP_STATE_PM_QUIRKS_1:
+	case PMP_STATE_PM_QUIRKS_3:
+		cam_fill_ataio(ataio,
+		      pmp_retry_count,
+		      pmpdone,
+		      /*flags*/CAM_DIR_NONE,
+		      0,
+		      /*data_ptr*/NULL,
+		      /*dxfer_len*/0,
+		      pmp_default_timeout * 1000);
+		ata_pm_read_cmd(ataio, 129, 15);
+		break;
+
+	case PMP_STATE_PM_QUIRKS_2:
+		cam_fill_ataio(ataio,
+		      pmp_retry_count,
+		      pmpdone,
+		      /*flags*/CAM_DIR_NONE,
+		      0,
+		      /*data_ptr*/NULL,
+		      /*dxfer_len*/0,
+		      pmp_default_timeout * 1000);
+		ata_pm_write_cmd(ataio, 129, 15, softc->caps & ~0x1);
+		break;
+
 	case PMP_STATE_PRECONFIG:
 		/* Get/update host SATA capabilities. */
 		bzero(&cts, sizeof(cts));
@@ -468,6 +504,8 @@
 		xpt_action((union ccb *)&cts);
 		if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
 			softc->caps = cts.xport_specific.sata.caps;
+		else
+			softc->caps = 0;
 		cam_fill_ataio(ataio,
 		      pmp_retry_count,
 		      pmpdone,
@@ -577,7 +615,10 @@
 	if (softc->restart) {
 		softc->restart = 0;
 		xpt_release_ccb(done_ccb);
-		softc->state = min(softc->state, PMP_STATE_PRECONFIG);
+		if (softc->pm_pid == 0x37261095 || softc->pm_pid == 0x38261095)
+			softc->state = min(softc->state, PMP_STATE_PM_QUIRKS_1);
+		else
+			softc->state = min(softc->state, PMP_STATE_PRECONFIG);
 		xpt_schedule(periph, priority);
 		return;
 	}
@@ -620,10 +661,48 @@
 		printf("%s%d: %d fan-out ports\n",
 		    periph->periph_name, periph->unit_number,
 		    softc->pm_ports);
+		if (softc->pm_pid == 0x37261095 || softc->pm_pid == 0x38261095)
+			softc->state = PMP_STATE_PM_QUIRKS_1;
+		else
+			softc->state = PMP_STATE_PRECONFIG;
+		xpt_release_ccb(done_ccb);
+		xpt_schedule(periph, priority);
+		return;
+
+	case PMP_STATE_PM_QUIRKS_1:
+		softc->caps = (ataio->res.lba_high << 24) +
+		    (ataio->res.lba_mid << 16) +
+		    (ataio->res.lba_low << 8) +
+		    ataio->res.sector_count;
+		if (softc->caps & 0x1)
+			softc->state = PMP_STATE_PM_QUIRKS_2;
+		else
+			softc->state = PMP_STATE_PRECONFIG;
+		xpt_release_ccb(done_ccb);
+		xpt_schedule(periph, priority);
+		return;
+
+	case PMP_STATE_PM_QUIRKS_2:
+		if (bootverbose)
+			softc->state = PMP_STATE_PM_QUIRKS_3;
+		else
+			softc->state = PMP_STATE_PRECONFIG;
+		xpt_release_ccb(done_ccb);
+		xpt_schedule(periph, priority);
+		return;
+
+	case PMP_STATE_PM_QUIRKS_3:
+		res = (ataio->res.lba_high << 24) +
+		    (ataio->res.lba_mid << 16) +
+		    (ataio->res.lba_low << 8) +
+		    ataio->res.sector_count;
+		printf("%s%d: Disabling SiI3x26 R_OK in GSCR_POLL: %x->%x\n",
+		    periph->periph_name, periph->unit_number, softc->caps, res);
 		softc->state = PMP_STATE_PRECONFIG;
 		xpt_release_ccb(done_ccb);
 		xpt_schedule(periph, priority);
 		return;
+
 	case PMP_STATE_PRECONFIG:
 		softc->pm_step = 0;
 		softc->state = PMP_STATE_RESET;



More information about the Midnightbsd-cvs mailing list