USB/Thunderbolt fixes for 6.18-rc8

Here are some last-minutes USB and Thunderbolt driver fixes and new
 device ids for 6.18-rc8.  Included in here are:
   - usb storage quirk fixup
   - xhci driver fixes for reported issues
   - usb gadget driver fixes
   - dwc3 driver fixes
   - UAS driver fixup
   - thunderbolt new device ids
   - usb-serial driver new ids
 
 All of these have been in linux-next with no reported issues, many for
 many weeks.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCaSnO0w8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ymqyACgvNvTnpfj8lx0L9aESj6Hra0UZ20AoKlYRFW1
 gAVcF4Wafnu7ehjAITXL
 =cH0/
 -----END PGP SIGNATURE-----

Merge tag 'usb-6.18-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB/Thunderbolt fixes from Greg KH:
 "Here are some last-minutes USB and Thunderbolt driver fixes and new
  device ids for 6.18-rc8. Included in here are:

   - usb storage quirk fixup

   - xhci driver fixes for reported issues

   - usb gadget driver fixes

   - dwc3 driver fixes

   - UAS driver fixup

   - thunderbolt new device ids

   - usb-serial driver new ids

  All of these have been in linux-next with no reported issues, many for
  many weeks"

* tag 'usb-6.18-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (21 commits)
  usb: gadget: renesas_usbf: Handle devm_pm_runtime_enable() errors
  USB: storage: Remove subclass and protocol overrides from Novatek quirk
  usb: uas: fix urb unmapping issue when the uas device is remove during ongoing data transfer
  usb: dwc3: Fix race condition between concurrent dwc3_remove_requests() call paths
  xhci: dbgtty: fix device unregister
  usb: storage: sddr55: Reject out-of-bound new_pba
  USB: serial: option: add support for Rolling RW101R-GL
  usb: typec: ucsi: psy: Set max current to zero when disconnected
  usb: gadget: f_eem: Fix memory leak in eem_unwrap
  usb: dwc3: pci: Sort out the Intel device IDs
  usb: dwc3: pci: add support for the Intel Nova Lake -S
  drivers/usb/dwc3: fix PCI parent check
  usb: storage: Fix memory leak in USB bulk transport
  xhci: sideband: Fix race condition in sideband unregister
  xhci: dbgtty: Fix data corruption when transmitting data form DbC to host
  xhci: fix stale flag preventig URBs after link state error is cleared
  USB: serial: ftdi_sio: add support for u-blox EVK-M101
  usb: cdns3: Fix double resource release in cdns3_pci_probe
  usb: gadget: udc: fix use-after-free in usb_gadget_state_work
  usb: renesas_usbhs: Fix synchronous external abort on unbind
  ...
This commit is contained in:
Linus Torvalds 2025-11-28 09:12:40 -08:00
commit 5d324e5159
25 changed files with 228 additions and 108 deletions

View File

@ -1538,6 +1538,8 @@ static struct pci_device_id nhi_ids[] = {
.driver_data = (kernel_ulong_t)&icl_nhi_ops }, .driver_data = (kernel_ulong_t)&icl_nhi_ops },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_P_NHI1), { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_P_NHI1),
.driver_data = (kernel_ulong_t)&icl_nhi_ops }, .driver_data = (kernel_ulong_t)&icl_nhi_ops },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_WCL_NHI0),
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI) }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI) },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI) }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI) },

View File

@ -75,6 +75,7 @@ extern const struct tb_nhi_ops icl_nhi_ops;
#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_BRIDGE 0x15ef #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_BRIDGE 0x15ef
#define PCI_DEVICE_ID_INTEL_ADL_NHI0 0x463e #define PCI_DEVICE_ID_INTEL_ADL_NHI0 0x463e
#define PCI_DEVICE_ID_INTEL_ADL_NHI1 0x466d #define PCI_DEVICE_ID_INTEL_ADL_NHI1 0x466d
#define PCI_DEVICE_ID_INTEL_WCL_NHI0 0x4d33
#define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI 0x5781 #define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI 0x5781
#define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI 0x5784 #define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI 0x5784
#define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HUB_80G_BRIDGE 0x5786 #define PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HUB_80G_BRIDGE 0x5786

View File

@ -98,10 +98,8 @@ static int cdns3_pci_probe(struct pci_dev *pdev,
wrap = pci_get_drvdata(func); wrap = pci_get_drvdata(func);
} else { } else {
wrap = kzalloc(sizeof(*wrap), GFP_KERNEL); wrap = kzalloc(sizeof(*wrap), GFP_KERNEL);
if (!wrap) { if (!wrap)
pci_disable_device(pdev);
return -ENOMEM; return -ENOMEM;
}
} }
res = wrap->dev_res; res = wrap->dev_res;
@ -160,7 +158,6 @@ static int cdns3_pci_probe(struct pci_dev *pdev,
/* register platform device */ /* register platform device */
wrap->plat_dev = platform_device_register_full(&plat_info); wrap->plat_dev = platform_device_register_full(&plat_info);
if (IS_ERR(wrap->plat_dev)) { if (IS_ERR(wrap->plat_dev)) {
pci_disable_device(pdev);
err = PTR_ERR(wrap->plat_dev); err = PTR_ERR(wrap->plat_dev);
kfree(wrap); kfree(wrap);
return err; return err;

View File

@ -25,6 +25,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_graph.h> #include <linux/of_graph.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/pci.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/devinfo.h> #include <linux/pinctrl/devinfo.h>
#include <linux/reset.h> #include <linux/reset.h>
@ -2241,7 +2242,7 @@ int dwc3_core_probe(const struct dwc3_probe_data *data)
dev_set_drvdata(dev, dwc); dev_set_drvdata(dev, dwc);
dwc3_cache_hwparams(dwc); dwc3_cache_hwparams(dwc);
if (!dwc->sysdev_is_parent && if (!dev_is_pci(dwc->sysdev) &&
DWC3_GHWPARAMS0_AWIDTH(dwc->hwparams.hwparams0) == 64) { DWC3_GHWPARAMS0_AWIDTH(dwc->hwparams.hwparams0) == 64) {
ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64)); ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64));
if (ret) if (ret)

View File

@ -21,40 +21,41 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/delay.h> #include <linux/delay.h>
#define PCI_DEVICE_ID_INTEL_BYT 0x0f37
#define PCI_DEVICE_ID_INTEL_MRFLD 0x119e
#define PCI_DEVICE_ID_INTEL_BSW 0x22b7
#define PCI_DEVICE_ID_INTEL_SPTLP 0x9d30
#define PCI_DEVICE_ID_INTEL_SPTH 0xa130
#define PCI_DEVICE_ID_INTEL_BXT 0x0aaa
#define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa
#define PCI_DEVICE_ID_INTEL_APL 0x5aaa
#define PCI_DEVICE_ID_INTEL_KBP 0xa2b0
#define PCI_DEVICE_ID_INTEL_CMLLP 0x02ee #define PCI_DEVICE_ID_INTEL_CMLLP 0x02ee
#define PCI_DEVICE_ID_INTEL_CMLH 0x06ee #define PCI_DEVICE_ID_INTEL_CMLH 0x06ee
#define PCI_DEVICE_ID_INTEL_BXT 0x0aaa
#define PCI_DEVICE_ID_INTEL_BYT 0x0f37
#define PCI_DEVICE_ID_INTEL_MRFLD 0x119e
#define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa
#define PCI_DEVICE_ID_INTEL_BSW 0x22b7
#define PCI_DEVICE_ID_INTEL_GLK 0x31aa #define PCI_DEVICE_ID_INTEL_GLK 0x31aa
#define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee
#define PCI_DEVICE_ID_INTEL_CNPH 0xa36e
#define PCI_DEVICE_ID_INTEL_CNPV 0xa3b0
#define PCI_DEVICE_ID_INTEL_ICLLP 0x34ee #define PCI_DEVICE_ID_INTEL_ICLLP 0x34ee
#define PCI_DEVICE_ID_INTEL_EHL 0x4b7e
#define PCI_DEVICE_ID_INTEL_TGPLP 0xa0ee
#define PCI_DEVICE_ID_INTEL_TGPH 0x43ee #define PCI_DEVICE_ID_INTEL_TGPH 0x43ee
#define PCI_DEVICE_ID_INTEL_JSP 0x4dee
#define PCI_DEVICE_ID_INTEL_WCL 0x4d7e
#define PCI_DEVICE_ID_INTEL_ADL 0x460e #define PCI_DEVICE_ID_INTEL_ADL 0x460e
#define PCI_DEVICE_ID_INTEL_ADL_PCH 0x51ee
#define PCI_DEVICE_ID_INTEL_ADLN 0x465e #define PCI_DEVICE_ID_INTEL_ADLN 0x465e
#define PCI_DEVICE_ID_INTEL_EHL 0x4b7e
#define PCI_DEVICE_ID_INTEL_WCL 0x4d7e
#define PCI_DEVICE_ID_INTEL_JSP 0x4dee
#define PCI_DEVICE_ID_INTEL_ADL_PCH 0x51ee
#define PCI_DEVICE_ID_INTEL_ADLN_PCH 0x54ee #define PCI_DEVICE_ID_INTEL_ADLN_PCH 0x54ee
#define PCI_DEVICE_ID_INTEL_ADLS 0x7ae1 #define PCI_DEVICE_ID_INTEL_APL 0x5aaa
#define PCI_DEVICE_ID_INTEL_RPL 0xa70e #define PCI_DEVICE_ID_INTEL_NVLS_PCH 0x6e6f
#define PCI_DEVICE_ID_INTEL_ARLH_PCH 0x777e
#define PCI_DEVICE_ID_INTEL_RPLS 0x7a61 #define PCI_DEVICE_ID_INTEL_RPLS 0x7a61
#define PCI_DEVICE_ID_INTEL_MTL 0x7e7e
#define PCI_DEVICE_ID_INTEL_ADLS 0x7ae1
#define PCI_DEVICE_ID_INTEL_MTLM 0x7eb1 #define PCI_DEVICE_ID_INTEL_MTLM 0x7eb1
#define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1 #define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1
#define PCI_DEVICE_ID_INTEL_MTLS 0x7f6f #define PCI_DEVICE_ID_INTEL_MTLS 0x7f6f
#define PCI_DEVICE_ID_INTEL_MTL 0x7e7e
#define PCI_DEVICE_ID_INTEL_ARLH_PCH 0x777e
#define PCI_DEVICE_ID_INTEL_TGL 0x9a15 #define PCI_DEVICE_ID_INTEL_TGL 0x9a15
#define PCI_DEVICE_ID_INTEL_SPTLP 0x9d30
#define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee
#define PCI_DEVICE_ID_INTEL_TGPLP 0xa0ee
#define PCI_DEVICE_ID_INTEL_SPTH 0xa130
#define PCI_DEVICE_ID_INTEL_KBP 0xa2b0
#define PCI_DEVICE_ID_INTEL_CNPH 0xa36e
#define PCI_DEVICE_ID_INTEL_CNPV 0xa3b0
#define PCI_DEVICE_ID_INTEL_RPL 0xa70e
#define PCI_DEVICE_ID_INTEL_PTLH 0xe332 #define PCI_DEVICE_ID_INTEL_PTLH 0xe332
#define PCI_DEVICE_ID_INTEL_PTLH_PCH 0xe37e #define PCI_DEVICE_ID_INTEL_PTLH_PCH 0xe37e
#define PCI_DEVICE_ID_INTEL_PTLU 0xe432 #define PCI_DEVICE_ID_INTEL_PTLU 0xe432
@ -412,40 +413,41 @@ static void dwc3_pci_remove(struct pci_dev *pci)
} }
static const struct pci_device_id dwc3_pci_id_table[] = { static const struct pci_device_id dwc3_pci_id_table[] = {
{ PCI_DEVICE_DATA(INTEL, BSW, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, BYT, &dwc3_pci_intel_byt_swnode) },
{ PCI_DEVICE_DATA(INTEL, MRFLD, &dwc3_pci_intel_mrfld_swnode) },
{ PCI_DEVICE_DATA(INTEL, CMLLP, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, CMLLP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, CMLH, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, CMLH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, SPTLP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, SPTH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, BXT, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, BXT, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, BYT, &dwc3_pci_intel_byt_swnode) },
{ PCI_DEVICE_DATA(INTEL, MRFLD, &dwc3_pci_intel_mrfld_swnode) },
{ PCI_DEVICE_DATA(INTEL, BXT_M, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, BXT_M, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, APL, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, BSW, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, KBP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, GLK, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, GLK, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, CNPLP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, CNPH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, CNPV, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, ICLLP, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, ICLLP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, EHL, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, TGPLP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, TGPH, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, TGPH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, JSP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, WCL, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, ADL, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, ADL, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, ADL_PCH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, ADLN, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, ADLN, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, EHL, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, WCL, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, JSP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, ADL_PCH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, ADLN_PCH, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, ADLN_PCH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, ADLS, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, APL, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, RPL, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, NVLS_PCH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, RPLS, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, RPLS, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, MTL, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, ADLS, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, MTLM, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, MTLM, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, MTLP, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, MTLP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, MTL, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, SPTLP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, CNPLP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, TGPLP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, SPTH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, KBP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, CNPH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, CNPV, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, RPL, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, PTLH, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, PTLH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, PTLH_PCH, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, PTLH_PCH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, PTLU, &dwc3_pci_intel_swnode) }, { PCI_DEVICE_DATA(INTEL, PTLU, &dwc3_pci_intel_swnode) },

View File

@ -94,6 +94,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
req->request.actual = 0; req->request.actual = 0;
req->request.status = -EINPROGRESS; req->request.status = -EINPROGRESS;
req->epnum = dep->number; req->epnum = dep->number;
req->status = DWC3_REQUEST_STATUS_QUEUED;
list_add_tail(&req->list, &dep->pending_list); list_add_tail(&req->list, &dep->pending_list);

View File

@ -228,6 +228,13 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
{ {
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
/*
* The request might have been processed and completed while the
* spinlock was released. Skip processing if already completed.
*/
if (req->status == DWC3_REQUEST_STATUS_COMPLETED)
return;
dwc3_gadget_del_and_unmap_request(dep, req, status); dwc3_gadget_del_and_unmap_request(dep, req, status);
req->status = DWC3_REQUEST_STATUS_COMPLETED; req->status = DWC3_REQUEST_STATUS_COMPLETED;

View File

@ -477,8 +477,13 @@ static int eem_unwrap(struct gether *port,
req->complete = eem_cmd_complete; req->complete = eem_cmd_complete;
req->zero = 1; req->zero = 1;
req->context = ctx; req->context = ctx;
if (usb_ep_queue(port->in_ep, req, GFP_ATOMIC)) if (usb_ep_queue(port->in_ep, req, GFP_ATOMIC)) {
DBG(cdev, "echo response queue fail\n"); DBG(cdev, "echo response queue fail\n");
kfree(ctx);
kfree(req->buf);
usb_ep_free_request(ep, req);
dev_kfree_skb_any(skb2);
}
break; break;
case 1: /* echo response */ case 1: /* echo response */

View File

@ -1126,8 +1126,13 @@ static void usb_gadget_state_work(struct work_struct *work)
void usb_gadget_set_state(struct usb_gadget *gadget, void usb_gadget_set_state(struct usb_gadget *gadget,
enum usb_device_state state) enum usb_device_state state)
{ {
unsigned long flags;
spin_lock_irqsave(&gadget->state_lock, flags);
gadget->state = state; gadget->state = state;
schedule_work(&gadget->work); if (!gadget->teardown)
schedule_work(&gadget->work);
spin_unlock_irqrestore(&gadget->state_lock, flags);
trace_usb_gadget_set_state(gadget, 0); trace_usb_gadget_set_state(gadget, 0);
} }
EXPORT_SYMBOL_GPL(usb_gadget_set_state); EXPORT_SYMBOL_GPL(usb_gadget_set_state);
@ -1361,6 +1366,8 @@ static void usb_udc_nop_release(struct device *dev)
void usb_initialize_gadget(struct device *parent, struct usb_gadget *gadget, void usb_initialize_gadget(struct device *parent, struct usb_gadget *gadget,
void (*release)(struct device *dev)) void (*release)(struct device *dev))
{ {
spin_lock_init(&gadget->state_lock);
gadget->teardown = false;
INIT_WORK(&gadget->work, usb_gadget_state_work); INIT_WORK(&gadget->work, usb_gadget_state_work);
gadget->dev.parent = parent; gadget->dev.parent = parent;
@ -1535,6 +1542,7 @@ EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
void usb_del_gadget(struct usb_gadget *gadget) void usb_del_gadget(struct usb_gadget *gadget)
{ {
struct usb_udc *udc = gadget->udc; struct usb_udc *udc = gadget->udc;
unsigned long flags;
if (!udc) if (!udc)
return; return;
@ -1548,6 +1556,13 @@ void usb_del_gadget(struct usb_gadget *gadget)
kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
sysfs_remove_link(&udc->dev.kobj, "gadget"); sysfs_remove_link(&udc->dev.kobj, "gadget");
device_del(&gadget->dev); device_del(&gadget->dev);
/*
* Set the teardown flag before flushing the work to prevent new work
* from being scheduled while we are cleaning up.
*/
spin_lock_irqsave(&gadget->state_lock, flags);
gadget->teardown = true;
spin_unlock_irqrestore(&gadget->state_lock, flags);
flush_work(&gadget->work); flush_work(&gadget->work);
ida_free(&gadget_id_numbers, gadget->id_number); ida_free(&gadget_id_numbers, gadget->id_number);
cancel_work_sync(&udc->vbus_work); cancel_work_sync(&udc->vbus_work);

View File

@ -3262,7 +3262,9 @@ static int usbf_probe(struct platform_device *pdev)
if (IS_ERR(udc->regs)) if (IS_ERR(udc->regs))
return PTR_ERR(udc->regs); return PTR_ERR(udc->regs);
devm_pm_runtime_enable(&pdev->dev); ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
return ret;
ret = pm_runtime_resume_and_get(&pdev->dev); ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0) if (ret < 0)
return ret; return ret;

View File

@ -114,6 +114,7 @@ struct dbc_port {
unsigned int tx_boundary; unsigned int tx_boundary;
bool registered; bool registered;
bool tx_running;
}; };
struct dbc_driver { struct dbc_driver {

View File

@ -47,7 +47,7 @@ dbc_kfifo_to_req(struct dbc_port *port, char *packet)
return len; return len;
} }
static int dbc_start_tx(struct dbc_port *port) static int dbc_do_start_tx(struct dbc_port *port)
__releases(&port->port_lock) __releases(&port->port_lock)
__acquires(&port->port_lock) __acquires(&port->port_lock)
{ {
@ -57,6 +57,8 @@ static int dbc_start_tx(struct dbc_port *port)
bool do_tty_wake = false; bool do_tty_wake = false;
struct list_head *pool = &port->write_pool; struct list_head *pool = &port->write_pool;
port->tx_running = true;
while (!list_empty(pool)) { while (!list_empty(pool)) {
req = list_entry(pool->next, struct dbc_request, list_pool); req = list_entry(pool->next, struct dbc_request, list_pool);
len = dbc_kfifo_to_req(port, req->buf); len = dbc_kfifo_to_req(port, req->buf);
@ -77,12 +79,25 @@ static int dbc_start_tx(struct dbc_port *port)
} }
} }
port->tx_running = false;
if (do_tty_wake && port->port.tty) if (do_tty_wake && port->port.tty)
tty_wakeup(port->port.tty); tty_wakeup(port->port.tty);
return status; return status;
} }
/* must be called with port->port_lock held */
static int dbc_start_tx(struct dbc_port *port)
{
lockdep_assert_held(&port->port_lock);
if (port->tx_running)
return -EBUSY;
return dbc_do_start_tx(port);
}
static void dbc_start_rx(struct dbc_port *port) static void dbc_start_rx(struct dbc_port *port)
__releases(&port->port_lock) __releases(&port->port_lock)
__acquires(&port->port_lock) __acquires(&port->port_lock)
@ -535,6 +550,12 @@ static void xhci_dbc_tty_unregister_device(struct xhci_dbc *dbc)
if (!port->registered) if (!port->registered)
return; return;
/*
* Hang up the TTY. This wakes up any blocked
* writers and causes subsequent writes to fail.
*/
tty_vhangup(port->port.tty);
tty_unregister_device(dbc_tty_driver, port->minor); tty_unregister_device(dbc_tty_driver, port->minor);
xhci_dbc_tty_exit_port(port); xhci_dbc_tty_exit_port(port);
port->registered = false; port->registered = false;

View File

@ -1985,6 +1985,7 @@ static void xhci_cavium_reset_phy_quirk(struct xhci_hcd *xhci)
static void handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event) static void handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event)
{ {
struct xhci_virt_device *vdev = NULL;
struct usb_hcd *hcd; struct usb_hcd *hcd;
u32 port_id; u32 port_id;
u32 portsc, cmd_reg; u32 portsc, cmd_reg;
@ -2016,6 +2017,9 @@ static void handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event)
goto cleanup; goto cleanup;
} }
if (port->slot_id)
vdev = xhci->devs[port->slot_id];
/* We might get interrupts after shared_hcd is removed */ /* We might get interrupts after shared_hcd is removed */
if (port->rhub == &xhci->usb3_rhub && xhci->shared_hcd == NULL) { if (port->rhub == &xhci->usb3_rhub && xhci->shared_hcd == NULL) {
xhci_dbg(xhci, "ignore port event for removed USB3 hcd\n"); xhci_dbg(xhci, "ignore port event for removed USB3 hcd\n");
@ -2038,10 +2042,11 @@ static void handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event)
usb_hcd_resume_root_hub(hcd); usb_hcd_resume_root_hub(hcd);
} }
if (hcd->speed >= HCD_USB3 && if (vdev && (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) {
(portsc & PORT_PLS_MASK) == XDEV_INACTIVE) { if (!(portsc & PORT_RESET))
if (port->slot_id && xhci->devs[port->slot_id]) vdev->flags |= VDEV_PORT_ERROR;
xhci->devs[port->slot_id]->flags |= VDEV_PORT_ERROR; } else if (vdev && portsc & PORT_RC) {
vdev->flags &= ~VDEV_PORT_ERROR;
} }
if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) { if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) {
@ -2099,7 +2104,7 @@ static void handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event)
* so the roothub behavior is consistent with external * so the roothub behavior is consistent with external
* USB 3.0 hub behavior. * USB 3.0 hub behavior.
*/ */
if (port->slot_id && xhci->devs[port->slot_id]) if (vdev)
xhci_ring_device(xhci, port->slot_id); xhci_ring_device(xhci, port->slot_id);
if (bus_state->port_remote_wakeup & (1 << hcd_portnum)) { if (bus_state->port_remote_wakeup & (1 << hcd_portnum)) {
xhci_test_and_clear_bit(xhci, port, PORT_PLC); xhci_test_and_clear_bit(xhci, port, PORT_PLC);

View File

@ -73,9 +73,12 @@ xhci_ring_to_sgtable(struct xhci_sideband *sb, struct xhci_ring *ring)
return NULL; return NULL;
} }
/* Caller must hold sb->mutex */
static void static void
__xhci_sideband_remove_endpoint(struct xhci_sideband *sb, struct xhci_virt_ep *ep) __xhci_sideband_remove_endpoint(struct xhci_sideband *sb, struct xhci_virt_ep *ep)
{ {
lockdep_assert_held(&sb->mutex);
/* /*
* Issue a stop endpoint command when an endpoint is removed. * Issue a stop endpoint command when an endpoint is removed.
* The stop ep cmd handler will handle the ring cleanup. * The stop ep cmd handler will handle the ring cleanup.
@ -86,6 +89,25 @@ __xhci_sideband_remove_endpoint(struct xhci_sideband *sb, struct xhci_virt_ep *e
sb->eps[ep->ep_index] = NULL; sb->eps[ep->ep_index] = NULL;
} }
/* Caller must hold sb->mutex */
static void
__xhci_sideband_remove_interrupter(struct xhci_sideband *sb)
{
struct usb_device *udev;
lockdep_assert_held(&sb->mutex);
if (!sb->ir)
return;
xhci_remove_secondary_interrupter(xhci_to_hcd(sb->xhci), sb->ir);
sb->ir = NULL;
udev = sb->vdev->udev;
if (udev->state != USB_STATE_NOTATTACHED)
usb_offload_put(udev);
}
/* sideband api functions */ /* sideband api functions */
/** /**
@ -131,14 +153,16 @@ xhci_sideband_add_endpoint(struct xhci_sideband *sb,
struct xhci_virt_ep *ep; struct xhci_virt_ep *ep;
unsigned int ep_index; unsigned int ep_index;
mutex_lock(&sb->mutex); guard(mutex)(&sb->mutex);
if (!sb->vdev)
return -ENODEV;
ep_index = xhci_get_endpoint_index(&host_ep->desc); ep_index = xhci_get_endpoint_index(&host_ep->desc);
ep = &sb->vdev->eps[ep_index]; ep = &sb->vdev->eps[ep_index];
if (ep->ep_state & EP_HAS_STREAMS) { if (ep->ep_state & EP_HAS_STREAMS)
mutex_unlock(&sb->mutex);
return -EINVAL; return -EINVAL;
}
/* /*
* Note, we don't know the DMA mask of the audio DSP device, if its * Note, we don't know the DMA mask of the audio DSP device, if its
@ -148,14 +172,11 @@ xhci_sideband_add_endpoint(struct xhci_sideband *sb,
* and let this function add the endpoint and allocate the ring buffer * and let this function add the endpoint and allocate the ring buffer
* with the smallest common DMA mask * with the smallest common DMA mask
*/ */
if (sb->eps[ep_index] || ep->sideband) { if (sb->eps[ep_index] || ep->sideband)
mutex_unlock(&sb->mutex);
return -EBUSY; return -EBUSY;
}
ep->sideband = sb; ep->sideband = sb;
sb->eps[ep_index] = ep; sb->eps[ep_index] = ep;
mutex_unlock(&sb->mutex);
return 0; return 0;
} }
@ -180,18 +201,16 @@ xhci_sideband_remove_endpoint(struct xhci_sideband *sb,
struct xhci_virt_ep *ep; struct xhci_virt_ep *ep;
unsigned int ep_index; unsigned int ep_index;
mutex_lock(&sb->mutex); guard(mutex)(&sb->mutex);
ep_index = xhci_get_endpoint_index(&host_ep->desc); ep_index = xhci_get_endpoint_index(&host_ep->desc);
ep = sb->eps[ep_index]; ep = sb->eps[ep_index];
if (!ep || !ep->sideband || ep->sideband != sb) { if (!ep || !ep->sideband || ep->sideband != sb)
mutex_unlock(&sb->mutex);
return -ENODEV; return -ENODEV;
}
__xhci_sideband_remove_endpoint(sb, ep); __xhci_sideband_remove_endpoint(sb, ep);
xhci_initialize_ring_info(ep->ring); xhci_initialize_ring_info(ep->ring);
mutex_unlock(&sb->mutex);
return 0; return 0;
} }
@ -316,28 +335,25 @@ xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg,
if (!sb || !sb->xhci) if (!sb || !sb->xhci)
return -ENODEV; return -ENODEV;
mutex_lock(&sb->mutex); guard(mutex)(&sb->mutex);
if (sb->ir) {
ret = -EBUSY; if (!sb->vdev)
goto out; return -ENODEV;
}
if (sb->ir)
return -EBUSY;
sb->ir = xhci_create_secondary_interrupter(xhci_to_hcd(sb->xhci), sb->ir = xhci_create_secondary_interrupter(xhci_to_hcd(sb->xhci),
num_seg, imod_interval, num_seg, imod_interval,
intr_num); intr_num);
if (!sb->ir) { if (!sb->ir)
ret = -ENOMEM; return -ENOMEM;
goto out;
}
udev = sb->vdev->udev; udev = sb->vdev->udev;
ret = usb_offload_get(udev); ret = usb_offload_get(udev);
sb->ir->ip_autoclear = ip_autoclear; sb->ir->ip_autoclear = ip_autoclear;
out:
mutex_unlock(&sb->mutex);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(xhci_sideband_create_interrupter); EXPORT_SYMBOL_GPL(xhci_sideband_create_interrupter);
@ -352,21 +368,12 @@ EXPORT_SYMBOL_GPL(xhci_sideband_create_interrupter);
void void
xhci_sideband_remove_interrupter(struct xhci_sideband *sb) xhci_sideband_remove_interrupter(struct xhci_sideband *sb)
{ {
struct usb_device *udev; if (!sb)
if (!sb || !sb->ir)
return; return;
mutex_lock(&sb->mutex); guard(mutex)(&sb->mutex);
xhci_remove_secondary_interrupter(xhci_to_hcd(sb->xhci), sb->ir);
sb->ir = NULL; __xhci_sideband_remove_interrupter(sb);
udev = sb->vdev->udev;
if (udev->state != USB_STATE_NOTATTACHED)
usb_offload_put(udev);
mutex_unlock(&sb->mutex);
} }
EXPORT_SYMBOL_GPL(xhci_sideband_remove_interrupter); EXPORT_SYMBOL_GPL(xhci_sideband_remove_interrupter);
@ -465,6 +472,7 @@ EXPORT_SYMBOL_GPL(xhci_sideband_register);
void void
xhci_sideband_unregister(struct xhci_sideband *sb) xhci_sideband_unregister(struct xhci_sideband *sb)
{ {
struct xhci_virt_device *vdev;
struct xhci_hcd *xhci; struct xhci_hcd *xhci;
int i; int i;
@ -473,17 +481,23 @@ xhci_sideband_unregister(struct xhci_sideband *sb)
xhci = sb->xhci; xhci = sb->xhci;
mutex_lock(&sb->mutex); scoped_guard(mutex, &sb->mutex) {
for (i = 0; i < EP_CTX_PER_DEV; i++) vdev = sb->vdev;
if (sb->eps[i]) if (!vdev)
__xhci_sideband_remove_endpoint(sb, sb->eps[i]); return;
mutex_unlock(&sb->mutex);
xhci_sideband_remove_interrupter(sb); for (i = 0; i < EP_CTX_PER_DEV; i++)
if (sb->eps[i])
__xhci_sideband_remove_endpoint(sb, sb->eps[i]);
__xhci_sideband_remove_interrupter(sb);
sb->vdev = NULL;
}
spin_lock_irq(&xhci->lock); spin_lock_irq(&xhci->lock);
sb->xhci = NULL; sb->xhci = NULL;
sb->vdev->sideband = NULL; vdev->sideband = NULL;
spin_unlock_irq(&xhci->lock); spin_unlock_irq(&xhci->lock);
kfree(sb); kfree(sb);

View File

@ -4007,6 +4007,7 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd,
xhci_get_slot_state(xhci, virt_dev->out_ctx)); xhci_get_slot_state(xhci, virt_dev->out_ctx));
xhci_dbg(xhci, "Not freeing device rings.\n"); xhci_dbg(xhci, "Not freeing device rings.\n");
/* Don't treat this as an error. May change my mind later. */ /* Don't treat this as an error. May change my mind later. */
virt_dev->flags = 0;
ret = 0; ret = 0;
goto command_cleanup; goto command_cleanup;
case COMP_SUCCESS: case COMP_SUCCESS:

View File

@ -813,18 +813,18 @@ static void usbhs_remove(struct platform_device *pdev)
flush_delayed_work(&priv->notify_hotplug_work); flush_delayed_work(&priv->notify_hotplug_work);
/* power off */
if (!usbhs_get_dparam(priv, runtime_pwctrl))
usbhsc_power_ctrl(priv, 0);
pm_runtime_disable(&pdev->dev);
usbhs_platform_call(priv, hardware_exit, pdev); usbhs_platform_call(priv, hardware_exit, pdev);
usbhsc_clk_put(priv);
reset_control_assert(priv->rsts); reset_control_assert(priv->rsts);
usbhs_mod_remove(priv); usbhs_mod_remove(priv);
usbhs_fifo_remove(priv); usbhs_fifo_remove(priv);
usbhs_pipe_remove(priv); usbhs_pipe_remove(priv);
/* power off */
if (!usbhs_get_dparam(priv, runtime_pwctrl))
usbhsc_power_ctrl(priv, 0);
usbhsc_clk_put(priv);
pm_runtime_disable(&pdev->dev);
} }
static int usbhsc_suspend(struct device *dev) static int usbhsc_suspend(struct device *dev)

View File

@ -1074,6 +1074,7 @@ static const struct usb_device_id id_table_combined[] = {
/* U-Blox devices */ /* U-Blox devices */
{ USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ZED_PID) }, { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ZED_PID) },
{ USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ODIN_PID) }, { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ODIN_PID) },
{ USB_DEVICE_INTERFACE_NUMBER(UBLOX_VID, UBLOX_EVK_M101_PID, 2) },
/* FreeCalypso USB adapters */ /* FreeCalypso USB adapters */
{ USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_BUF_PID), { USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_BUF_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },

View File

@ -1614,6 +1614,7 @@
#define UBLOX_VID 0x1546 #define UBLOX_VID 0x1546
#define UBLOX_C099F9P_ZED_PID 0x0502 #define UBLOX_C099F9P_ZED_PID 0x0502
#define UBLOX_C099F9P_ODIN_PID 0x0503 #define UBLOX_C099F9P_ODIN_PID 0x0503
#define UBLOX_EVK_M101_PID 0x0506
/* /*
* GMC devices * GMC devices

View File

@ -2424,12 +2424,18 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */
{ USB_DEVICE(0x33f8, 0x0104), /* Rolling RW101-GL (laptop RMNET) */ { USB_DEVICE(0x33f8, 0x0104), /* Rolling RW101-GL (laptop RMNET) */
.driver_info = RSVD(4) | RSVD(5) }, .driver_info = RSVD(4) | RSVD(5) },
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0115, 0xff), /* Rolling RW135-GL (laptop MBIM) */
.driver_info = RSVD(5) },
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a2, 0xff) }, /* Rolling RW101-GL (laptop MBIM) */ { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a2, 0xff) }, /* Rolling RW101-GL (laptop MBIM) */
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a3, 0xff) }, /* Rolling RW101-GL (laptop MBIM) */ { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a3, 0xff) }, /* Rolling RW101-GL (laptop MBIM) */
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a4, 0xff), /* Rolling RW101-GL (laptop MBIM) */ { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a4, 0xff), /* Rolling RW101-GL (laptop MBIM) */
.driver_info = RSVD(4) }, .driver_info = RSVD(4) },
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0115, 0xff), /* Rolling RW135-GL (laptop MBIM) */ { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a8, 0xff), /* Rolling RW101R-GL (laptop MBIM) */
.driver_info = RSVD(5) }, .driver_info = RSVD(4) },
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a9, 0xff), /* Rolling RW101R-GL (laptop MBIM) */
.driver_info = RSVD(4) },
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0301, 0xff) }, /* Rolling RW101R-GL (laptop MBIM) */
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0302, 0xff) }, /* Rolling RW101R-GL (laptop MBIM) */
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0802, 0xff), /* Rolling RW350-GL (laptop MBIM) */ { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0802, 0xff), /* Rolling RW350-GL (laptop MBIM) */
.driver_info = RSVD(5) }, .driver_info = RSVD(5) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for Global */ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for Global */

View File

@ -469,6 +469,12 @@ static int sddr55_write_data(struct us_data *us,
new_pba = (status[3] + (status[4] << 8) + (status[5] << 16)) new_pba = (status[3] + (status[4] << 8) + (status[5] << 16))
>> info->blockshift; >> info->blockshift;
/* check if device-reported new_pba is out of range */
if (new_pba >= (info->capacity >> (info->blockshift + info->pageshift))) {
result = USB_STOR_TRANSPORT_FAILED;
goto leave;
}
/* check status for error */ /* check status for error */
if (status[0] == 0xff && status[1] == 0x4) { if (status[0] == 0xff && status[1] == 0x4) {
info->pba_to_lba[new_pba] = BAD_BLOCK; info->pba_to_lba[new_pba] = BAD_BLOCK;

View File

@ -1200,7 +1200,23 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
US_BULK_CS_WRAP_LEN && US_BULK_CS_WRAP_LEN &&
bcs->Signature == bcs->Signature ==
cpu_to_le32(US_BULK_CS_SIGN)) { cpu_to_le32(US_BULK_CS_SIGN)) {
unsigned char buf[US_BULK_CS_WRAP_LEN];
usb_stor_dbg(us, "Device skipped data phase\n"); usb_stor_dbg(us, "Device skipped data phase\n");
/*
* Devices skipping data phase might leave CSW data in srb's
* transfer buffer. Zero it to prevent USB protocol leakage.
*/
sg = NULL;
offset = 0;
memset(buf, 0, sizeof(buf));
if (usb_stor_access_xfer_buf(buf,
US_BULK_CS_WRAP_LEN, srb, &sg,
&offset, TO_XFER_BUF) !=
US_BULK_CS_WRAP_LEN)
usb_stor_dbg(us, "Failed to clear CSW data\n");
scsi_set_resid(srb, transfer_length); scsi_set_resid(srb, transfer_length);
goto skipped_data_phase; goto skipped_data_phase;
} }

View File

@ -698,6 +698,10 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd)
* of queueing, no matter how fatal the error * of queueing, no matter how fatal the error
*/ */
if (err == -ENODEV) { if (err == -ENODEV) {
if (cmdinfo->state & (COMMAND_INFLIGHT | DATA_IN_URB_INFLIGHT |
DATA_OUT_URB_INFLIGHT))
goto out;
set_host_byte(cmnd, DID_NO_CONNECT); set_host_byte(cmnd, DID_NO_CONNECT);
scsi_done(cmnd); scsi_done(cmnd);
goto zombie; goto zombie;
@ -711,6 +715,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd)
uas_add_work(cmnd); uas_add_work(cmnd);
} }
out:
devinfo->cmnd[idx] = cmnd; devinfo->cmnd[idx] = cmnd;
zombie: zombie:
spin_unlock_irqrestore(&devinfo->lock, flags); spin_unlock_irqrestore(&devinfo->lock, flags);

View File

@ -938,7 +938,7 @@ UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x9451,
UNUSUAL_DEV( 0x0603, 0x8611, 0x0000, 0xffff, UNUSUAL_DEV( 0x0603, 0x8611, 0x0000, 0xffff,
"Novatek", "Novatek",
"NTK96550-based camera", "NTK96550-based camera",
USB_SC_SCSI, USB_PR_BULK, NULL, USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_BULK_IGNORE_TAG ), US_FL_BULK_IGNORE_TAG ),
/* /*

View File

@ -145,6 +145,11 @@ static int ucsi_psy_get_current_max(struct ucsi_connector *con,
{ {
u32 pdo; u32 pdo;
if (!UCSI_CONSTAT(con, CONNECTED)) {
val->intval = 0;
return 0;
}
switch (UCSI_CONSTAT(con, PWR_OPMODE)) { switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
case UCSI_CONSTAT_PWR_OPMODE_PD: case UCSI_CONSTAT_PWR_OPMODE_PD:
if (con->num_pdos > 0) { if (con->num_pdos > 0) {

View File

@ -376,6 +376,9 @@ struct usb_gadget_ops {
* can handle. The UDC must support this and all slower speeds and lower * can handle. The UDC must support this and all slower speeds and lower
* number of lanes. * number of lanes.
* @state: the state we are now (attached, suspended, configured, etc) * @state: the state we are now (attached, suspended, configured, etc)
* @state_lock: Spinlock protecting the `state` and `teardown` members.
* @teardown: True if the device is undergoing teardown, used to prevent
* new work from being scheduled during cleanup.
* @name: Identifies the controller hardware type. Used in diagnostics * @name: Identifies the controller hardware type. Used in diagnostics
* and sometimes configuration. * and sometimes configuration.
* @dev: Driver model state for this abstract device. * @dev: Driver model state for this abstract device.
@ -451,6 +454,8 @@ struct usb_gadget {
enum usb_ssp_rate max_ssp_rate; enum usb_ssp_rate max_ssp_rate;
enum usb_device_state state; enum usb_device_state state;
spinlock_t state_lock;
bool teardown;
const char *name; const char *name;
struct device dev; struct device dev;
unsigned isoch_delay; unsigned isoch_delay;