]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
more 2.6.22 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Mon, 19 Nov 2007 17:28:20 +0000 (09:28 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 19 Nov 2007 17:28:20 +0000 (09:28 -0800)
queue-2.6.22/i4l-fix-random-freezes-with-avm-b1-drivers.patch [new file with mode: 0644]
queue-2.6.22/i4l-fix-random-hard-freeze-with-avm-c4-card.patch [new file with mode: 0644]
queue-2.6.22/series
queue-2.6.22/usb-mutual-exclusion-for-ehci-init-and-port-resets.patch [new file with mode: 0644]
queue-2.6.22/usb-usbserial-fix-potential-deadlock-between-write-and-irq.patch [new file with mode: 0644]

diff --git a/queue-2.6.22/i4l-fix-random-freezes-with-avm-b1-drivers.patch b/queue-2.6.22/i4l-fix-random-freezes-with-avm-b1-drivers.patch
new file mode 100644 (file)
index 0000000..a68649a
--- /dev/null
@@ -0,0 +1,136 @@
+From stable-bounces@linux.kernel.org Thu Oct 18 03:05:05 2007
+From: Karsten Keil <kkeil@suse.de>
+Date: Thu, 18 Oct 2007 03:04:31 -0700
+Subject: i4l: fix random freezes with AVM B1 drivers
+To: torvalds@linux-foundation.org
+Cc: akpm@linux-foundation.org, stable@kernel.org, kkeil@suse.de
+Message-ID: <200710181004.l9IA4VVS005629@imap1.linux-foundation.org>
+
+
+From: Karsten Keil <kkeil@suse.de>
+
+patch 9713d9e650045f7f2afd81d58a068827be306993 in mainline.
+
+This fix the same issue which was debbuged for the C4 controller for the B1
+versions.
+
+The capilib_ function modify or traverse a linked list without locking.
+
+This patch extends the existing locking to the calls of these function to
+prevent access to a list which is in the middle of a modification.
+
+Signed-off-by: Karsten Keil <kkeil@suse.de>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/isdn/hardware/avm/b1.c |   28 +++++++++++++---------------
+ 1 file changed, 13 insertions(+), 15 deletions(-)
+
+--- a/drivers/isdn/hardware/avm/b1.c
++++ b/drivers/isdn/hardware/avm/b1.c
+@@ -321,12 +321,15 @@ void b1_reset_ctr(struct capi_ctr *ctrl)
+       avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+       avmcard *card = cinfo->card;
+       unsigned int port = card->port;
++      unsigned long flags;
+       b1_reset(port);
+       b1_reset(port);
+       memset(cinfo->version, 0, sizeof(cinfo->version));
++      spin_lock_irqsave(&card->lock, flags);
+       capilib_release(&cinfo->ncci_head);
++      spin_unlock_irqrestore(&card->lock, flags);
+       capi_ctr_reseted(ctrl);
+ }
+@@ -361,9 +364,8 @@ void b1_release_appl(struct capi_ctr *ct
+       unsigned int port = card->port;
+       unsigned long flags;
+-      capilib_release_appl(&cinfo->ncci_head, appl);
+-
+       spin_lock_irqsave(&card->lock, flags);
++      capilib_release_appl(&cinfo->ncci_head, appl);
+       b1_put_byte(port, SEND_RELEASE);
+       b1_put_word(port, appl);
+       spin_unlock_irqrestore(&card->lock, flags);
+@@ -380,27 +382,27 @@ u16 b1_send_message(struct capi_ctr *ctr
+       u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+       u16 dlen, retval;
++      spin_lock_irqsave(&card->lock, flags);
+       if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
+               retval = capilib_data_b3_req(&cinfo->ncci_head,
+                                            CAPIMSG_APPID(skb->data),
+                                            CAPIMSG_NCCI(skb->data),
+                                            CAPIMSG_MSGID(skb->data));
+-              if (retval != CAPI_NOERROR) 
++              if (retval != CAPI_NOERROR) {
++                      spin_unlock_irqrestore(&card->lock, flags);
+                       return retval;
++              }
+               dlen = CAPIMSG_DATALEN(skb->data);
+-              spin_lock_irqsave(&card->lock, flags);
+               b1_put_byte(port, SEND_DATA_B3_REQ);
+               b1_put_slice(port, skb->data, len);
+               b1_put_slice(port, skb->data + len, dlen);
+-              spin_unlock_irqrestore(&card->lock, flags);
+       } else {
+-              spin_lock_irqsave(&card->lock, flags);
+               b1_put_byte(port, SEND_MESSAGE);
+               b1_put_slice(port, skb->data, len);
+-              spin_unlock_irqrestore(&card->lock, flags);
+       }
++      spin_unlock_irqrestore(&card->lock, flags);
+       dev_kfree_skb_any(skb);
+       return CAPI_NOERROR;
+@@ -534,17 +536,17 @@ irqreturn_t b1_interrupt(int interrupt, 
+               ApplId = (unsigned) b1_get_word(card->port);
+               MsgLen = b1_get_slice(card->port, card->msgbuf);
+-              spin_unlock_irqrestore(&card->lock, flags);
+               if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
+                       printk(KERN_ERR "%s: incoming packet dropped\n",
+                                       card->name);
++                      spin_unlock_irqrestore(&card->lock, flags);
+               } else {
+                       memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+                       if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
+                               capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
+                                                    CAPIMSG_NCCI(skb->data),
+                                                    CAPIMSG_MSGID(skb->data));
+-
++                      spin_unlock_irqrestore(&card->lock, flags);
+                       capi_ctr_handle_message(ctrl, ApplId, skb);
+               }
+               break;
+@@ -554,21 +556,17 @@ irqreturn_t b1_interrupt(int interrupt, 
+               ApplId = b1_get_word(card->port);
+               NCCI = b1_get_word(card->port);
+               WindowSize = b1_get_word(card->port);
+-              spin_unlock_irqrestore(&card->lock, flags);
+-
+               capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
+-
++              spin_unlock_irqrestore(&card->lock, flags);
+               break;
+       case RECEIVE_FREE_NCCI:
+               ApplId = b1_get_word(card->port);
+               NCCI = b1_get_word(card->port);
+-              spin_unlock_irqrestore(&card->lock, flags);
+-
+               if (NCCI != 0xffffffff)
+                       capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
+-             
++              spin_unlock_irqrestore(&card->lock, flags);
+               break;
+       case RECEIVE_START:
diff --git a/queue-2.6.22/i4l-fix-random-hard-freeze-with-avm-c4-card.patch b/queue-2.6.22/i4l-fix-random-hard-freeze-with-avm-c4-card.patch
new file mode 100644 (file)
index 0000000..f30af9e
--- /dev/null
@@ -0,0 +1,104 @@
+From stable-bounces@linux.kernel.org Thu Oct 18 03:05:10 2007
+From: Karsten Keil <kkeil@suse.de>
+Date: Thu, 18 Oct 2007 03:04:32 -0700
+Subject: i4l: Fix random hard freeze with AVM c4 card
+To: torvalds@linux-foundation.org
+Cc: stable@kernel.org, akpm@linux-foundation.org, rainer.brestan@frequentis.com, kkeil@suse.de, rsc@runtux.com
+Message-ID: <200710181004.l9IA4WtD005633@imap1.linux-foundation.org>
+
+
+From: Karsten Keil <kkeil@suse.de>
+
+patch 1ccfd63367c1a6aaf8b33943f18856dde85f2f0b in mainline.
+
+The patch
+- Includes the call to capilib_data_b3_req in the spinlock. This routine
+  in turn calls the offending mq_enqueue routine that triggered the
+  freeze if not locked.  This should also fix other indicators of
+  incosistent capilib_msgidqueue list, that trigger messages like:
+  Oct  5 03:05:57 BERL0 kernel: kcapi: msgid 3019 ncci 0x30301 not on queue
+  that we saw several times a day (usually several in a row).
+- Fixes all occurrences of c4_dispatch_tx to be called with active
+  spinlock, there were some instances where no lock was active. Mostly
+  these are in very infrequently called routines, so the additional
+  performance penalty is minimal.
+
+Signed-off-by: Karsten Keil <kkeil@suse.de>
+Signed-off-by: Rainer Brestan <rainer.brestan@frequentis.com>
+Signed-off-by: Ralf Schlatterbeck <rsc@runtux.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/isdn/hardware/avm/c4.c |   14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+--- a/drivers/isdn/hardware/avm/c4.c
++++ b/drivers/isdn/hardware/avm/c4.c
+@@ -727,6 +727,7 @@ static void c4_send_init(avmcard *card)
+ {
+       struct sk_buff *skb;
+       void *p;
++      unsigned long flags;
+       skb = alloc_skb(15, GFP_ATOMIC);
+       if (!skb) {
+@@ -744,12 +745,15 @@ static void c4_send_init(avmcard *card)
+       skb_put(skb, (u8 *)p - (u8 *)skb->data);
+       skb_queue_tail(&card->dma->send_queue, skb);
++      spin_lock_irqsave(&card->lock, flags);
+       c4_dispatch_tx(card);
++      spin_unlock_irqrestore(&card->lock, flags);
+ }
+ static int queue_sendconfigword(avmcard *card, u32 val)
+ {
+       struct sk_buff *skb;
++      unsigned long flags;
+       void *p;
+       skb = alloc_skb(3+4, GFP_ATOMIC);
+@@ -766,7 +770,9 @@ static int queue_sendconfigword(avmcard 
+       skb_put(skb, (u8 *)p - (u8 *)skb->data);
+       skb_queue_tail(&card->dma->send_queue, skb);
++      spin_lock_irqsave(&card->lock, flags);
+       c4_dispatch_tx(card);
++      spin_unlock_irqrestore(&card->lock, flags);
+       return 0;
+ }
+@@ -986,7 +992,9 @@ static void c4_release_appl(struct capi_
+       struct sk_buff *skb;
+       void *p;
++      spin_lock_irqsave(&card->lock, flags);
+       capilib_release_appl(&cinfo->ncci_head, appl);
++      spin_unlock_irqrestore(&card->lock, flags);
+       if (ctrl->cnr == card->cardnr) {
+               skb = alloc_skb(7, GFP_ATOMIC);
+@@ -1019,7 +1027,8 @@ static u16 c4_send_message(struct capi_c
+       u16 retval = CAPI_NOERROR;
+       unsigned long flags;
+-      if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
++      spin_lock_irqsave(&card->lock, flags);
++      if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
+               retval = capilib_data_b3_req(&cinfo->ncci_head,
+                                            CAPIMSG_APPID(skb->data),
+                                            CAPIMSG_NCCI(skb->data),
+@@ -1027,10 +1036,9 @@ static u16 c4_send_message(struct capi_c
+       }
+       if (retval == CAPI_NOERROR) {
+               skb_queue_tail(&card->dma->send_queue, skb);
+-              spin_lock_irqsave(&card->lock, flags);
+               c4_dispatch_tx(card);
+-              spin_unlock_irqrestore(&card->lock, flags);
+       }
++      spin_unlock_irqrestore(&card->lock, flags);
+       return retval;
+ }
index 31478dd94ff81a7b36189c8e411f63fe5cfcb468..8ce5753d9b1eb2795ee70d41b806720a9d4f1166 100644 (file)
@@ -6,3 +6,7 @@ alsa-hda-codec-add-array-terminator-for-dmic-in-stac-codec.patch
 forcedeth-msi-bugfix.patch
 hptiop-avoid-buffer-overflow-when-returning-sense-data.patch
 fix-param_sysfs_builtin-name-length-check.patch
+usb-usbserial-fix-potential-deadlock-between-write-and-irq.patch
+usb-mutual-exclusion-for-ehci-init-and-port-resets.patch
+i4l-fix-random-hard-freeze-with-avm-c4-card.patch
+i4l-fix-random-freezes-with-avm-b1-drivers.patch
diff --git a/queue-2.6.22/usb-mutual-exclusion-for-ehci-init-and-port-resets.patch b/queue-2.6.22/usb-mutual-exclusion-for-ehci-init-and-port-resets.patch
new file mode 100644 (file)
index 0000000..715cd3a
--- /dev/null
@@ -0,0 +1,120 @@
+From gregkh@suse.de Fri Oct 12 15:30:23 2007
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 12 Oct 2007 15:19:14 -0700
+Subject: USB: mutual exclusion for EHCI init and port resets
+To: linux-usb-devel@lists.sourceforge.net
+Cc: Alan Stern <stern@rowland.harvard.edu>, David Miller <davem@davemloft.net>, Dely L Sy <dely.l.sy@intel.com>, Greg Kroah-Hartman <gregkh@suse.de>
+Message-ID: <1192227560-4852-136-git-send-email-gregkh@suse.de>
+
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+patch 32fe01985aa2cb2562f6fc171e526e279abe10db in mainline.
+
+This patch (as999) fixes a problem that sometimes shows up when host
+controller driver modules are loaded in the wrong order.  If ehci-hcd
+happens to initialize an EHCI controller while the companion OHCI or
+UHCI controller is in the middle of a port reset, the reset can fail
+and the companion may get very confused.  The patch adds an
+rw-semaphore and uses it to keep EHCI initialization and port resets
+mutually exclusive.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Acked-by: David Brownell <david-b@pacbell.net>
+Cc: David Miller <davem@davemloft.net>
+Cc: Dely L Sy <dely.l.sy@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/core/hcd.h      |    8 +++++++-
+ drivers/usb/core/hub.c      |   15 ++++++++++++++-
+ drivers/usb/host/ehci-hcd.c |    8 ++++++++
+ 3 files changed, 29 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -19,6 +19,8 @@
+ #ifdef __KERNEL__
++#include <linux/rwsem.h>
++
+ /* This file contains declarations of usbcore internals that are mostly
+  * used or exposed by Host Controller Drivers.
+  */
+@@ -464,5 +466,9 @@ static inline void usbmon_urb_complete(s
+               : (in_interrupt () ? "in_interrupt" : "can sleep"))
+-#endif /* __KERNEL__ */
++/* This rwsem is for use only by the hub driver and ehci-hcd.
++ * Nobody else should touch it.
++ */
++extern struct rw_semaphore ehci_cf_port_reset_rwsem;
++#endif /* __KERNEL__ */
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -117,6 +117,12 @@ MODULE_PARM_DESC(use_both_schemes,
+               "try the other device initialization scheme if the "
+               "first one fails");
++/* Mutual exclusion for EHCI CF initialization.  This interferes with
++ * port reset on some companion controllers.
++ */
++DECLARE_RWSEM(ehci_cf_port_reset_rwsem);
++EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
++
+ static inline char *portspeed(int portstatus)
+ {
+@@ -1513,6 +1519,11 @@ static int hub_port_reset(struct usb_hub
+ {
+       int i, status;
++      /* Block EHCI CF initialization during the port reset.
++       * Some companion controllers don't like it when they mix.
++       */
++      down_read(&ehci_cf_port_reset_rwsem);
++
+       /* Reset the port */
+       for (i = 0; i < PORT_RESET_TRIES; i++) {
+               status = set_port_feature(hub->hdev,
+@@ -1543,7 +1554,7 @@ static int hub_port_reset(struct usb_hub
+                       usb_set_device_state(udev, status
+                                       ? USB_STATE_NOTATTACHED
+                                       : USB_STATE_DEFAULT);
+-                      return status;
++                      goto done;
+               }
+               dev_dbg (hub->intfdev,
+@@ -1556,6 +1567,8 @@ static int hub_port_reset(struct usb_hub
+               "Cannot enable port %i.  Maybe the USB cable is bad?\n",
+               port1);
++ done:
++      up_read(&ehci_cf_port_reset_rwsem);
+       return status;
+ }
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -566,10 +566,18 @@ static int ehci_run (struct usb_hcd *hcd
+        * are explicitly handed to companion controller(s), so no TT is
+        * involved with the root hub.  (Except where one is integrated,
+        * and there's no companion controller unless maybe for USB OTG.)
++       *
++       * Turning on the CF flag will transfer ownership of all ports
++       * from the companions to the EHCI controller.  If any of the
++       * companions are in the middle of a port reset at the time, it
++       * could cause trouble.  Write-locking ehci_cf_port_reset_rwsem
++       * guarantees that no resets are in progress.
+        */
++      down_write(&ehci_cf_port_reset_rwsem);
+       hcd->state = HC_STATE_RUNNING;
+       ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+       ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
++      up_write(&ehci_cf_port_reset_rwsem);
+       temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
+       ehci_info (ehci,
diff --git a/queue-2.6.22/usb-usbserial-fix-potential-deadlock-between-write-and-irq.patch b/queue-2.6.22/usb-usbserial-fix-potential-deadlock-between-write-and-irq.patch
new file mode 100644 (file)
index 0000000..c8b1a52
--- /dev/null
@@ -0,0 +1,46 @@
+From acd2a847e7fee7df11817f67dba75a2802793e5d Mon Sep 17 00:00:00 2001
+From: Jiri Kosina <jkosina@suse.cz>
+Date: Sat, 20 Oct 2007 00:05:19 +0200
+Subject: USB: usbserial - fix potential deadlock between write() and IRQ
+Message-ID: <20071102152622.GB7279@kroah.com>
+
+From: Jiri Kosina <jkosina@suse.cz>
+
+patch acd2a847e7fee7df11817f67dba75a2802793e5d in mainline.
+
+USB: usbserial - fix potential deadlock between write() and IRQ
+
+usb_serial_generic_write() doesn't disable interrupts when taking port->lock,
+and could therefore deadlock with usb_serial_generic_read_bulk_callback()
+being called from interrupt, taking the same lock. Fix it.
+
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Acked-by: Larry Finger <larry.finger@lwfinger.net>
+Cc: Marcin Slusarz <marcin.slusarz@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/generic.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/serial/generic.c
++++ b/drivers/usb/serial/generic.c
+@@ -190,14 +190,15 @@ int usb_serial_generic_write(struct usb_
+       /* only do something if we have a bulk out endpoint */
+       if (serial->num_bulk_out) {
+-              spin_lock_bh(&port->lock);
++              unsigned long flags;
++              spin_lock_irqsave(&port->lock, flags);
+               if (port->write_urb_busy) {
+-                      spin_unlock_bh(&port->lock);
++                      spin_unlock_irqrestore(&port->lock, flags);
+                       dbg("%s - already writing", __FUNCTION__);
+                       return 0;
+               }
+               port->write_urb_busy = 1;
+-              spin_unlock_bh(&port->lock);
++              spin_unlock_irqrestore(&port->lock, flags);
+               count = (count > port->bulk_out_size) ? port->bulk_out_size : count;