]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 May 2014 07:00:34 +0000 (00:00 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 May 2014 07:00:34 +0000 (00:00 -0700)
added patches:
hvc-ensure-hvc_init-is-only-ever-called-once-in-hvc_console.c.patch
mtip32xx-mtip_async_complete-bug-fixes.patch
mtip32xx-set-queue-bounce-limit.patch
mtip32xx-unmap-the-dma-segments-before-completing-the-io-request.patch
usb-musb-avoid-null-pointer-dereference.patch
usb-musb-fix-phy-power-on-off.patch
usb-phy-add-ulpi-ids-for-smsc-usb3320-and-ti-tusb1210.patch
usb-phy-am335x-control-wait-1ms-after-power-up-transitions.patch
usb-unbind-all-interfaces-before-rebinding-any.patch

queue-3.14/hvc-ensure-hvc_init-is-only-ever-called-once-in-hvc_console.c.patch [new file with mode: 0644]
queue-3.14/mtip32xx-mtip_async_complete-bug-fixes.patch [new file with mode: 0644]
queue-3.14/mtip32xx-set-queue-bounce-limit.patch [new file with mode: 0644]
queue-3.14/mtip32xx-unmap-the-dma-segments-before-completing-the-io-request.patch [new file with mode: 0644]
queue-3.14/series
queue-3.14/usb-musb-avoid-null-pointer-dereference.patch [new file with mode: 0644]
queue-3.14/usb-musb-fix-phy-power-on-off.patch [new file with mode: 0644]
queue-3.14/usb-phy-add-ulpi-ids-for-smsc-usb3320-and-ti-tusb1210.patch [new file with mode: 0644]
queue-3.14/usb-phy-am335x-control-wait-1ms-after-power-up-transitions.patch [new file with mode: 0644]
queue-3.14/usb-unbind-all-interfaces-before-rebinding-any.patch [new file with mode: 0644]

diff --git a/queue-3.14/hvc-ensure-hvc_init-is-only-ever-called-once-in-hvc_console.c.patch b/queue-3.14/hvc-ensure-hvc_init-is-only-ever-called-once-in-hvc_console.c.patch
new file mode 100644 (file)
index 0000000..3a1cf74
--- /dev/null
@@ -0,0 +1,70 @@
+From f76a1cbed18c86e2d192455f0daebb48458965f3 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Tue, 14 Jan 2014 16:03:37 -0500
+Subject: hvc: ensure hvc_init is only ever called once in hvc_console.c
+
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+
+commit f76a1cbed18c86e2d192455f0daebb48458965f3 upstream.
+
+Commit 3e6c6f630a5282df8f3393a59f10eb9c56536d23 ("Delay creation of
+khcvd thread") moved the call of hvc_init from being a device_initcall
+into hvc_alloc, and used a non-null hvc_driver as indication of whether
+hvc_init had already been called.
+
+The problem with this is that hvc_driver is only assigned a value
+at the bottom of hvc_init, and so there is a window where multiple
+hvc_alloc calls can be in progress at the same time and hence try
+and call hvc_init multiple times.  Previously the use of device_init
+guaranteed that hvc_init was only called once.
+
+This manifests itself as sporadic instances of two hvc_init calls
+racing each other, and with the loser of the race getting -EBUSY
+from tty_register_driver() and hence that virtual console fails:
+
+    Couldn't register hvc console driver
+    virtio-ports vport0p1: error -16 allocating hvc for port
+
+Here we add an atomic_t to guarantee we'll never run hvc_init twice.
+
+Cc: Rusty Russell <rusty@rustcorp.com.au>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Fixes: 3e6c6f630a52 ("Delay creation of khcvd thread")
+Reported-by: Jim Somerville <Jim.Somerville@windriver.com>
+Tested-by: Jim Somerville <Jim.Somerville@windriver.com>
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/hvc/hvc_console.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/tty/hvc/hvc_console.c
++++ b/drivers/tty/hvc/hvc_console.c
+@@ -31,6 +31,7 @@
+ #include <linux/list.h>
+ #include <linux/module.h>
+ #include <linux/major.h>
++#include <linux/atomic.h>
+ #include <linux/sysrq.h>
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
+@@ -70,6 +71,9 @@ static struct task_struct *hvc_task;
+ /* Picks up late kicks after list walk but before schedule() */
+ static int hvc_kicked;
++/* hvc_init is triggered from hvc_alloc, i.e. only when actually used */
++static atomic_t hvc_needs_init __read_mostly = ATOMIC_INIT(-1);
++
+ static int hvc_init(void);
+ #ifdef CONFIG_MAGIC_SYSRQ
+@@ -851,7 +855,7 @@ struct hvc_struct *hvc_alloc(uint32_t vt
+       int i;
+       /* We wait until a driver actually comes along */
+-      if (!hvc_driver) {
++      if (atomic_inc_not_zero(&hvc_needs_init)) {
+               int err = hvc_init();
+               if (err)
+                       return ERR_PTR(err);
diff --git a/queue-3.14/mtip32xx-mtip_async_complete-bug-fixes.patch b/queue-3.14/mtip32xx-mtip_async_complete-bug-fixes.patch
new file mode 100644 (file)
index 0000000..23c174e
--- /dev/null
@@ -0,0 +1,178 @@
+From 5eb9291c36c7d71d7c6c832d5a4f551eb8ac015d Mon Sep 17 00:00:00 2001
+From: Sam Bradshaw <sbradshaw@micron.com>
+Date: Thu, 13 Mar 2014 14:33:30 -0700
+Subject: mtip32xx: mtip_async_complete() bug fixes
+
+From: Sam Bradshaw <sbradshaw@micron.com>
+
+commit 5eb9291c36c7d71d7c6c832d5a4f551eb8ac015d upstream.
+
+This patch fixes 2 issues in the fast completion path:
+1) Possible double completions / double dma_unmap_sg() calls due to lack
+of atomicity in the check and subsequent dereference of the upper layer
+callback function. Fixed with cmpxchg before unmap and callback.
+2) Regression in unaligned IO constraining workaround for p420m devices.
+Fixed by checking if IO is unaligned and using proper semaphore if so.
+
+Signed-off-by: Sam Bradshaw <sbradshaw@micron.com>
+Signed-off-by: Jens Axboe <axboe@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/mtip32xx/mtip32xx.c |   93 +++++++++++++++++++++-----------------
+ drivers/block/mtip32xx/mtip32xx.h |    2 
+ 2 files changed, 53 insertions(+), 42 deletions(-)
+
+--- a/drivers/block/mtip32xx/mtip32xx.c
++++ b/drivers/block/mtip32xx/mtip32xx.c
+@@ -252,38 +252,45 @@ static void mtip_async_complete(struct m
+                               void *data,
+                               int status)
+ {
+-      struct mtip_cmd *command;
++      struct mtip_cmd *cmd;
+       struct driver_data *dd = data;
+-      int cb_status = status ? -EIO : 0;
++      int unaligned, cb_status = status ? -EIO : 0;
++      void (*func)(void *, int);
+       if (unlikely(!dd) || unlikely(!port))
+               return;
+-      command = &port->commands[tag];
++      cmd = &port->commands[tag];
+       if (unlikely(status == PORT_IRQ_TF_ERR)) {
+               dev_warn(&port->dd->pdev->dev,
+                       "Command tag %d failed due to TFE\n", tag);
+       }
+-      /* Unmap the DMA scatter list entries */
+-      dma_unmap_sg(&dd->pdev->dev,
+-              command->sg,
+-              command->scatter_ents,
+-              command->direction);
++      /* Clear the active flag */
++      atomic_set(&port->commands[tag].active, 0);
+       /* Upper layer callback */
+-      if (likely(command->async_callback))
+-              command->async_callback(command->async_data, cb_status);
+-
+-      command->async_callback = NULL;
+-      command->comp_func = NULL;
++      func = cmd->async_callback;
++      if (likely(func && cmpxchg(&cmd->async_callback, func, 0) == func)) {
+-      /* Clear the allocated and active bits for the command */
+-      atomic_set(&port->commands[tag].active, 0);
+-      release_slot(port, tag);
+-
+-      up(&port->cmd_slot);
++              /* Unmap the DMA scatter list entries */
++              dma_unmap_sg(&dd->pdev->dev,
++                      cmd->sg,
++                      cmd->scatter_ents,
++                      cmd->direction);
++
++              func(cmd->async_data, cb_status);
++              unaligned = cmd->unaligned;
++
++              /* Clear the allocated bit for the command */
++              release_slot(port, tag);
++
++              if (unlikely(unaligned))
++                      up(&port->cmd_slot_unal);
++              else
++                      up(&port->cmd_slot);
++      }
+ }
+ /*
+@@ -660,11 +667,12 @@ static void mtip_timeout_function(unsign
+ {
+       struct mtip_port *port = (struct mtip_port *) data;
+       struct host_to_dev_fis *fis;
+-      struct mtip_cmd *command;
+-      int tag, cmdto_cnt = 0;
++      struct mtip_cmd *cmd;
++      int unaligned, tag, cmdto_cnt = 0;
+       unsigned int bit, group;
+       unsigned int num_command_slots;
+       unsigned long to, tagaccum[SLOTBITS_IN_LONGS];
++      void (*func)(void *, int);
+       if (unlikely(!port))
+               return;
+@@ -694,8 +702,8 @@ static void mtip_timeout_function(unsign
+                       group = tag >> 5;
+                       bit = tag & 0x1F;
+-                      command = &port->commands[tag];
+-                      fis = (struct host_to_dev_fis *) command->command;
++                      cmd = &port->commands[tag];
++                      fis = (struct host_to_dev_fis *) cmd->command;
+                       set_bit(tag, tagaccum);
+                       cmdto_cnt++;
+@@ -709,27 +717,30 @@ static void mtip_timeout_function(unsign
+                        */
+                       writel(1 << bit, port->completed[group]);
+-                      /* Unmap the DMA scatter list entries */
+-                      dma_unmap_sg(&port->dd->pdev->dev,
+-                                      command->sg,
+-                                      command->scatter_ents,
+-                                      command->direction);
+-
+-                      /* Call the async completion callback. */
+-                      if (likely(command->async_callback))
+-                              command->async_callback(command->async_data,
+-                                                       -EIO);
+-                      command->async_callback = NULL;
+-                      command->comp_func = NULL;
+-
+-                      /*
+-                       * Clear the allocated bit and active tag for the
+-                       * command.
+-                       */
++                      /* Clear the active flag for the command */
+                       atomic_set(&port->commands[tag].active, 0);
+-                      release_slot(port, tag);
+-                      up(&port->cmd_slot);
++                      func = cmd->async_callback;
++                      if (func &&
++                          cmpxchg(&cmd->async_callback, func, 0) == func) {
++
++                              /* Unmap the DMA scatter list entries */
++                              dma_unmap_sg(&port->dd->pdev->dev,
++                                              cmd->sg,
++                                              cmd->scatter_ents,
++                                              cmd->direction);
++
++                              func(cmd->async_data, -EIO);
++                              unaligned = cmd->unaligned;
++
++                              /* Clear the allocated bit for the command. */
++                              release_slot(port, tag);
++
++                              if (unaligned)
++                                      up(&port->cmd_slot_unal);
++                              else
++                                      up(&port->cmd_slot);
++                      }
+               }
+       }
+--- a/drivers/block/mtip32xx/mtip32xx.h
++++ b/drivers/block/mtip32xx/mtip32xx.h
+@@ -92,7 +92,7 @@
+ /* Driver name and version strings */
+ #define MTIP_DRV_NAME         "mtip32xx"
+-#define MTIP_DRV_VERSION      "1.3.0"
++#define MTIP_DRV_VERSION      "1.3.1"
+ /* Maximum number of minor device numbers per device. */
+ #define MTIP_MAX_MINORS               16
diff --git a/queue-3.14/mtip32xx-set-queue-bounce-limit.patch b/queue-3.14/mtip32xx-set-queue-bounce-limit.patch
new file mode 100644 (file)
index 0000000..a0246e5
--- /dev/null
@@ -0,0 +1,30 @@
+From 1044b1bb9278f2e656a1a7b63dc24a59506540aa Mon Sep 17 00:00:00 2001
+From: Felipe Franciosi <felipe@paradoxo.org>
+Date: Thu, 13 Mar 2014 14:34:20 +0000
+Subject: mtip32xx: Set queue bounce limit
+
+From: Felipe Franciosi <felipe@paradoxo.org>
+
+commit 1044b1bb9278f2e656a1a7b63dc24a59506540aa upstream.
+
+We need to set the queue bounce limit during the device initialization to
+prevent excessive bouncing on 32 bit architectures.
+
+Signed-off-by: Felipe Franciosi <felipe@paradoxo.org>
+Signed-off-by: Jens Axboe <axboe@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/mtip32xx/mtip32xx.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/block/mtip32xx/mtip32xx.c
++++ b/drivers/block/mtip32xx/mtip32xx.c
+@@ -4213,6 +4213,7 @@ skip_create_disk:
+       blk_queue_max_hw_sectors(dd->queue, 0xffff);
+       blk_queue_max_segment_size(dd->queue, 0x400000);
+       blk_queue_io_min(dd->queue, 4096);
++      blk_queue_bounce_limit(dd->queue, dd->pdev->dma_mask);
+       /*
+        * write back cache is not supported in the device. FUA depends on
diff --git a/queue-3.14/mtip32xx-unmap-the-dma-segments-before-completing-the-io-request.patch b/queue-3.14/mtip32xx-unmap-the-dma-segments-before-completing-the-io-request.patch
new file mode 100644 (file)
index 0000000..b9924d9
--- /dev/null
@@ -0,0 +1,74 @@
+From 368c89d7ac70f937c93cd6f3b65bcfdfb3ba794f Mon Sep 17 00:00:00 2001
+From: Felipe Franciosi <felipe@paradoxo.org>
+Date: Thu, 13 Mar 2014 14:34:21 +0000
+Subject: mtip32xx: Unmap the DMA segments before completing the IO request
+
+From: Felipe Franciosi <felipe@paradoxo.org>
+
+commit 368c89d7ac70f937c93cd6f3b65bcfdfb3ba794f upstream.
+
+If the buffers are unmapped after completing a request, then stale data
+might be in the request.
+
+Signed-off-by: Felipe Franciosi <felipe@paradoxo.org>
+Signed-off-by: Jens Axboe <axboe@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/mtip32xx/mtip32xx.c |   24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+--- a/drivers/block/mtip32xx/mtip32xx.c
++++ b/drivers/block/mtip32xx/mtip32xx.c
+@@ -266,6 +266,12 @@ static void mtip_async_complete(struct m
+                       "Command tag %d failed due to TFE\n", tag);
+       }
++      /* Unmap the DMA scatter list entries */
++      dma_unmap_sg(&dd->pdev->dev,
++              command->sg,
++              command->scatter_ents,
++              command->direction);
++
+       /* Upper layer callback */
+       if (likely(command->async_callback))
+               command->async_callback(command->async_data, cb_status);
+@@ -273,12 +279,6 @@ static void mtip_async_complete(struct m
+       command->async_callback = NULL;
+       command->comp_func = NULL;
+-      /* Unmap the DMA scatter list entries */
+-      dma_unmap_sg(&dd->pdev->dev,
+-              command->sg,
+-              command->scatter_ents,
+-              command->direction);
+-
+       /* Clear the allocated and active bits for the command */
+       atomic_set(&port->commands[tag].active, 0);
+       release_slot(port, tag);
+@@ -709,6 +709,12 @@ static void mtip_timeout_function(unsign
+                        */
+                       writel(1 << bit, port->completed[group]);
++                      /* Unmap the DMA scatter list entries */
++                      dma_unmap_sg(&port->dd->pdev->dev,
++                                      command->sg,
++                                      command->scatter_ents,
++                                      command->direction);
++
+                       /* Call the async completion callback. */
+                       if (likely(command->async_callback))
+                               command->async_callback(command->async_data,
+@@ -716,12 +722,6 @@ static void mtip_timeout_function(unsign
+                       command->async_callback = NULL;
+                       command->comp_func = NULL;
+-                      /* Unmap the DMA scatter list entries */
+-                      dma_unmap_sg(&port->dd->pdev->dev,
+-                                      command->sg,
+-                                      command->scatter_ents,
+-                                      command->direction);
+-
+                       /*
+                        * Clear the allocated bit and active tag for the
+                        * command.
index c651f0c2b6634e49f56c02451ab65bdf786b2a53..3342233b4ba1ec0a1945676bcdba8574ed62c54f 100644 (file)
@@ -121,3 +121,12 @@ media-omap3isp-preview-fix-the-crop-margins.patch
 media-media-gspca-sn9c20x-add-id-for-genius-look-1320-v2.patch
 usb-dwc3-fix-wrong-bit-mask-in-dwc3_event_devt.patch
 usb-dwc3-fix-randconfig-build-errors.patch
+usb-musb-avoid-null-pointer-dereference.patch
+usb-musb-fix-phy-power-on-off.patch
+hvc-ensure-hvc_init-is-only-ever-called-once-in-hvc_console.c.patch
+usb-phy-add-ulpi-ids-for-smsc-usb3320-and-ti-tusb1210.patch
+usb-phy-am335x-control-wait-1ms-after-power-up-transitions.patch
+usb-unbind-all-interfaces-before-rebinding-any.patch
+mtip32xx-set-queue-bounce-limit.patch
+mtip32xx-unmap-the-dma-segments-before-completing-the-io-request.patch
+mtip32xx-mtip_async_complete-bug-fixes.patch
diff --git a/queue-3.14/usb-musb-avoid-null-pointer-dereference.patch b/queue-3.14/usb-musb-avoid-null-pointer-dereference.patch
new file mode 100644 (file)
index 0000000..9648e6c
--- /dev/null
@@ -0,0 +1,50 @@
+From eee3f15d5f1f4f0c283dd4db67dc1b874a2852d1 Mon Sep 17 00:00:00 2001
+From: Felipe Balbi <balbi@ti.com>
+Date: Tue, 25 Feb 2014 10:58:43 -0600
+Subject: usb: musb: avoid NULL pointer dereference
+
+From: Felipe Balbi <balbi@ti.com>
+
+commit eee3f15d5f1f4f0c283dd4db67dc1b874a2852d1 upstream.
+
+instead of relying on the otg pointer, which
+can be NULL in certain cases, we can use the
+gadget and host pointers we already hold inside
+struct musb.
+
+Tested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/musb/musb_core.c |    5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -438,7 +438,6 @@ void musb_hnp_stop(struct musb *musb)
+ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+                               u8 devctl)
+ {
+-      struct usb_otg *otg = musb->xceiv->otg;
+       irqreturn_t handled = IRQ_NONE;
+       dev_dbg(musb->controller, "<== DevCtl=%02x, int_usb=0x%x\n", devctl,
+@@ -656,7 +655,7 @@ static irqreturn_t musb_stage0_irq(struc
+                               break;
+               case OTG_STATE_B_PERIPHERAL:
+                       musb_g_suspend(musb);
+-                      musb->is_active = otg->gadget->b_hnp_enable;
++                      musb->is_active = musb->g.b_hnp_enable;
+                       if (musb->is_active) {
+                               musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
+                               dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n");
+@@ -672,7 +671,7 @@ static irqreturn_t musb_stage0_irq(struc
+                       break;
+               case OTG_STATE_A_HOST:
+                       musb->xceiv->state = OTG_STATE_A_SUSPEND;
+-                      musb->is_active = otg->host->b_hnp_enable;
++                      musb->is_active = musb->hcd->self.b_hnp_enable;
+                       break;
+               case OTG_STATE_B_HOST:
+                       /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */
diff --git a/queue-3.14/usb-musb-fix-phy-power-on-off.patch b/queue-3.14/usb-musb-fix-phy-power-on-off.patch
new file mode 100644 (file)
index 0000000..f650e73
--- /dev/null
@@ -0,0 +1,55 @@
+From 3063a12be2b07c64e9802708a19489342e64c1a3 Mon Sep 17 00:00:00 2001
+From: Felipe Balbi <balbi@ti.com>
+Date: Fri, 28 Mar 2014 14:31:47 -0500
+Subject: usb: musb: fix PHY power on/off
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Felipe Balbi <balbi@ti.com>
+
+commit 3063a12be2b07c64e9802708a19489342e64c1a3 upstream.
+
+commi 30a70b0 (usb: musb: fix obex in g_nokia.ko
+causing kernel panic) removed phy_power_on()
+and phy_power_off() calls from runtime PM callbacks
+but it failed to note that the driver depended
+on pm_runtime_get_sync() calls to power up the PHY,
+thus leaving some platforms without any means to
+have a working PHY.
+
+Fix that by enabling the phy during omap2430_musb_init()
+and killing it in omap2430_musb_exit().
+
+Fixes: 30a70b0 (usb: musb: fix obex in g_nokia.ko causing kernel panic)
+Cc: Pali Rohár <pali.rohar@gmail.com>
+Cc: Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
+Reported-by: Michael Scott <hashcode0f@gmail.com>
+Tested-by: Michael Scott <hashcode0f@gmail.com>
+Tested-by: Stefan Roese <sr@denx.de>
+Reported-by: Rabin Vincent <rabin@rab.in>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/musb/omap2430.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -416,6 +416,7 @@ static int omap2430_musb_init(struct mus
+               omap_musb_set_mailbox(glue);
+       phy_init(musb->phy);
++      phy_power_on(musb->phy);
+       pm_runtime_put_noidle(musb->controller);
+       return 0;
+@@ -478,6 +479,7 @@ static int omap2430_musb_exit(struct mus
+       del_timer_sync(&musb_idle_timer);
+       omap2430_low_level_exit(musb);
++      phy_power_off(musb->phy);
+       phy_exit(musb->phy);
+       return 0;
diff --git a/queue-3.14/usb-phy-add-ulpi-ids-for-smsc-usb3320-and-ti-tusb1210.patch b/queue-3.14/usb-phy-add-ulpi-ids-for-smsc-usb3320-and-ti-tusb1210.patch
new file mode 100644 (file)
index 0000000..ccbfaa4
--- /dev/null
@@ -0,0 +1,29 @@
+From ead5178bf442dbae4008ee54bf4f66a1f6a317c9 Mon Sep 17 00:00:00 2001
+From: Michal Simek <michal.simek@xilinx.com>
+Date: Tue, 11 Mar 2014 13:23:14 +0100
+Subject: usb: phy: Add ulpi IDs for SMSC USB3320 and TI TUSB1210
+
+From: Michal Simek <michal.simek@xilinx.com>
+
+commit ead5178bf442dbae4008ee54bf4f66a1f6a317c9 upstream.
+
+Add new ulpi IDs which are available on Xilinx Zynq boards.
+
+Signed-off-by: Michal Simek <michal.simek@xilinx.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/phy/phy-ulpi.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/phy/phy-ulpi.c
++++ b/drivers/usb/phy/phy-ulpi.c
+@@ -47,6 +47,8 @@ struct ulpi_info {
+ static struct ulpi_info ulpi_ids[] = {
+       ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"),
+       ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"),
++      ULPI_INFO(ULPI_ID(0x0424, 0x0007), "SMSC USB3320"),
++      ULPI_INFO(ULPI_ID(0x0451, 0x1507), "TI TUSB1210"),
+ };
+ static int ulpi_set_otg_flags(struct usb_phy *phy)
diff --git a/queue-3.14/usb-phy-am335x-control-wait-1ms-after-power-up-transitions.patch b/queue-3.14/usb-phy-am335x-control-wait-1ms-after-power-up-transitions.patch
new file mode 100644 (file)
index 0000000..f13ea47
--- /dev/null
@@ -0,0 +1,46 @@
+From a31a942a148e0083ce560ffeb54fb60e06ab7201 Mon Sep 17 00:00:00 2001
+From: Daniel Mack <zonque@gmail.com>
+Date: Wed, 16 Apr 2014 17:11:16 +0200
+Subject: usb: phy: am335x-control: wait 1ms after power-up transitions
+
+From: Daniel Mack <zonque@gmail.com>
+
+commit a31a942a148e0083ce560ffeb54fb60e06ab7201 upstream.
+
+Tests have shown that when a power-up transition is followed by other
+PHY operations too quickly, the USB port appears dead. Waiting 1ms fixes
+this problem.
+
+Signed-off-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/phy/phy-am335x-control.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/usb/phy/phy-am335x-control.c
++++ b/drivers/usb/phy/phy-am335x-control.c
+@@ -3,6 +3,7 @@
+ #include <linux/err.h>
+ #include <linux/of.h>
+ #include <linux/io.h>
++#include <linux/delay.h>
+ #include "am35x-phy-control.h"
+ struct am335x_control_usb {
+@@ -86,6 +87,14 @@ static void am335x_phy_power(struct phy_
+       }
+       writel(val, usb_ctrl->phy_reg + reg);
++
++      /*
++       * Give the PHY ~1ms to complete the power up operation.
++       * Tests have shown unstable behaviour if other USB PHY related
++       * registers are written too shortly after such a transition.
++       */
++      if (on)
++              mdelay(1);
+ }
+ static const struct phy_control ctrl_am335x = {
diff --git a/queue-3.14/usb-unbind-all-interfaces-before-rebinding-any.patch b/queue-3.14/usb-unbind-all-interfaces-before-rebinding-any.patch
new file mode 100644 (file)
index 0000000..7f7ecc5
--- /dev/null
@@ -0,0 +1,232 @@
+From 6aec044cc2f5670cf3b143c151c8be846499bd15 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Wed, 12 Mar 2014 11:30:38 -0400
+Subject: USB: unbind all interfaces before rebinding any
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 6aec044cc2f5670cf3b143c151c8be846499bd15 upstream.
+
+When a driver doesn't have pre_reset, post_reset, or reset_resume
+methods, the USB core unbinds that driver when its device undergoes a
+reset or a reset-resume, and then rebinds it afterward.
+
+The existing straightforward implementation can lead to problems,
+because each interface gets unbound and rebound before the next
+interface is handled.  If a driver claims additional interfaces, the
+claim may fail because the old binding instance may still own the
+additional interface when the new instance tries to claim it.
+
+This patch fixes the problem by first unbinding all the interfaces
+that are marked (i.e., their needs_binding flag is set) and then
+rebinding all of them.
+
+The patch also makes the helper functions in driver.c a little more
+uniform and adjusts some out-of-date comments.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Reported-and-tested-by: "Poulain, Loic" <loic.poulain@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/driver.c |   94 +++++++++++++++++++++++++++-------------------
+ drivers/usb/core/hub.c    |    5 +-
+ drivers/usb/core/usb.h    |    2 
+ 3 files changed, 60 insertions(+), 41 deletions(-)
+
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -990,8 +990,7 @@ EXPORT_SYMBOL_GPL(usb_deregister);
+  * it doesn't support pre_reset/post_reset/reset_resume or
+  * because it doesn't support suspend/resume.
+  *
+- * The caller must hold @intf's device's lock, but not its pm_mutex
+- * and not @intf->dev.sem.
++ * The caller must hold @intf's device's lock, but not @intf's lock.
+  */
+ void usb_forced_unbind_intf(struct usb_interface *intf)
+ {
+@@ -1004,16 +1003,37 @@ void usb_forced_unbind_intf(struct usb_i
+       intf->needs_binding = 1;
+ }
++/*
++ * Unbind drivers for @udev's marked interfaces.  These interfaces have
++ * the needs_binding flag set, for example by usb_resume_interface().
++ *
++ * The caller must hold @udev's device lock.
++ */
++static void unbind_marked_interfaces(struct usb_device *udev)
++{
++      struct usb_host_config  *config;
++      int                     i;
++      struct usb_interface    *intf;
++
++      config = udev->actconfig;
++      if (config) {
++              for (i = 0; i < config->desc.bNumInterfaces; ++i) {
++                      intf = config->interface[i];
++                      if (intf->dev.driver && intf->needs_binding)
++                              usb_forced_unbind_intf(intf);
++              }
++      }
++}
++
+ /* Delayed forced unbinding of a USB interface driver and scan
+  * for rebinding.
+  *
+- * The caller must hold @intf's device's lock, but not its pm_mutex
+- * and not @intf->dev.sem.
++ * The caller must hold @intf's device's lock, but not @intf's lock.
+  *
+  * Note: Rebinds will be skipped if a system sleep transition is in
+  * progress and the PM "complete" callback hasn't occurred yet.
+  */
+-void usb_rebind_intf(struct usb_interface *intf)
++static void usb_rebind_intf(struct usb_interface *intf)
+ {
+       int rc;
+@@ -1030,68 +1050,66 @@ void usb_rebind_intf(struct usb_interfac
+       }
+ }
+-#ifdef CONFIG_PM
+-
+-/* Unbind drivers for @udev's interfaces that don't support suspend/resume
+- * There is no check for reset_resume here because it can be determined
+- * only during resume whether reset_resume is needed.
++/*
++ * Rebind drivers to @udev's marked interfaces.  These interfaces have
++ * the needs_binding flag set.
+  *
+  * The caller must hold @udev's device lock.
+  */
+-static void unbind_no_pm_drivers_interfaces(struct usb_device *udev)
++static void rebind_marked_interfaces(struct usb_device *udev)
+ {
+       struct usb_host_config  *config;
+       int                     i;
+       struct usb_interface    *intf;
+-      struct usb_driver       *drv;
+       config = udev->actconfig;
+       if (config) {
+               for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+                       intf = config->interface[i];
+-
+-                      if (intf->dev.driver) {
+-                              drv = to_usb_driver(intf->dev.driver);
+-                              if (!drv->suspend || !drv->resume)
+-                                      usb_forced_unbind_intf(intf);
+-                      }
++                      if (intf->needs_binding)
++                              usb_rebind_intf(intf);
+               }
+       }
+ }
+-/* Unbind drivers for @udev's interfaces that failed to support reset-resume.
+- * These interfaces have the needs_binding flag set by usb_resume_interface().
++/*
++ * Unbind all of @udev's marked interfaces and then rebind all of them.
++ * This ordering is necessary because some drivers claim several interfaces
++ * when they are first probed.
+  *
+  * The caller must hold @udev's device lock.
+  */
+-static void unbind_no_reset_resume_drivers_interfaces(struct usb_device *udev)
++void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev)
+ {
+-      struct usb_host_config  *config;
+-      int                     i;
+-      struct usb_interface    *intf;
+-
+-      config = udev->actconfig;
+-      if (config) {
+-              for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+-                      intf = config->interface[i];
+-                      if (intf->dev.driver && intf->needs_binding)
+-                              usb_forced_unbind_intf(intf);
+-              }
+-      }
++      unbind_marked_interfaces(udev);
++      rebind_marked_interfaces(udev);
+ }
+-static void do_rebind_interfaces(struct usb_device *udev)
++#ifdef CONFIG_PM
++
++/* Unbind drivers for @udev's interfaces that don't support suspend/resume
++ * There is no check for reset_resume here because it can be determined
++ * only during resume whether reset_resume is needed.
++ *
++ * The caller must hold @udev's device lock.
++ */
++static void unbind_no_pm_drivers_interfaces(struct usb_device *udev)
+ {
+       struct usb_host_config  *config;
+       int                     i;
+       struct usb_interface    *intf;
++      struct usb_driver       *drv;
+       config = udev->actconfig;
+       if (config) {
+               for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+                       intf = config->interface[i];
+-                      if (intf->needs_binding)
+-                              usb_rebind_intf(intf);
++
++                      if (intf->dev.driver) {
++                              drv = to_usb_driver(intf->dev.driver);
++                              if (!drv->suspend || !drv->resume)
++                                      usb_forced_unbind_intf(intf);
++                      }
+               }
+       }
+ }
+@@ -1420,7 +1438,7 @@ int usb_resume_complete(struct device *d
+        * whose needs_binding flag is set
+        */
+       if (udev->state != USB_STATE_NOTATTACHED)
+-              do_rebind_interfaces(udev);
++              rebind_marked_interfaces(udev);
+       return 0;
+ }
+@@ -1442,7 +1460,7 @@ int usb_resume(struct device *dev, pm_me
+               pm_runtime_disable(dev);
+               pm_runtime_set_active(dev);
+               pm_runtime_enable(dev);
+-              unbind_no_reset_resume_drivers_interfaces(udev);
++              unbind_marked_interfaces(udev);
+       }
+       /* Avoid PM error messages for devices disconnected while suspended
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -5340,10 +5340,11 @@ int usb_reset_device(struct usb_device *
+                               else if (cintf->condition ==
+                                               USB_INTERFACE_BOUND)
+                                       rebind = 1;
++                              if (rebind)
++                                      cintf->needs_binding = 1;
+                       }
+-                      if (ret == 0 && rebind)
+-                              usb_rebind_intf(cintf);
+               }
++              usb_unbind_and_rebind_marked_interfaces(udev);
+       }
+       usb_autosuspend_device(udev);
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -55,7 +55,7 @@ extern int usb_match_one_id_intf(struct
+ extern int usb_match_device(struct usb_device *dev,
+                           const struct usb_device_id *id);
+ extern void usb_forced_unbind_intf(struct usb_interface *intf);
+-extern void usb_rebind_intf(struct usb_interface *intf);
++extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev);
+ extern int usb_hub_claim_port(struct usb_device *hdev, unsigned port,
+               struct dev_state *owner);