diff options
Diffstat (limited to 'drivers/net/wireless/zd1211rw/zd_mac.c')
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.c | 229 |
1 files changed, 194 insertions, 35 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 6d666359a42f..16fa289ad77b 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/netdevice.h> | 23 | #include <linux/netdevice.h> |
24 | #include <linux/etherdevice.h> | 24 | #include <linux/etherdevice.h> |
25 | #include <linux/slab.h> | ||
25 | #include <linux/usb.h> | 26 | #include <linux/usb.h> |
26 | #include <linux/jiffies.h> | 27 | #include <linux/jiffies.h> |
27 | #include <net/ieee80211_radiotap.h> | 28 | #include <net/ieee80211_radiotap.h> |
@@ -88,6 +89,34 @@ static const struct ieee80211_rate zd_rates[] = { | |||
88 | .flags = 0 }, | 89 | .flags = 0 }, |
89 | }; | 90 | }; |
90 | 91 | ||
92 | /* | ||
93 | * Zydas retry rates table. Each line is listed in the same order as | ||
94 | * in zd_rates[] and contains all the rate used when a packet is sent | ||
95 | * starting with a given rates. Let's consider an example : | ||
96 | * | ||
97 | * "11 Mbits : 4, 3, 2, 1, 0" means : | ||
98 | * - packet is sent using 4 different rates | ||
99 | * - 1st rate is index 3 (ie 11 Mbits) | ||
100 | * - 2nd rate is index 2 (ie 5.5 Mbits) | ||
101 | * - 3rd rate is index 1 (ie 2 Mbits) | ||
102 | * - 4th rate is index 0 (ie 1 Mbits) | ||
103 | */ | ||
104 | |||
105 | static const struct tx_retry_rate zd_retry_rates[] = { | ||
106 | { /* 1 Mbits */ 1, { 0 }}, | ||
107 | { /* 2 Mbits */ 2, { 1, 0 }}, | ||
108 | { /* 5.5 Mbits */ 3, { 2, 1, 0 }}, | ||
109 | { /* 11 Mbits */ 4, { 3, 2, 1, 0 }}, | ||
110 | { /* 6 Mbits */ 5, { 4, 3, 2, 1, 0 }}, | ||
111 | { /* 9 Mbits */ 6, { 5, 4, 3, 2, 1, 0}}, | ||
112 | { /* 12 Mbits */ 5, { 6, 3, 2, 1, 0 }}, | ||
113 | { /* 18 Mbits */ 6, { 7, 6, 3, 2, 1, 0 }}, | ||
114 | { /* 24 Mbits */ 6, { 8, 6, 3, 2, 1, 0 }}, | ||
115 | { /* 36 Mbits */ 7, { 9, 8, 6, 3, 2, 1, 0 }}, | ||
116 | { /* 48 Mbits */ 8, {10, 9, 8, 6, 3, 2, 1, 0 }}, | ||
117 | { /* 54 Mbits */ 9, {11, 10, 9, 8, 6, 3, 2, 1, 0 }} | ||
118 | }; | ||
119 | |||
91 | static const struct ieee80211_channel zd_channels[] = { | 120 | static const struct ieee80211_channel zd_channels[] = { |
92 | { .center_freq = 2412, .hw_value = 1 }, | 121 | { .center_freq = 2412, .hw_value = 1 }, |
93 | { .center_freq = 2417, .hw_value = 2 }, | 122 | { .center_freq = 2417, .hw_value = 2 }, |
@@ -282,7 +311,7 @@ static void zd_op_stop(struct ieee80211_hw *hw) | |||
282 | } | 311 | } |
283 | 312 | ||
284 | /** | 313 | /** |
285 | * tx_status - reports tx status of a packet if required | 314 | * zd_mac_tx_status - reports tx status of a packet if required |
286 | * @hw - a &struct ieee80211_hw pointer | 315 | * @hw - a &struct ieee80211_hw pointer |
287 | * @skb - a sk-buffer | 316 | * @skb - a sk-buffer |
288 | * @flags: extra flags to set in the TX status info | 317 | * @flags: extra flags to set in the TX status info |
@@ -295,15 +324,49 @@ static void zd_op_stop(struct ieee80211_hw *hw) | |||
295 | * | 324 | * |
296 | * If no status information has been requested, the skb is freed. | 325 | * If no status information has been requested, the skb is freed. |
297 | */ | 326 | */ |
298 | static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | 327 | static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, |
299 | int ackssi, bool success) | 328 | int ackssi, struct tx_status *tx_status) |
300 | { | 329 | { |
301 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 330 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
331 | int i; | ||
332 | int success = 1, retry = 1; | ||
333 | int first_idx; | ||
334 | const struct tx_retry_rate *retries; | ||
302 | 335 | ||
303 | ieee80211_tx_info_clear_status(info); | 336 | ieee80211_tx_info_clear_status(info); |
304 | 337 | ||
305 | if (success) | 338 | if (tx_status) { |
339 | success = !tx_status->failure; | ||
340 | retry = tx_status->retry + success; | ||
341 | } | ||
342 | |||
343 | if (success) { | ||
344 | /* success */ | ||
306 | info->flags |= IEEE80211_TX_STAT_ACK; | 345 | info->flags |= IEEE80211_TX_STAT_ACK; |
346 | } else { | ||
347 | /* failure */ | ||
348 | info->flags &= ~IEEE80211_TX_STAT_ACK; | ||
349 | } | ||
350 | |||
351 | first_idx = info->status.rates[0].idx; | ||
352 | ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates)); | ||
353 | retries = &zd_retry_rates[first_idx]; | ||
354 | ZD_ASSERT(1 <= retry && retry <= retries->count); | ||
355 | |||
356 | info->status.rates[0].idx = retries->rate[0]; | ||
357 | info->status.rates[0].count = 1; // (retry > 1 ? 2 : 1); | ||
358 | |||
359 | for (i=1; i<IEEE80211_TX_MAX_RATES-1 && i<retry; i++) { | ||
360 | info->status.rates[i].idx = retries->rate[i]; | ||
361 | info->status.rates[i].count = 1; // ((i==retry-1) && success ? 1:2); | ||
362 | } | ||
363 | for (; i<IEEE80211_TX_MAX_RATES && i<retry; i++) { | ||
364 | info->status.rates[i].idx = retries->rate[retry - 1]; | ||
365 | info->status.rates[i].count = 1; // (success ? 1:2); | ||
366 | } | ||
367 | if (i<IEEE80211_TX_MAX_RATES) | ||
368 | info->status.rates[i].idx = -1; /* terminate */ | ||
369 | |||
307 | info->status.ack_signal = ackssi; | 370 | info->status.ack_signal = ackssi; |
308 | ieee80211_tx_status_irqsafe(hw, skb); | 371 | ieee80211_tx_status_irqsafe(hw, skb); |
309 | } | 372 | } |
@@ -312,20 +375,81 @@ static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
312 | * zd_mac_tx_failed - callback for failed frames | 375 | * zd_mac_tx_failed - callback for failed frames |
313 | * @dev: the mac80211 wireless device | 376 | * @dev: the mac80211 wireless device |
314 | * | 377 | * |
315 | * This function is called if a frame couldn't be succesfully be | 378 | * This function is called if a frame couldn't be successfully |
316 | * transferred. The first frame from the tx queue, will be selected and | 379 | * transferred. The first frame from the tx queue, will be selected and |
317 | * reported as error to the upper layers. | 380 | * reported as error to the upper layers. |
318 | */ | 381 | */ |
319 | void zd_mac_tx_failed(struct ieee80211_hw *hw) | 382 | void zd_mac_tx_failed(struct urb *urb) |
320 | { | 383 | { |
321 | struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue; | 384 | struct ieee80211_hw * hw = zd_usb_to_hw(urb->context); |
385 | struct zd_mac *mac = zd_hw_mac(hw); | ||
386 | struct sk_buff_head *q = &mac->ack_wait_queue; | ||
322 | struct sk_buff *skb; | 387 | struct sk_buff *skb; |
388 | struct tx_status *tx_status = (struct tx_status *)urb->transfer_buffer; | ||
389 | unsigned long flags; | ||
390 | int success = !tx_status->failure; | ||
391 | int retry = tx_status->retry + success; | ||
392 | int found = 0; | ||
393 | int i, position = 0; | ||
323 | 394 | ||
324 | skb = skb_dequeue(q); | 395 | q = &mac->ack_wait_queue; |
325 | if (skb == NULL) | 396 | spin_lock_irqsave(&q->lock, flags); |
326 | return; | 397 | |
398 | skb_queue_walk(q, skb) { | ||
399 | struct ieee80211_hdr *tx_hdr; | ||
400 | struct ieee80211_tx_info *info; | ||
401 | int first_idx, final_idx; | ||
402 | const struct tx_retry_rate *retries; | ||
403 | u8 final_rate; | ||
404 | |||
405 | position ++; | ||
406 | |||
407 | /* if the hardware reports a failure and we had a 802.11 ACK | ||
408 | * pending, then we skip the first skb when searching for a | ||
409 | * matching frame */ | ||
410 | if (tx_status->failure && mac->ack_pending && | ||
411 | skb_queue_is_first(q, skb)) { | ||
412 | continue; | ||
413 | } | ||
414 | |||
415 | tx_hdr = (struct ieee80211_hdr *)skb->data; | ||
416 | |||
417 | /* we skip all frames not matching the reported destination */ | ||
418 | if (unlikely(memcmp(tx_hdr->addr1, tx_status->mac, ETH_ALEN))) { | ||
419 | continue; | ||
420 | } | ||
421 | |||
422 | /* we skip all frames not matching the reported final rate */ | ||
423 | |||
424 | info = IEEE80211_SKB_CB(skb); | ||
425 | first_idx = info->status.rates[0].idx; | ||
426 | ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates)); | ||
427 | retries = &zd_retry_rates[first_idx]; | ||
428 | if (retry <= 0 || retry > retries->count) | ||
429 | continue; | ||
430 | |||
431 | final_idx = retries->rate[retry - 1]; | ||
432 | final_rate = zd_rates[final_idx].hw_value; | ||
327 | 433 | ||
328 | tx_status(hw, skb, 0, 0); | 434 | if (final_rate != tx_status->rate) { |
435 | continue; | ||
436 | } | ||
437 | |||
438 | found = 1; | ||
439 | break; | ||
440 | } | ||
441 | |||
442 | if (found) { | ||
443 | for (i=1; i<=position; i++) { | ||
444 | skb = __skb_dequeue(q); | ||
445 | zd_mac_tx_status(hw, skb, | ||
446 | mac->ack_pending ? mac->ack_signal : 0, | ||
447 | i == position ? tx_status : NULL); | ||
448 | mac->ack_pending = 0; | ||
449 | } | ||
450 | } | ||
451 | |||
452 | spin_unlock_irqrestore(&q->lock, flags); | ||
329 | } | 453 | } |
330 | 454 | ||
331 | /** | 455 | /** |
@@ -342,18 +466,27 @@ void zd_mac_tx_to_dev(struct sk_buff *skb, int error) | |||
342 | { | 466 | { |
343 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 467 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
344 | struct ieee80211_hw *hw = info->rate_driver_data[0]; | 468 | struct ieee80211_hw *hw = info->rate_driver_data[0]; |
469 | struct zd_mac *mac = zd_hw_mac(hw); | ||
470 | |||
471 | ieee80211_tx_info_clear_status(info); | ||
345 | 472 | ||
346 | skb_pull(skb, sizeof(struct zd_ctrlset)); | 473 | skb_pull(skb, sizeof(struct zd_ctrlset)); |
347 | if (unlikely(error || | 474 | if (unlikely(error || |
348 | (info->flags & IEEE80211_TX_CTL_NO_ACK))) { | 475 | (info->flags & IEEE80211_TX_CTL_NO_ACK))) { |
349 | tx_status(hw, skb, 0, !error); | 476 | /* |
477 | * FIXME : do we need to fill in anything ? | ||
478 | */ | ||
479 | ieee80211_tx_status_irqsafe(hw, skb); | ||
350 | } else { | 480 | } else { |
351 | struct sk_buff_head *q = | 481 | struct sk_buff_head *q = &mac->ack_wait_queue; |
352 | &zd_hw_mac(hw)->ack_wait_queue; | ||
353 | 482 | ||
354 | skb_queue_tail(q, skb); | 483 | skb_queue_tail(q, skb); |
355 | while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS) | 484 | while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS) { |
356 | zd_mac_tx_failed(hw); | 485 | zd_mac_tx_status(hw, skb_dequeue(q), |
486 | mac->ack_pending ? mac->ack_signal : 0, | ||
487 | NULL); | ||
488 | mac->ack_pending = 0; | ||
489 | } | ||
357 | } | 490 | } |
358 | } | 491 | } |
359 | 492 | ||
@@ -606,27 +739,47 @@ fail: | |||
606 | static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, | 739 | static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, |
607 | struct ieee80211_rx_status *stats) | 740 | struct ieee80211_rx_status *stats) |
608 | { | 741 | { |
742 | struct zd_mac *mac = zd_hw_mac(hw); | ||
609 | struct sk_buff *skb; | 743 | struct sk_buff *skb; |
610 | struct sk_buff_head *q; | 744 | struct sk_buff_head *q; |
611 | unsigned long flags; | 745 | unsigned long flags; |
746 | int found = 0; | ||
747 | int i, position = 0; | ||
612 | 748 | ||
613 | if (!ieee80211_is_ack(rx_hdr->frame_control)) | 749 | if (!ieee80211_is_ack(rx_hdr->frame_control)) |
614 | return 0; | 750 | return 0; |
615 | 751 | ||
616 | q = &zd_hw_mac(hw)->ack_wait_queue; | 752 | q = &mac->ack_wait_queue; |
617 | spin_lock_irqsave(&q->lock, flags); | 753 | spin_lock_irqsave(&q->lock, flags); |
618 | skb_queue_walk(q, skb) { | 754 | skb_queue_walk(q, skb) { |
619 | struct ieee80211_hdr *tx_hdr; | 755 | struct ieee80211_hdr *tx_hdr; |
620 | 756 | ||
757 | position ++; | ||
758 | |||
759 | if (mac->ack_pending && skb_queue_is_first(q, skb)) | ||
760 | continue; | ||
761 | |||
621 | tx_hdr = (struct ieee80211_hdr *)skb->data; | 762 | tx_hdr = (struct ieee80211_hdr *)skb->data; |
622 | if (likely(!memcmp(tx_hdr->addr2, rx_hdr->addr1, ETH_ALEN))) | 763 | if (likely(!memcmp(tx_hdr->addr2, rx_hdr->addr1, ETH_ALEN))) |
623 | { | 764 | { |
624 | __skb_unlink(skb, q); | 765 | found = 1; |
625 | tx_status(hw, skb, stats->signal, 1); | 766 | break; |
626 | goto out; | ||
627 | } | 767 | } |
628 | } | 768 | } |
629 | out: | 769 | |
770 | if (found) { | ||
771 | for (i=1; i<position; i++) { | ||
772 | skb = __skb_dequeue(q); | ||
773 | zd_mac_tx_status(hw, skb, | ||
774 | mac->ack_pending ? mac->ack_signal : 0, | ||
775 | NULL); | ||
776 | mac->ack_pending = 0; | ||
777 | } | ||
778 | |||
779 | mac->ack_pending = 1; | ||
780 | mac->ack_signal = stats->signal; | ||
781 | } | ||
782 | |||
630 | spin_unlock_irqrestore(&q->lock, flags); | 783 | spin_unlock_irqrestore(&q->lock, flags); |
631 | return 1; | 784 | return 1; |
632 | } | 785 | } |
@@ -674,9 +827,6 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
674 | stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; | 827 | stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; |
675 | stats.band = IEEE80211_BAND_2GHZ; | 828 | stats.band = IEEE80211_BAND_2GHZ; |
676 | stats.signal = status->signal_strength; | 829 | stats.signal = status->signal_strength; |
677 | stats.qual = zd_rx_qual_percent(buffer, | ||
678 | length - sizeof(struct rx_status), | ||
679 | status); | ||
680 | 830 | ||
681 | rate = zd_rx_rate(buffer, status); | 831 | rate = zd_rx_rate(buffer, status); |
682 | 832 | ||
@@ -709,6 +859,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
709 | skb_reserve(skb, 2); | 859 | skb_reserve(skb, 2); |
710 | } | 860 | } |
711 | 861 | ||
862 | /* FIXME : could we avoid this big memcpy ? */ | ||
712 | memcpy(skb_put(skb, length), buffer, length); | 863 | memcpy(skb_put(skb, length), buffer, length); |
713 | 864 | ||
714 | memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats)); | 865 | memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats)); |
@@ -717,7 +868,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
717 | } | 868 | } |
718 | 869 | ||
719 | static int zd_op_add_interface(struct ieee80211_hw *hw, | 870 | static int zd_op_add_interface(struct ieee80211_hw *hw, |
720 | struct ieee80211_if_init_conf *conf) | 871 | struct ieee80211_vif *vif) |
721 | { | 872 | { |
722 | struct zd_mac *mac = zd_hw_mac(hw); | 873 | struct zd_mac *mac = zd_hw_mac(hw); |
723 | 874 | ||
@@ -725,22 +876,22 @@ static int zd_op_add_interface(struct ieee80211_hw *hw, | |||
725 | if (mac->type != NL80211_IFTYPE_UNSPECIFIED) | 876 | if (mac->type != NL80211_IFTYPE_UNSPECIFIED) |
726 | return -EOPNOTSUPP; | 877 | return -EOPNOTSUPP; |
727 | 878 | ||
728 | switch (conf->type) { | 879 | switch (vif->type) { |
729 | case NL80211_IFTYPE_MONITOR: | 880 | case NL80211_IFTYPE_MONITOR: |
730 | case NL80211_IFTYPE_MESH_POINT: | 881 | case NL80211_IFTYPE_MESH_POINT: |
731 | case NL80211_IFTYPE_STATION: | 882 | case NL80211_IFTYPE_STATION: |
732 | case NL80211_IFTYPE_ADHOC: | 883 | case NL80211_IFTYPE_ADHOC: |
733 | mac->type = conf->type; | 884 | mac->type = vif->type; |
734 | break; | 885 | break; |
735 | default: | 886 | default: |
736 | return -EOPNOTSUPP; | 887 | return -EOPNOTSUPP; |
737 | } | 888 | } |
738 | 889 | ||
739 | return zd_write_mac_addr(&mac->chip, conf->mac_addr); | 890 | return zd_write_mac_addr(&mac->chip, vif->addr); |
740 | } | 891 | } |
741 | 892 | ||
742 | static void zd_op_remove_interface(struct ieee80211_hw *hw, | 893 | static void zd_op_remove_interface(struct ieee80211_hw *hw, |
743 | struct ieee80211_if_init_conf *conf) | 894 | struct ieee80211_vif *vif) |
744 | { | 895 | { |
745 | struct zd_mac *mac = zd_hw_mac(hw); | 896 | struct zd_mac *mac = zd_hw_mac(hw); |
746 | mac->type = NL80211_IFTYPE_UNSPECIFIED; | 897 | mac->type = NL80211_IFTYPE_UNSPECIFIED; |
@@ -835,12 +986,13 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw, | |||
835 | changed_flags &= SUPPORTED_FIF_FLAGS; | 986 | changed_flags &= SUPPORTED_FIF_FLAGS; |
836 | *new_flags &= SUPPORTED_FIF_FLAGS; | 987 | *new_flags &= SUPPORTED_FIF_FLAGS; |
837 | 988 | ||
838 | /* changed_flags is always populated but this driver | 989 | /* |
839 | * doesn't support all FIF flags so its possible we don't | 990 | * If multicast parameter (as returned by zd_op_prepare_multicast) |
840 | * need to do anything */ | 991 | * has changed, no bit in changed_flags is set. To handle this |
841 | if (!changed_flags) | 992 | * situation, we do not return if changed_flags is 0. If we do so, |
842 | return; | 993 | * we will have some issue with IPv6 which uses multicast for link |
843 | 994 | * layer address resolution. | |
995 | */ | ||
844 | if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) | 996 | if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) |
845 | zd_mc_add_all(&hash); | 997 | zd_mc_add_all(&hash); |
846 | 998 | ||
@@ -999,7 +1151,14 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) | |||
999 | hw->queues = 1; | 1151 | hw->queues = 1; |
1000 | hw->extra_tx_headroom = sizeof(struct zd_ctrlset); | 1152 | hw->extra_tx_headroom = sizeof(struct zd_ctrlset); |
1001 | 1153 | ||
1154 | /* | ||
1155 | * Tell mac80211 that we support multi rate retries | ||
1156 | */ | ||
1157 | hw->max_rates = IEEE80211_TX_MAX_RATES; | ||
1158 | hw->max_rate_tries = 18; /* 9 rates * 2 retries/rate */ | ||
1159 | |||
1002 | skb_queue_head_init(&mac->ack_wait_queue); | 1160 | skb_queue_head_init(&mac->ack_wait_queue); |
1161 | mac->ack_pending = 0; | ||
1003 | 1162 | ||
1004 | zd_chip_init(&mac->chip, hw, intf); | 1163 | zd_chip_init(&mac->chip, hw, intf); |
1005 | housekeeping_init(mac); | 1164 | housekeeping_init(mac); |