diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.h | 22 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 91 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 7 |
5 files changed, 111 insertions, 28 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 40eb64358821..0447e93306ad 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1108,7 +1108,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry) | |||
1108 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); | 1108 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); |
1109 | struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; | 1109 | struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; |
1110 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 1110 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
1111 | int pipe = usb_sndbulkpipe(usb_dev, 1); | 1111 | int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint); |
1112 | int length; | 1112 | int length; |
1113 | u16 reg; | 1113 | u16 reg; |
1114 | 1114 | ||
@@ -1134,7 +1134,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry) | |||
1134 | * length of the data to usb_fill_bulk_urb. Pass the skb | 1134 | * length of the data to usb_fill_bulk_urb. Pass the skb |
1135 | * to the driver to determine what the length should be. | 1135 | * to the driver to determine what the length should be. |
1136 | */ | 1136 | */ |
1137 | length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb); | 1137 | length = rt2x00dev->ops->lib->get_tx_data_len(entry); |
1138 | 1138 | ||
1139 | usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, | 1139 | usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, |
1140 | entry->skb->data, length, rt2500usb_beacondone, | 1140 | entry->skb->data, length, rt2500usb_beacondone, |
@@ -1156,8 +1156,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry) | |||
1156 | usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); | 1156 | usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); |
1157 | } | 1157 | } |
1158 | 1158 | ||
1159 | static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, | 1159 | static int rt2500usb_get_tx_data_len(struct queue_entry *entry) |
1160 | struct sk_buff *skb) | ||
1161 | { | 1160 | { |
1162 | int length; | 1161 | int length; |
1163 | 1162 | ||
@@ -1165,8 +1164,8 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, | |||
1165 | * The length _must_ be a multiple of 2, | 1164 | * The length _must_ be a multiple of 2, |
1166 | * but it must _not_ be a multiple of the USB packet size. | 1165 | * but it must _not_ be a multiple of the USB packet size. |
1167 | */ | 1166 | */ |
1168 | length = roundup(skb->len, 2); | 1167 | length = roundup(entry->skb->len, 2); |
1169 | length += (2 * !(length % rt2x00dev->usb_maxpacket)); | 1168 | length += (2 * !(length % entry->queue->usb_maxpacket)); |
1170 | 1169 | ||
1171 | return length; | 1170 | return length; |
1172 | } | 1171 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index fee61bee1e7e..780ba7365810 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -555,8 +555,7 @@ struct rt2x00lib_ops { | |||
555 | struct txentry_desc *txdesc); | 555 | struct txentry_desc *txdesc); |
556 | int (*write_tx_data) (struct queue_entry *entry); | 556 | int (*write_tx_data) (struct queue_entry *entry); |
557 | void (*write_beacon) (struct queue_entry *entry); | 557 | void (*write_beacon) (struct queue_entry *entry); |
558 | int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, | 558 | int (*get_tx_data_len) (struct queue_entry *entry); |
559 | struct sk_buff *skb); | ||
560 | void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, | 559 | void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, |
561 | const enum data_queue_qid queue); | 560 | const enum data_queue_qid queue); |
562 | 561 | ||
@@ -799,11 +798,6 @@ struct rt2x00_dev { | |||
799 | short lna_gain; | 798 | short lna_gain; |
800 | 799 | ||
801 | /* | 800 | /* |
802 | * USB Max frame size (for rt2500usb & rt73usb). | ||
803 | */ | ||
804 | u16 usb_maxpacket; | ||
805 | |||
806 | /* | ||
807 | * Current TX power value. | 801 | * Current TX power value. |
808 | */ | 802 | */ |
809 | u16 tx_power; | 803 | u16 tx_power; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 4d3c7246f9ae..2e99ab53ec65 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -380,6 +380,8 @@ enum queue_index { | |||
380 | * @cw_max: The cw max value for outgoing frames (field ignored in RX queue). | 380 | * @cw_max: The cw max value for outgoing frames (field ignored in RX queue). |
381 | * @data_size: Maximum data size for the frames in this queue. | 381 | * @data_size: Maximum data size for the frames in this queue. |
382 | * @desc_size: Hardware descriptor size for the data in this queue. | 382 | * @desc_size: Hardware descriptor size for the data in this queue. |
383 | * @usb_endpoint: Device endpoint used for communication (USB only) | ||
384 | * @usb_maxpacket: Max packet size for given endpoint (USB only) | ||
383 | */ | 385 | */ |
384 | struct data_queue { | 386 | struct data_queue { |
385 | struct rt2x00_dev *rt2x00dev; | 387 | struct rt2x00_dev *rt2x00dev; |
@@ -401,6 +403,9 @@ struct data_queue { | |||
401 | 403 | ||
402 | unsigned short data_size; | 404 | unsigned short data_size; |
403 | unsigned short desc_size; | 405 | unsigned short desc_size; |
406 | |||
407 | unsigned short usb_endpoint; | ||
408 | unsigned short usb_maxpacket; | ||
404 | }; | 409 | }; |
405 | 410 | ||
406 | /** | 411 | /** |
@@ -444,6 +449,19 @@ struct data_queue_desc { | |||
444 | &(__dev)->tx[(__dev)->ops->tx_queues] | 449 | &(__dev)->tx[(__dev)->ops->tx_queues] |
445 | 450 | ||
446 | /** | 451 | /** |
452 | * queue_next - Return pointer to next queue in list (HELPER MACRO). | ||
453 | * @__queue: Current queue for which we need the next queue | ||
454 | * | ||
455 | * Using the current queue address we take the address directly | ||
456 | * after the queue to take the next queue. Note that this macro | ||
457 | * should be used carefully since it does not protect against | ||
458 | * moving past the end of the list. (See macros &queue_end and | ||
459 | * &tx_queue_end for determining the end of the queue). | ||
460 | */ | ||
461 | #define queue_next(__queue) \ | ||
462 | &(__queue)[1] | ||
463 | |||
464 | /** | ||
447 | * queue_loop - Loop through the queues within a specific range (HELPER MACRO). | 465 | * queue_loop - Loop through the queues within a specific range (HELPER MACRO). |
448 | * @__entry: Pointer where the current queue entry will be stored in. | 466 | * @__entry: Pointer where the current queue entry will be stored in. |
449 | * @__start: Start queue pointer. | 467 | * @__start: Start queue pointer. |
@@ -453,8 +471,8 @@ struct data_queue_desc { | |||
453 | */ | 471 | */ |
454 | #define queue_loop(__entry, __start, __end) \ | 472 | #define queue_loop(__entry, __start, __end) \ |
455 | for ((__entry) = (__start); \ | 473 | for ((__entry) = (__start); \ |
456 | prefetch(&(__entry)[1]), (__entry) != (__end); \ | 474 | prefetch(queue_next(__entry)), (__entry) != (__end);\ |
457 | (__entry) = &(__entry)[1]) | 475 | (__entry) = queue_next(__entry)) |
458 | 476 | ||
459 | /** | 477 | /** |
460 | * queue_for_each - Loop through all queues | 478 | * queue_for_each - Loop through all queues |
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; |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ee59b4e35cdc..37a782dc8080 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -1508,8 +1508,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry) | |||
1508 | entry->skb = NULL; | 1508 | entry->skb = NULL; |
1509 | } | 1509 | } |
1510 | 1510 | ||
1511 | static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, | 1511 | static int rt73usb_get_tx_data_len(struct queue_entry *entry) |
1512 | struct sk_buff *skb) | ||
1513 | { | 1512 | { |
1514 | int length; | 1513 | int length; |
1515 | 1514 | ||
@@ -1517,8 +1516,8 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, | |||
1517 | * The length _must_ be a multiple of 4, | 1516 | * The length _must_ be a multiple of 4, |
1518 | * but it must _not_ be a multiple of the USB packet size. | 1517 | * but it must _not_ be a multiple of the USB packet size. |
1519 | */ | 1518 | */ |
1520 | length = roundup(skb->len, 4); | 1519 | length = roundup(entry->skb->len, 4); |
1521 | length += (4 * !(length % rt2x00dev->usb_maxpacket)); | 1520 | length += (4 * !(length % entry->queue->usb_maxpacket)); |
1522 | 1521 | ||
1523 | return length; | 1522 | return length; |
1524 | } | 1523 | } |