From owner-svn-src-stable-8@FreeBSD.ORG Sun Jan 18 20:40:11 2015 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 389016F4; Sun, 18 Jan 2015 20:40:11 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 22899C19; Sun, 18 Jan 2015 20:40:11 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t0IKeBFv038573; Sun, 18 Jan 2015 20:40:11 GMT (envelope-from np@FreeBSD.org) Received: (from np@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t0IKe94T038559; Sun, 18 Jan 2015 20:40:09 GMT (envelope-from np@FreeBSD.org) Message-Id: <201501182040.t0IKe94T038559@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: np set sender to np@FreeBSD.org using -f From: Navdeep Parhar Date: Sun, 18 Jan 2015 20:40:08 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r277345 - in stable/8/sys/dev/cxgb: . common X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Jan 2015 20:40:11 -0000 Author: np Date: Sun Jan 18 20:40:08 2015 New Revision: 277345 URL: https://svnweb.freebsd.org/changeset/base/277345 Log: MFC r276959: cxgb: replace r273280 with a more comprehensive fix. Poll for link state when the link is down, even for interrupt capable PHYs. Allow PHYs to report a dubious "partial" link. If this state is seen 3 consecutive times (each check is ~1s apart) then reset the PHY. This is a workaround for a situation where repeatedly toggling the link from the peer gets the AEL2005 PHY into a state where it never establishes a PCS block lock even when everything is in order. Modified: stable/8/sys/dev/cxgb/common/cxgb_ael1002.c stable/8/sys/dev/cxgb/common/cxgb_aq100x.c stable/8/sys/dev/cxgb/common/cxgb_common.h stable/8/sys/dev/cxgb/common/cxgb_mv88e1xxx.c stable/8/sys/dev/cxgb/common/cxgb_t3_hw.c stable/8/sys/dev/cxgb/common/cxgb_tn1010.c stable/8/sys/dev/cxgb/common/cxgb_vsc8211.c stable/8/sys/dev/cxgb/cxgb_main.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/dev/ (props changed) stable/8/sys/dev/cxgb/ (props changed) Modified: stable/8/sys/dev/cxgb/common/cxgb_ael1002.c ============================================================================== --- stable/8/sys/dev/cxgb/common/cxgb_ael1002.c Sun Jan 18 20:39:24 2015 (r277344) +++ stable/8/sys/dev/cxgb/common/cxgb_ael1002.c Sun Jan 18 20:40:08 2015 (r277345) @@ -283,10 +283,10 @@ static int ael1002_intr_noop(struct cphy /* * Get link status for a 10GBASE-R device. */ -static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed, +static int get_link_status_r(struct cphy *phy, int *link_state, int *speed, int *duplex, int *fc) { - if (link_ok) { + if (link_state) { unsigned int stat0, stat1, stat2; int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0); @@ -296,10 +296,16 @@ static int get_link_status_r(struct cphy err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2); if (err) return err; - *link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1; - if (*link_ok == 0) - return (0); + stat0 &= 1; + stat1 &= 1; + stat2 = (stat2 >> 12) & 1; + if (stat0 & stat1 & stat2) + *link_state = PHY_LINK_UP; + else if (stat0 == 1 && stat1 == 0 && stat2 == 1) + *link_state = PHY_LINK_PARTIAL; + else + *link_state = PHY_LINK_DOWN; } if (speed) *speed = SPEED_10000; @@ -1345,10 +1351,8 @@ static int ael2005_intr_handler(struct c return ret; ret |= cause; - if (!ret) { - (void) ael2005_reset(phy, 0); + if (!ret) ret |= cphy_cause_link_change; - } return ret; } @@ -2156,10 +2160,10 @@ int t3_ael2020_phy_prep(pinfo_t *pinfo, /* * Get link status for a 10GBASE-X device. */ -static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed, +static int get_link_status_x(struct cphy *phy, int *link_state, int *speed, int *duplex, int *fc) { - if (link_ok) { + if (link_state) { unsigned int stat0, stat1, stat2; int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0); @@ -2169,7 +2173,10 @@ static int get_link_status_x(struct cphy err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2); if (err) return err; - *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1; + if ((stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1) + *link_state = PHY_LINK_UP; + else + *link_state = PHY_LINK_DOWN; } if (speed) *speed = SPEED_10000; @@ -2230,10 +2237,10 @@ static int xaui_direct_reset(struct cphy return 0; } -static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok, +static int xaui_direct_get_link_status(struct cphy *phy, int *link_state, int *speed, int *duplex, int *fc) { - if (link_ok) { + if (link_state) { unsigned int status; adapter_t *adapter = phy->adapter; @@ -2245,7 +2252,7 @@ static int xaui_direct_get_link_status(s XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) | t3_read_reg(adapter, XGM_REG(A_XGM_SERDES_STAT3, phy->addr)); - *link_ok = !(status & F_LOWSIG0); + *link_state = status & F_LOWSIG0 ? PHY_LINK_DOWN : PHY_LINK_UP; } if (speed) *speed = SPEED_10000; Modified: stable/8/sys/dev/cxgb/common/cxgb_aq100x.c ============================================================================== --- stable/8/sys/dev/cxgb/common/cxgb_aq100x.c Sun Jan 18 20:39:24 2015 (r277344) +++ stable/8/sys/dev/cxgb/common/cxgb_aq100x.c Sun Jan 18 20:40:08 2015 (r277345) @@ -350,7 +350,7 @@ aq100x_set_speed_duplex(struct cphy *phy } static int -aq100x_get_link_status(struct cphy *phy, int *link_ok, int *speed, int *duplex, +aq100x_get_link_status(struct cphy *phy, int *link_state, int *speed, int *duplex, int *fc) { int err; @@ -440,8 +440,8 @@ aq100x_get_link_status(struct cphy *phy, link = 1; done: - if (link_ok) - *link_ok = link; + if (link_state) + *link_state = link ? PHY_LINK_UP : PHY_LINK_DOWN; return (0); } Modified: stable/8/sys/dev/cxgb/common/cxgb_common.h ============================================================================== --- stable/8/sys/dev/cxgb/common/cxgb_common.h Sun Jan 18 20:39:24 2015 (r277344) +++ stable/8/sys/dev/cxgb/common/cxgb_common.h Sun Jan 18 20:40:08 2015 (r277345) @@ -543,6 +543,12 @@ enum { phy_modtype_unknown }; +enum { + PHY_LINK_DOWN = 0, + PHY_LINK_UP, + PHY_LINK_PARTIAL +}; + /* PHY operations */ struct cphy_ops { int (*reset)(struct cphy *phy, int wait); @@ -558,7 +564,7 @@ struct cphy_ops { int (*advertise)(struct cphy *phy, unsigned int advertise_map); int (*set_loopback)(struct cphy *phy, int mmd, int dir, int enable); int (*set_speed_duplex)(struct cphy *phy, int speed, int duplex); - int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed, + int (*get_link_status)(struct cphy *phy, int *link_state, int *speed, int *duplex, int *fc); int (*power_down)(struct cphy *phy, int enable); }; @@ -567,6 +573,7 @@ struct cphy_ops { struct cphy { u8 addr; /* PHY address */ u8 modtype; /* PHY module type */ + u8 rst; unsigned int priv; /* scratch pad */ unsigned int caps; /* PHY capabilities */ adapter_t *adapter; /* associated adapter */ Modified: stable/8/sys/dev/cxgb/common/cxgb_mv88e1xxx.c ============================================================================== --- stable/8/sys/dev/cxgb/common/cxgb_mv88e1xxx.c Sun Jan 18 20:39:24 2015 (r277344) +++ stable/8/sys/dev/cxgb/common/cxgb_mv88e1xxx.c Sun Jan 18 20:40:08 2015 (r277345) @@ -185,7 +185,7 @@ static int mv88e1xxx_set_loopback(struct on ? BMCR_LOOPBACK : 0); } -static int mv88e1xxx_get_link_status(struct cphy *cphy, int *link_ok, +static int mv88e1xxx_get_link_status(struct cphy *cphy, int *link_state, int *speed, int *duplex, int *fc) { u32 status; @@ -206,8 +206,9 @@ static int mv88e1xxx_get_link_status(str else sp = SPEED_1000; } - if (link_ok) - *link_ok = (status & V_PSSR_LINK) != 0; + if (link_state) + *link_state = status & V_PSSR_LINK ? PHY_LINK_UP : + PHY_LINK_DOWN; if (speed) *speed = sp; if (duplex) Modified: stable/8/sys/dev/cxgb/common/cxgb_t3_hw.c ============================================================================== --- stable/8/sys/dev/cxgb/common/cxgb_t3_hw.c Sun Jan 18 20:39:24 2015 (r277344) +++ stable/8/sys/dev/cxgb/common/cxgb_t3_hw.c Sun Jan 18 20:40:08 2015 (r277345) @@ -1520,7 +1520,7 @@ static void t3_clear_faults(adapter_t *a */ void t3_link_changed(adapter_t *adapter, int port_id) { - int link_ok, speed, duplex, fc, link_fault; + int link_ok, speed, duplex, fc, link_fault, link_state; struct port_info *pi = adap2pinfo(adapter, port_id); struct cphy *phy = &pi->phy; struct cmac *mac = &pi->mac; @@ -1532,7 +1532,14 @@ void t3_link_changed(adapter_t *adapter, fc = lc->fc; link_fault = 0; - phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); + phy->ops->get_link_status(phy, &link_state, &speed, &duplex, &fc); + link_ok = (link_state == PHY_LINK_UP); + if (link_state != PHY_LINK_PARTIAL) + phy->rst = 0; + else if (++phy->rst == 3) { + phy->ops->reset(phy, 0); + phy->rst = 0; + } if (link_ok == 0) pi->link_fault = LF_NO; Modified: stable/8/sys/dev/cxgb/common/cxgb_tn1010.c ============================================================================== --- stable/8/sys/dev/cxgb/common/cxgb_tn1010.c Sun Jan 18 20:39:24 2015 (r277344) +++ stable/8/sys/dev/cxgb/common/cxgb_tn1010.c Sun Jan 18 20:40:08 2015 (r277345) @@ -129,7 +129,7 @@ static int tn1010_advertise(struct cphy ADVERTISE_LOOP_TIMING); } -static int tn1010_get_link_status(struct cphy *phy, int *link_ok, +static int tn1010_get_link_status(struct cphy *phy, int *link_state, int *speed, int *duplex, int *fc) { unsigned int status, lpa, adv; @@ -139,8 +139,9 @@ static int tn1010_get_link_status(struct if (err) return err; - if (link_ok) - *link_ok = (status & F_LINK_STAT) != 0; + if (link_state) + *link_state = status & F_LINK_STAT ? PHY_LINK_UP : + PHY_LINK_DOWN; if (G_ANEG_STAT(status) == ANEG_COMPLETE) { sp = (status & F_ANEG_SPEED_1G) ? SPEED_1000 : SPEED_10000; Modified: stable/8/sys/dev/cxgb/common/cxgb_vsc8211.c ============================================================================== --- stable/8/sys/dev/cxgb/common/cxgb_vsc8211.c Sun Jan 18 20:39:24 2015 (r277344) +++ stable/8/sys/dev/cxgb/common/cxgb_vsc8211.c Sun Jan 18 20:40:08 2015 (r277345) @@ -129,7 +129,7 @@ static int vsc8211_autoneg_restart(struc BMCR_ANRESTART); } -static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok, +static int vsc8211_get_link_status(struct cphy *cphy, int *link_state, int *speed, int *duplex, int *fc) { unsigned int bmcr, status, lpa, adv; @@ -141,7 +141,7 @@ static int vsc8211_get_link_status(struc if (err) return err; - if (link_ok) { + if (link_state) { /* * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it * once more to get the current link state. @@ -150,7 +150,8 @@ static int vsc8211_get_link_status(struc err = mdio_read(cphy, 0, MII_BMSR, &status); if (err) return err; - *link_ok = (status & BMSR_LSTATUS) != 0; + *link_state = status & BMSR_LSTATUS ? PHY_LINK_UP : + PHY_LINK_DOWN; } if (!(bmcr & BMCR_ANENABLE)) { dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; @@ -201,7 +202,7 @@ static int vsc8211_get_link_status(struc return 0; } -static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_ok, +static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_state, int *speed, int *duplex, int *fc) { unsigned int bmcr, status, lpa, adv; @@ -213,7 +214,7 @@ static int vsc8211_get_link_status_fiber if (err) return err; - if (link_ok) { + if (link_state) { /* * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it * once more to get the current link state. @@ -222,7 +223,8 @@ static int vsc8211_get_link_status_fiber err = mdio_read(cphy, 0, MII_BMSR, &status); if (err) return err; - *link_ok = (status & BMSR_LSTATUS) != 0; + *link_state = status & BMSR_LSTATUS ? PHY_LINK_UP : + PHY_LINK_DOWN; } if (!(bmcr & BMCR_ANENABLE)) { dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; Modified: stable/8/sys/dev/cxgb/cxgb_main.c ============================================================================== --- stable/8/sys/dev/cxgb/cxgb_main.c Sun Jan 18 20:39:24 2015 (r277344) +++ stable/8/sys/dev/cxgb/cxgb_main.c Sun Jan 18 20:40:08 2015 (r277345) @@ -2293,7 +2293,8 @@ check_link_status(void *arg, int pending t3_link_changed(sc, pi->port_id); - if (pi->link_fault || !(pi->phy.caps & SUPPORTED_LINK_IRQ)) + if (pi->link_fault || !(pi->phy.caps & SUPPORTED_LINK_IRQ) || + pi->link_config.link_ok == 0) callout_reset(&pi->link_check_ch, hz, link_check_callout, pi); } From owner-svn-src-stable-8@FreeBSD.ORG Mon Jan 19 07:16:24 2015 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 5752B900; Mon, 19 Jan 2015 07:16:24 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 382A8EEC; Mon, 19 Jan 2015 07:16:24 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t0J7GOiO045341; Mon, 19 Jan 2015 07:16:24 GMT (envelope-from hselasky@FreeBSD.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t0J7GML8045334; Mon, 19 Jan 2015 07:16:22 GMT (envelope-from hselasky@FreeBSD.org) Message-Id: <201501190716.t0J7GML8045334@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: hselasky set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky Date: Mon, 19 Jan 2015 07:16:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r277367 - in stable/8/sys/dev/usb: . quirk storage X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Jan 2015 07:16:24 -0000 Author: hselasky Date: Mon Jan 19 07:16:22 2015 New Revision: 277367 URL: https://svnweb.freebsd.org/changeset/base/277367 Log: MFC r239237, r242628 and r277044: - Add the UQ_MSC_NO_PREVENT_ALLOW quirk to handle devices that do not support the 'PREVENT/ALLOW MEDIUM REMOVAL' SCSI command. - Improve auto-quirks detection for certain Kingston memory sticks. - Increase the maximum number of dynamic USB quirks. USB memory stick devices which don't support the synchronize cache SCSI command are likely to also not support the prevent-allow medium removal SCSI command. Modified: stable/8/sys/dev/usb/quirk/usb_quirk.c stable/8/sys/dev/usb/quirk/usb_quirk.h stable/8/sys/dev/usb/storage/umass.c stable/8/sys/dev/usb/usb_freebsd.h stable/8/sys/dev/usb/usb_msctest.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/dev/ (props changed) stable/8/sys/dev/usb/ (props changed) Modified: stable/8/sys/dev/usb/quirk/usb_quirk.c ============================================================================== --- stable/8/sys/dev/usb/quirk/usb_quirk.c Mon Jan 19 07:14:36 2015 (r277366) +++ stable/8/sys/dev/usb/quirk/usb_quirk.c Mon Jan 19 07:16:22 2015 (r277367) @@ -397,6 +397,7 @@ static struct usb_quirk_entry usb_quirks UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN), USB_QUIRK(SONY, PORTABLE_HDD_V2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI), + USB_QUIRK(STMICRO, ST72682, 0x0000, 0xffff, UQ_MSC_NO_PREVENT_ALLOW), USB_QUIRK(SUPERTOP, IDE, 0x0000, 0xffff, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_SYNC_CACHE), USB_QUIRK(SUPERTOP, FLASHDRIVE, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY, @@ -523,6 +524,7 @@ static const char *usb_quirk_str[USB_QUI [UQ_MSC_NO_GETMAXLUN] = "UQ_MSC_NO_GETMAXLUN", [UQ_MSC_NO_INQUIRY] = "UQ_MSC_NO_INQUIRY", [UQ_MSC_NO_INQUIRY_EVPD] = "UQ_MSC_NO_INQUIRY_EVPD", + [UQ_MSC_NO_PREVENT_ALLOW] = "UQ_MSC_NO_PREVENT_ALLOW", [UQ_MSC_NO_SYNC_CACHE] = "UQ_MSC_NO_SYNC_CACHE", [UQ_MSC_SHUTTLE_INIT] = "UQ_MSC_SHUTTLE_INIT", [UQ_MSC_ALT_IFACE_1] = "UQ_MSC_ALT_IFACE_1", Modified: stable/8/sys/dev/usb/quirk/usb_quirk.h ============================================================================== --- stable/8/sys/dev/usb/quirk/usb_quirk.h Mon Jan 19 07:14:36 2015 (r277366) +++ stable/8/sys/dev/usb/quirk/usb_quirk.h Mon Jan 19 07:16:22 2015 (r277367) @@ -75,6 +75,7 @@ enum { UQ_MSC_NO_GETMAXLUN, /* does not support get max LUN */ UQ_MSC_NO_INQUIRY, /* fake generic inq response */ UQ_MSC_NO_INQUIRY_EVPD, /* does not support inq EVPD */ + UQ_MSC_NO_PREVENT_ALLOW, /* does not support medium removal */ UQ_MSC_NO_SYNC_CACHE, /* does not support sync cache */ UQ_MSC_SHUTTLE_INIT, /* requires Shuttle init sequence */ UQ_MSC_ALT_IFACE_1, /* switch to alternate interface 1 */ Modified: stable/8/sys/dev/usb/storage/umass.c ============================================================================== --- stable/8/sys/dev/usb/storage/umass.c Mon Jan 19 07:14:36 2015 (r277366) +++ stable/8/sys/dev/usb/storage/umass.c Mon Jan 19 07:16:22 2015 (r277367) @@ -371,6 +371,8 @@ typedef uint8_t (umass_transform_t)(stru * result. */ #define NO_SYNCHRONIZE_CACHE 0x4000 + /* Device does not support 'PREVENT/ALLOW MEDIUM REMOVAL'. */ +#define NO_PREVENT_ALLOW 0x8000 struct umass_softc { @@ -841,6 +843,8 @@ umass_probe_proto(device_t dev, struct u quirks |= NO_INQUIRY; if (usb_test_quirk(uaa, UQ_MSC_NO_INQUIRY_EVPD)) quirks |= NO_INQUIRY_EVPD; + if (usb_test_quirk(uaa, UQ_MSC_NO_PREVENT_ALLOW)) + quirks |= NO_PREVENT_ALLOW; if (usb_test_quirk(uaa, UQ_MSC_NO_SYNC_CACHE)) quirks |= NO_SYNCHRONIZE_CACHE; if (usb_test_quirk(uaa, UQ_MSC_SHUTTLE_INIT)) @@ -2376,6 +2380,13 @@ umass_cam_action(struct cam_sim *sim, un if (sc->sc_quirks & FORCE_SHORT_INQUIRY) { ccb->csio.dxfer_len = SHORT_INQUIRY_LENGTH; } + } else if (sc->sc_transfer.cmd_data[0] == PREVENT_ALLOW) { + if (sc->sc_quirks & NO_PREVENT_ALLOW) { + ccb->csio.scsi_status = SCSI_STATUS_OK; + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + goto done; + } } else if (sc->sc_transfer.cmd_data[0] == SYNCHRONIZE_CACHE) { if (sc->sc_quirks & NO_SYNCHRONIZE_CACHE) { ccb->csio.scsi_status = SCSI_STATUS_OK; Modified: stable/8/sys/dev/usb/usb_freebsd.h ============================================================================== --- stable/8/sys/dev/usb/usb_freebsd.h Mon Jan 19 07:14:36 2015 (r277366) +++ stable/8/sys/dev/usb/usb_freebsd.h Mon Jan 19 07:16:22 2015 (r277367) @@ -63,7 +63,7 @@ #define USB_EP0_BUFSIZE 1024 /* bytes */ #define USB_CS_RESET_LIMIT 20 /* failures = 20 * 50 ms = 1sec */ -#define USB_MAX_AUTO_QUIRK 4 /* maximum number of dynamic quirks */ +#define USB_MAX_AUTO_QUIRK 8 /* maximum number of dynamic quirks */ typedef uint32_t usb_timeout_t; /* milliseconds */ typedef uint32_t usb_frlength_t; /* bytes */ Modified: stable/8/sys/dev/usb/usb_msctest.c ============================================================================== --- stable/8/sys/dev/usb/usb_msctest.c Mon Jan 19 07:14:36 2015 (r277366) +++ stable/8/sys/dev/usb/usb_msctest.c Mon Jan 19 07:16:22 2015 (r277367) @@ -104,6 +104,8 @@ static uint8_t scsi_sync_cache[] = { 0x3 0x00, 0x00, 0x00, 0x00 }; static uint8_t scsi_request_sense[] = { 0x03, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static uint8_t scsi_read_capacity[] = { 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; #define BULK_SIZE 64 /* dummy */ #define ERR_CSW_FAILED -1 @@ -648,7 +650,7 @@ usb_msc_auto_quirk(struct usb_device *ud } is_no_direct = 1; - for (timeout = 4; timeout; timeout--) { + for (timeout = 4; timeout != 0; timeout--) { err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry), USB_MS_HZ); @@ -677,7 +679,9 @@ usb_msc_auto_quirk(struct usb_device *ud if (err != ERR_CSW_FAILED) goto error; } + timeout = 1; +retry_sync_cache: err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, &scsi_sync_cache, sizeof(scsi_sync_cache), USB_MS_HZ); @@ -687,9 +691,49 @@ usb_msc_auto_quirk(struct usb_device *ud if (err != ERR_CSW_FAILED) goto error; - DPRINTF("Device doesn't handle synchronize cache\n"); + DPRINTF("Device doesn't handle synchronize cache " + "and prevent allow medium removal\n"); usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE); + usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW); + } else { + + /* + * Certain Kingston memory sticks fail the first + * read capacity after a synchronize cache command + * has been issued. Disable the synchronize cache + * command for such devices. + */ + + err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8, + &scsi_read_capacity, sizeof(scsi_read_capacity), + USB_MS_HZ); + + if (err != 0) { + if (err != ERR_CSW_FAILED) + goto error; + + err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8, + &scsi_read_capacity, sizeof(scsi_read_capacity), + USB_MS_HZ); + + if (err == 0) { + if (timeout--) + goto retry_sync_cache; + + DPRINTF("Device most likely doesn't " + "handle synchronize cache nor" + "prevent allow medium removal\n"); + + usbd_add_dynamic_quirk(udev, + UQ_MSC_NO_SYNC_CACHE); + usbd_add_dynamic_quirk(udev, + UQ_MSC_NO_PREVENT_ALLOW); + } else { + if (err != ERR_CSW_FAILED) + goto error; + } + } } /* clear sense status of any failed commands on the device */ @@ -728,6 +772,7 @@ error: DPRINTF("Device did not respond, enabling all quirks\n"); usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE); + usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW); usbd_add_dynamic_quirk(udev, UQ_MSC_NO_TEST_UNIT_READY); /* Need to re-enumerate the device */