usb: fixes for v4.10-rc3
The first set of fixes for v4.10-rc cycle. The most important of which is a big regression on dwc3-pci which prevents it from probing altogether. There's also a fix to avoid Overflow events on DWC3 and another to make sure we don't starve DMA resources. Dummy HCD got some love after a long hiatus and DWC2 got a couple fixes related to DMA usage. Other than these, we have a set of minor fixes here and there. -----BEGIN PGP SIGNATURE----- iQJRBAABCAA7FiEElLzh7wn96CXwjh2IzL64meEamQYFAlhrnosdHGZlbGlwZS5i YWxiaUBsaW51eC5pbnRlbC5jb20ACgkQzL64meEamQZY6RAAnqW8t07zI8yjOvTD fMfob/ur54pIDzRxnCWMMQQmbnIWvpgE70s3OBBGog5GswOTfXP2OcKuMHkcbr89 o66ANwITps41irHXNJG+NX3be3ChjbiqgOcxagfClPMuFDE+kkLNb31DyFXwP0u3 UvP26js00LMpQ0TsesA+nWYbe0IEDC62eSTGKDee6Z+5DBIFXJGUC1cSI9VvD73b 1u5Phtc4dsTnlNkbhMgdPChuNznD9TJTopsChUG5wZKu+jbUE+rgenPLhd7i+LS2 8mqnnAqv80iiWB+Dz/MqsZH7iJmJiM2c5w7DduYnlRiVJAmWw3rPt22rSnywEfnb o2G4ptvZSWPLv/cnHt81i7BATdxpQSUEHtziZjQcCtaIEYYxpj2KXXeurANfS5Vw FK8eYFk5Ho53h1q0xPPOwc9uafxqWcbT69HHwdSHSYCqQT0rZsAQbKyDb+r7UtwS pWK8VEFK/mhNn/a2c3AzZWIk3vLpmL4/YppaBpzZO44K/1v9nLNX07eOSJq9Br2B Lp0eW+ZT0QBXAqodT54QWCRVG0YZX9iDU78R8Ru/7ahUmJ4KJZLDGuF4tGwyvMWk 1wVAFnNrwT1i4OKL+KNFlm8OGSeMeuxNcQVxjVCbMAjFbG95dfqETIIBiAb2QgNF xAM71aAUJ8vyTQvEmA9BZpb15Jo= =uEVv -----END PGP SIGNATURE----- Merge tag 'fixes-for-v4.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus Felipe writes: usb: fixes for v4.10-rc3 The first set of fixes for v4.10-rc cycle. The most important of which is a big regression on dwc3-pci which prevents it from probing altogether. There's also a fix to avoid Overflow events on DWC3 and another to make sure we don't starve DMA resources. Dummy HCD got some love after a long hiatus and DWC2 got a couple fixes related to DMA usage. Other than these, we have a set of minor fixes here and there.
This commit is contained in:
commit
8d6bbff677
|
@ -3753,7 +3753,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
|
|||
hs_ep->desc_list = dma_alloc_coherent(hsotg->dev,
|
||||
MAX_DMA_DESC_NUM_GENERIC *
|
||||
sizeof(struct dwc2_dma_desc),
|
||||
&hs_ep->desc_list_dma, GFP_KERNEL);
|
||||
&hs_ep->desc_list_dma, GFP_ATOMIC);
|
||||
if (!hs_ep->desc_list) {
|
||||
ret = -ENOMEM;
|
||||
goto error2;
|
||||
|
|
|
@ -247,8 +247,6 @@ MODULE_DEVICE_TABLE(of, dwc2_of_match_table);
|
|||
static void dwc2_get_device_property(struct dwc2_hsotg *hsotg,
|
||||
char *property, u8 size, u64 *value)
|
||||
{
|
||||
u8 val8;
|
||||
u16 val16;
|
||||
u32 val32;
|
||||
|
||||
switch (size) {
|
||||
|
@ -256,17 +254,7 @@ static void dwc2_get_device_property(struct dwc2_hsotg *hsotg,
|
|||
*value = device_property_read_bool(hsotg->dev, property);
|
||||
break;
|
||||
case 1:
|
||||
if (device_property_read_u8(hsotg->dev, property, &val8))
|
||||
return;
|
||||
|
||||
*value = val8;
|
||||
break;
|
||||
case 2:
|
||||
if (device_property_read_u16(hsotg->dev, property, &val16))
|
||||
return;
|
||||
|
||||
*value = val16;
|
||||
break;
|
||||
case 4:
|
||||
if (device_property_read_u32(hsotg->dev, property, &val32))
|
||||
return;
|
||||
|
@ -1100,13 +1088,13 @@ static void dwc2_set_gadget_dma(struct dwc2_hsotg *hsotg)
|
|||
/* Buffer DMA */
|
||||
dwc2_set_param_bool(hsotg, &p->g_dma,
|
||||
false, "gadget-dma",
|
||||
true, false,
|
||||
dma_capable, false,
|
||||
dma_capable);
|
||||
|
||||
/* DMA Descriptor */
|
||||
dwc2_set_param_bool(hsotg, &p->g_dma_desc, false,
|
||||
"gadget-dma-desc",
|
||||
p->g_dma, false,
|
||||
!!hw->dma_desc_enable, false,
|
||||
!!hw->dma_desc_enable);
|
||||
}
|
||||
|
||||
|
@ -1130,8 +1118,14 @@ static void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
|
|||
|
||||
dwc2_set_param_bool(hsotg, &p->host_dma,
|
||||
false, "host-dma",
|
||||
true, false,
|
||||
dma_capable, false,
|
||||
dma_capable);
|
||||
dwc2_set_param_host_rx_fifo_size(hsotg,
|
||||
params->host_rx_fifo_size);
|
||||
dwc2_set_param_host_nperio_tx_fifo_size(hsotg,
|
||||
params->host_nperio_tx_fifo_size);
|
||||
dwc2_set_param_host_perio_tx_fifo_size(hsotg,
|
||||
params->host_perio_tx_fifo_size);
|
||||
}
|
||||
dwc2_set_param_dma_desc_enable(hsotg, params->dma_desc_enable);
|
||||
dwc2_set_param_dma_desc_fs_enable(hsotg, params->dma_desc_fs_enable);
|
||||
|
@ -1140,12 +1134,6 @@ static void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
|
|||
params->host_support_fs_ls_low_power);
|
||||
dwc2_set_param_enable_dynamic_fifo(hsotg,
|
||||
params->enable_dynamic_fifo);
|
||||
dwc2_set_param_host_rx_fifo_size(hsotg,
|
||||
params->host_rx_fifo_size);
|
||||
dwc2_set_param_host_nperio_tx_fifo_size(hsotg,
|
||||
params->host_nperio_tx_fifo_size);
|
||||
dwc2_set_param_host_perio_tx_fifo_size(hsotg,
|
||||
params->host_perio_tx_fifo_size);
|
||||
dwc2_set_param_max_transfer_size(hsotg,
|
||||
params->max_transfer_size);
|
||||
dwc2_set_param_max_packet_count(hsotg,
|
||||
|
|
|
@ -45,9 +45,7 @@
|
|||
#define DWC3_XHCI_RESOURCES_NUM 2
|
||||
|
||||
#define DWC3_SCRATCHBUF_SIZE 4096 /* each buffer is assumed to be 4KiB */
|
||||
#define DWC3_EVENT_SIZE 4 /* bytes */
|
||||
#define DWC3_EVENT_MAX_NUM 64 /* 2 events/endpoint */
|
||||
#define DWC3_EVENT_BUFFERS_SIZE (DWC3_EVENT_SIZE * DWC3_EVENT_MAX_NUM)
|
||||
#define DWC3_EVENT_BUFFERS_SIZE 4096
|
||||
#define DWC3_EVENT_TYPE_MASK 0xfe
|
||||
|
||||
#define DWC3_EVENT_TYPE_DEV 0
|
||||
|
@ -311,9 +309,8 @@
|
|||
#define DWC3_DCFG_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */
|
||||
#define DWC3_DCFG_SUPERSPEED (4 << 0)
|
||||
#define DWC3_DCFG_HIGHSPEED (0 << 0)
|
||||
#define DWC3_DCFG_FULLSPEED2 (1 << 0)
|
||||
#define DWC3_DCFG_FULLSPEED (1 << 0)
|
||||
#define DWC3_DCFG_LOWSPEED (2 << 0)
|
||||
#define DWC3_DCFG_FULLSPEED1 (3 << 0)
|
||||
|
||||
#define DWC3_DCFG_NUMP_SHIFT 17
|
||||
#define DWC3_DCFG_NUMP(n) (((n) >> DWC3_DCFG_NUMP_SHIFT) & 0x1f)
|
||||
|
@ -405,9 +402,8 @@
|
|||
#define DWC3_DSTS_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */
|
||||
#define DWC3_DSTS_SUPERSPEED (4 << 0)
|
||||
#define DWC3_DSTS_HIGHSPEED (0 << 0)
|
||||
#define DWC3_DSTS_FULLSPEED2 (1 << 0)
|
||||
#define DWC3_DSTS_FULLSPEED (1 << 0)
|
||||
#define DWC3_DSTS_LOWSPEED (2 << 0)
|
||||
#define DWC3_DSTS_FULLSPEED1 (3 << 0)
|
||||
|
||||
/* Device Generic Command Register */
|
||||
#define DWC3_DGCMD_SET_LMP 0x01
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/dwc3-omap.h>
|
||||
|
@ -510,7 +511,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
|
|||
|
||||
/* check the DMA Status */
|
||||
reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
|
||||
|
||||
irq_set_status_flags(omap->irq, IRQ_NOAUTOEN);
|
||||
ret = devm_request_threaded_irq(dev, omap->irq, dwc3_omap_interrupt,
|
||||
dwc3_omap_interrupt_thread, IRQF_SHARED,
|
||||
"dwc3-omap", omap);
|
||||
|
@ -531,7 +532,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
dwc3_omap_enable_irqs(omap);
|
||||
|
||||
enable_irq(omap->irq);
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
|
@ -552,6 +553,7 @@ static int dwc3_omap_remove(struct platform_device *pdev)
|
|||
extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb);
|
||||
extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
|
||||
dwc3_omap_disable_irqs(omap);
|
||||
disable_irq(omap->irq);
|
||||
of_platform_depopulate(omap->dev);
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#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_GLK 0x31aa
|
||||
|
||||
#define PCI_INTEL_BXT_DSM_UUID "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
|
||||
#define PCI_INTEL_BXT_FUNC_PMU_PWR 4
|
||||
|
@ -73,16 +74,6 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
|
|||
{
|
||||
struct platform_device *dwc3 = dwc->dwc3;
|
||||
struct pci_dev *pdev = dwc->pci;
|
||||
int ret;
|
||||
|
||||
struct property_entry sysdev_property[] = {
|
||||
PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
|
||||
{ },
|
||||
};
|
||||
|
||||
ret = platform_device_add_properties(dwc3, sysdev_property);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_AMD &&
|
||||
pdev->device == PCI_DEVICE_ID_AMD_NL_USB) {
|
||||
|
@ -105,6 +96,7 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
|
|||
PROPERTY_ENTRY_BOOL("snps,disable_scramble_quirk"),
|
||||
PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"),
|
||||
PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
|
||||
PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
|
||||
{ },
|
||||
};
|
||||
|
||||
|
@ -115,7 +107,8 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
|
|||
int ret;
|
||||
|
||||
struct property_entry properties[] = {
|
||||
PROPERTY_ENTRY_STRING("dr-mode", "peripheral"),
|
||||
PROPERTY_ENTRY_STRING("dr_mode", "peripheral"),
|
||||
PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -167,6 +160,7 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
|
|||
PROPERTY_ENTRY_BOOL("snps,usb3_lpm_capable"),
|
||||
PROPERTY_ENTRY_BOOL("snps,has-lpm-erratum"),
|
||||
PROPERTY_ENTRY_BOOL("snps,dis_enblslpm_quirk"),
|
||||
PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
|
||||
{ },
|
||||
};
|
||||
|
||||
|
@ -274,6 +268,7 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
|
|||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT_M), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBP), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GLK), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), },
|
||||
{ } /* Terminating Entry */
|
||||
};
|
||||
|
|
|
@ -39,18 +39,13 @@ static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep);
|
|||
static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
|
||||
struct dwc3_ep *dep, struct dwc3_request *req);
|
||||
|
||||
static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
|
||||
u32 len, u32 type, bool chain)
|
||||
static void dwc3_ep0_prepare_one_trb(struct dwc3 *dwc, u8 epnum,
|
||||
dma_addr_t buf_dma, u32 len, u32 type, bool chain)
|
||||
{
|
||||
struct dwc3_gadget_ep_cmd_params params;
|
||||
struct dwc3_trb *trb;
|
||||
struct dwc3_ep *dep;
|
||||
|
||||
int ret;
|
||||
|
||||
dep = dwc->eps[epnum];
|
||||
if (dep->flags & DWC3_EP_BUSY)
|
||||
return 0;
|
||||
|
||||
trb = &dwc->ep0_trb[dep->trb_enqueue];
|
||||
|
||||
|
@ -71,15 +66,23 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
|
|||
trb->ctrl |= (DWC3_TRB_CTRL_IOC
|
||||
| DWC3_TRB_CTRL_LST);
|
||||
|
||||
if (chain)
|
||||
trace_dwc3_prepare_trb(dep, trb);
|
||||
}
|
||||
|
||||
static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum)
|
||||
{
|
||||
struct dwc3_gadget_ep_cmd_params params;
|
||||
struct dwc3_ep *dep;
|
||||
int ret;
|
||||
|
||||
dep = dwc->eps[epnum];
|
||||
if (dep->flags & DWC3_EP_BUSY)
|
||||
return 0;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.param0 = upper_32_bits(dwc->ep0_trb_addr);
|
||||
params.param1 = lower_32_bits(dwc->ep0_trb_addr);
|
||||
|
||||
trace_dwc3_prepare_trb(dep, trb);
|
||||
|
||||
ret = dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_STARTTRANSFER, ¶ms);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -280,8 +283,9 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
|
|||
|
||||
complete(&dwc->ep0_in_setup);
|
||||
|
||||
ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8,
|
||||
dwc3_ep0_prepare_one_trb(dwc, 0, dwc->ctrl_req_addr, 8,
|
||||
DWC3_TRBCTL_CONTROL_SETUP, false);
|
||||
ret = dwc3_ep0_start_trans(dwc, 0);
|
||||
WARN_ON(ret < 0);
|
||||
}
|
||||
|
||||
|
@ -912,9 +916,9 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
|
|||
|
||||
dwc->ep0_next_event = DWC3_EP0_COMPLETE;
|
||||
|
||||
ret = dwc3_ep0_start_trans(dwc, epnum,
|
||||
dwc->ctrl_req_addr, 0,
|
||||
DWC3_TRBCTL_CONTROL_DATA, false);
|
||||
dwc3_ep0_prepare_one_trb(dwc, epnum, dwc->ctrl_req_addr,
|
||||
0, DWC3_TRBCTL_CONTROL_DATA, false);
|
||||
ret = dwc3_ep0_start_trans(dwc, epnum);
|
||||
WARN_ON(ret < 0);
|
||||
}
|
||||
}
|
||||
|
@ -993,9 +997,10 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
|
|||
req->direction = !!dep->number;
|
||||
|
||||
if (req->request.length == 0) {
|
||||
ret = dwc3_ep0_start_trans(dwc, dep->number,
|
||||
dwc3_ep0_prepare_one_trb(dwc, dep->number,
|
||||
dwc->ctrl_req_addr, 0,
|
||||
DWC3_TRBCTL_CONTROL_DATA, false);
|
||||
ret = dwc3_ep0_start_trans(dwc, dep->number);
|
||||
} else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
|
||||
&& (dep->number == 0)) {
|
||||
u32 transfer_size = 0;
|
||||
|
@ -1011,7 +1016,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
|
|||
if (req->request.length > DWC3_EP0_BOUNCE_SIZE) {
|
||||
transfer_size = ALIGN(req->request.length - maxpacket,
|
||||
maxpacket);
|
||||
ret = dwc3_ep0_start_trans(dwc, dep->number,
|
||||
dwc3_ep0_prepare_one_trb(dwc, dep->number,
|
||||
req->request.dma,
|
||||
transfer_size,
|
||||
DWC3_TRBCTL_CONTROL_DATA,
|
||||
|
@ -1023,18 +1028,20 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
|
|||
|
||||
dwc->ep0_bounced = true;
|
||||
|
||||
ret = dwc3_ep0_start_trans(dwc, dep->number,
|
||||
dwc3_ep0_prepare_one_trb(dwc, dep->number,
|
||||
dwc->ep0_bounce_addr, transfer_size,
|
||||
DWC3_TRBCTL_CONTROL_DATA, false);
|
||||
ret = dwc3_ep0_start_trans(dwc, dep->number);
|
||||
} else {
|
||||
ret = usb_gadget_map_request_by_dev(dwc->sysdev,
|
||||
&req->request, dep->number);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma,
|
||||
dwc3_ep0_prepare_one_trb(dwc, dep->number, req->request.dma,
|
||||
req->request.length, DWC3_TRBCTL_CONTROL_DATA,
|
||||
false);
|
||||
ret = dwc3_ep0_start_trans(dwc, dep->number);
|
||||
}
|
||||
|
||||
WARN_ON(ret < 0);
|
||||
|
@ -1048,8 +1055,9 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
|
|||
type = dwc->three_stage_setup ? DWC3_TRBCTL_CONTROL_STATUS3
|
||||
: DWC3_TRBCTL_CONTROL_STATUS2;
|
||||
|
||||
return dwc3_ep0_start_trans(dwc, dep->number,
|
||||
dwc3_ep0_prepare_one_trb(dwc, dep->number,
|
||||
dwc->ctrl_req_addr, 0, type, false);
|
||||
return dwc3_ep0_start_trans(dwc, dep->number);
|
||||
}
|
||||
|
||||
static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep)
|
||||
|
|
|
@ -180,11 +180,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
|
|||
if (req->request.status == -EINPROGRESS)
|
||||
req->request.status = status;
|
||||
|
||||
if (dwc->ep0_bounced && dep->number == 0)
|
||||
if (dwc->ep0_bounced && dep->number <= 1)
|
||||
dwc->ep0_bounced = false;
|
||||
else
|
||||
usb_gadget_unmap_request_by_dev(dwc->sysdev,
|
||||
&req->request, req->direction);
|
||||
|
||||
usb_gadget_unmap_request_by_dev(dwc->sysdev,
|
||||
&req->request, req->direction);
|
||||
|
||||
trace_dwc3_gadget_giveback(req);
|
||||
|
||||
|
@ -1720,7 +1720,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
|
|||
reg |= DWC3_DCFG_LOWSPEED;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
reg |= DWC3_DCFG_FULLSPEED1;
|
||||
reg |= DWC3_DCFG_FULLSPEED;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
reg |= DWC3_DCFG_HIGHSPEED;
|
||||
|
@ -2232,9 +2232,14 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
|
|||
|
||||
dep = dwc->eps[epnum];
|
||||
|
||||
if (!(dep->flags & DWC3_EP_ENABLED) &&
|
||||
!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
|
||||
return;
|
||||
if (!(dep->flags & DWC3_EP_ENABLED)) {
|
||||
if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
|
||||
return;
|
||||
|
||||
/* Handle only EPCMDCMPLT when EP disabled */
|
||||
if (event->endpoint_event != DWC3_DEPEVT_EPCMDCMPLT)
|
||||
return;
|
||||
}
|
||||
|
||||
if (epnum == 0 || epnum == 1) {
|
||||
dwc3_ep0_interrupt(dwc, event);
|
||||
|
@ -2531,8 +2536,7 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
|
|||
dwc->gadget.ep0->maxpacket = 64;
|
||||
dwc->gadget.speed = USB_SPEED_HIGH;
|
||||
break;
|
||||
case DWC3_DSTS_FULLSPEED2:
|
||||
case DWC3_DSTS_FULLSPEED1:
|
||||
case DWC3_DSTS_FULLSPEED:
|
||||
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64);
|
||||
dwc->gadget.ep0->maxpacket = 64;
|
||||
dwc->gadget.speed = USB_SPEED_FULL;
|
||||
|
|
|
@ -1694,9 +1694,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|||
value = min(w_length, (u16) 1);
|
||||
break;
|
||||
|
||||
/* function drivers must handle get/set altsetting; if there's
|
||||
* no get() method, we know only altsetting zero works.
|
||||
*/
|
||||
/* function drivers must handle get/set altsetting */
|
||||
case USB_REQ_SET_INTERFACE:
|
||||
if (ctrl->bRequestType != USB_RECIP_INTERFACE)
|
||||
goto unknown;
|
||||
|
@ -1705,7 +1703,13 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|||
f = cdev->config->interface[intf];
|
||||
if (!f)
|
||||
break;
|
||||
if (w_value && !f->set_alt)
|
||||
|
||||
/*
|
||||
* If there's no get_alt() method, we know only altsetting zero
|
||||
* works. There is no need to check if set_alt() is not NULL
|
||||
* as we check this in usb_add_function().
|
||||
*/
|
||||
if (w_value && !f->get_alt)
|
||||
break;
|
||||
value = f->set_alt(f, w_index, w_value);
|
||||
if (value == USB_GADGET_DELAYED_STATUS) {
|
||||
|
|
|
@ -2091,8 +2091,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
|
|||
|
||||
case FFS_STRING:
|
||||
/*
|
||||
* Strings are indexed from 1 (0 is magic ;) reserved
|
||||
* for languages list or some such)
|
||||
* Strings are indexed from 1 (0 is reserved
|
||||
* for languages list)
|
||||
*/
|
||||
if (*valuep > helper->ffs->strings_count)
|
||||
helper->ffs->strings_count = *valuep;
|
||||
|
@ -2252,7 +2252,7 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
|
|||
|
||||
if (len < sizeof(*d) ||
|
||||
d->bFirstInterfaceNumber >= ffs->interfaces_count ||
|
||||
!d->Reserved1)
|
||||
d->Reserved1)
|
||||
return -EINVAL;
|
||||
for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i)
|
||||
if (d->Reserved2[i])
|
||||
|
@ -3666,6 +3666,7 @@ static void ffs_closed(struct ffs_data *ffs)
|
|||
{
|
||||
struct ffs_dev *ffs_obj;
|
||||
struct f_fs_opts *opts;
|
||||
struct config_item *ci;
|
||||
|
||||
ENTER();
|
||||
ffs_dev_lock();
|
||||
|
@ -3689,8 +3690,11 @@ static void ffs_closed(struct ffs_data *ffs)
|
|||
|| !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount))
|
||||
goto done;
|
||||
|
||||
unregister_gadget_item(ffs_obj->opts->
|
||||
func_inst.group.cg_item.ci_parent->ci_parent);
|
||||
ci = opts->func_inst.group.cg_item.ci_parent->ci_parent;
|
||||
ffs_dev_unlock();
|
||||
|
||||
unregister_gadget_item(ci);
|
||||
return;
|
||||
done:
|
||||
ffs_dev_unlock();
|
||||
}
|
||||
|
|
|
@ -593,7 +593,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
|||
}
|
||||
status = usb_ep_enable(hidg->out_ep);
|
||||
if (status < 0) {
|
||||
ERROR(cdev, "Enable IN endpoint FAILED!\n");
|
||||
ERROR(cdev, "Enable OUT endpoint FAILED!\n");
|
||||
goto fail;
|
||||
}
|
||||
hidg->out_ep->driver_data = hidg;
|
||||
|
|
|
@ -1126,7 +1126,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
|||
/* data and/or status stage for control request */
|
||||
} else if (dev->state == STATE_DEV_SETUP) {
|
||||
|
||||
/* IN DATA+STATUS caller makes len <= wLength */
|
||||
len = min_t(size_t, len, dev->setup_wLength);
|
||||
if (dev->setup_in) {
|
||||
retval = setup_req (dev->gadget->ep0, dev->req, len);
|
||||
if (retval == 0) {
|
||||
|
@ -1734,10 +1734,12 @@ static struct usb_gadget_driver gadgetfs_driver = {
|
|||
* such as configuration notifications.
|
||||
*/
|
||||
|
||||
static int is_valid_config (struct usb_config_descriptor *config)
|
||||
static int is_valid_config(struct usb_config_descriptor *config,
|
||||
unsigned int total)
|
||||
{
|
||||
return config->bDescriptorType == USB_DT_CONFIG
|
||||
&& config->bLength == USB_DT_CONFIG_SIZE
|
||||
&& total >= USB_DT_CONFIG_SIZE
|
||||
&& config->bConfigurationValue != 0
|
||||
&& (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0
|
||||
&& (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0;
|
||||
|
@ -1762,7 +1764,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
|||
}
|
||||
spin_unlock_irq(&dev->lock);
|
||||
|
||||
if (len < (USB_DT_CONFIG_SIZE + USB_DT_DEVICE_SIZE + 4))
|
||||
if ((len < (USB_DT_CONFIG_SIZE + USB_DT_DEVICE_SIZE + 4)) ||
|
||||
(len > PAGE_SIZE * 4))
|
||||
return -EINVAL;
|
||||
|
||||
/* we might need to change message format someday */
|
||||
|
@ -1786,7 +1789,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
|||
/* full or low speed config */
|
||||
dev->config = (void *) kbuf;
|
||||
total = le16_to_cpu(dev->config->wTotalLength);
|
||||
if (!is_valid_config (dev->config) || total >= length)
|
||||
if (!is_valid_config(dev->config, total) ||
|
||||
total > length - USB_DT_DEVICE_SIZE)
|
||||
goto fail;
|
||||
kbuf += total;
|
||||
length -= total;
|
||||
|
@ -1795,10 +1799,13 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
|||
if (kbuf [1] == USB_DT_CONFIG) {
|
||||
dev->hs_config = (void *) kbuf;
|
||||
total = le16_to_cpu(dev->hs_config->wTotalLength);
|
||||
if (!is_valid_config (dev->hs_config) || total >= length)
|
||||
if (!is_valid_config(dev->hs_config, total) ||
|
||||
total > length - USB_DT_DEVICE_SIZE)
|
||||
goto fail;
|
||||
kbuf += total;
|
||||
length -= total;
|
||||
} else {
|
||||
dev->hs_config = NULL;
|
||||
}
|
||||
|
||||
/* could support multiple configs, using another encoding! */
|
||||
|
@ -1811,7 +1818,6 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
|||
|| dev->dev->bDescriptorType != USB_DT_DEVICE
|
||||
|| dev->dev->bNumConfigurations != 1)
|
||||
goto fail;
|
||||
dev->dev->bNumConfigurations = 1;
|
||||
dev->dev->bcdUSB = cpu_to_le16 (0x0200);
|
||||
|
||||
/* triggers gadgetfs_bind(); then we can enumerate. */
|
||||
|
|
|
@ -1317,7 +1317,11 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
|
|||
if (!ret)
|
||||
break;
|
||||
}
|
||||
if (!ret && !udc->driver)
|
||||
if (ret)
|
||||
ret = -ENODEV;
|
||||
else if (udc->driver)
|
||||
ret = -EBUSY;
|
||||
else
|
||||
goto found;
|
||||
} else {
|
||||
list_for_each_entry(udc, &udc_list, list) {
|
||||
|
|
|
@ -330,7 +330,7 @@ static void nuke(struct dummy *dum, struct dummy_ep *ep)
|
|||
/* caller must hold lock */
|
||||
static void stop_activity(struct dummy *dum)
|
||||
{
|
||||
struct dummy_ep *ep;
|
||||
int i;
|
||||
|
||||
/* prevent any more requests */
|
||||
dum->address = 0;
|
||||
|
@ -338,8 +338,8 @@ static void stop_activity(struct dummy *dum)
|
|||
/* The timer is left running so that outstanding URBs can fail */
|
||||
|
||||
/* nuke any pending requests first, so driver i/o is quiesced */
|
||||
list_for_each_entry(ep, &dum->gadget.ep_list, ep.ep_list)
|
||||
nuke(dum, ep);
|
||||
for (i = 0; i < DUMMY_ENDPOINTS; ++i)
|
||||
nuke(dum, &dum->ep[i]);
|
||||
|
||||
/* driver now does any non-usb quiescing necessary */
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ struct usb_ext_prop_desc {
|
|||
* | 0 | magic | LE32 | FUNCTIONFS_DESCRIPTORS_MAGIC_V2 |
|
||||
* | 4 | length | LE32 | length of the whole data chunk |
|
||||
* | 8 | flags | LE32 | combination of functionfs_flags |
|
||||
* | | eventfd | LE32 | eventfd file descriptor |
|
||||
* | | fs_count | LE32 | number of full-speed descriptors |
|
||||
* | | hs_count | LE32 | number of high-speed descriptors |
|
||||
* | | ss_count | LE32 | number of super-speed descriptors |
|
||||
|
|
Loading…
Reference in New Issue