Skip to content

Commit

Permalink
Merge tag 'fixes-for-v4.10-rc3' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/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.
  • Loading branch information
gregkh committed Jan 3, 2017
2 parents 0c744ea + 43aef5c commit 8d6bbff
Show file tree
Hide file tree
Showing 14 changed files with 103 additions and 91 deletions.
2 changes: 1 addition & 1 deletion drivers/usb/dwc2/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
30 changes: 9 additions & 21 deletions drivers/usb/dwc2/params.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,26 +247,14 @@ 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) {
case 0:
*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;
Expand Down Expand Up @@ -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);
}

Expand All @@ -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);
Expand All @@ -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,
Expand Down
10 changes: 3 additions & 7 deletions drivers/usb/dwc3/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions drivers/usb/dwc3/dwc3-omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand All @@ -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:
Expand All @@ -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);
Expand Down
17 changes: 6 additions & 11 deletions drivers/usb/dwc3/dwc3-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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"),
{ },
};

Expand All @@ -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"),
{ }
};

Expand Down Expand Up @@ -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"),
{ },
};

Expand Down Expand Up @@ -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 */
};
Expand Down
46 changes: 27 additions & 19 deletions drivers/usb/dwc3/ep0.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];

Expand All @@ -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(&params, 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, &params);
if (ret < 0)
return ret;
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -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)
Expand Down
24 changes: 14 additions & 10 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
Loading

0 comments on commit 8d6bbff

Please sign in to comment.