On 11/17/2004 21:41, Gilles Espinasse wrote:
>Well
>thank to inform usb.
>
>It is closed for you but not for us.
>Did you have a link for your patch
>
>
I thought it would be appropriate to send the patch to usb-users list.
However, it seems my mail didn't come through so I posted it there once
more. Hopefully it will show up in archives shortly.
I guess it won't hurt to post the patch here as well, so here it goes
(seet attachment). The patch was made against the version of uhci-hcd
driver found in 2.6.9 kernel.
Andrej
P.S. Because I'm not sure how this mailing list handles attachments, the
copy of patch is also pasted below.
PIIX3-bugfix.patch
<--------cut-here-------->
diff -Naur linux-2.6.9/drivers/usb/host/uhci-hcd.c
linux-2.6.9-mod/drivers/usb/host/uhci-hcd.c
--- linux-2.6.9/drivers/usb/host/uhci-hcd.c 2004-10-18
23:55:07.000000000 +0200
+++ linux-2.6.9-mod/drivers/usb/host/uhci-hcd.c 2004-11-17
19:11:05.000000000 +0100
@@ -27,6 +27,8 @@
* - working around the horridness of the rest
*/
+#define PIIX3_BUGFIX
+
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
@@ -604,6 +606,9 @@
urbp->inserttime = jiffies;
urbp->fsbrtime = jiffies;
urbp->urb = urb;
+#ifdef PIIX3_BUGFIX
+ urbp->last_element = NULL;
+#endif
INIT_LIST_HEAD(&urbp->td_list);
INIT_LIST_HEAD(&urbp->queue_list);
@@ -1473,6 +1478,73 @@
spin_unlock(&urb->lock);
}
+#ifdef PIIX3_BUGFIX
+/* Checks whether URB's qh->element points to an active td and fixes it
+ * when necessary. Gives HC a chance to correct this state by ignoring
+ * it for the first time
+ *
+ * Note: URB lock has to be locked before passing URB to this function
+ */
+static void uhci_check_qh_element(struct uhci_hcd *hcd, struct urb* urb) {
+ struct urb_priv *urbp;
+ struct uhci_td *td;
+ struct uhci_td *element_td;
+ dma_addr_t dma_handle;
+ struct list_head *head;
+ __le32 element;
+ + if (urb->status != -EINPROGRESS) /* URB dequeued, we've got
nothing to do */
+ return;
+ + urbp = (struct urb_priv *)urb->hcpriv;
+ element = urbp->qh->element;
+ + if (element & UHCI_PTR_TERM)
+ return;
+ + /* CHECK ME: what can we do when element points to QH? I
guess that nothing. */
+ if (element & UHCI_PTR_QH)
+ return;
+ + /* convert dma_handle to td's addresss */
+ /* CHECK ME: this is awkward way to do this, anything simpler? */
+ dma_handle = le32_to_cpu(element & ~ UHCI_PTR_BITS);
+
+ element_td = NULL;
+ head = &urbp->td_list;
+ list_for_each_entry(td, head, list) {
+ if (td->dma_handle == dma_handle) {
+ element_td = td;
+ break;
+ }
+ }
+ + /* reverse mapping failed, bail out */
+ if (element_td == NULL)
+ return;
+ + /* check qh->element's state */
+ if (!(td_status(element_td) & TD_CTRL_ACTIVE)) {
+ /* this is first time we observed this state, we give HC a
time to take care of it */
+ if (urbp->last_element != element_td) {
+ urbp->last_element = element_td;
+ /* HC haven't fixed the intermediate state since last check,
we'll help it */
+ } else { + /* set qh->element to next linked td */
+ if (debug > 2)
+ dev_dbg(uhci_dev(hcd), "Setting qh->element to td=%x
(was %x) for URB %p\n",element_td->link,element,urb);
+ + urbp->qh->element = element_td->link;
+ urbp->last_element = NULL;
+ } + } else {
+ urbp->last_element = NULL;
+ }
+
+ return;
+}
+#endif
+
static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
{
struct list_head *head, *tmp;
@@ -1629,6 +1701,13 @@
tmp = tmp->next;
spin_lock(&u->lock);
+ +#ifdef PIIX3_BUGFIX
+ /* Check if the URB's qh->element points to an active td
+ * and fix it if necessary
+ */
+ uhci_check_qh_element(uhci, u);
+#endif
/* Check if the FSBR timed out */
if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies,
up->fsbrtime + IDLE_TIMEOUT))
diff -Naur linux-2.6.9/drivers/usb/host/uhci-hcd.h
linux-2.6.9-mod/drivers/usb/host/uhci-hcd.h
--- linux-2.6.9/drivers/usb/host/uhci-hcd.h 2004-10-18
23:54:55.000000000 +0200
+++ linux-2.6.9-mod/drivers/usb/host/uhci-hcd.h 2004-11-17
12:51:54.000000000 +0100
@@ -394,6 +394,11 @@
unsigned long inserttime; /* In jiffies */
unsigned long fsbrtime; /* In jiffies */
+ +#ifdef PIIX3_BUGFIX + struct uhci_td *last_element; /* Set to
the last observed inactive qh->element
+ * or to NULL if qh->element was active */
+#endif
struct list_head queue_list; /* P: uhci->frame_list_lock */
};
<--------cut-here-------->
-- Attached file included as plaintext by Listar --
-- File: PIIX3-bugfix.patch
diff -Naur linux-2.6.9/drivers/usb/host/uhci-hcd.c
linux-2.6.9-mod/drivers/usb/host/uhci-hcd.c
--- linux-2.6.9/drivers/usb/host/uhci-hcd.c 2004-10-18 23:55:07.000000000
+0200
+++ linux-2.6.9-mod/drivers/usb/host/uhci-hcd.c 2004-11-17 19:11:05.000000000
+0100
@@ -27,6 +27,8 @@
* - working around the horridness of the rest
*/
+#define PIIX3_BUGFIX
+
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
@@ -604,6 +606,9 @@
urbp->inserttime = jiffies;
urbp->fsbrtime = jiffies;
urbp->urb = urb;
+#ifdef PIIX3_BUGFIX
+ urbp->last_element = NULL;
+#endif
INIT_LIST_HEAD(&urbp->td_list);
INIT_LIST_HEAD(&urbp->queue_list);
@@ -1473,6 +1478,73 @@
spin_unlock(&urb->lock);
}
+#ifdef PIIX3_BUGFIX
+/* Checks whether URB's qh->element points to an active td and fixes it
+ * when necessary. Gives HC a chance to correct this state by ignoring
+ * it for the first time
+ *
+ * Note: URB lock has to be locked before passing URB to this function
+ */
+static void uhci_check_qh_element(struct uhci_hcd *hcd, struct urb* urb) {
+ struct urb_priv *urbp;
+ struct uhci_td *td;
+ struct uhci_td *element_td;
+ dma_addr_t dma_handle;
+ struct list_head *head;
+ __le32 element;
+
+ if (urb->status != -EINPROGRESS) /* URB dequeued, we've got
nothing to do */
+ return;
+
+ urbp = (struct urb_priv *)urb->hcpriv;
+ element = urbp->qh->element;
+
+ if (element & UHCI_PTR_TERM)
+ return;
+
+ /* CHECK ME: what can we do when element points to QH? I guess that
nothing. */
+ if (element & UHCI_PTR_QH)
+ return;
+
+ /* convert dma_handle to td's addresss */
+ /* CHECK ME: this is awkward way to do this, anything simpler? */
+ dma_handle = le32_to_cpu(element & ~ UHCI_PTR_BITS);
+
+ element_td = NULL;
+ head = &urbp->td_list;
+ list_for_each_entry(td, head, list) {
+ if (td->dma_handle == dma_handle) {
+ element_td = td;
+ break;
+ }
+ }
+
+ /* reverse mapping failed, bail out */
+ if (element_td == NULL)
+ return;
+
+ /* check qh->element's state */
+ if (!(td_status(element_td) & TD_CTRL_ACTIVE)) {
+ /* this is first time we observed this state, we give HC a time
to take care of it */
+ if (urbp->last_element != element_td) {
+ urbp->last_element = element_td;
+ /* HC haven't fixed the intermediate state since last check,
we'll help it */
+ } else {
+ /* set qh->element to next linked td */
+ if (debug > 2)
+ dev_dbg(uhci_dev(hcd), "Setting qh->element to
td=%x (was %x) for URB %p\n",element_td->link,element,urb);
+
+ urbp->qh->element = element_td->link;
+ urbp->last_element = NULL;
+ }
+ } else {
+ urbp->last_element = NULL;
+ }
+
+ return;
+}
+#endif
+
static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
{
struct list_head *head, *tmp;
@@ -1629,6 +1701,13 @@
tmp = tmp->next;
spin_lock(&u->lock);
+
+#ifdef PIIX3_BUGFIX
+ /* Check if the URB's qh->element points to an active td
+ * and fix it if necessary
+ */
+ uhci_check_qh_element(uhci, u);
+#endif
/* Check if the FSBR timed out */
if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies,
up->fsbrtime + IDLE_TIMEOUT))
diff -Naur linux-2.6.9/drivers/usb/host/uhci-hcd.h
linux-2.6.9-mod/drivers/usb/host/uhci-hcd.h
--- linux-2.6.9/drivers/usb/host/uhci-hcd.h 2004-10-18 23:54:55.000000000
+0200
+++ linux-2.6.9-mod/drivers/usb/host/uhci-hcd.h 2004-11-17 12:51:54.000000000
+0100
@@ -394,6 +394,11 @@
unsigned long inserttime; /* In jiffies */
unsigned long fsbrtime; /* In jiffies */
+
+#ifdef PIIX3_BUGFIX
+ struct uhci_td *last_element; /* Set to the last observed inactive
qh->element
+ * or to NULL if qh->element was active
*/
+#endif
struct list_head queue_list; /* P: uhci->frame_list_lock */
};
Liste de diffusion modem ALCATEL SpeedTouch USB
Pour se d�sinscrire : mailto:[EMAIL PROTECTED]