svn commit: r251096 - stable/9/sys/cam/ata
Alexander Motin
mav at FreeBSD.org
Wed May 29 04:17:06 UTC 2013
Author: mav
Date: Wed May 29 04:17:05 2013
New Revision: 251096
URL: http://svnweb.freebsd.org/changeset/base/251096
Log:
MFC r250508:
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:
stable/9/sys/cam/ata/ata_pmp.c
Directory Properties:
stable/9/sys/ (props changed)
Modified: stable/9/sys/cam/ata/ata_pmp.c
==============================================================================
--- stable/9/sys/cam/ata/ata_pmp.c Wed May 29 04:14:41 2013 (r251095)
+++ stable/9/sys/cam/ata/ata_pmp.c Wed May 29 04:17:05 2013 (r251096)
@@ -64,6 +64,9 @@ __FBSDID("$FreeBSD$");
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 @@ pmpasync(void *callback_arg, u_int32_t c
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 @@ pmpstart(struct cam_periph *periph, unio
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 @@ pmpstart(struct cam_periph *periph, unio
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 @@ pmpstart(struct cam_periph *periph, unio
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 @@ pmpdone(struct cam_periph *periph, union
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 @@ pmpdone(struct cam_periph *periph, union
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 svn-src-stable-9
mailing list