*/
#include <linux/config.h>
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#else
-#undef DEBUG
-#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include "../core/hcd.h"
#include "uhci-hcd.h"
+#include "pci-quirks.h"
/*
* Version Information
*/
-#define DRIVER_VERSION "v2.3"
+#define DRIVER_VERSION "v3.0"
#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \
Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
Alan Stern"
/*
* debug = 0, no debugging messages
- * debug = 1, dump failed URB's except for stalls
- * debug = 2, dump all failed URB's (including stalls)
+ * debug = 1, dump failed URBs except for stalls
+ * debug = 2, dump all failed URBs (including stalls)
* show all queues in /debug/uhci/[pci_addr]
- * debug = 3, show all TD's in URB's when dumping
+ * debug = 3, show all TDs in URBs when dumping
*/
#ifdef DEBUG
+#define DEBUG_CONFIGURED 1
static int debug = 1;
-#else
-static int debug = 0;
-#endif
module_param(debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug level");
+
+#else
+#define DEBUG_CONFIGURED 0
+#define debug 0
+#endif
+
static char *errbuf;
#define ERRBUF_LEN (32 * 1024)
#define FSBR_DELAY msecs_to_jiffies(50)
/* When we timeout an idle transfer for FSBR, we'll switch it over to */
-/* depth first traversal. We'll do it in groups of this number of TD's */
+/* depth first traversal. We'll do it in groups of this number of TDs */
/* to make sure it doesn't hog all of the bandwidth */
#define DEPTH_INTERVAL 5
#include "uhci-q.c"
#include "uhci-hub.c"
-extern void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
-extern int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
-
/*
* Finish up a host controller reset and update the recorded state.
*/
for (port = 0; port < uhci->rh_numports; ++port)
outw(0, uhci->io_addr + USBPORTSC1 + (port * 2));
- uhci->port_c_suspend = uhci->suspended_ports =
- uhci->resuming_ports = 0;
+ uhci->port_c_suspend = uhci->resuming_ports = 0;
uhci->rh_state = UHCI_RH_RESET;
uhci->is_stopped = UHCI_IS_STOPPED;
uhci_to_hcd(uhci)->state = HC_STATE_HALT;
dev_err(uhci_dev(uhci),
"host controller halted, "
"very bad!\n");
+ if (debug > 1 && errbuf) {
+ /* Print the schedule for debugging */
+ uhci_sprint_schedule(uhci,
+ errbuf, ERRBUF_LEN);
+ lprintk(errbuf);
+ }
hc_died(uhci);
/* Force a callback in case there are
{
int i;
+ if (DEBUG_CONFIGURED) {
+ spin_lock_irq(&uhci->lock);
+ uhci->is_initialized = 0;
+ spin_unlock_irq(&uhci->lock);
+
+ debugfs_remove(uhci->dentry);
+ }
+
for (i = 0; i < UHCI_NUM_SKELQH; i++)
uhci_free_qh(uhci, uhci->skelqh[i]);
dma_free_coherent(uhci_dev(uhci),
UHCI_NUMFRAMES * sizeof(*uhci->frame),
uhci->frame, uhci->frame_dma_handle);
-
- debugfs_remove(uhci->dentry);
}
static int uhci_reset(struct usb_hcd *hcd)
struct dentry *dentry;
hcd->uses_new_polling = 1;
- if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM))
- hcd->can_wakeup = 1; /* Assume it supports PME# */
-
- dentry = debugfs_create_file(hcd->self.bus_name,
- S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci,
- &uhci_debug_operations);
- if (!dentry) {
- dev_err(uhci_dev(uhci),
- "couldn't create uhci debugfs entry\n");
- retval = -ENOMEM;
- goto err_create_debug_entry;
- }
- uhci->dentry = dentry;
uhci->fsbr = 0;
uhci->fsbrtimeout = 0;
spin_lock_init(&uhci->lock);
- INIT_LIST_HEAD(&uhci->qh_remove_list);
INIT_LIST_HEAD(&uhci->td_remove_list);
-
- INIT_LIST_HEAD(&uhci->urb_remove_list);
-
- INIT_LIST_HEAD(&uhci->urb_list);
-
- INIT_LIST_HEAD(&uhci->complete_list);
+ INIT_LIST_HEAD(&uhci->idle_qh_list);
init_waitqueue_head(&uhci->waitqh);
+ if (DEBUG_CONFIGURED) {
+ dentry = debugfs_create_file(hcd->self.bus_name,
+ S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root,
+ uhci, &uhci_debug_operations);
+ if (!dentry) {
+ dev_err(uhci_dev(uhci), "couldn't create uhci "
+ "debugfs entry\n");
+ retval = -ENOMEM;
+ goto err_create_debug_entry;
+ }
+ uhci->dentry = dentry;
+ }
+
uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
UHCI_NUMFRAMES * sizeof(*uhci->frame),
&uhci->frame_dma_handle, 0);
}
for (i = 0; i < UHCI_NUM_SKELQH; i++) {
- uhci->skelqh[i] = uhci_alloc_qh(uhci);
+ uhci->skelqh[i] = uhci_alloc_qh(uhci, NULL, NULL);
if (!uhci->skelqh[i]) {
dev_err(uhci_dev(uhci), "unable to allocate QH\n");
goto err_alloc_skelqh;
uhci->skel_int16_qh->link =
uhci->skel_int8_qh->link =
uhci->skel_int4_qh->link =
- uhci->skel_int2_qh->link =
- cpu_to_le32(uhci->skel_int1_qh->dma_handle) | UHCI_PTR_QH;
- uhci->skel_int1_qh->link = cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH;
-
- uhci->skel_ls_control_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
- uhci->skel_fs_control_qh->link = cpu_to_le32(uhci->skel_bulk_qh->dma_handle) | UHCI_PTR_QH;
- uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH;
+ uhci->skel_int2_qh->link = UHCI_PTR_QH |
+ cpu_to_le32(uhci->skel_int1_qh->dma_handle);
+
+ uhci->skel_int1_qh->link = UHCI_PTR_QH |
+ cpu_to_le32(uhci->skel_ls_control_qh->dma_handle);
+ uhci->skel_ls_control_qh->link = UHCI_PTR_QH |
+ cpu_to_le32(uhci->skel_fs_control_qh->dma_handle);
+ uhci->skel_fs_control_qh->link = UHCI_PTR_QH |
+ cpu_to_le32(uhci->skel_bulk_qh->dma_handle);
+ uhci->skel_bulk_qh->link = UHCI_PTR_QH |
+ cpu_to_le32(uhci->skel_term_qh->dma_handle);
/* This dummy TD is to work around a bug in Intel PIIX controllers */
- uhci_fill_td(uhci->term_td, 0, (UHCI_NULL_DATA_SIZE << 21) |
+ uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle);
/*
* ffs (Find First bit Set) does exactly what we need:
- * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[6],
- * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[5], etc.
- * ffs > 6 => not on any high-period queue, so use
- * skel_int1_qh = skelqh[7].
+ * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8],
+ * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
+ * ffs >= 7 => not on any high-period queue, so use
+ * skel_int1_qh = skelqh[9].
* Add UHCI_NUMFRAMES to insure at least one bit is set.
*/
- irq = 6 - (int) __ffs(i + UHCI_NUMFRAMES);
- if (irq < 0)
- irq = 7;
+ irq = 8 - (int) __ffs(i + UHCI_NUMFRAMES);
+ if (irq <= 1)
+ irq = 9;
/* Only place we don't use the frame list routines */
uhci->frame[i] = UHCI_PTR_QH |
mb();
configure_hc(uhci);
+ uhci->is_initialized = 1;
start_rh(uhci);
return 0;
dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
- /* We aren't in D3 state anymore, we do that even if dead as I
- * really don't want to keep a stale HCD_FLAG_HW_ACCESSIBLE=0
+ /* Since we aren't in D3 any more, it's safe to set this flag
+ * even if the controller was dead. It might not even be dead
+ * any more, if the firmware or quirks code has reset it.
*/
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
mb();
check_and_reset_hc(uhci);
configure_hc(uhci);
- if (uhci->rh_state == UHCI_RH_RESET)
+ if (uhci->rh_state == UHCI_RH_RESET) {
+
+ /* The controller had to be reset */
+ usb_root_hub_lost_power(hcd->self.root_hub);
suspend_rh(uhci, UHCI_RH_SUSPENDED);
+ }
spin_unlock_irq(&uhci->lock);
}
#endif
-/* Wait until all the URBs for a particular device/endpoint are gone */
+/* Wait until a particular device/endpoint's QH is idle, and free it */
static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd,
- struct usb_host_endpoint *ep)
+ struct usb_host_endpoint *hep)
{
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ struct uhci_qh *qh;
+
+ spin_lock_irq(&uhci->lock);
+ qh = (struct uhci_qh *) hep->hcpriv;
+ if (qh == NULL)
+ goto done;
- wait_event_interruptible(uhci->waitqh, list_empty(&ep->urb_list));
+ while (qh->state != QH_STATE_IDLE) {
+ ++uhci->num_waiting;
+ spin_unlock_irq(&uhci->lock);
+ wait_event_interruptible(uhci->waitqh,
+ qh->state == QH_STATE_IDLE);
+ spin_lock_irq(&uhci->lock);
+ --uhci->num_waiting;
+ }
+
+ uhci_free_qh(uhci, qh);
+done:
+ spin_unlock_irq(&uhci->lock);
}
static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
if (usb_disabled())
return -ENODEV;
- if (debug) {
+ if (DEBUG_CONFIGURED) {
errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
if (!errbuf)
goto errbuf_failed;
+ uhci_debugfs_root = debugfs_create_dir("uhci", NULL);
+ if (!uhci_debugfs_root)
+ goto debug_failed;
}
- uhci_debugfs_root = debugfs_create_dir("uhci", NULL);
- if (!uhci_debugfs_root)
- goto debug_failed;
-
uhci_up_cachep = kmem_cache_create("uhci_urb_priv",
sizeof(struct urb_priv), 0, 0, NULL, NULL);
if (!uhci_up_cachep)
init_failed:
if (kmem_cache_destroy(uhci_up_cachep))
- warn("not all urb_priv's were freed!");
+ warn("not all urb_privs were freed!");
up_failed:
debugfs_remove(uhci_debugfs_root);
pci_unregister_driver(&uhci_pci_driver);
if (kmem_cache_destroy(uhci_up_cachep))
- warn("not all urb_priv's were freed!");
+ warn("not all urb_privs were freed!");
debugfs_remove(uhci_debugfs_root);
kfree(errbuf);