diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 91 |
1 files changed, 82 insertions, 9 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 2fbf78ff6b18..83df312ac56f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -234,10 +234,10 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry) | |||
234 | * length of the data to usb_fill_bulk_urb. Pass the skb | 234 | * length of the data to usb_fill_bulk_urb. Pass the skb |
235 | * to the driver to determine what the length should be. | 235 | * to the driver to determine what the length should be. |
236 | */ | 236 | */ |
237 | length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb); | 237 | length = rt2x00dev->ops->lib->get_tx_data_len(entry); |
238 | 238 | ||
239 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, | 239 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, |
240 | usb_sndbulkpipe(usb_dev, 1), | 240 | usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint), |
241 | entry->skb->data, length, | 241 | entry->skb->data, length, |
242 | rt2x00usb_interrupt_txdone, entry); | 242 | rt2x00usb_interrupt_txdone, entry); |
243 | 243 | ||
@@ -378,10 +378,11 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) | |||
378 | struct usb_device *usb_dev = | 378 | struct usb_device *usb_dev = |
379 | to_usb_device_intf(entry->queue->rt2x00dev->dev); | 379 | to_usb_device_intf(entry->queue->rt2x00dev->dev); |
380 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 380 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
381 | int pipe; | ||
381 | 382 | ||
382 | if (entry->queue->qid == QID_RX) { | 383 | if (entry->queue->qid == QID_RX) { |
383 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, | 384 | pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); |
384 | usb_rcvbulkpipe(usb_dev, 1), | 385 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, |
385 | entry->skb->data, entry->skb->len, | 386 | entry->skb->data, entry->skb->len, |
386 | rt2x00usb_interrupt_rxdone, entry); | 387 | rt2x00usb_interrupt_rxdone, entry); |
387 | 388 | ||
@@ -393,6 +394,76 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) | |||
393 | } | 394 | } |
394 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); | 395 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); |
395 | 396 | ||
397 | static void rt2x00usb_assign_endpoint(struct data_queue *queue, | ||
398 | struct usb_endpoint_descriptor *ep_desc) | ||
399 | { | ||
400 | struct usb_device *usb_dev = to_usb_device_intf(queue->rt2x00dev->dev); | ||
401 | int pipe; | ||
402 | |||
403 | queue->usb_endpoint = usb_endpoint_num(ep_desc); | ||
404 | |||
405 | if (queue->qid == QID_RX) { | ||
406 | pipe = usb_rcvbulkpipe(usb_dev, queue->usb_endpoint); | ||
407 | queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 0); | ||
408 | } else { | ||
409 | pipe = usb_sndbulkpipe(usb_dev, queue->usb_endpoint); | ||
410 | queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 1); | ||
411 | } | ||
412 | |||
413 | if (!queue->usb_maxpacket) | ||
414 | queue->usb_maxpacket = 1; | ||
415 | } | ||
416 | |||
417 | static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev) | ||
418 | { | ||
419 | struct usb_interface *intf = to_usb_interface(rt2x00dev->dev); | ||
420 | struct usb_host_interface *intf_desc = intf->cur_altsetting; | ||
421 | struct usb_endpoint_descriptor *ep_desc; | ||
422 | struct data_queue *queue = rt2x00dev->tx; | ||
423 | struct usb_endpoint_descriptor *tx_ep_desc = NULL; | ||
424 | unsigned int i; | ||
425 | |||
426 | /* | ||
427 | * Walk through all available endpoints to search for "bulk in" | ||
428 | * and "bulk out" endpoints. When we find such endpoints collect | ||
429 | * the information we need from the descriptor and assign it | ||
430 | * to the queue. | ||
431 | */ | ||
432 | for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) { | ||
433 | ep_desc = &intf_desc->endpoint[i].desc; | ||
434 | |||
435 | if (usb_endpoint_is_bulk_in(ep_desc)) { | ||
436 | rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc); | ||
437 | } else if (usb_endpoint_is_bulk_out(ep_desc)) { | ||
438 | rt2x00usb_assign_endpoint(queue, ep_desc); | ||
439 | |||
440 | if (queue != queue_end(rt2x00dev)) | ||
441 | queue = queue_next(queue); | ||
442 | tx_ep_desc = ep_desc; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | /* | ||
447 | * At least 1 endpoint for RX and 1 endpoint for TX must be available. | ||
448 | */ | ||
449 | if (!rt2x00dev->rx->usb_endpoint || !rt2x00dev->tx->usb_endpoint) { | ||
450 | ERROR(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n"); | ||
451 | return -EPIPE; | ||
452 | } | ||
453 | |||
454 | /* | ||
455 | * It might be possible not all queues have a dedicated endpoint. | ||
456 | * Loop through all TX queues and copy the endpoint information | ||
457 | * which we have gathered from already assigned endpoints. | ||
458 | */ | ||
459 | txall_queue_for_each(rt2x00dev, queue) { | ||
460 | if (!queue->usb_endpoint) | ||
461 | rt2x00usb_assign_endpoint(queue, tx_ep_desc); | ||
462 | } | ||
463 | |||
464 | return 0; | ||
465 | } | ||
466 | |||
396 | static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, | 467 | static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, |
397 | struct data_queue *queue) | 468 | struct data_queue *queue) |
398 | { | 469 | { |
@@ -464,6 +535,13 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) | |||
464 | int status; | 535 | int status; |
465 | 536 | ||
466 | /* | 537 | /* |
538 | * Find endpoints for each queue | ||
539 | */ | ||
540 | status = rt2x00usb_find_endpoints(rt2x00dev); | ||
541 | if (status) | ||
542 | goto exit; | ||
543 | |||
544 | /* | ||
467 | * Allocate DMA | 545 | * Allocate DMA |
468 | */ | 546 | */ |
469 | queue_for_each(rt2x00dev, queue) { | 547 | queue_for_each(rt2x00dev, queue) { |
@@ -554,11 +632,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, | |||
554 | rt2x00dev->ops = ops; | 632 | rt2x00dev->ops = ops; |
555 | rt2x00dev->hw = hw; | 633 | rt2x00dev->hw = hw; |
556 | 634 | ||
557 | rt2x00dev->usb_maxpacket = | ||
558 | usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1); | ||
559 | if (!rt2x00dev->usb_maxpacket) | ||
560 | rt2x00dev->usb_maxpacket = 1; | ||
561 | |||
562 | retval = rt2x00usb_alloc_reg(rt2x00dev); | 635 | retval = rt2x00usb_alloc_reg(rt2x00dev); |
563 | if (retval) | 636 | if (retval) |
564 | goto exit_free_device; | 637 | goto exit_free_device; |