ChangeSet 1.883.3.2, 2002/12/16 10:31:24-08:00, [EMAIL PROTECTED]

[PATCH] ehci-hcd (2/2): rest of tasklet remove

This is the rest of the work to remove the tasklet: the non-syntax
portions which affect work scheduling.  It's not quite davem's version;
it's got locking updates, which among other things prevent a hang when
the timer kicks in.

This scheduling change is split out from the other parts in case more
problems like that unlink race (fixed in my previous patch) show up.
It doesn't fix (or help fix) any ehci bugs, but simpler code is fine.


diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c       Wed Dec 18 00:35:24 2002
+++ b/drivers/usb/host/ehci-hcd.c       Wed Dec 18 00:35:24 2002
@@ -244,9 +244,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void ehci_tasklet (unsigned long param);
-
-static void ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs);
+static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs);
 
 static void ehci_watchdog (unsigned long param)
 {
@@ -254,10 +252,25 @@
        unsigned long           flags;
 
        spin_lock_irqsave (&ehci->lock, flags);
-       /* guard against lost IAA, which wedges everything */
-       ehci_irq (&ehci->hcd, NULL);
+
+       /* lost IAA irqs wedge things badly; seen with a vt8235 */
+       if (ehci->reclaim) {
+               u32             status = readl (&ehci->regs->status);
+
+               if (status & STS_IAA) {
+                       ehci_vdbg (ehci, "lost IAA\n");
+                       writel (STS_IAA, &ehci->regs->status);
+                       ehci->reclaim_ready = 1;
+               }
+       }
+
+       ehci_work (ehci, NULL);
+       if (ehci->reclaim && !timer_pending (&ehci->watchdog))
+               mod_timer (&ehci->watchdog,
+                               jiffies + EHCI_WATCHDOG_JIFFIES);
+
        /* stop async processing after it's idled a while */
-       if (ehci->async_idle) {
+       else if (ehci->async_idle) {
                start_unlink_async (ehci, ehci->async);
                ehci->async_idle = 0;
        }
@@ -418,9 +431,6 @@
 
        /* 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;
@@ -499,8 +509,9 @@
        remove_debug_files (ehci);
 
        /* root hub is shut down separately (first, when possible) */
-       tasklet_disable (&ehci->tasklet);
-       ehci_tasklet ((unsigned long) ehci);
+       spin_lock_irq (&ehci->lock);
+       ehci_work (ehci, NULL);
+       spin_unlock_irq (&ehci->lock);
        ehci_mem_cleanup (ehci);
 
 #ifdef EHCI_STATS
@@ -608,23 +619,16 @@
 /*-------------------------------------------------------------------------*/
 
 /*
- * tasklet scheduled by some interrupts and other events
- * calls driver completion functions ... but not in_irq()
+ * ehci_work is called from some interrupts, timers, and so on.
+ * it calls driver completion functions, after dropping ehci->lock.
  */
-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;
-       struct pt_regs          *regs = NULL;
-
-       spin_lock_irq (&ehci->lock);
-
        if (ehci->reclaim_ready)
                end_unlink_async (ehci, regs);
        scan_async (ehci, regs);
        if (ehci->next_uframe != -1)
                scan_periodic (ehci, regs);
-
-       spin_unlock_irq (&ehci->lock);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -645,6 +649,8 @@
        if (!status)                    /* irq sharing? */
                return;
 
+       spin_lock (&ehci->lock);
+
        /* clear (just) interrupts */
        writel (status, &ehci->regs->status);
        readl (&ehci->regs->command);   /* unblock posted write */
@@ -684,9 +690,9 @@
                bh = 1;
        }
 
-       /* most work doesn't need to be in_irq() */
-       if (likely (bh == 1))
-               tasklet_schedule (&ehci->tasklet);
+       if (bh)
+               ehci_work (ehci, regs);
+       spin_unlock (&ehci->lock);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -882,7 +888,7 @@
                                        ) {
                                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/timer/... can progress
                                 */
                                wait_ms (1);
                                spin_lock_irqsave (&ehci->lock, flags);
diff -Nru a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
--- a/drivers/usb/host/ehci-sched.c     Wed Dec 18 00:35:24 2002
+++ b/drivers/usb/host/ehci-sched.c     Wed Dec 18 00:35:24 2002
@@ -190,7 +190,7 @@
        /* 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;
diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
--- a/drivers/usb/host/ehci.h   Wed Dec 18 00:35:24 2002
+++ b/drivers/usb/host/ehci.h   Wed Dec 18 00:35:24 2002
@@ -65,9 +65,6 @@
        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];
 


-------------------------------------------------------
This sf.net email is sponsored by:
With Great Power, Comes Great Responsibility 
Learn to use your power at OSDN's High Performance Computing Channel
http://hpc.devchannel.org/
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to