From nobody Thu Mar 03 14:41:48 2022 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id CB8F719EC691; Thu, 3 Mar 2022 14:41:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4K8YbJ41xGz3h8X; Thu, 3 Mar 2022 14:41:48 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1646318508; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=GWh5c9GlCV6dovbquxqIR4pZnp1p6Qn2vjz1+kl1KsQ=; b=ik5Ks3MQiNLsDLlhSKW9+a9HOL4gJPlE+36MFAGbLyLf7ATicR22ixqfpd2O5II/LmuT15 LP3XE4HwkwITNiaIeobzc23ak4oChu+xbj/jBDUqxM6dpPCu0Tmd6ixo/YEFNx6WwOFqZq 4usbclfKZzcoprCdUaFG4DYua8tUayNT7Euzfe7M3e8bRqRmWxA0Gsc8ZBpDDPCwOryIiD zlA13glzkvhNikfrarav4FoRZlcet3OKLL5AxRzZCuIyXV3WJ0f2j2SrCgsMarFdG58sU4 UhI9z5z8x7smUbGWmd7/htsQg3fw+WN2E2y/gHTKAne+Qzj9GG4X+adQifEyDA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 6BDCC1984B; Thu, 3 Mar 2022 14:41:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 223Efm4I018347; Thu, 3 Mar 2022 14:41:48 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 223Efmm3018346; Thu, 3 Mar 2022 14:41:48 GMT (envelope-from git) Date: Thu, 3 Mar 2022 14:41:48 GMT Message-Id: <202203031441.223Efmm3018346@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Hans Petter Selasky Subject: git: cf912859d228 - stable/13 - usb(4): Automagically apply all quirks for USB mass storage devices. List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: hselasky X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: cf912859d228b41ef62b4233cc198a1a9e4ece31 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1646318508; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=GWh5c9GlCV6dovbquxqIR4pZnp1p6Qn2vjz1+kl1KsQ=; b=Xkr61u4Cb8njXW1kwYfed1x3677mD68p6T0uIo5j+ao/oaXZ0UcreJkU8lzm7o4uz6ZvfD lWb0MAmrlh5+2sIvD8UwODAwudG1Vtiq4Kr6FAooI8o15+5y8G+7dP4U9C+szfdrrGFmw3 kaMO7bkrUh4XZiguG6Pv+IKHuwA5Phjm2/o017cKI9eyc0Py0/T8VelPk4dmOeu11pu3lw obXY8xTjrEfFqySSqWmA6ld1rHT7x4y1PGfqiaVRBrdcnHap8GT4qRWnQBi4XgzYH+nTYx 6f9XK7OyQKH/L6BEl0DgDlXvewQZb1DiE7zExI7nY8p9v3w16espsbIvX8s6+g== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1646318508; a=rsa-sha256; cv=none; b=ZCFUoo0ZxZ+JVEkH/zXDM1RMcztjGII6Sd3GAO633OaZPR4Ra4JnUguPf2GsqvP+8dgchE kMJEc+1PEKRCI0l76buwS+XDdkXZWOzTQ/Y3C1OjSQm2mulNX5Mh9tlU39/0DDWC0nvi/j czy9CgFpoMER6EI+DHRCvbZ3t15ZV5EmbGUbx3Q5XkOy9c4OPA5gR99zmg/H7b6Rp0F/Sc MDAjzEtplEEJsBVea7zN3OuMWDiLusONJmeSg9Sj+mMoJiPs5x8VSe1twXAiDBp3lzUigE F31QdxKEnR53UbQcSNwkCvXxAVFAzlN2CQim8nH+DFCo8RPqhtfz1zlGZawdQQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by hselasky: URL: https://cgit.FreeBSD.org/src/commit/?id=cf912859d228b41ef62b4233cc198a1a9e4ece31 commit cf912859d228b41ef62b4233cc198a1a9e4ece31 Author: Hans Petter Selasky AuthorDate: 2022-02-21 08:24:28 +0000 Commit: Hans Petter Selasky CommitDate: 2022-03-03 14:41:12 +0000 usb(4): Automagically apply all quirks for USB mass storage devices. Currently there are five quirks the USB stack tries to automagically detect: - UQ_MSC_NO_PREVENT_ALLOW - UQ_MSC_NO_SYNC_CACHE - UQ_MSC_NO_TEST_UNIT_READY - UQ_MSC_NO_GETMAXLUN - UQ_MSC_NO_START_STOP If any of the quirks above are set, no further quirks will be probed. If any of the USB mass storage tests fail, the USB device is re-enumerated as a last resort to clear any error states from the device. Then the USB stack will try to probe and attach the umass device passing the detected quirks. While at it give more details in dmesg about what is going on. Tested by: several Submitted by: Idwer Vollering Differential Revision: https://reviews.freebsd.org/D30919 Sponsored by: NVIDIA Networking (cherry picked from commit 7520b88860d7a79432e12ffcc47056844518bb62) --- sys/dev/usb/storage/umass.c | 7 +++ sys/dev/usb/usb_device.c | 5 +- sys/dev/usb/usb_msctest.c | 133 +++++++++++++++++++++++++++----------------- sys/dev/usb/usb_msctest.h | 4 +- 4 files changed, 96 insertions(+), 53 deletions(-) diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c index 8260226e5d12..b8b502494264 100644 --- a/sys/dev/usb/storage/umass.c +++ b/sys/dev/usb/storage/umass.c @@ -2294,6 +2294,13 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb) xpt_done(ccb); goto done; } + } else if (sc->sc_transfer.cmd_data[0] == START_STOP_UNIT) { + if (sc->sc_quirks & NO_START_STOP) { + ccb->csio.scsi_status = SCSI_STATUS_OK; + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + goto done; + } } umass_command_start(sc, dir, ccb->csio.data_ptr, ccb->csio.dxfer_len, diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index 322e4f5401ba..8d0e7961f675 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -2047,13 +2047,16 @@ repeat_set_config: } #if USB_HAVE_MSCTEST if (set_config_failed == 0 && config_index == 0 && + usb_test_quirk(&uaa, UQ_MSC_NO_START_STOP) == 0 && + usb_test_quirk(&uaa, UQ_MSC_NO_PREVENT_ALLOW) == 0 && usb_test_quirk(&uaa, UQ_MSC_NO_SYNC_CACHE) == 0 && + usb_test_quirk(&uaa, UQ_MSC_NO_TEST_UNIT_READY) == 0 && usb_test_quirk(&uaa, UQ_MSC_NO_GETMAXLUN) == 0) { /* * Try to figure out if there are any MSC quirks we * should apply automatically: */ - err = usb_msc_auto_quirk(udev, 0); + err = usb_msc_auto_quirk(udev, 0, &uaa); if (err != 0) { set_config_failed = 1; diff --git a/sys/dev/usb/usb_msctest.c b/sys/dev/usb/usb_msctest.c index 0fffd99a73c4..5dcf8d151119 100644 --- a/sys/dev/usb/usb_msctest.c +++ b/sys/dev/usb/usb_msctest.c @@ -2,7 +2,8 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2008,2011 Hans Petter Selasky. All rights reserved. + * Copyright (c) 2008-2022 Hans Petter Selasky. + * Copyright (c) 2021-2022 Idwer Vollering. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,9 +30,6 @@ /* * The following file contains code that will detect USB autoinstall * disks. - * - * TODO: Potentially we could add code to automatically detect USB - * mass storage quirks for not supported SCSI commands! */ #ifdef USB_GLOBAL_INCLUDE_FILE @@ -97,7 +95,8 @@ enum { static uint8_t scsi_test_unit_ready[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static uint8_t scsi_inquiry[] = { 0x12, 0x00, 0x00, 0x00, SCSI_INQ_LEN, 0x00 }; static uint8_t scsi_rezero_init[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static uint8_t scsi_start_stop_unit[] = { 0x1b, 0x00, 0x00, 0x00, 0x02, 0x00 }; +static uint8_t scsi_start_unit[] = { 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00 }; +static uint8_t scsi_stop_unit[] = { 0x1b, 0x00, 0x00, 0x00, 0x02, 0x00 }; static uint8_t scsi_ztestor_eject[] = { 0x85, 0x01, 0x01, 0x01, 0x18, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00 }; static uint8_t scsi_cmotech_eject[] = { 0xff, 0x52, 0x44, 0x45, 0x56, 0x43, @@ -759,28 +758,49 @@ usb_msc_get_max_lun(struct usb_device *udev, uint8_t iface_index) return (buf); } +#define USB_ADD_QUIRK(udev, any, which) do { \ + if (usb_get_manufacturer(udev) != NULL && usb_get_product(udev) != NULL) { \ + DPRINTFN(0, #which " set for USB mass storage device %s %s (0x%04x:0x%04x)\n", \ + usb_get_manufacturer(udev), \ + usb_get_product(udev), \ + UGETW(udev->ddesc.idVendor), \ + UGETW(udev->ddesc.idProduct)); \ + } else { \ + DPRINTFN(0, #which " set for USB mass storage device, 0x%04x:0x%04x\n", \ + UGETW(udev->ddesc.idVendor), \ + UGETW(udev->ddesc.idProduct)); \ + } \ + usbd_add_dynamic_quirk(udev, which); \ + any = 1; \ +} while (0) + usb_error_t -usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index) +usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index, + const struct usb_attach_arg *uaa) { struct bbb_transfer *sc; uint8_t timeout; uint8_t is_no_direct; uint8_t sid_type; + uint8_t any_quirk; int err; sc = bbb_attach(udev, iface_index, UICLASS_MASS); if (sc == NULL) return (0); + any_quirk = 0; + /* * Some devices need a delay after that the configuration * value is set to function properly: */ usb_pause_mtx(NULL, hz); - if (usb_msc_get_max_lun(udev, iface_index) == 0) { + if (usb_test_quirk(uaa, UQ_MSC_NO_GETMAXLUN) == 0 && + usb_msc_get_max_lun(udev, iface_index) == 0) { DPRINTF("Device has only got one LUN.\n"); - usbd_add_dynamic_quirk(udev, UQ_MSC_NO_GETMAXLUN); + USB_ADD_QUIRK(udev, any_quirk, UQ_MSC_NO_GETMAXLUN); } is_no_direct = 1; @@ -807,37 +827,40 @@ usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index) goto done; } - err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, - &scsi_test_unit_ready, sizeof(scsi_test_unit_ready), - USB_MS_HZ); + if (usb_test_quirk(uaa, UQ_MSC_NO_TEST_UNIT_READY) == 0) { + err = bbb_command_start(sc, DIR_NONE, 0, NULL, 0, + &scsi_test_unit_ready, sizeof(scsi_test_unit_ready), + USB_MS_HZ); - if (err != 0) { - if (err != ERR_CSW_FAILED) - goto error; - DPRINTF("Test unit ready failed\n"); + if (err != 0) { + if (err != ERR_CSW_FAILED) + goto error; + USB_ADD_QUIRK(udev, any_quirk, UQ_MSC_NO_TEST_UNIT_READY); + } } - err = bbb_command_start(sc, DIR_OUT, 0, NULL, 0, - &scsi_prevent_removal, sizeof(scsi_prevent_removal), - USB_MS_HZ); - - if (err == 0) { - err = bbb_command_start(sc, DIR_OUT, 0, NULL, 0, - &scsi_allow_removal, sizeof(scsi_allow_removal), + if (usb_test_quirk(uaa, UQ_MSC_NO_PREVENT_ALLOW) == 0) { + err = bbb_command_start(sc, DIR_NONE, 0, NULL, 0, + &scsi_prevent_removal, sizeof(scsi_prevent_removal), USB_MS_HZ); - } - if (err != 0) { - if (err != ERR_CSW_FAILED) - goto error; - DPRINTF("Device doesn't handle prevent and allow removal\n"); - usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW); + if (err == 0) { + err = bbb_command_start(sc, DIR_NONE, 0, NULL, 0, + &scsi_allow_removal, sizeof(scsi_allow_removal), + USB_MS_HZ); + } + + if (err != 0) { + if (err != ERR_CSW_FAILED) + goto error; + USB_ADD_QUIRK(udev, any_quirk, UQ_MSC_NO_PREVENT_ALLOW); + } } timeout = 1; retry_sync_cache: - err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, + err = bbb_command_start(sc, DIR_NONE, 0, NULL, 0, &scsi_sync_cache, sizeof(scsi_sync_cache), USB_MS_HZ); @@ -845,9 +868,7 @@ retry_sync_cache: if (err != ERR_CSW_FAILED) goto error; - DPRINTF("Device doesn't handle synchronize cache\n"); - - usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE); + USB_ADD_QUIRK(udev, any_quirk, UQ_MSC_NO_SYNC_CACHE); } else { /* * Certain Kingston memory sticks fail the first @@ -872,11 +893,7 @@ retry_sync_cache: if (timeout--) goto retry_sync_cache; - DPRINTF("Device most likely doesn't " - "handle synchronize cache\n"); - - usbd_add_dynamic_quirk(udev, - UQ_MSC_NO_SYNC_CACHE); + USB_ADD_QUIRK(udev, any_quirk, UQ_MSC_NO_SYNC_CACHE); } else { if (err != ERR_CSW_FAILED) goto error; @@ -884,6 +901,18 @@ retry_sync_cache: } } + if (usb_test_quirk(uaa, UQ_MSC_NO_START_STOP) == 0) { + err = bbb_command_start(sc, DIR_NONE, 0, NULL, 0, + &scsi_start_unit, sizeof(scsi_start_unit), + USB_MS_HZ); + + if (err != 0) { + if (err != ERR_CSW_FAILED) + goto error; + USB_ADD_QUIRK(udev, any_quirk, UQ_MSC_NO_START_STOP); + } + } + /* clear sense status of any failed commands on the device */ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, @@ -907,24 +936,28 @@ retry_sync_cache: if (err != ERR_CSW_FAILED) goto error; } + goto done; +error: + /* Apply most quirks */ + USB_ADD_QUIRK(udev, any_quirk, UQ_MSC_NO_SYNC_CACHE); + USB_ADD_QUIRK(udev, any_quirk, UQ_MSC_NO_PREVENT_ALLOW); + USB_ADD_QUIRK(udev, any_quirk, UQ_MSC_NO_TEST_UNIT_READY); + USB_ADD_QUIRK(udev, any_quirk, UQ_MSC_NO_START_STOP); done: bbb_detach(sc); - return (0); -error: - bbb_detach(sc); - - 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); + if (any_quirk) { + /* Unconfigure device, to clear software data toggle. */ + usbd_set_config_index(udev, USB_UNCONFIG_INDEX); - /* Need to re-enumerate the device */ - usbd_req_re_enumerate(udev, NULL); + /* Need to re-enumerate the device to clear its state. */ + usbd_req_re_enumerate(udev, NULL); + return (USB_ERR_STALLED); + } - return (USB_ERR_STALLED); + /* No quirks were added, continue as usual. */ + return (0); } usb_error_t @@ -944,7 +977,7 @@ usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method) USB_MS_HZ); DPRINTF("Test unit ready status: %s\n", usbd_errstr(err)); err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, - &scsi_start_stop_unit, sizeof(scsi_start_stop_unit), + &scsi_stop_unit, sizeof(scsi_stop_unit), USB_MS_HZ); break; case MSC_EJECT_REZERO: diff --git a/sys/dev/usb/usb_msctest.h b/sys/dev/usb/usb_msctest.h index 6b5d3283738b..ba4e094bab60 100644 --- a/sys/dev/usb/usb_msctest.h +++ b/sys/dev/usb/usb_msctest.h @@ -2,7 +2,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. + * Copyright (c) 2008-2022 Hans Petter Selasky. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,7 +44,7 @@ int usb_iface_is_cdrom(struct usb_device *udev, usb_error_t usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method); usb_error_t usb_msc_auto_quirk(struct usb_device *udev, - uint8_t iface_index); + uint8_t iface_index, const struct usb_attach_arg *uaa); usb_error_t usb_msc_read_10(struct usb_device *udev, uint8_t iface_index, uint32_t lba, uint32_t blocks, void *buffer);