patch-2.3.99-pre4 linux/drivers/usb/usb-uhci.c
Next file: linux/drivers/usb/usb-uhci.h
Previous file: linux/drivers/usb/usb-storage.h
Back to the patch index
Back to the overall index
- Lines: 198
- Date:
Wed Apr 5 17:01:25 2000
- Orig file:
v2.3.99-pre3/linux/drivers/usb/usb-uhci.c
- Orig date:
Mon Mar 27 08:08:28 2000
diff -u --recursive --new-file v2.3.99-pre3/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
@@ -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;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)