patch-2.4.19 linux-2.4.19/drivers/usb/uhci.h
Next file: linux-2.4.19/drivers/usb/usb-ohci.c
Previous file: linux-2.4.19/drivers/usb/uhci.c
Back to the patch index
Back to the overall index
- Lines: 133
- Date:
Fri Aug 2 17:39:45 2002
- Orig file:
linux-2.4.18/drivers/usb/uhci.h
- Orig date:
Thu Nov 22 11:49:52 2001
diff -urN linux-2.4.18/drivers/usb/uhci.h linux-2.4.19/drivers/usb/uhci.h
@@ -121,15 +121,16 @@
* for TD <info>: (a.k.a. Token)
*/
#define TD_TOKEN_TOGGLE 19
-#define TD_PID 0xFF
+#define TD_TOKEN_PID_MASK 0xFF
+#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n - 1 */
#define uhci_maxlen(token) ((token) >> 21)
-#define uhci_expected_length(info) (((info >> 21) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
+#define uhci_expected_length(info) (((info >> 21) + 1) & TD_TOKEN_EXPLEN_MASK) /* 1-based */
#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE) & 1)
#define uhci_endpoint(token) (((token) >> 15) & 0xf)
#define uhci_devaddr(token) (((token) >> 8) & 0x7f)
#define uhci_devep(token) (((token) >> 8) & 0x7ff)
-#define uhci_packetid(token) ((token) & 0xff)
+#define uhci_packetid(token) ((token) & TD_TOKEN_PID_MASK)
#define uhci_packetout(token) (uhci_packetid(token) != USB_PID_IN)
#define uhci_packetin(token) (uhci_packetid(token) == USB_PID_IN)
@@ -163,7 +164,7 @@
struct list_head list; /* P: urb->lock */
int frame;
- struct list_head fl_list; /* P: frame_list_lock */
+ struct list_head fl_list; /* P: uhci->frame_list_lock */
} __attribute__((aligned(16)));
/*
@@ -286,17 +287,17 @@
struct uhci {
struct pci_dev *dev;
+#ifdef CONFIG_PROC_FS
/* procfs */
int num;
struct proc_dir_entry *proc_entry;
+#endif
/* Grabbed from PCI */
int irq;
unsigned int io_addr;
unsigned int io_size;
- struct list_head uhci_list;
-
struct pci_pool *qh_pool;
struct pci_pool *td_pool;
@@ -306,21 +307,26 @@
struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
spinlock_t frame_list_lock;
- struct uhci_frame_list *fl; /* Frame list */
+ struct uhci_frame_list *fl; /* P: uhci->frame_list_lock */
int fsbr; /* Full speed bandwidth reclamation */
+ unsigned long fsbrtimeout; /* FSBR delay */
int is_suspended;
+ /* Main list of URB's currently controlled by this HC */
+ spinlock_t urb_list_lock;
+ struct list_head urb_list; /* P: uhci->urb_list_lock */
+
+ /* List of QH's that are done, but waiting to be unlinked (race) */
spinlock_t qh_remove_list_lock;
- struct list_head qh_remove_list;
+ struct list_head qh_remove_list; /* P: uhci->qh_remove_list_lock */
+ /* List of asynchronously unlinked URB's */
spinlock_t urb_remove_list_lock;
- struct list_head urb_remove_list;
-
- spinlock_t urb_list_lock;
- struct list_head urb_list;
+ struct list_head urb_remove_list; /* P: uhci->urb_remove_list_lock */
+ /* List of URB's awaiting completion callback */
spinlock_t complete_list_lock;
- struct list_head complete_list;
+ struct list_head complete_list; /* P: uhci->complete_list_lock */
struct virt_root_hub rh; /* private data of the virtual root hub */
};
@@ -333,7 +339,7 @@
dma_addr_t transfer_buffer_dma_handle;
struct uhci_qh *qh; /* QH for this URB */
- struct list_head td_list;
+ struct list_head td_list; /* P: urb->lock */
int fsbr : 1; /* URB turned on FSBR */
int fsbr_timeout : 1; /* URB timed out on FSBR */
@@ -345,12 +351,37 @@
int status; /* Final status */
unsigned long inserttime; /* In jiffies */
- unsigned long fsbrtime; /* In jiffies */
+ unsigned long fsbrtime; /* In jiffies */
- struct list_head queue_list;
- struct list_head complete_list;
+ struct list_head queue_list; /* P: uhci->frame_list_lock */
+ struct list_head complete_list; /* P: uhci->complete_list_lock */
};
+/*
+ * Locking in uhci.c
+ *
+ * spinlocks are used extensively to protect the many lists and data
+ * structures we have. It's not that pretty, but it's necessary. We
+ * need to be done with all of the locks (except complete_list_lock) when
+ * we call urb->complete. I've tried to make it simple enough so I don't
+ * have to spend hours racking my brain trying to figure out if the
+ * locking is safe.
+ *
+ * Here's the safe locking order to prevent deadlocks:
+ *
+ * #1 uhci->urb_list_lock
+ * #2 urb->lock
+ * #3 uhci->urb_remove_list_lock, uhci->frame_list_lock,
+ * uhci->qh_remove_list_lock
+ * #4 uhci->complete_list_lock
+ *
+ * If you're going to grab 2 or more locks at once, ALWAYS grab the lock
+ * at the lowest level FIRST and NEVER grab locks at the same level at the
+ * same time.
+ *
+ * So, if you need uhci->urb_list_lock, grab it before you grab urb->lock
+ */
+
/* -------------------------------------------------------------------------
Virtual Root HUB
------------------------------------------------------------------------- */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)