diff options
Diffstat (limited to 'drivers/net/wireless/b43')
| -rw-r--r-- | drivers/net/wireless/b43/b43.h | 53 | ||||
| -rw-r--r-- | drivers/net/wireless/b43/dma.c | 386 | ||||
| -rw-r--r-- | drivers/net/wireless/b43/dma.h | 11 | ||||
| -rw-r--r-- | drivers/net/wireless/b43/main.c | 196 | ||||
| -rw-r--r-- | drivers/net/wireless/b43/main.h | 4 | ||||
| -rw-r--r-- | drivers/net/wireless/b43/xmit.c | 27 | ||||
| -rw-r--r-- | drivers/net/wireless/b43/xmit.h | 12 |
7 files changed, 427 insertions, 262 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 33459d61a717..d40be1568517 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
| @@ -99,6 +99,8 @@ | |||
| 99 | #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */ | 99 | #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */ |
| 100 | #define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */ | 100 | #define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */ |
| 101 | #define B43_MMIO_RNG 0x65A | 101 | #define B43_MMIO_RNG 0x65A |
| 102 | #define B43_MMIO_IFSCTL 0x688 /* Interframe space control */ | ||
| 103 | #define B43_MMIO_IFSCTL_USE_EDCF 0x0004 | ||
| 102 | #define B43_MMIO_POWERUP_DELAY 0x6A8 | 104 | #define B43_MMIO_POWERUP_DELAY 0x6A8 |
| 103 | 105 | ||
| 104 | /* SPROM boardflags_lo values */ | 106 | /* SPROM boardflags_lo values */ |
| @@ -587,15 +589,13 @@ struct b43_phy { | |||
| 587 | 589 | ||
| 588 | /* Data structures for DMA transmission, per 80211 core. */ | 590 | /* Data structures for DMA transmission, per 80211 core. */ |
| 589 | struct b43_dma { | 591 | struct b43_dma { |
| 590 | struct b43_dmaring *tx_ring0; | 592 | struct b43_dmaring *tx_ring_AC_BK; /* Background */ |
| 591 | struct b43_dmaring *tx_ring1; | 593 | struct b43_dmaring *tx_ring_AC_BE; /* Best Effort */ |
| 592 | struct b43_dmaring *tx_ring2; | 594 | struct b43_dmaring *tx_ring_AC_VI; /* Video */ |
| 593 | struct b43_dmaring *tx_ring3; | 595 | struct b43_dmaring *tx_ring_AC_VO; /* Voice */ |
| 594 | struct b43_dmaring *tx_ring4; | 596 | struct b43_dmaring *tx_ring_mcast; /* Multicast */ |
| 595 | struct b43_dmaring *tx_ring5; | 597 | |
| 596 | 598 | struct b43_dmaring *rx_ring; | |
| 597 | struct b43_dmaring *rx_ring0; | ||
| 598 | struct b43_dmaring *rx_ring3; /* only available on core.rev < 5 */ | ||
| 599 | }; | 599 | }; |
| 600 | 600 | ||
| 601 | /* Context information for a noise calculation (Link Quality). */ | 601 | /* Context information for a noise calculation (Link Quality). */ |
| @@ -621,6 +621,35 @@ struct b43_key { | |||
| 621 | u8 algorithm; | 621 | u8 algorithm; |
| 622 | }; | 622 | }; |
| 623 | 623 | ||
| 624 | /* SHM offsets to the QOS data structures for the 4 different queues. */ | ||
| 625 | #define B43_QOS_PARAMS(queue) (B43_SHM_SH_EDCFQ + \ | ||
| 626 | (B43_NR_QOSPARAMS * sizeof(u16) * (queue))) | ||
| 627 | #define B43_QOS_BACKGROUND B43_QOS_PARAMS(0) | ||
| 628 | #define B43_QOS_BESTEFFORT B43_QOS_PARAMS(1) | ||
| 629 | #define B43_QOS_VIDEO B43_QOS_PARAMS(2) | ||
| 630 | #define B43_QOS_VOICE B43_QOS_PARAMS(3) | ||
| 631 | |||
| 632 | /* QOS parameter hardware data structure offsets. */ | ||
| 633 | #define B43_NR_QOSPARAMS 22 | ||
| 634 | enum { | ||
| 635 | B43_QOSPARAM_TXOP = 0, | ||
| 636 | B43_QOSPARAM_CWMIN, | ||
| 637 | B43_QOSPARAM_CWMAX, | ||
| 638 | B43_QOSPARAM_CWCUR, | ||
| 639 | B43_QOSPARAM_AIFS, | ||
| 640 | B43_QOSPARAM_BSLOTS, | ||
| 641 | B43_QOSPARAM_REGGAP, | ||
| 642 | B43_QOSPARAM_STATUS, | ||
| 643 | }; | ||
| 644 | |||
| 645 | /* QOS parameters for a queue. */ | ||
| 646 | struct b43_qos_params { | ||
| 647 | /* The QOS parameters */ | ||
| 648 | struct ieee80211_tx_queue_params p; | ||
| 649 | /* Does this need to get uploaded to hardware? */ | ||
| 650 | bool need_hw_update; | ||
| 651 | }; | ||
| 652 | |||
| 624 | struct b43_wldev; | 653 | struct b43_wldev; |
| 625 | 654 | ||
| 626 | /* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */ | 655 | /* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */ |
| @@ -673,6 +702,12 @@ struct b43_wl { | |||
| 673 | struct sk_buff *current_beacon; | 702 | struct sk_buff *current_beacon; |
| 674 | bool beacon0_uploaded; | 703 | bool beacon0_uploaded; |
| 675 | bool beacon1_uploaded; | 704 | bool beacon1_uploaded; |
| 705 | |||
| 706 | /* The current QOS parameters for the 4 queues. | ||
| 707 | * This is protected by the irq_lock. */ | ||
| 708 | struct b43_qos_params qos_params[4]; | ||
| 709 | /* Workqueue for updating QOS parameters in hardware. */ | ||
| 710 | struct work_struct qos_update_work; | ||
| 676 | }; | 711 | }; |
| 677 | 712 | ||
| 678 | /* In-memory representation of a cached microcode file. */ | 713 | /* In-memory representation of a cached microcode file. */ |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 3dfb28a34be9..663aed4e9e05 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
| 39 | #include <linux/skbuff.h> | 39 | #include <linux/skbuff.h> |
| 40 | #include <linux/etherdevice.h> | 40 | #include <linux/etherdevice.h> |
| 41 | #include <asm/div64.h> | ||
| 41 | 42 | ||
| 42 | 43 | ||
| 43 | /* 32bit DMA ops. */ | 44 | /* 32bit DMA ops. */ |
| @@ -291,52 +292,6 @@ static inline int request_slot(struct b43_dmaring *ring) | |||
| 291 | return slot; | 292 | return slot; |
| 292 | } | 293 | } |
| 293 | 294 | ||
| 294 | /* Mac80211-queue to b43-ring mapping */ | ||
| 295 | static struct b43_dmaring *priority_to_txring(struct b43_wldev *dev, | ||
| 296 | int queue_priority) | ||
| 297 | { | ||
| 298 | struct b43_dmaring *ring; | ||
| 299 | |||
| 300 | /*FIXME: For now we always run on TX-ring-1 */ | ||
| 301 | return dev->dma.tx_ring1; | ||
| 302 | |||
| 303 | /* 0 = highest priority */ | ||
| 304 | switch (queue_priority) { | ||
| 305 | default: | ||
| 306 | B43_WARN_ON(1); | ||
| 307 | /* fallthrough */ | ||
| 308 | case 0: | ||
| 309 | ring = dev->dma.tx_ring3; | ||
| 310 | break; | ||
| 311 | case 1: | ||
| 312 | ring = dev->dma.tx_ring2; | ||
| 313 | break; | ||
| 314 | case 2: | ||
| 315 | ring = dev->dma.tx_ring1; | ||
| 316 | break; | ||
| 317 | case 3: | ||
| 318 | ring = dev->dma.tx_ring0; | ||
| 319 | break; | ||
| 320 | } | ||
| 321 | |||
| 322 | return ring; | ||
| 323 | } | ||
| 324 | |||
| 325 | /* b43-ring to mac80211-queue mapping */ | ||
| 326 | static inline int txring_to_priority(struct b43_dmaring *ring) | ||
| 327 | { | ||
| 328 | static const u8 idx_to_prio[] = { 3, 2, 1, 0, }; | ||
| 329 | unsigned int index; | ||
| 330 | |||
| 331 | /*FIXME: have only one queue, for now */ | ||
| 332 | return 0; | ||
| 333 | |||
| 334 | index = ring->index; | ||
| 335 | if (B43_WARN_ON(index >= ARRAY_SIZE(idx_to_prio))) | ||
| 336 | index = 0; | ||
| 337 | return idx_to_prio[index]; | ||
| 338 | } | ||
| 339 | |||
| 340 | static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx) | 295 | static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx) |
| 341 | { | 296 | { |
| 342 | static const u16 map64[] = { | 297 | static const u16 map64[] = { |
| @@ -924,16 +879,52 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
| 924 | goto out; | 879 | goto out; |
| 925 | } | 880 | } |
| 926 | 881 | ||
| 882 | #define divide(a, b) ({ \ | ||
| 883 | typeof(a) __a = a; \ | ||
| 884 | do_div(__a, b); \ | ||
| 885 | __a; \ | ||
| 886 | }) | ||
| 887 | |||
| 888 | #define modulo(a, b) ({ \ | ||
| 889 | typeof(a) __a = a; \ | ||
| 890 | do_div(__a, b); \ | ||
| 891 | }) | ||
| 892 | |||
| 927 | /* Main cleanup function. */ | 893 | /* Main cleanup function. */ |
| 928 | static void b43_destroy_dmaring(struct b43_dmaring *ring) | 894 | static void b43_destroy_dmaring(struct b43_dmaring *ring, |
| 895 | const char *ringname) | ||
| 929 | { | 896 | { |
| 930 | if (!ring) | 897 | if (!ring) |
| 931 | return; | 898 | return; |
| 932 | 899 | ||
| 933 | b43dbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots: %d/%d\n", | 900 | #ifdef CONFIG_B43_DEBUG |
| 934 | (unsigned int)(ring->type), | 901 | { |
| 935 | ring->mmio_base, | 902 | /* Print some statistics. */ |
| 936 | (ring->tx) ? "TX" : "RX", ring->max_used_slots, ring->nr_slots); | 903 | u64 failed_packets = ring->nr_failed_tx_packets; |
| 904 | u64 succeed_packets = ring->nr_succeed_tx_packets; | ||
| 905 | u64 nr_packets = failed_packets + succeed_packets; | ||
| 906 | u64 permille_failed = 0, average_tries = 0; | ||
| 907 | |||
| 908 | if (nr_packets) | ||
| 909 | permille_failed = divide(failed_packets * 1000, nr_packets); | ||
| 910 | if (nr_packets) | ||
| 911 | average_tries = divide(ring->nr_total_packet_tries * 100, nr_packets); | ||
| 912 | |||
| 913 | b43dbg(ring->dev->wl, "DMA-%u %s: " | ||
| 914 | "Used slots %d/%d, Failed frames %llu/%llu = %llu.%01llu%%, " | ||
| 915 | "Average tries %llu.%02llu\n", | ||
| 916 | (unsigned int)(ring->type), ringname, | ||
| 917 | ring->max_used_slots, | ||
| 918 | ring->nr_slots, | ||
| 919 | (unsigned long long)failed_packets, | ||
| 920 | (unsigned long long)nr_packets, | ||
| 921 | (unsigned long long)divide(permille_failed, 10), | ||
| 922 | (unsigned long long)modulo(permille_failed, 10), | ||
| 923 | (unsigned long long)divide(average_tries, 100), | ||
| 924 | (unsigned long long)modulo(average_tries, 100)); | ||
| 925 | } | ||
| 926 | #endif /* DEBUG */ | ||
| 927 | |||
| 937 | /* Device IRQs are disabled prior entering this function, | 928 | /* Device IRQs are disabled prior entering this function, |
| 938 | * so no need to take care of concurrency with rx handler stuff. | 929 | * so no need to take care of concurrency with rx handler stuff. |
| 939 | */ | 930 | */ |
| @@ -946,33 +937,26 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring) | |||
| 946 | kfree(ring); | 937 | kfree(ring); |
| 947 | } | 938 | } |
| 948 | 939 | ||
| 940 | #define destroy_ring(dma, ring) do { \ | ||
| 941 | b43_destroy_dmaring((dma)->ring, __stringify(ring)); \ | ||
| 942 | (dma)->ring = NULL; \ | ||
| 943 | } while (0) | ||
| 944 | |||
| 949 | void b43_dma_free(struct b43_wldev *dev) | 945 | void b43_dma_free(struct b43_wldev *dev) |
| 950 | { | 946 | { |
| 951 | struct b43_dma *dma = &dev->dma; | 947 | struct b43_dma *dma = &dev->dma; |
| 952 | 948 | ||
| 953 | b43_destroy_dmaring(dma->rx_ring3); | 949 | destroy_ring(dma, rx_ring); |
| 954 | dma->rx_ring3 = NULL; | 950 | destroy_ring(dma, tx_ring_AC_BK); |
| 955 | b43_destroy_dmaring(dma->rx_ring0); | 951 | destroy_ring(dma, tx_ring_AC_BE); |
| 956 | dma->rx_ring0 = NULL; | 952 | destroy_ring(dma, tx_ring_AC_VI); |
| 957 | 953 | destroy_ring(dma, tx_ring_AC_VO); | |
| 958 | b43_destroy_dmaring(dma->tx_ring5); | 954 | destroy_ring(dma, tx_ring_mcast); |
| 959 | dma->tx_ring5 = NULL; | ||
| 960 | b43_destroy_dmaring(dma->tx_ring4); | ||
| 961 | dma->tx_ring4 = NULL; | ||
| 962 | b43_destroy_dmaring(dma->tx_ring3); | ||
| 963 | dma->tx_ring3 = NULL; | ||
| 964 | b43_destroy_dmaring(dma->tx_ring2); | ||
| 965 | dma->tx_ring2 = NULL; | ||
| 966 | b43_destroy_dmaring(dma->tx_ring1); | ||
| 967 | dma->tx_ring1 = NULL; | ||
| 968 | b43_destroy_dmaring(dma->tx_ring0); | ||
| 969 | dma->tx_ring0 = NULL; | ||
| 970 | } | 955 | } |
| 971 | 956 | ||
| 972 | int b43_dma_init(struct b43_wldev *dev) | 957 | int b43_dma_init(struct b43_wldev *dev) |
| 973 | { | 958 | { |
| 974 | struct b43_dma *dma = &dev->dma; | 959 | struct b43_dma *dma = &dev->dma; |
| 975 | struct b43_dmaring *ring; | ||
| 976 | int err; | 960 | int err; |
| 977 | u64 dmamask; | 961 | u64 dmamask; |
| 978 | enum b43_dmatype type; | 962 | enum b43_dmatype type; |
| @@ -1002,83 +986,57 @@ int b43_dma_init(struct b43_wldev *dev) | |||
| 1002 | 986 | ||
| 1003 | err = -ENOMEM; | 987 | err = -ENOMEM; |
| 1004 | /* setup TX DMA channels. */ | 988 | /* setup TX DMA channels. */ |
| 1005 | ring = b43_setup_dmaring(dev, 0, 1, type); | 989 | dma->tx_ring_AC_BK = b43_setup_dmaring(dev, 0, 1, type); |
| 1006 | if (!ring) | 990 | if (!dma->tx_ring_AC_BK) |
| 1007 | goto out; | 991 | goto out; |
| 1008 | dma->tx_ring0 = ring; | ||
| 1009 | 992 | ||
| 1010 | ring = b43_setup_dmaring(dev, 1, 1, type); | 993 | dma->tx_ring_AC_BE = b43_setup_dmaring(dev, 1, 1, type); |
| 1011 | if (!ring) | 994 | if (!dma->tx_ring_AC_BE) |
| 1012 | goto err_destroy_tx0; | 995 | goto err_destroy_bk; |
| 1013 | dma->tx_ring1 = ring; | ||
| 1014 | 996 | ||
| 1015 | ring = b43_setup_dmaring(dev, 2, 1, type); | 997 | dma->tx_ring_AC_VI = b43_setup_dmaring(dev, 2, 1, type); |
| 1016 | if (!ring) | 998 | if (!dma->tx_ring_AC_VI) |
| 1017 | goto err_destroy_tx1; | 999 | goto err_destroy_be; |
| 1018 | dma->tx_ring2 = ring; | ||
| 1019 | 1000 | ||
| 1020 | ring = b43_setup_dmaring(dev, 3, 1, type); | 1001 | dma->tx_ring_AC_VO = b43_setup_dmaring(dev, 3, 1, type); |
| 1021 | if (!ring) | 1002 | if (!dma->tx_ring_AC_VO) |
| 1022 | goto err_destroy_tx2; | 1003 | goto err_destroy_vi; |
| 1023 | dma->tx_ring3 = ring; | ||
| 1024 | 1004 | ||
| 1025 | ring = b43_setup_dmaring(dev, 4, 1, type); | 1005 | dma->tx_ring_mcast = b43_setup_dmaring(dev, 4, 1, type); |
| 1026 | if (!ring) | 1006 | if (!dma->tx_ring_mcast) |
| 1027 | goto err_destroy_tx3; | 1007 | goto err_destroy_vo; |
| 1028 | dma->tx_ring4 = ring; | ||
| 1029 | 1008 | ||
| 1030 | ring = b43_setup_dmaring(dev, 5, 1, type); | 1009 | /* setup RX DMA channel. */ |
| 1031 | if (!ring) | 1010 | dma->rx_ring = b43_setup_dmaring(dev, 0, 0, type); |
| 1032 | goto err_destroy_tx4; | 1011 | if (!dma->rx_ring) |
| 1033 | dma->tx_ring5 = ring; | 1012 | goto err_destroy_mcast; |
| 1034 | 1013 | ||
| 1035 | /* setup RX DMA channels. */ | 1014 | /* No support for the TX status DMA ring. */ |
| 1036 | ring = b43_setup_dmaring(dev, 0, 0, type); | 1015 | B43_WARN_ON(dev->dev->id.revision < 5); |
| 1037 | if (!ring) | ||
| 1038 | goto err_destroy_tx5; | ||
| 1039 | dma->rx_ring0 = ring; | ||
| 1040 | |||
| 1041 | if (dev->dev->id.revision < 5) { | ||
| 1042 | ring = b43_setup_dmaring(dev, 3, 0, type); | ||
| 1043 | if (!ring) | ||
| 1044 | goto err_destroy_rx0; | ||
| 1045 | dma->rx_ring3 = ring; | ||
| 1046 | } | ||
| 1047 | 1016 | ||
| 1048 | b43dbg(dev->wl, "%u-bit DMA initialized\n", | 1017 | b43dbg(dev->wl, "%u-bit DMA initialized\n", |
| 1049 | (unsigned int)type); | 1018 | (unsigned int)type); |
| 1050 | err = 0; | 1019 | err = 0; |
| 1051 | out: | 1020 | out: |
| 1052 | return err; | 1021 | return err; |
| 1053 | 1022 | ||
| 1054 | err_destroy_rx0: | 1023 | err_destroy_mcast: |
| 1055 | b43_destroy_dmaring(dma->rx_ring0); | 1024 | destroy_ring(dma, tx_ring_mcast); |
| 1056 | dma->rx_ring0 = NULL; | 1025 | err_destroy_vo: |
| 1057 | err_destroy_tx5: | 1026 | destroy_ring(dma, tx_ring_AC_VO); |
| 1058 | b43_destroy_dmaring(dma->tx_ring5); | 1027 | err_destroy_vi: |
| 1059 | dma->tx_ring5 = NULL; | 1028 | destroy_ring(dma, tx_ring_AC_VI); |
| 1060 | err_destroy_tx4: | 1029 | err_destroy_be: |
| 1061 | b43_destroy_dmaring(dma->tx_ring4); | 1030 | destroy_ring(dma, tx_ring_AC_BE); |
| 1062 | dma->tx_ring4 = NULL; | 1031 | err_destroy_bk: |
| 1063 | err_destroy_tx3: | 1032 | destroy_ring(dma, tx_ring_AC_BK); |
| 1064 | b43_destroy_dmaring(dma->tx_ring3); | 1033 | return err; |
| 1065 | dma->tx_ring3 = NULL; | ||
| 1066 | err_destroy_tx2: | ||
| 1067 | b43_destroy_dmaring(dma->tx_ring2); | ||
| 1068 | dma->tx_ring2 = NULL; | ||
| 1069 | err_destroy_tx1: | ||
| 1070 | b43_destroy_dmaring(dma->tx_ring1); | ||
| 1071 | dma->tx_ring1 = NULL; | ||
| 1072 | err_destroy_tx0: | ||
| 1073 | b43_destroy_dmaring(dma->tx_ring0); | ||
| 1074 | dma->tx_ring0 = NULL; | ||
| 1075 | goto out; | ||
| 1076 | } | 1034 | } |
| 1077 | 1035 | ||
| 1078 | /* Generate a cookie for the TX header. */ | 1036 | /* Generate a cookie for the TX header. */ |
| 1079 | static u16 generate_cookie(struct b43_dmaring *ring, int slot) | 1037 | static u16 generate_cookie(struct b43_dmaring *ring, int slot) |
| 1080 | { | 1038 | { |
| 1081 | u16 cookie = 0x1000; | 1039 | u16 cookie; |
| 1082 | 1040 | ||
| 1083 | /* Use the upper 4 bits of the cookie as | 1041 | /* Use the upper 4 bits of the cookie as |
| 1084 | * DMA controller ID and store the slot number | 1042 | * DMA controller ID and store the slot number |
| @@ -1088,30 +1046,9 @@ static u16 generate_cookie(struct b43_dmaring *ring, int slot) | |||
| 1088 | * It can also not be 0xFFFF because that is special | 1046 | * It can also not be 0xFFFF because that is special |
| 1089 | * for multicast frames. | 1047 | * for multicast frames. |
| 1090 | */ | 1048 | */ |
| 1091 | switch (ring->index) { | 1049 | cookie = (((u16)ring->index + 1) << 12); |
| 1092 | case 0: | ||
| 1093 | cookie = 0x1000; | ||
| 1094 | break; | ||
| 1095 | case 1: | ||
| 1096 | cookie = 0x2000; | ||
| 1097 | break; | ||
| 1098 | case 2: | ||
| 1099 | cookie = 0x3000; | ||
| 1100 | break; | ||
| 1101 | case 3: | ||
| 1102 | cookie = 0x4000; | ||
| 1103 | break; | ||
| 1104 | case 4: | ||
| 1105 | cookie = 0x5000; | ||
| 1106 | break; | ||
| 1107 | case 5: | ||
| 1108 | cookie = 0x6000; | ||
| 1109 | break; | ||
| 1110 | default: | ||
| 1111 | B43_WARN_ON(1); | ||
| 1112 | } | ||
| 1113 | B43_WARN_ON(slot & ~0x0FFF); | 1050 | B43_WARN_ON(slot & ~0x0FFF); |
| 1114 | cookie |= (u16) slot; | 1051 | cookie |= (u16)slot; |
| 1115 | 1052 | ||
| 1116 | return cookie; | 1053 | return cookie; |
| 1117 | } | 1054 | } |
| @@ -1125,22 +1062,19 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot) | |||
| 1125 | 1062 | ||
| 1126 | switch (cookie & 0xF000) { | 1063 | switch (cookie & 0xF000) { |
| 1127 | case 0x1000: | 1064 | case 0x1000: |
| 1128 | ring = dma->tx_ring0; | 1065 | ring = dma->tx_ring_AC_BK; |
| 1129 | break; | 1066 | break; |
| 1130 | case 0x2000: | 1067 | case 0x2000: |
| 1131 | ring = dma->tx_ring1; | 1068 | ring = dma->tx_ring_AC_BE; |
| 1132 | break; | 1069 | break; |
| 1133 | case 0x3000: | 1070 | case 0x3000: |
| 1134 | ring = dma->tx_ring2; | 1071 | ring = dma->tx_ring_AC_VI; |
| 1135 | break; | 1072 | break; |
| 1136 | case 0x4000: | 1073 | case 0x4000: |
| 1137 | ring = dma->tx_ring3; | 1074 | ring = dma->tx_ring_AC_VO; |
| 1138 | break; | 1075 | break; |
| 1139 | case 0x5000: | 1076 | case 0x5000: |
| 1140 | ring = dma->tx_ring4; | 1077 | ring = dma->tx_ring_mcast; |
| 1141 | break; | ||
| 1142 | case 0x6000: | ||
| 1143 | ring = dma->tx_ring5; | ||
| 1144 | break; | 1078 | break; |
| 1145 | default: | 1079 | default: |
| 1146 | B43_WARN_ON(1); | 1080 | B43_WARN_ON(1); |
| @@ -1272,6 +1206,37 @@ static inline int should_inject_overflow(struct b43_dmaring *ring) | |||
| 1272 | return 0; | 1206 | return 0; |
| 1273 | } | 1207 | } |
| 1274 | 1208 | ||
| 1209 | /* Static mapping of mac80211's queues (priorities) to b43 DMA rings. */ | ||
| 1210 | static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev, | ||
| 1211 | u8 queue_prio) | ||
| 1212 | { | ||
| 1213 | struct b43_dmaring *ring; | ||
| 1214 | |||
| 1215 | if (b43_modparam_qos) { | ||
| 1216 | /* 0 = highest priority */ | ||
| 1217 | switch (queue_prio) { | ||
| 1218 | default: | ||
| 1219 | B43_WARN_ON(1); | ||
| 1220 | /* fallthrough */ | ||
| 1221 | case 0: | ||
| 1222 | ring = dev->dma.tx_ring_AC_VO; | ||
| 1223 | break; | ||
| 1224 | case 1: | ||
| 1225 | ring = dev->dma.tx_ring_AC_VI; | ||
| 1226 | break; | ||
| 1227 | case 2: | ||
| 1228 | ring = dev->dma.tx_ring_AC_BE; | ||
| 1229 | break; | ||
| 1230 | case 3: | ||
| 1231 | ring = dev->dma.tx_ring_AC_BK; | ||
| 1232 | break; | ||
| 1233 | } | ||
| 1234 | } else | ||
| 1235 | ring = dev->dma.tx_ring_AC_BE; | ||
| 1236 | |||
| 1237 | return ring; | ||
| 1238 | } | ||
| 1239 | |||
| 1275 | int b43_dma_tx(struct b43_wldev *dev, | 1240 | int b43_dma_tx(struct b43_wldev *dev, |
| 1276 | struct sk_buff *skb, struct ieee80211_tx_control *ctl) | 1241 | struct sk_buff *skb, struct ieee80211_tx_control *ctl) |
| 1277 | { | 1242 | { |
| @@ -1288,13 +1253,13 @@ int b43_dma_tx(struct b43_wldev *dev, | |||
| 1288 | hdr = (struct ieee80211_hdr *)skb->data; | 1253 | hdr = (struct ieee80211_hdr *)skb->data; |
| 1289 | if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { | 1254 | if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { |
| 1290 | /* The multicast ring will be sent after the DTIM */ | 1255 | /* The multicast ring will be sent after the DTIM */ |
| 1291 | ring = dev->dma.tx_ring4; | 1256 | ring = dev->dma.tx_ring_mcast; |
| 1292 | /* Set the more-data bit. Ucode will clear it on | 1257 | /* Set the more-data bit. Ucode will clear it on |
| 1293 | * the last frame for us. */ | 1258 | * the last frame for us. */ |
| 1294 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 1259 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
| 1295 | } else { | 1260 | } else { |
| 1296 | /* Decide by priority where to put this frame. */ | 1261 | /* Decide by priority where to put this frame. */ |
| 1297 | ring = priority_to_txring(dev, ctl->queue); | 1262 | ring = select_ring_by_priority(dev, ctl->queue); |
| 1298 | } | 1263 | } |
| 1299 | 1264 | ||
| 1300 | spin_lock_irqsave(&ring->lock, flags); | 1265 | spin_lock_irqsave(&ring->lock, flags); |
| @@ -1309,6 +1274,11 @@ int b43_dma_tx(struct b43_wldev *dev, | |||
| 1309 | * That would be a mac80211 bug. */ | 1274 | * That would be a mac80211 bug. */ |
| 1310 | B43_WARN_ON(ring->stopped); | 1275 | B43_WARN_ON(ring->stopped); |
| 1311 | 1276 | ||
| 1277 | /* Assign the queue number to the ring (if not already done before) | ||
| 1278 | * so TX status handling can use it. The queue to ring mapping is | ||
| 1279 | * static, so we don't need to store it per frame. */ | ||
| 1280 | ring->queue_prio = ctl->queue; | ||
| 1281 | |||
| 1312 | err = dma_tx_fragment(ring, skb, ctl); | 1282 | err = dma_tx_fragment(ring, skb, ctl); |
| 1313 | if (unlikely(err == -ENOKEY)) { | 1283 | if (unlikely(err == -ENOKEY)) { |
| 1314 | /* Drop this packet, as we don't have the encryption key | 1284 | /* Drop this packet, as we don't have the encryption key |
| @@ -1325,7 +1295,7 @@ int b43_dma_tx(struct b43_wldev *dev, | |||
| 1325 | if ((free_slots(ring) < SLOTS_PER_PACKET) || | 1295 | if ((free_slots(ring) < SLOTS_PER_PACKET) || |
| 1326 | should_inject_overflow(ring)) { | 1296 | should_inject_overflow(ring)) { |
| 1327 | /* This TX ring is full. */ | 1297 | /* This TX ring is full. */ |
| 1328 | ieee80211_stop_queue(dev->wl->hw, txring_to_priority(ring)); | 1298 | ieee80211_stop_queue(dev->wl->hw, ctl->queue); |
| 1329 | ring->stopped = 1; | 1299 | ring->stopped = 1; |
| 1330 | if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { | 1300 | if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { |
| 1331 | b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); | 1301 | b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); |
| @@ -1337,6 +1307,38 @@ out_unlock: | |||
| 1337 | return err; | 1307 | return err; |
| 1338 | } | 1308 | } |
| 1339 | 1309 | ||
| 1310 | static void b43_fill_txstatus_report(struct b43_dmaring *ring, | ||
| 1311 | struct ieee80211_tx_status *report, | ||
| 1312 | const struct b43_txstatus *status) | ||
| 1313 | { | ||
| 1314 | bool frame_failed = 0; | ||
| 1315 | |||
| 1316 | if (status->acked) { | ||
| 1317 | /* The frame was ACKed. */ | ||
| 1318 | report->flags |= IEEE80211_TX_STATUS_ACK; | ||
| 1319 | } else { | ||
| 1320 | /* The frame was not ACKed... */ | ||
| 1321 | if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) { | ||
| 1322 | /* ...but we expected an ACK. */ | ||
| 1323 | frame_failed = 1; | ||
| 1324 | report->excessive_retries = 1; | ||
| 1325 | } | ||
| 1326 | } | ||
| 1327 | if (status->frame_count == 0) { | ||
| 1328 | /* The frame was not transmitted at all. */ | ||
| 1329 | report->retry_count = 0; | ||
| 1330 | } else { | ||
| 1331 | report->retry_count = status->frame_count - 1; | ||
| 1332 | #ifdef CONFIG_B43_DEBUG | ||
| 1333 | if (frame_failed) | ||
| 1334 | ring->nr_failed_tx_packets++; | ||
| 1335 | else | ||
| 1336 | ring->nr_succeed_tx_packets++; | ||
| 1337 | ring->nr_total_packet_tries += status->frame_count; | ||
| 1338 | #endif /* DEBUG */ | ||
| 1339 | } | ||
| 1340 | } | ||
| 1341 | |||
| 1340 | void b43_dma_handle_txstatus(struct b43_wldev *dev, | 1342 | void b43_dma_handle_txstatus(struct b43_wldev *dev, |
| 1341 | const struct b43_txstatus *status) | 1343 | const struct b43_txstatus *status) |
| 1342 | { | 1344 | { |
| @@ -1371,18 +1373,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
| 1371 | * status of the transmission. | 1373 | * status of the transmission. |
| 1372 | * Some fields of txstat are already filled in dma_tx(). | 1374 | * Some fields of txstat are already filled in dma_tx(). |
| 1373 | */ | 1375 | */ |
| 1374 | if (status->acked) { | 1376 | b43_fill_txstatus_report(ring, &(meta->txstat), status); |
| 1375 | meta->txstat.flags |= IEEE80211_TX_STATUS_ACK; | ||
| 1376 | } else { | ||
| 1377 | if (!(meta->txstat.control.flags | ||
| 1378 | & IEEE80211_TXCTL_NO_ACK)) | ||
| 1379 | meta->txstat.excessive_retries = 1; | ||
| 1380 | } | ||
| 1381 | if (status->frame_count == 0) { | ||
| 1382 | /* The frame was not transmitted at all. */ | ||
| 1383 | meta->txstat.retry_count = 0; | ||
| 1384 | } else | ||
| 1385 | meta->txstat.retry_count = status->frame_count - 1; | ||
| 1386 | ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb, | 1377 | ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb, |
| 1387 | &(meta->txstat)); | 1378 | &(meta->txstat)); |
| 1388 | /* skb is freed by ieee80211_tx_status_irqsafe() */ | 1379 | /* skb is freed by ieee80211_tx_status_irqsafe() */ |
| @@ -1404,7 +1395,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
| 1404 | dev->stats.last_tx = jiffies; | 1395 | dev->stats.last_tx = jiffies; |
| 1405 | if (ring->stopped) { | 1396 | if (ring->stopped) { |
| 1406 | B43_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET); | 1397 | B43_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET); |
| 1407 | ieee80211_wake_queue(dev->wl->hw, txring_to_priority(ring)); | 1398 | ieee80211_wake_queue(dev->wl->hw, ring->queue_prio); |
| 1408 | ring->stopped = 0; | 1399 | ring->stopped = 0; |
| 1409 | if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { | 1400 | if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { |
| 1410 | b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index); | 1401 | b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index); |
| @@ -1425,7 +1416,7 @@ void b43_dma_get_tx_stats(struct b43_wldev *dev, | |||
| 1425 | 1416 | ||
| 1426 | for (i = 0; i < nr_queues; i++) { | 1417 | for (i = 0; i < nr_queues; i++) { |
| 1427 | data = &(stats->data[i]); | 1418 | data = &(stats->data[i]); |
| 1428 | ring = priority_to_txring(dev, i); | 1419 | ring = select_ring_by_priority(dev, i); |
| 1429 | 1420 | ||
| 1430 | spin_lock_irqsave(&ring->lock, flags); | 1421 | spin_lock_irqsave(&ring->lock, flags); |
| 1431 | data->len = ring->used_slots / SLOTS_PER_PACKET; | 1422 | data->len = ring->used_slots / SLOTS_PER_PACKET; |
| @@ -1451,25 +1442,6 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) | |||
| 1451 | sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); | 1442 | sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); |
| 1452 | skb = meta->skb; | 1443 | skb = meta->skb; |
| 1453 | 1444 | ||
| 1454 | if (ring->index == 3) { | ||
| 1455 | /* We received an xmit status. */ | ||
| 1456 | struct b43_hwtxstatus *hw = (struct b43_hwtxstatus *)skb->data; | ||
| 1457 | int i = 0; | ||
| 1458 | |||
| 1459 | while (hw->cookie == 0) { | ||
| 1460 | if (i > 100) | ||
| 1461 | break; | ||
| 1462 | i++; | ||
| 1463 | udelay(2); | ||
| 1464 | barrier(); | ||
| 1465 | } | ||
| 1466 | b43_handle_hwtxstatus(ring->dev, hw); | ||
| 1467 | /* recycle the descriptor buffer. */ | ||
| 1468 | sync_descbuffer_for_device(ring, meta->dmaaddr, | ||
| 1469 | ring->rx_buffersize); | ||
| 1470 | |||
| 1471 | return; | ||
| 1472 | } | ||
| 1473 | rxhdr = (struct b43_rxhdr_fw4 *)skb->data; | 1445 | rxhdr = (struct b43_rxhdr_fw4 *)skb->data; |
| 1474 | len = le16_to_cpu(rxhdr->frame_len); | 1446 | len = le16_to_cpu(rxhdr->frame_len); |
| 1475 | if (len == 0) { | 1447 | if (len == 0) { |
| @@ -1526,7 +1498,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) | |||
| 1526 | skb_pull(skb, ring->frameoffset); | 1498 | skb_pull(skb, ring->frameoffset); |
| 1527 | 1499 | ||
| 1528 | b43_rx(ring->dev, skb, rxhdr); | 1500 | b43_rx(ring->dev, skb, rxhdr); |
| 1529 | drop: | 1501 | drop: |
| 1530 | return; | 1502 | return; |
| 1531 | } | 1503 | } |
| 1532 | 1504 | ||
| @@ -1572,21 +1544,19 @@ static void b43_dma_tx_resume_ring(struct b43_dmaring *ring) | |||
| 1572 | void b43_dma_tx_suspend(struct b43_wldev *dev) | 1544 | void b43_dma_tx_suspend(struct b43_wldev *dev) |
| 1573 | { | 1545 | { |
| 1574 | b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); | 1546 | b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); |
| 1575 | b43_dma_tx_suspend_ring(dev->dma.tx_ring0); | 1547 | b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BK); |
| 1576 | b43_dma_tx_suspend_ring(dev->dma.tx_ring1); | 1548 | b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BE); |
| 1577 | b43_dma_tx_suspend_ring(dev->dma.tx_ring2); | 1549 | b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VI); |
| 1578 | b43_dma_tx_suspend_ring(dev->dma.tx_ring3); | 1550 | b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VO); |
| 1579 | b43_dma_tx_suspend_ring(dev->dma.tx_ring4); | 1551 | b43_dma_tx_suspend_ring(dev->dma.tx_ring_mcast); |
| 1580 | b43_dma_tx_suspend_ring(dev->dma.tx_ring5); | ||
| 1581 | } | 1552 | } |
| 1582 | 1553 | ||
| 1583 | void b43_dma_tx_resume(struct b43_wldev *dev) | 1554 | void b43_dma_tx_resume(struct b43_wldev *dev) |
| 1584 | { | 1555 | { |
| 1585 | b43_dma_tx_resume_ring(dev->dma.tx_ring5); | 1556 | b43_dma_tx_resume_ring(dev->dma.tx_ring_mcast); |
| 1586 | b43_dma_tx_resume_ring(dev->dma.tx_ring4); | 1557 | b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VO); |
| 1587 | b43_dma_tx_resume_ring(dev->dma.tx_ring3); | 1558 | b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VI); |
| 1588 | b43_dma_tx_resume_ring(dev->dma.tx_ring2); | 1559 | b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BE); |
| 1589 | b43_dma_tx_resume_ring(dev->dma.tx_ring1); | 1560 | b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BK); |
| 1590 | b43_dma_tx_resume_ring(dev->dma.tx_ring0); | ||
| 1591 | b43_power_saving_ctl_bits(dev, 0); | 1561 | b43_power_saving_ctl_bits(dev, 0); |
| 1592 | } | 1562 | } |
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index c0d6b69e6501..ea27085dec0e 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h | |||
| @@ -245,6 +245,9 @@ struct b43_dmaring { | |||
| 245 | enum b43_dmatype type; | 245 | enum b43_dmatype type; |
| 246 | /* Boolean. Is this ring stopped at ieee80211 level? */ | 246 | /* Boolean. Is this ring stopped at ieee80211 level? */ |
| 247 | bool stopped; | 247 | bool stopped; |
| 248 | /* The QOS priority assigned to this ring. Only used for TX rings. | ||
| 249 | * This is the mac80211 "queue" value. */ | ||
| 250 | u8 queue_prio; | ||
| 248 | /* Lock, only used for TX. */ | 251 | /* Lock, only used for TX. */ |
| 249 | spinlock_t lock; | 252 | spinlock_t lock; |
| 250 | struct b43_wldev *dev; | 253 | struct b43_wldev *dev; |
| @@ -253,7 +256,13 @@ struct b43_dmaring { | |||
| 253 | int max_used_slots; | 256 | int max_used_slots; |
| 254 | /* Last time we injected a ring overflow. */ | 257 | /* Last time we injected a ring overflow. */ |
| 255 | unsigned long last_injected_overflow; | 258 | unsigned long last_injected_overflow; |
| 256 | #endif /* CONFIG_B43_DEBUG */ | 259 | /* Statistics: Number of successfully transmitted packets */ |
| 260 | u64 nr_succeed_tx_packets; | ||
| 261 | /* Statistics: Number of failed TX packets */ | ||
| 262 | u64 nr_failed_tx_packets; | ||
| 263 | /* Statistics: Total number of TX plus all retries. */ | ||
| 264 | u64 nr_total_packet_tries; | ||
| 265 | #endif /* CONFIG_B43_DEBUG */ | ||
| 257 | }; | 266 | }; |
| 258 | 267 | ||
| 259 | static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset) | 268 | static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset) |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index f745308faaad..694e29570e5d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
| @@ -78,6 +78,11 @@ static int modparam_nohwcrypt; | |||
| 78 | module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); | 78 | module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); |
| 79 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 79 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
| 80 | 80 | ||
| 81 | int b43_modparam_qos = 1; | ||
| 82 | module_param_named(qos, b43_modparam_qos, int, 0444); | ||
| 83 | MODULE_PARM_DESC(qos, "Enable QOS support (default on)"); | ||
| 84 | |||
| 85 | |||
| 81 | static const struct ssb_device_id b43_ssb_tbl[] = { | 86 | static const struct ssb_device_id b43_ssb_tbl[] = { |
| 82 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), | 87 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), |
| 83 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6), | 88 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6), |
| @@ -1589,11 +1594,10 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev) | |||
| 1589 | 1594 | ||
| 1590 | /* Check the DMA reason registers for received data. */ | 1595 | /* Check the DMA reason registers for received data. */ |
| 1591 | if (dma_reason[0] & B43_DMAIRQ_RX_DONE) | 1596 | if (dma_reason[0] & B43_DMAIRQ_RX_DONE) |
| 1592 | b43_dma_rx(dev->dma.rx_ring0); | 1597 | b43_dma_rx(dev->dma.rx_ring); |
| 1593 | if (dma_reason[3] & B43_DMAIRQ_RX_DONE) | ||
| 1594 | b43_dma_rx(dev->dma.rx_ring3); | ||
| 1595 | B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE); | 1598 | B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE); |
| 1596 | B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE); | 1599 | B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE); |
| 1600 | B43_WARN_ON(dma_reason[3] & B43_DMAIRQ_RX_DONE); | ||
| 1597 | B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE); | 1601 | B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE); |
| 1598 | B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE); | 1602 | B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE); |
| 1599 | 1603 | ||
| @@ -2708,10 +2712,178 @@ out: | |||
| 2708 | return NETDEV_TX_OK; | 2712 | return NETDEV_TX_OK; |
| 2709 | } | 2713 | } |
| 2710 | 2714 | ||
| 2715 | /* Locking: wl->irq_lock */ | ||
| 2716 | static void b43_qos_params_upload(struct b43_wldev *dev, | ||
| 2717 | const struct ieee80211_tx_queue_params *p, | ||
| 2718 | u16 shm_offset) | ||
| 2719 | { | ||
| 2720 | u16 params[B43_NR_QOSPARAMS]; | ||
| 2721 | int cw_min, cw_max, aifs, bslots, tmp; | ||
| 2722 | unsigned int i; | ||
| 2723 | |||
| 2724 | const u16 aCWmin = 0x0001; | ||
| 2725 | const u16 aCWmax = 0x03FF; | ||
| 2726 | |||
| 2727 | /* Calculate the default values for the parameters, if needed. */ | ||
| 2728 | switch (shm_offset) { | ||
| 2729 | case B43_QOS_VOICE: | ||
| 2730 | aifs = (p->aifs == -1) ? 2 : p->aifs; | ||
| 2731 | cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 4 - 1) : p->cw_min; | ||
| 2732 | cw_max = (p->cw_max == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_max; | ||
| 2733 | break; | ||
| 2734 | case B43_QOS_VIDEO: | ||
| 2735 | aifs = (p->aifs == -1) ? 2 : p->aifs; | ||
| 2736 | cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_min; | ||
| 2737 | cw_max = (p->cw_max == 0) ? aCWmin : p->cw_max; | ||
| 2738 | break; | ||
| 2739 | case B43_QOS_BESTEFFORT: | ||
| 2740 | aifs = (p->aifs == -1) ? 3 : p->aifs; | ||
| 2741 | cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min; | ||
| 2742 | cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max; | ||
| 2743 | break; | ||
| 2744 | case B43_QOS_BACKGROUND: | ||
| 2745 | aifs = (p->aifs == -1) ? 7 : p->aifs; | ||
| 2746 | cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min; | ||
| 2747 | cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max; | ||
| 2748 | break; | ||
| 2749 | default: | ||
| 2750 | B43_WARN_ON(1); | ||
| 2751 | return; | ||
| 2752 | } | ||
| 2753 | if (cw_min <= 0) | ||
| 2754 | cw_min = aCWmin; | ||
| 2755 | if (cw_max <= 0) | ||
| 2756 | cw_max = aCWmin; | ||
| 2757 | bslots = b43_read16(dev, B43_MMIO_RNG) % cw_min; | ||
| 2758 | |||
| 2759 | memset(¶ms, 0, sizeof(params)); | ||
| 2760 | |||
| 2761 | params[B43_QOSPARAM_TXOP] = p->txop * 32; | ||
| 2762 | params[B43_QOSPARAM_CWMIN] = cw_min; | ||
| 2763 | params[B43_QOSPARAM_CWMAX] = cw_max; | ||
| 2764 | params[B43_QOSPARAM_CWCUR] = cw_min; | ||
| 2765 | params[B43_QOSPARAM_AIFS] = aifs; | ||
| 2766 | params[B43_QOSPARAM_BSLOTS] = bslots; | ||
| 2767 | params[B43_QOSPARAM_REGGAP] = bslots + aifs; | ||
| 2768 | |||
| 2769 | for (i = 0; i < ARRAY_SIZE(params); i++) { | ||
| 2770 | if (i == B43_QOSPARAM_STATUS) { | ||
| 2771 | tmp = b43_shm_read16(dev, B43_SHM_SHARED, | ||
| 2772 | shm_offset + (i * 2)); | ||
| 2773 | /* Mark the parameters as updated. */ | ||
| 2774 | tmp |= 0x100; | ||
| 2775 | b43_shm_write16(dev, B43_SHM_SHARED, | ||
| 2776 | shm_offset + (i * 2), | ||
| 2777 | tmp); | ||
| 2778 | } else { | ||
| 2779 | b43_shm_write16(dev, B43_SHM_SHARED, | ||
| 2780 | shm_offset + (i * 2), | ||
| 2781 | params[i]); | ||
| 2782 | } | ||
| 2783 | } | ||
| 2784 | } | ||
| 2785 | |||
| 2786 | /* Update the QOS parameters in hardware. */ | ||
| 2787 | static void b43_qos_update(struct b43_wldev *dev) | ||
| 2788 | { | ||
| 2789 | struct b43_wl *wl = dev->wl; | ||
| 2790 | struct b43_qos_params *params; | ||
| 2791 | unsigned long flags; | ||
| 2792 | unsigned int i; | ||
| 2793 | |||
| 2794 | /* Mapping of mac80211 queues to b43 SHM offsets. */ | ||
| 2795 | static const u16 qos_shm_offsets[] = { | ||
| 2796 | [0] = B43_QOS_VOICE, | ||
| 2797 | [1] = B43_QOS_VIDEO, | ||
| 2798 | [2] = B43_QOS_BESTEFFORT, | ||
| 2799 | [3] = B43_QOS_BACKGROUND, | ||
| 2800 | }; | ||
| 2801 | BUILD_BUG_ON(ARRAY_SIZE(qos_shm_offsets) != ARRAY_SIZE(wl->qos_params)); | ||
| 2802 | |||
| 2803 | b43_mac_suspend(dev); | ||
| 2804 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
| 2805 | |||
| 2806 | for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) { | ||
| 2807 | params = &(wl->qos_params[i]); | ||
| 2808 | if (params->need_hw_update) { | ||
| 2809 | b43_qos_params_upload(dev, &(params->p), | ||
| 2810 | qos_shm_offsets[i]); | ||
| 2811 | params->need_hw_update = 0; | ||
| 2812 | } | ||
| 2813 | } | ||
| 2814 | |||
| 2815 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
| 2816 | b43_mac_enable(dev); | ||
| 2817 | } | ||
| 2818 | |||
| 2819 | static void b43_qos_clear(struct b43_wl *wl) | ||
| 2820 | { | ||
| 2821 | struct b43_qos_params *params; | ||
| 2822 | unsigned int i; | ||
| 2823 | |||
| 2824 | for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) { | ||
| 2825 | params = &(wl->qos_params[i]); | ||
| 2826 | |||
| 2827 | memset(&(params->p), 0, sizeof(params->p)); | ||
| 2828 | params->p.aifs = -1; | ||
| 2829 | params->need_hw_update = 1; | ||
| 2830 | } | ||
| 2831 | } | ||
| 2832 | |||
| 2833 | /* Initialize the core's QOS capabilities */ | ||
| 2834 | static void b43_qos_init(struct b43_wldev *dev) | ||
| 2835 | { | ||
| 2836 | struct b43_wl *wl = dev->wl; | ||
| 2837 | unsigned int i; | ||
| 2838 | |||
| 2839 | /* Upload the current QOS parameters. */ | ||
| 2840 | for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) | ||
| 2841 | wl->qos_params[i].need_hw_update = 1; | ||
| 2842 | b43_qos_update(dev); | ||
| 2843 | |||
| 2844 | /* Enable QOS support. */ | ||
| 2845 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF); | ||
| 2846 | b43_write16(dev, B43_MMIO_IFSCTL, | ||
| 2847 | b43_read16(dev, B43_MMIO_IFSCTL) | ||
| 2848 | | B43_MMIO_IFSCTL_USE_EDCF); | ||
| 2849 | } | ||
| 2850 | |||
| 2851 | static void b43_qos_update_work(struct work_struct *work) | ||
| 2852 | { | ||
| 2853 | struct b43_wl *wl = container_of(work, struct b43_wl, qos_update_work); | ||
| 2854 | struct b43_wldev *dev; | ||
| 2855 | |||
| 2856 | mutex_lock(&wl->mutex); | ||
| 2857 | dev = wl->current_dev; | ||
| 2858 | if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) | ||
| 2859 | b43_qos_update(dev); | ||
| 2860 | mutex_unlock(&wl->mutex); | ||
| 2861 | } | ||
| 2862 | |||
| 2711 | static int b43_op_conf_tx(struct ieee80211_hw *hw, | 2863 | static int b43_op_conf_tx(struct ieee80211_hw *hw, |
| 2712 | int queue, | 2864 | int _queue, |
| 2713 | const struct ieee80211_tx_queue_params *params) | 2865 | const struct ieee80211_tx_queue_params *params) |
| 2714 | { | 2866 | { |
| 2867 | struct b43_wl *wl = hw_to_b43_wl(hw); | ||
| 2868 | unsigned long flags; | ||
| 2869 | unsigned int queue = (unsigned int)_queue; | ||
| 2870 | struct b43_qos_params *p; | ||
| 2871 | |||
| 2872 | if (queue >= ARRAY_SIZE(wl->qos_params)) { | ||
| 2873 | /* Queue not available or don't support setting | ||
| 2874 | * params on this queue. Return success to not | ||
| 2875 | * confuse mac80211. */ | ||
| 2876 | return 0; | ||
| 2877 | } | ||
| 2878 | |||
| 2879 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
| 2880 | p = &(wl->qos_params[queue]); | ||
| 2881 | memcpy(&(p->p), params, sizeof(p->p)); | ||
| 2882 | p->need_hw_update = 1; | ||
| 2883 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
| 2884 | |||
| 2885 | queue_work(hw->workqueue, &wl->qos_update_work); | ||
| 2886 | |||
| 2715 | return 0; | 2887 | return 0; |
| 2716 | } | 2888 | } |
| 2717 | 2889 | ||
| @@ -3732,6 +3904,7 @@ static int b43_op_start(struct ieee80211_hw *hw) | |||
| 3732 | memset(wl->mac_addr, 0, ETH_ALEN); | 3904 | memset(wl->mac_addr, 0, ETH_ALEN); |
| 3733 | wl->filter_flags = 0; | 3905 | wl->filter_flags = 0; |
| 3734 | wl->radiotap_enabled = 0; | 3906 | wl->radiotap_enabled = 0; |
| 3907 | b43_qos_clear(wl); | ||
| 3735 | 3908 | ||
| 3736 | /* First register RFkill. | 3909 | /* First register RFkill. |
| 3737 | * LEDs that are registered later depend on it. */ | 3910 | * LEDs that are registered later depend on it. */ |
| @@ -3773,6 +3946,7 @@ static void b43_op_stop(struct ieee80211_hw *hw) | |||
| 3773 | struct b43_wldev *dev = wl->current_dev; | 3946 | struct b43_wldev *dev = wl->current_dev; |
| 3774 | 3947 | ||
| 3775 | b43_rfkill_exit(dev); | 3948 | b43_rfkill_exit(dev); |
| 3949 | cancel_work_sync(&(wl->qos_update_work)); | ||
| 3776 | 3950 | ||
| 3777 | mutex_lock(&wl->mutex); | 3951 | mutex_lock(&wl->mutex); |
| 3778 | if (b43_status(dev) >= B43_STAT_STARTED) | 3952 | if (b43_status(dev) >= B43_STAT_STARTED) |
| @@ -3835,6 +4009,16 @@ static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw, | |||
| 3835 | return 0; | 4009 | return 0; |
| 3836 | } | 4010 | } |
| 3837 | 4011 | ||
| 4012 | static void b43_op_sta_notify(struct ieee80211_hw *hw, | ||
| 4013 | struct ieee80211_vif *vif, | ||
| 4014 | enum sta_notify_cmd notify_cmd, | ||
| 4015 | const u8 *addr) | ||
| 4016 | { | ||
| 4017 | struct b43_wl *wl = hw_to_b43_wl(hw); | ||
| 4018 | |||
| 4019 | B43_WARN_ON(!vif || wl->vif != vif); | ||
| 4020 | } | ||
| 4021 | |||
| 3838 | static const struct ieee80211_ops b43_hw_ops = { | 4022 | static const struct ieee80211_ops b43_hw_ops = { |
| 3839 | .tx = b43_op_tx, | 4023 | .tx = b43_op_tx, |
| 3840 | .conf_tx = b43_op_conf_tx, | 4024 | .conf_tx = b43_op_conf_tx, |
| @@ -3851,6 +4035,7 @@ static const struct ieee80211_ops b43_hw_ops = { | |||
| 3851 | .set_retry_limit = b43_op_set_retry_limit, | 4035 | .set_retry_limit = b43_op_set_retry_limit, |
| 3852 | .set_tim = b43_op_beacon_set_tim, | 4036 | .set_tim = b43_op_beacon_set_tim, |
| 3853 | .beacon_update = b43_op_ibss_beacon_update, | 4037 | .beacon_update = b43_op_ibss_beacon_update, |
| 4038 | .sta_notify = b43_op_sta_notify, | ||
| 3854 | }; | 4039 | }; |
| 3855 | 4040 | ||
| 3856 | /* Hard-reset the chip. Do not call this directly. | 4041 | /* Hard-reset the chip. Do not call this directly. |
| @@ -4122,7 +4307,7 @@ static int b43_wireless_init(struct ssb_device *dev) | |||
| 4122 | hw->max_signal = 100; | 4307 | hw->max_signal = 100; |
| 4123 | hw->max_rssi = -110; | 4308 | hw->max_rssi = -110; |
| 4124 | hw->max_noise = -110; | 4309 | hw->max_noise = -110; |
| 4125 | hw->queues = 1; /* FIXME: hardware has more queues */ | 4310 | hw->queues = b43_modparam_qos ? 4 : 1; |
| 4126 | SET_IEEE80211_DEV(hw, dev->dev); | 4311 | SET_IEEE80211_DEV(hw, dev->dev); |
| 4127 | if (is_valid_ether_addr(sprom->et1mac)) | 4312 | if (is_valid_ether_addr(sprom->et1mac)) |
| 4128 | SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); | 4313 | SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); |
| @@ -4138,6 +4323,7 @@ static int b43_wireless_init(struct ssb_device *dev) | |||
| 4138 | spin_lock_init(&wl->shm_lock); | 4323 | spin_lock_init(&wl->shm_lock); |
| 4139 | mutex_init(&wl->mutex); | 4324 | mutex_init(&wl->mutex); |
| 4140 | INIT_LIST_HEAD(&wl->devlist); | 4325 | INIT_LIST_HEAD(&wl->devlist); |
| 4326 | INIT_WORK(&wl->qos_update_work, b43_qos_update_work); | ||
| 4141 | 4327 | ||
| 4142 | ssb_set_devtypedata(dev, wl); | 4328 | ssb_set_devtypedata(dev, wl); |
| 4143 | b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); | 4329 | b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); |
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 24a79f5d6ff5..1197975f9207 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h | |||
| @@ -38,6 +38,10 @@ | |||
| 38 | /* Magic helper macro to pad structures. Ignore those above. It's magic. */ | 38 | /* Magic helper macro to pad structures. Ignore those above. It's magic. */ |
| 39 | #define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) | 39 | #define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) |
| 40 | 40 | ||
| 41 | |||
| 42 | extern int b43_modparam_qos; | ||
| 43 | |||
| 44 | |||
| 41 | /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ | 45 | /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ |
| 42 | static inline u8 b43_freq_to_channel_5ghz(int freq) | 46 | static inline u8 b43_freq_to_channel_5ghz(int freq) |
| 43 | { | 47 | { |
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 187c11bee0f1..ec10a8e182f9 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
| @@ -705,30 +705,3 @@ void b43_tx_resume(struct b43_wldev *dev) | |||
| 705 | { | 705 | { |
| 706 | b43_dma_tx_resume(dev); | 706 | b43_dma_tx_resume(dev); |
| 707 | } | 707 | } |
| 708 | |||
| 709 | #if 0 | ||
| 710 | static void upload_qos_parms(struct b43_wldev *dev, | ||
| 711 | const u16 * parms, u16 offset) | ||
| 712 | { | ||
| 713 | int i; | ||
| 714 | |||
| 715 | for (i = 0; i < B43_NR_QOSPARMS; i++) { | ||
| 716 | b43_shm_write16(dev, B43_SHM_SHARED, | ||
| 717 | offset + (i * 2), parms[i]); | ||
| 718 | } | ||
| 719 | } | ||
| 720 | #endif | ||
| 721 | |||
| 722 | /* Initialize the QoS parameters */ | ||
| 723 | void b43_qos_init(struct b43_wldev *dev) | ||
| 724 | { | ||
| 725 | /* FIXME: This function must probably be called from the mac80211 | ||
| 726 | * config callback. */ | ||
| 727 | return; | ||
| 728 | |||
| 729 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF); | ||
| 730 | //FIXME kill magic | ||
| 731 | b43_write16(dev, 0x688, b43_read16(dev, 0x688) | 0x4); | ||
| 732 | |||
| 733 | /*TODO: We might need some stack support here to get the values. */ | ||
| 734 | } | ||
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 41765039552b..bf58a8a85258 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h | |||
| @@ -302,18 +302,6 @@ void b43_handle_hwtxstatus(struct b43_wldev *dev, | |||
| 302 | void b43_tx_suspend(struct b43_wldev *dev); | 302 | void b43_tx_suspend(struct b43_wldev *dev); |
| 303 | void b43_tx_resume(struct b43_wldev *dev); | 303 | void b43_tx_resume(struct b43_wldev *dev); |
| 304 | 304 | ||
| 305 | #define B43_NR_QOSPARMS 22 | ||
| 306 | enum { | ||
| 307 | B43_QOSPARM_TXOP = 0, | ||
| 308 | B43_QOSPARM_CWMIN, | ||
| 309 | B43_QOSPARM_CWMAX, | ||
| 310 | B43_QOSPARM_CWCUR, | ||
| 311 | B43_QOSPARM_AIFS, | ||
| 312 | B43_QOSPARM_BSLOTS, | ||
| 313 | B43_QOSPARM_REGGAP, | ||
| 314 | B43_QOSPARM_STATUS, | ||
| 315 | }; | ||
| 316 | void b43_qos_init(struct b43_wldev *dev); | ||
| 317 | 305 | ||
| 318 | /* Helper functions for converting the key-table index from "firmware-format" | 306 | /* Helper functions for converting the key-table index from "firmware-format" |
| 319 | * to "raw-format" and back. The firmware API changed for this at some revision. | 307 | * to "raw-format" and back. The firmware API changed for this at some revision. |
