aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2008-08-14 06:58:32 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2008-08-14 06:58:32 -0700
commit5241b373252bbdf2e4c69fd6f5b1bb5a40cb85a2 (patch)
treed8f317fbebd3470e96b5e9f520cb7595210da583 /usb
parenteaa5df2a6d6f9b87334b5724bc4eb1eb75fc260e (diff)
downloadpatches-5241b373252bbdf2e4c69fd6f5b1bb5a40cb85a2.tar.gz
2.6.27-rc3-git2 resync
Diffstat (limited to 'usb')
-rw-r--r--usb/drivers-usb-class-usblp.c-adjust-error-handling-code.patch88
-rw-r--r--usb/ub-remove-sg_stat.patch37
-rw-r--r--usb/usb-extend-poisoning-to-anchors.patch158
-rw-r--r--usb/usb-kill-urbs-permanently.patch120
4 files changed, 403 insertions, 0 deletions
diff --git a/usb/drivers-usb-class-usblp.c-adjust-error-handling-code.patch b/usb/drivers-usb-class-usblp.c-adjust-error-handling-code.patch
new file mode 100644
index 00000000000000..8cc18ed4560cea
--- /dev/null
+++ b/usb/drivers-usb-class-usblp.c-adjust-error-handling-code.patch
@@ -0,0 +1,88 @@
+From linux-usb-owner@vger.kernel.org Thu Jul 31 10:35:53 2008
+From: Julia Lawall <julia@diku.dk>
+Date: Wed, 16 Jul 2008 18:00:42 +0200 (CEST)
+Subject: [PATCH retry] drivers/usb/class/usblp.c: adjust error handling code
+To: Oliver Neukum <oliver@neukum.org>
+Cc: zaitcev@redhat.com, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, kernel-janitors@vger.kernel.org
+Message-ID: <Pine.LNX.4.64.0807161758520.28783@ask.diku.dk>
+
+
+From: Julia Lawall <julia@diku.dk>
+
+In this code, it is possible to tell statically whether usblp will be NULL
+in the error handling code.
+
+Oliver Neukum suggested to make a goto to the final return rather than
+return directly.
+
+The semantic match that finds this problem is as follows:
+(http://www.emn.fr/x-info/coccinelle/)
+
+// <smpl>
+@@
+identifier f,err,l,l1;
+type T;
+expression x,E;
+statement S;
+@@
+
+x = NULL
+... when != goto l1;
+* x = f(...)
+... when != x
+err = E;
+goto l;
+...
+* if (x != NULL)
+ S
+return err;
+// </smpl>
+
+Signed-off-by: Julia Lawall <julia@diku.dk>
+Cc: Pete Zaitcev <zaitcev@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/class/usblp.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/class/usblp.c
++++ b/drivers/usb/class/usblp.c
+@@ -1076,15 +1076,16 @@ static int usblp_probe(struct usb_interf
+ const struct usb_device_id *id)
+ {
+ struct usb_device *dev = interface_to_usbdev (intf);
+- struct usblp *usblp = NULL;
++ struct usblp *usblp;
+ int protocol;
+ int retval;
+
+ /* Malloc and start initializing usblp structure so we can use it
+ * directly. */
+- if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) {
++ usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL);
++ if (!usblp) {
+ retval = -ENOMEM;
+- goto abort;
++ goto abort_ret;
+ }
+ usblp->dev = dev;
+ mutex_init(&usblp->wmut);
+@@ -1179,12 +1180,11 @@ abort_intfdata:
+ usb_set_intfdata (intf, NULL);
+ device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
+ abort:
+- if (usblp) {
+- kfree(usblp->readbuf);
+- kfree(usblp->statusbuf);
+- kfree(usblp->device_id_string);
+- kfree(usblp);
+- }
++ kfree(usblp->readbuf);
++ kfree(usblp->statusbuf);
++ kfree(usblp->device_id_string);
++ kfree(usblp);
++abort_ret:
+ return retval;
+ }
+
diff --git a/usb/ub-remove-sg_stat.patch b/usb/ub-remove-sg_stat.patch
new file mode 100644
index 00000000000000..efd29f107e3e90
--- /dev/null
+++ b/usb/ub-remove-sg_stat.patch
@@ -0,0 +1,37 @@
+From zaitcev@redhat.com Wed Aug 6 15:15:12 2008
+From: Pete Zaitcev <zaitcev@redhat.com>
+Date: Mon, 4 Aug 2008 17:15:40 -0600
+Subject: ub: remove sg_stat
+To: greg@kroah.com
+Cc: linux-usb@vger.kernel.org
+Message-ID: <20080804171540.36698160.zaitcev@redhat.com>
+
+
+Remove forgotten code related to sg_stat[].
+
+Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/block/ub.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/drivers/block/ub.c
++++ b/drivers/block/ub.c
+@@ -349,8 +349,6 @@ struct ub_dev {
+
+ struct work_struct reset_work;
+ wait_queue_head_t reset_wait;
+-
+- int sg_stat[6];
+ };
+
+ /*
+@@ -685,7 +683,6 @@ static int ub_request_fn_1(struct ub_lun
+ goto drop;
+ }
+ urq->nsg = n_elem;
+- sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
+
+ if (blk_pc_request(rq)) {
+ ub_cmd_build_packet(sc, lun, cmd, urq);
diff --git a/usb/usb-extend-poisoning-to-anchors.patch b/usb/usb-extend-poisoning-to-anchors.patch
new file mode 100644
index 00000000000000..67fa887d000c03
--- /dev/null
+++ b/usb/usb-extend-poisoning-to-anchors.patch
@@ -0,0 +1,158 @@
+From oliver@neukum.org Thu Jul 31 10:29:55 2008
+From: Oliver Neukum <oliver@neukum.org>
+Date: Tue, 29 Jul 2008 16:18:47 +0200
+Subject: USB: extend poisoning to anchors
+To: Greg KH <greg@kroah.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>, linux-usb@vger.kernel.org
+Message-ID: <200807291618.48198.oliver@neukum.org>
+Content-Disposition: inline
+
+
+this extends the poisoning concept to anchors. This way poisoning
+will work with fire and forget drivers.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/urb.c | 57 +++++++++++++++++++++++++++++++++++++++++--------
+ include/linux/usb.h | 2 +
+ 2 files changed, 50 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -10,6 +10,8 @@
+
+ #define to_urb(d) container_of(d, struct urb, kref)
+
++static DEFINE_SPINLOCK(usb_reject_lock);
++
+ static void urb_destroy(struct kref *kref)
+ {
+ struct urb *urb = to_urb(kref);
+@@ -127,6 +129,13 @@ void usb_anchor_urb(struct urb *urb, str
+ usb_get_urb(urb);
+ list_add_tail(&urb->anchor_list, &anchor->urb_list);
+ urb->anchor = anchor;
++
++ if (unlikely(anchor->poisoned)) {
++ spin_lock(&usb_reject_lock);
++ urb->reject++;
++ spin_unlock(&usb_reject_lock);
++ }
++
+ spin_unlock_irqrestore(&anchor->lock, flags);
+ }
+ EXPORT_SYMBOL_GPL(usb_anchor_urb);
+@@ -522,7 +531,6 @@ int usb_unlink_urb(struct urb *urb)
+ }
+ EXPORT_SYMBOL_GPL(usb_unlink_urb);
+
+-static DEFINE_MUTEX(usb_reject_mutex);
+ /**
+ * usb_kill_urb - cancel a transfer request and wait for it to finish
+ * @urb: pointer to URB describing a previously submitted request,
+@@ -548,16 +556,16 @@ void usb_kill_urb(struct urb *urb)
+ might_sleep();
+ if (!(urb && urb->dev && urb->ep))
+ return;
+- mutex_lock(&usb_reject_mutex);
++ spin_lock_irq(&usb_reject_lock);
+ ++urb->reject;
+- mutex_unlock(&usb_reject_mutex);
++ spin_unlock_irq(&usb_reject_lock);
+
+ usb_hcd_unlink_urb(urb, -ENOENT);
+ wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
+
+- mutex_lock(&usb_reject_mutex);
++ spin_lock_irq(&usb_reject_lock);
+ --urb->reject;
+- mutex_unlock(&usb_reject_mutex);
++ spin_unlock_irq(&usb_reject_lock);
+ }
+ EXPORT_SYMBOL_GPL(usb_kill_urb);
+
+@@ -586,9 +594,9 @@ void usb_poison_urb(struct urb *urb)
+ might_sleep();
+ if (!(urb && urb->dev && urb->ep))
+ return;
+- mutex_lock(&usb_reject_mutex);
++ spin_lock_irq(&usb_reject_lock);
+ ++urb->reject;
+- mutex_unlock(&usb_reject_mutex);
++ spin_unlock_irq(&usb_reject_lock);
+
+ usb_hcd_unlink_urb(urb, -ENOENT);
+ wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
+@@ -597,12 +605,14 @@ EXPORT_SYMBOL_GPL(usb_poison_urb);
+
+ void usb_unpoison_urb(struct urb *urb)
+ {
++ unsigned long flags;
++
+ if (!urb)
+ return;
+
+- mutex_lock(&usb_reject_mutex);
++ spin_lock_irqsave(&usb_reject_lock, flags);
+ --urb->reject;
+- mutex_unlock(&usb_reject_mutex);
++ spin_unlock_irqrestore(&usb_reject_lock, flags);
+ }
+ EXPORT_SYMBOL_GPL(usb_unpoison_urb);
+
+@@ -633,6 +643,35 @@ void usb_kill_anchored_urbs(struct usb_a
+ }
+ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
+
++
++/**
++ * usb_poison_anchored_urbs - cease all traffic from an anchor
++ * @anchor: anchor the requests are bound to
++ *
++ * this allows all outstanding URBs to be poisoned starting
++ * from the back of the queue. Newly added URBs will also be
++ * poisoned
++ */
++void usb_poison_anchored_urbs(struct usb_anchor *anchor)
++{
++ struct urb *victim;
++
++ spin_lock_irq(&anchor->lock);
++ anchor->poisoned = 1;
++ while (!list_empty(&anchor->urb_list)) {
++ victim = list_entry(anchor->urb_list.prev, struct urb,
++ anchor_list);
++ /* we must make sure the URB isn't freed before we kill it*/
++ usb_get_urb(victim);
++ spin_unlock_irq(&anchor->lock);
++ /* this will unanchor the URB */
++ usb_poison_urb(victim);
++ usb_put_urb(victim);
++ spin_lock_irq(&anchor->lock);
++ }
++ spin_unlock_irq(&anchor->lock);
++}
++EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs);
+ /**
+ * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse
+ * @anchor: anchor the requests are bound to
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1132,6 +1132,7 @@ struct usb_anchor {
+ struct list_head urb_list;
+ wait_queue_head_t wait;
+ spinlock_t lock;
++ unsigned int poisoned:1;
+ };
+
+ static inline void init_usb_anchor(struct usb_anchor *anchor)
+@@ -1459,6 +1460,7 @@ extern void usb_kill_urb(struct urb *urb
+ extern void usb_poison_urb(struct urb *urb);
+ extern void usb_unpoison_urb(struct urb *urb);
+ extern void usb_kill_anchored_urbs(struct usb_anchor *anchor);
++extern void usb_poison_anchored_urbs(struct usb_anchor *anchor);
+ extern void usb_unlink_anchored_urbs(struct usb_anchor *anchor);
+ extern void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor);
+ extern void usb_unanchor_urb(struct urb *urb);
diff --git a/usb/usb-kill-urbs-permanently.patch b/usb/usb-kill-urbs-permanently.patch
new file mode 100644
index 00000000000000..8d2e152f86710a
--- /dev/null
+++ b/usb/usb-kill-urbs-permanently.patch
@@ -0,0 +1,120 @@
+From oliver@neukum.org Thu Jul 31 10:27:14 2008
+From: Oliver Neukum <oliver@neukum.org>
+Date: Tue, 29 Jul 2008 15:26:15 +0200
+Subject: USB: kill URBs permanently
+To: Greg KH <greg@kroah.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>, linux-usb@vger.kernel.org
+Message-ID: <200807291526.16217.oliver@neukum.org>
+Content-Disposition: inline
+
+
+looking at usb_kill_urb() it seems to me that it is unnecessarily lenient.
+In the use case of disconnect() you never want to use the URB again
+(for the same device) But leaving urb->reject elevated will make it easier
+to avoid races between read/write and disconnect.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/core/urb.c | 56 +++++++++++++++++++++++++++++++++++++++++++------
+ include/linux/usb.h | 2 +
+ 2 files changed, 52 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -522,6 +522,7 @@ int usb_unlink_urb(struct urb *urb)
+ }
+ EXPORT_SYMBOL_GPL(usb_unlink_urb);
+
++static DEFINE_MUTEX(usb_reject_mutex);
+ /**
+ * usb_kill_urb - cancel a transfer request and wait for it to finish
+ * @urb: pointer to URB describing a previously submitted request,
+@@ -544,25 +545,68 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb);
+ */
+ void usb_kill_urb(struct urb *urb)
+ {
+- static DEFINE_MUTEX(reject_mutex);
+-
+ might_sleep();
+ if (!(urb && urb->dev && urb->ep))
+ return;
+- mutex_lock(&reject_mutex);
++ mutex_lock(&usb_reject_mutex);
+ ++urb->reject;
+- mutex_unlock(&reject_mutex);
++ mutex_unlock(&usb_reject_mutex);
+
+ usb_hcd_unlink_urb(urb, -ENOENT);
+ wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
+
+- mutex_lock(&reject_mutex);
++ mutex_lock(&usb_reject_mutex);
+ --urb->reject;
+- mutex_unlock(&reject_mutex);
++ mutex_unlock(&usb_reject_mutex);
+ }
+ EXPORT_SYMBOL_GPL(usb_kill_urb);
+
+ /**
++ * usb_poison_urb - reliably kill a transfer and prevent further use of an URB
++ * @urb: pointer to URB describing a previously submitted request,
++ * may be NULL
++ *
++ * This routine cancels an in-progress request. It is guaranteed that
++ * upon return all completion handlers will have finished and the URB
++ * will be totally idle and cannot be reused. These features make
++ * this an ideal way to stop I/O in a disconnect() callback.
++ * If the request has not already finished or been unlinked
++ * the completion handler will see urb->status == -ENOENT.
++ *
++ * After and while the routine runs, attempts to resubmit the URB will fail
++ * with error -EPERM. Thus even if the URB's completion handler always
++ * tries to resubmit, it will not succeed and the URB will become idle.
++ *
++ * This routine may not be used in an interrupt context (such as a bottom
++ * half or a completion handler), or when holding a spinlock, or in other
++ * situations where the caller can't schedule().
++ */
++void usb_poison_urb(struct urb *urb)
++{
++ might_sleep();
++ if (!(urb && urb->dev && urb->ep))
++ return;
++ mutex_lock(&usb_reject_mutex);
++ ++urb->reject;
++ mutex_unlock(&usb_reject_mutex);
++
++ usb_hcd_unlink_urb(urb, -ENOENT);
++ wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
++}
++EXPORT_SYMBOL_GPL(usb_poison_urb);
++
++void usb_unpoison_urb(struct urb *urb)
++{
++ if (!urb)
++ return;
++
++ mutex_lock(&usb_reject_mutex);
++ --urb->reject;
++ mutex_unlock(&usb_reject_mutex);
++}
++EXPORT_SYMBOL_GPL(usb_unpoison_urb);
++
++/**
+ * usb_kill_anchored_urbs - cancel transfer requests en masse
+ * @anchor: anchor the requests are bound to
+ *
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1456,6 +1456,8 @@ extern struct urb *usb_get_urb(struct ur
+ extern int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
+ extern int usb_unlink_urb(struct urb *urb);
+ extern void usb_kill_urb(struct urb *urb);
++extern void usb_poison_urb(struct urb *urb);
++extern void usb_unpoison_urb(struct urb *urb);
+ extern void usb_kill_anchored_urbs(struct usb_anchor *anchor);
+ extern void usb_unlink_anchored_urbs(struct usb_anchor *anchor);
+ extern void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor);