[PATCH 004/148] USB: UHCI: acquire spinlock before calling start_rh()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>

This patch (as1392) fixes a bug in uhci-hcd: The start_rh() routine is
supposed to be called with the private spinlock held.  If an IRQ comes
in at just the wrong time, the driver will think the controller has
died when in fact it simply hasn't start yet.

The patch also addresses some issues that may prevent an URB from
being unlinked after the controller has stopped.  This is an abnormal
occurrence (ordinarily the controller stops only when the entire bus
is suspended and hence there are no active URBs), so the pathways
haven't gotten much testing.  These two changes may be a little more
than is strictly necessary, but clearly they won't hurt.

Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
---
 drivers/usb/host/uhci-hcd.c |    2 ++
 drivers/usb/host/uhci-q.c   |    4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 6637e52..d1dce21 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -691,7 +691,9 @@ static int uhci_start(struct usb_hcd *hcd)
 
 	configure_hc(uhci);
 	uhci->is_initialized = 1;
+	spin_lock_irq(&uhci->lock);
 	start_rh(uhci);
+	spin_unlock_irq(&uhci->lock);
 	return 0;
 
 /*
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index acd582c..d3ade40 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -565,7 +565,7 @@ static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 	qh->unlink_frame = uhci->frame_number;
 
 	/* Force an interrupt so we know when the QH is fully unlinked */
-	if (list_empty(&uhci->skel_unlink_qh->node))
+	if (list_empty(&uhci->skel_unlink_qh->node) || uhci->is_stopped)
 		uhci_set_next_interrupt(uhci);
 
 	/* Move the QH from its old list to the end of the unlinking list */
@@ -1667,7 +1667,7 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
 			qh->advance_jiffies = jiffies;
 			goto done;
 		}
-		ret = 0;
+		ret = uhci->is_stopped;
 	}
 
 	/* The queue hasn't advanced; check for timeout */
-- 
1.7.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux