diff options
Diffstat (limited to 'drivers/usb/host/whci')
-rw-r--r-- | drivers/usb/host/whci/asl.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/whci/debug.c | 21 | ||||
-rw-r--r-- | drivers/usb/host/whci/hcd.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/whci/init.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/whci/pzl.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/whci/qset.c | 351 | ||||
-rw-r--r-- | drivers/usb/host/whci/whcd.h | 9 | ||||
-rw-r--r-- | drivers/usb/host/whci/whci-hc.h | 14 |
8 files changed, 353 insertions, 46 deletions
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index 562eba108816..773249306031 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/usb/host/whci/asl.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/gfp.h> | ||
19 | #include <linux/dma-mapping.h> | 20 | #include <linux/dma-mapping.h> |
20 | #include <linux/uwb/umc.h> | 21 | #include <linux/uwb/umc.h> |
21 | #include <linux/usb.h> | 22 | #include <linux/usb.h> |
diff --git a/drivers/usb/host/whci/debug.c b/drivers/usb/host/whci/debug.c index 2273c815941f..c5305b599ca0 100644 --- a/drivers/usb/host/whci/debug.c +++ b/drivers/usb/host/whci/debug.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | #include <linux/slab.h> | ||
18 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
19 | #include <linux/debugfs.h> | 20 | #include <linux/debugfs.h> |
20 | #include <linux/seq_file.h> | 21 | #include <linux/seq_file.h> |
@@ -31,17 +32,29 @@ struct whc_dbg { | |||
31 | 32 | ||
32 | void qset_print(struct seq_file *s, struct whc_qset *qset) | 33 | void qset_print(struct seq_file *s, struct whc_qset *qset) |
33 | { | 34 | { |
35 | static const char *qh_type[] = { | ||
36 | "ctrl", "isoc", "bulk", "intr", "rsvd", "rsvd", "rsvd", "lpintr", }; | ||
34 | struct whc_std *std; | 37 | struct whc_std *std; |
35 | struct urb *urb = NULL; | 38 | struct urb *urb = NULL; |
36 | int i; | 39 | int i; |
37 | 40 | ||
38 | seq_printf(s, "qset %08x\n", (u32)qset->qset_dma); | 41 | seq_printf(s, "qset %08x", (u32)qset->qset_dma); |
42 | if (&qset->list_node == qset->whc->async_list.prev) { | ||
43 | seq_printf(s, " (dummy)\n"); | ||
44 | } else { | ||
45 | seq_printf(s, " ep%d%s-%s maxpkt: %d\n", | ||
46 | qset->qh.info1 & 0x0f, | ||
47 | (qset->qh.info1 >> 4) & 0x1 ? "in" : "out", | ||
48 | qh_type[(qset->qh.info1 >> 5) & 0x7], | ||
49 | (qset->qh.info1 >> 16) & 0xffff); | ||
50 | } | ||
39 | seq_printf(s, " -> %08x\n", (u32)qset->qh.link); | 51 | seq_printf(s, " -> %08x\n", (u32)qset->qh.link); |
40 | seq_printf(s, " info: %08x %08x %08x\n", | 52 | seq_printf(s, " info: %08x %08x %08x\n", |
41 | qset->qh.info1, qset->qh.info2, qset->qh.info3); | 53 | qset->qh.info1, qset->qh.info2, qset->qh.info3); |
42 | seq_printf(s, " sts: %04x errs: %d\n", qset->qh.status, qset->qh.err_count); | 54 | seq_printf(s, " sts: %04x errs: %d curwin: %08x\n", |
55 | qset->qh.status, qset->qh.err_count, qset->qh.cur_window); | ||
43 | seq_printf(s, " TD: sts: %08x opts: %08x\n", | 56 | seq_printf(s, " TD: sts: %08x opts: %08x\n", |
44 | qset->qh.overlay.qtd.status, qset->qh.overlay.qtd.options); | 57 | qset->qh.overlay.qtd.status, qset->qh.overlay.qtd.options); |
45 | 58 | ||
46 | for (i = 0; i < WHCI_QSET_TD_MAX; i++) { | 59 | for (i = 0; i < WHCI_QSET_TD_MAX; i++) { |
47 | seq_printf(s, " %c%c TD[%d]: sts: %08x opts: %08x ptr: %08x\n", | 60 | seq_printf(s, " %c%c TD[%d]: sts: %08x opts: %08x ptr: %08x\n", |
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c index 687b622a1612..e0d3401285c8 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/usb/host/whci/hcd.c | |||
@@ -250,6 +250,7 @@ static int whc_probe(struct umc_dev *umc) | |||
250 | } | 250 | } |
251 | 251 | ||
252 | usb_hcd->wireless = 1; | 252 | usb_hcd->wireless = 1; |
253 | usb_hcd->self.sg_tablesize = 2048; /* somewhat arbitrary */ | ||
253 | 254 | ||
254 | wusbhc = usb_hcd_to_wusbhc(usb_hcd); | 255 | wusbhc = usb_hcd_to_wusbhc(usb_hcd); |
255 | whc = wusbhc_to_whc(wusbhc); | 256 | whc = wusbhc_to_whc(wusbhc); |
diff --git a/drivers/usb/host/whci/init.c b/drivers/usb/host/whci/init.c index 34a783cb0133..f7582e8e2169 100644 --- a/drivers/usb/host/whci/init.c +++ b/drivers/usb/host/whci/init.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/gfp.h> | ||
19 | #include <linux/dma-mapping.h> | 20 | #include <linux/dma-mapping.h> |
20 | #include <linux/uwb/umc.h> | 21 | #include <linux/uwb/umc.h> |
21 | 22 | ||
diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c index 0db3fb2dc03a..33c5580b4d25 100644 --- a/drivers/usb/host/whci/pzl.c +++ b/drivers/usb/host/whci/pzl.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/gfp.h> | ||
19 | #include <linux/dma-mapping.h> | 20 | #include <linux/dma-mapping.h> |
20 | #include <linux/uwb/umc.h> | 21 | #include <linux/uwb/umc.h> |
21 | #include <linux/usb.h> | 22 | #include <linux/usb.h> |
diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index 1b9dc1571570..141d049beb3e 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/dma-mapping.h> | 19 | #include <linux/dma-mapping.h> |
20 | #include <linux/slab.h> | ||
20 | #include <linux/uwb/umc.h> | 21 | #include <linux/uwb/umc.h> |
21 | #include <linux/usb.h> | 22 | #include <linux/usb.h> |
22 | 23 | ||
@@ -49,16 +50,19 @@ struct whc_qset *qset_alloc(struct whc *whc, gfp_t mem_flags) | |||
49 | * state | 50 | * state |
50 | * @urb: an urb for a transfer to this endpoint | 51 | * @urb: an urb for a transfer to this endpoint |
51 | */ | 52 | */ |
52 | static void qset_fill_qh(struct whc_qset *qset, struct urb *urb) | 53 | static void qset_fill_qh(struct whc *whc, struct whc_qset *qset, struct urb *urb) |
53 | { | 54 | { |
54 | struct usb_device *usb_dev = urb->dev; | 55 | struct usb_device *usb_dev = urb->dev; |
56 | struct wusb_dev *wusb_dev = usb_dev->wusb_dev; | ||
55 | struct usb_wireless_ep_comp_descriptor *epcd; | 57 | struct usb_wireless_ep_comp_descriptor *epcd; |
56 | bool is_out; | 58 | bool is_out; |
59 | uint8_t phy_rate; | ||
57 | 60 | ||
58 | is_out = usb_pipeout(urb->pipe); | 61 | is_out = usb_pipeout(urb->pipe); |
59 | 62 | ||
60 | epcd = (struct usb_wireless_ep_comp_descriptor *)qset->ep->extra; | 63 | qset->max_packet = le16_to_cpu(urb->ep->desc.wMaxPacketSize); |
61 | 64 | ||
65 | epcd = (struct usb_wireless_ep_comp_descriptor *)qset->ep->extra; | ||
62 | if (epcd) { | 66 | if (epcd) { |
63 | qset->max_seq = epcd->bMaxSequence; | 67 | qset->max_seq = epcd->bMaxSequence; |
64 | qset->max_burst = epcd->bMaxBurst; | 68 | qset->max_burst = epcd->bMaxBurst; |
@@ -67,12 +71,28 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb) | |||
67 | qset->max_burst = 1; | 71 | qset->max_burst = 1; |
68 | } | 72 | } |
69 | 73 | ||
74 | /* | ||
75 | * Initial PHY rate is 53.3 Mbit/s for control endpoints or | ||
76 | * the maximum supported by the device for other endpoints | ||
77 | * (unless limited by the user). | ||
78 | */ | ||
79 | if (usb_pipecontrol(urb->pipe)) | ||
80 | phy_rate = UWB_PHY_RATE_53; | ||
81 | else { | ||
82 | uint16_t phy_rates; | ||
83 | |||
84 | phy_rates = le16_to_cpu(wusb_dev->wusb_cap_descr->wPHYRates); | ||
85 | phy_rate = fls(phy_rates) - 1; | ||
86 | if (phy_rate > whc->wusbhc.phy_rate) | ||
87 | phy_rate = whc->wusbhc.phy_rate; | ||
88 | } | ||
89 | |||
70 | qset->qh.info1 = cpu_to_le32( | 90 | qset->qh.info1 = cpu_to_le32( |
71 | QH_INFO1_EP(usb_pipeendpoint(urb->pipe)) | 91 | QH_INFO1_EP(usb_pipeendpoint(urb->pipe)) |
72 | | (is_out ? QH_INFO1_DIR_OUT : QH_INFO1_DIR_IN) | 92 | | (is_out ? QH_INFO1_DIR_OUT : QH_INFO1_DIR_IN) |
73 | | usb_pipe_to_qh_type(urb->pipe) | 93 | | usb_pipe_to_qh_type(urb->pipe) |
74 | | QH_INFO1_DEV_INFO_IDX(wusb_port_no_to_idx(usb_dev->portnum)) | 94 | | QH_INFO1_DEV_INFO_IDX(wusb_port_no_to_idx(usb_dev->portnum)) |
75 | | QH_INFO1_MAX_PKT_LEN(usb_maxpacket(urb->dev, urb->pipe, is_out)) | 95 | | QH_INFO1_MAX_PKT_LEN(qset->max_packet) |
76 | ); | 96 | ); |
77 | qset->qh.info2 = cpu_to_le32( | 97 | qset->qh.info2 = cpu_to_le32( |
78 | QH_INFO2_BURST(qset->max_burst) | 98 | QH_INFO2_BURST(qset->max_burst) |
@@ -86,7 +106,7 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb) | |||
86 | * strength and can presumably guess the Tx power required | 106 | * strength and can presumably guess the Tx power required |
87 | * from that? */ | 107 | * from that? */ |
88 | qset->qh.info3 = cpu_to_le32( | 108 | qset->qh.info3 = cpu_to_le32( |
89 | QH_INFO3_TX_RATE_53_3 | 109 | QH_INFO3_TX_RATE(phy_rate) |
90 | | QH_INFO3_TX_PWR(0) /* 0 == max power */ | 110 | | QH_INFO3_TX_PWR(0) /* 0 == max power */ |
91 | ); | 111 | ); |
92 | 112 | ||
@@ -148,7 +168,7 @@ struct whc_qset *get_qset(struct whc *whc, struct urb *urb, | |||
148 | 168 | ||
149 | qset->ep = urb->ep; | 169 | qset->ep = urb->ep; |
150 | urb->ep->hcpriv = qset; | 170 | urb->ep->hcpriv = qset; |
151 | qset_fill_qh(qset, urb); | 171 | qset_fill_qh(whc, qset, urb); |
152 | } | 172 | } |
153 | return qset; | 173 | return qset; |
154 | } | 174 | } |
@@ -241,6 +261,36 @@ static void qset_remove_qtd(struct whc *whc, struct whc_qset *qset) | |||
241 | qset->ntds--; | 261 | qset->ntds--; |
242 | } | 262 | } |
243 | 263 | ||
264 | static void qset_copy_bounce_to_sg(struct whc *whc, struct whc_std *std) | ||
265 | { | ||
266 | struct scatterlist *sg; | ||
267 | void *bounce; | ||
268 | size_t remaining, offset; | ||
269 | |||
270 | bounce = std->bounce_buf; | ||
271 | remaining = std->len; | ||
272 | |||
273 | sg = std->bounce_sg; | ||
274 | offset = std->bounce_offset; | ||
275 | |||
276 | while (remaining) { | ||
277 | size_t len; | ||
278 | |||
279 | len = min(sg->length - offset, remaining); | ||
280 | memcpy(sg_virt(sg) + offset, bounce, len); | ||
281 | |||
282 | bounce += len; | ||
283 | remaining -= len; | ||
284 | |||
285 | offset += len; | ||
286 | if (offset >= sg->length) { | ||
287 | sg = sg_next(sg); | ||
288 | offset = 0; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | } | ||
293 | |||
244 | /** | 294 | /** |
245 | * qset_free_std - remove an sTD and free it. | 295 | * qset_free_std - remove an sTD and free it. |
246 | * @whc: the WHCI host controller | 296 | * @whc: the WHCI host controller |
@@ -249,13 +299,29 @@ static void qset_remove_qtd(struct whc *whc, struct whc_qset *qset) | |||
249 | void qset_free_std(struct whc *whc, struct whc_std *std) | 299 | void qset_free_std(struct whc *whc, struct whc_std *std) |
250 | { | 300 | { |
251 | list_del(&std->list_node); | 301 | list_del(&std->list_node); |
252 | if (std->num_pointers) { | 302 | if (std->bounce_buf) { |
253 | dma_unmap_single(whc->wusbhc.dev, std->dma_addr, | 303 | bool is_out = usb_pipeout(std->urb->pipe); |
254 | std->num_pointers * sizeof(struct whc_page_list_entry), | 304 | dma_addr_t dma_addr; |
255 | DMA_TO_DEVICE); | 305 | |
306 | if (std->num_pointers) | ||
307 | dma_addr = le64_to_cpu(std->pl_virt[0].buf_ptr); | ||
308 | else | ||
309 | dma_addr = std->dma_addr; | ||
310 | |||
311 | dma_unmap_single(whc->wusbhc.dev, dma_addr, | ||
312 | std->len, is_out ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
313 | if (!is_out) | ||
314 | qset_copy_bounce_to_sg(whc, std); | ||
315 | kfree(std->bounce_buf); | ||
316 | } | ||
317 | if (std->pl_virt) { | ||
318 | if (std->dma_addr) | ||
319 | dma_unmap_single(whc->wusbhc.dev, std->dma_addr, | ||
320 | std->num_pointers * sizeof(struct whc_page_list_entry), | ||
321 | DMA_TO_DEVICE); | ||
256 | kfree(std->pl_virt); | 322 | kfree(std->pl_virt); |
323 | std->pl_virt = NULL; | ||
257 | } | 324 | } |
258 | |||
259 | kfree(std); | 325 | kfree(std); |
260 | } | 326 | } |
261 | 327 | ||
@@ -293,12 +359,17 @@ static int qset_fill_page_list(struct whc *whc, struct whc_std *std, gfp_t mem_f | |||
293 | { | 359 | { |
294 | dma_addr_t dma_addr = std->dma_addr; | 360 | dma_addr_t dma_addr = std->dma_addr; |
295 | dma_addr_t sp, ep; | 361 | dma_addr_t sp, ep; |
296 | size_t std_len = std->len; | ||
297 | size_t pl_len; | 362 | size_t pl_len; |
298 | int p; | 363 | int p; |
299 | 364 | ||
300 | sp = ALIGN(dma_addr, WHCI_PAGE_SIZE); | 365 | /* Short buffers don't need a page list. */ |
301 | ep = dma_addr + std_len; | 366 | if (std->len <= WHCI_PAGE_SIZE) { |
367 | std->num_pointers = 0; | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | sp = dma_addr & ~(WHCI_PAGE_SIZE-1); | ||
372 | ep = dma_addr + std->len; | ||
302 | std->num_pointers = DIV_ROUND_UP(ep - sp, WHCI_PAGE_SIZE); | 373 | std->num_pointers = DIV_ROUND_UP(ep - sp, WHCI_PAGE_SIZE); |
303 | 374 | ||
304 | pl_len = std->num_pointers * sizeof(struct whc_page_list_entry); | 375 | pl_len = std->num_pointers * sizeof(struct whc_page_list_entry); |
@@ -309,7 +380,7 @@ static int qset_fill_page_list(struct whc *whc, struct whc_std *std, gfp_t mem_f | |||
309 | 380 | ||
310 | for (p = 0; p < std->num_pointers; p++) { | 381 | for (p = 0; p < std->num_pointers; p++) { |
311 | std->pl_virt[p].buf_ptr = cpu_to_le64(dma_addr); | 382 | std->pl_virt[p].buf_ptr = cpu_to_le64(dma_addr); |
312 | dma_addr = ALIGN(dma_addr + WHCI_PAGE_SIZE, WHCI_PAGE_SIZE); | 383 | dma_addr = (dma_addr + WHCI_PAGE_SIZE) & ~(WHCI_PAGE_SIZE-1); |
313 | } | 384 | } |
314 | 385 | ||
315 | return 0; | 386 | return 0; |
@@ -339,6 +410,218 @@ static void urb_dequeue_work(struct work_struct *work) | |||
339 | spin_unlock_irqrestore(&whc->lock, flags); | 410 | spin_unlock_irqrestore(&whc->lock, flags); |
340 | } | 411 | } |
341 | 412 | ||
413 | static struct whc_std *qset_new_std(struct whc *whc, struct whc_qset *qset, | ||
414 | struct urb *urb, gfp_t mem_flags) | ||
415 | { | ||
416 | struct whc_std *std; | ||
417 | |||
418 | std = kzalloc(sizeof(struct whc_std), mem_flags); | ||
419 | if (std == NULL) | ||
420 | return NULL; | ||
421 | |||
422 | std->urb = urb; | ||
423 | std->qtd = NULL; | ||
424 | |||
425 | INIT_LIST_HEAD(&std->list_node); | ||
426 | list_add_tail(&std->list_node, &qset->stds); | ||
427 | |||
428 | return std; | ||
429 | } | ||
430 | |||
431 | static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *urb, | ||
432 | gfp_t mem_flags) | ||
433 | { | ||
434 | size_t remaining; | ||
435 | struct scatterlist *sg; | ||
436 | int i; | ||
437 | int ntds = 0; | ||
438 | struct whc_std *std = NULL; | ||
439 | struct whc_page_list_entry *entry; | ||
440 | dma_addr_t prev_end = 0; | ||
441 | size_t pl_len; | ||
442 | int p = 0; | ||
443 | |||
444 | remaining = urb->transfer_buffer_length; | ||
445 | |||
446 | for_each_sg(urb->sg->sg, sg, urb->num_sgs, i) { | ||
447 | dma_addr_t dma_addr; | ||
448 | size_t dma_remaining; | ||
449 | dma_addr_t sp, ep; | ||
450 | int num_pointers; | ||
451 | |||
452 | if (remaining == 0) { | ||
453 | break; | ||
454 | } | ||
455 | |||
456 | dma_addr = sg_dma_address(sg); | ||
457 | dma_remaining = min_t(size_t, sg_dma_len(sg), remaining); | ||
458 | |||
459 | while (dma_remaining) { | ||
460 | size_t dma_len; | ||
461 | |||
462 | /* | ||
463 | * We can use the previous std (if it exists) provided that: | ||
464 | * - the previous one ended on a page boundary. | ||
465 | * - the current one begins on a page boundary. | ||
466 | * - the previous one isn't full. | ||
467 | * | ||
468 | * If a new std is needed but the previous one | ||
469 | * was not a whole number of packets then this | ||
470 | * sg list cannot be mapped onto multiple | ||
471 | * qTDs. Return an error and let the caller | ||
472 | * sort it out. | ||
473 | */ | ||
474 | if (!std | ||
475 | || (prev_end & (WHCI_PAGE_SIZE-1)) | ||
476 | || (dma_addr & (WHCI_PAGE_SIZE-1)) | ||
477 | || std->len + WHCI_PAGE_SIZE > QTD_MAX_XFER_SIZE) { | ||
478 | if (std->len % qset->max_packet != 0) | ||
479 | return -EINVAL; | ||
480 | std = qset_new_std(whc, qset, urb, mem_flags); | ||
481 | if (std == NULL) { | ||
482 | return -ENOMEM; | ||
483 | } | ||
484 | ntds++; | ||
485 | p = 0; | ||
486 | } | ||
487 | |||
488 | dma_len = dma_remaining; | ||
489 | |||
490 | /* | ||
491 | * If the remainder of this element doesn't | ||
492 | * fit in a single qTD, limit the qTD to a | ||
493 | * whole number of packets. This allows the | ||
494 | * remainder to go into the next qTD. | ||
495 | */ | ||
496 | if (std->len + dma_len > QTD_MAX_XFER_SIZE) { | ||
497 | dma_len = (QTD_MAX_XFER_SIZE / qset->max_packet) | ||
498 | * qset->max_packet - std->len; | ||
499 | } | ||
500 | |||
501 | std->len += dma_len; | ||
502 | std->ntds_remaining = -1; /* filled in later */ | ||
503 | |||
504 | sp = dma_addr & ~(WHCI_PAGE_SIZE-1); | ||
505 | ep = dma_addr + dma_len; | ||
506 | num_pointers = DIV_ROUND_UP(ep - sp, WHCI_PAGE_SIZE); | ||
507 | std->num_pointers += num_pointers; | ||
508 | |||
509 | pl_len = std->num_pointers * sizeof(struct whc_page_list_entry); | ||
510 | |||
511 | std->pl_virt = krealloc(std->pl_virt, pl_len, mem_flags); | ||
512 | if (std->pl_virt == NULL) { | ||
513 | return -ENOMEM; | ||
514 | } | ||
515 | |||
516 | for (;p < std->num_pointers; p++, entry++) { | ||
517 | std->pl_virt[p].buf_ptr = cpu_to_le64(dma_addr); | ||
518 | dma_addr = (dma_addr + WHCI_PAGE_SIZE) & ~(WHCI_PAGE_SIZE-1); | ||
519 | } | ||
520 | |||
521 | prev_end = dma_addr = ep; | ||
522 | dma_remaining -= dma_len; | ||
523 | remaining -= dma_len; | ||
524 | } | ||
525 | } | ||
526 | |||
527 | /* Now the number of stds is know, go back and fill in | ||
528 | std->ntds_remaining. */ | ||
529 | list_for_each_entry(std, &qset->stds, list_node) { | ||
530 | if (std->ntds_remaining == -1) { | ||
531 | pl_len = std->num_pointers * sizeof(struct whc_page_list_entry); | ||
532 | std->ntds_remaining = ntds--; | ||
533 | std->dma_addr = dma_map_single(whc->wusbhc.dev, std->pl_virt, | ||
534 | pl_len, DMA_TO_DEVICE); | ||
535 | } | ||
536 | } | ||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | /** | ||
541 | * qset_add_urb_sg_linearize - add an urb with sg list, copying the data | ||
542 | * | ||
543 | * If the URB contains an sg list whose elements cannot be directly | ||
544 | * mapped to qTDs then the data must be transferred via bounce | ||
545 | * buffers. | ||
546 | */ | ||
547 | static int qset_add_urb_sg_linearize(struct whc *whc, struct whc_qset *qset, | ||
548 | struct urb *urb, gfp_t mem_flags) | ||
549 | { | ||
550 | bool is_out = usb_pipeout(urb->pipe); | ||
551 | size_t max_std_len; | ||
552 | size_t remaining; | ||
553 | int ntds = 0; | ||
554 | struct whc_std *std = NULL; | ||
555 | void *bounce = NULL; | ||
556 | struct scatterlist *sg; | ||
557 | int i; | ||
558 | |||
559 | /* limit maximum bounce buffer to 16 * 3.5 KiB ~= 28 k */ | ||
560 | max_std_len = qset->max_burst * qset->max_packet; | ||
561 | |||
562 | remaining = urb->transfer_buffer_length; | ||
563 | |||
564 | for_each_sg(urb->sg->sg, sg, urb->sg->nents, i) { | ||
565 | size_t len; | ||
566 | size_t sg_remaining; | ||
567 | void *orig; | ||
568 | |||
569 | if (remaining == 0) { | ||
570 | break; | ||
571 | } | ||
572 | |||
573 | sg_remaining = min_t(size_t, remaining, sg->length); | ||
574 | orig = sg_virt(sg); | ||
575 | |||
576 | while (sg_remaining) { | ||
577 | if (!std || std->len == max_std_len) { | ||
578 | std = qset_new_std(whc, qset, urb, mem_flags); | ||
579 | if (std == NULL) | ||
580 | return -ENOMEM; | ||
581 | std->bounce_buf = kmalloc(max_std_len, mem_flags); | ||
582 | if (std->bounce_buf == NULL) | ||
583 | return -ENOMEM; | ||
584 | std->bounce_sg = sg; | ||
585 | std->bounce_offset = orig - sg_virt(sg); | ||
586 | bounce = std->bounce_buf; | ||
587 | ntds++; | ||
588 | } | ||
589 | |||
590 | len = min(sg_remaining, max_std_len - std->len); | ||
591 | |||
592 | if (is_out) | ||
593 | memcpy(bounce, orig, len); | ||
594 | |||
595 | std->len += len; | ||
596 | std->ntds_remaining = -1; /* filled in later */ | ||
597 | |||
598 | bounce += len; | ||
599 | orig += len; | ||
600 | sg_remaining -= len; | ||
601 | remaining -= len; | ||
602 | } | ||
603 | } | ||
604 | |||
605 | /* | ||
606 | * For each of the new sTDs, map the bounce buffers, create | ||
607 | * page lists (if necessary), and fill in std->ntds_remaining. | ||
608 | */ | ||
609 | list_for_each_entry(std, &qset->stds, list_node) { | ||
610 | if (std->ntds_remaining != -1) | ||
611 | continue; | ||
612 | |||
613 | std->dma_addr = dma_map_single(&whc->umc->dev, std->bounce_buf, std->len, | ||
614 | is_out ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
615 | |||
616 | if (qset_fill_page_list(whc, std, mem_flags) < 0) | ||
617 | return -ENOMEM; | ||
618 | |||
619 | std->ntds_remaining = ntds--; | ||
620 | } | ||
621 | |||
622 | return 0; | ||
623 | } | ||
624 | |||
342 | /** | 625 | /** |
343 | * qset_add_urb - add an urb to the qset's queue. | 626 | * qset_add_urb - add an urb to the qset's queue. |
344 | * | 627 | * |
@@ -353,10 +636,7 @@ int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb, | |||
353 | int remaining = urb->transfer_buffer_length; | 636 | int remaining = urb->transfer_buffer_length; |
354 | u64 transfer_dma = urb->transfer_dma; | 637 | u64 transfer_dma = urb->transfer_dma; |
355 | int ntds_remaining; | 638 | int ntds_remaining; |
356 | 639 | int ret; | |
357 | ntds_remaining = DIV_ROUND_UP(remaining, QTD_MAX_XFER_SIZE); | ||
358 | if (ntds_remaining == 0) | ||
359 | ntds_remaining = 1; | ||
360 | 640 | ||
361 | wurb = kzalloc(sizeof(struct whc_urb), mem_flags); | 641 | wurb = kzalloc(sizeof(struct whc_urb), mem_flags); |
362 | if (wurb == NULL) | 642 | if (wurb == NULL) |
@@ -366,32 +646,39 @@ int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb, | |||
366 | wurb->urb = urb; | 646 | wurb->urb = urb; |
367 | INIT_WORK(&wurb->dequeue_work, urb_dequeue_work); | 647 | INIT_WORK(&wurb->dequeue_work, urb_dequeue_work); |
368 | 648 | ||
649 | if (urb->sg) { | ||
650 | ret = qset_add_urb_sg(whc, qset, urb, mem_flags); | ||
651 | if (ret == -EINVAL) { | ||
652 | qset_free_stds(qset, urb); | ||
653 | ret = qset_add_urb_sg_linearize(whc, qset, urb, mem_flags); | ||
654 | } | ||
655 | if (ret < 0) | ||
656 | goto err_no_mem; | ||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | ntds_remaining = DIV_ROUND_UP(remaining, QTD_MAX_XFER_SIZE); | ||
661 | if (ntds_remaining == 0) | ||
662 | ntds_remaining = 1; | ||
663 | |||
369 | while (ntds_remaining) { | 664 | while (ntds_remaining) { |
370 | struct whc_std *std; | 665 | struct whc_std *std; |
371 | size_t std_len; | 666 | size_t std_len; |
372 | 667 | ||
373 | std = kmalloc(sizeof(struct whc_std), mem_flags); | ||
374 | if (std == NULL) | ||
375 | goto err_no_mem; | ||
376 | |||
377 | std_len = remaining; | 668 | std_len = remaining; |
378 | if (std_len > QTD_MAX_XFER_SIZE) | 669 | if (std_len > QTD_MAX_XFER_SIZE) |
379 | std_len = QTD_MAX_XFER_SIZE; | 670 | std_len = QTD_MAX_XFER_SIZE; |
380 | 671 | ||
381 | std->urb = urb; | 672 | std = qset_new_std(whc, qset, urb, mem_flags); |
673 | if (std == NULL) | ||
674 | goto err_no_mem; | ||
675 | |||
382 | std->dma_addr = transfer_dma; | 676 | std->dma_addr = transfer_dma; |
383 | std->len = std_len; | 677 | std->len = std_len; |
384 | std->ntds_remaining = ntds_remaining; | 678 | std->ntds_remaining = ntds_remaining; |
385 | std->qtd = NULL; | ||
386 | 679 | ||
387 | INIT_LIST_HEAD(&std->list_node); | 680 | if (qset_fill_page_list(whc, std, mem_flags) < 0) |
388 | list_add_tail(&std->list_node, &qset->stds); | 681 | goto err_no_mem; |
389 | |||
390 | if (std_len > WHCI_PAGE_SIZE) { | ||
391 | if (qset_fill_page_list(whc, std, mem_flags) < 0) | ||
392 | goto err_no_mem; | ||
393 | } else | ||
394 | std->num_pointers = 0; | ||
395 | 682 | ||
396 | ntds_remaining--; | 683 | ntds_remaining--; |
397 | remaining -= std_len; | 684 | remaining -= std_len; |
diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h index 24e94d983c5e..c80c7d93bc4a 100644 --- a/drivers/usb/host/whci/whcd.h +++ b/drivers/usb/host/whci/whcd.h | |||
@@ -84,6 +84,11 @@ struct whc { | |||
84 | * @len: the length of data in the associated TD. | 84 | * @len: the length of data in the associated TD. |
85 | * @ntds_remaining: number of TDs (starting from this one) in this transfer. | 85 | * @ntds_remaining: number of TDs (starting from this one) in this transfer. |
86 | * | 86 | * |
87 | * @bounce_buf: a bounce buffer if the std was from an urb with a sg | ||
88 | * list that could not be mapped to qTDs directly. | ||
89 | * @bounce_sg: the first scatterlist element bounce_buf is for. | ||
90 | * @bounce_offset: the offset into bounce_sg for the start of bounce_buf. | ||
91 | * | ||
87 | * Queued URBs may require more TDs than are available in a qset so we | 92 | * Queued URBs may require more TDs than are available in a qset so we |
88 | * use a list of these "software TDs" (sTDs) to hold per-TD data. | 93 | * use a list of these "software TDs" (sTDs) to hold per-TD data. |
89 | */ | 94 | */ |
@@ -97,6 +102,10 @@ struct whc_std { | |||
97 | int num_pointers; | 102 | int num_pointers; |
98 | dma_addr_t dma_addr; | 103 | dma_addr_t dma_addr; |
99 | struct whc_page_list_entry *pl_virt; | 104 | struct whc_page_list_entry *pl_virt; |
105 | |||
106 | void *bounce_buf; | ||
107 | struct scatterlist *bounce_sg; | ||
108 | unsigned bounce_offset; | ||
100 | }; | 109 | }; |
101 | 110 | ||
102 | /** | 111 | /** |
diff --git a/drivers/usb/host/whci/whci-hc.h b/drivers/usb/host/whci/whci-hc.h index e8d0001605be..4d4cbc0730bf 100644 --- a/drivers/usb/host/whci/whci-hc.h +++ b/drivers/usb/host/whci/whci-hc.h | |||
@@ -172,14 +172,7 @@ struct whc_qhead { | |||
172 | #define QH_INFO3_MAX_DELAY(d) ((d) << 0) /* maximum stream delay in 125 us units (isoc only) */ | 172 | #define QH_INFO3_MAX_DELAY(d) ((d) << 0) /* maximum stream delay in 125 us units (isoc only) */ |
173 | #define QH_INFO3_INTERVAL(i) ((i) << 16) /* segment interval in 125 us units (isoc only) */ | 173 | #define QH_INFO3_INTERVAL(i) ((i) << 16) /* segment interval in 125 us units (isoc only) */ |
174 | 174 | ||
175 | #define QH_INFO3_TX_RATE_53_3 (0 << 24) | 175 | #define QH_INFO3_TX_RATE(r) ((r) << 24) /* PHY rate (see [ECMA-368] section 10.3.1.1) */ |
176 | #define QH_INFO3_TX_RATE_80 (1 << 24) | ||
177 | #define QH_INFO3_TX_RATE_106_7 (2 << 24) | ||
178 | #define QH_INFO3_TX_RATE_160 (3 << 24) | ||
179 | #define QH_INFO3_TX_RATE_200 (4 << 24) | ||
180 | #define QH_INFO3_TX_RATE_320 (5 << 24) | ||
181 | #define QH_INFO3_TX_RATE_400 (6 << 24) | ||
182 | #define QH_INFO3_TX_RATE_480 (7 << 24) | ||
183 | #define QH_INFO3_TX_PWR(p) ((p) << 29) /* transmit power (see [WUSB] section 5.2.1.2) */ | 176 | #define QH_INFO3_TX_PWR(p) ((p) << 29) /* transmit power (see [WUSB] section 5.2.1.2) */ |
184 | 177 | ||
185 | #define QH_STATUS_FLOW_CTRL (1 << 15) | 178 | #define QH_STATUS_FLOW_CTRL (1 << 15) |
@@ -267,8 +260,9 @@ struct whc_qset { | |||
267 | unsigned reset:1; | 260 | unsigned reset:1; |
268 | struct urb *pause_after_urb; | 261 | struct urb *pause_after_urb; |
269 | struct completion remove_complete; | 262 | struct completion remove_complete; |
270 | int max_burst; | 263 | uint16_t max_packet; |
271 | int max_seq; | 264 | uint8_t max_burst; |
265 | uint8_t max_seq; | ||
272 | }; | 266 | }; |
273 | 267 | ||
274 | static inline void whc_qset_set_link_ptr(u64 *ptr, u64 target) | 268 | static inline void whc_qset_set_link_ptr(u64 *ptr, u64 target) |