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:
Greg Kroah-Hartman 2019-02-15 09:08:57 +01:00
Родитель 09aa11cfda 5895d311d2
Коммит dc8b2a691d
48 изменённых файлов: 381 добавлений и 263 удалений

Просмотреть файл

@ -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(&params, 0, sizeof(params));
ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
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,