aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/ehci-sched.c2
-rw-r--r--drivers/usb/host/whci/asl.c15
-rw-r--r--drivers/usb/host/whci/hcd.c23
-rw-r--r--drivers/usb/host/whci/pzl.c16
-rw-r--r--drivers/usb/host/whci/qset.c24
-rw-r--r--drivers/usb/host/whci/whcd.h1
-rw-r--r--drivers/usb/host/whci/whci-hc.h1
7 files changed, 69 insertions, 13 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index ada5d2ba297b..556d0ec0c1f8 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -323,7 +323,7 @@ static int tt_available (
323 * already scheduled transactions 323 * already scheduled transactions
324 */ 324 */
325 if (125 < usecs) { 325 if (125 < usecs) {
326 int ufs = (usecs / 125) - 1; 326 int ufs = (usecs / 125);
327 int i; 327 int i;
328 for (i = uframe; i < (uframe + ufs) && i < 8; i++) 328 for (i = uframe; i < (uframe + ufs) && i < 8; i++)
329 if (0 < tt_usecs[i]) { 329 if (0 < tt_usecs[i]) {
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c
index 958751ccea43..c2050785a819 100644
--- a/drivers/usb/host/whci/asl.c
+++ b/drivers/usb/host/whci/asl.c
@@ -122,7 +122,8 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset)
122 process_inactive_qtd(whc, qset, td); 122 process_inactive_qtd(whc, qset, td);
123 } 123 }
124 124
125 update |= qset_add_qtds(whc, qset); 125 if (!qset->remove)
126 update |= qset_add_qtds(whc, qset);
126 127
127done: 128done:
128 /* 129 /*
@@ -254,23 +255,29 @@ int asl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags)
254 255
255 spin_lock_irqsave(&whc->lock, flags); 256 spin_lock_irqsave(&whc->lock, flags);
256 257
258 err = usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb);
259 if (err < 0) {
260 spin_unlock_irqrestore(&whc->lock, flags);
261 return err;
262 }
263
257 qset = get_qset(whc, urb, GFP_ATOMIC); 264 qset = get_qset(whc, urb, GFP_ATOMIC);
258 if (qset == NULL) 265 if (qset == NULL)
259 err = -ENOMEM; 266 err = -ENOMEM;
260 else 267 else
261 err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); 268 err = qset_add_urb(whc, qset, urb, GFP_ATOMIC);
262 if (!err) { 269 if (!err) {
263 usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb);
264 if (!qset->in_sw_list) 270 if (!qset->in_sw_list)
265 asl_qset_insert_begin(whc, qset); 271 asl_qset_insert_begin(whc, qset);
266 } 272 } else
273 usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb);
267 274
268 spin_unlock_irqrestore(&whc->lock, flags); 275 spin_unlock_irqrestore(&whc->lock, flags);
269 276
270 if (!err) 277 if (!err)
271 queue_work(whc->workqueue, &whc->async_work); 278 queue_work(whc->workqueue, &whc->async_work);
272 279
273 return 0; 280 return err;
274} 281}
275 282
276/** 283/**
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c
index 1569afd6245b..e019a5058ab8 100644
--- a/drivers/usb/host/whci/hcd.c
+++ b/drivers/usb/host/whci/hcd.c
@@ -186,6 +186,28 @@ static void whc_endpoint_disable(struct usb_hcd *usb_hcd,
186 } 186 }
187} 187}
188 188
189static void whc_endpoint_reset(struct usb_hcd *usb_hcd,
190 struct usb_host_endpoint *ep)
191{
192 struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd);
193 struct whc *whc = wusbhc_to_whc(wusbhc);
194 struct whc_qset *qset;
195
196 qset = ep->hcpriv;
197 if (qset) {
198 qset->remove = 1;
199
200 if (usb_endpoint_xfer_bulk(&ep->desc)
201 || usb_endpoint_xfer_control(&ep->desc))
202 queue_work(whc->workqueue, &whc->async_work);
203 else
204 queue_work(whc->workqueue, &whc->periodic_work);
205
206 qset_reset(whc, qset);
207 }
208}
209
210
189static struct hc_driver whc_hc_driver = { 211static struct hc_driver whc_hc_driver = {
190 .description = "whci-hcd", 212 .description = "whci-hcd",
191 .product_desc = "Wireless host controller", 213 .product_desc = "Wireless host controller",
@@ -200,6 +222,7 @@ static struct hc_driver whc_hc_driver = {
200 .urb_enqueue = whc_urb_enqueue, 222 .urb_enqueue = whc_urb_enqueue,
201 .urb_dequeue = whc_urb_dequeue, 223 .urb_dequeue = whc_urb_dequeue,
202 .endpoint_disable = whc_endpoint_disable, 224 .endpoint_disable = whc_endpoint_disable,
225 .endpoint_reset = whc_endpoint_reset,
203 226
204 .hub_status_data = wusbhc_rh_status_data, 227 .hub_status_data = wusbhc_rh_status_data,
205 .hub_control = wusbhc_rh_control, 228 .hub_control = wusbhc_rh_control,
diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c
index df8b85f07092..ff4ef9e910d9 100644
--- a/drivers/usb/host/whci/pzl.c
+++ b/drivers/usb/host/whci/pzl.c
@@ -128,7 +128,8 @@ static enum whc_update pzl_process_qset(struct whc *whc, struct whc_qset *qset)
128 process_inactive_qtd(whc, qset, td); 128 process_inactive_qtd(whc, qset, td);
129 } 129 }
130 130
131 update |= qset_add_qtds(whc, qset); 131 if (!qset->remove)
132 update |= qset_add_qtds(whc, qset);
132 133
133done: 134done:
134 /* 135 /*
@@ -282,23 +283,29 @@ int pzl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags)
282 283
283 spin_lock_irqsave(&whc->lock, flags); 284 spin_lock_irqsave(&whc->lock, flags);
284 285
286 err = usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb);
287 if (err < 0) {
288 spin_unlock_irqrestore(&whc->lock, flags);
289 return err;
290 }
291
285 qset = get_qset(whc, urb, GFP_ATOMIC); 292 qset = get_qset(whc, urb, GFP_ATOMIC);
286 if (qset == NULL) 293 if (qset == NULL)
287 err = -ENOMEM; 294 err = -ENOMEM;
288 else 295 else
289 err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); 296 err = qset_add_urb(whc, qset, urb, GFP_ATOMIC);
290 if (!err) { 297 if (!err) {
291 usb_hcd_link_urb_to_ep(&whc->wusbhc.usb_hcd, urb);
292 if (!qset->in_sw_list) 298 if (!qset->in_sw_list)
293 qset_insert_in_sw_list(whc, qset); 299 qset_insert_in_sw_list(whc, qset);
294 } 300 } else
301 usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb);
295 302
296 spin_unlock_irqrestore(&whc->lock, flags); 303 spin_unlock_irqrestore(&whc->lock, flags);
297 304
298 if (!err) 305 if (!err)
299 queue_work(whc->workqueue, &whc->periodic_work); 306 queue_work(whc->workqueue, &whc->periodic_work);
300 307
301 return 0; 308 return err;
302} 309}
303 310
304/** 311/**
@@ -353,7 +360,6 @@ void pzl_qset_delete(struct whc *whc, struct whc_qset *qset)
353 qset_delete(whc, qset); 360 qset_delete(whc, qset);
354} 361}
355 362
356
357/** 363/**
358 * pzl_init - initialize the periodic zone list 364 * pzl_init - initialize the periodic zone list
359 * @whc: the WHCI host controller 365 * @whc: the WHCI host controller
diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c
index 7be74314ee12..640b38fbd051 100644
--- a/drivers/usb/host/whci/qset.c
+++ b/drivers/usb/host/whci/qset.c
@@ -89,11 +89,16 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb)
89 QH_INFO3_TX_RATE_53_3 89 QH_INFO3_TX_RATE_53_3
90 | QH_INFO3_TX_PWR(0) /* 0 == max power */ 90 | QH_INFO3_TX_PWR(0) /* 0 == max power */
91 ); 91 );
92
93 qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
92} 94}
93 95
94/** 96/**
95 * qset_clear - clear fields in a qset so it may be reinserted into a 97 * qset_clear - clear fields in a qset so it may be reinserted into a
96 * schedule 98 * schedule.
99 *
100 * The sequence number and current window are not cleared (see
101 * qset_reset()).
97 */ 102 */
98void qset_clear(struct whc *whc, struct whc_qset *qset) 103void qset_clear(struct whc *whc, struct whc_qset *qset)
99{ 104{
@@ -101,9 +106,8 @@ void qset_clear(struct whc *whc, struct whc_qset *qset)
101 qset->remove = 0; 106 qset->remove = 0;
102 107
103 qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); 108 qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T);
104 qset->qh.status = cpu_to_le16(QH_STATUS_ICUR(qset->td_start)); 109 qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK;
105 qset->qh.err_count = 0; 110 qset->qh.err_count = 0;
106 qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
107 qset->qh.scratch[0] = 0; 111 qset->qh.scratch[0] = 0;
108 qset->qh.scratch[1] = 0; 112 qset->qh.scratch[1] = 0;
109 qset->qh.scratch[2] = 0; 113 qset->qh.scratch[2] = 0;
@@ -114,6 +118,20 @@ void qset_clear(struct whc *whc, struct whc_qset *qset)
114} 118}
115 119
116/** 120/**
121 * qset_reset - reset endpoint state in a qset.
122 *
123 * Clears the sequence number and current window. This qset must not
124 * be in the ASL or PZL.
125 */
126void qset_reset(struct whc *whc, struct whc_qset *qset)
127{
128 wait_for_completion(&qset->remove_complete);
129
130 qset->qh.status &= ~QH_STATUS_SEQ_MASK;
131 qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
132}
133
134/**
117 * get_qset - get the qset for an async endpoint 135 * get_qset - get the qset for an async endpoint
118 * 136 *
119 * A new qset is created if one does not already exist. 137 * A new qset is created if one does not already exist.
diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h
index d3543a181dc9..24e94d983c5e 100644
--- a/drivers/usb/host/whci/whcd.h
+++ b/drivers/usb/host/whci/whcd.h
@@ -184,6 +184,7 @@ void qset_free(struct whc *whc, struct whc_qset *qset);
184struct whc_qset *get_qset(struct whc *whc, struct urb *urb, gfp_t mem_flags); 184struct whc_qset *get_qset(struct whc *whc, struct urb *urb, gfp_t mem_flags);
185void qset_delete(struct whc *whc, struct whc_qset *qset); 185void qset_delete(struct whc *whc, struct whc_qset *qset);
186void qset_clear(struct whc *whc, struct whc_qset *qset); 186void qset_clear(struct whc *whc, struct whc_qset *qset);
187void qset_reset(struct whc *whc, struct whc_qset *qset);
187int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb, 188int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb,
188 gfp_t mem_flags); 189 gfp_t mem_flags);
189void qset_free_std(struct whc *whc, struct whc_std *std); 190void qset_free_std(struct whc *whc, struct whc_std *std);
diff --git a/drivers/usb/host/whci/whci-hc.h b/drivers/usb/host/whci/whci-hc.h
index 51df7e313b38..794dba0d0f0a 100644
--- a/drivers/usb/host/whci/whci-hc.h
+++ b/drivers/usb/host/whci/whci-hc.h
@@ -185,6 +185,7 @@ struct whc_qhead {
185#define QH_STATUS_FLOW_CTRL (1 << 15) 185#define QH_STATUS_FLOW_CTRL (1 << 15)
186#define QH_STATUS_ICUR(i) ((i) << 5) 186#define QH_STATUS_ICUR(i) ((i) << 5)
187#define QH_STATUS_TO_ICUR(s) (((s) >> 5) & 0x7) 187#define QH_STATUS_TO_ICUR(s) (((s) >> 5) & 0x7)
188#define QH_STATUS_SEQ_MASK 0x1f
188 189
189/** 190/**
190 * usb_pipe_to_qh_type - USB core pipe type to QH transfer type 191 * usb_pipe_to_qh_type - USB core pipe type to QH transfer type