From 202adafe5a6e68fea30982c57cf51489936487ef Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 17 May 2017 13:19:06 +0300 Subject: usb: dwc3: gadget: don't WARN about lack of TRBs We don't need a big fat warning with stack dump at all. Running out of TRBs is a normal condition and we will have more TRBs available as soon as some transfers complete. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 6f6f0b3be3ad..7113a9f53ca9 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -953,7 +953,6 @@ static struct dwc3_trb *dwc3_ep_prev_trb(struct dwc3_ep *dep, u8 index) static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep) { struct dwc3_trb *tmp; - struct dwc3 *dwc = dep->dwc; u8 trbs_left; /* @@ -965,8 +964,7 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep) */ if (dep->trb_enqueue == dep->trb_dequeue) { tmp = dwc3_ep_prev_trb(dep, dep->trb_enqueue); - if (dev_WARN_ONCE(dwc->dev, tmp->ctrl & DWC3_TRB_CTRL_HWO, - "%s No TRBS left\n", dep->name)) + if (tmp->ctrl & DWC3_TRB_CTRL_HWO) return 0; return DWC3_TRB_NUM - 1; -- cgit v1.2.3 From cdb55b39fab82b5d48c9a7aa0348268f07b993ed Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 17 May 2017 13:21:14 +0300 Subject: usb: dwc3: gadget: lazily map requests for DMA Some functions might want to have very, very long request queues. We can't make any assumptions about how many requests we *are* able to map, so instead of mapping requests early, let's map them late. This way, functions can queue as many requests as they'd like but we won't take DMA resources until they are needed. Also, we can now stop processing requests when we run out of DMA resources but still keep requests in the queue for late processing. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 7113a9f53ca9..750364eb11e1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1099,6 +1099,17 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) } list_for_each_entry_safe(req, n, &dep->pending_list, list) { + struct dwc3 *dwc = dep->dwc; + int ret; + + ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request, + dep->direction); + if (ret) + return; + + req->sg = req->request.sg; + req->num_pending_sgs = req->request.num_mapped_sgs; + if (req->num_pending_sgs > 0) dwc3_prepare_one_trb_sg(dep, req); else @@ -1205,7 +1216,7 @@ static void dwc3_gadget_start_isoc(struct dwc3 *dwc, static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) { struct dwc3 *dwc = dep->dwc; - int ret; + int ret = 0; if (!dep->endpoint.desc) { dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n", @@ -1229,14 +1240,6 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) trace_dwc3_ep_queue(req); - ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request, - dep->direction); - if (ret) - return ret; - - req->sg = req->request.sg; - req->num_pending_sgs = req->request.num_mapped_sgs; - list_add_tail(&req->list, &dep->pending_list); /* -- cgit v1.2.3 From 65db7a0c9816370da5303500c7ba3754fa430720 Mon Sep 17 00:00:00 2001 From: William Wu Date: Wed, 19 Apr 2017 20:11:38 +0800 Subject: usb: dwc3: add disable u2mac linestate check quirk This patch adds a quirk to disable USB 2.0 MAC linestate check during HS transmit. Refer the dwc3 databook, we can use it for some special platforms if the linestate not reflect the expected line state(J) during transmission. When use this quirk, the controller implements a fixed 40-bit TxEndDelay after the packet is given on UTMI and ignores the linestate during the transmit of a token (during token-to-token and token-to-data IPGAP). On some rockchip platforms (e.g. rk3399), it requires to disable the u2mac linestate check to decrease the SSPLIT token to SETUP token inter-packet delay from 566ns to 466ns, and fix the issue that FS/LS devices not recognized if inserted through USB 3.0 HUB. Acked-by: Rob Herring Reviewed-by: Guenter Roeck Signed-off-by: William Wu Signed-off-by: Felipe Balbi --- Documentation/devicetree/bindings/usb/dwc3.txt | 2 ++ drivers/usb/dwc3/core.c | 20 ++++++++++++++------ drivers/usb/dwc3/core.h | 4 ++++ 3 files changed, 20 insertions(+), 6 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index f658f394c2d3..52fb41046b34 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt @@ -45,6 +45,8 @@ Optional properties: a free-running PHY clock. - snps,dis-del-phy-power-chg-quirk: when set core will change PHY power from P0 to P1/P2/P3 without delay. + - snps,dis-tx-ipgap-linecheck-quirk: when set, disable u2mac linestate check + during HS transmit. - snps,is-utmi-l1-suspend: true when DWC3 asserts output signal utmi_l1_suspend_n, false when asserts utmi_sleep_n - snps,hird-threshold: HIRD threshold diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 455d89a1cd6d..9d5a67cc2645 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -796,13 +796,19 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); } - /* - * Enable hardware control of sending remote wakeup in HS when - * the device is in the L1 state. - */ - if (dwc->revision >= DWC3_REVISION_290A) { + if (dwc->revision >= DWC3_REVISION_250A) { reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); - reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW; + + /* + * Enable hardware control of sending remote wakeup + * in HS when the device is in the L1 state. + */ + if (dwc->revision >= DWC3_REVISION_290A) + reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW; + + if (dwc->dis_tx_ipgap_linecheck_quirk) + reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS; + dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); } @@ -1023,6 +1029,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) "snps,dis-u2-freeclk-exists-quirk"); dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev, "snps,dis-del-phy-power-chg-quirk"); + dwc->dis_tx_ipgap_linecheck_quirk = device_property_read_bool(dev, + "snps,dis-tx-ipgap-linecheck-quirk"); dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, "snps,tx_de_emphasis_quirk"); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 981c77f5628e..6f6294dbea9d 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -204,6 +204,7 @@ #define DWC3_GCTL_DSBLCLKGTNG BIT(0) /* Global User Control 1 Register */ +#define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28) #define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24) /* Global USB2 PHY Configuration Register */ @@ -850,6 +851,8 @@ struct dwc3_scratchpad_array { * provide a free-running PHY clock. * @dis_del_phy_power_chg_quirk: set if we disable delay phy power * change quirk. + * @dis_tx_ipgap_linecheck_quirk: set if we disable u2mac linestate + * check during HS transmit. * @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk * @tx_de_emphasis: Tx de-emphasis value * 0 - -6dB de-emphasis @@ -1004,6 +1007,7 @@ struct dwc3 { unsigned dis_rxdet_inp3_quirk:1; unsigned dis_u2_freeclk_exists_quirk:1; unsigned dis_del_phy_power_chg_quirk:1; + unsigned dis_tx_ipgap_linecheck_quirk:1; unsigned tx_de_emphasis_quirk:1; unsigned tx_de_emphasis:2; -- cgit v1.2.3 From 04fb365c453e14ff9e8a28f1c46050d920a27a4a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 17 May 2017 15:57:45 +0300 Subject: usb: dwc3: replace %p with %pK %p will leak kernel pointers, so let's not expose the information on dmesg and instead use %pK. %pK will only show the actual addresses if explicitly enabled under /proc/sys/kernel/kptr_restrict. Cc: Acked-by: Greg Kroah-Hartman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-st.c | 2 +- drivers/usb/dwc3/gadget.c | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c index dfbf464eb88c..505676fd3ba4 100644 --- a/drivers/usb/dwc3/dwc3-st.c +++ b/drivers/usb/dwc3/dwc3-st.c @@ -230,7 +230,7 @@ static int st_dwc3_probe(struct platform_device *pdev) dwc3_data->syscfg_reg_off = res->start; - dev_vdbg(&pdev->dev, "glue-logic addr 0x%p, syscfg-reg offset 0x%x\n", + dev_vdbg(&pdev->dev, "glue-logic addr 0x%pK, syscfg-reg offset 0x%x\n", dwc3_data->glue_base, dwc3_data->syscfg_reg_off); dwc3_data->rstc_pwrdn = diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 750364eb11e1..011ac3ccfbe7 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1224,12 +1224,9 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) return -ESHUTDOWN; } - if (WARN(req->dep != dep, "request %p belongs to '%s'\n", - &req->request, req->dep->name)) { - dev_err(dwc->dev, "%s: request %p belongs to '%s'\n", - dep->name, &req->request, req->dep->name); + if (WARN(req->dep != dep, "request %pK belongs to '%s'\n", + &req->request, req->dep->name)) return -EINVAL; - } pm_runtime_get(dwc->dev); @@ -1387,7 +1384,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, } goto out1; } - dev_err(dwc->dev, "request %p was not queued to %s\n", + dev_err(dwc->dev, "request %pK was not queued to %s\n", request, ep->name); ret = -EINVAL; goto out0; -- cgit v1.2.3 From bfad65ee9be2096a854e350ba6324e3e48ad5e1d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 19 Apr 2017 14:59:27 +0300 Subject: usb: dwc3: update documentation No functional changes, just making sure we can use these for ReST docs later. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 44 +++++++++-------- drivers/usb/dwc3/ep0.c | 2 +- drivers/usb/dwc3/gadget.c | 121 +++++++++++++++++++++++++++++++--------------- drivers/usb/dwc3/gadget.h | 22 +++++++-- 4 files changed, 124 insertions(+), 65 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 6f6294dbea9d..ea910acb4bb0 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1,4 +1,4 @@ -/** +/* * core.h - DesignWare USB3 DRD Core Header * * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com @@ -523,7 +523,6 @@ struct dwc3_event_buffer { * @trb_pool_dma: dma address of @trb_pool * @trb_enqueue: enqueue 'pointer' into TRB array * @trb_dequeue: dequeue 'pointer' into TRB array - * @desc: usb_endpoint_descriptor pointer * @dwc: pointer to DWC controller * @saved_state: ep state saved during hibernation * @flags: endpoint flags (wedged, stalled, ...) @@ -665,7 +664,7 @@ enum dwc3_link_state { * @bpl: DW0-3 * @bph: DW4-7 * @size: DW8-B - * @trl: DWC-F + * @ctrl: DWC-F */ struct dwc3_trb { u32 bpl; @@ -675,16 +674,16 @@ struct dwc3_trb { } __packed; /** - * dwc3_hwparams - copy of HWPARAMS registers - * @hwparams0 - GHWPARAMS0 - * @hwparams1 - GHWPARAMS1 - * @hwparams2 - GHWPARAMS2 - * @hwparams3 - GHWPARAMS3 - * @hwparams4 - GHWPARAMS4 - * @hwparams5 - GHWPARAMS5 - * @hwparams6 - GHWPARAMS6 - * @hwparams7 - GHWPARAMS7 - * @hwparams8 - GHWPARAMS8 + * struct dwc3_hwparams - copy of HWPARAMS registers + * @hwparams0: GHWPARAMS0 + * @hwparams1: GHWPARAMS1 + * @hwparams2: GHWPARAMS2 + * @hwparams3: GHWPARAMS3 + * @hwparams4: GHWPARAMS4 + * @hwparams5: GHWPARAMS5 + * @hwparams6: GHWPARAMS6 + * @hwparams7: GHWPARAMS7 + * @hwparams8: GHWPARAMS8 */ struct dwc3_hwparams { u32 hwparams0; @@ -731,7 +730,8 @@ struct dwc3_hwparams { * @unaligned: true for OUT endpoints with length not divisible by maxp * @direction: IN or OUT direction flag * @mapped: true when request has been dma-mapped - * @queued: true when request has been queued to HW + * @started: request is started + * @zero: wants a ZLP */ struct dwc3_request { struct usb_request request; @@ -762,17 +762,23 @@ struct dwc3_scratchpad_array { /** * struct dwc3 - representation of our controller - * @drd_work - workqueue used for role swapping + * @drd_work: workqueue used for role swapping * @ep0_trb: trb which is used for the ctrl_req + * @bounce: address of bounce buffer + * @scratchbuf: address of scratch buffer * @setup_buf: used while precessing STD USB requests - * @ep0_trb: dma address of ep0_trb + * @ep0_trb_addr: dma address of @ep0_trb + * @bounce_addr: dma address of @bounce * @ep0_usb_req: dummy req used while handling STD USB requests * @scratch_addr: dma address of scratchbuf * @ep0_in_setup: one control transfer is completed and enter setup phase * @lock: for synchronizing * @dev: pointer to our struct device + * @sysdev: pointer to the DMA-capable device * @xhci: pointer to our xHCI child - * @event_buffer_list: a list of event buffers + * @xhci_resources: struct resources for our @xhci child + * @ev_buf: struct dwc3_event_buffer pointer + * @eps: endpoint array * @gadget: device side representation of the peripheral controller * @gadget_driver: pointer to the gadget driver * @regs: base address for our registers @@ -796,8 +802,6 @@ struct dwc3_scratchpad_array { * @usb2_generic_phy: pointer to USB2 PHY * @usb3_generic_phy: pointer to USB3 PHY * @ulpi: pointer to ulpi interface - * @dcfg: saved contents of DCFG register - * @gctl: saved contents of GCTL register * @isoch_delay: wValue from Set Isochronous Delay request; * @u2sel: parameter from Set SEL request. * @u2pel: parameter from Set SEL request. @@ -831,7 +835,6 @@ struct dwc3_scratchpad_array { * @pending_events: true when we have pending IRQs to be handled * @pullups_connected: true when Run/Stop bit is set * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround - * @start_config_issued: true when StartConfig command has been issued * @three_stage_setup: set if we perform a three phase setup * @usb3_lpm_capable: set if hadrware supports Link Power Management * @disable_scramble_quirk: set if we enable the disable scramble quirk @@ -846,6 +849,7 @@ struct dwc3_scratchpad_array { * @dis_u2_susphy_quirk: set if we disable usb2 suspend phy * @dis_enblslpm_quirk: set if we clear enblslpm in GUSB2PHYCFG, * disabling the suspend signal to the PHY. + * @dis_rxdet_inp3_quirk: set if we disable Rx.Detect in P3 * @dis_u2_freeclk_exists_quirk : set if we clear u2_freeclk_exists * in GUSB2PHYCFG, specify that USB2 PHY doesn't * provide a free-running PHY clock. diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index a78c78e7a8c3..8cfce8425101 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -1,4 +1,4 @@ -/** +/* * ep0.c - DesignWare USB3 DRD Controller Endpoint 0 Handling * * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 011ac3ccfbe7..e4e872c703f1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1,4 +1,4 @@ -/** +/* * gadget.c - DesignWare USB3 DRD Controller Gadget Framework Link * * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com @@ -36,13 +36,12 @@ #include "io.h" /** - * dwc3_gadget_set_test_mode - Enables USB2 Test Modes + * dwc3_gadget_set_test_mode - enables usb2 test modes * @dwc: pointer to our context structure * @mode: the mode to set (J, K SE0 NAK, Force Enable) * - * Caller should take care of locking. This function will - * return 0 on success or -EINVAL if wrong Test Selector - * is passed + * Caller should take care of locking. This function will return 0 on + * success or -EINVAL if wrong Test Selector is passed. */ int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode) { @@ -69,7 +68,7 @@ int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode) } /** - * dwc3_gadget_get_link_state - Gets current state of USB Link + * dwc3_gadget_get_link_state - gets current state of usb link * @dwc: pointer to our context structure * * Caller should take care of locking. This function will @@ -85,7 +84,7 @@ int dwc3_gadget_get_link_state(struct dwc3 *dwc) } /** - * dwc3_gadget_set_link_state - Sets USB Link to a particular State + * dwc3_gadget_set_link_state - sets usb link to a particular state * @dwc: pointer to our context structure * @state: the state to put link into * @@ -143,8 +142,8 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) } /** - * dwc3_ep_inc_trb() - Increment a TRB index. - * @index - Pointer to the TRB index to increment. + * dwc3_ep_inc_trb - increment a trb index. + * @index: Pointer to the TRB index to increment. * * The index should never point to the link TRB. After incrementing, * if it is point to the link TRB, wrap around to the beginning. The @@ -157,16 +156,34 @@ static void dwc3_ep_inc_trb(u8 *index) *index = 0; } +/** + * dwc3_ep_inc_enq - increment endpoint's enqueue pointer + * @dep: The endpoint whose enqueue pointer we're incrementing + */ static void dwc3_ep_inc_enq(struct dwc3_ep *dep) { dwc3_ep_inc_trb(&dep->trb_enqueue); } +/** + * dwc3_ep_inc_deq - increment endpoint's dequeue pointer + * @dep: The endpoint whose enqueue pointer we're incrementing + */ static void dwc3_ep_inc_deq(struct dwc3_ep *dep) { dwc3_ep_inc_trb(&dep->trb_dequeue); } +/** + * dwc3_gadget_giveback - call struct usb_request's ->complete callback + * @dep: The endpoint to whom the request belongs to + * @req: The request we're giving back + * @status: completion code for the request + * + * Must be called with controller's lock held and interrupts disabled. This + * function will unmap @req and call its ->complete() callback to notify upper + * layers that it has completed. + */ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, int status) { @@ -193,6 +210,15 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, pm_runtime_put(dwc->dev); } +/** + * dwc3_send_gadget_generic_command - issue a generic command for the controller + * @dwc: pointer to the controller context + * @cmd: the command to be issued + * @param: command parameter + * + * Caller should take care of locking. Issue @cmd with a given @param to @dwc + * and wait for its completion. + */ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param) { u32 timeout = 500; @@ -225,6 +251,15 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param) static int __dwc3_gadget_wakeup(struct dwc3 *dwc); +/** + * dwc3_send_gadget_ep_cmd - issue an endpoint command + * @dep: the endpoint to which the command is going to be issued + * @cmd: the command to be issued + * @params: parameters to the command + * + * Caller should handle locking. This function will issue @cmd with given + * @params to @dep and wait for its completion. + */ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, struct dwc3_gadget_ep_cmd_params *params) { @@ -422,36 +457,38 @@ static void dwc3_free_trb_pool(struct dwc3_ep *dep) static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep); /** - * dwc3_gadget_start_config - Configure EP resources + * dwc3_gadget_start_config - configure ep resources * @dwc: pointer to our controller context structure * @dep: endpoint that is being enabled * - * The assignment of transfer resources cannot perfectly follow the - * data book due to the fact that the controller driver does not have - * all knowledge of the configuration in advance. It is given this - * information piecemeal by the composite gadget framework after every - * SET_CONFIGURATION and SET_INTERFACE. Trying to follow the databook - * programming model in this scenario can cause errors. For two - * reasons: + * Issue a %DWC3_DEPCMD_DEPSTARTCFG command to @dep. After the command's + * completion, it will set Transfer Resource for all available endpoints. * - * 1) The databook says to do DEPSTARTCFG for every SET_CONFIGURATION - * and SET_INTERFACE (8.1.5). This is incorrect in the scenario of - * multiple interfaces. + * The assignment of transfer resources cannot perfectly follow the data book + * due to the fact that the controller driver does not have all knowledge of the + * configuration in advance. It is given this information piecemeal by the + * composite gadget framework after every SET_CONFIGURATION and + * SET_INTERFACE. Trying to follow the databook programming model in this + * scenario can cause errors. For two reasons: * - * 2) The databook does not mention doing more DEPXFERCFG for new + * 1) The databook says to do %DWC3_DEPCMD_DEPSTARTCFG for every + * %USB_REQ_SET_CONFIGURATION and %USB_REQ_SET_INTERFACE (8.1.5). This is + * incorrect in the scenario of multiple interfaces. + * + * 2) The databook does not mention doing more %DWC3_DEPCMD_DEPXFERCFG for new * endpoint on alt setting (8.1.6). * * The following simplified method is used instead: * - * All hardware endpoints can be assigned a transfer resource and this - * setting will stay persistent until either a core reset or - * hibernation. So whenever we do a DEPSTARTCFG(0) we can go ahead and - * do DEPXFERCFG for every hardware endpoint as well. We are + * All hardware endpoints can be assigned a transfer resource and this setting + * will stay persistent until either a core reset or hibernation. So whenever we + * do a %DWC3_DEPCMD_DEPSTARTCFG(0) we can go ahead and do + * %DWC3_DEPCMD_DEPXFERCFG for every hardware endpoint as well. We are * guaranteed that there are as many transfer resources as endpoints. * - * This function is called for each endpoint when it is being enabled - * but is triggered only when called for EP0-out, which always happens - * first, and which should only happen in one of the above conditions. + * This function is called for each endpoint when it is being enabled but is + * triggered only when called for EP0-out, which always happens first, and which + * should only happen in one of the above conditions. */ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) { @@ -569,11 +606,13 @@ static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep) } /** - * __dwc3_gadget_ep_enable - Initializes a HW endpoint + * __dwc3_gadget_ep_enable - initializes a hw endpoint * @dep: endpoint to be initialized - * @desc: USB Endpoint Descriptor + * @modify: if true, modify existing endpoint configuration + * @restore: if true, restore endpoint configuration from scratch buffer * - * Caller should take care of locking + * Caller should take care of locking. Execute all necessary commands to + * initialize a HW endpoint so it can be used by a gadget driver. */ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, bool modify, bool restore) @@ -685,11 +724,13 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) } /** - * __dwc3_gadget_ep_disable - Disables a HW endpoint + * __dwc3_gadget_ep_disable - disables a hw endpoint * @dep: the endpoint to disable * - * This function also removes requests which are currently processed ny the - * hardware and those which are not yet scheduled. + * This function undoes what __dwc3_gadget_ep_enable did and also removes + * requests which are currently being processed by the hardware and those which + * are not yet scheduled. + * * Caller should take care of locking. */ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) @@ -932,7 +973,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, } /** - * dwc3_ep_prev_trb() - Returns the previous TRB in the ring + * dwc3_ep_prev_trb - returns the previous TRB in the ring * @dep: The endpoint with the TRB ring * @index: The index of the current TRB in the ring * @@ -1729,8 +1770,8 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc); static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc); /** - * dwc3_gadget_setup_nump - Calculate and initialize NUMP field of DCFG - * dwc: pointer to our context structure + * dwc3_gadget_setup_nump - calculate and initialize NUMP field of %DWC3_DCFG + * @dwc: pointer to our context structure * * The following looks like complex but it's actually very simple. In order to * calculate the number of packets we can burst at once on OUT transfers, we're @@ -1789,7 +1830,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) reg = dwc3_readl(dwc->regs, DWC3_DCFG); reg &= ~(DWC3_DCFG_SPEED_MASK); - /** + /* * WORKAROUND: DWC3 revision < 2.20a have an issue * which would cause metastability state on Run/Stop * bit if we try to force the IP to USB2-only mode. @@ -2859,7 +2900,7 @@ static void dwc3_gadget_hibernation_interrupt(struct dwc3 *dwc, { unsigned int is_ss = evtinfo & BIT(4); - /** + /* * WORKAROUND: DWC3 revison 2.20a with hibernation support * have a known issue which can cause USB CV TD.9.23 to fail * randomly. @@ -3089,7 +3130,7 @@ out: } /** - * dwc3_gadget_init - Initializes gadget related registers + * dwc3_gadget_init - initializes gadget related registers * @dwc: pointer to our controller context structure * * Returns 0 on success otherwise negative errno. diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index e4602d0e515b..4a3227543255 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -1,4 +1,4 @@ -/** +/* * gadget.h - DesignWare USB3 DRD Gadget Header * * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com @@ -60,11 +60,25 @@ struct dwc3; #define to_dwc3_request(r) (container_of(r, struct dwc3_request, request)) +/** + * next_request - gets the next request on the given list + * @list: the request list to operate on + * + * Caller should take care of locking. This function return %NULL or the first + * request available on @list. + */ static inline struct dwc3_request *next_request(struct list_head *list) { return list_first_entry_or_null(list, struct dwc3_request, list); } +/** + * dwc3_gadget_move_started_request - move @req to the started_list + * @req: the request to be moved + * + * Caller should take care of locking. This function will move @req from its + * current list to the endpoint's started_list. + */ static inline void dwc3_gadget_move_started_request(struct dwc3_request *req) { struct dwc3_ep *dep = req->dep; @@ -87,10 +101,10 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol); /** * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW - * @dwc: DesignWare USB3 Pointer - * @number: DWC endpoint number + * @dep: dwc3 endpoint * - * Caller should take care of locking + * Caller should take care of locking. Returns the transfer resource + * index for a given endpoint. */ static inline u32 dwc3_gadget_ep_get_transfer_index(struct dwc3_ep *dep) { -- cgit v1.2.3 From 436841d53dd798ad67fc7c9bc7403613a9d9b4e0 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 20 Apr 2017 15:21:27 +0300 Subject: usb: dwc3: debugfs: slightly improve output of trb_ring Instead of printing out enqueue and dequeue pointer value as a header to the output, let's mark the TRBs in question with 'E' and 'D'. The output looks slightly easier to read. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 7be963dd8e3b..4e09be80e59f 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -653,16 +653,13 @@ static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused) goto out; } - seq_printf(s, "enqueue pointer %d\n", dep->trb_enqueue); - seq_printf(s, "dequeue pointer %d\n", dep->trb_dequeue); - seq_printf(s, "\n--------------------------------------------------\n\n"); seq_printf(s, "buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo\n"); for (i = 0; i < DWC3_TRB_NUM; i++) { struct dwc3_trb *trb = &dep->trb_pool[i]; unsigned int type = DWC3_TRBCTL_TYPE(trb->ctrl); - seq_printf(s, "%08x%08x,%d,%s,%d,%d,%d,%d,%d,%d\n", + seq_printf(s, "%08x%08x,%d,%s,%d,%d,%d,%d,%d,%d %c%c\n", trb->bph, trb->bpl, trb->size, dwc3_trb_type_string(type), !!(trb->ctrl & DWC3_TRB_CTRL_IOC), @@ -670,7 +667,9 @@ static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused) !!(trb->ctrl & DWC3_TRB_CTRL_CSP), !!(trb->ctrl & DWC3_TRB_CTRL_CHN), !!(trb->ctrl & DWC3_TRB_CTRL_LST), - !!(trb->ctrl & DWC3_TRB_CTRL_HWO)); + !!(trb->ctrl & DWC3_TRB_CTRL_HWO), + dep->trb_enqueue == i ? 'E' : ' ', + dep->trb_dequeue == i ? 'D' : ' '); } out: -- cgit v1.2.3 From dfc5e80578f21552e7d5880ea7c0556b8b625895 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 26 Apr 2017 13:44:51 +0300 Subject: usb: dwc3: gadget: slight cleanup to dwc3_process_event_entry() No functional changes, just a slight readability improvement. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e4e872c703f1..d2bd28dc28b6 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2972,20 +2972,12 @@ static void dwc3_process_event_entry(struct dwc3 *dwc, { trace_dwc3_event(event->raw, dwc); - /* Endpoint IRQ, handle it and return early */ - if (event->type.is_devspec == 0) { - /* depevt */ - return dwc3_endpoint_interrupt(dwc, &event->depevt); - } - - switch (event->type.type) { - case DWC3_EVENT_TYPE_DEV: + if (!event->type.is_devspec) + dwc3_endpoint_interrupt(dwc, &event->depevt); + else if (event->type.type == DWC3_EVENT_TYPE_DEV) dwc3_gadget_interrupt(dwc, &event->devt); - break; - /* REVISIT what to do with Carkit and I2C events ? */ - default: + else dev_err(dwc->dev, "UNKNOWN IRQ type %d\n", event->raw); - } } static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt) -- cgit v1.2.3 From e42f09b85f200e277d6d11d8c973f18efcc847fd Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 28 Apr 2017 12:54:52 +0300 Subject: usb: dwc3: trace: rely on __string() and __assign_str() Instead of going for a 512 byte buffer and using snprintf(), let's rely on helps __string() and __assign_str() where possible. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/trace.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index f1bd444d22a3..15909b579e69 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h @@ -107,7 +107,7 @@ DECLARE_EVENT_CLASS(dwc3_log_request, TP_PROTO(struct dwc3_request *req), TP_ARGS(req), TP_STRUCT__entry( - __dynamic_array(char, name, DWC3_MSG_MAX) + __string(name, req->dep->name) __field(struct dwc3_request *, req) __field(unsigned, actual) __field(unsigned, length) @@ -117,7 +117,7 @@ DECLARE_EVENT_CLASS(dwc3_log_request, __field(int, no_interrupt) ), TP_fast_assign( - snprintf(__get_str(name), DWC3_MSG_MAX, "%s", req->dep->name); + __assign_str(name, req->dep->name); __entry->req = req; __entry->actual = req->request.actual; __entry->length = req->request.length; @@ -190,7 +190,7 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd, struct dwc3_gadget_ep_cmd_params *params, int cmd_status), TP_ARGS(dep, cmd, params, cmd_status), TP_STRUCT__entry( - __dynamic_array(char, name, DWC3_MSG_MAX) + __string(name, dep->name) __field(unsigned int, cmd) __field(u32, param0) __field(u32, param1) @@ -198,7 +198,7 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd, __field(int, cmd_status) ), TP_fast_assign( - snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name); + __assign_str(name, dep->name); __entry->cmd = cmd; __entry->param0 = params->param0; __entry->param1 = params->param1; @@ -223,7 +223,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb), TP_ARGS(dep, trb), TP_STRUCT__entry( - __dynamic_array(char, name, DWC3_MSG_MAX) + __string(name, dep->name) __field(struct dwc3_trb *, trb) __field(u32, allocated) __field(u32, queued) @@ -234,7 +234,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, __field(u32, type) ), TP_fast_assign( - snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name); + __assign_str(name, dep->name); __entry->trb = trb; __entry->allocated = dep->allocated_requests; __entry->queued = dep->queued_requests; @@ -291,7 +291,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep, TP_PROTO(struct dwc3_ep *dep), TP_ARGS(dep), TP_STRUCT__entry( - __dynamic_array(char, name, DWC3_MSG_MAX) + __string(name, dep->name) __field(unsigned, maxpacket) __field(unsigned, maxpacket_limit) __field(unsigned, max_streams) @@ -302,7 +302,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep, __field(u8, trb_dequeue) ), TP_fast_assign( - snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name); + __assign_str(name, dep->name); __entry->maxpacket = dep->endpoint.maxpacket; __entry->maxpacket_limit = dep->endpoint.maxpacket_limit; __entry->max_streams = dep->endpoint.max_streams; -- cgit v1.2.3 From 3587f36a125fd18596e8068ec70cbaae84bb624c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 28 Apr 2017 11:28:35 +0300 Subject: usb: dwc3: debug: remove static char buffer from dwc3_decode_event() Instead, we can require caller to pass a buffer for the function to use. This cleans things quite a bit. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debug.h | 13 ++++++------- drivers/usb/dwc3/trace.h | 4 +++- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index cb2d8d3f7f3d..1025713ebdd1 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h @@ -173,9 +173,8 @@ static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) * @event: the event code */ static inline const char * -dwc3_gadget_event_string(const struct dwc3_event_devt *event) +dwc3_gadget_event_string(char *str, const struct dwc3_event_devt *event) { - static char str[256]; enum dwc3_link_state state = event->event_info & DWC3_LINK_STATE_MASK; switch (event->type) { @@ -228,10 +227,10 @@ dwc3_gadget_event_string(const struct dwc3_event_devt *event) * @event: then event code */ static inline const char * -dwc3_ep_event_string(const struct dwc3_event_depevt *event, u32 ep0state) +dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event, + u32 ep0state) { u8 epnum = event->endpoint_number; - static char str[256]; size_t len; int status; int ret; @@ -332,14 +331,14 @@ static inline const char *dwc3_gadget_event_type_string(u8 event) } } -static inline const char *dwc3_decode_event(u32 event, u32 ep0state) +static inline const char *dwc3_decode_event(char *str, u32 event, u32 ep0state) { const union dwc3_event evt = (union dwc3_event) event; if (evt.type.is_devspec) - return dwc3_gadget_event_string(&evt.devt); + return dwc3_gadget_event_string(str, &evt.devt); else - return dwc3_ep_event_string(&evt.depevt, ep0state); + return dwc3_ep_event_string(str, &evt.depevt, ep0state); } static inline const char *dwc3_ep_cmd_status_string(int status) diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index 15909b579e69..af093b4e5dc5 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h @@ -60,13 +60,15 @@ DECLARE_EVENT_CLASS(dwc3_log_event, TP_STRUCT__entry( __field(u32, event) __field(u32, ep0state) + __dynamic_array(char, str, DWC3_MSG_MAX) ), TP_fast_assign( __entry->event = event; __entry->ep0state = dwc->ep0state; ), TP_printk("event (%08x): %s", __entry->event, - dwc3_decode_event(__entry->event, __entry->ep0state)) + dwc3_decode_event(__get_str(str), __entry->event, + __entry->ep0state)) ); DEFINE_EVENT(dwc3_log_event, dwc3_event, -- cgit v1.2.3 From af32423a2d866a3263552b000a70c11cffbd2b55 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 26 Apr 2017 16:09:09 +0300 Subject: usb: dwc3: trace: decode ctrl request Instead of *always* dumping raw ctrl bytes, let's decode standard requests which will make the lives of those debugging DWC3 quite a bit easier. Output will now look like so: irq/34-dwc3-1594 [000] d..1 107.573081: dwc3_ctrl_req: Get Device Descriptor(Index = 0, Length = 18) irq/34-dwc3-1594 [000] d..1 107.573694: dwc3_ctrl_req: Set Address(Addr = 01) irq/34-dwc3-1594 [000] d..1 107.588319: dwc3_ctrl_req: Get Device Descriptor(Index = 0, Length = 18) irq/34-dwc3-1594 [000] d..1 107.588816: dwc3_ctrl_req: Get Configuration Descriptor(Index = 0, Length = 9) irq/34-dwc3-1594 [000] d..1 107.589191: dwc3_ctrl_req: Set Configuration(Config = 3) irq/34-dwc3-1594 [000] d..1 107.589846: dwc3_ctrl_req: Get BOS Descriptor(Index = 0, Length = 5) irq/34-dwc3-1594 [000] d..1 107.590146: dwc3_ctrl_req: Get BOS Descriptor(Index = 0, Length = 22) irq/34-dwc3-1594 [000] d..1 107.590546: dwc3_ctrl_req: Get Configuration Descriptor(Index = 0, Length = 9) irq/34-dwc3-1594 [000] d..1 107.590840: dwc3_ctrl_req: Get Configuration Descriptor(Index = 0, Length = 69) irq/34-dwc3-1594 [000] d..1 107.591138: dwc3_ctrl_req: Get Configuration Descriptor(Index = 1, Length = 9) irq/34-dwc3-1594 [000] d..1 107.591541: dwc3_ctrl_req: Get Configuration Descriptor(Index = 1, Length = 32) irq/34-dwc3-1594 [000] d..1 107.591834: dwc3_ctrl_req: Get Device Descriptor(Index = 0, Length = 18) irq/34-dwc3-1594 [000] d..1 114.701005: dwc3_ctrl_req: Get Device Descriptor(Index = 0, Length = 18) irq/34-dwc3-1594 [000] d..1 114.721080: dwc3_ctrl_req: Get Device Descriptor(Index = 0, Length = 18) irq/34-dwc3-1594 [000] d..1 114.722709: dwc3_ctrl_req: Get Device Descriptor(Index = 0, Length = 18) irq/34-dwc3-1594 [000] d..1 114.728979: dwc3_ctrl_req: Get Device Descriptor(Index = 0, Length = 18) irq/34-dwc3-1594 [000] d..1 114.730544: dwc3_ctrl_req: Get Device Qualifier Descriptor(Index = 0, Length = 10) irq/34-dwc3-1594 [000] d..1 115.776018: dwc3_ctrl_req: Get Configuration Descriptor(Index = 0, Length = 9) irq/34-dwc3-1594 [000] d..1 115.776760: dwc3_ctrl_req: Set Configuration(Config = 0) irq/34-dwc3-1594 [000] d..1 115.777676: dwc3_ctrl_req: Get Configuration(Length = 1) irq/34-dwc3-1594 [000] d..1 115.924797: dwc3_ctrl_req: Get Device Descriptor(Index = 0, Length = 18) irq/34-dwc3-1594 [000] d..1 115.929025: dwc3_ctrl_req: Get String Descriptor(Index = 0, Length = 500) irq/34-dwc3-1594 [000] d..1 115.929566: dwc3_ctrl_req: Get String Descriptor(Index = 1, Length = 500) irq/34-dwc3-1594 [000] d..1 115.930911: dwc3_ctrl_req: Get String Descriptor(Index = 0, Length = 500) irq/34-dwc3-1594 [000] d..1 115.931528: dwc3_ctrl_req: Get String Descriptor(Index = 2, Length = 500) irq/34-dwc3-1594 [000] d..1 115.932950: dwc3_ctrl_req: Get String Descriptor(Index = 0, Length = 500) irq/34-dwc3-1594 [000] d..1 115.933533: dwc3_ctrl_req: Get String Descriptor(Index = 3, Length = 500) Note that Class and Vendor requests won't be decoded for obvious reasons. Those will be printed as a raw sequence of bytes. This patch has been tested against a normal host (both Linux and Windows) and USB30CV Chapter 9 tests. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debug.h | 234 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/dwc3/trace.h | 8 +- 2 files changed, 238 insertions(+), 4 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index 1025713ebdd1..5e9c070ec874 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h @@ -222,6 +222,240 @@ dwc3_gadget_event_string(char *str, const struct dwc3_event_devt *event) return str; } +static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str) +{ + switch (t & USB_RECIP_MASK) { + case USB_RECIP_INTERFACE: + sprintf(str, "Get Interface Status(Intf = %d, Length = %d)", + i, l); + break; + case USB_RECIP_ENDPOINT: + sprintf(str, "Get Endpoint Status(ep%d%s)", + i & ~USB_DIR_IN, + i & USB_DIR_IN ? "in" : "out"); + break; + } +} + +static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v, + __u16 i, char *str) +{ + switch (t & USB_RECIP_MASK) { + case USB_RECIP_DEVICE: + sprintf(str, "%s Device Feature(%s%s)", + b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", + ({char *s; + switch (v) { + case USB_DEVICE_SELF_POWERED: + s = "Self Powered"; + break; + case USB_DEVICE_REMOTE_WAKEUP: + s = "Remote Wakeup"; + break; + case USB_DEVICE_TEST_MODE: + s = "Test Mode"; + break; + default: + s = "UNKNOWN"; + } s; }), + v == USB_DEVICE_TEST_MODE ? + ({ char *s; + switch (i) { + case TEST_J: + s = ": TEST_J"; + break; + case TEST_K: + s = ": TEST_K"; + break; + case TEST_SE0_NAK: + s = ": TEST_SE0_NAK"; + break; + case TEST_PACKET: + s = ": TEST_PACKET"; + break; + case TEST_FORCE_EN: + s = ": TEST_FORCE_EN"; + break; + default: + s = ": UNKNOWN"; + } s; }) : ""); + break; + case USB_RECIP_INTERFACE: + sprintf(str, "%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)", + b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", + v == USB_ENDPOINT_HALT ? "Halt" : "UNKNOWN", + i & ~USB_DIR_IN, + i & USB_DIR_IN ? "in" : "out"); + break; + } +} + +static inline void dwc3_decode_set_address(__u16 v, char *str) +{ + sprintf(str, "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) +{ + sprintf(str, "%s %s Descriptor(Index = %d, Length = %d)", + b == USB_REQ_GET_DESCRIPTOR ? "Get" : "Set", + ({ char *s; + switch (v >> 8) { + case USB_DT_DEVICE: + s = "Device"; + break; + case USB_DT_CONFIG: + s = "Configuration"; + break; + case USB_DT_STRING: + s = "String"; + break; + case USB_DT_INTERFACE: + s = "Interface"; + break; + case USB_DT_ENDPOINT: + s = "Endpoint"; + break; + case USB_DT_DEVICE_QUALIFIER: + s = "Device Qualifier"; + break; + case USB_DT_OTHER_SPEED_CONFIG: + s = "Other Speed Config"; + break; + case USB_DT_INTERFACE_POWER: + s = "Interface Power"; + break; + case USB_DT_OTG: + s = "OTG"; + break; + case USB_DT_DEBUG: + s = "Debug"; + break; + case USB_DT_INTERFACE_ASSOCIATION: + s = "Interface Association"; + break; + case USB_DT_BOS: + s = "BOS"; + break; + case USB_DT_DEVICE_CAPABILITY: + s = "Device Capability"; + break; + case USB_DT_PIPE_USAGE: + s = "Pipe Usage"; + break; + case USB_DT_SS_ENDPOINT_COMP: + s = "SS Endpoint Companion"; + break; + case USB_DT_SSP_ISOC_ENDPOINT_COMP: + s = "SSP Isochronous Endpoint Companion"; + break; + default: + s = "UNKNOWN"; + break; + } s; }), v & 0xff, l); +} + + +static inline void dwc3_decode_get_configuration(__u16 l, char *str) +{ + sprintf(str, "Get Configuration(Length = %d)", l); +} + +static inline void dwc3_decode_set_configuration(__u8 v, char *str) +{ + sprintf(str, "Set Configuration(Config = %d)", v); +} + +static inline void dwc3_decode_get_intf(__u16 i, __u16 l, char *str) +{ + sprintf(str, "Get Interface(Intf = %d, Length = %d)", i, l); +} + +static inline void dwc3_decode_set_intf(__u8 v, __u16 i, char *str) +{ + sprintf(str, "Set Interface(Intf = %d, Alt.Setting = %d)", i, v); +} + +static inline void dwc3_decode_synch_frame(__u16 i, __u16 l, char *str) +{ + sprintf(str, "Synch Frame(Endpoint = %d, Length = %d)", i, l); +} + +static inline void dwc3_decode_set_sel(__u16 l, char *str) +{ + sprintf(str, "Set SEL(Length = %d)", l); +} + +static inline void dwc3_decode_set_isoch_delay(__u8 v, char *str) +{ + sprintf(str, "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) +{ + switch (bRequest) { + case USB_REQ_GET_STATUS: + dwc3_decode_get_status(bRequestType, wIndex, wLength, str); + break; + case USB_REQ_CLEAR_FEATURE: + case USB_REQ_SET_FEATURE: + dwc3_decode_set_clear_feature(bRequestType, bRequest, wValue, + wIndex, str); + break; + case USB_REQ_SET_ADDRESS: + dwc3_decode_set_address(wValue, str); + break; + case USB_REQ_GET_DESCRIPTOR: + case USB_REQ_SET_DESCRIPTOR: + dwc3_decode_get_set_descriptor(bRequestType, bRequest, wValue, + wIndex, wLength, str); + break; + case USB_REQ_GET_CONFIGURATION: + dwc3_decode_get_configuration(wLength, str); + break; + case USB_REQ_SET_CONFIGURATION: + dwc3_decode_set_configuration(wValue, str); + break; + case USB_REQ_GET_INTERFACE: + dwc3_decode_get_intf(wIndex, wLength, str); + break; + case USB_REQ_SET_INTERFACE: + dwc3_decode_set_intf(wValue, wIndex, str); + break; + case USB_REQ_SYNCH_FRAME: + dwc3_decode_synch_frame(wIndex, wLength, str); + break; + case USB_REQ_SET_SEL: + dwc3_decode_set_sel(wLength, str); + break; + case USB_REQ_SET_ISOCH_DELAY: + dwc3_decode_set_isoch_delay(wValue, str); + break; + default: + sprintf(str, "%02x %02x %02x %02x %02x %02x %02x %02x", + bRequestType, bRequest, + cpu_to_le16(wValue) & 0xff, + cpu_to_le16(wValue) >> 8, + cpu_to_le16(wIndex) & 0xff, + cpu_to_le16(wIndex) >> 8, + cpu_to_le16(wLength) & 0xff, + cpu_to_le16(wLength) >> 8); + } + + return str; +} + /** * dwc3_ep_event_string - returns event name * @event: then event code diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index af093b4e5dc5..6504b116da04 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h @@ -85,6 +85,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl, __field(__u16, wValue) __field(__u16, wIndex) __field(__u16, wLength) + __dynamic_array(char, str, DWC3_MSG_MAX) ), TP_fast_assign( __entry->bRequestType = ctrl->bRequestType; @@ -93,10 +94,9 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl, __entry->wIndex = le16_to_cpu(ctrl->wIndex); __entry->wLength = le16_to_cpu(ctrl->wLength); ), - TP_printk("bRequestType %02x bRequest %02x wValue %04x wIndex %04x wLength %d", - __entry->bRequestType, __entry->bRequest, - __entry->wValue, __entry->wIndex, - __entry->wLength + TP_printk("%s", dwc3_decode_ctrl(__get_str(str), __entry->bRequestType, + __entry->bRequest, __entry->wValue, + __entry->wIndex, __entry->wLength) ) ); -- cgit v1.2.3 From 7d8d0639565ff22d5fad419c2f2887213d7c2915 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 6 Jun 2017 16:05:23 +0300 Subject: usb: dwc3: gadget: implement ->udc_set_speed() Use this method to make sure we don't try to connect on speeds not supported by the gadget driver. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 101 ++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 43 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index d2bd28dc28b6..01cd7ddc9981 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1827,49 +1827,6 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), 0); } - reg = dwc3_readl(dwc->regs, DWC3_DCFG); - reg &= ~(DWC3_DCFG_SPEED_MASK); - - /* - * WORKAROUND: DWC3 revision < 2.20a have an issue - * which would cause metastability state on Run/Stop - * bit if we try to force the IP to USB2-only mode. - * - * Because of that, we cannot configure the IP to any - * speed other than the SuperSpeed - * - * Refers to: - * - * STAR#9000525659: Clock Domain Crossing on DCTL in - * USB 2.0 Mode - */ - if (dwc->revision < DWC3_REVISION_220A) { - reg |= DWC3_DCFG_SUPERSPEED; - } else { - switch (dwc->maximum_speed) { - case USB_SPEED_LOW: - reg |= DWC3_DCFG_LOWSPEED; - break; - case USB_SPEED_FULL: - reg |= DWC3_DCFG_FULLSPEED; - break; - case USB_SPEED_HIGH: - reg |= DWC3_DCFG_HIGHSPEED; - break; - case USB_SPEED_SUPER_PLUS: - reg |= DWC3_DCFG_SUPERSPEED_PLUS; - break; - default: - dev_err(dwc->dev, "invalid dwc->maximum_speed (%d)\n", - dwc->maximum_speed); - /* fall through */ - case USB_SPEED_SUPER: - reg |= DWC3_DCFG_SUPERSPEED; - break; - } - } - dwc3_writel(dwc->regs, DWC3_DCFG, reg); - /* * We are telling dwc3 that we want to use DCFG.NUMP as ACK TP's NUMP * field instead of letting dwc3 itself calculate that automatically. @@ -2001,6 +1958,63 @@ out: return 0; } +static void dwc3_gadget_set_speed(struct usb_gadget *g, + enum usb_device_speed speed) +{ + struct dwc3 *dwc = gadget_to_dwc(g); + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&dwc->lock, flags); + reg = dwc3_readl(dwc->regs, DWC3_DCFG); + reg &= ~(DWC3_DCFG_SPEED_MASK); + + /* + * WORKAROUND: DWC3 revision < 2.20a have an issue + * which would cause metastability state on Run/Stop + * bit if we try to force the IP to USB2-only mode. + * + * Because of that, we cannot configure the IP to any + * speed other than the SuperSpeed + * + * Refers to: + * + * STAR#9000525659: Clock Domain Crossing on DCTL in + * USB 2.0 Mode + */ + if (dwc->revision < DWC3_REVISION_220A) { + reg |= DWC3_DCFG_SUPERSPEED; + } else { + switch (speed) { + case USB_SPEED_LOW: + reg |= DWC3_DCFG_LOWSPEED; + break; + case USB_SPEED_FULL: + reg |= DWC3_DCFG_FULLSPEED; + break; + case USB_SPEED_HIGH: + reg |= DWC3_DCFG_HIGHSPEED; + break; + case USB_SPEED_SUPER: + reg |= DWC3_DCFG_SUPERSPEED; + break; + case USB_SPEED_SUPER_PLUS: + reg |= DWC3_DCFG_SUPERSPEED_PLUS; + break; + default: + dev_err(dwc->dev, "invalid speed (%d)\n", speed); + + if (dwc->revision & DWC3_REVISION_IS_DWC31) + reg |= DWC3_DCFG_SUPERSPEED_PLUS; + else + reg |= DWC3_DCFG_SUPERSPEED; + } + } + dwc3_writel(dwc->regs, DWC3_DCFG, reg); + + spin_unlock_irqrestore(&dwc->lock, flags); +} + static const struct usb_gadget_ops dwc3_gadget_ops = { .get_frame = dwc3_gadget_get_frame, .wakeup = dwc3_gadget_wakeup, @@ -2008,6 +2022,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = { .pullup = dwc3_gadget_pullup, .udc_start = dwc3_gadget_start, .udc_stop = dwc3_gadget_stop, + .udc_set_speed = dwc3_gadget_set_speed, }; /* -------------------------------------------------------------------------- */ -- cgit v1.2.3 From 9b0a1f95c4b48a18ae95e204b1bcde47436b0248 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 8 Jun 2017 13:16:18 +0300 Subject: usb: dwc3: ep0: make sure wValue is 0 on GetStatus() We don't (yet) support PTM_STATUS messages so let's not reply to them erroneously. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 8cfce8425101..827e376bfa97 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -319,10 +319,16 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc, { struct dwc3_ep *dep; u32 recip; + u32 value; u32 reg; u16 usb_status = 0; __le16 *response_pkt; + /* We don't support PTM_STATUS */ + value = le16_to_cpu(ctrl->wValue); + if (value != 0) + return -EINVAL; + recip = ctrl->bRequestType & USB_RECIP_MASK; switch (recip) { case USB_RECIP_DEVICE: -- cgit v1.2.3 From e0082698b68981c8456061e509eb32c5f65b228c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 5 Jun 2017 17:01:22 +0300 Subject: usb: dwc3: ulpi: conditionally resume ULPI PHY If PHY is suspended by the time we want to issue ULPI transfers, we will observe timeouts on the ULPI interface. In order to avoid such issue, let's make sure PHY is resumed before issuing a ULPI transfer. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ulpi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/ulpi.c b/drivers/usb/dwc3/ulpi.c index bd86f84f3790..e87ce8e9edee 100644 --- a/drivers/usb/dwc3/ulpi.c +++ b/drivers/usb/dwc3/ulpi.c @@ -41,6 +41,12 @@ static int dwc3_ulpi_read(struct device *dev, u8 addr) u32 reg; int ret; + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + if (reg & DWC3_GUSB2PHYCFG_SUSPHY) { + reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + } + reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr); dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg); @@ -58,6 +64,12 @@ static int dwc3_ulpi_write(struct device *dev, u8 addr, u8 val) struct dwc3 *dwc = dev_get_drvdata(dev); u32 reg; + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + if (reg & DWC3_GUSB2PHYCFG_SUSPHY) { + reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + } + reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr); reg |= DWC3_GUSB2PHYACC_WRITE | val; dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg); -- cgit v1.2.3 From f54edb539c1167e7a96073848d0afad100df4580 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 5 Jun 2017 17:03:18 +0300 Subject: usb: dwc3: core: initialize ULPI before trying to get the PHY If don't reorder initialization like this, we will never be able to get a reference to ULPI PHYs. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 9d5a67cc2645..25165a97db5e 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -721,6 +721,8 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GCTL, reg); } +static int dwc3_core_get_phy(struct dwc3 *dwc); + /** * dwc3_core_init - Low-level initialization of DWC3 Core * @dwc: Pointer to our controller context structure @@ -759,6 +761,10 @@ static int dwc3_core_init(struct dwc3 *dwc) if (ret) goto err0; + ret = dwc3_core_get_phy(dwc); + if (ret) + goto err0; + dwc3_core_setup_global_control(dwc); dwc3_core_num_eps(dwc); @@ -1156,10 +1162,6 @@ static int dwc3_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dwc); dwc3_cache_hwparams(dwc); - ret = dwc3_core_get_phy(dwc); - if (ret) - goto err0; - spin_lock_init(&dwc->lock); pm_runtime_set_active(dev); -- cgit v1.2.3 From 958d1a4c40ddc24e02683074d04ad5cb30380705 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 5 Jun 2017 17:22:10 +0300 Subject: usb: dwc3: core: program PHY for proper DRD modes If PHY is entering Host mode, we need to enable VBUS. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 25165a97db5e..326b302fc440 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -151,11 +151,24 @@ static void __dwc3_set_mode(struct work_struct *work) switch (dwc->desired_dr_role) { case DWC3_GCTL_PRTCAP_HOST: ret = dwc3_host_init(dwc); - if (ret) + if (ret) { dev_err(dwc->dev, "failed to initialize host\n"); + } else { + if (dwc->usb2_phy) + otg_set_vbus(dwc->usb2_phy->otg, true); + if (dwc->usb2_generic_phy) + phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); + + } break; case DWC3_GCTL_PRTCAP_DEVICE: dwc3_event_buffers_setup(dwc); + + if (dwc->usb2_phy) + otg_set_vbus(dwc->usb2_phy->otg, false); + if (dwc->usb2_generic_phy) + phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE); + ret = dwc3_gadget_init(dwc); if (ret) dev_err(dwc->dev, "failed to initialize peripheral\n"); @@ -915,6 +928,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); + + if (dwc->usb2_phy) + otg_set_vbus(dwc->usb2_phy->otg, false); + if (dwc->usb2_generic_phy) + phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE); + ret = dwc3_gadget_init(dwc); if (ret) { if (ret != -EPROBE_DEFER) @@ -924,6 +943,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) break; case USB_DR_MODE_HOST: dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); + + if (dwc->usb2_phy) + otg_set_vbus(dwc->usb2_phy->otg, true); + if (dwc->usb2_generic_phy) + phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); + ret = dwc3_host_init(dwc); if (ret) { if (ret != -EPROBE_DEFER) -- cgit v1.2.3 From 46b780d46bccdc75b63a98b2a9cca5a4e0ff2cec Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 12 Jun 2017 15:11:25 +0300 Subject: usb: dwc3: gadget: increase readability of dwc3_gadget_init_endpoints() The commit 47d3946ea220 usb: dwc3: refactor gadget endpoint count calculation refactored dwc3_gadget_init_endpoints() and in particular changed in or out endpoint numbering to be through. It's not always convenient and makes code a slightly harder to read. Introduce a new temporary variable to make it easier to understand what is going on inside the function. While doing that, rename local variables as follows: u8 num -> u8 total int num -> int kbytes Replace implicit direction check via epnum with explicit use of direction variable. While here, replace %d to %u when compounding endpoint name since we are using unsigned type. Signed-off-by: Andy Shevchenko Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 01cd7ddc9981..7fd4b22f4e97 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2027,15 +2027,16 @@ static const struct usb_gadget_ops dwc3_gadget_ops = { /* -------------------------------------------------------------------------- */ -static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 num) +static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total) { struct dwc3_ep *dep; u8 epnum; INIT_LIST_HEAD(&dwc->gadget.ep_list); - for (epnum = 0; epnum < num; epnum++) { + for (epnum = 0; epnum < total; epnum++) { bool direction = epnum & 1; + u8 num = epnum >> 1; dep = kzalloc(sizeof(*dep), GFP_KERNEL); if (!dep) @@ -2047,7 +2048,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 num) dep->regs = dwc->regs + DWC3_DEP_BASE(epnum); dwc->eps[epnum] = dep; - snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1, + snprintf(dep->name, sizeof(dep->name), "ep%u%s", num, direction ? "in" : "out"); dep->endpoint.name = dep->name; @@ -2059,39 +2060,39 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 num) spin_lock_init(&dep->lock); - if (epnum == 0 || epnum == 1) { + if (num == 0) { usb_ep_set_maxpacket_limit(&dep->endpoint, 512); dep->endpoint.maxburst = 1; dep->endpoint.ops = &dwc3_gadget_ep0_ops; - if (!epnum) + if (!direction) dwc->gadget.ep0 = &dep->endpoint; } else if (direction) { int mdwidth; + int kbytes; int size; int ret; - int num; mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0); /* MDWIDTH is represented in bits, we need it in bytes */ mdwidth /= 8; - size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(epnum >> 1)); + size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num)); size = DWC3_GTXFIFOSIZ_TXFDEF(size); /* FIFO Depth is in MDWDITH bytes. Multiply */ size *= mdwidth; - num = size / 1024; - if (num == 0) - num = 1; + kbytes = size / 1024; + if (kbytes == 0) + kbytes = 1; /* - * FIFO sizes account an extra MDWIDTH * (num + 1) bytes for + * FIFO sizes account an extra MDWIDTH * (kbytes + 1) bytes for * internal overhead. We don't really know how these are used, * but documentation say it exists. */ - size -= mdwidth * (num + 1); - size /= num; + size -= mdwidth * (kbytes + 1); + size /= kbytes; usb_ep_set_maxpacket_limit(&dep->endpoint, size); @@ -2117,7 +2118,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 num) return ret; } - if (epnum == 0 || epnum == 1) { + if (num == 0) { dep->endpoint.caps.type_control = true; } else { dep->endpoint.caps.type_iso = true; -- cgit v1.2.3 From ece7af5f787ee94ef4a8adb5cd9c40d6f475a7ba Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 12 Jun 2017 16:23:31 +0530 Subject: usb: dwc3: exynos: Handle return value of clk_prepare_enable clk_prepare_enable() can fail here and we must check its return value. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Arvind Yadav Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-exynos.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/usb/dwc3') diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index 98f74ff66120..e089df72f766 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -125,12 +125,16 @@ static int dwc3_exynos_probe(struct platform_device *pdev) dev_err(dev, "couldn't get clock\n"); return -EINVAL; } - clk_prepare_enable(exynos->clk); + ret = clk_prepare_enable(exynos->clk); + if (ret) + return ret; exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk"); if (IS_ERR(exynos->susp_clk)) exynos->susp_clk = NULL; - clk_prepare_enable(exynos->susp_clk); + ret = clk_prepare_enable(exynos->susp_clk); + if (ret) + goto susp_clk_err; if (of_device_is_compatible(node, "samsung,exynos7-dwusb3")) { exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk"); @@ -139,7 +143,9 @@ static int dwc3_exynos_probe(struct platform_device *pdev) ret = -ENODEV; goto axius_clk_err; } - clk_prepare_enable(exynos->axius_clk); + ret = clk_prepare_enable(exynos->axius_clk); + if (ret) + goto axius_clk_err; } else { exynos->axius_clk = NULL; } @@ -197,6 +203,7 @@ vdd33_err: clk_disable_unprepare(exynos->axius_clk); axius_clk_err: clk_disable_unprepare(exynos->susp_clk); +susp_clk_err: clk_disable_unprepare(exynos->clk); return ret; } -- cgit v1.2.3