Hi,
as somebody already suggested, it would be a good idea to decrease the
current interrupt rate for usb-uhci of 1000Hz to a much lower level ;-)

Attached is the patch to do this, it has the full interrupt rate only when
the remainings of asynchronously killed URBs have to be processed, 
there's a 30Hz rate if there are URBs with specified timeouts pending.

Please apply.
-- 
        Bye
         Georg Acher, [EMAIL PROTECTED]         
         http://www.in.tum.de/~acher/
          "Oh no, not again !" The bowl of petunias          
diff -u linux/drivers/usb/usb-uhci.c linux.afs/drivers/usb/usb-uhci.c
--- linux/drivers/usb/usb-uhci.c        Thu Mar 23 23:59:56 2000
+++ linux.afs/drivers/usb/usb-uhci.c    Wed Apr  5 18:17:07 2000
@@ -12,7 +12,7 @@
  * (C) Copyright 1999 Johannes Erdfelt
  * (C) Copyright 1999 Randy Dunlap
  *
- * $Id: usb-uhci.c,v 1.222 2000/03/13 21:18:02 fliegl Exp $
+ * $Id: usb-uhci.c,v 1.228 2000/04/02 19:55:51 acher Exp $
  */
 
 #include <linux/config.h>
@@ -50,6 +50,8 @@
 /* This enables an extra UHCI slab for memory debugging */
 #define DEBUG_SLAB
 
+#define VERSTR "$Revision: 1.228 $ time " __TIME__ " " __DATE__
+
 #include <linux/usb.h>
 #include "usb-uhci.h"
 #include "usb-uhci-debug.h"
@@ -116,6 +118,26 @@
        }
 }
 /*-------------------------------------------------------------------*/
+_static void uhci_switch_timer_int(uhci_t *s)
+{
+
+       if (!list_empty(&s->urb_unlinked)) {
+               s->td1ms->hw.td.status |= TD_CTRL_IOC;
+       }
+       else {
+               s->td1ms->hw.td.status &= ~TD_CTRL_IOC;
+       }
+
+       if (s->timeout_urbs) {
+               s->td32ms->hw.td.status |= TD_CTRL_IOC;
+       }
+       else {
+               s->td32ms->hw.td.status &= ~TD_CTRL_IOC;
+       }
+
+       wmb();
+}
+/*-------------------------------------------------------------------*/
 #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
 _static void enable_desc_loop(uhci_t *s, urb_t *urb)
 {
@@ -162,6 +184,9 @@
 #endif
        ((urb_priv_t*)urb->hcpriv)->started=jiffies;
        list_add (p, &s->urb_list);
+       if (urb->timeout)
+               s->timeout_urbs++;
+       uhci_switch_timer_int(s);
 }
 /*-------------------------------------------------------------------*/
 _static void queue_urb (uhci_t *s, urb_t *urb)
@@ -185,6 +210,9 @@
 #endif
 
        list_del (&urb->urb_list);
+       if (urb->timeout && s->timeout_urbs)
+               s->timeout_urbs--;
+
 }
 /*-------------------------------------------------------------------*/
 _static int alloc_td (uhci_desc_t ** new, int flags)
@@ -439,6 +467,13 @@
 
        clean_descs(s,1);
 
+       
+       if (s->td32ms) {
+       
+               unlink_td(s,s->td32ms,1);
+               delete_desc(s->td32ms);
+       }
+
        for (n = 0; n < 8; n++) {
                td = s->int_chain[n];
                clean_td_chain (td);
@@ -531,8 +566,9 @@
        if (ret)
                goto init_skel_cleanup;
        
-       fill_td (td, TD_CTRL_IOC, 0, 0); // generate 1ms interrupt
+       fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on 
+demand)
        insert_td (s, qh, td, 0);
+       s->td1ms=td;
 
        dbg("allocating qh: bulk_chain");
        ret = alloc_qh (&qh);
@@ -597,6 +633,16 @@
                                        ((uhci_desc_t*) s->iso_td[n])->hw.td.link = 
virt_to_bus (s->int_chain[o]);
        }
 
+       ret = alloc_td (&td, 0);
+
+       if (ret)
+               goto init_skel_cleanup;
+       
+       fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 32ms interrupt
+       s->td32ms=td;
+
+       insert_td_horizontal (s, s->int_chain[5], td);
+
        mb();
        //uhci_show_queue(s->control_chain);   
        dbg("init_skel exit");
@@ -995,6 +1041,7 @@
        if (urb->status == -EINPROGRESS) {
                // URB probably still in work
                dequeue_urb (s, urb);
+               uhci_switch_timer_int(s);
                s->unlink_urb_done=1;
                spin_unlock_irqrestore (&s->urb_list_lock, flags);              
                
@@ -1125,9 +1172,11 @@
 
        if (urb->status == -EINPROGRESS) {
                ((urb_priv_t*)urb->hcpriv)->started = ~0;
+
                dequeue_urb (s, urb);
                list_add_tail (&urb->urb_list, &s->urb_unlinked); // store urb
-
+               uhci_switch_timer_int(s);
+                       
                s->unlink_urb_done = 1;
                
                urb->status = -ECONNABORTED;    // mark urb as "waiting to be killed"  
 
@@ -1495,7 +1544,7 @@
                     (!(urb->transfer_flags & USB_QUEUE_BULK) || 
!(bulk_urb->transfer_flags & USB_QUEUE_BULK)))) {
                        spin_unlock_irqrestore (&s->urb_list_lock, flags);
                        usb_dec_dev_use (urb->dev);
-                       err("ENXIO1 %08x, flags %x, urb %p, burb 
%p",urb->pipe,urb->transfer_flags,urb,bulk_urb);
+                       err("ENXIO %08x, flags %x, urb %p, burb 
+%p",urb->pipe,urb->transfer_flags,urb,bulk_urb);
                        return -ENXIO;  // urb already queued
                }
        }
@@ -1599,6 +1648,7 @@
 #endif
 
        }
+       s->timeout_check=jiffies;
 }
 
 /*-------------------------------------------------------------------
@@ -1922,7 +1972,7 @@
                        OK (len);
                case (0x03):    /* string descriptors */
                        len = usb_root_hub_string (wValue & 0xff,
-                               uhci->io_addr, "UHCI",
+                               uhci->io_addr, "UHCI",
                                data, wLength);
                        if (len > 0) {
                                OK (min (leni, len));
@@ -2481,15 +2531,15 @@
                        goto restart;
                }
        }
-       if ((s->frame_counter & 63) == 0)
+       if ((jiffies - s->timeout_check) > (HZ/30)) 
                uhci_check_timeouts(s);
 
        clean_descs(s,0);
        uhci_cleanup_unlink(s, 0);
-       
+       uhci_switch_timer_int(s);
+                                                       
        spin_unlock (&s->urb_list_lock);
        
-       s->frame_counter++;
        outw (status, io_addr + USBSTS);
 
        //dbg("uhci_interrupt: done");
@@ -2630,12 +2680,14 @@
        spin_lock_init (&s->qh_lock);
        spin_lock_init (&s->td_lock);
        atomic_set(&s->avoid_bulk, 0);
+       s->timeout_urbs = 0;    
        s->irq = -1;
        s->io_addr = io_addr;
        s->io_size = io_size;
        s->next = devs; //chain new uhci device into global list        
-       s->frame_counter = 0;
-       
+       s->timeout_check = 0;
+       s->uhci_pci=dev;
+
        bus = usb_alloc_bus (&uhci_device_operations);
        if (!bus) {
                kfree (s);
@@ -2739,6 +2791,7 @@
                        info("Intel USB controller: setting latency timer to %d", 
UHCI_LATENCY_TIMER);
                        pci_write_config_byte(dev, PCI_LATENCY_TIMER, 
UHCI_LATENCY_TIMER);
                }
+       
                return alloc_uhci(dev, dev->irq, io_addr, io_size);
        }
        return -1;
diff -u linux/drivers/usb/usb-uhci.h linux.afs/drivers/usb/usb-uhci.h
--- linux/drivers/usb/usb-uhci.h        Wed Mar 15 03:09:51 2000
+++ linux.afs/drivers/usb/usb-uhci.h    Mon Apr  3 10:51:51 2000
@@ -2,10 +2,9 @@
 #define __LINUX_UHCI_H
 
 /*
-   $Id: usb-uhci.h,v 1.50 2000/03/13 21:18:04 fliegl Exp $
+   $Id: usb-uhci.h,v 1.54 2000/04/02 19:55:53 acher Exp $
  */
 #define MODNAME "usb-uhci"
-#define VERSTR "$Revision: 1.50 $ time " __TIME__ " " __DATE__
 #define UHCI_LATENCY_TIMER 0
 
 static __inline__ void uhci_wait_ms(unsigned int ms)
@@ -202,6 +201,8 @@
        uhci_desc_t *control_chain;
        uhci_desc_t *bulk_chain;
        uhci_desc_t *chain_end;
+       uhci_desc_t *td1ms;
+       uhci_desc_t *td32ms;
        struct list_head free_desc;
        spinlock_t qh_lock;
        spinlock_t td_lock;
@@ -209,7 +210,9 @@
        int loop_usage;            // URBs using bandwidth reclamation
 
        struct list_head urb_unlinked;  // list of all unlinked  urbs
-       int frame_counter;
+       long timeout_check;
+       int timeout_urbs;
+       struct pci_dev *uhci_pci;
 } uhci_t, *puhci_t;
 
 

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to