Commit 8d6bbff6 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'fixes-for-v4.10-rc3' of...

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.
parents 0c744ea4 43aef5c2
...@@ -3753,7 +3753,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, ...@@ -3753,7 +3753,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
hs_ep->desc_list = dma_alloc_coherent(hsotg->dev, hs_ep->desc_list = dma_alloc_coherent(hsotg->dev,
MAX_DMA_DESC_NUM_GENERIC * MAX_DMA_DESC_NUM_GENERIC *
sizeof(struct dwc2_dma_desc), sizeof(struct dwc2_dma_desc),
&hs_ep->desc_list_dma, GFP_KERNEL); &hs_ep->desc_list_dma, GFP_ATOMIC);
if (!hs_ep->desc_list) { if (!hs_ep->desc_list) {
ret = -ENOMEM; ret = -ENOMEM;
goto error2; goto error2;
......
...@@ -247,8 +247,6 @@ MODULE_DEVICE_TABLE(of, dwc2_of_match_table); ...@@ -247,8 +247,6 @@ MODULE_DEVICE_TABLE(of, dwc2_of_match_table);
static void dwc2_get_device_property(struct dwc2_hsotg *hsotg, static void dwc2_get_device_property(struct dwc2_hsotg *hsotg,
char *property, u8 size, u64 *value) char *property, u8 size, u64 *value)
{ {
u8 val8;
u16 val16;
u32 val32; u32 val32;
switch (size) { switch (size) {
...@@ -256,17 +254,7 @@ static void dwc2_get_device_property(struct dwc2_hsotg *hsotg, ...@@ -256,17 +254,7 @@ static void dwc2_get_device_property(struct dwc2_hsotg *hsotg,
*value = device_property_read_bool(hsotg->dev, property); *value = device_property_read_bool(hsotg->dev, property);
break; break;
case 1: case 1:
if (device_property_read_u8(hsotg->dev, property, &val8))
return;
*value = val8;
break;
case 2: case 2:
if (device_property_read_u16(hsotg->dev, property, &val16))
return;
*value = val16;
break;
case 4: case 4:
if (device_property_read_u32(hsotg->dev, property, &val32)) if (device_property_read_u32(hsotg->dev, property, &val32))
return; return;
...@@ -1100,13 +1088,13 @@ static void dwc2_set_gadget_dma(struct dwc2_hsotg *hsotg) ...@@ -1100,13 +1088,13 @@ static void dwc2_set_gadget_dma(struct dwc2_hsotg *hsotg)
/* Buffer DMA */ /* Buffer DMA */
dwc2_set_param_bool(hsotg, &p->g_dma, dwc2_set_param_bool(hsotg, &p->g_dma,
false, "gadget-dma", false, "gadget-dma",
true, false, dma_capable, false,
dma_capable); dma_capable);
/* DMA Descriptor */ /* DMA Descriptor */
dwc2_set_param_bool(hsotg, &p->g_dma_desc, false, dwc2_set_param_bool(hsotg, &p->g_dma_desc, false,
"gadget-dma-desc", "gadget-dma-desc",
p->g_dma, false, !!hw->dma_desc_enable, false,
!!hw->dma_desc_enable); !!hw->dma_desc_enable);
} }
...@@ -1130,8 +1118,14 @@ static void dwc2_set_parameters(struct dwc2_hsotg *hsotg, ...@@ -1130,8 +1118,14 @@ static void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
dwc2_set_param_bool(hsotg, &p->host_dma, dwc2_set_param_bool(hsotg, &p->host_dma,
false, "host-dma", false, "host-dma",
true, false, dma_capable, false,
dma_capable); 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_enable(hsotg, params->dma_desc_enable);
dwc2_set_param_dma_desc_fs_enable(hsotg, params->dma_desc_fs_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, ...@@ -1140,12 +1134,6 @@ static void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
params->host_support_fs_ls_low_power); params->host_support_fs_ls_low_power);
dwc2_set_param_enable_dynamic_fifo(hsotg, dwc2_set_param_enable_dynamic_fifo(hsotg,
params->enable_dynamic_fifo); 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, dwc2_set_param_max_transfer_size(hsotg,
params->max_transfer_size); params->max_transfer_size);
dwc2_set_param_max_packet_count(hsotg, dwc2_set_param_max_packet_count(hsotg,
......
...@@ -45,9 +45,7 @@ ...@@ -45,9 +45,7 @@
#define DWC3_XHCI_RESOURCES_NUM 2 #define DWC3_XHCI_RESOURCES_NUM 2
#define DWC3_SCRATCHBUF_SIZE 4096 /* each buffer is assumed to be 4KiB */ #define DWC3_SCRATCHBUF_SIZE 4096 /* each buffer is assumed to be 4KiB */
#define DWC3_EVENT_SIZE 4 /* bytes */ #define DWC3_EVENT_BUFFERS_SIZE 4096
#define DWC3_EVENT_MAX_NUM 64 /* 2 events/endpoint */
#define DWC3_EVENT_BUFFERS_SIZE (DWC3_EVENT_SIZE * DWC3_EVENT_MAX_NUM)
#define DWC3_EVENT_TYPE_MASK 0xfe #define DWC3_EVENT_TYPE_MASK 0xfe
#define DWC3_EVENT_TYPE_DEV 0 #define DWC3_EVENT_TYPE_DEV 0
...@@ -311,9 +309,8 @@ ...@@ -311,9 +309,8 @@
#define DWC3_DCFG_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */ #define DWC3_DCFG_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */
#define DWC3_DCFG_SUPERSPEED (4 << 0) #define DWC3_DCFG_SUPERSPEED (4 << 0)
#define DWC3_DCFG_HIGHSPEED (0 << 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_LOWSPEED (2 << 0)
#define DWC3_DCFG_FULLSPEED1 (3 << 0)
#define DWC3_DCFG_NUMP_SHIFT 17 #define DWC3_DCFG_NUMP_SHIFT 17
#define DWC3_DCFG_NUMP(n) (((n) >> DWC3_DCFG_NUMP_SHIFT) & 0x1f) #define DWC3_DCFG_NUMP(n) (((n) >> DWC3_DCFG_NUMP_SHIFT) & 0x1f)
...@@ -405,9 +402,8 @@ ...@@ -405,9 +402,8 @@
#define DWC3_DSTS_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */ #define DWC3_DSTS_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */
#define DWC3_DSTS_SUPERSPEED (4 << 0) #define DWC3_DSTS_SUPERSPEED (4 << 0)
#define DWC3_DSTS_HIGHSPEED (0 << 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_LOWSPEED (2 << 0)
#define DWC3_DSTS_FULLSPEED1 (3 << 0)
/* Device Generic Command Register */ /* Device Generic Command Register */
#define DWC3_DGCMD_SET_LMP 0x01 #define DWC3_DGCMD_SET_LMP 0x01
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/platform_data/dwc3-omap.h> #include <linux/platform_data/dwc3-omap.h>
...@@ -510,7 +511,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) ...@@ -510,7 +511,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
/* check the DMA Status */ /* check the DMA Status */
reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG); 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, ret = devm_request_threaded_irq(dev, omap->irq, dwc3_omap_interrupt,
dwc3_omap_interrupt_thread, IRQF_SHARED, dwc3_omap_interrupt_thread, IRQF_SHARED,
"dwc3-omap", omap); "dwc3-omap", omap);
...@@ -531,7 +532,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) ...@@ -531,7 +532,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
} }
dwc3_omap_enable_irqs(omap); dwc3_omap_enable_irqs(omap);
enable_irq(omap->irq);
return 0; return 0;
err2: err2:
...@@ -552,6 +553,7 @@ static int dwc3_omap_remove(struct platform_device *pdev) ...@@ -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, &omap->vbus_nb);
extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb); extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
dwc3_omap_disable_irqs(omap); dwc3_omap_disable_irqs(omap);
disable_irq(omap->irq);
of_platform_depopulate(omap->dev); of_platform_depopulate(omap->dev);
pm_runtime_put_sync(&pdev->dev); pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa #define PCI_DEVICE_ID_INTEL_BXT_M 0x1aaa
#define PCI_DEVICE_ID_INTEL_APL 0x5aaa #define PCI_DEVICE_ID_INTEL_APL 0x5aaa
#define PCI_DEVICE_ID_INTEL_KBP 0xa2b0 #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_DSM_UUID "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
#define PCI_INTEL_BXT_FUNC_PMU_PWR 4 #define PCI_INTEL_BXT_FUNC_PMU_PWR 4
...@@ -73,16 +74,6 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) ...@@ -73,16 +74,6 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
{ {
struct platform_device *dwc3 = dwc->dwc3; struct platform_device *dwc3 = dwc->dwc3;
struct pci_dev *pdev = dwc->pci; 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 && if (pdev->vendor == PCI_VENDOR_ID_AMD &&
pdev->device == PCI_DEVICE_ID_AMD_NL_USB) { pdev->device == PCI_DEVICE_ID_AMD_NL_USB) {
...@@ -105,6 +96,7 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) ...@@ -105,6 +96,7 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
PROPERTY_ENTRY_BOOL("snps,disable_scramble_quirk"), PROPERTY_ENTRY_BOOL("snps,disable_scramble_quirk"),
PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"), PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"),
PROPERTY_ENTRY_BOOL("snps,dis_u2_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) ...@@ -115,7 +107,8 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
int ret; int ret;
struct property_entry properties[] = { 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) ...@@ -167,6 +160,7 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
PROPERTY_ENTRY_BOOL("snps,usb3_lpm_capable"), PROPERTY_ENTRY_BOOL("snps,usb3_lpm_capable"),
PROPERTY_ENTRY_BOOL("snps,has-lpm-erratum"), PROPERTY_ENTRY_BOOL("snps,has-lpm-erratum"),
PROPERTY_ENTRY_BOOL("snps,dis_enblslpm_quirk"), 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[] = { ...@@ -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_BXT_M), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), }, { 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_KBP), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GLK), },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), },
{ } /* Terminating Entry */ { } /* Terminating Entry */
}; };
......
...@@ -39,18 +39,13 @@ static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep); ...@@ -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, static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
struct dwc3_ep *dep, struct dwc3_request *req); struct dwc3_ep *dep, struct dwc3_request *req);
static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, static void dwc3_ep0_prepare_one_trb(struct dwc3 *dwc, u8 epnum,
u32 len, u32 type, bool chain) dma_addr_t buf_dma, u32 len, u32 type, bool chain)
{ {
struct dwc3_gadget_ep_cmd_params params;
struct dwc3_trb *trb; struct dwc3_trb *trb;
struct dwc3_ep *dep; struct dwc3_ep *dep;
int ret;
dep = dwc->eps[epnum]; dep = dwc->eps[epnum];
if (dep->flags & DWC3_EP_BUSY)
return 0;
trb = &dwc->ep0_trb[dep->trb_enqueue]; 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, ...@@ -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 trb->ctrl |= (DWC3_TRB_CTRL_IOC
| DWC3_TRB_CTRL_LST); | 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; return 0;
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
params.param0 = upper_32_bits(dwc->ep0_trb_addr); params.param0 = upper_32_bits(dwc->ep0_trb_addr);
params.param1 = lower_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, &params); ret = dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_STARTTRANSFER, &params);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -280,8 +283,9 @@ void dwc3_ep0_out_start(struct dwc3 *dwc) ...@@ -280,8 +283,9 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
complete(&dwc->ep0_in_setup); 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); DWC3_TRBCTL_CONTROL_SETUP, false);
ret = dwc3_ep0_start_trans(dwc, 0);
WARN_ON(ret < 0); WARN_ON(ret < 0);
} }
...@@ -912,9 +916,9 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, ...@@ -912,9 +916,9 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
dwc->ep0_next_event = DWC3_EP0_COMPLETE; dwc->ep0_next_event = DWC3_EP0_COMPLETE;
ret = dwc3_ep0_start_trans(dwc, epnum, dwc3_ep0_prepare_one_trb(dwc, epnum, dwc->ctrl_req_addr,
dwc->ctrl_req_addr, 0, 0, DWC3_TRBCTL_CONTROL_DATA, false);
DWC3_TRBCTL_CONTROL_DATA, false); ret = dwc3_ep0_start_trans(dwc, epnum);
WARN_ON(ret < 0); WARN_ON(ret < 0);
} }
} }
...@@ -993,9 +997,10 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, ...@@ -993,9 +997,10 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
req->direction = !!dep->number; req->direction = !!dep->number;
if (req->request.length == 0) { 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, dwc->ctrl_req_addr, 0,
DWC3_TRBCTL_CONTROL_DATA, false); DWC3_TRBCTL_CONTROL_DATA, false);
ret = dwc3_ep0_start_trans(dwc, dep->number);
} else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
&& (dep->number == 0)) { && (dep->number == 0)) {
u32 transfer_size = 0; u32 transfer_size = 0;
...@@ -1011,7 +1016,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, ...@@ -1011,7 +1016,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
if (req->request.length > DWC3_EP0_BOUNCE_SIZE) { if (req->request.length > DWC3_EP0_BOUNCE_SIZE) {
transfer_size = ALIGN(req->request.length - maxpacket, transfer_size = ALIGN(req->request.length - maxpacket,
maxpacket); maxpacket);
ret = dwc3_ep0_start_trans(dwc, dep->number, dwc3_ep0_prepare_one_trb(dwc, dep->number,
req->request.dma, req->request.dma,
transfer_size, transfer_size,
DWC3_TRBCTL_CONTROL_DATA, DWC3_TRBCTL_CONTROL_DATA,
...@@ -1023,18 +1028,20 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, ...@@ -1023,18 +1028,20 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
dwc->ep0_bounced = true; 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, dwc->ep0_bounce_addr, transfer_size,
DWC3_TRBCTL_CONTROL_DATA, false); DWC3_TRBCTL_CONTROL_DATA, false);
ret = dwc3_ep0_start_trans(dwc, dep->number);
} else { } else {
ret = usb_gadget_map_request_by_dev(dwc->sysdev, ret = usb_gadget_map_request_by_dev(dwc->sysdev,
&req->request, dep->number); &req->request, dep->number);
if (ret) if (ret)
return; 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, req->request.length, DWC3_TRBCTL_CONTROL_DATA,
false); false);
ret = dwc3_ep0_start_trans(dwc, dep->number);
} }
WARN_ON(ret < 0); WARN_ON(ret < 0);
...@@ -1048,8 +1055,9 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) ...@@ -1048,8 +1055,9 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
type = dwc->three_stage_setup ? DWC3_TRBCTL_CONTROL_STATUS3 type = dwc->three_stage_setup ? DWC3_TRBCTL_CONTROL_STATUS3
: DWC3_TRBCTL_CONTROL_STATUS2; : 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); 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) static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep)
......
...@@ -180,9 +180,9 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, ...@@ -180,9 +180,9 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
if (req->request.status == -EINPROGRESS) if (req->request.status == -EINPROGRESS)
req->request.status = status; req->request.status = status;
if (dwc->ep0_bounced && dep->number == 0) if (dwc->ep0_bounced && dep->number <= 1)
dwc->ep0_bounced = false; dwc->ep0_bounced = false;
else
usb_gadget_unmap_request_by_dev(dwc->sysdev, usb_gadget_unmap_request_by_dev(dwc->sysdev,
&req->request, req->direction); &req->request, req->direction);
...@@ -1720,7 +1720,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) ...@@ -1720,7 +1720,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
reg |= DWC3_DCFG_LOWSPEED; reg |= DWC3_DCFG_LOWSPEED;
break; break;
case USB_SPEED_FULL: case USB_SPEED_FULL:
reg |= DWC3_DCFG_FULLSPEED1; reg |= DWC3_DCFG_FULLSPEED;
break; break;
case USB_SPEED_HIGH: case USB_SPEED_HIGH:
reg |= DWC3_DCFG_HIGHSPEED; reg |= DWC3_DCFG_HIGHSPEED;
...@@ -2232,10 +2232,15 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, ...@@ -2232,10 +2232,15 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
dep = dwc->eps[epnum]; dep = dwc->eps[epnum];
if (!(dep->flags & DWC3_EP_ENABLED) && if (!(dep->flags & DWC3_EP_ENABLED)) {
!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
return; return;
/* Handle only EPCMDCMPLT when EP disabled */
if (event->endpoint_event != DWC3_DEPEVT_EPCMDCMPLT)
return;
}
if (epnum == 0 || epnum == 1) { if (epnum == 0 || epnum == 1) {
dwc3_ep0_interrupt(dwc, event); dwc3_ep0_interrupt(dwc, event);
return; return;
...@@ -2531,8 +2536,7 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) ...@@ -2531,8 +2536,7 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
dwc->gadget.ep0->maxpacket = 64; dwc->gadget.ep0->maxpacket = 64;
dwc->gadget.speed = USB_SPEED_HIGH; dwc->gadget.speed = USB_SPEED_HIGH;
break; break;
case DWC3_DSTS_FULLSPEED2: case DWC3_DSTS_FULLSPEED:
case DWC3_DSTS_FULLSPEED1:
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64);
dwc->gadget.ep0->maxpacket = 64; dwc->gadget.ep0->maxpacket = 64;
dwc->gadget.speed = USB_SPEED_FULL; dwc->gadget.speed = USB_SPEED_FULL;
......
...@@ -1694,9 +1694,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1694,9 +1694,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
value = min(w_length, (u16) 1); value = min(w_length, (u16) 1);
break; break;
/* function drivers must handle get/set altsetting; if there's /* function drivers must handle get/set altsetting */
* no get() method, we know only altsetting zero works.
*/
case USB_REQ_SET_INTERFACE: case USB_REQ_SET_INTERFACE:
if (ctrl->bRequestType != USB_RECIP_INTERFACE) if (ctrl->bRequestType != USB_RECIP_INTERFACE)
goto unknown; goto unknown;
...@@ -1705,7 +1703,13 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1705,7 +1703,13 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
f = cdev->config->interface[intf]; f = cdev->config->interface[intf];
if (!f) if (!f)
break; 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; break;
value = f->set_alt(f, w_index, w_value); value = f->set_alt(f, w_index, w_value);
if (value == USB_GADGET_DELAYED_STATUS) { if (value == USB_GADGET_DELAYED_STATUS) {
......
...@@ -2091,8 +2091,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type, ...@@ -2091,8 +2091,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
case FFS_STRING: case FFS_STRING:
/* /*
* Strings are indexed from 1 (0 is magic ;) reserved * Strings are indexed from 1 (0 is reserved
* for languages list or some such) * for languages list)
*/ */
if (*valuep > helper->ffs->strings_count) if (*valuep > helper->ffs->strings_count)
helper->ffs->strings_count = *valuep; helper->ffs->strings_count = *valuep;
...@@ -2252,7 +2252,7 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type, ...@@ -2252,7 +2252,7 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
if (len < sizeof(*d) || if (len < sizeof(*d) ||
d->bFirstInterfaceNumber >= ffs->interfaces_count || d->bFirstInterfaceNumber >= ffs->interfaces_count ||
!d->Reserved1) d->Reserved1)
return -EINVAL; return -EINVAL;
for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i) for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i)
if (d->Reserved2[i]) if (d->Reserved2[i])
...@@ -3666,6 +3666,7 @@ static void ffs_closed(struct ffs_data *ffs) ...@@ -3666,6 +3666,7 @@ static void ffs_closed(struct ffs_data *ffs)
{ {
struct ffs_dev *ffs_obj; struct ffs_dev *ffs_obj;
struct f_fs_opts *opts; struct f_fs_opts *opts;
struct config_item *ci;
ENTER(); ENTER();
ffs_dev_lock(); ffs_dev_lock();
...@@ -3689,8 +3690,11 @@ static void ffs_closed(struct ffs_data *ffs) ...@@ -3689,8 +3690,11 @@ static void ffs_closed(struct ffs_data *ffs)
|| !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount)) || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount))
goto done; goto done;
unregister_gadget_item(ffs_obj->opts-> ci = opts->func_inst.group.cg_item.ci_parent->ci_parent;
func_inst.group.cg_item.ci_parent->ci_parent); ffs_dev_unlock();
unregister_gadget_item(ci);
return;
done: done:
ffs_dev_unlock(); ffs_dev_unlock();
} }
......
...@@ -593,7 +593,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) ...@@ -593,7 +593,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
} }
status = usb_ep_enable(hidg->out_ep); status = usb_ep_enable(hidg->out_ep);
if (status < 0) { if (status < 0) {
ERROR(cdev, "Enable IN endpoint FAILED!\n"); ERROR(cdev, "Enable OUT endpoint FAILED!\n");
goto fail; goto fail;
} }
hidg->out_ep->driver_data = hidg; 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) ...@@ -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 */ /* data and/or status stage for control request */
} else if (dev->state == STATE_DEV_SETUP) { } 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) { if (dev->setup_in) {
retval = setup_req (dev->gadget->ep0, dev->req, len); retval = setup_req (dev->gadget->ep0, dev->req, len);
if (retval == 0) { if (retval == 0) {
...@@ -1734,10 +1734,12 @@ static struct usb_gadget_driver gadgetfs_driver = { ...@@ -1734,10 +1734,12 @@ static struct usb_gadget_driver gadgetfs_driver = {
* such as configuration notifications. * 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 return config->bDescriptorType == USB_DT_CONFIG
&& config->bLength == USB_DT_CONFIG_SIZE && config->bLength == USB_DT_CONFIG_SIZE
&& total >= USB_DT_CONFIG_SIZE
&& config->bConfigurationValue != 0 && config->bConfigurationValue != 0
&& (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0 && (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0
&& (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 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) ...@@ -1762,7 +1764,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
} }
spin_unlock_irq(&dev->lock); 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; return -EINVAL;
/* we might need to change message format someday */ /* 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) ...@@ -1786,7 +1789,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
/* full or low speed config */ /* full or low speed config */
dev->config = (void *) kbuf; dev->config = (void *) kbuf;
total = le16_to_cpu(dev->config->wTotalLength); 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; goto fail;
kbuf += total; kbuf += total;
length -= total; length -= total;
...@@ -1795,10 +1799,13 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) ...@@ -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) { if (kbuf [1] == USB_DT_CONFIG) {
dev->hs_config = (void *) kbuf; dev->hs_config = (void *) kbuf;
total = le16_to_cpu(dev->hs_config->wTotalLength); 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; goto fail;
kbuf += total; kbuf += total;
length -= total; length -= total;
} else {
dev->hs_config = NULL;
} }
/* could support multiple configs, using another encoding! */ /* 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) ...@@ -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->bDescriptorType != USB_DT_DEVICE
|| dev->dev->bNumConfigurations != 1) || dev->dev->bNumConfigurations != 1)
goto fail; goto fail;
dev->dev->bNumConfigurations = 1;
dev->dev->bcdUSB = cpu_to_le16 (0x0200); dev->dev->bcdUSB = cpu_to_le16 (0x0200);
/* triggers gadgetfs_bind(); then we can enumerate. */ /* triggers gadgetfs_bind(); then we can enumerate. */
......
...@@ -1317,7 +1317,11 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver) ...@@ -1317,7 +1317,11 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
if (!ret) if (!ret)
break; break;
} }
if (!ret && !udc->driver) if (ret)
ret = -ENODEV;
else if (udc->driver)
ret = -EBUSY;
else
goto found; goto found;
} else { } else {
list_for_each_entry(udc, &udc_list, list) { list_for_each_entry(udc, &udc_list, list) {
......
...@@ -330,7 +330,7 @@ static void nuke(struct dummy *dum, struct dummy_ep *ep) ...@@ -330,7 +330,7 @@ static void nuke(struct dummy *dum, struct dummy_ep *ep)
/* caller must hold lock */ /* caller must hold lock */
static void stop_activity(struct dummy *dum) static void stop_activity(struct dummy *dum)
{ {
struct dummy_ep *ep; int i;
/* prevent any more requests */ /* prevent any more requests */
dum->address = 0; dum->address = 0;
...@@ -338,8 +338,8 @@ static void stop_activity(struct dummy *dum) ...@@ -338,8 +338,8 @@ static void stop_activity(struct dummy *dum)
/* The timer is left running so that outstanding URBs can fail */ /* The timer is left running so that outstanding URBs can fail */
/* nuke any pending requests first, so driver i/o is quiesced */ /* nuke any pending requests first, so driver i/o is quiesced */
list_for_each_entry(ep, &dum->gadget.ep_list, ep.ep_list) for (i = 0; i < DUMMY_ENDPOINTS; ++i)
nuke(dum, ep); nuke(dum, &dum->ep[i]);
/* driver now does any non-usb quiescing necessary */ /* driver now does any non-usb quiescing necessary */
} }
......
...@@ -93,6 +93,7 @@ struct usb_ext_prop_desc { ...@@ -93,6 +93,7 @@ struct usb_ext_prop_desc {
* | 0 | magic | LE32 | FUNCTIONFS_DESCRIPTORS_MAGIC_V2 | * | 0 | magic | LE32 | FUNCTIONFS_DESCRIPTORS_MAGIC_V2 |
* | 4 | length | LE32 | length of the whole data chunk | * | 4 | length | LE32 | length of the whole data chunk |
* | 8 | flags | LE32 | combination of functionfs_flags | * | 8 | flags | LE32 | combination of functionfs_flags |
* | | eventfd | LE32 | eventfd file descriptor |
* | | fs_count | LE32 | number of full-speed descriptors | * | | fs_count | LE32 | number of full-speed descriptors |
* | | hs_count | LE32 | number of high-speed descriptors | * | | hs_count | LE32 | number of high-speed descriptors |
* | | ss_count | LE32 | number of super-speed descriptors | * | | ss_count | LE32 | number of super-speed descriptors |
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment