1
0
Fork 0

USB fixes for 4.16-rc3

Here are a number of USB fixes for 4.16-rc3
 
 Nothing major, but a number of different fixes all over the place in the
 USB stack for reported issues.  Mostly gadget driver fixes, although the
 typical set of xhci bugfixes are there, along with some new quirks
 additions as well.
 
 All of these have been in linux-next for a while with no reported
 issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWo613g8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ymS1QCcCDbBPEJQAKF64SyHWZfebeFIBpMAnR9vku/h
 1YXAXpcAJE5lGVVva3+I
 =57Qr
 -----END PGP SIGNATURE-----

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

Pull USB fixes from Greg KH:
 "Here are a number of USB fixes for 4.16-rc3

  Nothing major, but a number of different fixes all over the place in
  the USB stack for reported issues. Mostly gadget driver fixes,
  although the typical set of xhci bugfixes are there, along with some
  new quirks additions as well.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'usb-4.16-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (39 commits)
  Revert "usb: musb: host: don't start next rx urb if current one failed"
  usb: musb: fix enumeration after resume
  usb: cdc_acm: prevent race at write to acm while system resumes
  Add delay-init quirk for Corsair K70 RGB keyboards
  usb: ohci: Proper handling of ed_rm_list to handle race condition between usb_kill_urb() and finish_unlinks()
  usb: host: ehci: always enable interrupt for qtd completion at test mode
  usb: ldusb: add PIDs for new CASSY devices supported by this driver
  usb: renesas_usbhs: missed the "running" flag in usb_dmac with rx path
  usb: host: ehci: use correct device pointer for dma ops
  usbip: keep usbip_device sockfd state in sync with tcp_socket
  ohci-hcd: Fix race condition caused by ohci_urb_enqueue() and io_watchdog_func()
  USB: serial: option: Add support for Quectel EP06
  xhci: fix xhci debugfs errors in xhci_stop
  xhci: xhci debugfs device nodes weren't removed after device plugged out
  xhci: Fix xhci debugfs devices node disappearance after hibernation
  xhci: Fix NULL pointer in xhci debugfs
  xhci: Don't print a warning when setting link state for disabled ports
  xhci: workaround for AMD Promontory disabled ports wakeup
  usb: dwc3: core: Fix ULPI PHYs and prevent phy_get/ulpi_init during suspend/resume
  USB: gadget: udc: Add missing platform_device_put() on error in bdc_pci_probe()
  ...
hifive-unleashed-5.1
Linus Torvalds 2018-02-22 12:13:01 -08:00
commit a638af00b2
38 changed files with 352 additions and 135 deletions

View File

@ -645,6 +645,9 @@
#define USB_DEVICE_ID_LD_MICROCASSYTIME 0x1033
#define USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE 0x1035
#define USB_DEVICE_ID_LD_MICROCASSYPH 0x1038
#define USB_DEVICE_ID_LD_POWERANALYSERCASSY 0x1040
#define USB_DEVICE_ID_LD_CONVERTERCONTROLLERCASSY 0x1042
#define USB_DEVICE_ID_LD_MACHINETESTCASSY 0x1043
#define USB_DEVICE_ID_LD_JWM 0x1080
#define USB_DEVICE_ID_LD_DMMP 0x1081
#define USB_DEVICE_ID_LD_UMIP 0x1090

View File

@ -809,6 +809,9 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTIME) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYPH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERANALYSERCASSY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CONVERTERCONTROLLERCASSY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETESTCASSY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) },

View File

@ -174,6 +174,7 @@ static int acm_wb_alloc(struct acm *acm)
wb = &acm->wb[wbn];
if (!wb->use) {
wb->use = 1;
wb->len = 0;
return wbn;
}
wbn = (wbn + 1) % ACM_NW;
@ -805,16 +806,18 @@ static int acm_tty_write(struct tty_struct *tty,
static void acm_tty_flush_chars(struct tty_struct *tty)
{
struct acm *acm = tty->driver_data;
struct acm_wb *cur = acm->putbuffer;
struct acm_wb *cur;
int err;
unsigned long flags;
spin_lock_irqsave(&acm->write_lock, flags);
cur = acm->putbuffer;
if (!cur) /* nothing to do */
return;
goto out;
acm->putbuffer = NULL;
err = usb_autopm_get_interface_async(acm->control);
spin_lock_irqsave(&acm->write_lock, flags);
if (err < 0) {
cur->use = 0;
acm->putbuffer = cur;

View File

@ -226,6 +226,9 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x1a0a, 0x0200), .driver_info =
USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
/* Corsair K70 RGB */
{ USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT },
/* Corsair Strafe RGB */
{ USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT },

View File

@ -1917,7 +1917,9 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
/* Not specific buffer needed for ep0 ZLP */
dma_addr_t dma = hs_ep->desc_list_dma;
dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep);
if (!index)
dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep);
dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, dma, 0);
} else {
dwc2_writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
@ -2974,9 +2976,13 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
if (ints & DXEPINT_STSPHSERCVD) {
dev_dbg(hsotg->dev, "%s: StsPhseRcvd\n", __func__);
/* Move to STATUS IN for DDMA */
if (using_desc_dma(hsotg))
dwc2_hsotg_ep0_zlp(hsotg, true);
/* Safety check EP0 state when STSPHSERCVD asserted */
if (hsotg->ep0_state == DWC2_EP0_DATA_OUT) {
/* Move to STATUS IN for DDMA */
if (using_desc_dma(hsotg))
dwc2_hsotg_ep0_zlp(hsotg, true);
}
}
if (ints & DXEPINT_BACK2BACKSETUP)
@ -3375,12 +3381,6 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
DXEPCTL_USBACTEP, hsotg->regs + DIEPCTL0);
dwc2_hsotg_enqueue_setup(hsotg);
dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
dwc2_readl(hsotg->regs + DIEPCTL0),
dwc2_readl(hsotg->regs + DOEPCTL0));
/* clear global NAKs */
val = DCTL_CGOUTNAK | DCTL_CGNPINNAK;
if (!is_usb_reset)
@ -3391,6 +3391,12 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
mdelay(3);
hsotg->lx_state = DWC2_L0;
dwc2_hsotg_enqueue_setup(hsotg);
dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
dwc2_readl(hsotg->regs + DIEPCTL0),
dwc2_readl(hsotg->regs + DOEPCTL0));
}
static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)

View File

@ -100,6 +100,8 @@ static void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
reg |= DWC3_GCTL_PRTCAPDIR(mode);
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
dwc->current_dr_role = mode;
}
static void __dwc3_set_mode(struct work_struct *work)
@ -133,8 +135,6 @@ static void __dwc3_set_mode(struct work_struct *work)
dwc3_set_prtcap(dwc, dwc->desired_dr_role);
dwc->current_dr_role = dwc->desired_dr_role;
spin_unlock_irqrestore(&dwc->lock, flags);
switch (dwc->desired_dr_role) {
@ -219,7 +219,7 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
* XHCI driver will reset the host block. If dwc3 was configured for
* host-only mode, then we can return early.
*/
if (dwc->dr_mode == USB_DR_MODE_HOST)
if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST)
return 0;
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
@ -234,6 +234,9 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
udelay(1);
} while (--retries);
phy_exit(dwc->usb3_generic_phy);
phy_exit(dwc->usb2_generic_phy);
return -ETIMEDOUT;
}
@ -483,6 +486,22 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
}
static int dwc3_core_ulpi_init(struct dwc3 *dwc)
{
int intf;
int ret = 0;
intf = DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3);
if (intf == DWC3_GHWPARAMS3_HSPHY_IFC_ULPI ||
(intf == DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI &&
dwc->hsphy_interface &&
!strncmp(dwc->hsphy_interface, "ulpi", 4)))
ret = dwc3_ulpi_init(dwc);
return ret;
}
/**
* dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
* @dwc: Pointer to our controller context structure
@ -494,7 +513,6 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
static int dwc3_phy_setup(struct dwc3 *dwc)
{
u32 reg;
int ret;
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
@ -565,9 +583,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
}
/* FALLTHROUGH */
case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI:
ret = dwc3_ulpi_init(dwc);
if (ret)
return ret;
/* FALLTHROUGH */
default:
break;
@ -724,6 +739,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc)
}
static int dwc3_core_get_phy(struct dwc3 *dwc);
static int dwc3_core_ulpi_init(struct dwc3 *dwc);
/**
* dwc3_core_init - Low-level initialization of DWC3 Core
@ -755,18 +771,28 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc->maximum_speed = USB_SPEED_HIGH;
}
ret = dwc3_core_get_phy(dwc);
if (ret)
goto err0;
ret = dwc3_core_soft_reset(dwc);
if (ret)
goto err0;
ret = dwc3_phy_setup(dwc);
if (ret)
goto err0;
if (!dwc->ulpi_ready) {
ret = dwc3_core_ulpi_init(dwc);
if (ret)
goto err0;
dwc->ulpi_ready = true;
}
if (!dwc->phys_ready) {
ret = dwc3_core_get_phy(dwc);
if (ret)
goto err0a;
dwc->phys_ready = true;
}
ret = dwc3_core_soft_reset(dwc);
if (ret)
goto err0a;
dwc3_core_setup_global_control(dwc);
dwc3_core_num_eps(dwc);
@ -838,6 +864,9 @@ err1:
phy_exit(dwc->usb2_generic_phy);
phy_exit(dwc->usb3_generic_phy);
err0a:
dwc3_ulpi_exit(dwc);
err0:
return ret;
}
@ -916,7 +945,6 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
dwc->current_dr_role = DWC3_GCTL_PRTCAP_DEVICE;
dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
if (dwc->usb2_phy)
@ -932,7 +960,6 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
}
break;
case USB_DR_MODE_HOST:
dwc->current_dr_role = DWC3_GCTL_PRTCAP_HOST;
dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);
if (dwc->usb2_phy)
@ -1234,7 +1261,6 @@ err4:
err3:
dwc3_free_event_buffers(dwc);
dwc3_ulpi_exit(dwc);
err2:
pm_runtime_allow(&pdev->dev);
@ -1284,7 +1310,7 @@ static int dwc3_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM
static int dwc3_suspend_common(struct dwc3 *dwc)
static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
{
unsigned long flags;
@ -1296,6 +1322,10 @@ static int dwc3_suspend_common(struct dwc3 *dwc)
dwc3_core_exit(dwc);
break;
case DWC3_GCTL_PRTCAP_HOST:
/* do nothing during host runtime_suspend */
if (!PMSG_IS_AUTO(msg))
dwc3_core_exit(dwc);
break;
default:
/* do nothing */
break;
@ -1304,7 +1334,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc)
return 0;
}
static int dwc3_resume_common(struct dwc3 *dwc)
static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
{
unsigned long flags;
int ret;
@ -1320,6 +1350,13 @@ static int dwc3_resume_common(struct dwc3 *dwc)
spin_unlock_irqrestore(&dwc->lock, flags);
break;
case DWC3_GCTL_PRTCAP_HOST:
/* nothing to do on host runtime_resume */
if (!PMSG_IS_AUTO(msg)) {
ret = dwc3_core_init(dwc);
if (ret)
return ret;
}
break;
default:
/* do nothing */
break;
@ -1331,12 +1368,11 @@ static int dwc3_resume_common(struct dwc3 *dwc)
static int dwc3_runtime_checks(struct dwc3 *dwc)
{
switch (dwc->current_dr_role) {
case USB_DR_MODE_PERIPHERAL:
case USB_DR_MODE_OTG:
case DWC3_GCTL_PRTCAP_DEVICE:
if (dwc->connected)
return -EBUSY;
break;
case USB_DR_MODE_HOST:
case DWC3_GCTL_PRTCAP_HOST:
default:
/* do nothing */
break;
@ -1353,7 +1389,7 @@ static int dwc3_runtime_suspend(struct device *dev)
if (dwc3_runtime_checks(dwc))
return -EBUSY;
ret = dwc3_suspend_common(dwc);
ret = dwc3_suspend_common(dwc, PMSG_AUTO_SUSPEND);
if (ret)
return ret;
@ -1369,7 +1405,7 @@ static int dwc3_runtime_resume(struct device *dev)
device_init_wakeup(dev, false);
ret = dwc3_resume_common(dwc);
ret = dwc3_resume_common(dwc, PMSG_AUTO_RESUME);
if (ret)
return ret;
@ -1416,7 +1452,7 @@ static int dwc3_suspend(struct device *dev)
struct dwc3 *dwc = dev_get_drvdata(dev);
int ret;
ret = dwc3_suspend_common(dwc);
ret = dwc3_suspend_common(dwc, PMSG_SUSPEND);
if (ret)
return ret;
@ -1432,7 +1468,7 @@ static int dwc3_resume(struct device *dev)
pinctrl_pm_select_default_state(dev);
ret = dwc3_resume_common(dwc);
ret = dwc3_resume_common(dwc, PMSG_RESUME);
if (ret)
return ret;

View File

@ -158,13 +158,15 @@
#define DWC3_GDBGFIFOSPACE_TYPE(n) (((n) << 5) & 0x1e0)
#define DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(n) (((n) >> 16) & 0xffff)
#define DWC3_TXFIFOQ 1
#define DWC3_RXFIFOQ 3
#define DWC3_TXREQQ 5
#define DWC3_RXREQQ 7
#define DWC3_RXINFOQ 9
#define DWC3_DESCFETCHQ 13
#define DWC3_EVENTQ 15
#define DWC3_TXFIFOQ 0
#define DWC3_RXFIFOQ 1
#define DWC3_TXREQQ 2
#define DWC3_RXREQQ 3
#define DWC3_RXINFOQ 4
#define DWC3_PSTATQ 5
#define DWC3_DESCFETCHQ 6
#define DWC3_EVENTQ 7
#define DWC3_AUXEVENTQ 8
/* Global RX Threshold Configuration Register */
#define DWC3_GRXTHRCFG_MAXRXBURSTSIZE(n) (((n) & 0x1f) << 19)
@ -795,7 +797,9 @@ struct dwc3_scratchpad_array {
* @usb3_phy: pointer to USB3 PHY
* @usb2_generic_phy: pointer to USB2 PHY
* @usb3_generic_phy: pointer to USB3 PHY
* @phys_ready: flag to indicate that PHYs are ready
* @ulpi: pointer to ulpi interface
* @ulpi_ready: flag to indicate that ULPI is initialized
* @u2sel: parameter from Set SEL request.
* @u2pel: parameter from Set SEL request.
* @u1sel: parameter from Set SEL request.
@ -893,7 +897,10 @@ struct dwc3 {
struct phy *usb2_generic_phy;
struct phy *usb3_generic_phy;
bool phys_ready;
struct ulpi *ulpi;
bool ulpi_ready;
void __iomem *regs;
size_t regs_size;

View File

@ -143,6 +143,7 @@ static int dwc3_of_simple_remove(struct platform_device *pdev)
clk_disable_unprepare(simple->clks[i]);
clk_put(simple->clks[i]);
}
simple->num_clocks = 0;
reset_control_assert(simple->resets);
reset_control_put(simple->resets);

View File

@ -582,9 +582,25 @@ static int dwc3_omap_resume(struct device *dev)
return 0;
}
static void dwc3_omap_complete(struct device *dev)
{
struct dwc3_omap *omap = dev_get_drvdata(dev);
if (extcon_get_state(omap->edev, EXTCON_USB))
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
else
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF);
if (extcon_get_state(omap->edev, EXTCON_USB_HOST))
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
else
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT);
}
static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume)
.complete = dwc3_omap_complete,
};
#define DEV_PM_OPS (&dwc3_omap_dev_pm_ops)

View File

@ -854,7 +854,12 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
trb++;
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
trace_dwc3_complete_trb(ep0, trb);
ep0->trb_enqueue = 0;
if (r->direction)
dwc->eps[1]->trb_enqueue = 0;
else
dwc->eps[0]->trb_enqueue = 0;
dwc->ep0_bounced = false;
}

View File

@ -2745,6 +2745,8 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
break;
}
dwc->eps[1]->endpoint.maxpacket = dwc->gadget.ep0->maxpacket;
/* Enable USB2 LPM Capability */
if ((dwc->revision > DWC3_REVISION_194A) &&

View File

@ -1855,44 +1855,20 @@ static int ffs_func_eps_enable(struct ffs_function *func)
spin_lock_irqsave(&func->ffs->eps_lock, flags);
while(count--) {
struct usb_endpoint_descriptor *ds;
struct usb_ss_ep_comp_descriptor *comp_desc = NULL;
int needs_comp_desc = false;
int desc_idx;
if (ffs->gadget->speed == USB_SPEED_SUPER) {
desc_idx = 2;
needs_comp_desc = true;
} else if (ffs->gadget->speed == USB_SPEED_HIGH)
desc_idx = 1;
else
desc_idx = 0;
/* fall-back to lower speed if desc missing for current speed */
do {
ds = ep->descs[desc_idx];
} while (!ds && --desc_idx >= 0);
if (!ds) {
ret = -EINVAL;
break;
}
ep->ep->driver_data = ep;
ep->ep->desc = ds;
if (needs_comp_desc) {
comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds +
USB_DT_ENDPOINT_SIZE);
ep->ep->maxburst = comp_desc->bMaxBurst + 1;
ep->ep->comp_desc = comp_desc;
ret = config_ep_by_speed(func->gadget, &func->function, ep->ep);
if (ret) {
pr_err("%s: config_ep_by_speed(%s) returned %d\n",
__func__, ep->ep->name, ret);
break;
}
ret = usb_ep_enable(ep->ep);
if (likely(!ret)) {
epfile->ep = ep;
epfile->in = usb_endpoint_dir_in(ds);
epfile->isoc = usb_endpoint_xfer_isoc(ds);
epfile->in = usb_endpoint_dir_in(ep->ep->desc);
epfile->isoc = usb_endpoint_xfer_isoc(ep->ep->desc);
} else {
break;
}
@ -2979,10 +2955,8 @@ static int _ffs_func_bind(struct usb_configuration *c,
struct ffs_data *ffs = func->ffs;
const int full = !!func->ffs->fs_descs_count;
const int high = gadget_is_dualspeed(func->gadget) &&
func->ffs->hs_descs_count;
const int super = gadget_is_superspeed(func->gadget) &&
func->ffs->ss_descs_count;
const int high = !!func->ffs->hs_descs_count;
const int super = !!func->ffs->ss_descs_count;
int fs_len, hs_len, ss_len, ret, i;
struct ffs_ep *eps_ptr;

View File

@ -524,6 +524,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
return ret;
}
iad_desc.bFirstInterface = ret;
std_ac_if_desc.bInterfaceNumber = ret;
uac2->ac_intf = ret;
uac2->ac_alt = 0;

View File

@ -274,7 +274,6 @@ config USB_SNP_UDC_PLAT
tristate "Synopsys USB 2.0 Device controller"
depends on USB_GADGET && OF && HAS_DMA
depends on EXTCON || EXTCON=n
select USB_GADGET_DUALSPEED
select USB_SNP_CORE
default ARCH_BCM_IPROC
help

View File

@ -77,6 +77,7 @@ static int bdc_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
if (ret) {
dev_err(&pci->dev,
"couldn't add resources to bdc device\n");
platform_device_put(bdc);
return ret;
}

View File

@ -180,8 +180,8 @@ EXPORT_SYMBOL_GPL(usb_ep_alloc_request);
void usb_ep_free_request(struct usb_ep *ep,
struct usb_request *req)
{
ep->ops->free_request(ep, req);
trace_usb_ep_free_request(ep, req, 0);
ep->ops->free_request(ep, req);
}
EXPORT_SYMBOL_GPL(usb_ep_free_request);

View File

@ -1305,7 +1305,7 @@ static void udc_reset_ep_queue(struct fsl_udc *udc, u8 pipe)
{
struct fsl_ep *ep = get_ep_by_pipe(udc, pipe);
if (ep->name)
if (ep->ep.name)
nuke(ep, -ESHUTDOWN);
}
@ -1693,7 +1693,7 @@ static void dtd_complete_irq(struct fsl_udc *udc)
curr_ep = get_ep_by_pipe(udc, i);
/* If the ep is configured */
if (curr_ep->name == NULL) {
if (!curr_ep->ep.name) {
WARNING("Invalid EP?");
continue;
}

View File

@ -2410,7 +2410,7 @@ static int renesas_usb3_remove(struct platform_device *pdev)
__renesas_usb3_ep_free_request(usb3->ep0_req);
if (usb3->phy)
phy_put(usb3->phy);
pm_runtime_disable(usb3_to_dev(usb3));
pm_runtime_disable(&pdev->dev);
return 0;
}

View File

@ -774,12 +774,12 @@ static struct urb *request_single_step_set_feature_urb(
atomic_inc(&urb->use_count);
atomic_inc(&urb->dev->urbnum);
urb->setup_dma = dma_map_single(
hcd->self.controller,
hcd->self.sysdev,
urb->setup_packet,
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
urb->transfer_dma = dma_map_single(
hcd->self.controller,
hcd->self.sysdev,
urb->transfer_buffer,
urb->transfer_buffer_length,
DMA_FROM_DEVICE);

View File

@ -1188,10 +1188,10 @@ static int submit_single_step_set_feature(
* 15 secs after the setup
*/
if (is_setup) {
/* SETUP pid */
/* SETUP pid, and interrupt after SETUP completion */
qtd_fill(ehci, qtd, urb->setup_dma,
sizeof(struct usb_ctrlrequest),
token | (2 /* "setup" */ << 8), 8);
QTD_IOC | token | (2 /* "setup" */ << 8), 8);
submit_async(ehci, urb, &qtd_list, GFP_ATOMIC);
return 0; /*Return now; we shall come back after 15 seconds*/
@ -1228,12 +1228,8 @@ static int submit_single_step_set_feature(
qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
list_add_tail(&qtd->qtd_list, head);
/* dont fill any data in such packets */
qtd_fill(ehci, qtd, 0, 0, token, 0);
/* by default, enable interrupt on urb completion */
if (likely(!(urb->transfer_flags & URB_NO_INTERRUPT)))
qtd->hw_token |= cpu_to_hc32(ehci, QTD_IOC);
/* Interrupt after STATUS completion */
qtd_fill(ehci, qtd, 0, 0, token | QTD_IOC, 0);
submit_async(ehci, urb, &qtd_list, GFP_KERNEL);

View File

@ -74,6 +74,7 @@ static const char hcd_name [] = "ohci_hcd";
#define STATECHANGE_DELAY msecs_to_jiffies(300)
#define IO_WATCHDOG_DELAY msecs_to_jiffies(275)
#define IO_WATCHDOG_OFF 0xffffff00
#include "ohci.h"
#include "pci-quirks.h"
@ -231,7 +232,7 @@ static int ohci_urb_enqueue (
}
/* Start up the I/O watchdog timer, if it's not running */
if (!timer_pending(&ohci->io_watchdog) &&
if (ohci->prev_frame_no == IO_WATCHDOG_OFF &&
list_empty(&ohci->eds_in_use) &&
!(ohci->flags & OHCI_QUIRK_QEMU)) {
ohci->prev_frame_no = ohci_frame_no(ohci);
@ -501,6 +502,7 @@ static int ohci_init (struct ohci_hcd *ohci)
return 0;
timer_setup(&ohci->io_watchdog, io_watchdog_func, 0);
ohci->prev_frame_no = IO_WATCHDOG_OFF;
ohci->hcca = dma_alloc_coherent (hcd->self.controller,
sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_KERNEL);
@ -730,7 +732,7 @@ static void io_watchdog_func(struct timer_list *t)
u32 head;
struct ed *ed;
struct td *td, *td_start, *td_next;
unsigned frame_no;
unsigned frame_no, prev_frame_no = IO_WATCHDOG_OFF;
unsigned long flags;
spin_lock_irqsave(&ohci->lock, flags);
@ -835,7 +837,7 @@ static void io_watchdog_func(struct timer_list *t)
}
}
if (!list_empty(&ohci->eds_in_use)) {
ohci->prev_frame_no = frame_no;
prev_frame_no = frame_no;
ohci->prev_wdh_cnt = ohci->wdh_cnt;
ohci->prev_donehead = ohci_readl(ohci,
&ohci->regs->donehead);
@ -845,6 +847,7 @@ static void io_watchdog_func(struct timer_list *t)
}
done:
ohci->prev_frame_no = prev_frame_no;
spin_unlock_irqrestore(&ohci->lock, flags);
}
@ -973,6 +976,7 @@ static void ohci_stop (struct usb_hcd *hcd)
if (quirk_nec(ohci))
flush_work(&ohci->nec_work);
del_timer_sync(&ohci->io_watchdog);
ohci->prev_frame_no = IO_WATCHDOG_OFF;
ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
ohci_usb_reset(ohci);

View File

@ -311,8 +311,10 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
rc = ohci_rh_suspend (ohci, 0);
spin_unlock_irq (&ohci->lock);
if (rc == 0)
if (rc == 0) {
del_timer_sync(&ohci->io_watchdog);
ohci->prev_frame_no = IO_WATCHDOG_OFF;
}
return rc;
}

View File

@ -1019,6 +1019,8 @@ skip_ed:
* have modified this list. normally it's just prepending
* entries (which we'd ignore), but paranoia won't hurt.
*/
*last = ed->ed_next;
ed->ed_next = NULL;
modified = 0;
/* unlink urbs as requested, but rescan the list after
@ -1077,21 +1079,22 @@ rescan_this:
goto rescan_this;
/*
* If no TDs are queued, take ED off the ed_rm_list.
* If no TDs are queued, ED is now idle.
* Otherwise, if the HC is running, reschedule.
* If not, leave it on the list for further dequeues.
* If the HC isn't running, add ED back to the
* start of the list for later processing.
*/
if (list_empty(&ed->td_list)) {
*last = ed->ed_next;
ed->ed_next = NULL;
ed->state = ED_IDLE;
list_del(&ed->in_use_list);
} else if (ohci->rh_state == OHCI_RH_RUNNING) {
*last = ed->ed_next;
ed->ed_next = NULL;
ed_schedule(ohci, ed);
} else {
last = &ed->ed_next;
ed->ed_next = ohci->ed_rm_list;
ohci->ed_rm_list = ed;
/* Don't loop on the same ED */
if (last == &ohci->ed_rm_list)
last = &ed->ed_next;
}
if (modified)

View File

@ -66,6 +66,23 @@
#define AX_INDXC 0x30
#define AX_DATAC 0x34
#define PT_ADDR_INDX 0xE8
#define PT_READ_INDX 0xE4
#define PT_SIG_1_ADDR 0xA520
#define PT_SIG_2_ADDR 0xA521
#define PT_SIG_3_ADDR 0xA522
#define PT_SIG_4_ADDR 0xA523
#define PT_SIG_1_DATA 0x78
#define PT_SIG_2_DATA 0x56
#define PT_SIG_3_DATA 0x34
#define PT_SIG_4_DATA 0x12
#define PT4_P1_REG 0xB521
#define PT4_P2_REG 0xB522
#define PT2_P1_REG 0xD520
#define PT2_P2_REG 0xD521
#define PT1_P1_REG 0xD522
#define PT1_P2_REG 0xD523
#define NB_PCIE_INDX_ADDR 0xe0
#define NB_PCIE_INDX_DATA 0xe4
#define PCIE_P_CNTL 0x10040
@ -512,6 +529,98 @@ void usb_amd_dev_put(void)
}
EXPORT_SYMBOL_GPL(usb_amd_dev_put);
/*
* Check if port is disabled in BIOS on AMD Promontory host.
* BIOS Disabled ports may wake on connect/disconnect and need
* driver workaround to keep them disabled.
* Returns true if port is marked disabled.
*/
bool usb_amd_pt_check_port(struct device *device, int port)
{
unsigned char value, port_shift;
struct pci_dev *pdev;
u16 reg;
pdev = to_pci_dev(device);
pci_write_config_word(pdev, PT_ADDR_INDX, PT_SIG_1_ADDR);
pci_read_config_byte(pdev, PT_READ_INDX, &value);
if (value != PT_SIG_1_DATA)
return false;
pci_write_config_word(pdev, PT_ADDR_INDX, PT_SIG_2_ADDR);
pci_read_config_byte(pdev, PT_READ_INDX, &value);
if (value != PT_SIG_2_DATA)
return false;
pci_write_config_word(pdev, PT_ADDR_INDX, PT_SIG_3_ADDR);
pci_read_config_byte(pdev, PT_READ_INDX, &value);
if (value != PT_SIG_3_DATA)
return false;
pci_write_config_word(pdev, PT_ADDR_INDX, PT_SIG_4_ADDR);
pci_read_config_byte(pdev, PT_READ_INDX, &value);
if (value != PT_SIG_4_DATA)
return false;
/* Check disabled port setting, if bit is set port is enabled */
switch (pdev->device) {
case 0x43b9:
case 0x43ba:
/*
* device is AMD_PROMONTORYA_4(0x43b9) or PROMONTORYA_3(0x43ba)
* PT4_P1_REG bits[7..1] represents USB2.0 ports 6 to 0
* PT4_P2_REG bits[6..0] represents ports 13 to 7
*/
if (port > 6) {
reg = PT4_P2_REG;
port_shift = port - 7;
} else {
reg = PT4_P1_REG;
port_shift = port + 1;
}
break;
case 0x43bb:
/*
* device is AMD_PROMONTORYA_2(0x43bb)
* PT2_P1_REG bits[7..5] represents USB2.0 ports 2 to 0
* PT2_P2_REG bits[5..0] represents ports 9 to 3
*/
if (port > 2) {
reg = PT2_P2_REG;
port_shift = port - 3;
} else {
reg = PT2_P1_REG;
port_shift = port + 5;
}
break;
case 0x43bc:
/*
* device is AMD_PROMONTORYA_1(0x43bc)
* PT1_P1_REG[7..4] represents USB2.0 ports 3 to 0
* PT1_P2_REG[5..0] represents ports 9 to 4
*/
if (port > 3) {
reg = PT1_P2_REG;
port_shift = port - 4;
} else {
reg = PT1_P1_REG;
port_shift = port + 4;
}
break;
default:
return false;
}
pci_write_config_word(pdev, PT_ADDR_INDX, reg);
pci_read_config_byte(pdev, PT_READ_INDX, &value);
return !(value & BIT(port_shift));
}
EXPORT_SYMBOL_GPL(usb_amd_pt_check_port);
/*
* Make sure the controller is completely inactive, unable to
* generate interrupts or do DMA.

View File

@ -17,6 +17,7 @@ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
void sb800_prefetch(struct device *dev, int on);
bool usb_xhci_needs_pci_reset(struct pci_dev *pdev);
bool usb_amd_pt_check_port(struct device *device, int port);
#else
struct pci_dev;
static inline void usb_amd_quirk_pll_disable(void) {}
@ -25,6 +26,10 @@ static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}
static inline void usb_amd_dev_put(void) {}
static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
static inline void sb800_prefetch(struct device *dev, int on) {}
static inline bool usb_amd_pt_check_port(struct device *device, int port)
{
return false;
}
#endif /* CONFIG_USB_PCI */
#endif /* __LINUX_USB_PCI_QUIRKS_H */

View File

@ -211,7 +211,7 @@ static void xhci_ring_dump_segment(struct seq_file *s,
static int xhci_ring_trb_show(struct seq_file *s, void *unused)
{
int i;
struct xhci_ring *ring = s->private;
struct xhci_ring *ring = *(struct xhci_ring **)s->private;
struct xhci_segment *seg = ring->first_seg;
for (i = 0; i < ring->num_segs; i++) {
@ -387,7 +387,7 @@ void xhci_debugfs_create_endpoint(struct xhci_hcd *xhci,
snprintf(epriv->name, sizeof(epriv->name), "ep%02d", ep_index);
epriv->root = xhci_debugfs_create_ring_dir(xhci,
&dev->eps[ep_index].new_ring,
&dev->eps[ep_index].ring,
epriv->name,
spriv->root);
spriv->eps[ep_index] = epriv;

View File

@ -1224,17 +1224,17 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp = readl(port_array[wIndex]);
break;
}
/* Software should not attempt to set
* port link state above '3' (U3) and the port
* must be enabled.
*/
if ((temp & PORT_PE) == 0 ||
(link_state > USB_SS_PORT_LS_U3)) {
xhci_warn(xhci, "Cannot set link state.\n");
/* Port must be enabled */
if (!(temp & PORT_PE)) {
retval = -ENODEV;
break;
}
/* Can't set port link state above '3' (U3) */
if (link_state > USB_SS_PORT_LS_U3) {
xhci_warn(xhci, "Cannot set port %d link state %d\n",
wIndex, link_state);
goto error;
}
if (link_state == USB_SS_PORT_LS_U3) {
slot_id = xhci_find_slot_id_by_port(hcd, xhci,
wIndex + 1);
@ -1522,6 +1522,13 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
t2 |= PORT_WKOC_E | PORT_WKCONN_E;
t2 &= ~PORT_WKDISC_E;
}
if ((xhci->quirks & XHCI_U2_DISABLE_WAKE) &&
(hcd->speed < HCD_USB3)) {
if (usb_amd_pt_check_port(hcd->self.controller,
port_index))
t2 &= ~PORT_WAKE_BITS;
}
} else
t2 &= ~PORT_WAKE_BITS;

View File

@ -42,6 +42,10 @@
#define PCI_DEVICE_ID_INTEL_APL_XHCI 0x5aa8
#define PCI_DEVICE_ID_INTEL_DNV_XHCI 0x19d0
#define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9
#define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba
#define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb
#define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc
#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142
static const char hcd_name[] = "xhci_hcd";
@ -125,6 +129,13 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
if (pdev->vendor == PCI_VENDOR_ID_AMD)
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
if ((pdev->vendor == PCI_VENDOR_ID_AMD) &&
((pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4) ||
(pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_3) ||
(pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_2) ||
(pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_1)))
xhci->quirks |= XHCI_U2_DISABLE_WAKE;
if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
xhci->quirks |= XHCI_LPM_SUPPORT;
xhci->quirks |= XHCI_INTEL_HOST;

View File

@ -646,8 +646,6 @@ static void xhci_stop(struct usb_hcd *hcd)
return;
}
xhci_debugfs_exit(xhci);
xhci_dbc_exit(xhci);
spin_lock_irq(&xhci->lock);
@ -680,6 +678,7 @@ static void xhci_stop(struct usb_hcd *hcd)
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "cleaning up memory");
xhci_mem_cleanup(xhci);
xhci_debugfs_exit(xhci);
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"xhci_stop completed - status = %x",
readl(&xhci->op_regs->status));
@ -1014,6 +1013,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
xhci_dbg(xhci, "cleaning up memory\n");
xhci_mem_cleanup(xhci);
xhci_debugfs_exit(xhci);
xhci_dbg(xhci, "xhci_stop completed - status = %x\n",
readl(&xhci->op_regs->status));
@ -3544,12 +3544,10 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING;
del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);
}
xhci_debugfs_remove_slot(xhci, udev->slot_id);
ret = xhci_disable_slot(xhci, udev->slot_id);
if (ret) {
xhci_debugfs_remove_slot(xhci, udev->slot_id);
if (ret)
xhci_free_virt_device(xhci, udev->slot_id);
}
}
int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)

View File

@ -1822,7 +1822,7 @@ struct xhci_hcd {
/* For controller with a broken Port Disable implementation */
#define XHCI_BROKEN_PORT_PED (1 << 25)
#define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26)
/* Reserved. It was XHCI_U2_DISABLE_WAKE */
#define XHCI_U2_DISABLE_WAKE (1 << 27)
#define XHCI_ASMEDIA_MODIFY_FLOWCONTROL (1 << 28)
#define XHCI_HW_LPM_DISABLE (1 << 29)

View File

@ -42,6 +42,9 @@
#define USB_DEVICE_ID_LD_MICROCASSYTIME 0x1033 /* USB Product ID of Micro-CASSY Time (reserved) */
#define USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE 0x1035 /* USB Product ID of Micro-CASSY Temperature */
#define USB_DEVICE_ID_LD_MICROCASSYPH 0x1038 /* USB Product ID of Micro-CASSY pH */
#define USB_DEVICE_ID_LD_POWERANALYSERCASSY 0x1040 /* USB Product ID of Power Analyser CASSY */
#define USB_DEVICE_ID_LD_CONVERTERCONTROLLERCASSY 0x1042 /* USB Product ID of Converter Controller CASSY */
#define USB_DEVICE_ID_LD_MACHINETESTCASSY 0x1043 /* USB Product ID of Machine Test CASSY */
#define USB_DEVICE_ID_LD_JWM 0x1080 /* USB Product ID of Joule and Wattmeter */
#define USB_DEVICE_ID_LD_DMMP 0x1081 /* USB Product ID of Digital Multimeter P (reserved) */
#define USB_DEVICE_ID_LD_UMIP 0x1090 /* USB Product ID of UMI P */
@ -84,6 +87,9 @@ static const struct usb_device_id ld_usb_table[] = {
{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTIME) },
{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE) },
{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYPH) },
{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERANALYSERCASSY) },
{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CONVERTERCONTROLLERCASSY) },
{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETESTCASSY) },
{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) },
{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) },
{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) },

View File

@ -2708,7 +2708,8 @@ static int musb_resume(struct device *dev)
if ((devctl & mask) != (musb->context.devctl & mask))
musb->port1_status = 0;
musb_start(musb);
musb_enable_interrupts(musb);
musb_platform_enable(musb);
spin_lock_irqsave(&musb->lock, flags);
error = musb_run_resume_work(musb);

View File

@ -391,13 +391,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb,
}
}
/*
* The pipe must be broken if current urb->status is set, so don't
* start next urb.
* TODO: to minimize the risk of regression, only check urb->status
* for RX, until we have a test case to understand the behavior of TX.
*/
if ((!status || !is_in) && qh && qh->is_ready) {
if (qh != NULL && qh->is_ready) {
musb_dbg(musb, "... next ep%d %cX urb %p",
hw_ep->epnum, is_in ? 'R' : 'T', next_urb(qh));
musb_start_urb(musb, is_in, qh);

View File

@ -602,6 +602,9 @@ static enum usb_charger_type mxs_phy_charger_detect(struct usb_phy *phy)
void __iomem *base = phy->io_priv;
enum usb_charger_type chgr_type = UNKNOWN_TYPE;
if (!regmap)
return UNKNOWN_TYPE;
if (mxs_charger_data_contact_detect(mxs_phy))
return chgr_type;

View File

@ -982,6 +982,10 @@ static int usbhsf_dma_prepare_pop_with_usb_dmac(struct usbhs_pkt *pkt,
if ((uintptr_t)pkt->buf & (USBHS_USB_DMAC_XFER_SIZE - 1))
goto usbhsf_pio_prepare_pop;
/* return at this time if the pipe is running */
if (usbhs_pipe_is_running(pipe))
return 0;
usbhs_pipe_config_change_bfre(pipe, 1);
ret = usbhsf_fifo_select(pipe, fifo, 0);
@ -1172,6 +1176,7 @@ static int usbhsf_dma_pop_done_with_usb_dmac(struct usbhs_pkt *pkt,
usbhsf_fifo_clear(pipe, fifo);
pkt->actual = usbhs_dma_calc_received_size(pkt, chan, rcv_len);
usbhs_pipe_running(pipe, 0);
usbhsf_dma_stop(pipe, fifo);
usbhsf_dma_unmap(pkt);
usbhsf_fifo_unselect(pipe, pipe->fifo);

View File

@ -241,6 +241,7 @@ static void option_instat_callback(struct urb *urb);
#define QUECTEL_PRODUCT_EC21 0x0121
#define QUECTEL_PRODUCT_EC25 0x0125
#define QUECTEL_PRODUCT_BG96 0x0296
#define QUECTEL_PRODUCT_EP06 0x0306
#define CMOTECH_VENDOR_ID 0x16d8
#define CMOTECH_PRODUCT_6001 0x6001
@ -689,6 +690,10 @@ static const struct option_blacklist_info yuga_clm920_nc5_blacklist = {
.reserved = BIT(1) | BIT(4),
};
static const struct option_blacklist_info quectel_ep06_blacklist = {
.reserved = BIT(4) | BIT(5),
};
static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@ -1203,6 +1208,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06),
.driver_info = (kernel_ulong_t)&quectel_ep06_blacklist },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),

View File

@ -73,6 +73,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
goto err;
sdev->ud.tcp_socket = socket;
sdev->ud.sockfd = sockfd;
spin_unlock_irq(&sdev->ud.lock);
@ -172,6 +173,7 @@ static void stub_shutdown_connection(struct usbip_device *ud)
if (ud->tcp_socket) {
sockfd_put(ud->tcp_socket);
ud->tcp_socket = NULL;
ud->sockfd = -1;
}
/* 3. free used data */
@ -266,6 +268,7 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev)
sdev->ud.status = SDEV_ST_AVAILABLE;
spin_lock_init(&sdev->ud.lock);
sdev->ud.tcp_socket = NULL;
sdev->ud.sockfd = -1;
INIT_LIST_HEAD(&sdev->priv_init);
INIT_LIST_HEAD(&sdev->priv_tx);

View File

@ -984,6 +984,7 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
if (vdev->ud.tcp_socket) {
sockfd_put(vdev->ud.tcp_socket);
vdev->ud.tcp_socket = NULL;
vdev->ud.sockfd = -1;
}
pr_info("release socket\n");
@ -1030,6 +1031,7 @@ static void vhci_device_reset(struct usbip_device *ud)
if (ud->tcp_socket) {
sockfd_put(ud->tcp_socket);
ud->tcp_socket = NULL;
ud->sockfd = -1;
}
ud->status = VDEV_ST_NULL;