]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge tag 'usb-for-v3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 May 2014 02:28:21 +0000 (11:28 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 May 2014 02:28:21 +0000 (11:28 +0900)
Felipe writes:

usb: patches for v3.16 merge window

Not a lot here during this merge window. Mostly we just have
the usual miscellaneous patches (removal of unnecessary prints,
proper dependencies being added to Kconfig, build warning fixes,
new device ID, etc.

Other than those, the only important new features are the
new support for OS Strings which should help Linux Gadget
Drivers behave better under MS Windows. Also Babble Recovery
implementation for MUSB on AM335x. Lastly, we also have
ARCH_QCOM PHY support though phy-msm.

Signed-of-by: Felipe Balbi <balbi@ti.com>
Conflicts:
drivers/usb/phy/phy-mv-u3d-usb.c

1  2 
drivers/usb/dwc3/core.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/f_rndis.c
drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/rndis.c
drivers/usb/gadget/u_ether.c
drivers/usb/musb/musb_dsps.c
drivers/usb/phy/Kconfig

diff --combined drivers/usb/dwc3/core.c
index 10aaaae9af25e8f6b797f063b5e5ba64ec37c847,3f59c124782515b37e04bf4d0b1275e72d29d957..eb69eb9f06c8f580c70cc2dd2ee62f7870782492
@@@ -486,70 -486,20 +486,20 @@@ static void dwc3_core_exit(struct dwc3 
        phy_exit(dwc->usb3_generic_phy);
  }
  
- #define DWC3_ALIGN_MASK               (16 - 1)
- static int dwc3_probe(struct platform_device *pdev)
+ static int dwc3_core_get_phy(struct dwc3 *dwc)
  {
-       struct device           *dev = &pdev->dev;
-       struct dwc3_platform_data *pdata = dev_get_platdata(dev);
+       struct device           *dev = dwc->dev;
        struct device_node      *node = dev->of_node;
-       struct resource         *res;
-       struct dwc3             *dwc;
-       int                     ret = -ENOMEM;
-       void __iomem            *regs;
-       void                    *mem;
-       mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
-       if (!mem) {
-               dev_err(dev, "not enough memory\n");
-               return -ENOMEM;
-       }
-       dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
-       dwc->mem = mem;
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res) {
-               dev_err(dev, "missing IRQ\n");
-               return -ENODEV;
-       }
-       dwc->xhci_resources[1].start = res->start;
-       dwc->xhci_resources[1].end = res->end;
-       dwc->xhci_resources[1].flags = res->flags;
-       dwc->xhci_resources[1].name = res->name;
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "missing memory resource\n");
-               return -ENODEV;
-       }
+       int ret;
  
        if (node) {
-               dwc->maximum_speed = of_usb_get_maximum_speed(node);
                dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
                dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
-               dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
-               dwc->dr_mode = of_usb_get_dr_mode(node);
-       } else if (pdata) {
-               dwc->maximum_speed = pdata->maximum_speed;
-               dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
-               dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
-               dwc->needs_fifo_resize = pdata->tx_fifo_resize;
-               dwc->dr_mode = pdata->dr_mode;
        } else {
                dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
                dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
        }
  
-       /* default to superspeed if no maximum_speed passed */
-       if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
-               dwc->maximum_speed = USB_SPEED_SUPER;
        if (IS_ERR(dwc->usb2_phy)) {
                ret = PTR_ERR(dwc->usb2_phy);
                if (ret == -ENXIO || ret == -ENODEV) {
                }
        }
  
+       return 0;
+ }
+ static int dwc3_core_init_mode(struct dwc3 *dwc)
+ {
+       struct device *dev = dwc->dev;
+       int ret;
+       switch (dwc->dr_mode) {
+       case USB_DR_MODE_PERIPHERAL:
+               dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
+               ret = dwc3_gadget_init(dwc);
+               if (ret) {
+                       dev_err(dev, "failed to initialize gadget\n");
+                       return ret;
+               }
+               break;
+       case USB_DR_MODE_HOST:
+               dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
+               ret = dwc3_host_init(dwc);
+               if (ret) {
+                       dev_err(dev, "failed to initialize host\n");
+                       return ret;
+               }
+               break;
+       case USB_DR_MODE_OTG:
+               dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
+               ret = dwc3_host_init(dwc);
+               if (ret) {
+                       dev_err(dev, "failed to initialize host\n");
+                       return ret;
+               }
+               ret = dwc3_gadget_init(dwc);
+               if (ret) {
+                       dev_err(dev, "failed to initialize gadget\n");
+                       return ret;
+               }
+               break;
+       default:
+               dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
+               return -EINVAL;
+       }
+       return 0;
+ }
+ static void dwc3_core_exit_mode(struct dwc3 *dwc)
+ {
+       switch (dwc->dr_mode) {
+       case USB_DR_MODE_PERIPHERAL:
+               dwc3_gadget_exit(dwc);
+               break;
+       case USB_DR_MODE_HOST:
+               dwc3_host_exit(dwc);
+               break;
+       case USB_DR_MODE_OTG:
+               dwc3_host_exit(dwc);
+               dwc3_gadget_exit(dwc);
+               break;
+       default:
+               /* do nothing */
+               break;
+       }
+ }
+ #define DWC3_ALIGN_MASK               (16 - 1)
+ static int dwc3_probe(struct platform_device *pdev)
+ {
+       struct device           *dev = &pdev->dev;
+       struct dwc3_platform_data *pdata = dev_get_platdata(dev);
+       struct device_node      *node = dev->of_node;
+       struct resource         *res;
+       struct dwc3             *dwc;
+       int                     ret;
+       void __iomem            *regs;
+       void                    *mem;
+       mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
+       if (!mem) {
+               dev_err(dev, "not enough memory\n");
+               return -ENOMEM;
+       }
+       dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
+       dwc->mem = mem;
+       dwc->dev = dev;
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res) {
+               dev_err(dev, "missing IRQ\n");
+               return -ENODEV;
+       }
+       dwc->xhci_resources[1].start = res->start;
+       dwc->xhci_resources[1].end = res->end;
+       dwc->xhci_resources[1].flags = res->flags;
+       dwc->xhci_resources[1].name = res->name;
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(dev, "missing memory resource\n");
+               return -ENODEV;
+       }
+       if (node) {
+               dwc->maximum_speed = of_usb_get_maximum_speed(node);
+               dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
+               dwc->dr_mode = of_usb_get_dr_mode(node);
+       } else if (pdata) {
+               dwc->maximum_speed = pdata->maximum_speed;
+               dwc->needs_fifo_resize = pdata->tx_fifo_resize;
+               dwc->dr_mode = pdata->dr_mode;
+       }
+       /* default to superspeed if no maximum_speed passed */
+       if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
+               dwc->maximum_speed = USB_SPEED_SUPER;
+       ret = dwc3_core_get_phy(dwc);
+       if (ret)
+               return ret;
        dwc->xhci_resources[0].start = res->start;
        dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
                                        DWC3_XHCI_REGS_END;
  
        dwc->regs       = regs;
        dwc->regs_size  = resource_size(res);
-       dwc->dev        = dev;
  
        dev->dma_mask   = dev->parent->dma_mask;
        dev->dma_parms  = dev->parent->dma_parms;
                goto err_usb3phy_power;
        }
  
-       switch (dwc->dr_mode) {
-       case USB_DR_MODE_PERIPHERAL:
-               dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
-               ret = dwc3_gadget_init(dwc);
-               if (ret) {
-                       dev_err(dev, "failed to initialize gadget\n");
-                       goto err2;
-               }
-               break;
-       case USB_DR_MODE_HOST:
-               dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
-               ret = dwc3_host_init(dwc);
-               if (ret) {
-                       dev_err(dev, "failed to initialize host\n");
-                       goto err2;
-               }
-               break;
-       case USB_DR_MODE_OTG:
-               dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
-               ret = dwc3_host_init(dwc);
-               if (ret) {
-                       dev_err(dev, "failed to initialize host\n");
-                       goto err2;
-               }
-               ret = dwc3_gadget_init(dwc);
-               if (ret) {
-                       dev_err(dev, "failed to initialize gadget\n");
-                       goto err2;
-               }
-               break;
-       default:
-               dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
+       ret = dwc3_core_init_mode(dwc);
+       if (ret)
                goto err2;
-       }
  
        ret = dwc3_debugfs_init(dwc);
        if (ret) {
        return 0;
  
  err3:
-       switch (dwc->dr_mode) {
-       case USB_DR_MODE_PERIPHERAL:
-               dwc3_gadget_exit(dwc);
-               break;
-       case USB_DR_MODE_HOST:
-               dwc3_host_exit(dwc);
-               break;
-       case USB_DR_MODE_OTG:
-               dwc3_host_exit(dwc);
-               dwc3_gadget_exit(dwc);
-               break;
-       default:
-               /* do nothing */
-               break;
-       }
+       dwc3_core_exit_mode(dwc);
  
  err2:
        dwc3_event_buffers_cleanup(dwc);
@@@ -766,23 -795,7 +795,7 @@@ static int dwc3_remove(struct platform_
        pm_runtime_disable(&pdev->dev);
  
        dwc3_debugfs_exit(dwc);
-       switch (dwc->dr_mode) {
-       case USB_DR_MODE_PERIPHERAL:
-               dwc3_gadget_exit(dwc);
-               break;
-       case USB_DR_MODE_HOST:
-               dwc3_host_exit(dwc);
-               break;
-       case USB_DR_MODE_OTG:
-               dwc3_host_exit(dwc);
-               dwc3_gadget_exit(dwc);
-               break;
-       default:
-               /* do nothing */
-               break;
-       }
+       dwc3_core_exit_mode(dwc);
        dwc3_event_buffers_cleanup(dwc);
        dwc3_free_event_buffers(dwc);
        dwc3_core_exit(dwc);
@@@ -821,7 -834,6 +834,7 @@@ static void dwc3_complete(struct devic
  
        spin_lock_irqsave(&dwc->lock, flags);
  
 +      dwc3_event_buffers_setup(dwc);
        switch (dwc->dr_mode) {
        case USB_DR_MODE_PERIPHERAL:
        case USB_DR_MODE_OTG:
                /* FALLTHROUGH */
        case USB_DR_MODE_HOST:
        default:
 -              dwc3_event_buffers_setup(dwc);
                break;
        }
  
index 70715eeededda3b4acfab6bff72f13531338a8b2,696b472274ef97ae3d4851a7be589bd2415ac436..9d64dd02c57eabf33b8fecd692ccd75368edcea7
@@@ -187,12 -187,15 +187,12 @@@ int dwc3_gadget_resize_tx_fifos(struct 
         * improve this algorithm so that we better use the internal
         * FIFO space
         */
 -      for (num = 0; num < DWC3_ENDPOINTS_NUM; num++) {
 -              struct dwc3_ep  *dep = dwc->eps[num];
 -              int             fifo_number = dep->number >> 1;
 +      for (num = 0; num < dwc->num_in_eps; num++) {
 +              /* bit0 indicates direction; 1 means IN ep */
 +              struct dwc3_ep  *dep = dwc->eps[(num << 1) | 1];
                int             mult = 1;
                int             tmp;
  
 -              if (!(dep->number & 1))
 -                      continue;
 -
                if (!(dep->flags & DWC3_EP_ENABLED))
                        continue;
  
                dev_vdbg(dwc->dev, "%s: Fifo Addr %04x Size %d\n",
                                dep->name, last_fifo_depth, fifo_size & 0xffff);
  
 -              dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(fifo_number),
 -                              fifo_size);
 +              dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num), fifo_size);
  
                last_fifo_depth += (fifo_size & 0xffff);
        }
@@@ -298,11 -302,76 +298,76 @@@ static const char *dwc3_gadget_ep_cmd_s
        }
  }
  
+ static const char *dwc3_gadget_generic_cmd_string(u8 cmd)
+ {
+       switch (cmd) {
+       case DWC3_DGCMD_SET_LMP:
+               return "Set LMP";
+       case DWC3_DGCMD_SET_PERIODIC_PAR:
+               return "Set Periodic Parameters";
+       case DWC3_DGCMD_XMIT_FUNCTION:
+               return "Transmit Function Wake Device Notification";
+       case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO:
+               return "Set Scratchpad Buffer Array Address Lo";
+       case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI:
+               return "Set Scratchpad Buffer Array Address Hi";
+       case DWC3_DGCMD_SELECTED_FIFO_FLUSH:
+               return "Selected FIFO Flush";
+       case DWC3_DGCMD_ALL_FIFO_FLUSH:
+               return "All FIFO Flush";
+       case DWC3_DGCMD_SET_ENDPOINT_NRDY:
+               return "Set Endpoint NRDY";
+       case DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK:
+               return "Run SoC Bus Loopback Test";
+       default:
+               return "UNKNOWN";
+       }
+ }
+ static const char *dwc3_gadget_link_string(enum dwc3_link_state link_state)
+ {
+       switch (link_state) {
+       case DWC3_LINK_STATE_U0:
+               return "U0";
+       case DWC3_LINK_STATE_U1:
+               return "U1";
+       case DWC3_LINK_STATE_U2:
+               return "U2";
+       case DWC3_LINK_STATE_U3:
+               return "U3";
+       case DWC3_LINK_STATE_SS_DIS:
+               return "SS.Disabled";
+       case DWC3_LINK_STATE_RX_DET:
+               return "RX.Detect";
+       case DWC3_LINK_STATE_SS_INACT:
+               return "SS.Inactive";
+       case DWC3_LINK_STATE_POLL:
+               return "Polling";
+       case DWC3_LINK_STATE_RECOV:
+               return "Recovery";
+       case DWC3_LINK_STATE_HRESET:
+               return "Hot Reset";
+       case DWC3_LINK_STATE_CMPLY:
+               return "Compliance";
+       case DWC3_LINK_STATE_LPBK:
+               return "Loopback";
+       case DWC3_LINK_STATE_RESET:
+               return "Reset";
+       case DWC3_LINK_STATE_RESUME:
+               return "Resume";
+       default:
+               return "UNKNOWN link state\n";
+       }
+ }
  int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param)
  {
        u32             timeout = 500;
        u32             reg;
  
+       dev_vdbg(dwc->dev, "generic cmd '%s' [%d] param %08x\n",
+                       dwc3_gadget_generic_cmd_string(cmd), cmd, param);
        dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param);
        dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT);
  
@@@ -332,9 -401,9 +397,9 @@@ int dwc3_send_gadget_ep_cmd(struct dwc
        u32                     timeout = 500;
        u32                     reg;
  
-       dev_vdbg(dwc->dev, "%s: cmd '%s' params %08x %08x %08x\n",
+       dev_vdbg(dwc->dev, "%s: cmd '%s' [%d] params %08x %08x %08x\n",
                        dep->name,
-                       dwc3_gadget_ep_cmd_string(cmd), params->param0,
+                       dwc3_gadget_ep_cmd_string(cmd), cmd, params->param0,
                        params->param1, params->param2);
  
        dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0);
@@@ -515,7 -584,7 +580,7 @@@ static int __dwc3_gadget_ep_enable(stru
  {
        struct dwc3             *dwc = dep->dwc;
        u32                     reg;
-       int                     ret = -ENOMEM;
+       int                     ret;
  
        dev_vdbg(dwc->dev, "Enabling %s\n", dep->name);
  
@@@ -604,6 -673,10 +669,10 @@@ static int __dwc3_gadget_ep_disable(str
  
        dwc3_remove_requests(dwc, dep);
  
+       /* make sure HW endpoint isn't stalled */
+       if (dep->flags & DWC3_EP_STALL)
+               __dwc3_gadget_ep_set_halt(dep, 0);
        reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
        reg &= ~DWC3_DALEPENA_EP(dep->number);
        dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
@@@ -2441,8 -2514,6 +2510,6 @@@ static void dwc3_gadget_linksts_change_
                }
        }
  
-       dwc->link_state = next;
        switch (next) {
        case DWC3_LINK_STATE_U1:
                if (dwc->speed == USB_SPEED_SUPER)
                break;
        }
  
-       dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state);
+       dev_vdbg(dwc->dev, "link change: %s [%d] -> %s [%d]\n",
+                       dwc3_gadget_link_string(dwc->link_state),
+                       dwc->link_state, dwc3_gadget_link_string(next), next);
+       dwc->link_state = next;
  }
  
  static void dwc3_gadget_hibernation_interrupt(struct dwc3 *dwc,
index 1e12b3ee56fd837117a03266cf66205bb418b366,38641ea820a803eaafa903034351c77dcb994f96..74202d67f91166b0d0ef0fc49ab387602260ad12
  #include <linux/poll.h>
  
  #include "u_fs.h"
+ #include "u_f.h"
  #include "configfs.h"
  
  #define FUNCTIONFS_MAGIC      0xa647361 /* Chosen by a honest dice roll ;) */
  
- /* Variable Length Array Macros **********************************************/
- #define vla_group(groupname) size_t groupname##__next = 0
- #define vla_group_size(groupname) groupname##__next
- #define vla_item(groupname, type, name, n) \
-       size_t groupname##_##name##__offset = ({                               \
-               size_t align_mask = __alignof__(type) - 1;                     \
-               size_t offset = (groupname##__next + align_mask) & ~align_mask;\
-               size_t size = (n) * sizeof(type);                              \
-               groupname##__next = offset + size;                             \
-               offset;                                                        \
-       })
- #define vla_item_with_sz(groupname, type, name, n) \
-       size_t groupname##_##name##__sz = (n) * sizeof(type);                  \
-       size_t groupname##_##name##__offset = ({                               \
-               size_t align_mask = __alignof__(type) - 1;                     \
-               size_t offset = (groupname##__next + align_mask) & ~align_mask;\
-               size_t size = groupname##_##name##__sz;                        \
-               groupname##__next = offset + size;                             \
-               offset;                                                        \
-       })
- #define vla_ptr(ptr, groupname, name) \
-       ((void *) ((char *)ptr + groupname##_##name##__offset))
  /* Reference counter handling */
  static void ffs_data_get(struct ffs_data *ffs);
  static void ffs_data_put(struct ffs_data *ffs);
@@@ -190,7 -165,7 +165,7 @@@ ffs_sb_create_file(struct super_block *
  /* Devices management *******************************************************/
  
  DEFINE_MUTEX(ffs_lock);
- EXPORT_SYMBOL(ffs_lock);
+ EXPORT_SYMBOL_GPL(ffs_lock);
  
  static struct ffs_dev *_ffs_find_dev(const char *name);
  static struct ffs_dev *_ffs_alloc_dev(void);
@@@ -745,12 -720,6 +720,12 @@@ static ssize_t ffs_epfile_io(struct fil
                 */
                struct usb_gadget *gadget = epfile->ffs->gadget;
  
 +              spin_lock_irq(&epfile->ffs->eps_lock);
 +              /* In the meantime, endpoint got disabled or changed. */
 +              if (epfile->ep != ep) {
 +                      spin_unlock_irq(&epfile->ffs->eps_lock);
 +                      return -ESHUTDOWN;
 +              }
                /*
                 * Controller may require buffer size to be aligned to
                 * maxpacketsize of an out endpoint.
                data_len = io_data->read ?
                           usb_ep_align_maybe(gadget, ep->ep, io_data->len) :
                           io_data->len;
 +              spin_unlock_irq(&epfile->ffs->eps_lock);
  
                data = kmalloc(data_len, GFP_KERNEL);
                if (unlikely(!data))
@@@ -2883,7 -2851,7 +2858,7 @@@ int ffs_name_dev(struct ffs_dev *dev, c
  
        return ret;
  }
- EXPORT_SYMBOL(ffs_name_dev);
+ EXPORT_SYMBOL_GPL(ffs_name_dev);
  
  int ffs_single_dev(struct ffs_dev *dev)
  {
        ffs_dev_unlock();
        return ret;
  }
- EXPORT_SYMBOL(ffs_single_dev);
+ EXPORT_SYMBOL_GPL(ffs_single_dev);
  
  /*
   * ffs_lock must be taken by the caller of this function
index 9a4f49dc6ac4f879cfac9496c49951b21c18fe71,f1bf5763eac425bfe5829489956d74b8b978491d..eed3ad8780478e23bcaf07402d1f658914d1d484
@@@ -27,6 -27,7 +27,7 @@@
  #include "u_ether_configfs.h"
  #include "u_rndis.h"
  #include "rndis.h"
+ #include "configfs.h"
  
  /*
   * This function is an RNDIS Ethernet port -- a Microsoft protocol that's
@@@ -377,7 -378,7 +378,7 @@@ static struct sk_buff *rndis_add_header
        if (skb2)
                rndis_add_hdr(skb2);
  
 -      dev_kfree_skb_any(skb);
 +      dev_kfree_skb(skb);
        return skb2;
  }
  
@@@ -682,6 -683,15 +683,15 @@@ rndis_bind(struct usb_configuration *c
  
        rndis_opts = container_of(f->fi, struct f_rndis_opts, func_inst);
  
+       if (cdev->use_os_string) {
+               f->os_desc_table = kzalloc(sizeof(*f->os_desc_table),
+                                          GFP_KERNEL);
+               if (!f->os_desc_table)
+                       return PTR_ERR(f->os_desc_table);
+               f->os_desc_n = 1;
+               f->os_desc_table[0].os_desc = &rndis_opts->rndis_os_desc;
+       }
        /*
         * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
         * configurations are bound in sequence with list_for_each_entry,
                gether_set_gadget(rndis_opts->net, cdev->gadget);
                status = gether_register_netdev(rndis_opts->net);
                if (status)
-                       return status;
+                       goto fail;
                rndis_opts->bound = true;
        }
  
        us = usb_gstrings_attach(cdev, rndis_strings,
                                 ARRAY_SIZE(rndis_string_defs));
-       if (IS_ERR(us))
-               return PTR_ERR(us);
+       if (IS_ERR(us)) {
+               status = PTR_ERR(us);
+               goto fail;
+       }
        rndis_control_intf.iInterface = us[0].id;
        rndis_data_intf.iInterface = us[1].id;
        rndis_iad_descriptor.iFunction = us[2].id;
        return 0;
  
  fail:
+       kfree(f->os_desc_table);
+       f->os_desc_n = 0;
        usb_free_all_descriptors(f);
  
        if (rndis->notify_req) {
@@@ -834,7 -848,7 +848,7 @@@ void rndis_borrow_net(struct usb_functi
        opts->borrowed_net = opts->bound = true;
        opts->net = net;
  }
- EXPORT_SYMBOL(rndis_borrow_net);
+ EXPORT_SYMBOL_GPL(rndis_borrow_net);
  
  static inline struct f_rndis_opts *to_f_rndis_opts(struct config_item *item)
  {
@@@ -882,16 -896,21 +896,21 @@@ static void rndis_free_inst(struct usb_
                else
                        free_netdev(opts->net);
        }
+       kfree(opts->rndis_os_desc.group.default_groups); /* single VLA chunk */
        kfree(opts);
  }
  
  static struct usb_function_instance *rndis_alloc_inst(void)
  {
        struct f_rndis_opts *opts;
+       struct usb_os_desc *descs[1];
  
        opts = kzalloc(sizeof(*opts), GFP_KERNEL);
        if (!opts)
                return ERR_PTR(-ENOMEM);
+       opts->rndis_os_desc.ext_compat_id = opts->rndis_ext_compat_id;
        mutex_init(&opts->lock);
        opts->func_inst.free_func_inst = rndis_free_inst;
        opts->net = gether_setup_default();
                kfree(opts);
                return ERR_CAST(net);
        }
+       INIT_LIST_HEAD(&opts->rndis_os_desc.ext_prop);
  
+       descs[0] = &opts->rndis_os_desc;
+       usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs,
+                                      THIS_MODULE);
        config_group_init_type_name(&opts->func_inst.group, "",
                                    &rndis_func_type);
  
@@@ -925,6 -948,8 +948,8 @@@ static void rndis_unbind(struct usb_con
  {
        struct f_rndis          *rndis = func_to_rndis(f);
  
+       kfree(f->os_desc_table);
+       f->os_desc_n = 0;
        usb_free_all_descriptors(f);
  
        kfree(rndis->notify_req->buf);
index a2f26cdb56fef07a0a15e8bb329c089413efab6a,68843f081377f884ff4f2d426c8518d39e0990cf..28e4fc957026746f25bb605cec0d54387e00d570
@@@ -1219,10 -1219,6 +1219,10 @@@ static int fsl_pullup(struct usb_gadge
        struct fsl_udc *udc;
  
        udc = container_of(gadget, struct fsl_udc, gadget);
 +
 +      if (!udc->vbus_active)
 +              return -EOPNOTSUPP;
 +
        udc->softconnect = (is_on != 0);
        if (can_pullup(udc))
                fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
@@@ -2256,10 -2252,8 +2256,8 @@@ static int __init struct_udc_setup(stru
        udc->phy_mode = pdata->phy_mode;
  
        udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
-       if (!udc->eps) {
-               ERR("malloc fsl_ep failed\n");
+       if (!udc->eps)
                return -1;
-       }
  
        /* initialized QHs, take care of alignment */
        size = udc->max_ep * sizeof(struct ep_queue_head);
@@@ -2342,10 -2336,8 +2340,8 @@@ static int __init fsl_udc_probe(struct 
        u32 dccparams;
  
        udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
-       if (udc_controller == NULL) {
-               ERR("malloc udc failed\n");
+       if (udc_controller == NULL)
                return -ENOMEM;
-       }
  
        pdata = dev_get_platdata(&pdev->dev);
        udc_controller->pdata = pdata;
@@@ -2536,8 -2528,8 +2532,8 @@@ static int __exit fsl_udc_remove(struc
        if (!udc_controller)
                return -ENODEV;
  
 -      usb_del_gadget_udc(&udc_controller->gadget);
        udc_controller->done = &done;
 +      usb_del_gadget_udc(&udc_controller->gadget);
  
        fsl_udc_clk_release();
  
index a925d0cbcd4199d777071408f8e335119932b3ab,09e21517377c067c932ce4b46287c98d84039ab6..5b840fb0cce52fd90490be3471b471c392cc7b7f
@@@ -1494,6 -1494,7 +1494,7 @@@ gadgetfs_setup (struct usb_gadget *gadg
                 */
                if (value == 0) {
                        INFO (dev, "configuration #%d\n", dev->current_config);
+                       usb_gadget_set_state(gadget, USB_STATE_CONFIGURED);
                        if (dev->usermode_setup) {
                                dev->setup_can_stall = 0;
                                goto delegate;
@@@ -2043,7 -2044,6 +2044,7 @@@ gadgetfs_fill_super (struct super_bloc
                return -ESRCH;
  
        /* fake probe to determine $CHIP */
 +      CHIP = NULL;
        usb_gadget_probe_driver(&probe_driver);
        if (!CHIP)
                return -ENODEV;
index 7ed452d90f4d76c9d48c2bb3c2f55a8d40a0f5e9,4c36694a01326a5eb3ad6889bdd11ee7c9ff7f8c..95d2324f69778faf8d7cf8fbd64f553f6f8b4105
@@@ -35,7 -35,6 +35,7 @@@
  #include <asm/byteorder.h>
  #include <asm/unaligned.h>
  
 +#include "u_rndis.h"
  
  #undef        VERBOSE_DEBUG
  
@@@ -761,7 -760,7 +761,7 @@@ int rndis_signal_connect(int configNr
        return rndis_indicate_status_msg(configNr,
                                          RNDIS_STATUS_MEDIA_CONNECT);
  }
- EXPORT_SYMBOL(rndis_signal_connect);
+ EXPORT_SYMBOL_GPL(rndis_signal_connect);
  
  int rndis_signal_disconnect(int configNr)
  {
        return rndis_indicate_status_msg(configNr,
                                          RNDIS_STATUS_MEDIA_DISCONNECT);
  }
- EXPORT_SYMBOL(rndis_signal_disconnect);
+ EXPORT_SYMBOL_GPL(rndis_signal_disconnect);
  
  void rndis_uninit(int configNr)
  {
        while ((buf = rndis_get_next_response(configNr, &length)))
                rndis_free_response(configNr, buf);
  }
- EXPORT_SYMBOL(rndis_uninit);
+ EXPORT_SYMBOL_GPL(rndis_uninit);
  
  void rndis_set_host_mac(int configNr, const u8 *addr)
  {
        rndis_per_dev_params[configNr].host_mac = addr;
  }
- EXPORT_SYMBOL(rndis_set_host_mac);
+ EXPORT_SYMBOL_GPL(rndis_set_host_mac);
  
  /*
   * Message Parser
@@@ -874,7 -873,7 +874,7 @@@ int rndis_msg_parser(u8 configNr, u8 *b
  
        return -ENOTSUPP;
  }
- EXPORT_SYMBOL(rndis_msg_parser);
+ EXPORT_SYMBOL_GPL(rndis_msg_parser);
  
  int rndis_register(void (*resp_avail)(void *v), void *v)
  {
  
        return -ENODEV;
  }
- EXPORT_SYMBOL(rndis_register);
+ EXPORT_SYMBOL_GPL(rndis_register);
  
  void rndis_deregister(int configNr)
  {
        if (configNr >= RNDIS_MAX_CONFIGS) return;
        rndis_per_dev_params[configNr].used = 0;
  }
- EXPORT_SYMBOL(rndis_deregister);
+ EXPORT_SYMBOL_GPL(rndis_deregister);
  
  int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
  {
  
        return 0;
  }
- EXPORT_SYMBOL(rndis_set_param_dev);
+ EXPORT_SYMBOL_GPL(rndis_set_param_dev);
  
  int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
  {
  
        return 0;
  }
- EXPORT_SYMBOL(rndis_set_param_vendor);
+ EXPORT_SYMBOL_GPL(rndis_set_param_vendor);
  
  int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
  {
  
        return 0;
  }
- EXPORT_SYMBOL(rndis_set_param_medium);
+ EXPORT_SYMBOL_GPL(rndis_set_param_medium);
  
  void rndis_add_hdr(struct sk_buff *skb)
  {
        header->DataOffset = cpu_to_le32(36);
        header->DataLength = cpu_to_le32(skb->len - sizeof(*header));
  }
- EXPORT_SYMBOL(rndis_add_hdr);
+ EXPORT_SYMBOL_GPL(rndis_add_hdr);
  
  void rndis_free_response(int configNr, u8 *buf)
  {
                }
        }
  }
- EXPORT_SYMBOL(rndis_free_response);
+ EXPORT_SYMBOL_GPL(rndis_free_response);
  
  u8 *rndis_get_next_response(int configNr, u32 *length)
  {
  
        return NULL;
  }
- EXPORT_SYMBOL(rndis_get_next_response);
+ EXPORT_SYMBOL_GPL(rndis_get_next_response);
  
  static rndis_resp_t *rndis_add_response(int configNr, u32 length)
  {
@@@ -1042,7 -1041,7 +1042,7 @@@ int rndis_rm_hdr(struct gether *port
        skb_queue_tail(list, skb);
        return 0;
  }
- EXPORT_SYMBOL(rndis_rm_hdr);
+ EXPORT_SYMBOL_GPL(rndis_rm_hdr);
  
  #ifdef CONFIG_USB_GADGET_DEBUG_FILES
  
index b7d4f82872b700e14d4fc2469bcc1f936a94bf61,216bbd1c871e935418bc2bb128c553b5e4c17ec4..fe0880d0873e04c973c1db5699c947b9ffc1d69a
@@@ -48,6 -48,8 +48,6 @@@
  
  #define UETH__VERSION "29-May-2008"
  
 -#define GETHER_NAPI_WEIGHT    32
 -
  struct eth_dev {
        /* lock is held while accessing port_usb
         */
@@@ -72,6 -74,7 +72,6 @@@
                                                struct sk_buff_head *list);
  
        struct work_struct      work;
 -      struct napi_struct      rx_napi;
  
        unsigned long           todo;
  #define       WORK_RX_MEMORY          0
@@@ -253,18 -256,16 +253,18 @@@ enomem
                DBG(dev, "rx submit --> %d\n", retval);
                if (skb)
                        dev_kfree_skb_any(skb);
 +              spin_lock_irqsave(&dev->req_lock, flags);
 +              list_add(&req->list, &dev->rx_reqs);
 +              spin_unlock_irqrestore(&dev->req_lock, flags);
        }
        return retval;
  }
  
  static void rx_complete(struct usb_ep *ep, struct usb_request *req)
  {
 -      struct sk_buff  *skb = req->context;
 +      struct sk_buff  *skb = req->context, *skb2;
        struct eth_dev  *dev = ep->driver_data;
        int             status = req->status;
 -      bool            rx_queue = 0;
  
        switch (status) {
  
                } else {
                        skb_queue_tail(&dev->rx_frames, skb);
                }
 -              if (!status)
 -                      rx_queue = 1;
 +              skb = NULL;
 +
 +              skb2 = skb_dequeue(&dev->rx_frames);
 +              while (skb2) {
 +                      if (status < 0
 +                                      || ETH_HLEN > skb2->len
 +                                      || skb2->len > VLAN_ETH_FRAME_LEN) {
 +                              dev->net->stats.rx_errors++;
 +                              dev->net->stats.rx_length_errors++;
 +                              DBG(dev, "rx length %d\n", skb2->len);
 +                              dev_kfree_skb_any(skb2);
 +                              goto next_frame;
 +                      }
 +                      skb2->protocol = eth_type_trans(skb2, dev->net);
 +                      dev->net->stats.rx_packets++;
 +                      dev->net->stats.rx_bytes += skb2->len;
 +
 +                      /* no buffer copies needed, unless hardware can't
 +                       * use skb buffers.
 +                       */
 +                      status = netif_rx(skb2);
 +next_frame:
 +                      skb2 = skb_dequeue(&dev->rx_frames);
 +              }
                break;
  
        /* software-driven interface shutdown */
@@@ -334,22 -313,20 +334,22 @@@ quiesce
                /* FALLTHROUGH */
  
        default:
 -              rx_queue = 1;
 -              dev_kfree_skb_any(skb);
                dev->net->stats.rx_errors++;
                DBG(dev, "rx status %d\n", status);
                break;
        }
  
 +      if (skb)
 +              dev_kfree_skb_any(skb);
 +      if (!netif_running(dev->net)) {
  clean:
                spin_lock(&dev->req_lock);
                list_add(&req->list, &dev->rx_reqs);
                spin_unlock(&dev->req_lock);
 -
 -      if (rx_queue && likely(napi_schedule_prep(&dev->rx_napi)))
 -              __napi_schedule(&dev->rx_napi);
 +              req = NULL;
 +      }
 +      if (req)
 +              rx_submit(dev, req, GFP_ATOMIC);
  }
  
  static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n)
@@@ -414,16 -391,24 +414,16 @@@ static void rx_fill(struct eth_dev *dev
  {
        struct usb_request      *req;
        unsigned long           flags;
 -      int                     rx_counts = 0;
  
        /* fill unused rxq slots with some skb */
        spin_lock_irqsave(&dev->req_lock, flags);
        while (!list_empty(&dev->rx_reqs)) {
 -
 -              if (++rx_counts > qlen(dev->gadget, dev->qmult))
 -                      break;
 -
                req = container_of(dev->rx_reqs.next,
                                struct usb_request, list);
                list_del_init(&req->list);
                spin_unlock_irqrestore(&dev->req_lock, flags);
  
                if (rx_submit(dev, req, gfp_flags) < 0) {
 -                      spin_lock_irqsave(&dev->req_lock, flags);
 -                      list_add(&req->list, &dev->rx_reqs);
 -                      spin_unlock_irqrestore(&dev->req_lock, flags);
                        defer_kevent(dev, WORK_RX_MEMORY);
                        return;
                }
        spin_unlock_irqrestore(&dev->req_lock, flags);
  }
  
 -static int gether_poll(struct napi_struct *napi, int budget)
 -{
 -      struct eth_dev  *dev = container_of(napi, struct eth_dev, rx_napi);
 -      struct sk_buff  *skb;
 -      unsigned int    work_done = 0;
 -      int             status = 0;
 -
 -      while ((skb = skb_dequeue(&dev->rx_frames))) {
 -              if (status < 0
 -                              || ETH_HLEN > skb->len
 -                              || skb->len > VLAN_ETH_FRAME_LEN) {
 -                      dev->net->stats.rx_errors++;
 -                      dev->net->stats.rx_length_errors++;
 -                      DBG(dev, "rx length %d\n", skb->len);
 -                      dev_kfree_skb_any(skb);
 -                      continue;
 -              }
 -              skb->protocol = eth_type_trans(skb, dev->net);
 -              dev->net->stats.rx_packets++;
 -              dev->net->stats.rx_bytes += skb->len;
 -
 -              status = netif_rx_ni(skb);
 -      }
 -
 -      if (netif_running(dev->net)) {
 -              rx_fill(dev, GFP_KERNEL);
 -              work_done++;
 -      }
 -
 -      if (work_done < budget)
 -              napi_complete(&dev->rx_napi);
 -
 -      return work_done;
 -}
 -
  static void eth_work(struct work_struct *work)
  {
        struct eth_dev  *dev = container_of(work, struct eth_dev, work);
@@@ -625,6 -645,7 +625,6 @@@ static void eth_start(struct eth_dev *d
        /* and open the tx floodgates */
        atomic_set(&dev->tx_qlen, 0);
        netif_wake_queue(dev->net);
 -      napi_enable(&dev->rx_napi);
  }
  
  static int eth_open(struct net_device *net)
@@@ -651,6 -672,7 +651,6 @@@ static int eth_stop(struct net_device *
        unsigned long   flags;
  
        VDBG(dev, "%s\n", __func__);
 -      napi_disable(&dev->rx_napi);
        netif_stop_queue(net);
  
        DBG(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
@@@ -768,6 -790,7 +768,6 @@@ struct eth_dev *gether_setup_name(struc
                return ERR_PTR(-ENOMEM);
  
        dev = netdev_priv(net);
 -      netif_napi_add(net, &dev->rx_napi, gether_poll, GETHER_NAPI_WEIGHT);
        spin_lock_init(&dev->lock);
        spin_lock_init(&dev->req_lock);
        INIT_WORK(&dev->work, eth_work);
  
        return dev;
  }
- EXPORT_SYMBOL(gether_setup_name);
+ EXPORT_SYMBOL_GPL(gether_setup_name);
  
  struct net_device *gether_setup_name_default(const char *netname)
  {
                return ERR_PTR(-ENOMEM);
  
        dev = netdev_priv(net);
 -      netif_napi_add(net, &dev->rx_napi, gether_poll, GETHER_NAPI_WEIGHT);
        spin_lock_init(&dev->lock);
        spin_lock_init(&dev->req_lock);
        INIT_WORK(&dev->work, eth_work);
  
        return net;
  }
- EXPORT_SYMBOL(gether_setup_name_default);
+ EXPORT_SYMBOL_GPL(gether_setup_name_default);
  
  int gether_register_netdev(struct net_device *net)
  {
  
        return status;
  }
- EXPORT_SYMBOL(gether_register_netdev);
+ EXPORT_SYMBOL_GPL(gether_register_netdev);
  
  void gether_set_gadget(struct net_device *net, struct usb_gadget *g)
  {
        dev->gadget = g;
        SET_NETDEV_DEV(net, &g->dev);
  }
- EXPORT_SYMBOL(gether_set_gadget);
+ EXPORT_SYMBOL_GPL(gether_set_gadget);
  
  int gether_set_dev_addr(struct net_device *net, const char *dev_addr)
  {
        memcpy(dev->dev_mac, new_addr, ETH_ALEN);
        return 0;
  }
- EXPORT_SYMBOL(gether_set_dev_addr);
+ EXPORT_SYMBOL_GPL(gether_set_dev_addr);
  
  int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len)
  {
        dev = netdev_priv(net);
        return get_ether_addr_str(dev->dev_mac, dev_addr, len);
  }
- EXPORT_SYMBOL(gether_get_dev_addr);
+ EXPORT_SYMBOL_GPL(gether_get_dev_addr);
  
  int gether_set_host_addr(struct net_device *net, const char *host_addr)
  {
        memcpy(dev->host_mac, new_addr, ETH_ALEN);
        return 0;
  }
- EXPORT_SYMBOL(gether_set_host_addr);
+ EXPORT_SYMBOL_GPL(gether_set_host_addr);
  
  int gether_get_host_addr(struct net_device *net, char *host_addr, int len)
  {
        dev = netdev_priv(net);
        return get_ether_addr_str(dev->host_mac, host_addr, len);
  }
- EXPORT_SYMBOL(gether_get_host_addr);
+ EXPORT_SYMBOL_GPL(gether_get_host_addr);
  
  int gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len)
  {
  
        return strlen(host_addr);
  }
- EXPORT_SYMBOL(gether_get_host_addr_cdc);
+ EXPORT_SYMBOL_GPL(gether_get_host_addr_cdc);
  
  void gether_get_host_addr_u8(struct net_device *net, u8 host_mac[ETH_ALEN])
  {
        dev = netdev_priv(net);
        memcpy(host_mac, dev->host_mac, ETH_ALEN);
  }
- EXPORT_SYMBOL(gether_get_host_addr_u8);
+ EXPORT_SYMBOL_GPL(gether_get_host_addr_u8);
  
  void gether_set_qmult(struct net_device *net, unsigned qmult)
  {
        dev = netdev_priv(net);
        dev->qmult = qmult;
  }
- EXPORT_SYMBOL(gether_set_qmult);
+ EXPORT_SYMBOL_GPL(gether_set_qmult);
  
  unsigned gether_get_qmult(struct net_device *net)
  {
        dev = netdev_priv(net);
        return dev->qmult;
  }
- EXPORT_SYMBOL(gether_get_qmult);
+ EXPORT_SYMBOL_GPL(gether_get_qmult);
  
  int gether_get_ifname(struct net_device *net, char *name, int len)
  {
        rtnl_unlock();
        return strlen(name);
  }
- EXPORT_SYMBOL(gether_get_ifname);
+ EXPORT_SYMBOL_GPL(gether_get_ifname);
  
  /**
   * gether_cleanup - remove Ethernet-over-USB device
@@@ -1014,7 -1038,7 +1014,7 @@@ void gether_cleanup(struct eth_dev *dev
        flush_work(&dev->work);
        free_netdev(dev->net);
  }
- EXPORT_SYMBOL(gether_cleanup);
+ EXPORT_SYMBOL_GPL(gether_cleanup);
  
  /**
   * gether_connect - notify network layer that USB link is active
@@@ -1095,7 -1119,7 +1095,7 @@@ fail0
                return ERR_PTR(result);
        return dev->net;
  }
- EXPORT_SYMBOL(gether_connect);
+ EXPORT_SYMBOL_GPL(gether_connect);
  
  /**
   * gether_disconnect - notify network layer that USB link is inactive
@@@ -1113,6 -1137,7 +1113,6 @@@ void gether_disconnect(struct gether *l
  {
        struct eth_dev          *dev = link->ioport;
        struct usb_request      *req;
 -      struct sk_buff          *skb;
  
        WARN_ON(!dev);
        if (!dev)
                spin_lock(&dev->req_lock);
        }
        spin_unlock(&dev->req_lock);
 -
 -      spin_lock(&dev->rx_frames.lock);
 -      while ((skb = __skb_dequeue(&dev->rx_frames)))
 -              dev_kfree_skb_any(skb);
 -      spin_unlock(&dev->rx_frames.lock);
 -
        link->in_ep->driver_data = NULL;
        link->in_ep->desc = NULL;
  
        dev->port_usb = NULL;
        spin_unlock(&dev->lock);
  }
- EXPORT_SYMBOL(gether_disconnect);
+ EXPORT_SYMBOL_GPL(gether_disconnect);
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("David Brownell");
index e2fd263585de3fb2d8cb5cab3e782eff5675a198,9d9acaaa1f183c36c5e257e7f8bf35447656677b..51beb13c7e1a4d4f9694a5469a12363751ef5d6b
@@@ -35,7 -35,7 +35,7 @@@
  #include <linux/dma-mapping.h>
  #include <linux/pm_runtime.h>
  #include <linux/module.h>
- #include <linux/usb/usb_phy_gen_xceiv.h>
+ #include <linux/usb/usb_phy_generic.h>
  #include <linux/platform_data/usb-omap.h>
  #include <linux/sizes.h>
  
@@@ -329,9 -329,21 +329,21 @@@ static irqreturn_t dsps_interrupt(int i
         * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
         * Also, DRVVBUS pulses for SRP (but not at 5V) ...
         */
-       if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE)
+       if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE) {
                pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
  
+               /*
+                * When a babble condition occurs, the musb controller removes
+                * the session and is no longer in host mode. Hence, all
+                * devices connected to its root hub get disconnected.
+                *
+                * Hand this error down to the musb core isr, so it can
+                * recover.
+                */
+               musb->int_usb = MUSB_INTR_BABBLE | MUSB_INTR_DISCONNECT;
+               musb->int_tx = musb->int_rx = 0;
+       }
        if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
                int drvvbus = dsps_readl(reg_base, wrp->status);
                void __iomem *mregs = musb->mregs;
@@@ -470,9 -482,8 +482,9 @@@ static int dsps_musb_exit(struct musb *
        struct dsps_glue *glue = dev_get_drvdata(dev->parent);
  
        del_timer_sync(&glue->timer);
 -
        usb_phy_shutdown(musb->xceiv);
 +      debugfs_remove_recursive(glue->dbgfs_root);
 +
        return 0;
  }
  
@@@ -524,6 -535,16 +536,16 @@@ static int dsps_musb_set_mode(struct mu
        return 0;
  }
  
+ static void dsps_musb_reset(struct musb *musb)
+ {
+       struct device *dev = musb->controller;
+       struct dsps_glue *glue = dev_get_drvdata(dev->parent);
+       const struct dsps_musb_wrapper *wrp = glue->wrp;
+       dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset));
+       udelay(100);
+ }
  static struct musb_platform_ops dsps_ops = {
        .init           = dsps_musb_init,
        .exit           = dsps_musb_exit,
  
        .try_idle       = dsps_musb_try_idle,
        .set_mode       = dsps_musb_set_mode,
+       .reset          = dsps_musb_reset,
  };
  
  static u64 musb_dmamask = DMA_BIT_MASK(32);
@@@ -709,6 -731,8 +732,6 @@@ static int dsps_remove(struct platform_
        pm_runtime_put(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
  
 -      debugfs_remove_recursive(glue->dbgfs_root);
 -
        return 0;
  }
  
@@@ -750,7 -774,7 +773,7 @@@ static const struct of_device_id musb_d
  };
  MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
  
- #ifdef CONFIG_PM
+ #ifdef CONFIG_PM_SLEEP
  static int dsps_suspend(struct device *dev)
  {
        struct dsps_glue *glue = dev_get_drvdata(dev);
diff --combined drivers/usb/phy/Kconfig
index 33dd6a6c320a6bccd4765ff15525efe8d04fd7df,ec531a48d24034aba8a1626ddc0832c58c9a290f..adccdeb996d9b827d918fac285a59d57554930cc
@@@ -59,6 -59,14 +59,6 @@@ config KEYSTONE_USB_PH
          interface to interact with USB 2.0 and USB 3.0 PHY that is part
          of the Keystone SOC.
  
 -config MV_U3D_PHY
 -      bool "Marvell USB 3.0 PHY controller Driver"
 -      depends on CPU_MMP3
 -      select USB_PHY
 -      help
 -        Enable this to support Marvell USB 3.0 phy controller for Marvell
 -        SoC.
 -
  config NOP_USB_XCEIV
        tristate "NOP USB Transceiver Driver"
        select USB_PHY
@@@ -163,11 -171,12 +163,12 @@@ config USB_ISP130
          module will be called phy-isp1301.
  
  config USB_MSM_OTG
-       tristate "OTG support for Qualcomm on-chip USB controller"
-       depends on (USB || USB_GADGET) && ARCH_MSM
+       tristate "Qualcomm on-chip USB OTG controller support"
+       depends on (USB || USB_GADGET) && (ARCH_MSM || ARCH_QCOM || COMPILE_TEST)
+       depends on RESET_CONTROLLER
        select USB_PHY
        help
-         Enable this to support the USB OTG transceiver on MSM chips. It
+         Enable this to support the USB OTG transceiver on Qualcomm chips. It
          handles PHY initialization, clock management, and workarounds
          required after resetting the hardware and power management.
          This driver is required even for peripheral only or host only