Commit dc8b2a69 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'usb-for-v5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

Felipe writes:

USB: changes for v5.1 merge window

Dwc3 now works on TI's AM6xx platforms. Also on dwc3 we have a few
changes which improve request cancellation and some improvements to
how we print to the trace buffer.

Renesas_usb3 got support for r8a774c0 device.

Dwc2 got scatter-gather support.

Apart from these, the usual set of minor fixes and all sorts of small
details.

* tag 'usb-for-v5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb: (40 commits)
  usb: phy: twl6030-usb: fix possible use-after-free on remove
  usb: misc: usbtest: add super-speed isoc support
  usb: dwc3: Reset num_trbs after skipping
  usb: dwc3: gadget: don't enable interrupt when disabling endpoint
  fotg210-udc: pass struct device to DMA API functions
  fotg210-udc: remove a bogus dma_sync_single_for_device call
  usb: gadget: Change Andrzej Pietrasiewicz's e-mail address
  usb: f_fs: Avoid crash due to out-of-scope stack ptr access
  usb: dwc3: haps: Workaround matching VID PID
  usb: gadget: f_fs: preserve wMaxPacketSize across usb_ep_autoconfig() call
  usb: gadget: move non-super speed code out of usb_ep_autoconfig_ss()
  usb: gadget: function: sync f_uac1 ac header baInterfaceNr
  usb: dwc2: gadget: Add scatter-gather mode
  usb: gadget: fix various indentation issues
  usb: dwc2: Fix EP TxFIFO number setting
  udc: net2280: Fix net2280_disable
  USB: gadget: Improve kerneldoc for usb_ep_dequeue()
  usb: dwc3: debug: purge usage of strcat
  usb: dwc3: trace: pass trace buffer size to decoding functions
  usb: dwc3: gadget: remove DWC3_EP_END_TRANSFER_PENDING
  ...
parents 09aa11cf 5895d311
...@@ -3,7 +3,9 @@ TI Keystone Soc USB Controller ...@@ -3,7 +3,9 @@ TI Keystone Soc USB Controller
DWC3 GLUE DWC3 GLUE
Required properties: Required properties:
- compatible: should be "ti,keystone-dwc3". - compatible: should be
"ti,keystone-dwc3" for Keystone 2 SoCs
"ti,am654-dwc3" for AM654 SoC
- #address-cells, #size-cells : should be '1' if the device has sub-nodes - #address-cells, #size-cells : should be '1' if the device has sub-nodes
with 'reg' property. with 'reg' property.
- reg : Address and length of the register set for the USB subsystem on - reg : Address and length of the register set for the USB subsystem on
...@@ -21,7 +23,7 @@ SoCs only: ...@@ -21,7 +23,7 @@ SoCs only:
- clock-names: Must be "usb". - clock-names: Must be "usb".
The following are mandatory properties for Keystone 2 66AK2G SoCs only: The following are mandatory properties for 66AK2G and AM654:
- power-domains: Should contain a phandle to a PM domain provider node - power-domains: Should contain a phandle to a PM domain provider node
and an args specifier containing the USB device id and an args specifier containing the USB device id
......
...@@ -4,6 +4,7 @@ Required properties: ...@@ -4,6 +4,7 @@ Required properties:
- compatible: Compatible list, contains - compatible: Compatible list, contains
"qcom,dwc3" "qcom,dwc3"
"qcom,msm8996-dwc3" for msm8996 SOC. "qcom,msm8996-dwc3" for msm8996 SOC.
"qcom,msm8998-dwc3" for msm8998 SOC.
"qcom,sdm845-dwc3" for sdm845 SOC. "qcom,sdm845-dwc3" for sdm845 SOC.
- reg: Offset and length of register set for QSCRATCH wrapper - reg: Offset and length of register set for QSCRATCH wrapper
- power-domains: specifies a phandle to PM domain provider node - power-domains: specifies a phandle to PM domain provider node
......
...@@ -3,6 +3,7 @@ Renesas Electronics USB3.0 Peripheral driver ...@@ -3,6 +3,7 @@ Renesas Electronics USB3.0 Peripheral driver
Required properties: Required properties:
- compatible: Must contain one of the following: - compatible: Must contain one of the following:
- "renesas,r8a774a1-usb3-peri" - "renesas,r8a774a1-usb3-peri"
- "renesas,r8a774c0-usb3-peri"
- "renesas,r8a7795-usb3-peri" - "renesas,r8a7795-usb3-peri"
- "renesas,r8a7796-usb3-peri" - "renesas,r8a7796-usb3-peri"
- "renesas,r8a77965-usb3-peri" - "renesas,r8a77965-usb3-peri"
......
...@@ -7,6 +7,7 @@ Required properties: ...@@ -7,6 +7,7 @@ Required properties:
- "renesas,usbhs-r8a7744" for r8a7744 (RZ/G1N) compatible device - "renesas,usbhs-r8a7744" for r8a7744 (RZ/G1N) compatible device
- "renesas,usbhs-r8a7745" for r8a7745 (RZ/G1E) compatible device - "renesas,usbhs-r8a7745" for r8a7745 (RZ/G1E) compatible device
- "renesas,usbhs-r8a774a1" for r8a774a1 (RZ/G2M) compatible device - "renesas,usbhs-r8a774a1" for r8a774a1 (RZ/G2M) compatible device
- "renesas,usbhs-r8a774c0" for r8a774c0 (RZ/G2E) compatible device
- "renesas,usbhs-r8a7790" for r8a7790 (R-Car H2) compatible device - "renesas,usbhs-r8a7790" for r8a7790 (R-Car H2) compatible device
- "renesas,usbhs-r8a7791" for r8a7791 (R-Car M2-W) compatible device - "renesas,usbhs-r8a7791" for r8a7791 (R-Car M2-W) compatible device
- "renesas,usbhs-r8a7792" for r8a7792 (R-Car V2H) compatible device - "renesas,usbhs-r8a7792" for r8a7792 (R-Car V2H) compatible device
......
...@@ -768,22 +768,13 @@ static u32 dwc2_gadget_get_desc_params(struct dwc2_hsotg_ep *hs_ep, u32 *mask) ...@@ -768,22 +768,13 @@ static u32 dwc2_gadget_get_desc_params(struct dwc2_hsotg_ep *hs_ep, u32 *mask)
return desc_size; return desc_size;
} }
/* static void dwc2_gadget_fill_nonisoc_xfer_ddma_one(struct dwc2_hsotg_ep *hs_ep,
* dwc2_gadget_config_nonisoc_xfer_ddma - prepare non ISOC DMA desc chain. struct dwc2_dma_desc **desc,
* @hs_ep: The endpoint
* @dma_buff: DMA address to use
* @len: Length of the transfer
*
* This function will iterate over descriptor chain and fill its entries
* with corresponding information based on transfer data.
*/
static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep,
dma_addr_t dma_buff, dma_addr_t dma_buff,
unsigned int len) unsigned int len,
bool true_last)
{ {
struct dwc2_hsotg *hsotg = hs_ep->parent;
int dir_in = hs_ep->dir_in; int dir_in = hs_ep->dir_in;
struct dwc2_dma_desc *desc = hs_ep->desc_list;
u32 mps = hs_ep->ep.maxpacket; u32 mps = hs_ep->ep.maxpacket;
u32 maxsize = 0; u32 maxsize = 0;
u32 offset = 0; u32 offset = 0;
...@@ -798,39 +789,77 @@ static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep, ...@@ -798,39 +789,77 @@ static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep,
hs_ep->desc_count = 1; hs_ep->desc_count = 1;
for (i = 0; i < hs_ep->desc_count; ++i) { for (i = 0; i < hs_ep->desc_count; ++i) {
desc->status = 0; (*desc)->status = 0;
desc->status |= (DEV_DMA_BUFF_STS_HBUSY (*desc)->status |= (DEV_DMA_BUFF_STS_HBUSY
<< DEV_DMA_BUFF_STS_SHIFT); << DEV_DMA_BUFF_STS_SHIFT);
if (len > maxsize) { if (len > maxsize) {
if (!hs_ep->index && !dir_in) if (!hs_ep->index && !dir_in)
desc->status |= (DEV_DMA_L | DEV_DMA_IOC); (*desc)->status |= (DEV_DMA_L | DEV_DMA_IOC);
desc->status |= (maxsize << (*desc)->status |=
DEV_DMA_NBYTES_SHIFT & mask); maxsize << DEV_DMA_NBYTES_SHIFT & mask;
desc->buf = dma_buff + offset; (*desc)->buf = dma_buff + offset;
len -= maxsize; len -= maxsize;
offset += maxsize; offset += maxsize;
} else { } else {
desc->status |= (DEV_DMA_L | DEV_DMA_IOC); if (true_last)
(*desc)->status |= (DEV_DMA_L | DEV_DMA_IOC);
if (dir_in) if (dir_in)
desc->status |= (len % mps) ? DEV_DMA_SHORT : (*desc)->status |= (len % mps) ? DEV_DMA_SHORT :
((hs_ep->send_zlp) ? DEV_DMA_SHORT : 0); ((hs_ep->send_zlp && true_last) ?
if (len > maxsize) DEV_DMA_SHORT : 0);
dev_err(hsotg->dev, "wrong len %d\n", len);
desc->status |= (*desc)->status |=
len << DEV_DMA_NBYTES_SHIFT & mask; len << DEV_DMA_NBYTES_SHIFT & mask;
desc->buf = dma_buff + offset; (*desc)->buf = dma_buff + offset;
} }
desc->status &= ~DEV_DMA_BUFF_STS_MASK; (*desc)->status &= ~DEV_DMA_BUFF_STS_MASK;
desc->status |= (DEV_DMA_BUFF_STS_HREADY (*desc)->status |= (DEV_DMA_BUFF_STS_HREADY
<< DEV_DMA_BUFF_STS_SHIFT); << DEV_DMA_BUFF_STS_SHIFT);
desc++; (*desc)++;
}
}
/*
* dwc2_gadget_config_nonisoc_xfer_ddma - prepare non ISOC DMA desc chain.
* @hs_ep: The endpoint
* @ureq: Request to transfer
* @offset: offset in bytes
* @len: Length of the transfer
*
* This function will iterate over descriptor chain and fill its entries
* with corresponding information based on transfer data.
*/
static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep,
struct usb_request *ureq,
unsigned int offset,
unsigned int len)
{
struct dwc2_dma_desc *desc = hs_ep->desc_list;
struct scatterlist *sg;
int i;
u8 desc_count = 0;
/* non-DMA sg buffer */
if (!ureq->num_sgs) {
dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc,
ureq->dma + offset, len, true);
return;
} }
/* DMA sg buffer */
for_each_sg(ureq->sg, sg, ureq->num_sgs, i) {
dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc,
sg_dma_address(sg) + sg->offset, sg_dma_len(sg),
sg_is_last(sg));
desc_count += hs_ep->desc_count;
}
hs_ep->desc_count = desc_count;
} }
/* /*
...@@ -944,7 +973,13 @@ static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep) ...@@ -944,7 +973,13 @@ static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep)
hs_ep->next_desc = 0; hs_ep->next_desc = 0;
list_for_each_entry_safe(hs_req, treq, &hs_ep->queue, queue) { list_for_each_entry_safe(hs_req, treq, &hs_ep->queue, queue) {
ret = dwc2_gadget_fill_isoc_desc(hs_ep, hs_req->req.dma, dma_addr_t dma_addr = hs_req->req.dma;
if (hs_req->req.num_sgs) {
WARN_ON(hs_req->req.num_sgs > 1);
dma_addr = sg_dma_address(hs_req->req.sg);
}
ret = dwc2_gadget_fill_isoc_desc(hs_ep, dma_addr,
hs_req->req.length); hs_req->req.length);
if (ret) if (ret)
break; break;
...@@ -1100,7 +1135,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg, ...@@ -1100,7 +1135,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
offset = ureq->actual; offset = ureq->actual;
/* Fill DDMA chain entries */ /* Fill DDMA chain entries */
dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, ureq->dma + offset, dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, ureq, offset,
length); length);
/* write descriptor chain address to control register */ /* write descriptor chain address to control register */
...@@ -1399,7 +1434,13 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, ...@@ -1399,7 +1434,13 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
*/ */
if (using_desc_dma(hs) && hs_ep->isochronous) { if (using_desc_dma(hs) && hs_ep->isochronous) {
if (hs_ep->target_frame != TARGET_FRAME_INITIAL) { if (hs_ep->target_frame != TARGET_FRAME_INITIAL) {
dwc2_gadget_fill_isoc_desc(hs_ep, hs_req->req.dma, dma_addr_t dma_addr = hs_req->req.dma;
if (hs_req->req.num_sgs) {
WARN_ON(hs_req->req.num_sgs > 1);
dma_addr = sg_dma_address(hs_req->req.sg);
}
dwc2_gadget_fill_isoc_desc(hs_ep, dma_addr,
hs_req->req.length); hs_req->req.length);
} }
return 0; return 0;
...@@ -1987,13 +2028,12 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg, ...@@ -1987,13 +2028,12 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n", dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n",
index); index);
if (using_desc_dma(hsotg)) { if (using_desc_dma(hsotg)) {
/* Not specific buffer needed for ep0 ZLP */
dma_addr_t dma = hs_ep->desc_list_dma;
if (!index) if (!index)
dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep); dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep);
dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, dma, 0); /* Not specific buffer needed for ep0 ZLP */
dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &hs_ep->desc_list,
hs_ep->desc_list_dma, 0, true);
} else { } else {
dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) | dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
DXEPTSIZ_XFERSIZE(0), DXEPTSIZ_XFERSIZE(0),
...@@ -4005,6 +4045,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, ...@@ -4005,6 +4045,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
ret = -ENOMEM; ret = -ENOMEM;
goto error1; goto error1;
} }
epctrl &= ~(DXEPCTL_TXFNUM_LIMIT << DXEPCTL_TXFNUM_SHIFT);
hsotg->fifo_map |= 1 << fifo_index; hsotg->fifo_map |= 1 << fifo_index;
epctrl |= DXEPCTL_TXFNUM(fifo_index); epctrl |= DXEPCTL_TXFNUM(fifo_index);
hs_ep->fifo_index = fifo_index; hs_ep->fifo_index = fifo_index;
...@@ -4385,6 +4426,7 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget, ...@@ -4385,6 +4426,7 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget,
hsotg->enabled = 0; hsotg->enabled = 0;
spin_unlock_irqrestore(&hsotg->lock, flags); spin_unlock_irqrestore(&hsotg->lock, flags);
gadget->sg_supported = using_desc_dma(hsotg);
dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name); dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
return 0; return 0;
......
...@@ -88,11 +88,11 @@ config USB_DWC3_HAPS ...@@ -88,11 +88,11 @@ config USB_DWC3_HAPS
platform, please say 'Y' or 'M' here. platform, please say 'Y' or 'M' here.
config USB_DWC3_KEYSTONE config USB_DWC3_KEYSTONE
tristate "Texas Instruments Keystone2 Platforms" tristate "Texas Instruments Keystone2/AM654 Platforms"
depends on ARCH_KEYSTONE || COMPILE_TEST depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST
default USB_DWC3 default USB_DWC3
help help
Support of USB2/3 functionality in TI Keystone2 platforms. Support of USB2/3 functionality in TI Keystone2 and AM654 platforms.
Say 'Y' or 'M' here if you have one such device Say 'Y' or 'M' here if you have one such device
config USB_DWC3_OF_SIMPLE config USB_DWC3_OF_SIMPLE
......
...@@ -692,7 +692,6 @@ struct dwc3_ep { ...@@ -692,7 +692,6 @@ struct dwc3_ep {
#define DWC3_EP_WEDGE BIT(2) #define DWC3_EP_WEDGE BIT(2)
#define DWC3_EP_TRANSFER_STARTED BIT(3) #define DWC3_EP_TRANSFER_STARTED BIT(3)
#define DWC3_EP_PENDING_REQUEST BIT(5) #define DWC3_EP_PENDING_REQUEST BIT(5)
#define DWC3_EP_END_TRANSFER_PENDING BIT(7)
/* This last one is specific to EP0 */ /* This last one is specific to EP0 */
#define DWC3_EP0_DIR_IN BIT(31) #define DWC3_EP0_DIR_IN BIT(31)
...@@ -863,6 +862,7 @@ struct dwc3_hwparams { ...@@ -863,6 +862,7 @@ struct dwc3_hwparams {
* @num_pending_sgs: counter to pending sgs * @num_pending_sgs: counter to pending sgs
* @num_queued_sgs: counter to the number of sgs which already got queued * @num_queued_sgs: counter to the number of sgs which already got queued
* @remaining: amount of data remaining * @remaining: amount of data remaining
* @status: internal dwc3 request status tracking
* @epnum: endpoint number to which this request refers * @epnum: endpoint number to which this request refers
* @trb: pointer to struct dwc3_trb * @trb: pointer to struct dwc3_trb
* @trb_dma: DMA address of @trb * @trb_dma: DMA address of @trb
...@@ -871,7 +871,6 @@ struct dwc3_hwparams { ...@@ -871,7 +871,6 @@ struct dwc3_hwparams {
* or unaligned OUT) * or unaligned OUT)
* @direction: IN or OUT direction flag * @direction: IN or OUT direction flag
* @mapped: true when request has been dma-mapped * @mapped: true when request has been dma-mapped
* @started: request is started
*/ */
struct dwc3_request { struct dwc3_request {
struct usb_request request; struct usb_request request;
...@@ -883,6 +882,14 @@ struct dwc3_request { ...@@ -883,6 +882,14 @@ struct dwc3_request {
unsigned num_pending_sgs; unsigned num_pending_sgs;
unsigned int num_queued_sgs; unsigned int num_queued_sgs;
unsigned remaining; unsigned remaining;
unsigned int status;
#define DWC3_REQUEST_STATUS_QUEUED 0
#define DWC3_REQUEST_STATUS_STARTED 1
#define DWC3_REQUEST_STATUS_CANCELLED 2
#define DWC3_REQUEST_STATUS_COMPLETED 3
#define DWC3_REQUEST_STATUS_UNKNOWN -1
u8 epnum; u8 epnum;
struct dwc3_trb *trb; struct dwc3_trb *trb;
dma_addr_t trb_dma; dma_addr_t trb_dma;
...@@ -892,7 +899,6 @@ struct dwc3_request { ...@@ -892,7 +899,6 @@ struct dwc3_request {
unsigned needs_extra_trb:1; unsigned needs_extra_trb:1;
unsigned direction:1; unsigned direction:1;
unsigned mapped:1; unsigned mapped:1;
unsigned started:1;
}; };
/* /*
......
This diff is collapsed.
...@@ -106,6 +106,15 @@ static const struct pci_device_id dwc3_haps_id_table[] = { ...@@ -106,6 +106,15 @@ static const struct pci_device_id dwc3_haps_id_table[] = {
{ {
PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3), PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
/*
* i.MX6QP and i.MX7D platform use a PCIe controller with the
* same VID and PID as this USB controller. The system may
* incorrectly match this driver to that PCIe controller. To
* workaround this, specifically use class type USB to prevent
* incorrect driver matching.
*/
.class = (PCI_CLASS_SERIAL_USB << 8),
.class_mask = 0xffff00,
}, },
{ {
PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
......
...@@ -106,6 +106,10 @@ static int kdwc3_probe(struct platform_device *pdev) ...@@ -106,6 +106,10 @@ static int kdwc3_probe(struct platform_device *pdev)
goto err_irq; goto err_irq;
} }
/* IRQ processing not required currently for AM65 */
if (of_device_is_compatible(node, "ti,am654-dwc3"))
goto skip_irq;
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
dev_err(&pdev->dev, "missing irq\n"); dev_err(&pdev->dev, "missing irq\n");
...@@ -123,6 +127,7 @@ static int kdwc3_probe(struct platform_device *pdev) ...@@ -123,6 +127,7 @@ static int kdwc3_probe(struct platform_device *pdev)
kdwc3_enable_irqs(kdwc); kdwc3_enable_irqs(kdwc);
skip_irq:
error = of_platform_populate(node, NULL, NULL, dev); error = of_platform_populate(node, NULL, NULL, dev);
if (error) { if (error) {
dev_err(&pdev->dev, "failed to create dwc3 core\n"); dev_err(&pdev->dev, "failed to create dwc3 core\n");
...@@ -152,8 +157,11 @@ static int kdwc3_remove_core(struct device *dev, void *c) ...@@ -152,8 +157,11 @@ static int kdwc3_remove_core(struct device *dev, void *c)
static int kdwc3_remove(struct platform_device *pdev) static int kdwc3_remove(struct platform_device *pdev)
{ {
struct dwc3_keystone *kdwc = platform_get_drvdata(pdev); struct dwc3_keystone *kdwc = platform_get_drvdata(pdev);
struct device_node *node = pdev->dev.of_node;
if (!of_device_is_compatible(node, "ti,am654-dwc3"))
kdwc3_disable_irqs(kdwc);
kdwc3_disable_irqs(kdwc);
device_for_each_child(&pdev->dev, NULL, kdwc3_remove_core); device_for_each_child(&pdev->dev, NULL, kdwc3_remove_core);
pm_runtime_put_sync(kdwc->dev); pm_runtime_put_sync(kdwc->dev);
pm_runtime_disable(kdwc->dev); pm_runtime_disable(kdwc->dev);
...@@ -165,6 +173,7 @@ static int kdwc3_remove(struct platform_device *pdev) ...@@ -165,6 +173,7 @@ static int kdwc3_remove(struct platform_device *pdev)
static const struct of_device_id kdwc3_of_match[] = { static const struct of_device_id kdwc3_of_match[] = {
{ .compatible = "ti,keystone-dwc3", }, { .compatible = "ti,keystone-dwc3", },
{ .compatible = "ti,am654-dwc3" },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, kdwc3_of_match); MODULE_DEVICE_TABLE(of, kdwc3_of_match);
......
...@@ -595,6 +595,7 @@ static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = { ...@@ -595,6 +595,7 @@ static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = {
static const struct of_device_id dwc3_qcom_of_match[] = { static const struct of_device_id dwc3_qcom_of_match[] = {
{ .compatible = "qcom,dwc3" }, { .compatible = "qcom,dwc3" },
{ .compatible = "qcom,msm8996-dwc3" }, { .compatible = "qcom,msm8996-dwc3" },
{ .compatible = "qcom,msm8998-dwc3" },
{ .compatible = "qcom,sdm845-dwc3" }, { .compatible = "qcom,sdm845-dwc3" },
{ } { }
}; };
......
...@@ -174,7 +174,6 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep, ...@@ -174,7 +174,6 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
{ {
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
req->started = false;
list_del(&req->list); list_del(&req->list);
req->remaining = 0; req->remaining = 0;
req->needs_extra_trb = false; req->needs_extra_trb = false;
...@@ -209,6 +208,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, ...@@ -209,6 +208,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
dwc3_gadget_del_and_unmap_request(dep, req, status); dwc3_gadget_del_and_unmap_request(dep, req, status);
req->status = DWC3_REQUEST_STATUS_COMPLETED;
spin_unlock(&dwc->lock); spin_unlock(&dwc->lock);
usb_gadget_giveback_request(&dep->endpoint, &req->request); usb_gadget_giveback_request(&dep->endpoint, &req->request);
...@@ -384,19 +384,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, ...@@ -384,19 +384,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status); trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status);
if (ret == 0) { if (ret == 0 && DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
switch (DWC3_DEPCMD_CMD(cmd)) { dep->flags |= DWC3_EP_TRANSFER_STARTED;
case DWC3_DEPCMD_STARTTRANSFER: dwc3_gadget_ep_get_transfer_index(dep);
dep->flags |= DWC3_EP_TRANSFER_STARTED;
dwc3_gadget_ep_get_transfer_index(dep);
break;
case DWC3_DEPCMD_ENDTRANSFER:
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
break;
default:
/* nothing */
break;
}
} }
if (saved_config) { if (saved_config) {
...@@ -642,7 +632,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) ...@@ -642,7 +632,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
dep->type = usb_endpoint_type(desc); dep->type = usb_endpoint_type(desc);
dep->flags |= DWC3_EP_ENABLED; dep->flags |= DWC3_EP_ENABLED;
dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
reg |= DWC3_DALEPENA_EP(dep->number); reg |= DWC3_DALEPENA_EP(dep->number);
...@@ -698,12 +687,13 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) ...@@ -698,12 +687,13 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
return 0; return 0;
} }
static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force); static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
bool interrupt);
static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
{ {
struct dwc3_request *req; struct dwc3_request *req;
dwc3_stop_active_transfer(dep, true); dwc3_stop_active_transfer(dep, true, false);
/* - giveback all requests to gadget driver */ /* - giveback all requests to gadget driver */
while (!list_empty(&dep->started_list)) { while (!list_empty(&dep->started_list)) {
...@@ -748,7 +738,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) ...@@ -748,7 +738,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->stream_capable = false; dep->stream_capable = false;
dep->type = 0; dep->type = 0;
dep->flags &= DWC3_EP_END_TRANSFER_PENDING; dep->flags = 0;
/* Clear out the ep descriptors for non-ep0 */ /* Clear out the ep descriptors for non-ep0 */
if (dep->number > 1) { if (dep->number > 1) {
...@@ -847,6 +837,7 @@ static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep, ...@@ -847,6 +837,7 @@ static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep,
req->direction = dep->direction; req->direction = dep->direction;
req->epnum = dep->number; req->epnum = dep->number;
req->dep = dep; req->dep = dep;
req->status = DWC3_REQUEST_STATUS_UNKNOWN;
trace_dwc3_alloc_request(req); trace_dwc3_alloc_request(req);
...@@ -1360,7 +1351,7 @@ static int dwc3_gadget_start_isoc_quirk(struct dwc3_ep *dep) ...@@ -1360,7 +1351,7 @@ static int dwc3_gadget_start_isoc_quirk(struct dwc3_ep *dep)
* to wait for the next XferNotReady to test the command again * to wait for the next XferNotReady to test the command again
*/ */
if (cmd_status == 0) { if (cmd_status == 0) {
dwc3_stop_active_transfer(dep, true); dwc3_stop_active_transfer(dep, true, true);
return 0; return 0;
} }
} }
...@@ -1435,6 +1426,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) ...@@ -1435,6 +1426,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
&req->request, req->dep->name)) &req->request, req->dep->name))
return -EINVAL; return -EINVAL;
if (WARN(req->status < DWC3_REQUEST_STATUS_COMPLETED,
"%s: request %pK already in flight\n",
dep->name, &req->request))
return -EINVAL;
pm_runtime_get(dwc->dev); pm_runtime_get(dwc->dev);
req->request.actual = 0; req->request.actual = 0;
...@@ -1443,6 +1439,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) ...@@ -1443,6 +1439,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
trace_dwc3_ep_queue(req); trace_dwc3_ep_queue(req);
list_add_tail(&req->list, &dep->pending_list); list_add_tail(&req->list, &dep->pending_list);
req->status = DWC3_REQUEST_STATUS_QUEUED;
/* /*
* NOTICE: Isochronous endpoints should NEVER be prestarted. We must * NOTICE: Isochronous endpoints should NEVER be prestarted. We must
...@@ -1506,6 +1503,8 @@ static void dwc3_gadget_ep_skip_trbs(struct dwc3_ep *dep, struct dwc3_request *r ...@@ -1506,6 +1503,8 @@ static void dwc3_gadget_ep_skip_trbs(struct dwc3_ep *dep, struct dwc3_request *r
trb->ctrl &= ~DWC3_TRB_CTRL_HWO; trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
dwc3_ep_inc_deq(dep); dwc3_ep_inc_deq(dep);
} }
req->num_trbs = 0;
} }
static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep) static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep)
...@@ -1547,13 +1546,16 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, ...@@ -1547,13 +1546,16 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
} }
if (r == req) { if (r == req) {
/* wait until it is processed */ /* wait until it is processed */
dwc3_stop_active_transfer(dep, true); dwc3_stop_active_transfer(dep, true, true);
if (!r->trb) if (!r->trb)
goto out0; goto out0;
dwc3_gadget_move_cancelled_request(req); dwc3_gadget_move_cancelled_request(req);
goto out0; if (dep->flags & DWC3_EP_TRANSFER_STARTED)
goto out0;
else
goto out1;
} }
dev_err(dwc->dev, "request %pK was not queued to %s\n", dev_err(dwc->dev, "request %pK was not queued to %s\n",
request, ep->name); request, ep->name);
...@@ -1561,6 +1563,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, ...@@ -1561,6 +1563,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
goto out0; goto out0;
} }
out1:
dwc3_gadget_giveback(dep, req, -ECONNRESET); dwc3_gadget_giveback(dep, req, -ECONNRESET);
out0: out0:
...@@ -2500,7 +2503,7 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep, ...@@ -2500,7 +2503,7 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep,
dwc3_gadget_ep_cleanup_completed_requests(dep, event, status); dwc3_gadget_ep_cleanup_completed_requests(dep, event, status);
if (stop) { if (stop) {
dwc3_stop_active_transfer(dep, true); dwc3_stop_active_transfer(dep, true, true);
dep->flags = DWC3_EP_ENABLED; dep->flags = DWC3_EP_ENABLED;
} }
...@@ -2547,7 +2550,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, ...@@ -2547,7 +2550,7 @@ 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)) {
if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) if (!(dep->flags & DWC3_EP_TRANSFER_STARTED))
return; return;
/* Handle only EPCMDCMPLT when EP disabled */ /* Handle only EPCMDCMPLT when EP disabled */
...@@ -2571,7 +2574,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, ...@@ -2571,7 +2574,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
cmd = DEPEVT_PARAMETER_CMD(event->parameters); cmd = DEPEVT_PARAMETER_CMD(event->parameters);
if (cmd == DWC3_DEPCMD_ENDTRANSFER) { if (cmd == DWC3_DEPCMD_ENDTRANSFER) {
dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
dwc3_gadget_ep_cleanup_cancelled_requests(dep); dwc3_gadget_ep_cleanup_cancelled_requests(dep);
} }
break; break;
...@@ -2621,15 +2624,15 @@ static void dwc3_reset_gadget(struct dwc3 *dwc) ...@@ -2621,15 +2624,15 @@ static void dwc3_reset_gadget(struct dwc3 *dwc)
} }
} }
static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force) static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
bool interrupt)
{ {
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
struct dwc3_gadget_ep_cmd_params params; struct dwc3_gadget_ep_cmd_params params;
u32 cmd; u32 cmd;
int ret; int ret;
if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) || if (!(dep->flags & DWC3_EP_TRANSFER_STARTED))
!dep->resource_index)
return; return;
/* /*
...@@ -2665,17 +2668,15 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force) ...@@ -2665,17 +2668,15 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force)
cmd = DWC3_DEPCMD_ENDTRANSFER; cmd = DWC3_DEPCMD_ENDTRANSFER;
cmd |= force ? DWC3_DEPCMD_HIPRI_FORCERM : 0; cmd |= force ? DWC3_DEPCMD_HIPRI_FORCERM : 0;
cmd |= DWC3_DEPCMD_CMDIOC; cmd |= interrupt ? DWC3_DEPCMD_CMDIOC : 0;
cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params); ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
WARN_ON_ONCE(ret); WARN_ON_ONCE(ret);
dep->resource_index = 0; dep->resource_index = 0;
if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A) { if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A)
dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
udelay(100); udelay(100);
}
} }
static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
...@@ -3339,6 +3340,8 @@ int dwc3_gadget_init(struct dwc3 *dwc) ...@@ -3339,6 +3340,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err4; goto err4;
} }
dwc3_gadget_set_speed(&dwc->gadget, dwc->maximum_speed);
return 0; return 0;
err4: err4:
......
...@@ -75,7 +75,7 @@ static inline void dwc3_gadget_move_started_request(struct dwc3_request *req) ...@@ -75,7 +75,7 @@ static inline void dwc3_gadget_move_started_request(struct dwc3_request *req)
{ {
struct dwc3_ep *dep = req->dep; struct dwc3_ep *dep = req->dep;
req->started = true; req->status = DWC3_REQUEST_STATUS_STARTED;
list_move_tail(&req->list, &dep->started_list); list_move_tail(&req->list, &dep->started_list);
} }
...@@ -90,7 +90,7 @@ static inline void dwc3_gadget_move_cancelled_request(struct dwc3_request *req) ...@@ -90,7 +90,7 @@ static inline void dwc3_gadget_move_cancelled_request(struct dwc3_request *req)
{ {
struct dwc3_ep *dep = req->dep; struct dwc3_ep *dep = req->dep;
req->started = false; req->status = DWC3_REQUEST_STATUS_CANCELLED;
list_move_tail(&req->list, &dep->cancelled_list); list_move_tail(&req->list, &dep->cancelled_list);
} }
......
...@@ -59,8 +59,8 @@ DECLARE_EVENT_CLASS(dwc3_log_event, ...@@ -59,8 +59,8 @@ DECLARE_EVENT_CLASS(dwc3_log_event,
__entry->ep0state = dwc->ep0state; __entry->ep0state = dwc->ep0state;
), ),
TP_printk("event (%08x): %s", __entry->event, TP_printk("event (%08x): %s", __entry->event,
dwc3_decode_event(__get_str(str), __entry->event, dwc3_decode_event(__get_str(str), DWC3_MSG_MAX,
__entry->ep0state)) __entry->event, __entry->ep0state))
); );
DEFINE_EVENT(dwc3_log_event, dwc3_event, DEFINE_EVENT(dwc3_log_event, dwc3_event,
...@@ -86,7 +86,8 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl, ...@@ -86,7 +86,8 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
__entry->wIndex = le16_to_cpu(ctrl->wIndex); __entry->wIndex = le16_to_cpu(ctrl->wIndex);
__entry->wLength = le16_to_cpu(ctrl->wLength); __entry->wLength = le16_to_cpu(ctrl->wLength);
), ),
TP_printk("%s", dwc3_decode_ctrl(__get_str(str), __entry->bRequestType, TP_printk("%s", dwc3_decode_ctrl(__get_str(str), DWC3_MSG_MAX,
__entry->bRequestType,
__entry->bRequest, __entry->wValue, __entry->bRequest, __entry->wValue,
__entry->wIndex, __entry->wLength) __entry->wIndex, __entry->wLength)
) )
...@@ -305,7 +306,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep, ...@@ -305,7 +306,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep,
__entry->trb_enqueue = dep->trb_enqueue; __entry->trb_enqueue = dep->trb_enqueue;
__entry->trb_dequeue = dep->trb_dequeue; __entry->trb_dequeue = dep->trb_dequeue;
), ),
TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c:%c:%c", TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c:%c",
__get_str(name), __entry->maxpacket, __get_str(name), __entry->maxpacket,
__entry->maxpacket_limit, __entry->max_streams, __entry->maxpacket_limit, __entry->max_streams,
__entry->maxburst, __entry->trb_enqueue, __entry->maxburst, __entry->trb_enqueue,
...@@ -315,7 +316,6 @@ DECLARE_EVENT_CLASS(dwc3_log_ep, ...@@ -315,7 +316,6 @@ DECLARE_EVENT_CLASS(dwc3_log_ep,
__entry->flags & DWC3_EP_WEDGE ? 'W' : 'w', __entry->flags & DWC3_EP_WEDGE ? 'W' : 'w',
__entry->flags & DWC3_EP_TRANSFER_STARTED ? 'B' : 'b', __entry->flags & DWC3_EP_TRANSFER_STARTED ? 'B' : 'b',
__entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p', __entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p',
__entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e',
__entry->direction ? '<' : '>' __entry->direction ? '<' : '>'
) )
); );
......
...@@ -67,9 +67,6 @@ struct usb_ep *usb_ep_autoconfig_ss( ...@@ -67,9 +67,6 @@ struct usb_ep *usb_ep_autoconfig_ss(
) )
{ {
struct usb_ep *ep; struct usb_ep *ep;
u8 type;
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
if (gadget->ops->match_ep) { if (gadget->ops->match_ep) {
ep = gadget->ops->match_ep(gadget, desc, ep_comp); ep = gadget->ops->match_ep(gadget, desc, ep_comp);
...@@ -109,16 +106,6 @@ struct usb_ep *usb_ep_autoconfig_ss( ...@@ -109,16 +106,6 @@ struct usb_ep *usb_ep_autoconfig_ss(
desc->bEndpointAddress |= gadget->out_epnum; desc->bEndpointAddress |= gadget->out_epnum;
} }
/* report (variable) full speed bulk maxpacket */
if ((type == USB_ENDPOINT_XFER_BULK) && !ep_comp) {
int size = ep->maxpacket_limit;
/* min() doesn't work on bitfields with gcc-3.5 */
if (size > 64)
size = 64;
desc->wMaxPacketSize = cpu_to_le16(size);
}
ep->address = desc->bEndpointAddress; ep->address = desc->bEndpointAddress;
ep->desc = NULL; ep->desc = NULL;
ep->comp_desc = NULL; ep->comp_desc = NULL;
...@@ -152,9 +139,10 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss); ...@@ -152,9 +139,10 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
* *
* On success, this returns an claimed usb_ep, and modifies the endpoint * On success, this returns an claimed usb_ep, and modifies the endpoint
* descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
* is initialized as if the endpoint were used at full speed. To prevent * is initialized as if the endpoint were used at full speed. Because of
* the endpoint from being returned by a later autoconfig call, claims it * that the users must consider adjusting the autoconfigured descriptor.
* by assigning ep->claimed to true. * To prevent the endpoint from being returned by a later autoconfig call,
* claims it by assigning ep->claimed to true.
* *
* On failure, this returns a null endpoint descriptor. * On failure, this returns a null endpoint descriptor.
*/ */
...@@ -163,7 +151,26 @@ struct usb_ep *usb_ep_autoconfig( ...@@ -163,7 +151,26 @@ struct usb_ep *usb_ep_autoconfig(
struct usb_endpoint_descriptor *desc struct usb_endpoint_descriptor *desc
) )
{ {
return usb_ep_autoconfig_ss(gadget, desc, NULL); struct usb_ep *ep;
u8 type;
ep = usb_ep_autoconfig_ss(gadget, desc, NULL);
if (!ep)
return NULL;
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
/* report (variable) full speed bulk maxpacket */
if (type == USB_ENDPOINT_XFER_BULK) {
int size = ep->maxpacket_limit;
/* min() doesn't work on bitfields with gcc-3.5 */
if (size > 64)
size = 64;
desc->wMaxPacketSize = cpu_to_le16(size);
}
return ep;
} }
EXPORT_SYMBOL_GPL(usb_ep_autoconfig); EXPORT_SYMBOL_GPL(usb_ep_autoconfig);
......
...@@ -1082,6 +1082,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) ...@@ -1082,6 +1082,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
* condition with req->complete callback. * condition with req->complete callback.
*/ */
usb_ep_dequeue(ep->ep, req); usb_ep_dequeue(ep->ep, req);
wait_for_completion(&done);
interrupted = ep->status < 0; interrupted = ep->status < 0;
} }
...@@ -2843,12 +2844,18 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, ...@@ -2843,12 +2844,18 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
struct usb_request *req; struct usb_request *req;
struct usb_ep *ep; struct usb_ep *ep;
u8 bEndpointAddress; u8 bEndpointAddress;
u16 wMaxPacketSize;
/* /*
* We back up bEndpointAddress because autoconfig overwrites * We back up bEndpointAddress because autoconfig overwrites
* it with physical endpoint address. * it with physical endpoint address.
*/ */
bEndpointAddress = ds->bEndpointAddress; bEndpointAddress = ds->bEndpointAddress;
/*
* We back up wMaxPacketSize because autoconfig treats
* endpoint descriptors as if they were full speed.
*/
wMaxPacketSize = ds->wMaxPacketSize;
pr_vdebug("autoconfig\n"); pr_vdebug("autoconfig\n");
ep = usb_ep_autoconfig(func->gadget, ds); ep = usb_ep_autoconfig(func->gadget, ds);
if (unlikely(!ep)) if (unlikely(!ep))
...@@ -2869,6 +2876,11 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, ...@@ -2869,6 +2876,11 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
*/ */
if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR) if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
ds->bEndpointAddress = bEndpointAddress; ds->bEndpointAddress = bEndpointAddress;
/*
* Restore wMaxPacketSize which was potentially
* overwritten by autoconfig.
*/
ds->wMaxPacketSize = wMaxPacketSize;
} }
ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength); ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength);
......
...@@ -459,10 +459,10 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt) ...@@ -459,10 +459,10 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
} else if (intf == uac1->as_in_intf) { } else if (intf == uac1->as_in_intf) {
uac1->as_in_alt = alt; uac1->as_in_alt = alt;
if (alt) if (alt)
ret = u_audio_start_playback(&uac1->g_audio); ret = u_audio_start_playback(&uac1->g_audio);
else else
u_audio_stop_playback(&uac1->g_audio); u_audio_stop_playback(&uac1->g_audio);
} else { } else {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
return -EINVAL; return -EINVAL;
...@@ -568,6 +568,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -568,6 +568,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
goto fail; goto fail;
as_out_interface_alt_0_desc.bInterfaceNumber = status; as_out_interface_alt_0_desc.bInterfaceNumber = status;
as_out_interface_alt_1_desc.bInterfaceNumber = status; as_out_interface_alt_1_desc.bInterfaceNumber = status;
ac_header_desc.baInterfaceNr[0] = status;
uac1->as_out_intf = status; uac1->as_out_intf = status;
uac1->as_out_alt = 0; uac1->as_out_alt = 0;
...@@ -576,6 +577,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -576,6 +577,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
goto fail; goto fail;
as_in_interface_alt_0_desc.bInterfaceNumber = status; as_in_interface_alt_0_desc.bInterfaceNumber = status;
as_in_interface_alt_1_desc.bInterfaceNumber = status; as_in_interface_alt_1_desc.bInterfaceNumber = status;
ac_header_desc.baInterfaceNr[1] = status;
uac1->as_in_intf = status; uac1->as_in_intf = status;
uac1->as_in_alt = 0; uac1->as_in_alt = 0;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd. * Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef U_ECM_H #ifndef U_ECM_H
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd. * Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef U_EEM_H #ifndef U_EEM_H
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd. * Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef __U_ETHER_CONFIGFS_H #ifndef __U_ETHER_CONFIGFS_H
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd. * Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef U_FFS_H #ifndef U_FFS_H
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd. * Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef U_GETHER_H #ifndef U_GETHER_H
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd. * Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef U_HID_H #ifndef U_HID_H
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd. * Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef U_MIDI_H #ifndef U_MIDI_H
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd. * Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef U_NCM_H #ifndef U_NCM_H
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2015 Samsung Electronics Co., Ltd. * Copyright (c) 2015 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef U_PRINTER_H #ifndef U_PRINTER_H
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd. * Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef U_RNDIS_H #ifndef U_RNDIS_H
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/tty.h> #include <linux/tty.h>
...@@ -26,6 +25,7 @@ ...@@ -26,6 +25,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/workqueue.h>
#include <linux/kfifo.h> #include <linux/kfifo.h>
#include "u_serial.h" #include "u_serial.h"
...@@ -110,7 +110,7 @@ struct gs_port { ...@@ -110,7 +110,7 @@ struct gs_port {
int read_allocated; int read_allocated;
struct list_head read_queue; struct list_head read_queue;
unsigned n_read; unsigned n_read;
struct tasklet_struct push; struct delayed_work push;
struct list_head write_pool; struct list_head write_pool;
int write_started; int write_started;
...@@ -352,9 +352,10 @@ __acquires(&port->port_lock) ...@@ -352,9 +352,10 @@ __acquires(&port->port_lock)
* So QUEUE_SIZE packets plus however many the FIFO holds (usually two) * So QUEUE_SIZE packets plus however many the FIFO holds (usually two)
* can be buffered before the TTY layer's buffers (currently 64 KB). * can be buffered before the TTY layer's buffers (currently 64 KB).
*/ */
static void gs_rx_push(unsigned long _port) static void gs_rx_push(struct work_struct *work)
{ {
struct gs_port *port = (void *)_port; struct delayed_work *w = to_delayed_work(work);
struct gs_port *port = container_of(w, struct gs_port, push);
struct tty_struct *tty; struct tty_struct *tty;
struct list_head *queue = &port->read_queue; struct list_head *queue = &port->read_queue;
bool disconnect = false; bool disconnect = false;
...@@ -429,21 +430,13 @@ static void gs_rx_push(unsigned long _port) ...@@ -429,21 +430,13 @@ static void gs_rx_push(unsigned long _port)
/* We want our data queue to become empty ASAP, keeping data /* We want our data queue to become empty ASAP, keeping data
* in the tty and ldisc (not here). If we couldn't push any * in the tty and ldisc (not here). If we couldn't push any
* this time around, there may be trouble unless there's an * this time around, RX may be starved, so wait until next jiffy.
* implicit tty_unthrottle() call on its way...
* *
* REVISIT we should probably add a timer to keep the tasklet * We may leave non-empty queue only when there is a tty, and
* from starving ... but it's not clear that case ever happens. * either it is throttled or there is no more room in flip buffer.
*/ */
if (!list_empty(queue) && tty) { if (!list_empty(queue) && !tty_throttled(tty))
if (!tty_throttled(tty)) { schedule_delayed_work(&port->push, 1);
if (do_push)
tasklet_schedule(&port->push);
else
pr_warn("ttyGS%d: RX not scheduled?\n",
port->port_num);
}
}
/* If we're still connected, refill the USB RX queue. */ /* If we're still connected, refill the USB RX queue. */
if (!disconnect && port->port_usb) if (!disconnect && port->port_usb)
...@@ -459,7 +452,7 @@ static void gs_read_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -459,7 +452,7 @@ static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
/* Queue all received data until the tty layer is ready for it. */ /* Queue all received data until the tty layer is ready for it. */
spin_lock(&port->port_lock); spin_lock(&port->port_lock);
list_add_tail(&req->list, &port->read_queue); list_add_tail(&req->list, &port->read_queue);
tasklet_schedule(&port->push); schedule_delayed_work(&port->push, 0);
spin_unlock(&port->port_lock); spin_unlock(&port->port_lock);
} }
...@@ -854,8 +847,8 @@ static void gs_unthrottle(struct tty_struct *tty) ...@@ -854,8 +847,8 @@ static void gs_unthrottle(struct tty_struct *tty)
* rts/cts, or other handshaking with the host, but if the * rts/cts, or other handshaking with the host, but if the
* read queue backs up enough we'll be NAKing OUT packets. * read queue backs up enough we'll be NAKing OUT packets.
*/ */
tasklet_schedule(&port->push);
pr_vdebug("ttyGS%d: unthrottle\n", port->port_num); pr_vdebug("ttyGS%d: unthrottle\n", port->port_num);
schedule_delayed_work(&port->push, 0);
} }
spin_unlock_irqrestore(&port->port_lock, flags); spin_unlock_irqrestore(&port->port_lock, flags);
} }
...@@ -1159,7 +1152,7 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding) ...@@ -1159,7 +1152,7 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
init_waitqueue_head(&port->drain_wait); init_waitqueue_head(&port->drain_wait);
init_waitqueue_head(&port->close_wait); init_waitqueue_head(&port->close_wait);
tasklet_init(&port->push, gs_rx_push, (unsigned long) port); INIT_DELAYED_WORK(&port->push, gs_rx_push);
INIT_LIST_HEAD(&port->read_pool); INIT_LIST_HEAD(&port->read_pool);
INIT_LIST_HEAD(&port->read_queue); INIT_LIST_HEAD(&port->read_queue);
...@@ -1186,7 +1179,7 @@ static int gs_closed(struct gs_port *port) ...@@ -1186,7 +1179,7 @@ static int gs_closed(struct gs_port *port)
static void gserial_free_port(struct gs_port *port) static void gserial_free_port(struct gs_port *port)
{ {
tasklet_kill(&port->push); cancel_delayed_work_sync(&port->push);
/* wait for old opens to finish */ /* wait for old opens to finish */
wait_event(port->close_wait, gs_closed(port)); wait_event(port->close_wait, gs_closed(port));
WARN_ON(port->port_usb != NULL); WARN_ON(port->port_usb != NULL);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd. * Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef U_UAC2_H #ifndef U_UAC2_H
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2013-2014 Samsung Electronics Co., Ltd. * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef U_UVC_H #ifndef U_UVC_H
......
...@@ -56,6 +56,8 @@ extern unsigned int uvc_gadget_trace_param; ...@@ -56,6 +56,8 @@ extern unsigned int uvc_gadget_trace_param;
dev_dbg(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args) dev_dbg(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
#define uvcg_info(f, fmt, args...) \ #define uvcg_info(f, fmt, args...) \
dev_info(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args) dev_info(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
#define uvcg_warn(f, fmt, args...) \
dev_warn(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
#define uvcg_err(f, fmt, args...) \ #define uvcg_err(f, fmt, args...) \
dev_err(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args) dev_err(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd. * Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#include <linux/sort.h> #include <linux/sort.h>
...@@ -1570,10 +1570,6 @@ uvcg_uncompressed_##cname##_store(struct config_item *item, \ ...@@ -1570,10 +1570,6 @@ uvcg_uncompressed_##cname##_store(struct config_item *item, \
if (ret) \ if (ret) \
goto end; \ goto end; \
\ \
if (num > 255) { \
ret = -EINVAL; \
goto end; \
} \
u->desc.aname = num; \ u->desc.aname = num; \
ret = len; \ ret = len; \
end: \ end: \
...@@ -1767,10 +1763,6 @@ uvcg_mjpeg_##cname##_store(struct config_item *item, \ ...@@ -1767,10 +1763,6 @@ uvcg_mjpeg_##cname##_store(struct config_item *item, \
if (ret) \ if (ret) \
goto end; \ goto end; \
\ \
if (num > 255) { \
ret = -EINVAL; \
goto end; \
} \
u->desc.aname = num; \ u->desc.aname = num; \
ret = len; \ ret = len; \
end: \ end: \
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd. * Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef UVC_CONFIGFS_H #ifndef UVC_CONFIGFS_H
#define UVC_CONFIGFS_H #define UVC_CONFIGFS_H
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* Copyright (c) 2013 Samsung Electronics Co., Ltd. * Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef __UVC_V4L2_H__ #ifndef __UVC_V4L2_H__
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* Copyright (c) 2013 Samsung Electronics Co., Ltd. * Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef __UVC_VIDEO_H__ #ifndef __UVC_VIDEO_H__
#define __UVC_VIDEO_H__ #define __UVC_VIDEO_H__
......
...@@ -1218,27 +1218,27 @@ ep0_poll (struct file *fd, poll_table *wait) ...@@ -1218,27 +1218,27 @@ ep0_poll (struct file *fd, poll_table *wait)
if (dev->state <= STATE_DEV_OPENED) if (dev->state <= STATE_DEV_OPENED)
return DEFAULT_POLLMASK; return DEFAULT_POLLMASK;
poll_wait(fd, &dev->wait, wait); poll_wait(fd, &dev->wait, wait);
spin_lock_irq (&dev->lock); spin_lock_irq(&dev->lock);
/* report fd mode change before acting on it */ /* report fd mode change before acting on it */
if (dev->setup_abort) { if (dev->setup_abort) {
dev->setup_abort = 0; dev->setup_abort = 0;
mask = EPOLLHUP; mask = EPOLLHUP;
goto out; goto out;
} }
if (dev->state == STATE_DEV_SETUP) { if (dev->state == STATE_DEV_SETUP) {
if (dev->setup_in || dev->setup_can_stall) if (dev->setup_in || dev->setup_can_stall)
mask = EPOLLOUT; mask = EPOLLOUT;
} else { } else {
if (dev->ev_next != 0) if (dev->ev_next != 0)
mask = EPOLLIN; mask = EPOLLIN;
} }
out: out:
spin_unlock_irq(&dev->lock); spin_unlock_irq(&dev->lock);
return mask; return mask;
} }
static long dev_ioctl (struct file *fd, unsigned code, unsigned long value) static long dev_ioctl (struct file *fd, unsigned code, unsigned long value)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd. * Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#include "u_f.h" #include "u_f.h"
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2013 Samsung Electronics Co., Ltd. * Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef __U_F_H__ #ifndef __U_F_H__
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2014 Samsung Electronics Co., Ltd. * Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/ */
#ifndef __U_OS_DESC_H__ #ifndef __U_OS_DESC_H__
......
...@@ -120,7 +120,7 @@ static void ast_vhub_epn_handle_ack(struct ast_vhub_ep *ep) ...@@ -120,7 +120,7 @@ static void ast_vhub_epn_handle_ack(struct ast_vhub_ep *ep)
/* No current DMA ongoing */ /* No current DMA ongoing */
req->active = false; req->active = false;
/* Grab lenght out of HW */ /* Grab length out of HW */
len = VHUB_EP_DMA_TX_SIZE(stat); len = VHUB_EP_DMA_TX_SIZE(stat);
/* If not using DMA, copy data out if needed */ /* If not using DMA, copy data out if needed */
......
...@@ -295,7 +295,7 @@ static int ast_vhub_rep_desc(struct ast_vhub_ep *ep, ...@@ -295,7 +295,7 @@ static int ast_vhub_rep_desc(struct ast_vhub_ep *ep,
dsize = AST_VHUB_HUB_DESC_SIZE; dsize = AST_VHUB_HUB_DESC_SIZE;
memcpy(ep->buf, &ast_vhub_hub_desc, dsize); memcpy(ep->buf, &ast_vhub_hub_desc, dsize);
BUILD_BUG_ON(dsize > sizeof(ast_vhub_hub_desc)); BUILD_BUG_ON(dsize > sizeof(ast_vhub_hub_desc));
BUILD_BUG_ON(AST_VHUB_HUB_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET); BUILD_BUG_ON(AST_VHUB_HUB_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET);
break; break;
default: default:
return std_req_stall; return std_req_stall;
......
...@@ -311,8 +311,8 @@ int bdc_ep_clear_stall(struct bdc *bdc, int epnum) ...@@ -311,8 +311,8 @@ int bdc_ep_clear_stall(struct bdc *bdc, int epnum)
/* if the endpoint it not stallled */ /* if the endpoint it not stallled */
if (!(ep->flags & BDC_EP_STALL)) { if (!(ep->flags & BDC_EP_STALL)) {
ret = bdc_ep_set_stall(bdc, epnum); ret = bdc_ep_set_stall(bdc, epnum);
if (ret) if (ret)
return ret; return ret;
} }
} }
/* Preserve the seq number for ep0 only */ /* Preserve the seq number for ep0 only */
......
...@@ -281,10 +281,10 @@ EXPORT_SYMBOL_GPL(usb_ep_queue); ...@@ -281,10 +281,10 @@ EXPORT_SYMBOL_GPL(usb_ep_queue);
* @ep:the endpoint associated with the request * @ep:the endpoint associated with the request
* @req:the request being canceled * @req:the request being canceled
* *
* If the request is still active on the endpoint, it is dequeued and its * If the request is still active on the endpoint, it is dequeued and
* completion routine is called (with status -ECONNRESET); else a negative * eventually its completion routine is called (with status -ECONNRESET);
* error code is returned. This is guaranteed to happen before the call to * else a negative error code is returned. This routine is asynchronous,
* usb_ep_dequeue() returns. * that is, it may return before the completion routine runs.
* *
* Note that some hardware can't clear out write fifos (to unlink the request * Note that some hardware can't clear out write fifos (to unlink the request
* at the head of the queue) except as part of disconnecting from usb. Such * at the head of the queue) except as part of disconnecting from usb. Such
......
...@@ -326,6 +326,7 @@ static void fotg210_wait_dma_done(struct fotg210_ep *ep) ...@@ -326,6 +326,7 @@ static void fotg210_wait_dma_done(struct fotg210_ep *ep)
static void fotg210_start_dma(struct fotg210_ep *ep, static void fotg210_start_dma(struct fotg210_ep *ep,
struct fotg210_request *req) struct fotg210_request *req)
{ {
struct device *dev = &ep->fotg210->gadget.dev;
dma_addr_t d; dma_addr_t d;
u8 *buffer; u8 *buffer;
u32 length; u32 length;
...@@ -348,18 +349,14 @@ static void fotg210_start_dma(struct fotg210_ep *ep, ...@@ -348,18 +349,14 @@ static void fotg210_start_dma(struct fotg210_ep *ep,
length = req->req.length; length = req->req.length;
} }
d = dma_map_single(NULL, buffer, length, d = dma_map_single(dev, buffer, length,
ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (dma_mapping_error(NULL, d)) { if (dma_mapping_error(dev, d)) {
pr_err("dma_mapping_error\n"); pr_err("dma_mapping_error\n");
return; return;
} }
dma_sync_single_for_device(NULL, d, length,
ep->dir_in ? DMA_TO_DEVICE :
DMA_FROM_DEVICE);
fotg210_enable_dma(ep, d, length); fotg210_enable_dma(ep, d, length);
/* check if dma is done */ /* check if dma is done */
...@@ -370,7 +367,7 @@ static void fotg210_start_dma(struct fotg210_ep *ep, ...@@ -370,7 +367,7 @@ static void fotg210_start_dma(struct fotg210_ep *ep,
/* update actual transfer length */ /* update actual transfer length */
req->req.actual += length; req->req.actual += length;
dma_unmap_single(NULL, d, length, DMA_TO_DEVICE); dma_unmap_single(dev, d, length, DMA_TO_DEVICE);
} }
static void fotg210_ep0_queue(struct fotg210_ep *ep, static void fotg210_ep0_queue(struct fotg210_ep *ep,
......
...@@ -516,8 +516,8 @@ static int net2280_disable(struct usb_ep *_ep) ...@@ -516,8 +516,8 @@ static int net2280_disable(struct usb_ep *_ep)
unsigned long flags; unsigned long flags;
ep = container_of(_ep, struct net2280_ep, ep); ep = container_of(_ep, struct net2280_ep, ep);
if (!_ep || !ep->desc || _ep->name == ep0name) { if (!_ep || _ep->name == ep0name) {
pr_err("%s: Invalid ep=%p or ep->desc\n", __func__, _ep); pr_err("%s: Invalid ep=%p\n", __func__, _ep);
return -EINVAL; return -EINVAL;
} }
spin_lock_irqsave(&ep->dev->lock, flags); spin_lock_irqsave(&ep->dev->lock, flags);
...@@ -2279,7 +2279,7 @@ static void usb_reinit_338x(struct net2280 *dev) ...@@ -2279,7 +2279,7 @@ static void usb_reinit_338x(struct net2280 *dev)
* - It is safe to set for all connection speeds; all chip revisions. * - It is safe to set for all connection speeds; all chip revisions.
* - R-M-W to leave other bits undisturbed. * - R-M-W to leave other bits undisturbed.
* - Reference PLX TT-7372 * - Reference PLX TT-7372
*/ */
val = readl(&dev->ll_chicken_reg->ll_tsn_chicken_bit); val = readl(&dev->ll_chicken_reg->ll_tsn_chicken_bit);
val |= BIT(RECOVERY_IDLE_TO_RECOVER_FMW); val |= BIT(RECOVERY_IDLE_TO_RECOVER_FMW);
writel(val, &dev->ll_chicken_reg->ll_tsn_chicken_bit); writel(val, &dev->ll_chicken_reg->ll_tsn_chicken_bit);
......
...@@ -2629,6 +2629,10 @@ static const struct of_device_id usb3_of_match[] = { ...@@ -2629,6 +2629,10 @@ static const struct of_device_id usb3_of_match[] = {
MODULE_DEVICE_TABLE(of, usb3_of_match); MODULE_DEVICE_TABLE(of, usb3_of_match);
static const struct soc_device_attribute renesas_usb3_quirks_match[] = { static const struct soc_device_attribute renesas_usb3_quirks_match[] = {
{
.soc_id = "r8a774c0",
.data = &renesas_usb3_priv_r8a77990,
},
{ {
.soc_id = "r8a7795", .revision = "ES1.*", .soc_id = "r8a7795", .revision = "ES1.*",
.data = &renesas_usb3_priv_r8a7795_es1, .data = &renesas_usb3_priv_r8a7795_es1,
......
...@@ -347,6 +347,14 @@ static unsigned get_maxpacket(struct usb_device *udev, int pipe) ...@@ -347,6 +347,14 @@ static unsigned get_maxpacket(struct usb_device *udev, int pipe)
return le16_to_cpup(&ep->desc.wMaxPacketSize); return le16_to_cpup(&ep->desc.wMaxPacketSize);
} }
static int ss_isoc_get_packet_num(struct usb_device *udev, int pipe)
{
struct usb_host_endpoint *ep = usb_pipe_endpoint(udev, pipe);
return USB_SS_MULT(ep->ss_ep_comp.bmAttributes)
* (1 + ep->ss_ep_comp.bMaxBurst);
}
static void simple_fill_buf(struct urb *urb) static void simple_fill_buf(struct urb *urb)
{ {
unsigned i; unsigned i;
...@@ -1976,8 +1984,13 @@ static struct urb *iso_alloc_urb( ...@@ -1976,8 +1984,13 @@ static struct urb *iso_alloc_urb(
if (bytes < 0 || !desc) if (bytes < 0 || !desc)
return NULL; return NULL;
maxp = usb_endpoint_maxp(desc); maxp = usb_endpoint_maxp(desc);
maxp *= usb_endpoint_maxp_mult(desc); if (udev->speed >= USB_SPEED_SUPER)
maxp *= ss_isoc_get_packet_num(udev, pipe);
else
maxp *= usb_endpoint_maxp_mult(desc);
packets = DIV_ROUND_UP(bytes, maxp); packets = DIV_ROUND_UP(bytes, maxp);
urb = usb_alloc_urb(packets, GFP_KERNEL); urb = usb_alloc_urb(packets, GFP_KERNEL);
...@@ -2065,17 +2078,24 @@ test_queue(struct usbtest_dev *dev, struct usbtest_param_32 *param, ...@@ -2065,17 +2078,24 @@ test_queue(struct usbtest_dev *dev, struct usbtest_param_32 *param,
packets *= param->iterations; packets *= param->iterations;
if (context.is_iso) { if (context.is_iso) {
int transaction_num;
if (udev->speed >= USB_SPEED_SUPER)
transaction_num = ss_isoc_get_packet_num(udev, pipe);
else
transaction_num = usb_endpoint_maxp_mult(desc);
dev_info(&dev->intf->dev, dev_info(&dev->intf->dev,
"iso period %d %sframes, wMaxPacket %d, transactions: %d\n", "iso period %d %sframes, wMaxPacket %d, transactions: %d\n",
1 << (desc->bInterval - 1), 1 << (desc->bInterval - 1),
(udev->speed == USB_SPEED_HIGH) ? "micro" : "", (udev->speed >= USB_SPEED_HIGH) ? "micro" : "",
usb_endpoint_maxp(desc), usb_endpoint_maxp(desc),
usb_endpoint_maxp_mult(desc)); transaction_num);
dev_info(&dev->intf->dev, dev_info(&dev->intf->dev,
"total %lu msec (%lu packets)\n", "total %lu msec (%lu packets)\n",
(packets * (1 << (desc->bInterval - 1))) (packets * (1 << (desc->bInterval - 1)))
/ ((udev->speed == USB_SPEED_HIGH) ? 8 : 1), / ((udev->speed >= USB_SPEED_HIGH) ? 8 : 1),
packets); packets);
} }
......
...@@ -400,7 +400,7 @@ static int twl6030_usb_remove(struct platform_device *pdev) ...@@ -400,7 +400,7 @@ static int twl6030_usb_remove(struct platform_device *pdev)
{ {
struct twl6030_usb *twl = platform_get_drvdata(pdev); struct twl6030_usb *twl = platform_get_drvdata(pdev);
cancel_delayed_work(&twl->get_status_work); cancel_delayed_work_sync(&twl->get_status_work);
twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
REG_INT_MSK_LINE_C); REG_INT_MSK_LINE_C);
twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
......
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