From: David Brownell <[EMAIL PROTECTED]>
   Date: Thu, 05 Dec 2002 20:55:23 -0800

    >      EHCI is problematic here, as it does the URB
    >      work in a tasklet :(  we need to decide whether
    >      we can move the normal URB completion back into
    >      the hw interrupt handler or not
   
   It's worked fine so far ... but simpler would be fine too,
   and I'd take a patch for this.
   
Here ya go:

--- ./drivers/usb/host/ehci.h.~1~       Mon Dec  9 14:06:42 2002
+++ ./drivers/usb/host/ehci.h   Mon Dec  9 14:06:50 2002
@@ -65,9 +65,6 @@ struct ehci_hcd {                     /* one per controlle
        int                     next_uframe;    /* scan periodic, start here */
        unsigned                periodic_sched; /* periodic activity count */
 
-       /* deferred work from IRQ, etc */
-       struct tasklet_struct   tasklet;
-
        /* per root hub port */
        unsigned long           reset_done [EHCI_MAX_ROOT_PORTS];
 
--- ./drivers/usb/host/ehci-q.c.~1~     Mon Dec  9 14:10:59 2002
+++ ./drivers/usb/host/ehci-q.c Mon Dec  9 14:19:03 2002
@@ -159,7 +159,7 @@ static inline void qtd_copy_status (stru
        }
 }
 
-static void ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb)
+static void ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb, struct pt_regs 
+*regs)
 {
        if (likely (urb->hcpriv != 0)) {
                struct ehci_qh  *qh = (struct ehci_qh *) urb->hcpriv;
@@ -191,7 +191,7 @@ static void ehci_urb_done (struct ehci_h
 
        /* complete() can reenter this HCD */
        spin_unlock (&ehci->lock);
-       usb_hcd_giveback_urb (&ehci->hcd, urb, NULL);
+       usb_hcd_giveback_urb (&ehci->hcd, urb, regs);
 
        spin_lock (&ehci->lock);
 }
@@ -203,7 +203,7 @@ static void ehci_urb_done (struct ehci_h
  * indicating how much "real" work we did.
  */
 static unsigned
-qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
 {
        struct ehci_qtd         *qtd, *last;
        struct list_head        *next, *qtd_list = &qh->qtd_list;
@@ -225,7 +225,7 @@ qh_completions (struct ehci_hcd *ehci, s
                /* clean up any state from previous QTD ...*/
                if (last) {
                        if (likely (last->urb != urb)) {
-                               ehci_urb_done (ehci, last->urb);
+                               ehci_urb_done (ehci, last->urb, regs);
                                count++;
                        }
                        ehci_qtd_free (ehci, last);
@@ -311,7 +311,7 @@ qh_completions (struct ehci_hcd *ehci, s
 
        /* last urb's completion might still need calling */
        if (likely (last != 0)) {
-               ehci_urb_done (ehci, last->urb);
+               ehci_urb_done (ehci, last->urb, regs);
                count++;
                ehci_qtd_free (ehci, last);
        }
@@ -879,7 +879,7 @@ submit_async (
 /* the async qh for the qtds being reclaimed are now unlinked from the HC */
 /* caller must not own ehci->lock */
 
-static void end_unlink_async (struct ehci_hcd *ehci)
+static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
        struct ehci_qh          *qh = ehci->reclaim;
 
@@ -891,7 +891,7 @@ static void end_unlink_async (struct ehc
        ehci->reclaim = 0;
        ehci->reclaim_ready = 0;
 
-       qh_completions (ehci, qh);
+       qh_completions (ehci, qh, regs);
 
        if (!list_empty (&qh->qtd_list)
                        && HCD_IS_RUNNING (ehci->hcd.state))
@@ -943,7 +943,7 @@ static void start_unlink_async (struct e
 
        if (unlikely (ehci->hcd.state == USB_STATE_HALT)) {
                ehci->reclaim_ready = 1;
-               tasklet_schedule (&ehci->tasklet);
+               __ehci_work (ehci, NULL);
                return;
        }
 
@@ -966,7 +966,7 @@ static void start_unlink_async (struct e
 /*-------------------------------------------------------------------------*/
 
 static void
-scan_async (struct ehci_hcd *ehci)
+scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
        struct ehci_qh          *qh;
        unsigned                count;
@@ -982,7 +982,7 @@ rescan:
                                qh = qh_get (qh);
 
                                /* concurrent unlink could happen here */
-                               count += qh_completions (ehci, qh);
+                               count += qh_completions (ehci, qh, regs);
                                qh_put (ehci, qh);
                                goto rescan;
                        }
--- ./drivers/usb/host/ehci-hcd.c.~1~   Mon Dec  9 14:06:42 2002
+++ ./drivers/usb/host/ehci-hcd.c       Mon Dec  9 14:18:23 2002
@@ -241,6 +241,9 @@ static void ehci_ready (struct ehci_hcd 
        ehci->hcd.state = USB_STATE_READY;
 }
 
+static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs);
+static void __ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs);
+
 /*-------------------------------------------------------------------------*/
 
 #include "ehci-hub.c"
@@ -250,8 +253,6 @@ static void ehci_ready (struct ehci_hcd 
 
 /*-------------------------------------------------------------------------*/
 
-static void ehci_tasklet (unsigned long param);
-
 static void ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs);
 
 static void ehci_watchdog (unsigned long param)
@@ -426,9 +427,6 @@ static int ehci_start (struct usb_hcd *h
 
        /* set async sleep time = 10 us ... ? */
 
-       ehci->tasklet.func = ehci_tasklet;
-       ehci->tasklet.data = (unsigned long) ehci;
-
        init_timer (&ehci->watchdog);
        ehci->watchdog.function = ehci_watchdog;
        ehci->watchdog.data = (unsigned long) ehci;
@@ -506,8 +504,7 @@ static void ehci_stop (struct usb_hcd *h
        remove_debug_files (ehci);
 
        /* root hub is shut down separately (first, when possible) */
-       tasklet_disable (&ehci->tasklet);
-       ehci_tasklet ((unsigned long) ehci);
+       ehci_work (ehci, NULL);
        ehci_mem_cleanup (ehci);
 
 #ifdef EHCI_STATS
@@ -615,21 +612,22 @@ dbg ("%s: resume port %d", hcd_to_bus (h
 /*-------------------------------------------------------------------------*/
 
 /*
- * tasklet scheduled by some interrupts and other events
- * calls driver completion functions ... but not in_irq()
+ * work run by some interrupts and other events
+ * calls driver completion functions
  */
-static void ehci_tasklet (unsigned long param)
+static void __ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
-       struct ehci_hcd         *ehci = (struct ehci_hcd *) param;
-
-       spin_lock_irq (&ehci->lock);
-
        if (ehci->reclaim_ready)
-               end_unlink_async (ehci);
-       scan_async (ehci);
+               end_unlink_async (ehci, regs);
+       scan_async (ehci, regs);
        if (ehci->next_uframe != -1)
-               scan_periodic (ehci);
+               scan_periodic (ehci, regs);
+}
 
+static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
+{
+       spin_lock_irq (&ehci->lock);
+       __ehci_work(ehci, regs);
        spin_unlock_irq (&ehci->lock);
 }
 
@@ -693,7 +691,7 @@ dead:
 
        /* most work doesn't need to be in_irq() */
        if (likely (bh == 1))
-               tasklet_schedule (&ehci->tasklet);
+               ehci_work (ehci, regs);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -799,7 +797,7 @@ static int ehci_urb_dequeue (struct usb_
                        intr_deschedule (ehci, qh, 1);
                        /* qh_state == IDLE */
                }
-               qh_completions (ehci, qh);
+               qh_completions (ehci, qh, NULL);
 
                /* reschedule QH iff another request is queued */
                if (!list_empty (&qh->qtd_list)
@@ -889,7 +887,7 @@ static void ehci_free_config (struct usb
                                        ) {
                                spin_unlock_irqrestore (&ehci->lock, flags);
                                /* wait_ms() won't spin, we're a thread;
-                                * and we know IRQ+tasklet can progress
+                                * and we know IRQ can progress
                                 */
                                wait_ms (1);
                                spin_lock_irqsave (&ehci->lock, flags);
--- ./drivers/usb/host/ehci-sched.c.~1~ Mon Dec  9 14:11:16 2002
+++ ./drivers/usb/host/ehci-sched.c     Mon Dec  9 14:19:13 2002
@@ -190,7 +190,7 @@ static int enable_periodic (struct ehci_
        /* posted write ... PSS happens later */
        ehci->hcd.state = USB_STATE_RUNNING;
 
-       /* make sure tasklet scans these */
+       /* make sure ehci_work scans these */
        ehci->next_uframe = readl (&ehci->regs->frame_index)
                                % (ehci->periodic_size << 3);
        return 0;
@@ -495,7 +495,8 @@ static unsigned
 intr_complete (
        struct ehci_hcd *ehci,
        unsigned        frame,
-       struct ehci_qh  *qh
+       struct ehci_qh  *qh,
+       struct pt_regs  *regs
 ) {
        unsigned        count;
 
@@ -509,7 +510,7 @@ intr_complete (
        }
        
        /* handle any completions */
-       count = qh_completions (ehci, qh);
+       count = qh_completions (ehci, qh, regs);
 
        if (unlikely (list_empty (&qh->qtd_list)))
                intr_deschedule (ehci, qh, 0);
@@ -867,7 +868,8 @@ static unsigned
 itd_complete (
        struct ehci_hcd *ehci,
        struct ehci_itd *itd,
-       unsigned        uframe
+       unsigned        uframe,
+       struct pt_regs  *regs
 ) {
        struct urb                              *urb = itd->urb;
        struct usb_iso_packet_descriptor        *desc;
@@ -922,7 +924,7 @@ itd_complete (
 
        /* complete() can reenter this HCD */
        spin_unlock (&ehci->lock);
-       usb_hcd_giveback_urb (&ehci->hcd, urb, NULL);
+       usb_hcd_giveback_urb (&ehci->hcd, urb, regs);
        spin_lock (&ehci->lock);
 
        /* defer stopping schedule; completion can submit */
@@ -973,7 +975,7 @@ static int itd_submit (struct ehci_hcd *
 /*-------------------------------------------------------------------------*/
 
 static void
-scan_periodic (struct ehci_hcd *ehci)
+scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
        unsigned        frame, clock, now_uframe, mod;
        unsigned        count = 0;
@@ -1031,7 +1033,7 @@ restart:
                                temp = q.qh->qh_next;
                                type = Q_NEXT_TYPE (q.qh->hw_next);
                                count += intr_complete (ehci, frame,
-                                               qh_get (q.qh));
+                                               qh_get (q.qh), regs);
                                qh_put (ehci, q.qh);
                                q = temp;
                                break;
@@ -1064,7 +1066,7 @@ restart:
 
                                                /* might free q.itd ... */
                                                count += itd_complete (ehci,
-                                                       temp.itd, uf);
+                                                       temp.itd, uf, regs);
                                                break;
                                        }
                                }


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to