From: Greg Kroah-Hartman Date: Mon, 19 Nov 2007 17:28:20 +0000 (-0800) Subject: more 2.6.22 patches X-Git-Tag: v2.6.22.14~20 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=38f540a855e628e420b13ac76637b6abd669681c;p=thirdparty%2Fkernel%2Fstable-queue.git more 2.6.22 patches --- 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 index 00000000000..a68649a0a5a --- /dev/null +++ b/queue-2.6.22/i4l-fix-random-freezes-with-avm-b1-drivers.patch @@ -0,0 +1,136 @@ +From stable-bounces@linux.kernel.org Thu Oct 18 03:05:05 2007 +From: Karsten Keil +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 + +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 +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..f30af9e9ad4 --- /dev/null +++ b/queue-2.6.22/i4l-fix-random-hard-freeze-with-avm-c4-card.patch @@ -0,0 +1,104 @@ +From stable-bounces@linux.kernel.org Thu Oct 18 03:05:10 2007 +From: Karsten Keil +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 + +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 +Signed-off-by: Rainer Brestan +Signed-off-by: Ralf Schlatterbeck +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } + diff --git a/queue-2.6.22/series b/queue-2.6.22/series index 31478dd94ff..8ce5753d9b1 100644 --- a/queue-2.6.22/series +++ b/queue-2.6.22/series @@ -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 index 00000000000..715cd3a334b --- /dev/null +++ b/queue-2.6.22/usb-mutual-exclusion-for-ehci-init-and-port-resets.patch @@ -0,0 +1,120 @@ +From gregkh@suse.de Fri Oct 12 15:30:23 2007 +From: Alan Stern +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 , David Miller , Dely L Sy , Greg Kroah-Hartman +Message-ID: <1192227560-4852-136-git-send-email-gregkh@suse.de> + + +From: Alan Stern + +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 +Acked-by: David Brownell +Cc: David Miller +Cc: Dely L Sy +Signed-off-by: Greg Kroah-Hartman +--- + 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 ++ + /* 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 index 00000000000..c8b1a5290c3 --- /dev/null +++ b/queue-2.6.22/usb-usbserial-fix-potential-deadlock-between-write-and-irq.patch @@ -0,0 +1,46 @@ +From acd2a847e7fee7df11817f67dba75a2802793e5d Mon Sep 17 00:00:00 2001 +From: Jiri Kosina +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 + +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 +Acked-by: Larry Finger +Cc: Marcin Slusarz +Signed-off-by: Greg Kroah-Hartman + +--- + 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; +