These patches are against kernels 2.6.18 through at least 2.6.18-git7.
patch 5: first half of untangling intermixed ehci_iso_sched, itd and
sitd code; moves/groups scattered code into self-contained sections.
Adds kernel-doc entries for functions. This patch should result in no
functional difference.
Signed-off-by: Christopher "Monty" Montgomery <[EMAIL PROTECTED]>
---
diff -X b/Documentation/dontdiff -upr a/drivers/usb/host/ehci-sched.c
b/drivers/usb/host/ehci-sched.c
--- a/drivers/usb/host/ehci-sched.c 2006-09-26 22:20:51.000000000 -0400
+++ b/drivers/usb/host/ehci-sched.c 2006-09-26 22:21:02.000000000 -0400
@@ -969,9 +969,15 @@ iso_sched_free (struct ehci_iso_stream *
}
/*-------------------------------------------------------------------------*/
+/* ISO stream generic machinery; tracks the ITDs and sITDs associated
+ with an isochronous endpoint */
-/* ehci_iso_stream ops work with both ITD and SITD */
-
+/* iso_stream_alloc - allocate a new iso stream structure; and iso
+ * stream performs a role similar to QHs for ISO endpoints (both ITD
+ * and SITD)
+ *
+ * @mem_flags: flags for memory allocation
+ */
static struct ehci_iso_stream *
iso_stream_alloc (gfp_t mem_flags)
{
@@ -987,6 +993,14 @@ iso_stream_alloc (gfp_t mem_flags)
return stream;
}
+/* iso_stream_init - initialize fields of an ehci_iso_stream structure
+ *
+ * @ehci: pointer to ehci host controller device structure
+ * @stream: ehci_iso_stream structure to initialize
+ * @dev: endpoint usb device
+ * @pipe: pipe handle
+ * @interval: bInterval of endpoint; frames for FS/LS, uFrames for HS
+ */
static void
iso_stream_init (
struct ehci_hcd *ehci,
@@ -1082,6 +1096,12 @@ iso_stream_init (
stream->maxp = maxp;
}
+/* iso_stream_put - decrement refcount of passed in ehci_iso_stream
+ * structure, reaping it if count has fallen to zero.
+ *
+ * @ehci: pointer to ehci host controller device structure
+ * @stream: ehci_iso_stream structure
+ */
static void
iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
{
@@ -1144,6 +1164,11 @@ iso_stream_put(struct ehci_hcd *ehci, st
}
}
+/* iso_stream_get - increment refcount of passed in ehci_iso_stream
+ * structure
+ *
+ * @stream: ehci_iso_stream structure
+ */
static inline struct ehci_iso_stream *
iso_stream_get (struct ehci_iso_stream *stream)
{
@@ -1152,6 +1177,14 @@ iso_stream_get (struct ehci_iso_stream *
return stream;
}
+/* iso_stream_find - returns ehci_iso_stream structure matching the
+ * passed in urb; if no match is found, a new ehci_iso_stream is
+ * allocated and initialized to match the urb. This function is thus
+ * used both for looup and lazy alloc.
+ *
+ * @ehci: pointer to ehci host controller device structure
+ * @urb: usb request block
+ */
static struct ehci_iso_stream *
iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
{
@@ -1194,114 +1227,6 @@ iso_stream_find (struct ehci_hcd *ehci,
return stream;
}
-static inline void
-itd_sched_init (
- struct ehci_iso_sched *iso_sched,
- struct ehci_iso_stream *stream,
- struct urb *urb
-)
-{
- unsigned i;
- dma_addr_t dma = urb->transfer_dma;
-
- /* how many uframes are needed for these transfers */
- iso_sched->span = urb->number_of_packets * stream->interval;
-
- /* figure out per-uframe itd fields that we'll need later
- * when we fit new itds into the schedule.
- */
- for (i = 0; i < urb->number_of_packets; i++) {
- struct ehci_iso_packet *uframe = &iso_sched->packet [i];
- unsigned length;
- dma_addr_t buf;
- u32 trans;
-
- length = urb->iso_frame_desc [i].length;
- buf = dma + urb->iso_frame_desc [i].offset;
-
- trans = EHCI_ISOC_ACTIVE;
- trans |= buf & 0x0fff;
- if (unlikely (((i + 1) == urb->number_of_packets))
- && !(urb->transfer_flags & URB_NO_INTERRUPT))
- trans |= EHCI_ITD_IOC;
- trans |= length << 16;
- uframe->transaction = cpu_to_le32 (trans);
-
- /* might need to cross a buffer page within a uframe */
- uframe->bufp = (buf & ~(u64)0x0fff);
- buf += length;
- if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff))))
- uframe->cross = 1;
- }
-}
-
-static int
-itd_urb_transaction (
- struct ehci_iso_stream *stream,
- struct ehci_hcd *ehci,
- struct urb *urb,
- gfp_t mem_flags
-)
-{
- struct ehci_itd *itd;
- dma_addr_t itd_dma;
- int i;
- unsigned num_itds;
- struct ehci_iso_sched *sched;
- unsigned long flags;
-
- sched = iso_sched_alloc (urb->number_of_packets, mem_flags);
- if (unlikely (sched == NULL))
- return -ENOMEM;
-
- itd_sched_init (sched, stream, urb);
-
- if (urb->interval < 8)
- num_itds = 1 + (sched->span + 7) / 8;
- else
- num_itds = urb->number_of_packets;
-
- /* allocate/init ITDs */
- spin_lock_irqsave (&ehci->lock, flags);
- for (i = 0; i < num_itds; i++) {
-
- /* free_list.next might be cache-hot ... but maybe
- * the HC caches it too. avoid that issue for now.
- */
-
- /* prefer previously-allocated itds */
- if (likely (!list_empty(&stream->free_list))) {
- itd = list_entry (stream->free_list.prev,
- struct ehci_itd, itd_list);
- list_del (&itd->itd_list);
- itd_dma = itd->itd_dma;
- } else
- itd = NULL;
-
- if (!itd) {
- spin_unlock_irqrestore (&ehci->lock, flags);
- itd = dma_pool_alloc (ehci->itd_pool, mem_flags,
- &itd_dma);
- spin_lock_irqsave (&ehci->lock, flags);
- }
-
- if (unlikely (NULL == itd)) {
- iso_sched_free (stream, sched);
- spin_unlock_irqrestore (&ehci->lock, flags);
- return -ENOMEM;
- }
- memset (itd, 0, sizeof *itd);
- itd->itd_dma = itd_dma;
- list_add (&itd->itd_list, &sched->td_list);
- }
- spin_unlock_irqrestore (&ehci->lock, flags);
-
- /* temporarily store schedule info in hcpriv */
- urb->hcpriv = sched;
- urb->error_count = 0;
- return 0;
-}
-
/*-------------------------------------------------------------------------*/
static inline int
@@ -1416,12 +1341,19 @@ sitd_slot_ok (
#define SCHEDULE_SLOP 10 /* frames */
-static int
-iso_stream_schedule (
+/* iso_stream_schedule - schedules an iso request transaction into the
+ * periodic schedule, budgeting persistent periodic bandwidth for this
+ * stream if that has not yet been done.
+ *
+ * @ehci: pointer to ehci host controller device structure
+ * @urb: request
+ * @stream: persistent iso stream
+ */
+static int iso_stream_schedule (
struct ehci_hcd *ehci,
struct urb *urb,
struct ehci_iso_stream *stream
-)
+ )
{
u32 now, start, max, period;
int status;
@@ -1529,6 +1461,139 @@ ready:
/*-------------------------------------------------------------------------*/
+/* itd_sched_init - ITD-specific initialization of an ehci_iso_sched
+ * structure to hold the specifics of the current requested
+ * transaction during the various steps of budgeting and scheduling.
+ *
+ * @iso_sched: structure to initialize
+ * @stream: iso stream
+ * @urb: current request
+ */
+static inline void
+itd_sched_init (
+ struct ehci_iso_sched *iso_sched,
+ struct ehci_iso_stream *stream,
+ struct urb *urb
+)
+{
+ unsigned i;
+ dma_addr_t dma = urb->transfer_dma;
+
+ /* how many uframes are needed for these transfers */
+ iso_sched->span = urb->number_of_packets * stream->interval;
+
+ /* figure out per-uframe itd fields that we'll need later
+ * when we fit new itds into the schedule.
+ */
+ for (i = 0; i < urb->number_of_packets; i++) {
+ struct ehci_iso_packet *uframe = &iso_sched->packet [i];
+ unsigned length;
+ dma_addr_t buf;
+ u32 trans;
+
+ length = urb->iso_frame_desc [i].length;
+ buf = dma + urb->iso_frame_desc [i].offset;
+
+ trans = EHCI_ISOC_ACTIVE;
+ trans |= buf & 0x0fff;
+ if (unlikely (((i + 1) == urb->number_of_packets))
+ && !(urb->transfer_flags & URB_NO_INTERRUPT))
+ trans |= EHCI_ITD_IOC;
+ trans |= length << 16;
+ uframe->transaction = cpu_to_le32 (trans);
+
+ /* might need to cross a buffer page within a uframe */
+ uframe->bufp = (buf & ~(u64)0x0fff);
+ buf += length;
+ if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff))))
+ uframe->cross = 1;
+ }
+}
+
+/* itd_urb_transaction - sets up memory and relevant structures to
+ * process current transaction; initializes the iso_sched structure
+ * and preallocates transfer descriptors
+ *
+ * @stream: iso stream
+ * @ehci: pointer to ehci host controller device structure
+ * @urb: current request
+ * mem_flags: flags to use for in-kernel memory allocation
+ */
+static int
+itd_urb_transaction (
+ struct ehci_iso_stream *stream,
+ struct ehci_hcd *ehci,
+ struct urb *urb,
+ gfp_t mem_flags
+)
+{
+ struct ehci_itd *itd;
+ dma_addr_t itd_dma;
+ int i;
+ unsigned num_itds;
+ struct ehci_iso_sched *sched;
+ unsigned long flags;
+
+ sched = iso_sched_alloc (urb->number_of_packets, mem_flags);
+ if (unlikely (sched == NULL))
+ return -ENOMEM;
+
+ itd_sched_init (sched, stream, urb);
+
+ if (urb->interval < 8)
+ num_itds = 1 + (sched->span + 7) / 8;
+ else
+ num_itds = urb->number_of_packets;
+
+ /* allocate/init ITDs */
+ spin_lock_irqsave (&ehci->lock, flags);
+ for (i = 0; i < num_itds; i++) {
+
+ /* free_list.next might be cache-hot ... but maybe
+ * the HC caches it too. avoid that issue for now.
+ */
+
+ /* prefer previously-allocated itds */
+ if (likely (!list_empty(&stream->free_list))) {
+ itd = list_entry (stream->free_list.prev,
+ struct ehci_itd, itd_list);
+ list_del (&itd->itd_list);
+ itd_dma = itd->itd_dma;
+ } else
+ itd = NULL;
+
+ if (!itd) {
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ itd = dma_pool_alloc (ehci->itd_pool, mem_flags,
+ &itd_dma);
+ spin_lock_irqsave (&ehci->lock, flags);
+ }
+
+ if (unlikely (NULL == itd)) {
+ iso_sched_free (stream, sched);
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ return -ENOMEM;
+ }
+ memset (itd, 0, sizeof *itd);
+ itd->itd_dma = itd_dma;
+ list_add (&itd->itd_list, &sched->td_list);
+ }
+ spin_unlock_irqrestore (&ehci->lock, flags);
+
+ /* temporarily store schedule info in hcpriv */
+ urb->hcpriv = sched;
+ urb->error_count = 0;
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* itd_init - performs master initilization of the ITD fields that are
+ * drawn from the stream structure.
+ *
+ * @stream: iso stream
+ * @itd: New ITD that is to be added to the shadow/hardware schedule
+ */
static inline void
itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd)
{
@@ -1546,6 +1611,13 @@ itd_init (struct ehci_iso_stream *stream
/* All other fields are filled when scheduling */
}
+/* itd_patch - patches additional transfer descriptors into an existing ITD.
+ *
+ * @itd: New ITD that is to be added to the shadow/hardware schedule
+ * @iso_sched: ehci_iso_sched holding transfer descriptors
+ * @index: packet number to reference within the ehci_iso_sched
+ * @uframe: uframe in which to schedule specified packet
+ */
static inline void
itd_patch (
struct ehci_itd *itd,
@@ -1576,6 +1648,12 @@ itd_patch (
}
}
+/* itd_link - place one completed itd into the shadow/hardware schedule
+ *
+ * @ehci: pointer to ehci host controller device structure
+ * @frame: shadow/hardware schedule frame
+ * @itd: ITD to link into schedule
+ */
static inline void
itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
{
@@ -1588,7 +1666,14 @@ itd_link (struct ehci_hcd *ehci, unsigne
ehci->periodic [frame] = cpu_to_le32 (itd->itd_dma) | Q_TYPE_ITD;
}
-/* fit urb's itds into the selected schedule slot; activate as needed */
+/* itd_link_urb - link urb's ITDs into the hardware schedule acording
+ * to shadow budget
+ *
+ * @ehci: pointer to ehci host controller device structure
+ * @urb: current USB request
+ * @mod: size of periodic hardware schedule [in uFrames]
+ * @stream: stream into which to queue request
+ */
static int
itd_link_urb (
struct ehci_hcd *ehci,
@@ -1663,6 +1748,15 @@ itd_link_urb (
#define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE |
EHCI_ISOC_XACTERR)
+/* itd_complete - process a single complete ITD that has been removed
+ * from the periodic schedule and handed to us by scan_periodic. If
+ * this is the last ITD that needed to be completed for a URB, hand
+ * the URB back to the upper level driver.
+ *
+ * @ehci: pointer to ehci host controller device structure
+ * @itd: completed ITD
+ * @regs: ptrace registers
+ */
static unsigned
itd_complete (
struct ehci_hcd *ehci,
@@ -1744,8 +1838,13 @@ itd_complete (
return 1;
}
-/*-------------------------------------------------------------------------*/
-
+/* itd_submit - top level submission point for a HS isochronous
+ * endpoint request.
+ *
+ * @ehci: pointer to ehci host controller device structure
+ * @urb: new USB request
+ * @mem_flags: flags for memory allocation
+ */
static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
gfp_t mem_flags)
{
@@ -1803,12 +1902,17 @@ done:
#ifdef CONFIG_USB_EHCI_SPLIT_ISO
/*-------------------------------------------------------------------------*/
+/* Split-ISO transfer machinery; used for FS isoch transfers through the
+ * TTs in USB 2.0 hubs. */
-/*
- * "Split ISO TDs" ... used for USB 1.1 devices going through the
- * TTs in USB 2.0 hubs. These need microframe scheduling.
+/* sitd_sched_init - sITD-specific initialization of an ehci_iso_sched
+ * structure to hold the specifics of the current requested
+ * transaction during the various steps of budgeting and scheduling.
+ *
+ * @iso_sched: structure to initialize
+ * @stream: iso stream
+ * @urb: current request
*/
-
static inline void
sitd_sched_init (
struct ehci_iso_sched *iso_sched,
@@ -1857,6 +1961,15 @@ sitd_sched_init (
}
}
+/* sitd_urb_transaction - sets up memory and relevant structures to
+ * process current transaction; initializes the iso_sched structure
+ * and preallocates transfer descriptors
+ *
+ * @stream: iso stream
+ * @ehci: pointer to ehci host controller device structure
+ * @urb: current request
+ * @mem_flags: flags to use for in-kernel memory allocation
+ */
static int
sitd_urb_transaction (
struct ehci_iso_stream *stream,
@@ -1924,8 +2037,15 @@ sitd_urb_transaction (
return 0;
}
-/*-------------------------------------------------------------------------*/
-
+/* sitd_patch - finishes filling in the hardware fields of a sITD
+ * schedule prior to it being linked into the hardware/shadow
+ * schedule.
+ *
+ * @stream: stream into which this request will be queued
+ * @sitd: New sITD that is to be added to the shadow/hardware schedule
+ * @iso_sched: ehci_iso_sched holding transfer descriptors
+ * @index: packet number
+ */
static inline void
sitd_patch (
struct ehci_iso_stream *stream,
@@ -1954,6 +2074,13 @@ sitd_patch (
sitd->index = index;
}
+/* sitd_link - fill in and link one sITD into the shadow/hardware
+ * schedule
+ *
+ * @ehci: pointer to ehci host controller device structure
+ * @frame: shadow/hardware schedule frame
+ * @sitd: sitd to link
+ */
static inline void
sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd)
{
@@ -1966,7 +2093,14 @@ sitd_link (struct ehci_hcd *ehci, unsign
ehci->periodic [frame] = cpu_to_le32 (sitd->sitd_dma) | Q_TYPE_SITD;
}
-/* fit urb's sitds into the selected schedule slot; activate as needed */
+/* sitd_link_urb - link urb's sITDs into the hardware schedule
+ * acording to shadow budget
+ *
+ * @ehci: pointer to ehci host controller device structure
+ * @urb: current USB request
+ * @mod: size of periodic hardware schedule [in uFrames]
+ * @stream: stream into which to queue request
+ */
static int
sitd_link_urb (
struct ehci_hcd *ehci,
@@ -2029,11 +2163,18 @@ sitd_link_urb (
return 0;
}
-/*-------------------------------------------------------------------------*/
-
#define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \
| SITD_STS_XACT | SITD_STS_MMF)
+/* sitd_complete - process a single complete sITD that has been removed
+ * from the periodic schedule and handed to us by scan_periodic. If
+ * this is the last sITD that needed to be completed for a URB, hand
+ * the URB back to the upper level driver.
+ *
+ * @ehci: pointer to ehci host controller device structure
+ * @sitd: completed sITD
+ * @regs: ptrace registers
+ */
static unsigned
sitd_complete (
struct ehci_hcd *ehci,
@@ -2104,6 +2245,13 @@ sitd_complete (
}
+/* sitd_submit - top level submission point for a FS split isochronous
+ * endpoint request.
+ *
+ * @ehci: pointer to ehci host controller device structure
+ * @urb: new USB request
+ * @mem_flags: flags for memory allocation
+ */
static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
gfp_t mem_flags)
{
@@ -2177,8 +2325,15 @@ sitd_complete (
#endif /* USB_EHCI_SPLIT_ISO */
-/*-------------------------------------------------------------------------*/
-
+/* scan_periodic - completion worker; called out of interrupt (or
+ * poll) handler to finish processing of transactions that have been
+ * completed by the host controller. Also now has the responsibility
+ * of halting the hardware periodic schedule after a complete pass
+ * through the schedule with nothing to do.
+ *
+ * @ehci: pointer to ehci host controller device structure
+ * @regs: ptrace registers
+ */
static void
scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
{
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel