aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-07-11 11:22:39 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-16 19:54:26 -0400
commit8c5bf7be56f1a8aecc1f802f132d53f556a9bc45 (patch)
treed3b22a284f3f81b804bf9898928f866cfb8a45cd /drivers/usb
parent55934eb3b9fa52eb53b9d7342267fc73c38206aa (diff)
USB: EHCI: don't refcount iso_stream structures
This patch (as1580) makes ehci_iso_stream structures behave more like QHs, in that they will remain allocated until their isochronous endpoint is disabled. This will come in useful in the future, when periodic bandwidth gets allocated as an altsetting is installed rather than on-the-fly. For now, the change to the ehci_iso_stream lifetimes means that each structure is always deallocated at exactly one spot in ehci_endpoint_disable() and never used again. As a result, it is no longer necessary to use reference counting on these things, and the patch removes it. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/ehci-hcd.c12
-rw-r--r--drivers/usb/host/ehci-sched.c53
-rw-r--r--drivers/usb/host/ehci.h3
3 files changed, 16 insertions, 52 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 98b945840c9e..fb1966cf5649 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1085,8 +1085,14 @@ rescan:
1085 * accelerate iso completions ... so spin a while. 1085 * accelerate iso completions ... so spin a while.
1086 */ 1086 */
1087 if (qh->hw == NULL) { 1087 if (qh->hw == NULL) {
1088 ehci_vdbg (ehci, "iso delay\n"); 1088 struct ehci_iso_stream *stream = ep->hcpriv;
1089 goto idle_timeout; 1089
1090 if (!list_empty(&stream->td_list))
1091 goto idle_timeout;
1092
1093 /* BUG_ON(!list_empty(&stream->free_list)); */
1094 kfree(stream);
1095 goto done;
1090 } 1096 }
1091 1097
1092 if (ehci->rh_state < EHCI_RH_RUNNING) 1098 if (ehci->rh_state < EHCI_RH_RUNNING)
@@ -1127,8 +1133,8 @@ idle_timeout:
1127 list_empty (&qh->qtd_list) ? "" : "(has tds)"); 1133 list_empty (&qh->qtd_list) ? "" : "(has tds)");
1128 break; 1134 break;
1129 } 1135 }
1136 done:
1130 ep->hcpriv = NULL; 1137 ep->hcpriv = NULL;
1131done:
1132 spin_unlock_irqrestore (&ehci->lock, flags); 1138 spin_unlock_irqrestore (&ehci->lock, flags);
1133} 1139}
1134 1140
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 1e4f13c11b6a..11b2f21d7ac1 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -934,7 +934,6 @@ iso_stream_alloc (gfp_t mem_flags)
934 INIT_LIST_HEAD(&stream->td_list); 934 INIT_LIST_HEAD(&stream->td_list);
935 INIT_LIST_HEAD(&stream->free_list); 935 INIT_LIST_HEAD(&stream->free_list);
936 stream->next_uframe = -1; 936 stream->next_uframe = -1;
937 stream->refcount = 1;
938 } 937 }
939 return stream; 938 return stream;
940} 939}
@@ -1034,32 +1033,6 @@ iso_stream_init (
1034 stream->maxp = maxp; 1033 stream->maxp = maxp;
1035} 1034}
1036 1035
1037static void
1038iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
1039{
1040 stream->refcount--;
1041
1042 /* free whenever just a dev->ep reference remains.
1043 * not like a QH -- no persistent state (toggle, halt)
1044 */
1045 if (stream->refcount == 1) {
1046 // BUG_ON (!list_empty(&stream->td_list));
1047
1048 if (stream->ep)
1049 stream->ep->hcpriv = NULL;
1050
1051 kfree(stream);
1052 }
1053}
1054
1055static inline struct ehci_iso_stream *
1056iso_stream_get (struct ehci_iso_stream *stream)
1057{
1058 if (likely (stream != NULL))
1059 stream->refcount++;
1060 return stream;
1061}
1062
1063static struct ehci_iso_stream * 1036static struct ehci_iso_stream *
1064iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) 1037iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
1065{ 1038{
@@ -1080,7 +1053,6 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
1080 if (unlikely (stream == NULL)) { 1053 if (unlikely (stream == NULL)) {
1081 stream = iso_stream_alloc(GFP_ATOMIC); 1054 stream = iso_stream_alloc(GFP_ATOMIC);
1082 if (likely (stream != NULL)) { 1055 if (likely (stream != NULL)) {
1083 /* dev->ep owns the initial refcount */
1084 ep->hcpriv = stream; 1056 ep->hcpriv = stream;
1085 stream->ep = ep; 1057 stream->ep = ep;
1086 iso_stream_init(ehci, stream, urb->dev, urb->pipe, 1058 iso_stream_init(ehci, stream, urb->dev, urb->pipe,
@@ -1095,9 +1067,6 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
1095 stream = NULL; 1067 stream = NULL;
1096 } 1068 }
1097 1069
1098 /* caller guarantees an eventual matching iso_stream_put */
1099 stream = iso_stream_get (stream);
1100
1101 spin_unlock_irqrestore (&ehci->lock, flags); 1070 spin_unlock_irqrestore (&ehci->lock, flags);
1102 return stream; 1071 return stream;
1103} 1072}
@@ -1611,7 +1580,7 @@ static void itd_link_urb(
1611 itd = list_entry (iso_sched->td_list.next, 1580 itd = list_entry (iso_sched->td_list.next,
1612 struct ehci_itd, itd_list); 1581 struct ehci_itd, itd_list);
1613 list_move_tail (&itd->itd_list, &stream->td_list); 1582 list_move_tail (&itd->itd_list, &stream->td_list);
1614 itd->stream = iso_stream_get (stream); 1583 itd->stream = stream;
1615 itd->urb = urb; 1584 itd->urb = urb;
1616 itd_init (ehci, stream, itd); 1585 itd_init (ehci, stream, itd);
1617 } 1586 }
@@ -1735,7 +1704,6 @@ itd_complete (
1735 dev->devpath, stream->bEndpointAddress & 0x0f, 1704 dev->devpath, stream->bEndpointAddress & 0x0f,
1736 (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); 1705 (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
1737 } 1706 }
1738 iso_stream_put (ehci, stream);
1739 1707
1740done: 1708done:
1741 itd->urb = NULL; 1709 itd->urb = NULL;
@@ -1750,7 +1718,6 @@ done:
1750 start_free_itds(ehci); 1718 start_free_itds(ehci);
1751 } 1719 }
1752 1720
1753 iso_stream_put(ehci, stream);
1754 return retval; 1721 return retval;
1755} 1722}
1756 1723
@@ -1807,12 +1774,9 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
1807 itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); 1774 itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
1808 else 1775 else
1809 usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); 1776 usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
1810done_not_linked: 1777 done_not_linked:
1811 spin_unlock_irqrestore (&ehci->lock, flags); 1778 spin_unlock_irqrestore (&ehci->lock, flags);
1812 1779 done:
1813done:
1814 if (unlikely (status < 0))
1815 iso_stream_put (ehci, stream);
1816 return status; 1780 return status;
1817} 1781}
1818 1782
@@ -2028,7 +1992,7 @@ static void sitd_link_urb(
2028 sitd = list_entry (sched->td_list.next, 1992 sitd = list_entry (sched->td_list.next,
2029 struct ehci_sitd, sitd_list); 1993 struct ehci_sitd, sitd_list);
2030 list_move_tail (&sitd->sitd_list, &stream->td_list); 1994 list_move_tail (&sitd->sitd_list, &stream->td_list);
2031 sitd->stream = iso_stream_get (stream); 1995 sitd->stream = stream;
2032 sitd->urb = urb; 1996 sitd->urb = urb;
2033 1997
2034 sitd_patch(ehci, stream, sitd, sched, packet); 1998 sitd_patch(ehci, stream, sitd, sched, packet);
@@ -2126,7 +2090,6 @@ sitd_complete (
2126 dev->devpath, stream->bEndpointAddress & 0x0f, 2090 dev->devpath, stream->bEndpointAddress & 0x0f,
2127 (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); 2091 (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
2128 } 2092 }
2129 iso_stream_put (ehci, stream);
2130 2093
2131done: 2094done:
2132 sitd->urb = NULL; 2095 sitd->urb = NULL;
@@ -2141,7 +2104,6 @@ done:
2141 start_free_itds(ehci); 2104 start_free_itds(ehci);
2142 } 2105 }
2143 2106
2144 iso_stream_put(ehci, stream);
2145 return retval; 2107 return retval;
2146} 2108}
2147 2109
@@ -2195,12 +2157,9 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
2195 sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); 2157 sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
2196 else 2158 else
2197 usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); 2159 usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
2198done_not_linked: 2160 done_not_linked:
2199 spin_unlock_irqrestore (&ehci->lock, flags); 2161 spin_unlock_irqrestore (&ehci->lock, flags);
2200 2162 done:
2201done:
2202 if (status < 0)
2203 iso_stream_put (ehci, stream);
2204 return status; 2163 return status;
2205} 2164}
2206 2165
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index bcfbb175e2b4..755e30b0000b 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -386,7 +386,7 @@ struct ehci_qh_hw {
386} __attribute__ ((aligned(32))); 386} __attribute__ ((aligned(32)));
387 387
388struct ehci_qh { 388struct ehci_qh {
389 struct ehci_qh_hw *hw; 389 struct ehci_qh_hw *hw; /* Must come first */
390 /* the rest is HCD-private */ 390 /* the rest is HCD-private */
391 dma_addr_t qh_dma; /* address of qh */ 391 dma_addr_t qh_dma; /* address of qh */
392 union ehci_shadow qh_next; /* ptr to qh; or periodic */ 392 union ehci_shadow qh_next; /* ptr to qh; or periodic */
@@ -453,7 +453,6 @@ struct ehci_iso_stream {
453 /* first field matches ehci_hq, but is NULL */ 453 /* first field matches ehci_hq, but is NULL */
454 struct ehci_qh_hw *hw; 454 struct ehci_qh_hw *hw;
455 455
456 u32 refcount;
457 u8 bEndpointAddress; 456 u8 bEndpointAddress;
458 u8 highspeed; 457 u8 highspeed;
459 struct list_head td_list; /* queued itds/sitds */ 458 struct list_head td_list; /* queued itds/sitds */