forked from Minki/linux
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. -----BEGIN PGP SIGNATURE----- iQJRBAABCAA7FiEElLzh7wn96CXwjh2IzL64meEamQYFAlxlU88dHGZlbGlwZS5i YWxiaUBsaW51eC5pbnRlbC5jb20ACgkQzL64meEamQYCTA/9EOtd5A2UkUkYIwh0 uV1NOTMIcTnQeNLxOe1c/3yNo4pxGeaKkVc4g/3pdh9dQ121DxUdKy3KAJkDsqDe sbab7Ww2DZds17NqQfMloq3UyLjG2nCOJRl6UjoMCMcd4nVwi9by15W+NjBQSThw 3qvv9qVHiP9O7rKyUOMH/aPqHno1cEb8YJoFDdQuYL3Gv6kbbhfjynBhIzO5W+Zq Za1aIayUEcbnk7OXLj2jUaaQS9TKb8zdhSXb8UGIuQkHQ/GbZF/Me/RbJif+KY7L P+A8PUrk08B/QKm5PdmPjl5MjjoXa8/sEVzOMqEG4vtT8loQ6WCm9k1NNvzHXPa3 aRD316Yvp5EAPUBv3B8IrYUnLRH/xdG1YzEnDHrtsSwVN50qUXXUnvX2TkBic7M/ kEmcB2TS1Pqlto0DUwuSlNUQ6KHDRIxoZ66jdxPfORMzEBWVtoIRLhLSG/oMXYFC SvwKKv2UY0Z/55sUEDuAR8VO3a/KI4FefcmeKsem5I4FfRdQ0SumNYmolpY7Kpqo BL3P+4LQ4CiNBNoBEfifKRUy/jEfU7fTDedgrua8zMH/c7zFXGL+SGNkIixRESO1 B4Cl5/INP4slwtegvSsp3A/4hakPGyBhebCLKVZ/M71BeG0+1TPlAZruPO8SIiqc 7FSxVk2X9Ic0mkXmSqnT7ItuLUU= =4fTL -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
commit
dc8b2a691d
@ -3,7 +3,9 @@ TI Keystone Soc USB Controller
|
||||
DWC3 GLUE
|
||||
|
||||
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
|
||||
with 'reg' property.
|
||||
- reg : Address and length of the register set for the USB subsystem on
|
||||
@ -21,7 +23,7 @@ SoCs only:
|
||||
- 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
|
||||
and an args specifier containing the USB device id
|
||||
|
@ -4,6 +4,7 @@ Required properties:
|
||||
- compatible: Compatible list, contains
|
||||
"qcom,dwc3"
|
||||
"qcom,msm8996-dwc3" for msm8996 SOC.
|
||||
"qcom,msm8998-dwc3" for msm8998 SOC.
|
||||
"qcom,sdm845-dwc3" for sdm845 SOC.
|
||||
- reg: Offset and length of register set for QSCRATCH wrapper
|
||||
- power-domains: specifies a phandle to PM domain provider node
|
||||
|
@ -3,6 +3,7 @@ Renesas Electronics USB3.0 Peripheral driver
|
||||
Required properties:
|
||||
- compatible: Must contain one of the following:
|
||||
- "renesas,r8a774a1-usb3-peri"
|
||||
- "renesas,r8a774c0-usb3-peri"
|
||||
- "renesas,r8a7795-usb3-peri"
|
||||
- "renesas,r8a7796-usb3-peri"
|
||||
- "renesas,r8a77965-usb3-peri"
|
||||
|
@ -7,6 +7,7 @@ Required properties:
|
||||
- "renesas,usbhs-r8a7744" for r8a7744 (RZ/G1N) compatible device
|
||||
- "renesas,usbhs-r8a7745" for r8a7745 (RZ/G1E) 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-r8a7791" for r8a7791 (R-Car M2-W) 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)
|
||||
return desc_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* dwc2_gadget_config_nonisoc_xfer_ddma - prepare non ISOC DMA desc chain.
|
||||
* @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,
|
||||
static void dwc2_gadget_fill_nonisoc_xfer_ddma_one(struct dwc2_hsotg_ep *hs_ep,
|
||||
struct dwc2_dma_desc **desc,
|
||||
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;
|
||||
struct dwc2_dma_desc *desc = hs_ep->desc_list;
|
||||
u32 mps = hs_ep->ep.maxpacket;
|
||||
u32 maxsize = 0;
|
||||
u32 offset = 0;
|
||||
@ -798,41 +789,79 @@ static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep,
|
||||
hs_ep->desc_count = 1;
|
||||
|
||||
for (i = 0; i < hs_ep->desc_count; ++i) {
|
||||
desc->status = 0;
|
||||
desc->status |= (DEV_DMA_BUFF_STS_HBUSY
|
||||
(*desc)->status = 0;
|
||||
(*desc)->status |= (DEV_DMA_BUFF_STS_HBUSY
|
||||
<< DEV_DMA_BUFF_STS_SHIFT);
|
||||
|
||||
if (len > maxsize) {
|
||||
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 <<
|
||||
DEV_DMA_NBYTES_SHIFT & mask);
|
||||
desc->buf = dma_buff + offset;
|
||||
(*desc)->status |=
|
||||
maxsize << DEV_DMA_NBYTES_SHIFT & mask;
|
||||
(*desc)->buf = dma_buff + offset;
|
||||
|
||||
len -= maxsize;
|
||||
offset += maxsize;
|
||||
} else {
|
||||
desc->status |= (DEV_DMA_L | DEV_DMA_IOC);
|
||||
if (true_last)
|
||||
(*desc)->status |= (DEV_DMA_L | DEV_DMA_IOC);
|
||||
|
||||
if (dir_in)
|
||||
desc->status |= (len % mps) ? DEV_DMA_SHORT :
|
||||
((hs_ep->send_zlp) ? DEV_DMA_SHORT : 0);
|
||||
if (len > maxsize)
|
||||
dev_err(hsotg->dev, "wrong len %d\n", len);
|
||||
(*desc)->status |= (len % mps) ? DEV_DMA_SHORT :
|
||||
((hs_ep->send_zlp && true_last) ?
|
||||
DEV_DMA_SHORT : 0);
|
||||
|
||||
desc->status |=
|
||||
(*desc)->status |=
|
||||
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_HREADY
|
||||
(*desc)->status &= ~DEV_DMA_BUFF_STS_MASK;
|
||||
(*desc)->status |= (DEV_DMA_BUFF_STS_HREADY
|
||||
<< 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* dwc2_gadget_fill_isoc_desc - fills next isochronous descriptor in chain.
|
||||
* @hs_ep: The isochronous endpoint.
|
||||
@ -944,7 +973,13 @@ static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep)
|
||||
|
||||
hs_ep->next_desc = 0;
|
||||
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);
|
||||
if (ret)
|
||||
break;
|
||||
@ -1100,7 +1135,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
|
||||
offset = ureq->actual;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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,
|
||||
*/
|
||||
if (using_desc_dma(hs) && hs_ep->isochronous) {
|
||||
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);
|
||||
}
|
||||
return 0;
|
||||
@ -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",
|
||||
index);
|
||||
if (using_desc_dma(hsotg)) {
|
||||
/* Not specific buffer needed for ep0 ZLP */
|
||||
dma_addr_t dma = hs_ep->desc_list_dma;
|
||||
|
||||
if (!index)
|
||||
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 {
|
||||
dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
|
||||
DXEPTSIZ_XFERSIZE(0),
|
||||
@ -4005,6 +4045,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
|
||||
ret = -ENOMEM;
|
||||
goto error1;
|
||||
}
|
||||
epctrl &= ~(DXEPCTL_TXFNUM_LIMIT << DXEPCTL_TXFNUM_SHIFT);
|
||||
hsotg->fifo_map |= 1 << fifo_index;
|
||||
epctrl |= DXEPCTL_TXFNUM(fifo_index);
|
||||
hs_ep->fifo_index = fifo_index;
|
||||
@ -4385,6 +4426,7 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget,
|
||||
hsotg->enabled = 0;
|
||||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
|
||||
gadget->sg_supported = using_desc_dma(hsotg);
|
||||
dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
|
||||
|
||||
return 0;
|
||||
|
@ -88,11 +88,11 @@ config USB_DWC3_HAPS
|
||||
platform, please say 'Y' or 'M' here.
|
||||
|
||||
config USB_DWC3_KEYSTONE
|
||||
tristate "Texas Instruments Keystone2 Platforms"
|
||||
depends on ARCH_KEYSTONE || COMPILE_TEST
|
||||
tristate "Texas Instruments Keystone2/AM654 Platforms"
|
||||
depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST
|
||||
default USB_DWC3
|
||||
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
|
||||
|
||||
config USB_DWC3_OF_SIMPLE
|
||||
|
@ -692,7 +692,6 @@ struct dwc3_ep {
|
||||
#define DWC3_EP_WEDGE BIT(2)
|
||||
#define DWC3_EP_TRANSFER_STARTED BIT(3)
|
||||
#define DWC3_EP_PENDING_REQUEST BIT(5)
|
||||
#define DWC3_EP_END_TRANSFER_PENDING BIT(7)
|
||||
|
||||
/* This last one is specific to EP0 */
|
||||
#define DWC3_EP0_DIR_IN BIT(31)
|
||||
@ -863,6 +862,7 @@ struct dwc3_hwparams {
|
||||
* @num_pending_sgs: counter to pending sgs
|
||||
* @num_queued_sgs: counter to the number of sgs which already got queued
|
||||
* @remaining: amount of data remaining
|
||||
* @status: internal dwc3 request status tracking
|
||||
* @epnum: endpoint number to which this request refers
|
||||
* @trb: pointer to struct dwc3_trb
|
||||
* @trb_dma: DMA address of @trb
|
||||
@ -871,7 +871,6 @@ struct dwc3_hwparams {
|
||||
* or unaligned OUT)
|
||||
* @direction: IN or OUT direction flag
|
||||
* @mapped: true when request has been dma-mapped
|
||||
* @started: request is started
|
||||
*/
|
||||
struct dwc3_request {
|
||||
struct usb_request request;
|
||||
@ -883,6 +882,14 @@ struct dwc3_request {
|
||||
unsigned num_pending_sgs;
|
||||
unsigned int num_queued_sgs;
|
||||
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;
|
||||
struct dwc3_trb *trb;
|
||||
dma_addr_t trb_dma;
|
||||
@ -892,7 +899,6 @@ struct dwc3_request {
|
||||
unsigned needs_extra_trb:1;
|
||||
unsigned direction:1;
|
||||
unsigned mapped:1;
|
||||
unsigned started:1;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -193,65 +193,69 @@ static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
|
||||
* dwc3_gadget_event_string - returns event name
|
||||
* @event: the event code
|
||||
*/
|
||||
static inline const char *
|
||||
dwc3_gadget_event_string(char *str, const struct dwc3_event_devt *event)
|
||||
static inline const char *dwc3_gadget_event_string(char *str, size_t size,
|
||||
const struct dwc3_event_devt *event)
|
||||
{
|
||||
enum dwc3_link_state state = event->event_info & DWC3_LINK_STATE_MASK;
|
||||
|
||||
switch (event->type) {
|
||||
case DWC3_DEVICE_EVENT_DISCONNECT:
|
||||
sprintf(str, "Disconnect: [%s]",
|
||||
snprintf(str, size, "Disconnect: [%s]",
|
||||
dwc3_gadget_link_string(state));
|
||||
break;
|
||||
case DWC3_DEVICE_EVENT_RESET:
|
||||
sprintf(str, "Reset [%s]", dwc3_gadget_link_string(state));
|
||||
snprintf(str, size, "Reset [%s]",
|
||||
dwc3_gadget_link_string(state));
|
||||
break;
|
||||
case DWC3_DEVICE_EVENT_CONNECT_DONE:
|
||||
sprintf(str, "Connection Done [%s]",
|
||||
snprintf(str, size, "Connection Done [%s]",
|
||||
dwc3_gadget_link_string(state));
|
||||
break;
|
||||
case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
|
||||
sprintf(str, "Link Change [%s]",
|
||||
snprintf(str, size, "Link Change [%s]",
|
||||
dwc3_gadget_link_string(state));
|
||||
break;
|
||||
case DWC3_DEVICE_EVENT_WAKEUP:
|
||||
sprintf(str, "WakeUp [%s]", dwc3_gadget_link_string(state));
|
||||
snprintf(str, size, "WakeUp [%s]",
|
||||
dwc3_gadget_link_string(state));
|
||||
break;
|
||||
case DWC3_DEVICE_EVENT_EOPF:
|
||||
sprintf(str, "End-Of-Frame [%s]",
|
||||
snprintf(str, size, "End-Of-Frame [%s]",
|
||||
dwc3_gadget_link_string(state));
|
||||
break;
|
||||
case DWC3_DEVICE_EVENT_SOF:
|
||||
sprintf(str, "Start-Of-Frame [%s]",
|
||||
snprintf(str, size, "Start-Of-Frame [%s]",
|
||||
dwc3_gadget_link_string(state));
|
||||
break;
|
||||
case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
|
||||
sprintf(str, "Erratic Error [%s]",
|
||||
snprintf(str, size, "Erratic Error [%s]",
|
||||
dwc3_gadget_link_string(state));
|
||||
break;
|
||||
case DWC3_DEVICE_EVENT_CMD_CMPL:
|
||||
sprintf(str, "Command Complete [%s]",
|
||||
snprintf(str, size, "Command Complete [%s]",
|
||||
dwc3_gadget_link_string(state));
|
||||
break;
|
||||
case DWC3_DEVICE_EVENT_OVERFLOW:
|
||||
sprintf(str, "Overflow [%s]", dwc3_gadget_link_string(state));
|
||||
snprintf(str, size, "Overflow [%s]",
|
||||
dwc3_gadget_link_string(state));
|
||||
break;
|
||||
default:
|
||||
sprintf(str, "UNKNOWN");
|
||||
snprintf(str, size, "UNKNOWN");
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str)
|
||||
static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str,
|
||||
size_t size)
|
||||
{
|
||||
switch (t & USB_RECIP_MASK) {
|
||||
case USB_RECIP_INTERFACE:
|
||||
sprintf(str, "Get Interface Status(Intf = %d, Length = %d)",
|
||||
i, l);
|
||||
snprintf(str, size, "Get Interface Status(Intf = %d, Length = %d)",
|
||||
i, l);
|
||||
break;
|
||||
case USB_RECIP_ENDPOINT:
|
||||
sprintf(str, "Get Endpoint Status(ep%d%s)",
|
||||
snprintf(str, size, "Get Endpoint Status(ep%d%s)",
|
||||
i & ~USB_DIR_IN,
|
||||
i & USB_DIR_IN ? "in" : "out");
|
||||
break;
|
||||
@ -259,11 +263,11 @@ static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str)
|
||||
}
|
||||
|
||||
static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v,
|
||||
__u16 i, char *str)
|
||||
__u16 i, char *str, size_t size)
|
||||
{
|
||||
switch (t & USB_RECIP_MASK) {
|
||||
case USB_RECIP_DEVICE:
|
||||
sprintf(str, "%s Device Feature(%s%s)",
|
||||
snprintf(str, size, "%s Device Feature(%s%s)",
|
||||
b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
|
||||
({char *s;
|
||||
switch (v) {
|
||||
@ -311,13 +315,13 @@ static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v,
|
||||
} s; }) : "");
|
||||
break;
|
||||
case USB_RECIP_INTERFACE:
|
||||
sprintf(str, "%s Interface Feature(%s)",
|
||||
snprintf(str, size, "%s Interface Feature(%s)",
|
||||
b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
|
||||
v == USB_INTRF_FUNC_SUSPEND ?
|
||||
"Function Suspend" : "UNKNOWN");
|
||||
break;
|
||||
case USB_RECIP_ENDPOINT:
|
||||
sprintf(str, "%s Endpoint Feature(%s ep%d%s)",
|
||||
snprintf(str, size, "%s Endpoint Feature(%s ep%d%s)",
|
||||
b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
|
||||
v == USB_ENDPOINT_HALT ? "Halt" : "UNKNOWN",
|
||||
i & ~USB_DIR_IN,
|
||||
@ -326,15 +330,15 @@ static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dwc3_decode_set_address(__u16 v, char *str)
|
||||
static inline void dwc3_decode_set_address(__u16 v, char *str, size_t size)
|
||||
{
|
||||
sprintf(str, "Set Address(Addr = %02x)", v);
|
||||
snprintf(str, size, "Set Address(Addr = %02x)", v);
|
||||
}
|
||||
|
||||
static inline void dwc3_decode_get_set_descriptor(__u8 t, __u8 b, __u16 v,
|
||||
__u16 i, __u16 l, char *str)
|
||||
__u16 i, __u16 l, char *str, size_t size)
|
||||
{
|
||||
sprintf(str, "%s %s Descriptor(Index = %d, Length = %d)",
|
||||
snprintf(str, size, "%s %s Descriptor(Index = %d, Length = %d)",
|
||||
b == USB_REQ_GET_DESCRIPTOR ? "Get" : "Set",
|
||||
({ char *s;
|
||||
switch (v >> 8) {
|
||||
@ -393,87 +397,92 @@ static inline void dwc3_decode_get_set_descriptor(__u8 t, __u8 b, __u16 v,
|
||||
}
|
||||
|
||||
|
||||
static inline void dwc3_decode_get_configuration(__u16 l, char *str)
|
||||
static inline void dwc3_decode_get_configuration(__u16 l, char *str,
|
||||
size_t size)
|
||||
{
|
||||
sprintf(str, "Get Configuration(Length = %d)", l);
|
||||
snprintf(str, size, "Get Configuration(Length = %d)", l);
|
||||
}
|
||||
|
||||
static inline void dwc3_decode_set_configuration(__u8 v, char *str)
|
||||
static inline void dwc3_decode_set_configuration(__u8 v, char *str, size_t size)
|
||||
{
|
||||
sprintf(str, "Set Configuration(Config = %d)", v);
|
||||
snprintf(str, size, "Set Configuration(Config = %d)", v);
|
||||
}
|
||||
|
||||
static inline void dwc3_decode_get_intf(__u16 i, __u16 l, char *str)
|
||||
static inline void dwc3_decode_get_intf(__u16 i, __u16 l, char *str,
|
||||
size_t size)
|
||||
{
|
||||
sprintf(str, "Get Interface(Intf = %d, Length = %d)", i, l);
|
||||
snprintf(str, size, "Get Interface(Intf = %d, Length = %d)", i, l);
|
||||
}
|
||||
|
||||
static inline void dwc3_decode_set_intf(__u8 v, __u16 i, char *str)
|
||||
static inline void dwc3_decode_set_intf(__u8 v, __u16 i, char *str, size_t size)
|
||||
{
|
||||
sprintf(str, "Set Interface(Intf = %d, Alt.Setting = %d)", i, v);
|
||||
snprintf(str, size, "Set Interface(Intf = %d, Alt.Setting = %d)", i, v);
|
||||
}
|
||||
|
||||
static inline void dwc3_decode_synch_frame(__u16 i, __u16 l, char *str)
|
||||
static inline void dwc3_decode_synch_frame(__u16 i, __u16 l, char *str,
|
||||
size_t size)
|
||||
{
|
||||
sprintf(str, "Synch Frame(Endpoint = %d, Length = %d)", i, l);
|
||||
snprintf(str, size, "Synch Frame(Endpoint = %d, Length = %d)", i, l);
|
||||
}
|
||||
|
||||
static inline void dwc3_decode_set_sel(__u16 l, char *str)
|
||||
static inline void dwc3_decode_set_sel(__u16 l, char *str, size_t size)
|
||||
{
|
||||
sprintf(str, "Set SEL(Length = %d)", l);
|
||||
snprintf(str, size, "Set SEL(Length = %d)", l);
|
||||
}
|
||||
|
||||
static inline void dwc3_decode_set_isoch_delay(__u8 v, char *str)
|
||||
static inline void dwc3_decode_set_isoch_delay(__u8 v, char *str, size_t size)
|
||||
{
|
||||
sprintf(str, "Set Isochronous Delay(Delay = %d ns)", v);
|
||||
snprintf(str, size, "Set Isochronous Delay(Delay = %d ns)", v);
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc3_decode_ctrl - returns a string represetion of ctrl request
|
||||
*/
|
||||
static inline const char *dwc3_decode_ctrl(char *str, __u8 bRequestType,
|
||||
__u8 bRequest, __u16 wValue, __u16 wIndex, __u16 wLength)
|
||||
static inline const char *dwc3_decode_ctrl(char *str, size_t size,
|
||||
__u8 bRequestType, __u8 bRequest, __u16 wValue, __u16 wIndex,
|
||||
__u16 wLength)
|
||||
{
|
||||
switch (bRequest) {
|
||||
case USB_REQ_GET_STATUS:
|
||||
dwc3_decode_get_status(bRequestType, wIndex, wLength, str);
|
||||
dwc3_decode_get_status(bRequestType, wIndex, wLength, str,
|
||||
size);
|
||||
break;
|
||||
case USB_REQ_CLEAR_FEATURE:
|
||||
case USB_REQ_SET_FEATURE:
|
||||
dwc3_decode_set_clear_feature(bRequestType, bRequest, wValue,
|
||||
wIndex, str);
|
||||
wIndex, str, size);
|
||||
break;
|
||||
case USB_REQ_SET_ADDRESS:
|
||||
dwc3_decode_set_address(wValue, str);
|
||||
dwc3_decode_set_address(wValue, str, size);
|
||||
break;
|
||||
case USB_REQ_GET_DESCRIPTOR:
|
||||
case USB_REQ_SET_DESCRIPTOR:
|
||||
dwc3_decode_get_set_descriptor(bRequestType, bRequest, wValue,
|
||||
wIndex, wLength, str);
|
||||
wIndex, wLength, str, size);
|
||||
break;
|
||||
case USB_REQ_GET_CONFIGURATION:
|
||||
dwc3_decode_get_configuration(wLength, str);
|
||||
dwc3_decode_get_configuration(wLength, str, size);
|
||||
break;
|
||||
case USB_REQ_SET_CONFIGURATION:
|
||||
dwc3_decode_set_configuration(wValue, str);
|
||||
dwc3_decode_set_configuration(wValue, str, size);
|
||||
break;
|
||||
case USB_REQ_GET_INTERFACE:
|
||||
dwc3_decode_get_intf(wIndex, wLength, str);
|
||||
dwc3_decode_get_intf(wIndex, wLength, str, size);
|
||||
break;
|
||||
case USB_REQ_SET_INTERFACE:
|
||||
dwc3_decode_set_intf(wValue, wIndex, str);
|
||||
dwc3_decode_set_intf(wValue, wIndex, str, size);
|
||||
break;
|
||||
case USB_REQ_SYNCH_FRAME:
|
||||
dwc3_decode_synch_frame(wIndex, wLength, str);
|
||||
dwc3_decode_synch_frame(wIndex, wLength, str, size);
|
||||
break;
|
||||
case USB_REQ_SET_SEL:
|
||||
dwc3_decode_set_sel(wLength, str);
|
||||
dwc3_decode_set_sel(wLength, str, size);
|
||||
break;
|
||||
case USB_REQ_SET_ISOCH_DELAY:
|
||||
dwc3_decode_set_isoch_delay(wValue, str);
|
||||
dwc3_decode_set_isoch_delay(wValue, str, size);
|
||||
break;
|
||||
default:
|
||||
sprintf(str, "%02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
snprintf(str, size, "%02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
bRequestType, bRequest,
|
||||
cpu_to_le16(wValue) & 0xff,
|
||||
cpu_to_le16(wValue) >> 8,
|
||||
@ -490,16 +499,15 @@ static inline const char *dwc3_decode_ctrl(char *str, __u8 bRequestType,
|
||||
* dwc3_ep_event_string - returns event name
|
||||
* @event: then event code
|
||||
*/
|
||||
static inline const char *
|
||||
dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event,
|
||||
u32 ep0state)
|
||||
static inline const char *dwc3_ep_event_string(char *str, size_t size,
|
||||
const struct dwc3_event_depevt *event, u32 ep0state)
|
||||
{
|
||||
u8 epnum = event->endpoint_number;
|
||||
size_t len;
|
||||
int status;
|
||||
int ret;
|
||||
|
||||
ret = sprintf(str, "ep%d%s: ", epnum >> 1,
|
||||
ret = snprintf(str, size, "ep%d%s: ", epnum >> 1,
|
||||
(epnum & 1) ? "in" : "out");
|
||||
if (ret < 0)
|
||||
return "UNKNOWN";
|
||||
@ -509,7 +517,7 @@ dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event,
|
||||
switch (event->endpoint_event) {
|
||||
case DWC3_DEPEVT_XFERCOMPLETE:
|
||||
len = strlen(str);
|
||||
sprintf(str + len, "Transfer Complete (%c%c%c)",
|
||||
snprintf(str + len, size - len, "Transfer Complete (%c%c%c)",
|
||||
status & DEPEVT_STATUS_SHORT ? 'S' : 's',
|
||||
status & DEPEVT_STATUS_IOC ? 'I' : 'i',
|
||||
status & DEPEVT_STATUS_LST ? 'L' : 'l');
|
||||
@ -517,12 +525,13 @@ dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event,
|
||||
len = strlen(str);
|
||||
|
||||
if (epnum <= 1)
|
||||
sprintf(str + len, " [%s]", dwc3_ep0_state_string(ep0state));
|
||||
snprintf(str + len, size - len, " [%s]",
|
||||
dwc3_ep0_state_string(ep0state));
|
||||
break;
|
||||
case DWC3_DEPEVT_XFERINPROGRESS:
|
||||
len = strlen(str);
|
||||
|
||||
sprintf(str + len, "Transfer In Progress [%d] (%c%c%c)",
|
||||
snprintf(str + len, size - len, "Transfer In Progress [%d] (%c%c%c)",
|
||||
event->parameters,
|
||||
status & DEPEVT_STATUS_SHORT ? 'S' : 's',
|
||||
status & DEPEVT_STATUS_IOC ? 'I' : 'i',
|
||||
@ -531,47 +540,51 @@ dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event,
|
||||
case DWC3_DEPEVT_XFERNOTREADY:
|
||||
len = strlen(str);
|
||||
|
||||
sprintf(str + len, "Transfer Not Ready [%d]%s",
|
||||
snprintf(str + len, size - len, "Transfer Not Ready [%d]%s",
|
||||
event->parameters,
|
||||
status & DEPEVT_STATUS_TRANSFER_ACTIVE ?
|
||||
" (Active)" : " (Not Active)");
|
||||
|
||||
len = strlen(str);
|
||||
|
||||
/* Control Endpoints */
|
||||
if (epnum <= 1) {
|
||||
int phase = DEPEVT_STATUS_CONTROL_PHASE(event->status);
|
||||
|
||||
switch (phase) {
|
||||
case DEPEVT_STATUS_CONTROL_DATA:
|
||||
strcat(str, " [Data Phase]");
|
||||
snprintf(str + ret, size - ret,
|
||||
" [Data Phase]");
|
||||
break;
|
||||
case DEPEVT_STATUS_CONTROL_STATUS:
|
||||
strcat(str, " [Status Phase]");
|
||||
snprintf(str + ret, size - ret,
|
||||
" [Status Phase]");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DWC3_DEPEVT_RXTXFIFOEVT:
|
||||
strcat(str, "FIFO");
|
||||
snprintf(str + ret, size - ret, "FIFO");
|
||||
break;
|
||||
case DWC3_DEPEVT_STREAMEVT:
|
||||
status = event->status;
|
||||
|
||||
switch (status) {
|
||||
case DEPEVT_STREAMEVT_FOUND:
|
||||
sprintf(str + ret, " Stream %d Found",
|
||||
snprintf(str + ret, size - ret, " Stream %d Found",
|
||||
event->parameters);
|
||||
break;
|
||||
case DEPEVT_STREAMEVT_NOTFOUND:
|
||||
default:
|
||||
strcat(str, " Stream Not Found");
|
||||
snprintf(str + ret, size - ret, " Stream Not Found");
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case DWC3_DEPEVT_EPCMDCMPLT:
|
||||
strcat(str, "Endpoint Command Complete");
|
||||
snprintf(str + ret, size - ret, "Endpoint Command Complete");
|
||||
break;
|
||||
default:
|
||||
sprintf(str, "UNKNOWN");
|
||||
snprintf(str, size, "UNKNOWN");
|
||||
}
|
||||
|
||||
return str;
|
||||
@ -611,14 +624,15 @@ static inline const char *dwc3_gadget_event_type_string(u8 event)
|
||||
}
|
||||
}
|
||||
|
||||
static inline const char *dwc3_decode_event(char *str, u32 event, u32 ep0state)
|
||||
static inline const char *dwc3_decode_event(char *str, size_t size, u32 event,
|
||||
u32 ep0state)
|
||||
{
|
||||
const union dwc3_event evt = (union dwc3_event) event;
|
||||
|
||||
if (evt.type.is_devspec)
|
||||
return dwc3_gadget_event_string(str, &evt.devt);
|
||||
return dwc3_gadget_event_string(str, size, &evt.devt);
|
||||
else
|
||||
return dwc3_ep_event_string(str, &evt.depevt, ep0state);
|
||||
return dwc3_ep_event_string(str, size, &evt.depevt, ep0state);
|
||||
}
|
||||
|
||||
static inline const char *dwc3_ep_cmd_status_string(int status)
|
||||
|
@ -106,6 +106,15 @@ static const struct pci_device_id dwc3_haps_id_table[] = {
|
||||
{
|
||||
PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
|
||||
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,
|
||||
|
@ -106,6 +106,10 @@ static int kdwc3_probe(struct platform_device *pdev)
|
||||
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);
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "missing irq\n");
|
||||
@ -123,6 +127,7 @@ static int kdwc3_probe(struct platform_device *pdev)
|
||||
|
||||
kdwc3_enable_irqs(kdwc);
|
||||
|
||||
skip_irq:
|
||||
error = of_platform_populate(node, NULL, NULL, dev);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to create dwc3 core\n");
|
||||
@ -152,8 +157,11 @@ static int kdwc3_remove_core(struct device *dev, void *c)
|
||||
static int kdwc3_remove(struct platform_device *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);
|
||||
pm_runtime_put_sync(kdwc->dev);
|
||||
pm_runtime_disable(kdwc->dev);
|
||||
@ -165,6 +173,7 @@ static int kdwc3_remove(struct platform_device *pdev)
|
||||
|
||||
static const struct of_device_id kdwc3_of_match[] = {
|
||||
{ .compatible = "ti,keystone-dwc3", },
|
||||
{ .compatible = "ti,am654-dwc3" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, kdwc3_of_match);
|
||||
|
@ -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[] = {
|
||||
{ .compatible = "qcom,dwc3" },
|
||||
{ .compatible = "qcom,msm8996-dwc3" },
|
||||
{ .compatible = "qcom,msm8998-dwc3" },
|
||||
{ .compatible = "qcom,sdm845-dwc3" },
|
||||
{ }
|
||||
};
|
||||
|
@ -174,7 +174,6 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
|
||||
{
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
|
||||
req->started = false;
|
||||
list_del(&req->list);
|
||||
req->remaining = 0;
|
||||
req->needs_extra_trb = false;
|
||||
@ -209,6 +208,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
|
||||
dwc3_gadget_del_and_unmap_request(dep, req, status);
|
||||
req->status = DWC3_REQUEST_STATUS_COMPLETED;
|
||||
|
||||
spin_unlock(&dwc->lock);
|
||||
usb_gadget_giveback_request(&dep->endpoint, &req->request);
|
||||
@ -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);
|
||||
|
||||
if (ret == 0) {
|
||||
switch (DWC3_DEPCMD_CMD(cmd)) {
|
||||
case DWC3_DEPCMD_STARTTRANSFER:
|
||||
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 (ret == 0 && DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
|
||||
dep->flags |= DWC3_EP_TRANSFER_STARTED;
|
||||
dwc3_gadget_ep_get_transfer_index(dep);
|
||||
}
|
||||
|
||||
if (saved_config) {
|
||||
@ -642,7 +632,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
|
||||
|
||||
dep->type = usb_endpoint_type(desc);
|
||||
dep->flags |= DWC3_EP_ENABLED;
|
||||
dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
|
||||
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
|
||||
reg |= DWC3_DALEPENA_EP(dep->number);
|
||||
@ -698,12 +687,13 @@ out:
|
||||
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)
|
||||
{
|
||||
struct dwc3_request *req;
|
||||
|
||||
dwc3_stop_active_transfer(dep, true);
|
||||
dwc3_stop_active_transfer(dep, true, false);
|
||||
|
||||
/* - giveback all requests to gadget driver */
|
||||
while (!list_empty(&dep->started_list)) {
|
||||
@ -748,7 +738,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
|
||||
|
||||
dep->stream_capable = false;
|
||||
dep->type = 0;
|
||||
dep->flags &= DWC3_EP_END_TRANSFER_PENDING;
|
||||
dep->flags = 0;
|
||||
|
||||
/* Clear out the ep descriptors for non-ep0 */
|
||||
if (dep->number > 1) {
|
||||
@ -847,6 +837,7 @@ static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep,
|
||||
req->direction = dep->direction;
|
||||
req->epnum = dep->number;
|
||||
req->dep = dep;
|
||||
req->status = DWC3_REQUEST_STATUS_UNKNOWN;
|
||||
|
||||
trace_dwc3_alloc_request(req);
|
||||
|
||||
@ -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
|
||||
*/
|
||||
if (cmd_status == 0) {
|
||||
dwc3_stop_active_transfer(dep, true);
|
||||
dwc3_stop_active_transfer(dep, true, true);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -1435,6 +1426,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
|
||||
&req->request, req->dep->name))
|
||||
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);
|
||||
|
||||
req->request.actual = 0;
|
||||
@ -1443,6 +1439,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
|
||||
trace_dwc3_ep_queue(req);
|
||||
|
||||
list_add_tail(&req->list, &dep->pending_list);
|
||||
req->status = DWC3_REQUEST_STATUS_QUEUED;
|
||||
|
||||
/*
|
||||
* 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
|
||||
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
|
||||
dwc3_ep_inc_deq(dep);
|
||||
}
|
||||
|
||||
req->num_trbs = 0;
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
if (r == req) {
|
||||
/* wait until it is processed */
|
||||
dwc3_stop_active_transfer(dep, true);
|
||||
dwc3_stop_active_transfer(dep, true, true);
|
||||
|
||||
if (!r->trb)
|
||||
goto out0;
|
||||
|
||||
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",
|
||||
request, ep->name);
|
||||
@ -1561,6 +1563,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
|
||||
goto out0;
|
||||
}
|
||||
|
||||
out1:
|
||||
dwc3_gadget_giveback(dep, req, -ECONNRESET);
|
||||
|
||||
out0:
|
||||
@ -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);
|
||||
|
||||
if (stop) {
|
||||
dwc3_stop_active_transfer(dep, true);
|
||||
dwc3_stop_active_transfer(dep, true, true);
|
||||
dep->flags = DWC3_EP_ENABLED;
|
||||
}
|
||||
|
||||
@ -2547,7 +2550,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
|
||||
dep = dwc->eps[epnum];
|
||||
|
||||
if (!(dep->flags & DWC3_EP_ENABLED)) {
|
||||
if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
|
||||
if (!(dep->flags & DWC3_EP_TRANSFER_STARTED))
|
||||
return;
|
||||
|
||||
/* Handle only EPCMDCMPLT when EP disabled */
|
||||
@ -2571,7 +2574,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
|
||||
cmd = DEPEVT_PARAMETER_CMD(event->parameters);
|
||||
|
||||
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);
|
||||
}
|
||||
break;
|
||||
@ -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_gadget_ep_cmd_params params;
|
||||
u32 cmd;
|
||||
int ret;
|
||||
|
||||
if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) ||
|
||||
!dep->resource_index)
|
||||
if (!(dep->flags & DWC3_EP_TRANSFER_STARTED))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -2665,17 +2668,15 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force)
|
||||
|
||||
cmd = DWC3_DEPCMD_ENDTRANSFER;
|
||||
cmd |= force ? DWC3_DEPCMD_HIPRI_FORCERM : 0;
|
||||
cmd |= DWC3_DEPCMD_CMDIOC;
|
||||
cmd |= interrupt ? DWC3_DEPCMD_CMDIOC : 0;
|
||||
cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms);
|
||||
WARN_ON_ONCE(ret);
|
||||
dep->resource_index = 0;
|
||||
|
||||
if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A) {
|
||||
dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
|
||||
if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A)
|
||||
udelay(100);
|
||||
}
|
||||
}
|
||||
|
||||
static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
|
||||
@ -3339,6 +3340,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
|
||||
goto err4;
|
||||
}
|
||||
|
||||
dwc3_gadget_set_speed(&dwc->gadget, dwc->maximum_speed);
|
||||
|
||||
return 0;
|
||||
|
||||
err4:
|
||||
|
@ -75,7 +75,7 @@ static inline void dwc3_gadget_move_started_request(struct dwc3_request *req)
|
||||
{
|
||||
struct dwc3_ep *dep = req->dep;
|
||||
|
||||
req->started = true;
|
||||
req->status = DWC3_REQUEST_STATUS_STARTED;
|
||||
list_move_tail(&req->list, &dep->started_list);
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ static inline void dwc3_gadget_move_cancelled_request(struct dwc3_request *req)
|
||||
{
|
||||
struct dwc3_ep *dep = req->dep;
|
||||
|
||||
req->started = false;
|
||||
req->status = DWC3_REQUEST_STATUS_CANCELLED;
|
||||
list_move_tail(&req->list, &dep->cancelled_list);
|
||||
}
|
||||
|
||||
|
@ -59,8 +59,8 @@ DECLARE_EVENT_CLASS(dwc3_log_event,
|
||||
__entry->ep0state = dwc->ep0state;
|
||||
),
|
||||
TP_printk("event (%08x): %s", __entry->event,
|
||||
dwc3_decode_event(__get_str(str), __entry->event,
|
||||
__entry->ep0state))
|
||||
dwc3_decode_event(__get_str(str), DWC3_MSG_MAX,
|
||||
__entry->event, __entry->ep0state))
|
||||
);
|
||||
|
||||
DEFINE_EVENT(dwc3_log_event, dwc3_event,
|
||||
@ -86,7 +86,8 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
|
||||
__entry->wIndex = le16_to_cpu(ctrl->wIndex);
|
||||
__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->wIndex, __entry->wLength)
|
||||
)
|
||||
@ -305,7 +306,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep,
|
||||
__entry->trb_enqueue = dep->trb_enqueue;
|
||||
__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,
|
||||
__entry->maxpacket_limit, __entry->max_streams,
|
||||
__entry->maxburst, __entry->trb_enqueue,
|
||||
@ -315,7 +316,6 @@ DECLARE_EVENT_CLASS(dwc3_log_ep,
|
||||
__entry->flags & DWC3_EP_WEDGE ? 'W' : 'w',
|
||||
__entry->flags & DWC3_EP_TRANSFER_STARTED ? 'B' : 'b',
|
||||
__entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p',
|
||||
__entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e',
|
||||
__entry->direction ? '<' : '>'
|
||||
)
|
||||
);
|
||||
|
@ -67,9 +67,6 @@ struct usb_ep *usb_ep_autoconfig_ss(
|
||||
)
|
||||
{
|
||||
struct usb_ep *ep;
|
||||
u8 type;
|
||||
|
||||
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
|
||||
|
||||
if (gadget->ops->match_ep) {
|
||||
ep = gadget->ops->match_ep(gadget, desc, ep_comp);
|
||||
@ -109,16 +106,6 @@ found_ep:
|
||||
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->desc = NULL;
|
||||
ep->comp_desc = NULL;
|
||||
@ -152,9 +139,10 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
|
||||
*
|
||||
* On success, this returns an claimed usb_ep, and modifies the endpoint
|
||||
* descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
|
||||
* is initialized as if the endpoint were used at full speed. To prevent
|
||||
* the endpoint from being returned by a later autoconfig call, claims it
|
||||
* by assigning ep->claimed to true.
|
||||
* is initialized as if the endpoint were used at full speed. Because of
|
||||
* that the users must consider adjusting the autoconfigured descriptor.
|
||||
* 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.
|
||||
*/
|
||||
@ -163,7 +151,26 @@ struct usb_ep *usb_ep_autoconfig(
|
||||
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);
|
||||
|
||||
|
@ -1082,6 +1082,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
|
||||
* condition with req->complete callback.
|
||||
*/
|
||||
usb_ep_dequeue(ep->ep, req);
|
||||
wait_for_completion(&done);
|
||||
interrupted = ep->status < 0;
|
||||
}
|
||||
|
||||
@ -2843,12 +2844,18 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
|
||||
struct usb_request *req;
|
||||
struct usb_ep *ep;
|
||||
u8 bEndpointAddress;
|
||||
u16 wMaxPacketSize;
|
||||
|
||||
/*
|
||||
* We back up bEndpointAddress because autoconfig overwrites
|
||||
* it with physical endpoint address.
|
||||
*/
|
||||
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");
|
||||
ep = usb_ep_autoconfig(func->gadget, ds);
|
||||
if (unlikely(!ep))
|
||||
@ -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)
|
||||
ds->bEndpointAddress = bEndpointAddress;
|
||||
/*
|
||||
* Restore wMaxPacketSize which was potentially
|
||||
* overwritten by autoconfig.
|
||||
*/
|
||||
ds->wMaxPacketSize = wMaxPacketSize;
|
||||
}
|
||||
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)
|
||||
} else if (intf == uac1->as_in_intf) {
|
||||
uac1->as_in_alt = alt;
|
||||
|
||||
if (alt)
|
||||
ret = u_audio_start_playback(&uac1->g_audio);
|
||||
else
|
||||
u_audio_stop_playback(&uac1->g_audio);
|
||||
if (alt)
|
||||
ret = u_audio_start_playback(&uac1->g_audio);
|
||||
else
|
||||
u_audio_stop_playback(&uac1->g_audio);
|
||||
} else {
|
||||
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
|
||||
return -EINVAL;
|
||||
@ -568,6 +568,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
goto fail;
|
||||
as_out_interface_alt_0_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_alt = 0;
|
||||
|
||||
@ -576,6 +577,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
goto fail;
|
||||
as_in_interface_alt_0_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_alt = 0;
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef U_ECM_H
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef U_EEM_H
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __U_ETHER_CONFIGFS_H
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef U_FFS_H
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef U_GETHER_H
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef U_HID_H
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef U_MIDI_H
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef U_NCM_H
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef U_PRINTER_H
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef U_RNDIS_H
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/tty.h>
|
||||
@ -26,6 +25,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/kfifo.h>
|
||||
|
||||
#include "u_serial.h"
|
||||
@ -110,7 +110,7 @@ struct gs_port {
|
||||
int read_allocated;
|
||||
struct list_head read_queue;
|
||||
unsigned n_read;
|
||||
struct tasklet_struct push;
|
||||
struct delayed_work push;
|
||||
|
||||
struct list_head write_pool;
|
||||
int write_started;
|
||||
@ -352,9 +352,10 @@ __acquires(&port->port_lock)
|
||||
* So QUEUE_SIZE packets plus however many the FIFO holds (usually two)
|
||||
* 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 list_head *queue = &port->read_queue;
|
||||
bool disconnect = false;
|
||||
@ -429,21 +430,13 @@ static void gs_rx_push(unsigned long _port)
|
||||
|
||||
/* We want our data queue to become empty ASAP, keeping data
|
||||
* in the tty and ldisc (not here). If we couldn't push any
|
||||
* this time around, there may be trouble unless there's an
|
||||
* implicit tty_unthrottle() call on its way...
|
||||
* this time around, RX may be starved, so wait until next jiffy.
|
||||
*
|
||||
* REVISIT we should probably add a timer to keep the tasklet
|
||||
* from starving ... but it's not clear that case ever happens.
|
||||
* We may leave non-empty queue only when there is a tty, and
|
||||
* either it is throttled or there is no more room in flip buffer.
|
||||
*/
|
||||
if (!list_empty(queue) && tty) {
|
||||
if (!tty_throttled(tty)) {
|
||||
if (do_push)
|
||||
tasklet_schedule(&port->push);
|
||||
else
|
||||
pr_warn("ttyGS%d: RX not scheduled?\n",
|
||||
port->port_num);
|
||||
}
|
||||
}
|
||||
if (!list_empty(queue) && !tty_throttled(tty))
|
||||
schedule_delayed_work(&port->push, 1);
|
||||
|
||||
/* If we're still connected, refill the USB RX queue. */
|
||||
if (!disconnect && port->port_usb)
|
||||
@ -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. */
|
||||
spin_lock(&port->port_lock);
|
||||
list_add_tail(&req->list, &port->read_queue);
|
||||
tasklet_schedule(&port->push);
|
||||
schedule_delayed_work(&port->push, 0);
|
||||
spin_unlock(&port->port_lock);
|
||||
}
|
||||
|
||||
@ -854,8 +847,8 @@ static void gs_unthrottle(struct tty_struct *tty)
|
||||
* rts/cts, or other handshaking with the host, but if the
|
||||
* read queue backs up enough we'll be NAKing OUT packets.
|
||||
*/
|
||||
tasklet_schedule(&port->push);
|
||||
pr_vdebug("ttyGS%d: unthrottle\n", port->port_num);
|
||||
schedule_delayed_work(&port->push, 0);
|
||||
}
|
||||
spin_unlock_irqrestore(&port->port_lock, flags);
|
||||
}
|
||||
@ -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->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_queue);
|
||||
@ -1186,7 +1179,7 @@ static int gs_closed(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_event(port->close_wait, gs_closed(port));
|
||||
WARN_ON(port->port_usb != NULL);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef U_UAC2_H
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2013-2014 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef U_UVC_H
|
||||
|
@ -56,6 +56,8 @@ extern unsigned int uvc_gadget_trace_param;
|
||||
dev_dbg(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
|
||||
#define uvcg_info(f, fmt, 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...) \
|
||||
dev_err(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/sort.h>
|
||||
@ -1570,10 +1570,6 @@ uvcg_uncompressed_##cname##_store(struct config_item *item, \
|
||||
if (ret) \
|
||||
goto end; \
|
||||
\
|
||||
if (num > 255) { \
|
||||
ret = -EINVAL; \
|
||||
goto end; \
|
||||
} \
|
||||
u->desc.aname = num; \
|
||||
ret = len; \
|
||||
end: \
|
||||
@ -1767,10 +1763,6 @@ uvcg_mjpeg_##cname##_store(struct config_item *item, \
|
||||
if (ret) \
|
||||
goto end; \
|
||||
\
|
||||
if (num > 255) { \
|
||||
ret = -EINVAL; \
|
||||
goto end; \
|
||||
} \
|
||||
u->desc.aname = num; \
|
||||
ret = len; \
|
||||
end: \
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
#ifndef UVC_CONFIGFS_H
|
||||
#define UVC_CONFIGFS_H
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __UVC_V4L2_H__
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
#ifndef __UVC_VIDEO_H__
|
||||
#define __UVC_VIDEO_H__
|
||||
|
@ -1218,27 +1218,27 @@ ep0_poll (struct file *fd, poll_table *wait)
|
||||
if (dev->state <= STATE_DEV_OPENED)
|
||||
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 */
|
||||
if (dev->setup_abort) {
|
||||
dev->setup_abort = 0;
|
||||
mask = EPOLLHUP;
|
||||
goto out;
|
||||
}
|
||||
/* report fd mode change before acting on it */
|
||||
if (dev->setup_abort) {
|
||||
dev->setup_abort = 0;
|
||||
mask = EPOLLHUP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dev->state == STATE_DEV_SETUP) {
|
||||
if (dev->setup_in || dev->setup_can_stall)
|
||||
mask = EPOLLOUT;
|
||||
} else {
|
||||
if (dev->ev_next != 0)
|
||||
mask = EPOLLIN;
|
||||
}
|
||||
if (dev->state == STATE_DEV_SETUP) {
|
||||
if (dev->setup_in || dev->setup_can_stall)
|
||||
mask = EPOLLOUT;
|
||||
} else {
|
||||
if (dev->ev_next != 0)
|
||||
mask = EPOLLIN;
|
||||
}
|
||||
out:
|
||||
spin_unlock_irq(&dev->lock);
|
||||
return mask;
|
||||
spin_unlock_irq(&dev->lock);
|
||||
return mask;
|
||||
}
|
||||
|
||||
static long dev_ioctl (struct file *fd, unsigned code, unsigned long value)
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#include "u_f.h"
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __U_F_H__
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
* Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __U_OS_DESC_H__
|
||||
|
@ -120,7 +120,7 @@ static void ast_vhub_epn_handle_ack(struct ast_vhub_ep *ep)
|
||||
/* No current DMA ongoing */
|
||||
req->active = false;
|
||||
|
||||
/* Grab lenght out of HW */
|
||||
/* Grab length out of HW */
|
||||
len = VHUB_EP_DMA_TX_SIZE(stat);
|
||||
|
||||
/* If not using DMA, copy data out if needed */
|
||||
|
@ -295,7 +295,7 @@ static int ast_vhub_rep_desc(struct ast_vhub_ep *ep,
|
||||
dsize = AST_VHUB_HUB_DESC_SIZE;
|
||||
memcpy(ep->buf, &ast_vhub_hub_desc, dsize);
|
||||
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;
|
||||
default:
|
||||
return std_req_stall;
|
||||
|
@ -311,8 +311,8 @@ int bdc_ep_clear_stall(struct bdc *bdc, int epnum)
|
||||
/* if the endpoint it not stallled */
|
||||
if (!(ep->flags & BDC_EP_STALL)) {
|
||||
ret = bdc_ep_set_stall(bdc, epnum);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/* Preserve the seq number for ep0 only */
|
||||
|
@ -281,10 +281,10 @@ EXPORT_SYMBOL_GPL(usb_ep_queue);
|
||||
* @ep:the endpoint associated with the request
|
||||
* @req:the request being canceled
|
||||
*
|
||||
* If the request is still active on the endpoint, it is dequeued and its
|
||||
* completion routine is called (with status -ECONNRESET); else a negative
|
||||
* error code is returned. This is guaranteed to happen before the call to
|
||||
* usb_ep_dequeue() returns.
|
||||
* If the request is still active on the endpoint, it is dequeued and
|
||||
* eventually its completion routine is called (with status -ECONNRESET);
|
||||
* else a negative error code is returned. This routine is asynchronous,
|
||||
* that is, it may return before the completion routine runs.
|
||||
*
|
||||
* 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
|
||||
|
@ -326,6 +326,7 @@ dma_reset:
|
||||
static void fotg210_start_dma(struct fotg210_ep *ep,
|
||||
struct fotg210_request *req)
|
||||
{
|
||||
struct device *dev = &ep->fotg210->gadget.dev;
|
||||
dma_addr_t d;
|
||||
u8 *buffer;
|
||||
u32 length;
|
||||
@ -348,18 +349,14 @@ static void fotg210_start_dma(struct fotg210_ep *ep,
|
||||
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);
|
||||
|
||||
if (dma_mapping_error(NULL, d)) {
|
||||
if (dma_mapping_error(dev, d)) {
|
||||
pr_err("dma_mapping_error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dma_sync_single_for_device(NULL, d, length,
|
||||
ep->dir_in ? DMA_TO_DEVICE :
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
fotg210_enable_dma(ep, d, length);
|
||||
|
||||
/* check if dma is done */
|
||||
@ -370,7 +367,7 @@ static void fotg210_start_dma(struct fotg210_ep *ep,
|
||||
/* update actual transfer 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,
|
||||
|
@ -516,8 +516,8 @@ static int net2280_disable(struct usb_ep *_ep)
|
||||
unsigned long flags;
|
||||
|
||||
ep = container_of(_ep, struct net2280_ep, ep);
|
||||
if (!_ep || !ep->desc || _ep->name == ep0name) {
|
||||
pr_err("%s: Invalid ep=%p or ep->desc\n", __func__, _ep);
|
||||
if (!_ep || _ep->name == ep0name) {
|
||||
pr_err("%s: Invalid ep=%p\n", __func__, _ep);
|
||||
return -EINVAL;
|
||||
}
|
||||
spin_lock_irqsave(&ep->dev->lock, flags);
|
||||
@ -2279,7 +2279,7 @@ static void usb_reinit_338x(struct net2280 *dev)
|
||||
* - It is safe to set for all connection speeds; all chip revisions.
|
||||
* - R-M-W to leave other bits undisturbed.
|
||||
* - Reference PLX TT-7372
|
||||
*/
|
||||
*/
|
||||
val = readl(&dev->ll_chicken_reg->ll_tsn_chicken_bit);
|
||||
val |= BIT(RECOVERY_IDLE_TO_RECOVER_FMW);
|
||||
writel(val, &dev->ll_chicken_reg->ll_tsn_chicken_bit);
|
||||
|
@ -2629,6 +2629,10 @@ static const struct of_device_id usb3_of_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, usb3_of_match);
|
||||
|
||||
static const struct soc_device_attribute renesas_usb3_quirks_match[] = {
|
||||
{
|
||||
.soc_id = "r8a774c0",
|
||||
.data = &renesas_usb3_priv_r8a77990,
|
||||
},
|
||||
{
|
||||
.soc_id = "r8a7795", .revision = "ES1.*",
|
||||
.data = &renesas_usb3_priv_r8a7795_es1,
|
||||
|
@ -347,6 +347,14 @@ static unsigned get_maxpacket(struct usb_device *udev, int pipe)
|
||||
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)
|
||||
{
|
||||
unsigned i;
|
||||
@ -1976,8 +1984,13 @@ static struct urb *iso_alloc_urb(
|
||||
|
||||
if (bytes < 0 || !desc)
|
||||
return NULL;
|
||||
|
||||
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);
|
||||
|
||||
urb = usb_alloc_urb(packets, GFP_KERNEL);
|
||||
@ -2065,17 +2078,24 @@ test_queue(struct usbtest_dev *dev, struct usbtest_param_32 *param,
|
||||
packets *= param->iterations;
|
||||
|
||||
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,
|
||||
"iso period %d %sframes, wMaxPacket %d, transactions: %d\n",
|
||||
1 << (desc->bInterval - 1),
|
||||
(udev->speed == USB_SPEED_HIGH) ? "micro" : "",
|
||||
(udev->speed >= USB_SPEED_HIGH) ? "micro" : "",
|
||||
usb_endpoint_maxp(desc),
|
||||
usb_endpoint_maxp_mult(desc));
|
||||
transaction_num);
|
||||
|
||||
dev_info(&dev->intf->dev,
|
||||
"total %lu msec (%lu packets)\n",
|
||||
(packets * (1 << (desc->bInterval - 1)))
|
||||
/ ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
|
||||
/ ((udev->speed >= USB_SPEED_HIGH) ? 8 : 1),
|
||||
packets);
|
||||
}
|
||||
|
||||
|
@ -400,7 +400,7 @@ static int twl6030_usb_remove(struct platform_device *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,
|
||||
REG_INT_MSK_LINE_C);
|
||||
twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
|
||||
|
Loading…
Reference in New Issue
Block a user