OSDN Git Service

usb: dwc2: Clear fifo_map when resetting core.
authorArtur Petrosyan <Arthur.Petrosyan@synopsys.com>
Fri, 16 Apr 2021 12:47:30 +0000 (16:47 +0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 22 Apr 2021 09:55:34 +0000 (11:55 +0200)
Switching from device mode to host mode by disconnecting
device cable core enters and exits form hibernation.
However, the fifo map remains not cleared. It results
to a WARNING (WARNING: CPU: 5 PID: 0 at drivers/usb/dwc2/
gadget.c:307 dwc2_hsotg_init_fifo+0x12/0x152 [dwc2])
if in host mode we disconnect the micro a to b host
cable. Because core reset occurs.

To avoid the WARNING, fifo_map should be cleared
in dwc2_core_reset() function by taking into account configs.
fifo_map must be cleared only if driver is configured in
"CONFIG_USB_DWC2_PERIPHERAL" or "CONFIG_USB_DWC2_DUAL_ROLE"
mode.

- Added "static inline void dwc2_clear_fifo_map()" helper
function to clear fifo_map with peripheral or dual role mode.

- Added a dummy version of "dwc2_clear_fifo_map()" helper
for host-only mode.

Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
Signed-off-by: Artur Petrosyan <Arthur.Petrosyan@synopsys.com>
Link: https://lore.kernel.org/r/20210416124731.C500AA005D@mailhost.synopsys.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/dwc2/core.c
drivers/usb/dwc2/core.h

index cb65f7f..eccd96f 100644 (file)
@@ -470,6 +470,22 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
                dwc2_writel(hsotg, greset, GRSTCTL);
        }
 
+       /*
+        * Switching from device mode to host mode by disconnecting
+        * device cable core enters and exits form hibernation.
+        * However, the fifo map remains not cleared. It results
+        * to a WARNING (WARNING: CPU: 5 PID: 0 at drivers/usb/dwc2/
+        * gadget.c:307 dwc2_hsotg_init_fifo+0x12/0x152 [dwc2])
+        * if in host mode we disconnect the micro a to b host
+        * cable. Because core reset occurs.
+        * To avoid the WARNING, fifo_map should be cleared
+        * in dwc2_core_reset() function by taking into account configs.
+        * fifo_map must be cleared only if driver is configured in
+        * "CONFIG_USB_DWC2_PERIPHERAL" or "CONFIG_USB_DWC2_DUAL_ROLE"
+        * mode.
+        */
+       dwc2_clear_fifo_map(hsotg);
+
        /* Wait for AHB master IDLE state */
        if (dwc2_hsotg_wait_bit_set(hsotg, GRSTCTL, GRSTCTL_AHBIDLE, 10000)) {
                dev_warn(hsotg->dev, "%s: HANG! AHB Idle timeout GRSTCTL GRSTCTL_AHBIDLE\n",
index e927701..da5ac4a 100644 (file)
@@ -1425,6 +1425,8 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg);
 int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg);
 void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg);
 void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg);
+static inline void dwc2_clear_fifo_map(struct dwc2_hsotg *hsotg)
+{ hsotg->fifo_map = 0; }
 #else
 static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2)
 { return 0; }
@@ -1469,6 +1471,7 @@ static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg)
 { return 0; }
 static inline void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg) {}
 static inline void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg) {}
+static inline void dwc2_clear_fifo_map(struct dwc2_hsotg *hsotg) {}
 #endif
 
 #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)