usb: dwc3: allocate gadget structure dynamically
authorPeter Chen <peter.chen@nxp.com>
Fri, 21 Aug 2020 02:55:48 +0000 (10:55 +0800)
committerFelipe Balbi <balbi@kernel.org>
Fri, 2 Oct 2020 06:57:42 +0000 (09:57 +0300)
The current code uses commit fac323471df6 ("usb: udc: allow adding
and removing the same gadget device") as the workaround to let
the gadget device is re-used, but it is not allowed from driver
core point. In this commit, we allocate gadget structure dynamically,
and free it at its release function. Since the gadget device's
driver_data has already occupied by usb_composite_dev structure, we have
to use gadget device's platform data to store dwc3 structure.

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Alan Stern <stern@rowland.harvard.edu>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Felipe Balbi <balbi@kernel.org>
drivers/usb/dwc3/core.h
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/dwc3/gadget.h

index 60672f149aaf8a41eb0f586da7daae0c07135636..83b6c871d58d5809ca268f7b821a213b1eba6266 100644 (file)
@@ -1080,7 +1080,7 @@ struct dwc3 {
        struct dwc3_event_buffer *ev_buf;
        struct dwc3_ep          *eps[DWC3_ENDPOINTS_NUM];
 
-       struct usb_gadget       gadget;
+       struct usb_gadget       *gadget;
        struct usb_gadget_driver *gadget_driver;
 
        struct clk_bulk_data    *clks;
index 291482b2ef7e415003f7a29df60892c927cca123..b0363e3ba4d14a18f7c3012e3a2a62542f881d07 100644 (file)
@@ -131,7 +131,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
 
                direction = !dwc->ep0_expect_in;
                dwc->delayed_status = false;
-               usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED);
+               usb_gadget_set_state(dwc->gadget, USB_STATE_CONFIGURED);
 
                if (dwc->ep0state == EP0_STATUS_PHASE)
                        __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
@@ -325,7 +325,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
                /*
                 * LTM will be set once we know how to set this in HW.
                 */
-               usb_status |= dwc->gadget.is_selfpowered;
+               usb_status |= dwc->gadget->is_selfpowered;
 
                if ((dwc->speed == DWC3_DSTS_SUPERSPEED) ||
                    (dwc->speed == DWC3_DSTS_SUPERSPEED_PLUS)) {
@@ -450,7 +450,7 @@ static int dwc3_ep0_handle_device(struct dwc3 *dwc,
 
        wValue = le16_to_cpu(ctrl->wValue);
        wIndex = le16_to_cpu(ctrl->wIndex);
-       state = dwc->gadget.state;
+       state = dwc->gadget->state;
 
        switch (wValue) {
        case USB_DEVICE_REMOTE_WAKEUP:
@@ -564,7 +564,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 
 static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
-       enum usb_device_state state = dwc->gadget.state;
+       enum usb_device_state state = dwc->gadget->state;
        u32 addr;
        u32 reg;
 
@@ -585,9 +585,9 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
        dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
        if (addr)
-               usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS);
+               usb_gadget_set_state(dwc->gadget, USB_STATE_ADDRESS);
        else
-               usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
+               usb_gadget_set_state(dwc->gadget, USB_STATE_DEFAULT);
 
        return 0;
 }
@@ -597,14 +597,14 @@ static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
        int ret;
 
        spin_unlock(&dwc->lock);
-       ret = dwc->gadget_driver->setup(&dwc->gadget, ctrl);
+       ret = dwc->gadget_driver->setup(dwc->gadget, ctrl);
        spin_lock(&dwc->lock);
        return ret;
 }
 
 static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
-       enum usb_device_state state = dwc->gadget.state;
+       enum usb_device_state state = dwc->gadget->state;
        u32 cfg;
        int ret;
        u32 reg;
@@ -627,7 +627,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
                         * to change the state on the next usb_ep_queue()
                         */
                        if (ret == 0)
-                               usb_gadget_set_state(&dwc->gadget,
+                               usb_gadget_set_state(dwc->gadget,
                                                USB_STATE_CONFIGURED);
 
                        /*
@@ -646,7 +646,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
        case USB_STATE_CONFIGURED:
                ret = dwc3_ep0_delegate_req(dwc, ctrl);
                if (!cfg && !ret)
-                       usb_gadget_set_state(&dwc->gadget,
+                       usb_gadget_set_state(dwc->gadget,
                                        USB_STATE_ADDRESS);
                break;
        default:
@@ -702,7 +702,7 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req)
 static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
        struct dwc3_ep  *dep;
-       enum usb_device_state state = dwc->gadget.state;
+       enum usb_device_state state = dwc->gadget->state;
        u16             wLength;
 
        if (state == USB_STATE_DEFAULT)
@@ -746,7 +746,7 @@ static int dwc3_ep0_set_isoch_delay(struct dwc3 *dwc, struct usb_ctrlrequest *ct
        if (wIndex || wLength)
                return -EINVAL;
 
-       dwc->gadget.isoch_delay = wValue;
+       dwc->gadget->isoch_delay = wValue;
 
        return 0;
 }
@@ -1118,7 +1118,7 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
                         */
                        if (!list_empty(&dep->pending_list)) {
                                dwc->delayed_status = false;
-                               usb_gadget_set_state(&dwc->gadget,
+                               usb_gadget_set_state(dwc->gadget,
                                                     USB_STATE_CONFIGURED);
                                dwc3_ep0_do_control_status(dwc, event);
                        }
index 08111b97df048b8df3fdf1394b361c57df9241a5..4c7b6cceeafd43ed3421c4de163bca3a85cd3385 100644 (file)
@@ -291,7 +291,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
         *
         * DWC_usb3 3.30a and DWC_usb31 1.90a programming guide section 3.2.2
         */
-       if (dwc->gadget.speed <= USB_SPEED_HIGH) {
+       if (dwc->gadget->speed <= USB_SPEED_HIGH) {
                reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
                if (unlikely(reg & DWC3_GUSB2PHYCFG_SUSPHY)) {
                        saved_config |= DWC3_GUSB2PHYCFG_SUSPHY;
@@ -423,7 +423,7 @@ static int dwc3_send_clear_stall_ep_cmd(struct dwc3_ep *dep)
         */
        if (dep->direction &&
            !DWC3_VER_IS_PRIOR(DWC3, 260A) &&
-           (dwc->gadget.speed >= USB_SPEED_SUPER))
+           (dwc->gadget->speed >= USB_SPEED_SUPER))
                cmd |= DWC3_DEPCMD_CLEARPENDIN;
 
        memset(&params, 0, sizeof(params));
@@ -563,7 +563,7 @@ static int dwc3_gadget_set_ep_config(struct dwc3_ep *dep, unsigned int action)
                | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc));
 
        /* Burst size is only needed in SuperSpeed mode */
-       if (dwc->gadget.speed >= USB_SPEED_SUPER) {
+       if (dwc->gadget->speed >= USB_SPEED_SUPER) {
                u32 burst = dep->endpoint.maxburst;
 
                params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst - 1);
@@ -950,7 +950,7 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
                unsigned int is_last)
 {
        struct dwc3             *dwc = dep->dwc;
-       struct usb_gadget       *gadget = &dwc->gadget;
+       struct usb_gadget       *gadget = dwc->gadget;
        enum usb_device_speed   speed = gadget->speed;
 
        trb->size = DWC3_TRB_SIZE_LENGTH(length);
@@ -1542,12 +1542,12 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
        if (!dwc->dis_start_transfer_quirk &&
            (DWC3_VER_IS_PRIOR(DWC31, 170A) ||
             DWC3_VER_TYPE_IS_WITHIN(DWC31, 170A, EA01, EA06))) {
-               if (dwc->gadget.speed <= USB_SPEED_HIGH && dep->direction)
+               if (dwc->gadget->speed <= USB_SPEED_HIGH && dep->direction)
                        return dwc3_gadget_start_isoc_quirk(dep);
        }
 
        if (desc->bInterval <= 14 &&
-           dwc->gadget.speed >= USB_SPEED_HIGH) {
+           dwc->gadget->speed >= USB_SPEED_HIGH) {
                u32 frame = __dwc3_gadget_get_frame(dwc);
                bool rollover = frame <
                                (dep->frame_number & DWC3_FRNUMBER_MASK);
@@ -2256,7 +2256,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        spin_lock_irqsave(&dwc->lock, flags);
        if (dwc->gadget_driver) {
                dev_err(dwc->dev, "%s is already bound to %s\n",
-                               dwc->gadget.name,
+                               dwc->gadget->name,
                                dwc->gadget_driver->driver.name);
                ret = -EBUSY;
                goto err1;
@@ -2428,7 +2428,7 @@ static int dwc3_gadget_init_control_endpoint(struct dwc3_ep *dep)
        dep->endpoint.maxburst = 1;
        dep->endpoint.ops = &dwc3_gadget_ep0_ops;
        if (!dep->direction)
-               dwc->gadget.ep0 = &dep->endpoint;
+               dwc->gadget->ep0 = &dep->endpoint;
 
        dep->endpoint.caps.type_control = true;
 
@@ -2474,7 +2474,7 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
        dep->endpoint.max_streams = 15;
        dep->endpoint.ops = &dwc3_gadget_ep_ops;
        list_add_tail(&dep->endpoint.ep_list,
-                       &dwc->gadget.ep_list);
+                       &dwc->gadget->ep_list);
        dep->endpoint.caps.type_iso = true;
        dep->endpoint.caps.type_bulk = true;
        dep->endpoint.caps.type_int = true;
@@ -2523,7 +2523,7 @@ static int dwc3_gadget_init_out_endpoint(struct dwc3_ep *dep)
        dep->endpoint.max_streams = 15;
        dep->endpoint.ops = &dwc3_gadget_ep_ops;
        list_add_tail(&dep->endpoint.ep_list,
-                       &dwc->gadget.ep_list);
+                       &dwc->gadget->ep_list);
        dep->endpoint.caps.type_iso = true;
        dep->endpoint.caps.type_bulk = true;
        dep->endpoint.caps.type_int = true;
@@ -2584,7 +2584,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total)
 {
        u8                              epnum;
 
-       INIT_LIST_HEAD(&dwc->gadget.ep_list);
+       INIT_LIST_HEAD(&dwc->gadget->ep_list);
 
        for (epnum = 0; epnum < total; epnum++) {
                int                     ret;
@@ -3051,7 +3051,7 @@ static void dwc3_disconnect_gadget(struct dwc3 *dwc)
 {
        if (dwc->gadget_driver && dwc->gadget_driver->disconnect) {
                spin_unlock(&dwc->lock);
-               dwc->gadget_driver->disconnect(&dwc->gadget);
+               dwc->gadget_driver->disconnect(dwc->gadget);
                spin_lock(&dwc->lock);
        }
 }
@@ -3060,7 +3060,7 @@ static void dwc3_suspend_gadget(struct dwc3 *dwc)
 {
        if (dwc->gadget_driver && dwc->gadget_driver->suspend) {
                spin_unlock(&dwc->lock);
-               dwc->gadget_driver->suspend(&dwc->gadget);
+               dwc->gadget_driver->suspend(dwc->gadget);
                spin_lock(&dwc->lock);
        }
 }
@@ -3069,7 +3069,7 @@ static void dwc3_resume_gadget(struct dwc3 *dwc)
 {
        if (dwc->gadget_driver && dwc->gadget_driver->resume) {
                spin_unlock(&dwc->lock);
-               dwc->gadget_driver->resume(&dwc->gadget);
+               dwc->gadget_driver->resume(dwc->gadget);
                spin_lock(&dwc->lock);
        }
 }
@@ -3079,9 +3079,9 @@ static void dwc3_reset_gadget(struct dwc3 *dwc)
        if (!dwc->gadget_driver)
                return;
 
-       if (dwc->gadget.speed != USB_SPEED_UNKNOWN) {
+       if (dwc->gadget->speed != USB_SPEED_UNKNOWN) {
                spin_unlock(&dwc->lock);
-               usb_gadget_udc_reset(&dwc->gadget, dwc->gadget_driver);
+               usb_gadget_udc_reset(dwc->gadget, dwc->gadget_driver);
                spin_lock(&dwc->lock);
        }
 }
@@ -3182,9 +3182,9 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
 
        dwc3_disconnect_gadget(dwc);
 
-       dwc->gadget.speed = USB_SPEED_UNKNOWN;
+       dwc->gadget->speed = USB_SPEED_UNKNOWN;
        dwc->setup_packet_pending = false;
-       usb_gadget_set_state(&dwc->gadget, USB_STATE_NOTATTACHED);
+       usb_gadget_set_state(dwc->gadget, USB_STATE_NOTATTACHED);
 
        dwc->connected = false;
 }
@@ -3263,8 +3263,8 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
        switch (speed) {
        case DWC3_DSTS_SUPERSPEED_PLUS:
                dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
-               dwc->gadget.ep0->maxpacket = 512;
-               dwc->gadget.speed = USB_SPEED_SUPER_PLUS;
+               dwc->gadget->ep0->maxpacket = 512;
+               dwc->gadget->speed = USB_SPEED_SUPER_PLUS;
                break;
        case DWC3_DSTS_SUPERSPEED:
                /*
@@ -3284,27 +3284,27 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
                        dwc3_gadget_reset_interrupt(dwc);
 
                dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
-               dwc->gadget.ep0->maxpacket = 512;
-               dwc->gadget.speed = USB_SPEED_SUPER;
+               dwc->gadget->ep0->maxpacket = 512;
+               dwc->gadget->speed = USB_SPEED_SUPER;
                break;
        case DWC3_DSTS_HIGHSPEED:
                dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64);
-               dwc->gadget.ep0->maxpacket = 64;
-               dwc->gadget.speed = USB_SPEED_HIGH;
+               dwc->gadget->ep0->maxpacket = 64;
+               dwc->gadget->speed = USB_SPEED_HIGH;
                break;
        case DWC3_DSTS_FULLSPEED:
                dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64);
-               dwc->gadget.ep0->maxpacket = 64;
-               dwc->gadget.speed = USB_SPEED_FULL;
+               dwc->gadget->ep0->maxpacket = 64;
+               dwc->gadget->speed = USB_SPEED_FULL;
                break;
        case DWC3_DSTS_LOWSPEED:
                dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(8);
-               dwc->gadget.ep0->maxpacket = 8;
-               dwc->gadget.speed = USB_SPEED_LOW;
+               dwc->gadget->ep0->maxpacket = 8;
+               dwc->gadget->speed = USB_SPEED_LOW;
                break;
        }
 
-       dwc->eps[1]->endpoint.maxpacket = dwc->gadget.ep0->maxpacket;
+       dwc->eps[1]->endpoint.maxpacket = dwc->gadget->ep0->maxpacket;
 
        /* Enable USB2 LPM Capability */
 
@@ -3372,7 +3372,7 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc)
 
        if (dwc->gadget_driver && dwc->gadget_driver->resume) {
                spin_unlock(&dwc->lock);
-               dwc->gadget_driver->resume(&dwc->gadget);
+               dwc->gadget_driver->resume(dwc->gadget);
                spin_lock(&dwc->lock);
        }
 }
@@ -3543,7 +3543,7 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc,
                         * Ignore suspend event until the gadget enters into
                         * USB_STATE_CONFIGURED state.
                         */
-                       if (dwc->gadget.state >= USB_STATE_CONFIGURED)
+                       if (dwc->gadget->state >= USB_STATE_CONFIGURED)
                                dwc3_gadget_suspend_interrupt(dwc,
                                                event->event_info);
                }
@@ -3718,6 +3718,13 @@ out:
        return irq;
 }
 
+static void dwc_gadget_release(struct device *dev)
+{
+       struct usb_gadget *gadget = container_of(dev, struct usb_gadget, dev);
+
+       kfree(gadget);
+}
+
 /**
  * dwc3_gadget_init - initializes gadget related registers
  * @dwc: pointer to our controller context structure
@@ -3728,6 +3735,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 {
        int ret;
        int irq;
+       struct device *dev;
 
        irq = dwc3_gadget_get_irq(dwc);
        if (irq < 0) {
@@ -3760,12 +3768,21 @@ int dwc3_gadget_init(struct dwc3 *dwc)
        }
 
        init_completion(&dwc->ep0_in_setup);
+       dwc->gadget = kzalloc(sizeof(struct usb_gadget), GFP_KERNEL);
+       if (!dwc->gadget) {
+               ret = -ENOMEM;
+               goto err3;
+       }
 
-       dwc->gadget.ops                 = &dwc3_gadget_ops;
-       dwc->gadget.speed               = USB_SPEED_UNKNOWN;
-       dwc->gadget.sg_supported        = true;
-       dwc->gadget.name                = "dwc3-gadget";
-       dwc->gadget.lpm_capable         = true;
+
+       usb_initialize_gadget(dwc->dev, dwc->gadget, dwc_gadget_release);
+       dev                             = &dwc->gadget->dev;
+       dev->platform_data              = dwc;
+       dwc->gadget->ops                = &dwc3_gadget_ops;
+       dwc->gadget->speed              = USB_SPEED_UNKNOWN;
+       dwc->gadget->sg_supported       = true;
+       dwc->gadget->name               = "dwc3-gadget";
+       dwc->gadget->lpm_capable        = true;
 
        /*
         * FIXME We might be setting max_speed to <SUPER, however versions
@@ -3788,7 +3805,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
                dev_info(dwc->dev, "changing max_speed on rev %08x\n",
                                dwc->revision);
 
-       dwc->gadget.max_speed           = dwc->maximum_speed;
+       dwc->gadget->max_speed          = dwc->maximum_speed;
 
        /*
         * REVISIT: Here we should clear all pending IRQs to be
@@ -3797,21 +3814,22 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 
        ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps);
        if (ret)
-               goto err3;
+               goto err4;
 
-       ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
+       ret = usb_add_gadget(dwc->gadget);
        if (ret) {
-               dev_err(dwc->dev, "failed to register udc\n");
-               goto err4;
+               dev_err(dwc->dev, "failed to add gadget\n");
+               goto err5;
        }
 
-       dwc3_gadget_set_speed(&dwc->gadget, dwc->maximum_speed);
+       dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed);
 
        return 0;
 
-err4:
+err5:
        dwc3_gadget_free_endpoints(dwc);
-
+err4:
+       usb_put_gadget(dwc->gadget);
 err3:
        dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce,
                        dwc->bounce_addr);
@@ -3831,7 +3849,7 @@ err0:
 
 void dwc3_gadget_exit(struct dwc3 *dwc)
 {
-       usb_del_gadget_udc(&dwc->gadget);
+       usb_del_gadget_udc(dwc->gadget);
        dwc3_gadget_free_endpoints(dwc);
        dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce,
                          dwc->bounce_addr);
index a7791cb827c497d3f1ddbb9093c99af6aba5d935..0cd28194997017a98cd00fe16bae54713cc0f186 100644 (file)
@@ -17,7 +17,7 @@
 
 struct dwc3;
 #define to_dwc3_ep(ep)         (container_of(ep, struct dwc3_ep, endpoint))
-#define gadget_to_dwc(g)       (container_of(g, struct dwc3, gadget))
+#define gadget_to_dwc(g)       (dev_get_platdata(&g->dev))
 
 /* DEPCFG parameter 1 */
 #define DWC3_DEPCFG_INT_NUM(n)         (((n) & 0x1f) << 0)