diff options
author | David S. Miller <davem@davemloft.net> | 2008-09-25 16:16:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-09-25 16:16:16 -0400 |
commit | db4148da2cc84c31419b5e3ae3115ac6e11817a1 (patch) | |
tree | 72d7d99cd7a4903e017169e0ae8e2b37027129c6 | |
parent | ef40a685311bef053dedd833a72dffaf25669dda (diff) | |
parent | 8d09a5e1c36d0dec5728e6c8b0bb5412de09b27b (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
60 files changed, 1077 insertions, 1080 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index ae58a12befd3..370133e492d2 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -7107,7 +7107,7 @@ static int airo_get_aplist(struct net_device *dev, | |||
7107 | */ | 7107 | */ |
7108 | static int airo_set_scan(struct net_device *dev, | 7108 | static int airo_set_scan(struct net_device *dev, |
7109 | struct iw_request_info *info, | 7109 | struct iw_request_info *info, |
7110 | struct iw_param *vwrq, | 7110 | struct iw_point *dwrq, |
7111 | char *extra) | 7111 | char *extra) |
7112 | { | 7112 | { |
7113 | struct airo_info *ai = dev->priv; | 7113 | struct airo_info *ai = dev->priv; |
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index f12355398fe7..fd72e427cb28 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c | |||
@@ -147,7 +147,7 @@ static int airo_probe(struct pcmcia_device *p_dev) | |||
147 | DEBUG(0, "airo_attach()\n"); | 147 | DEBUG(0, "airo_attach()\n"); |
148 | 148 | ||
149 | /* Interrupt setup */ | 149 | /* Interrupt setup */ |
150 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 150 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; |
151 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; | 151 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
152 | p_dev->irq.Handler = NULL; | 152 | p_dev->irq.Handler = NULL; |
153 | 153 | ||
diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index 1ea8ed962d26..e43f6563e61a 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c | |||
@@ -2124,7 +2124,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
2124 | beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); | 2124 | beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); |
2125 | ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); | 2125 | ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); |
2126 | 2126 | ||
2127 | udelay(2300); | 2127 | mdelay(2); |
2128 | 2128 | ||
2129 | /* | 2129 | /* |
2130 | * Set the channel (with AGC turned off) | 2130 | * Set the channel (with AGC turned off) |
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h index a98832364448..410f99a6d616 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath5k/reg.h | |||
@@ -820,8 +820,6 @@ | |||
820 | #define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */ | 820 | #define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */ |
821 | #define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */ | 821 | #define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */ |
822 | #define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */ | 822 | #define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */ |
823 | #define AR5K_RESET_CTL_CHIP (AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA | \ | ||
824 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY) | ||
825 | 823 | ||
826 | /* | 824 | /* |
827 | * Sleep control register | 825 | * Sleep control register |
diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c index f5c3de890cdb..953ba3b19ff7 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath5k/reset.c | |||
@@ -173,8 +173,10 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | |||
173 | udelay(15); | 173 | udelay(15); |
174 | 174 | ||
175 | if (ah->ah_version == AR5K_AR5210) { | 175 | if (ah->ah_version == AR5K_AR5210) { |
176 | val &= AR5K_RESET_CTL_CHIP; | 176 | val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA |
177 | mask &= AR5K_RESET_CTL_CHIP; | 177 | | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; |
178 | mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA | ||
179 | | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; | ||
178 | } else { | 180 | } else { |
179 | val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; | 181 | val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; |
180 | mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; | 182 | mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; |
@@ -361,16 +363,20 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
361 | bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; | 363 | bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; |
362 | 364 | ||
363 | /* Reset chipset */ | 365 | /* Reset chipset */ |
364 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | 366 | if (ah->ah_version == AR5K_AR5210) { |
365 | AR5K_RESET_CTL_BASEBAND | bus_flags); | 367 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | |
368 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | | ||
369 | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); | ||
370 | mdelay(2); | ||
371 | } else { | ||
372 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | ||
373 | AR5K_RESET_CTL_BASEBAND | bus_flags); | ||
374 | } | ||
366 | if (ret) { | 375 | if (ret) { |
367 | ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); | 376 | ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); |
368 | return -EIO; | 377 | return -EIO; |
369 | } | 378 | } |
370 | 379 | ||
371 | if (ah->ah_version == AR5K_AR5210) | ||
372 | udelay(2300); | ||
373 | |||
374 | /* ...wakeup again!*/ | 380 | /* ...wakeup again!*/ |
375 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 381 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); |
376 | if (ret) { | 382 | if (ret) { |
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index c43fd5861163..eedb465d25d3 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c | |||
@@ -16,7 +16,6 @@ | |||
16 | 16 | ||
17 | /* Implementation of beacon processing. */ | 17 | /* Implementation of beacon processing. */ |
18 | 18 | ||
19 | #include <asm/unaligned.h> | ||
20 | #include "core.h" | 19 | #include "core.h" |
21 | 20 | ||
22 | /* | 21 | /* |
@@ -26,7 +25,6 @@ | |||
26 | * the operating mode of the station (AP or AdHoc). Parameters are AIFS | 25 | * the operating mode of the station (AP or AdHoc). Parameters are AIFS |
27 | * settings and channel width min/max | 26 | * settings and channel width min/max |
28 | */ | 27 | */ |
29 | |||
30 | static int ath_beaconq_config(struct ath_softc *sc) | 28 | static int ath_beaconq_config(struct ath_softc *sc) |
31 | { | 29 | { |
32 | struct ath_hal *ah = sc->sc_ah; | 30 | struct ath_hal *ah = sc->sc_ah; |
@@ -63,19 +61,18 @@ static int ath_beaconq_config(struct ath_softc *sc) | |||
63 | * up all required antenna switch parameters, rate codes, and channel flags. | 61 | * up all required antenna switch parameters, rate codes, and channel flags. |
64 | * Beacons are always sent out at the lowest rate, and are not retried. | 62 | * Beacons are always sent out at the lowest rate, and are not retried. |
65 | */ | 63 | */ |
66 | |||
67 | static void ath_beacon_setup(struct ath_softc *sc, | 64 | static void ath_beacon_setup(struct ath_softc *sc, |
68 | struct ath_vap *avp, struct ath_buf *bf) | 65 | struct ath_vap *avp, struct ath_buf *bf) |
69 | { | 66 | { |
70 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; | 67 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; |
71 | struct ath_hal *ah = sc->sc_ah; | 68 | struct ath_hal *ah = sc->sc_ah; |
72 | struct ath_desc *ds; | 69 | struct ath_desc *ds; |
73 | int flags, antenna; | 70 | struct ath9k_11n_rate_series series[4]; |
74 | const struct ath9k_rate_table *rt; | 71 | const struct ath9k_rate_table *rt; |
72 | int flags, antenna; | ||
75 | u8 rix, rate; | 73 | u8 rix, rate; |
76 | int ctsrate = 0; | 74 | int ctsrate = 0; |
77 | int ctsduration = 0; | 75 | int ctsduration = 0; |
78 | struct ath9k_11n_rate_series series[4]; | ||
79 | 76 | ||
80 | DPRINTF(sc, ATH_DBG_BEACON, "%s: m %p len %u\n", | 77 | DPRINTF(sc, ATH_DBG_BEACON, "%s: m %p len %u\n", |
81 | __func__, skb, skb->len); | 78 | __func__, skb, skb->len); |
@@ -115,20 +112,21 @@ static void ath_beacon_setup(struct ath_softc *sc, | |||
115 | rate |= rt->info[rix].shortPreamble; | 112 | rate |= rt->info[rix].shortPreamble; |
116 | 113 | ||
117 | ath9k_hw_set11n_txdesc(ah, ds, | 114 | ath9k_hw_set11n_txdesc(ah, ds, |
118 | skb->len + FCS_LEN, /* frame length */ | 115 | skb->len + FCS_LEN, /* frame length */ |
119 | ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */ | 116 | ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */ |
120 | avp->av_btxctl.txpower, /* txpower XXX */ | 117 | avp->av_btxctl.txpower, /* txpower XXX */ |
121 | ATH9K_TXKEYIX_INVALID, /* no encryption */ | 118 | ATH9K_TXKEYIX_INVALID, /* no encryption */ |
122 | ATH9K_KEY_TYPE_CLEAR, /* no encryption */ | 119 | ATH9K_KEY_TYPE_CLEAR, /* no encryption */ |
123 | flags /* no ack, veol for beacons */ | 120 | flags /* no ack, |
121 | veol for beacons */ | ||
124 | ); | 122 | ); |
125 | 123 | ||
126 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ | 124 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ |
127 | ath9k_hw_filltxdesc(ah, ds, | 125 | ath9k_hw_filltxdesc(ah, ds, |
128 | roundup(skb->len, 4), /* buffer length */ | 126 | roundup(skb->len, 4), /* buffer length */ |
129 | true, /* first segment */ | 127 | true, /* first segment */ |
130 | true, /* last segment */ | 128 | true, /* last segment */ |
131 | ds /* first descriptor */ | 129 | ds /* first descriptor */ |
132 | ); | 130 | ); |
133 | 131 | ||
134 | memzero(series, sizeof(struct ath9k_11n_rate_series) * 4); | 132 | memzero(series, sizeof(struct ath9k_11n_rate_series) * 4); |
@@ -153,22 +151,23 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | |||
153 | struct ath_buf *bf; | 151 | struct ath_buf *bf; |
154 | struct ath_vap *avp; | 152 | struct ath_vap *avp; |
155 | struct sk_buff *skb; | 153 | struct sk_buff *skb; |
156 | int cabq_depth; | ||
157 | struct ath_txq *cabq; | 154 | struct ath_txq *cabq; |
158 | struct ieee80211_tx_info *info; | 155 | struct ieee80211_tx_info *info; |
156 | int cabq_depth; | ||
157 | |||
159 | avp = sc->sc_vaps[if_id]; | 158 | avp = sc->sc_vaps[if_id]; |
159 | ASSERT(avp); | ||
160 | 160 | ||
161 | cabq = sc->sc_cabq; | 161 | cabq = sc->sc_cabq; |
162 | 162 | ||
163 | ASSERT(avp); | ||
164 | |||
165 | if (avp->av_bcbuf == NULL) { | 163 | if (avp->av_bcbuf == NULL) { |
166 | DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n", | 164 | DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n", |
167 | __func__, avp, avp->av_bcbuf); | 165 | __func__, avp, avp->av_bcbuf); |
168 | return NULL; | 166 | return NULL; |
169 | } | 167 | } |
168 | |||
170 | bf = avp->av_bcbuf; | 169 | bf = avp->av_bcbuf; |
171 | skb = (struct sk_buff *) bf->bf_mpdu; | 170 | skb = (struct sk_buff *)bf->bf_mpdu; |
172 | if (skb) { | 171 | if (skb) { |
173 | pci_unmap_single(sc->pdev, bf->bf_dmacontext, | 172 | pci_unmap_single(sc->pdev, bf->bf_dmacontext, |
174 | skb_end_pointer(skb) - skb->head, | 173 | skb_end_pointer(skb) - skb->head, |
@@ -179,17 +178,19 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | |||
179 | bf->bf_mpdu = skb; | 178 | bf->bf_mpdu = skb; |
180 | if (skb == NULL) | 179 | if (skb == NULL) |
181 | return NULL; | 180 | return NULL; |
181 | |||
182 | info = IEEE80211_SKB_CB(skb); | 182 | info = IEEE80211_SKB_CB(skb); |
183 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 183 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
184 | /* | 184 | /* |
185 | * TODO: make sure the seq# gets assigned properly (vs. other | 185 | * TODO: make sure the seq# gets assigned properly (vs. other |
186 | * TX frames) | 186 | * TX frames) |
187 | */ | 187 | */ |
188 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 188 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
189 | sc->seq_no += 0x10; | 189 | sc->seq_no += 0x10; |
190 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | 190 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); |
191 | hdr->seq_ctrl |= cpu_to_le16(sc->seq_no); | 191 | hdr->seq_ctrl |= cpu_to_le16(sc->seq_no); |
192 | } | 192 | } |
193 | |||
193 | bf->bf_buf_addr = bf->bf_dmacontext = | 194 | bf->bf_buf_addr = bf->bf_dmacontext = |
194 | pci_map_single(sc->pdev, skb->data, | 195 | pci_map_single(sc->pdev, skb->data, |
195 | skb_end_pointer(skb) - skb->head, | 196 | skb_end_pointer(skb) - skb->head, |
@@ -241,7 +242,6 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | |||
241 | * Startup beacon transmission for adhoc mode when they are sent entirely | 242 | * Startup beacon transmission for adhoc mode when they are sent entirely |
242 | * by the hardware using the self-linked descriptor + veol trick. | 243 | * by the hardware using the self-linked descriptor + veol trick. |
243 | */ | 244 | */ |
244 | |||
245 | static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id) | 245 | static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id) |
246 | { | 246 | { |
247 | struct ath_hal *ah = sc->sc_ah; | 247 | struct ath_hal *ah = sc->sc_ah; |
@@ -278,7 +278,6 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id) | |||
278 | * min/max, and enable aifs). The info structure does not need to be | 278 | * min/max, and enable aifs). The info structure does not need to be |
279 | * persistant. | 279 | * persistant. |
280 | */ | 280 | */ |
281 | |||
282 | int ath_beaconq_setup(struct ath_hal *ah) | 281 | int ath_beaconq_setup(struct ath_hal *ah) |
283 | { | 282 | { |
284 | struct ath9k_tx_queue_info qi; | 283 | struct ath9k_tx_queue_info qi; |
@@ -299,26 +298,24 @@ int ath_beaconq_setup(struct ath_hal *ah) | |||
299 | * the ATH interface. This routine also calculates the beacon "slot" for | 298 | * the ATH interface. This routine also calculates the beacon "slot" for |
300 | * staggared beacons in the mBSSID case. | 299 | * staggared beacons in the mBSSID case. |
301 | */ | 300 | */ |
302 | |||
303 | int ath_beacon_alloc(struct ath_softc *sc, int if_id) | 301 | int ath_beacon_alloc(struct ath_softc *sc, int if_id) |
304 | { | 302 | { |
305 | struct ath_vap *avp; | 303 | struct ath_vap *avp; |
306 | struct ieee80211_hdr *wh; | 304 | struct ieee80211_hdr *hdr; |
307 | struct ath_buf *bf; | 305 | struct ath_buf *bf; |
308 | struct sk_buff *skb; | 306 | struct sk_buff *skb; |
307 | __le64 tstamp; | ||
309 | 308 | ||
310 | avp = sc->sc_vaps[if_id]; | 309 | avp = sc->sc_vaps[if_id]; |
311 | ASSERT(avp); | 310 | ASSERT(avp); |
312 | 311 | ||
313 | /* Allocate a beacon descriptor if we haven't done so. */ | 312 | /* Allocate a beacon descriptor if we haven't done so. */ |
314 | if (!avp->av_bcbuf) { | 313 | if (!avp->av_bcbuf) { |
315 | /* | 314 | /* Allocate beacon state for hostap/ibss. We know |
316 | * Allocate beacon state for hostap/ibss. We know | 315 | * a buffer is available. */ |
317 | * a buffer is available. | ||
318 | */ | ||
319 | 316 | ||
320 | avp->av_bcbuf = list_first_entry(&sc->sc_bbuf, | 317 | avp->av_bcbuf = list_first_entry(&sc->sc_bbuf, |
321 | struct ath_buf, list); | 318 | struct ath_buf, list); |
322 | list_del(&avp->av_bcbuf->list); | 319 | list_del(&avp->av_bcbuf->list); |
323 | 320 | ||
324 | if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP || | 321 | if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP || |
@@ -362,9 +359,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) | |||
362 | } | 359 | } |
363 | 360 | ||
364 | /* | 361 | /* |
365 | * NB: the beacon data buffer must be 32-bit aligned; | 362 | * NB: the beacon data buffer must be 32-bit aligned. |
366 | * we assume the wbuf routines will return us something | ||
367 | * with this alignment (perhaps should assert). | ||
368 | * FIXME: Fill avp->av_btxctl.txpower and | 363 | * FIXME: Fill avp->av_btxctl.txpower and |
369 | * avp->av_btxctl.shortPreamble | 364 | * avp->av_btxctl.shortPreamble |
370 | */ | 365 | */ |
@@ -375,6 +370,9 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) | |||
375 | return -ENOMEM; | 370 | return -ENOMEM; |
376 | } | 371 | } |
377 | 372 | ||
373 | tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; | ||
374 | sc->bc_tstamp = le64_to_cpu(tstamp); | ||
375 | |||
378 | /* | 376 | /* |
379 | * Calculate a TSF adjustment factor required for | 377 | * Calculate a TSF adjustment factor required for |
380 | * staggered beacons. Note that we assume the format | 378 | * staggered beacons. Note that we assume the format |
@@ -408,8 +406,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) | |||
408 | __func__, "stagger", | 406 | __func__, "stagger", |
409 | avp->av_bslot, intval, (unsigned long long)tsfadjust); | 407 | avp->av_bslot, intval, (unsigned long long)tsfadjust); |
410 | 408 | ||
411 | wh = (struct ieee80211_hdr *)skb->data; | 409 | hdr = (struct ieee80211_hdr *)skb->data; |
412 | memcpy(&wh[1], &val, sizeof(val)); | 410 | memcpy(&hdr[1], &val, sizeof(val)); |
413 | } | 411 | } |
414 | 412 | ||
415 | bf->bf_buf_addr = bf->bf_dmacontext = | 413 | bf->bf_buf_addr = bf->bf_dmacontext = |
@@ -425,9 +423,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) | |||
425 | * Reclaim beacon resources and return buffer to the pool. | 423 | * Reclaim beacon resources and return buffer to the pool. |
426 | * | 424 | * |
427 | * Checks the VAP to put the beacon frame buffer back to the ATH object | 425 | * Checks the VAP to put the beacon frame buffer back to the ATH object |
428 | * queue, and de-allocates any wbuf frames that were sent as CAB traffic. | 426 | * queue, and de-allocates any skbs that were sent as CAB traffic. |
429 | */ | 427 | */ |
430 | |||
431 | void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) | 428 | void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) |
432 | { | 429 | { |
433 | if (avp->av_bcbuf != NULL) { | 430 | if (avp->av_bcbuf != NULL) { |
@@ -459,10 +456,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) | |||
459 | * Transmit one or more beacon frames at SWBA. Dynamic updates to the frame | 456 | * Transmit one or more beacon frames at SWBA. Dynamic updates to the frame |
460 | * contents are done as needed and the slot time is also adjusted based on | 457 | * contents are done as needed and the slot time is also adjusted based on |
461 | * current state. | 458 | * current state. |
462 | * | ||
463 | * This tasklet is not scheduled, it's called in ISR context. | ||
464 | */ | 459 | */ |
465 | |||
466 | void ath9k_beacon_tasklet(unsigned long data) | 460 | void ath9k_beacon_tasklet(unsigned long data) |
467 | { | 461 | { |
468 | struct ath_softc *sc = (struct ath_softc *)data; | 462 | struct ath_softc *sc = (struct ath_softc *)data; |
@@ -490,6 +484,8 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
490 | * and wait for the next. Missed beacons indicate | 484 | * and wait for the next. Missed beacons indicate |
491 | * a problem and should not occur. If we miss too | 485 | * a problem and should not occur. If we miss too |
492 | * many consecutive beacons reset the device. | 486 | * many consecutive beacons reset the device. |
487 | * | ||
488 | * FIXME: Clean up this mess !! | ||
493 | */ | 489 | */ |
494 | if (ath9k_hw_numtxpending(ah, sc->sc_bhalq) != 0) { | 490 | if (ath9k_hw_numtxpending(ah, sc->sc_bhalq) != 0) { |
495 | sc->sc_bmisscount++; | 491 | sc->sc_bmisscount++; |
@@ -505,19 +501,16 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
505 | __func__, sc->sc_bmisscount); | 501 | __func__, sc->sc_bmisscount); |
506 | if (show_cycles) { | 502 | if (show_cycles) { |
507 | /* | 503 | /* |
508 | * Display cycle counter stats | 504 | * Display cycle counter stats from HW |
509 | * from HW to aide in debug of | 505 | * to aide in debug of stickiness. |
510 | * stickiness. | ||
511 | */ | 506 | */ |
512 | DPRINTF(sc, | 507 | DPRINTF(sc, ATH_DBG_BEACON, |
513 | ATH_DBG_BEACON, | ||
514 | "%s: busy times: rx_clear=%d, " | 508 | "%s: busy times: rx_clear=%d, " |
515 | "rx_frame=%d, tx_frame=%d\n", | 509 | "rx_frame=%d, tx_frame=%d\n", |
516 | __func__, rx_clear, rx_frame, | 510 | __func__, rx_clear, rx_frame, |
517 | tx_frame); | 511 | tx_frame); |
518 | } else { | 512 | } else { |
519 | DPRINTF(sc, | 513 | DPRINTF(sc, ATH_DBG_BEACON, |
520 | ATH_DBG_BEACON, | ||
521 | "%s: unable to obtain " | 514 | "%s: unable to obtain " |
522 | "busy times\n", __func__); | 515 | "busy times\n", __func__); |
523 | } | 516 | } |
@@ -529,8 +522,7 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
529 | } else if (sc->sc_bmisscount >= BSTUCK_THRESH) { | 522 | } else if (sc->sc_bmisscount >= BSTUCK_THRESH) { |
530 | if (sc->sc_flags & SC_OP_NO_RESET) { | 523 | if (sc->sc_flags & SC_OP_NO_RESET) { |
531 | if (sc->sc_bmisscount == BSTUCK_THRESH) { | 524 | if (sc->sc_bmisscount == BSTUCK_THRESH) { |
532 | DPRINTF(sc, | 525 | DPRINTF(sc, ATH_DBG_BEACON, |
533 | ATH_DBG_BEACON, | ||
534 | "%s: beacon is officially " | 526 | "%s: beacon is officially " |
535 | "stuck\n", __func__); | 527 | "stuck\n", __func__); |
536 | ath9k_hw_dmaRegDump(ah); | 528 | ath9k_hw_dmaRegDump(ah); |
@@ -542,13 +534,12 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
542 | ath_bstuck_process(sc); | 534 | ath_bstuck_process(sc); |
543 | } | 535 | } |
544 | } | 536 | } |
545 | |||
546 | return; | 537 | return; |
547 | } | 538 | } |
539 | |||
548 | if (sc->sc_bmisscount != 0) { | 540 | if (sc->sc_bmisscount != 0) { |
549 | if (sc->sc_flags & SC_OP_NO_RESET) { | 541 | if (sc->sc_flags & SC_OP_NO_RESET) { |
550 | DPRINTF(sc, | 542 | DPRINTF(sc, ATH_DBG_BEACON, |
551 | ATH_DBG_BEACON, | ||
552 | "%s: resume beacon xmit after %u misses\n", | 543 | "%s: resume beacon xmit after %u misses\n", |
553 | __func__, sc->sc_bmisscount); | 544 | __func__, sc->sc_bmisscount); |
554 | } else { | 545 | } else { |
@@ -572,10 +563,12 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
572 | tsftu = TSF_TO_TU(tsf>>32, tsf); | 563 | tsftu = TSF_TO_TU(tsf>>32, tsf); |
573 | slot = ((tsftu % intval) * ATH_BCBUF) / intval; | 564 | slot = ((tsftu % intval) * ATH_BCBUF) / intval; |
574 | if_id = sc->sc_bslot[(slot + 1) % ATH_BCBUF]; | 565 | if_id = sc->sc_bslot[(slot + 1) % ATH_BCBUF]; |
566 | |||
575 | DPRINTF(sc, ATH_DBG_BEACON, | 567 | DPRINTF(sc, ATH_DBG_BEACON, |
576 | "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n", | 568 | "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n", |
577 | __func__, slot, (unsigned long long) tsf, tsftu, | 569 | __func__, slot, (unsigned long long)tsf, tsftu, |
578 | intval, if_id); | 570 | intval, if_id); |
571 | |||
579 | bfaddr = 0; | 572 | bfaddr = 0; |
580 | if (if_id != ATH_IF_ID_ANY) { | 573 | if (if_id != ATH_IF_ID_ANY) { |
581 | bf = ath_beacon_generate(sc, if_id); | 574 | bf = ath_beacon_generate(sc, if_id); |
@@ -632,9 +625,8 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
632 | * Tasklet for Beacon Stuck processing | 625 | * Tasklet for Beacon Stuck processing |
633 | * | 626 | * |
634 | * Processing for Beacon Stuck. | 627 | * Processing for Beacon Stuck. |
635 | * Basically calls the ath_internal_reset function to reset the chip. | 628 | * Basically resets the chip. |
636 | */ | 629 | */ |
637 | |||
638 | void ath_bstuck_process(struct ath_softc *sc) | 630 | void ath_bstuck_process(struct ath_softc *sc) |
639 | { | 631 | { |
640 | DPRINTF(sc, ATH_DBG_BEACON, | 632 | DPRINTF(sc, ATH_DBG_BEACON, |
@@ -658,13 +650,12 @@ void ath_bstuck_process(struct ath_softc *sc) | |||
658 | * interrupt when we stop seeing beacons from the AP | 650 | * interrupt when we stop seeing beacons from the AP |
659 | * we've associated with. | 651 | * we've associated with. |
660 | */ | 652 | */ |
661 | |||
662 | void ath_beacon_config(struct ath_softc *sc, int if_id) | 653 | void ath_beacon_config(struct ath_softc *sc, int if_id) |
663 | { | 654 | { |
664 | struct ath_hal *ah = sc->sc_ah; | 655 | struct ath_hal *ah = sc->sc_ah; |
665 | u32 nexttbtt, intval; | ||
666 | struct ath_beacon_config conf; | 656 | struct ath_beacon_config conf; |
667 | enum ath9k_opmode av_opmode; | 657 | enum ath9k_opmode av_opmode; |
658 | u32 nexttbtt, intval; | ||
668 | 659 | ||
669 | if (if_id != ATH_IF_ID_ANY) | 660 | if (if_id != ATH_IF_ID_ANY) |
670 | av_opmode = sc->sc_vaps[if_id]->av_opmode; | 661 | av_opmode = sc->sc_vaps[if_id]->av_opmode; |
@@ -673,12 +664,6 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
673 | 664 | ||
674 | memzero(&conf, sizeof(struct ath_beacon_config)); | 665 | memzero(&conf, sizeof(struct ath_beacon_config)); |
675 | 666 | ||
676 | /* FIXME: Use default values for now - Sujith */ | ||
677 | /* Query beacon configuration first */ | ||
678 | /* | ||
679 | * Protocol stack doesn't support dynamic beacon configuration, | ||
680 | * use default configurations. | ||
681 | */ | ||
682 | conf.beacon_interval = sc->hw->conf.beacon_int ? | 667 | conf.beacon_interval = sc->hw->conf.beacon_int ? |
683 | sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; | 668 | sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; |
684 | conf.listen_interval = 1; | 669 | conf.listen_interval = 1; |
@@ -687,8 +672,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
687 | conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval; | 672 | conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval; |
688 | 673 | ||
689 | /* extract tstamp from last beacon and convert to TU */ | 674 | /* extract tstamp from last beacon and convert to TU */ |
690 | nexttbtt = TSF_TO_TU(get_unaligned_le32(conf.u.last_tstamp + 4), | 675 | nexttbtt = TSF_TO_TU(sc->bc_tstamp >> 32, sc->bc_tstamp); |
691 | get_unaligned_le32(conf.u.last_tstamp)); | 676 | |
692 | /* XXX conditionalize multi-bss support? */ | 677 | /* XXX conditionalize multi-bss support? */ |
693 | if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) { | 678 | if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) { |
694 | /* | 679 | /* |
@@ -704,12 +689,14 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
704 | intval = conf.beacon_interval & ATH9K_BEACON_PERIOD; | 689 | intval = conf.beacon_interval & ATH9K_BEACON_PERIOD; |
705 | } | 690 | } |
706 | 691 | ||
707 | if (nexttbtt == 0) /* e.g. for ap mode */ | 692 | if (nexttbtt == 0) /* e.g. for ap mode */ |
708 | nexttbtt = intval; | 693 | nexttbtt = intval; |
709 | else if (intval) /* NB: can be 0 for monitor mode */ | 694 | else if (intval) /* NB: can be 0 for monitor mode */ |
710 | nexttbtt = roundup(nexttbtt, intval); | 695 | nexttbtt = roundup(nexttbtt, intval); |
696 | |||
711 | DPRINTF(sc, ATH_DBG_BEACON, "%s: nexttbtt %u intval %u (%u)\n", | 697 | DPRINTF(sc, ATH_DBG_BEACON, "%s: nexttbtt %u intval %u (%u)\n", |
712 | __func__, nexttbtt, intval, conf.beacon_interval); | 698 | __func__, nexttbtt, intval, conf.beacon_interval); |
699 | |||
713 | /* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */ | 700 | /* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */ |
714 | if (sc->sc_ah->ah_opmode == ATH9K_M_STA) { | 701 | if (sc->sc_ah->ah_opmode == ATH9K_M_STA) { |
715 | struct ath9k_beacon_state bs; | 702 | struct ath9k_beacon_state bs; |
@@ -723,19 +710,19 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
723 | * last beacon we received (which may be none). | 710 | * last beacon we received (which may be none). |
724 | */ | 711 | */ |
725 | dtimperiod = conf.dtim_period; | 712 | dtimperiod = conf.dtim_period; |
726 | if (dtimperiod <= 0) /* NB: 0 if not known */ | 713 | if (dtimperiod <= 0) /* NB: 0 if not known */ |
727 | dtimperiod = 1; | 714 | dtimperiod = 1; |
728 | dtimcount = conf.dtim_count; | 715 | dtimcount = conf.dtim_count; |
729 | if (dtimcount >= dtimperiod) /* NB: sanity check */ | 716 | if (dtimcount >= dtimperiod) /* NB: sanity check */ |
730 | dtimcount = 0; /* XXX? */ | 717 | dtimcount = 0; |
731 | cfpperiod = 1; /* NB: no PCF support yet */ | 718 | cfpperiod = 1; /* NB: no PCF support yet */ |
732 | cfpcount = 0; | 719 | cfpcount = 0; |
733 | 720 | ||
734 | sleepduration = conf.listen_interval * intval; | 721 | sleepduration = conf.listen_interval * intval; |
735 | if (sleepduration <= 0) | 722 | if (sleepduration <= 0) |
736 | sleepduration = intval; | 723 | sleepduration = intval; |
737 | 724 | ||
738 | #define FUDGE 2 | 725 | #define FUDGE 2 |
739 | /* | 726 | /* |
740 | * Pull nexttbtt forward to reflect the current | 727 | * Pull nexttbtt forward to reflect the current |
741 | * TSF and calculate dtim+cfp state for the result. | 728 | * TSF and calculate dtim+cfp state for the result. |
@@ -759,6 +746,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
759 | bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; | 746 | bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; |
760 | bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; | 747 | bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; |
761 | bs.bs_cfpmaxduration = 0; | 748 | bs.bs_cfpmaxduration = 0; |
749 | |||
762 | /* | 750 | /* |
763 | * Calculate the number of consecutive beacons to miss | 751 | * Calculate the number of consecutive beacons to miss |
764 | * before taking a BMISS interrupt. The configuration | 752 | * before taking a BMISS interrupt. The configuration |
@@ -767,9 +755,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
767 | * result to at most 15 beacons. | 755 | * result to at most 15 beacons. |
768 | */ | 756 | */ |
769 | if (sleepduration > intval) { | 757 | if (sleepduration > intval) { |
770 | bs.bs_bmissthreshold = | 758 | bs.bs_bmissthreshold = conf.listen_interval * |
771 | conf.listen_interval * | 759 | ATH_DEFAULT_BMISS_LIMIT / 2; |
772 | ATH_DEFAULT_BMISS_LIMIT / 2; | ||
773 | } else { | 760 | } else { |
774 | bs.bs_bmissthreshold = | 761 | bs.bs_bmissthreshold = |
775 | DIV_ROUND_UP(conf.bmiss_timeout, intval); | 762 | DIV_ROUND_UP(conf.bmiss_timeout, intval); |
@@ -789,8 +776,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
789 | * XXX fixed at 100ms | 776 | * XXX fixed at 100ms |
790 | */ | 777 | */ |
791 | 778 | ||
792 | bs.bs_sleepduration = | 779 | bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), |
793 | roundup(IEEE80211_MS_TO_TU(100), sleepduration); | 780 | sleepduration); |
794 | if (bs.bs_sleepduration > bs.bs_dtimperiod) | 781 | if (bs.bs_sleepduration > bs.bs_dtimperiod) |
795 | bs.bs_sleepduration = bs.bs_dtimperiod; | 782 | bs.bs_sleepduration = bs.bs_dtimperiod; |
796 | 783 | ||
@@ -834,9 +821,9 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
834 | if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS) { | 821 | if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS) { |
835 | /* | 822 | /* |
836 | * Pull nexttbtt forward to reflect the current | 823 | * Pull nexttbtt forward to reflect the current |
837 | * TSF . | 824 | * TSF |
838 | */ | 825 | */ |
839 | #define FUDGE 2 | 826 | #define FUDGE 2 |
840 | if (!(intval & ATH9K_BEACON_RESET_TSF)) { | 827 | if (!(intval & ATH9K_BEACON_RESET_TSF)) { |
841 | tsf = ath9k_hw_gettsf64(ah); | 828 | tsf = ath9k_hw_gettsf64(ah); |
842 | tsftu = TSF_TO_TU((u32)(tsf>>32), | 829 | tsftu = TSF_TO_TU((u32)(tsf>>32), |
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c index c262ef279ff3..690f7c56af3d 100644 --- a/drivers/net/wireless/ath9k/core.c +++ b/drivers/net/wireless/ath9k/core.c | |||
@@ -534,7 +534,8 @@ int ath_vap_attach(struct ath_softc *sc, | |||
534 | avp->av_opmode = opmode; | 534 | avp->av_opmode = opmode; |
535 | avp->av_bslot = -1; | 535 | avp->av_bslot = -1; |
536 | 536 | ||
537 | ath9k_hw_set_tsfadjust(sc->sc_ah, 1); | 537 | if (opmode == ATH9K_M_HOSTAP) |
538 | ath9k_hw_set_tsfadjust(sc->sc_ah, 1); | ||
538 | 539 | ||
539 | sc->sc_vaps[if_id] = avp; | 540 | sc->sc_vaps[if_id] = avp; |
540 | sc->sc_nvaps++; | 541 | sc->sc_nvaps++; |
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index b66de29cf662..6ff3befe39f7 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h | |||
@@ -1001,6 +1001,7 @@ struct ath_softc { | |||
1001 | u32 sc_bhalq; | 1001 | u32 sc_bhalq; |
1002 | u32 sc_bmisscount; | 1002 | u32 sc_bmisscount; |
1003 | u32 ast_be_xmit; /* beacons transmitted */ | 1003 | u32 ast_be_xmit; /* beacons transmitted */ |
1004 | u64 bc_tstamp; | ||
1004 | 1005 | ||
1005 | /* Rate */ | 1006 | /* Rate */ |
1006 | struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; | 1007 | struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; |
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 0251e59f2f84..272c75816609 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c | |||
@@ -2526,6 +2526,11 @@ static void ath9k_ani_reset(struct ath_hal *ah) | |||
2526 | } | 2526 | } |
2527 | } | 2527 | } |
2528 | 2528 | ||
2529 | /* | ||
2530 | * Process a MIB interrupt. We may potentially be invoked because | ||
2531 | * any of the MIB counters overflow/trigger so don't assume we're | ||
2532 | * here because a PHY error counter triggered. | ||
2533 | */ | ||
2529 | void ath9k_hw_procmibevent(struct ath_hal *ah, | 2534 | void ath9k_hw_procmibevent(struct ath_hal *ah, |
2530 | const struct ath9k_node_stats *stats) | 2535 | const struct ath9k_node_stats *stats) |
2531 | { | 2536 | { |
@@ -2533,18 +2538,20 @@ void ath9k_hw_procmibevent(struct ath_hal *ah, | |||
2533 | u32 phyCnt1, phyCnt2; | 2538 | u32 phyCnt1, phyCnt2; |
2534 | 2539 | ||
2535 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Processing Mib Intr\n"); | 2540 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Processing Mib Intr\n"); |
2536 | 2541 | /* Reset these counters regardless */ | |
2537 | REG_WRITE(ah, AR_FILT_OFDM, 0); | 2542 | REG_WRITE(ah, AR_FILT_OFDM, 0); |
2538 | REG_WRITE(ah, AR_FILT_CCK, 0); | 2543 | REG_WRITE(ah, AR_FILT_CCK, 0); |
2539 | if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) | 2544 | if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) |
2540 | REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); | 2545 | REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); |
2541 | 2546 | ||
2547 | /* Clear the mib counters and save them in the stats */ | ||
2542 | ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats); | 2548 | ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats); |
2543 | ahp->ah_stats.ast_nodestats = *stats; | 2549 | ahp->ah_stats.ast_nodestats = *stats; |
2544 | 2550 | ||
2545 | if (!DO_ANI(ah)) | 2551 | if (!DO_ANI(ah)) |
2546 | return; | 2552 | return; |
2547 | 2553 | ||
2554 | /* NB: these are not reset-on-read */ | ||
2548 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | 2555 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); |
2549 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | 2556 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); |
2550 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || | 2557 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || |
@@ -2552,6 +2559,7 @@ void ath9k_hw_procmibevent(struct ath_hal *ah, | |||
2552 | struct ar5416AniState *aniState = ahp->ah_curani; | 2559 | struct ar5416AniState *aniState = ahp->ah_curani; |
2553 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | 2560 | u32 ofdmPhyErrCnt, cckPhyErrCnt; |
2554 | 2561 | ||
2562 | /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */ | ||
2555 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | 2563 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; |
2556 | ahp->ah_stats.ast_ani_ofdmerrs += | 2564 | ahp->ah_stats.ast_ani_ofdmerrs += |
2557 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | 2565 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; |
@@ -2562,11 +2570,17 @@ void ath9k_hw_procmibevent(struct ath_hal *ah, | |||
2562 | cckPhyErrCnt - aniState->cckPhyErrCount; | 2570 | cckPhyErrCnt - aniState->cckPhyErrCount; |
2563 | aniState->cckPhyErrCount = cckPhyErrCnt; | 2571 | aniState->cckPhyErrCount = cckPhyErrCnt; |
2564 | 2572 | ||
2573 | /* | ||
2574 | * NB: figure out which counter triggered. If both | ||
2575 | * trigger we'll only deal with one as the processing | ||
2576 | * clobbers the error counter so the trigger threshold | ||
2577 | * check will never be true. | ||
2578 | */ | ||
2565 | if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) | 2579 | if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) |
2566 | ath9k_hw_ani_ofdm_err_trigger(ah); | 2580 | ath9k_hw_ani_ofdm_err_trigger(ah); |
2567 | if (aniState->cckPhyErrCount > aniState->cckTrigHigh) | 2581 | if (aniState->cckPhyErrCount > aniState->cckTrigHigh) |
2568 | ath9k_hw_ani_cck_err_trigger(ah); | 2582 | ath9k_hw_ani_cck_err_trigger(ah); |
2569 | 2583 | /* NB: always restart to insure the h/w counters are reset */ | |
2570 | ath9k_ani_restart(ah); | 2584 | ath9k_ani_restart(ah); |
2571 | } | 2585 | } |
2572 | } | 2586 | } |
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 1cc9daf44550..cca2fc5b0765 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include "core.h" | 22 | #include "core.h" |
23 | /* FIXME: remove this include! */ | ||
23 | #include "../net/mac80211/rate.h" | 24 | #include "../net/mac80211/rate.h" |
24 | 25 | ||
25 | static u32 tx_triglevel_max; | 26 | static u32 tx_triglevel_max; |
@@ -1812,20 +1813,18 @@ static void ath_rc_sib_init(struct ath_rate_node *ath_rc_priv) | |||
1812 | } | 1813 | } |
1813 | 1814 | ||
1814 | 1815 | ||
1815 | static void ath_setup_rates(struct ieee80211_local *local, struct sta_info *sta) | 1816 | static void ath_setup_rates(struct ath_softc *sc, |
1817 | struct ieee80211_supported_band *sband, | ||
1818 | struct ieee80211_sta *sta, | ||
1819 | struct ath_rate_node *rc_priv) | ||
1816 | 1820 | ||
1817 | { | 1821 | { |
1818 | struct ieee80211_supported_band *sband; | ||
1819 | struct ieee80211_hw *hw = local_to_hw(local); | ||
1820 | struct ath_softc *sc = hw->priv; | ||
1821 | struct ath_rate_node *rc_priv = sta->rate_ctrl_priv; | ||
1822 | int i, j = 0; | 1822 | int i, j = 0; |
1823 | 1823 | ||
1824 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | 1824 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
1825 | 1825 | ||
1826 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
1827 | for (i = 0; i < sband->n_bitrates; i++) { | 1826 | for (i = 0; i < sband->n_bitrates; i++) { |
1828 | if (sta->sta.supp_rates[local->hw.conf.channel->band] & BIT(i)) { | 1827 | if (sta->supp_rates[sband->band] & BIT(i)) { |
1829 | rc_priv->neg_rates.rs_rates[j] | 1828 | rc_priv->neg_rates.rs_rates[j] |
1830 | = (sband->bitrates[i].bitrate * 2) / 10; | 1829 | = (sband->bitrates[i].bitrate * 2) / 10; |
1831 | j++; | 1830 | j++; |
@@ -1852,19 +1851,17 @@ void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv) | |||
1852 | } | 1851 | } |
1853 | 1852 | ||
1854 | /* Rate Control callbacks */ | 1853 | /* Rate Control callbacks */ |
1855 | static void ath_tx_status(void *priv, struct net_device *dev, | 1854 | static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, |
1855 | struct ieee80211_sta *sta, void *priv_sta, | ||
1856 | struct sk_buff *skb) | 1856 | struct sk_buff *skb) |
1857 | { | 1857 | { |
1858 | struct ath_softc *sc = priv; | 1858 | struct ath_softc *sc = priv; |
1859 | struct ath_tx_info_priv *tx_info_priv; | 1859 | struct ath_tx_info_priv *tx_info_priv; |
1860 | struct ath_node *an; | 1860 | struct ath_node *an; |
1861 | struct sta_info *sta; | ||
1862 | struct ieee80211_local *local; | ||
1863 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1861 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1864 | struct ieee80211_hdr *hdr; | 1862 | struct ieee80211_hdr *hdr; |
1865 | __le16 fc; | 1863 | __le16 fc; |
1866 | 1864 | ||
1867 | local = hw_to_local(sc->hw); | ||
1868 | hdr = (struct ieee80211_hdr *)skb->data; | 1865 | hdr = (struct ieee80211_hdr *)skb->data; |
1869 | fc = hdr->frame_control; | 1866 | fc = hdr->frame_control; |
1870 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; | 1867 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; |
@@ -1873,8 +1870,7 @@ static void ath_tx_status(void *priv, struct net_device *dev, | |||
1873 | an = ath_node_find(sc, hdr->addr1); | 1870 | an = ath_node_find(sc, hdr->addr1); |
1874 | spin_unlock_bh(&sc->node_lock); | 1871 | spin_unlock_bh(&sc->node_lock); |
1875 | 1872 | ||
1876 | sta = sta_info_get(local, hdr->addr1); | 1873 | if (!an || !priv_sta || !ieee80211_is_data(fc)) { |
1877 | if (!an || !sta || !ieee80211_is_data(fc)) { | ||
1878 | if (tx_info->driver_data[0] != NULL) { | 1874 | if (tx_info->driver_data[0] != NULL) { |
1879 | kfree(tx_info->driver_data[0]); | 1875 | kfree(tx_info->driver_data[0]); |
1880 | tx_info->driver_data[0] = NULL; | 1876 | tx_info->driver_data[0] = NULL; |
@@ -1882,24 +1878,22 @@ static void ath_tx_status(void *priv, struct net_device *dev, | |||
1882 | return; | 1878 | return; |
1883 | } | 1879 | } |
1884 | if (tx_info->driver_data[0] != NULL) { | 1880 | if (tx_info->driver_data[0] != NULL) { |
1885 | ath_rate_tx_complete(sc, an, sta->rate_ctrl_priv, tx_info_priv); | 1881 | ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv); |
1886 | kfree(tx_info->driver_data[0]); | 1882 | kfree(tx_info->driver_data[0]); |
1887 | tx_info->driver_data[0] = NULL; | 1883 | tx_info->driver_data[0] = NULL; |
1888 | } | 1884 | } |
1889 | } | 1885 | } |
1890 | 1886 | ||
1891 | static void ath_tx_aggr_resp(struct ath_softc *sc, | 1887 | static void ath_tx_aggr_resp(struct ath_softc *sc, |
1892 | struct sta_info *sta, | 1888 | struct ieee80211_supported_band *sband, |
1889 | struct ieee80211_sta *sta, | ||
1893 | struct ath_node *an, | 1890 | struct ath_node *an, |
1894 | u8 tidno) | 1891 | u8 tidno) |
1895 | { | 1892 | { |
1896 | struct ieee80211_hw *hw = sc->hw; | ||
1897 | struct ieee80211_local *local; | ||
1898 | struct ath_atx_tid *txtid; | 1893 | struct ath_atx_tid *txtid; |
1899 | struct ieee80211_supported_band *sband; | ||
1900 | u16 buffersize = 0; | 1894 | u16 buffersize = 0; |
1901 | int state; | 1895 | int state; |
1902 | DECLARE_MAC_BUF(mac); | 1896 | struct sta_info *si; |
1903 | 1897 | ||
1904 | if (!(sc->sc_flags & SC_OP_TXAGGR)) | 1898 | if (!(sc->sc_flags & SC_OP_TXAGGR)) |
1905 | return; | 1899 | return; |
@@ -1908,11 +1902,16 @@ static void ath_tx_aggr_resp(struct ath_softc *sc, | |||
1908 | if (!txtid->paused) | 1902 | if (!txtid->paused) |
1909 | return; | 1903 | return; |
1910 | 1904 | ||
1911 | local = hw_to_local(sc->hw); | 1905 | /* |
1912 | sband = hw->wiphy->bands[hw->conf.channel->band]; | 1906 | * XXX: This is entirely busted, we aren't supposed to |
1907 | * access the sta from here because it's internal | ||
1908 | * to mac80211, and looking at the state without | ||
1909 | * locking is wrong too. | ||
1910 | */ | ||
1911 | si = container_of(sta, struct sta_info, sta); | ||
1913 | buffersize = IEEE80211_MIN_AMPDU_BUF << | 1912 | buffersize = IEEE80211_MIN_AMPDU_BUF << |
1914 | sband->ht_info.ampdu_factor; /* FIXME */ | 1913 | sband->ht_info.ampdu_factor; /* FIXME */ |
1915 | state = sta->ampdu_mlme.tid_state_tx[tidno]; | 1914 | state = si->ampdu_mlme.tid_state_tx[tidno]; |
1916 | 1915 | ||
1917 | if (state & HT_ADDBA_RECEIVED_MSK) { | 1916 | if (state & HT_ADDBA_RECEIVED_MSK) { |
1918 | txtid->addba_exchangecomplete = 1; | 1917 | txtid->addba_exchangecomplete = 1; |
@@ -1928,18 +1927,15 @@ static void ath_tx_aggr_resp(struct ath_softc *sc, | |||
1928 | } | 1927 | } |
1929 | } | 1928 | } |
1930 | 1929 | ||
1931 | static void ath_get_rate(void *priv, struct net_device *dev, | 1930 | static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband, |
1932 | struct ieee80211_supported_band *sband, | 1931 | struct ieee80211_sta *sta, void *priv_sta, |
1933 | struct sk_buff *skb, | 1932 | struct sk_buff *skb, struct rate_selection *sel) |
1934 | struct rate_selection *sel) | ||
1935 | { | 1933 | { |
1936 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1934 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1937 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1935 | struct ath_softc *sc = priv; |
1938 | struct sta_info *sta; | ||
1939 | struct ath_softc *sc = (struct ath_softc *)priv; | ||
1940 | struct ieee80211_hw *hw = sc->hw; | 1936 | struct ieee80211_hw *hw = sc->hw; |
1941 | struct ath_tx_info_priv *tx_info_priv; | 1937 | struct ath_tx_info_priv *tx_info_priv; |
1942 | struct ath_rate_node *ath_rc_priv; | 1938 | struct ath_rate_node *ath_rc_priv = priv_sta; |
1943 | struct ath_node *an; | 1939 | struct ath_node *an; |
1944 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1940 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1945 | int is_probe = FALSE, chk, ret; | 1941 | int is_probe = FALSE, chk, ret; |
@@ -1955,8 +1951,7 @@ static void ath_get_rate(void *priv, struct net_device *dev, | |||
1955 | ASSERT(tx_info->driver_data[0] != NULL); | 1951 | ASSERT(tx_info->driver_data[0] != NULL); |
1956 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; | 1952 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; |
1957 | 1953 | ||
1958 | sta = sta_info_get(local, hdr->addr1); | 1954 | lowest_idx = rate_lowest_index(sband, sta); |
1959 | lowest_idx = rate_lowest_index(local, sband, sta); | ||
1960 | tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10; | 1955 | tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10; |
1961 | /* lowest rate for management and multicast/broadcast frames */ | 1956 | /* lowest rate for management and multicast/broadcast frames */ |
1962 | if (!ieee80211_is_data(fc) || | 1957 | if (!ieee80211_is_data(fc) || |
@@ -1965,8 +1960,6 @@ static void ath_get_rate(void *priv, struct net_device *dev, | |||
1965 | return; | 1960 | return; |
1966 | } | 1961 | } |
1967 | 1962 | ||
1968 | ath_rc_priv = sta->rate_ctrl_priv; | ||
1969 | |||
1970 | /* Find tx rate for unicast frames */ | 1963 | /* Find tx rate for unicast frames */ |
1971 | ath_rate_findrate(sc, ath_rc_priv, | 1964 | ath_rate_findrate(sc, ath_rc_priv, |
1972 | ATH_11N_TXMAXTRY, 4, | 1965 | ATH_11N_TXMAXTRY, 4, |
@@ -1975,8 +1968,7 @@ static void ath_get_rate(void *priv, struct net_device *dev, | |||
1975 | &is_probe, | 1968 | &is_probe, |
1976 | false); | 1969 | false); |
1977 | if (is_probe) | 1970 | if (is_probe) |
1978 | sel->probe_idx = ((struct ath_tx_ratectrl *) | 1971 | sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate; |
1979 | sta->rate_ctrl_priv)->probe_rate; | ||
1980 | 1972 | ||
1981 | /* Ratecontrol sometimes returns invalid rate index */ | 1973 | /* Ratecontrol sometimes returns invalid rate index */ |
1982 | if (tx_info_priv->rcs[0].rix != 0xff) | 1974 | if (tx_info_priv->rcs[0].rix != 0xff) |
@@ -2020,37 +2012,31 @@ static void ath_get_rate(void *priv, struct net_device *dev, | |||
2020 | __func__, | 2012 | __func__, |
2021 | print_mac(mac, hdr->addr1)); | 2013 | print_mac(mac, hdr->addr1)); |
2022 | } else if (chk == AGGR_EXCHANGE_PROGRESS) | 2014 | } else if (chk == AGGR_EXCHANGE_PROGRESS) |
2023 | ath_tx_aggr_resp(sc, sta, an, tid); | 2015 | ath_tx_aggr_resp(sc, sband, sta, an, tid); |
2024 | } | 2016 | } |
2025 | } | 2017 | } |
2026 | } | 2018 | } |
2027 | 2019 | ||
2028 | static void ath_rate_init(void *priv, void *priv_sta, | 2020 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, |
2029 | struct ieee80211_local *local, | 2021 | struct ieee80211_sta *sta, void *priv_sta) |
2030 | struct sta_info *sta) | ||
2031 | { | 2022 | { |
2032 | struct ieee80211_supported_band *sband; | 2023 | struct ath_softc *sc = priv; |
2033 | struct ieee80211_hw *hw = local_to_hw(local); | ||
2034 | struct ieee80211_conf *conf = &local->hw.conf; | ||
2035 | struct ath_softc *sc = hw->priv; | ||
2036 | struct ath_rate_node *ath_rc_priv = priv_sta; | 2024 | struct ath_rate_node *ath_rc_priv = priv_sta; |
2037 | int i, j = 0; | 2025 | int i, j = 0; |
2038 | 2026 | ||
2039 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | 2027 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
2040 | 2028 | ||
2041 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 2029 | ath_setup_rates(sc, sband, sta, ath_rc_priv); |
2042 | 2030 | if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) { | |
2043 | ath_setup_rates(local, sta); | ||
2044 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { | ||
2045 | for (i = 0; i < MCS_SET_SIZE; i++) { | 2031 | for (i = 0; i < MCS_SET_SIZE; i++) { |
2046 | if (conf->ht_conf.supp_mcs_set[i/8] & (1<<(i%8))) | 2032 | if (sc->hw->conf.ht_conf.supp_mcs_set[i/8] & (1<<(i%8))) |
2047 | ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; | 2033 | ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; |
2048 | if (j == ATH_RATE_MAX) | 2034 | if (j == ATH_RATE_MAX) |
2049 | break; | 2035 | break; |
2050 | } | 2036 | } |
2051 | ath_rc_priv->neg_ht_rates.rs_nrates = j; | 2037 | ath_rc_priv->neg_ht_rates.rs_nrates = j; |
2052 | } | 2038 | } |
2053 | ath_rc_node_update(hw, priv_sta); | 2039 | ath_rc_node_update(sc->hw, priv_sta); |
2054 | } | 2040 | } |
2055 | 2041 | ||
2056 | static void ath_rate_clear(void *priv) | 2042 | static void ath_rate_clear(void *priv) |
@@ -2058,13 +2044,12 @@ static void ath_rate_clear(void *priv) | |||
2058 | return; | 2044 | return; |
2059 | } | 2045 | } |
2060 | 2046 | ||
2061 | static void *ath_rate_alloc(struct ieee80211_local *local) | 2047 | static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
2062 | { | 2048 | { |
2063 | struct ieee80211_hw *hw = local_to_hw(local); | ||
2064 | struct ath_softc *sc = hw->priv; | 2049 | struct ath_softc *sc = hw->priv; |
2065 | 2050 | ||
2066 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | 2051 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
2067 | return local->hw.priv; | 2052 | return hw->priv; |
2068 | } | 2053 | } |
2069 | 2054 | ||
2070 | static void ath_rate_free(void *priv) | 2055 | static void ath_rate_free(void *priv) |
@@ -2072,7 +2057,7 @@ static void ath_rate_free(void *priv) | |||
2072 | return; | 2057 | return; |
2073 | } | 2058 | } |
2074 | 2059 | ||
2075 | static void *ath_rate_alloc_sta(void *priv, gfp_t gfp) | 2060 | static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) |
2076 | { | 2061 | { |
2077 | struct ath_softc *sc = priv; | 2062 | struct ath_softc *sc = priv; |
2078 | struct ath_vap *avp = sc->sc_vaps[0]; | 2063 | struct ath_vap *avp = sc->sc_vaps[0]; |
@@ -2092,7 +2077,8 @@ static void *ath_rate_alloc_sta(void *priv, gfp_t gfp) | |||
2092 | return rate_priv; | 2077 | return rate_priv; |
2093 | } | 2078 | } |
2094 | 2079 | ||
2095 | static void ath_rate_free_sta(void *priv, void *priv_sta) | 2080 | static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, |
2081 | void *priv_sta) | ||
2096 | { | 2082 | { |
2097 | struct ath_rate_node *rate_priv = priv_sta; | 2083 | struct ath_rate_node *rate_priv = priv_sta; |
2098 | struct ath_softc *sc = priv; | 2084 | struct ath_softc *sc = priv; |
@@ -2111,7 +2097,7 @@ static struct rate_control_ops ath_rate_ops = { | |||
2111 | .alloc = ath_rate_alloc, | 2097 | .alloc = ath_rate_alloc, |
2112 | .free = ath_rate_free, | 2098 | .free = ath_rate_free, |
2113 | .alloc_sta = ath_rate_alloc_sta, | 2099 | .alloc_sta = ath_rate_alloc_sta, |
2114 | .free_sta = ath_rate_free_sta | 2100 | .free_sta = ath_rate_free_sta, |
2115 | }; | 2101 | }; |
2116 | 2102 | ||
2117 | int ath_rate_control_register(void) | 2103 | int ath_rate_control_register(void) |
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index bd65c485098c..ecb02bdaab5b 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c | |||
@@ -2258,7 +2258,7 @@ static int atmel_get_freq(struct net_device *dev, | |||
2258 | 2258 | ||
2259 | static int atmel_set_scan(struct net_device *dev, | 2259 | static int atmel_set_scan(struct net_device *dev, |
2260 | struct iw_request_info *info, | 2260 | struct iw_request_info *info, |
2261 | struct iw_param *vwrq, | 2261 | struct iw_point *dwrq, |
2262 | char *extra) | 2262 | char *extra) |
2263 | { | 2263 | { |
2264 | struct atmel_private *priv = netdev_priv(dev); | 2264 | struct atmel_private *priv = netdev_priv(dev); |
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 12617cd0b78e..d2388e8d179a 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c | |||
@@ -158,7 +158,7 @@ static int atmel_probe(struct pcmcia_device *p_dev) | |||
158 | DEBUG(0, "atmel_attach()\n"); | 158 | DEBUG(0, "atmel_attach()\n"); |
159 | 159 | ||
160 | /* Interrupt setup */ | 160 | /* Interrupt setup */ |
161 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 161 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; |
162 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; | 162 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
163 | p_dev->irq.Handler = NULL; | 163 | p_dev->irq.Handler = NULL; |
164 | 164 | ||
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 7b9e99adb8c3..96902da7d661 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c | |||
@@ -188,6 +188,11 @@ void b43_rfkill_init(struct b43_wldev *dev) | |||
188 | "The built-in radio LED will not work.\n"); | 188 | "The built-in radio LED will not work.\n"); |
189 | #endif /* CONFIG_RFKILL_INPUT */ | 189 | #endif /* CONFIG_RFKILL_INPUT */ |
190 | 190 | ||
191 | #if !defined(CONFIG_RFKILL_INPUT) && !defined(CONFIG_RFKILL_INPUT_MODULE) | ||
192 | b43warn(wl, "The rfkill-input subsystem is not available. " | ||
193 | "The built-in radio LED will not work.\n"); | ||
194 | #endif | ||
195 | |||
191 | err = input_register_polled_device(rfk->poll_dev); | 196 | err = input_register_polled_device(rfk->poll_dev); |
192 | if (err) | 197 | if (err) |
193 | goto err_unreg_rfk; | 198 | goto err_unreg_rfk; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index a279bf1dc9b0..6fc5e7361f26 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c | |||
@@ -36,8 +36,6 @@ | |||
36 | 36 | ||
37 | #include <linux/workqueue.h> | 37 | #include <linux/workqueue.h> |
38 | 38 | ||
39 | #include "../net/mac80211/rate.h" | ||
40 | |||
41 | #include "iwl-3945.h" | 39 | #include "iwl-3945.h" |
42 | 40 | ||
43 | #define RS_NAME "iwl-3945-rs" | 41 | #define RS_NAME "iwl-3945-rs" |
@@ -319,10 +317,10 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, | |||
319 | } | 317 | } |
320 | } | 318 | } |
321 | 319 | ||
322 | static void rs_rate_init(void *priv_rate, void *priv_sta, | 320 | static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband, |
323 | struct ieee80211_local *local, struct sta_info *sta) | 321 | struct ieee80211_sta *sta, void *priv_sta) |
324 | { | 322 | { |
325 | struct iwl3945_rs_sta *rs_sta = (void *)sta->rate_ctrl_priv; | 323 | struct iwl3945_rs_sta *rs_sta = priv_sta; |
326 | int i; | 324 | int i; |
327 | 325 | ||
328 | IWL_DEBUG_RATE("enter\n"); | 326 | IWL_DEBUG_RATE("enter\n"); |
@@ -333,22 +331,22 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, | |||
333 | * after assoc.. */ | 331 | * after assoc.. */ |
334 | 332 | ||
335 | for (i = IWL_RATE_COUNT - 1; i >= 0; i--) { | 333 | for (i = IWL_RATE_COUNT - 1; i >= 0; i--) { |
336 | if (sta->sta.supp_rates[local->hw.conf.channel->band] & (1 << i)) { | 334 | if (sta->supp_rates[sband->band] & (1 << i)) { |
337 | rs_sta->last_txrate_idx = i; | 335 | rs_sta->last_txrate_idx = i; |
338 | break; | 336 | break; |
339 | } | 337 | } |
340 | } | 338 | } |
341 | 339 | ||
342 | /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ | 340 | /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ |
343 | if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) | 341 | if (sband->band == IEEE80211_BAND_5GHZ) |
344 | rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; | 342 | rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; |
345 | 343 | ||
346 | IWL_DEBUG_RATE("leave\n"); | 344 | IWL_DEBUG_RATE("leave\n"); |
347 | } | 345 | } |
348 | 346 | ||
349 | static void *rs_alloc(struct ieee80211_local *local) | 347 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
350 | { | 348 | { |
351 | return local->hw.priv; | 349 | return hw->priv; |
352 | } | 350 | } |
353 | 351 | ||
354 | /* rate scale requires free function to be implemented */ | 352 | /* rate scale requires free function to be implemented */ |
@@ -356,17 +354,24 @@ static void rs_free(void *priv) | |||
356 | { | 354 | { |
357 | return; | 355 | return; |
358 | } | 356 | } |
357 | |||
359 | static void rs_clear(void *priv) | 358 | static void rs_clear(void *priv) |
360 | { | 359 | { |
361 | return; | 360 | return; |
362 | } | 361 | } |
363 | 362 | ||
364 | 363 | ||
365 | static void *rs_alloc_sta(void *priv, gfp_t gfp) | 364 | static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) |
366 | { | 365 | { |
367 | struct iwl3945_rs_sta *rs_sta; | 366 | struct iwl3945_rs_sta *rs_sta; |
367 | struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; | ||
368 | int i; | 368 | int i; |
369 | 369 | ||
370 | /* | ||
371 | * XXX: If it's using sta->drv_priv anyway, it might | ||
372 | * as well just put all the information there. | ||
373 | */ | ||
374 | |||
370 | IWL_DEBUG_RATE("enter\n"); | 375 | IWL_DEBUG_RATE("enter\n"); |
371 | 376 | ||
372 | rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp); | 377 | rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp); |
@@ -375,6 +380,8 @@ static void *rs_alloc_sta(void *priv, gfp_t gfp) | |||
375 | return NULL; | 380 | return NULL; |
376 | } | 381 | } |
377 | 382 | ||
383 | psta->rs_sta = rs_sta; | ||
384 | |||
378 | spin_lock_init(&rs_sta->lock); | 385 | spin_lock_init(&rs_sta->lock); |
379 | 386 | ||
380 | rs_sta->start_rate = IWL_RATE_INVALID; | 387 | rs_sta->start_rate = IWL_RATE_INVALID; |
@@ -400,10 +407,14 @@ static void *rs_alloc_sta(void *priv, gfp_t gfp) | |||
400 | return rs_sta; | 407 | return rs_sta; |
401 | } | 408 | } |
402 | 409 | ||
403 | static void rs_free_sta(void *priv, void *priv_sta) | 410 | static void rs_free_sta(void *priv, struct ieee80211_sta *sta, |
411 | void *priv_sta) | ||
404 | { | 412 | { |
413 | struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; | ||
405 | struct iwl3945_rs_sta *rs_sta = priv_sta; | 414 | struct iwl3945_rs_sta *rs_sta = priv_sta; |
406 | 415 | ||
416 | psta->rs_sta = NULL; | ||
417 | |||
407 | IWL_DEBUG_RATE("enter\n"); | 418 | IWL_DEBUG_RATE("enter\n"); |
408 | del_timer_sync(&rs_sta->rate_scale_flush); | 419 | del_timer_sync(&rs_sta->rate_scale_flush); |
409 | kfree(rs_sta); | 420 | kfree(rs_sta); |
@@ -445,26 +456,19 @@ static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate) | |||
445 | * NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by | 456 | * NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by |
446 | * the hardware for each rate. | 457 | * the hardware for each rate. |
447 | */ | 458 | */ |
448 | static void rs_tx_status(void *priv_rate, | 459 | static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband, |
449 | struct net_device *dev, | 460 | struct ieee80211_sta *sta, void *priv_sta, |
450 | struct sk_buff *skb) | 461 | struct sk_buff *skb) |
451 | { | 462 | { |
452 | u8 retries, current_count; | 463 | u8 retries, current_count; |
453 | int scale_rate_index, first_index, last_index; | 464 | int scale_rate_index, first_index, last_index; |
454 | unsigned long flags; | 465 | unsigned long flags; |
455 | struct sta_info *sta; | ||
456 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
457 | struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; | 466 | struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; |
458 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 467 | struct iwl3945_rs_sta *rs_sta = priv_sta; |
459 | struct iwl3945_rs_sta *rs_sta; | ||
460 | struct ieee80211_supported_band *sband; | ||
461 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 468 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
462 | 469 | ||
463 | IWL_DEBUG_RATE("enter\n"); | 470 | IWL_DEBUG_RATE("enter\n"); |
464 | 471 | ||
465 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
466 | |||
467 | |||
468 | retries = info->status.retry_count; | 472 | retries = info->status.retry_count; |
469 | first_index = sband->bitrates[info->tx_rate_idx].hw_value; | 473 | first_index = sband->bitrates[info->tx_rate_idx].hw_value; |
470 | if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { | 474 | if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { |
@@ -472,17 +476,11 @@ static void rs_tx_status(void *priv_rate, | |||
472 | return; | 476 | return; |
473 | } | 477 | } |
474 | 478 | ||
475 | rcu_read_lock(); | 479 | if (!priv_sta) { |
476 | |||
477 | sta = sta_info_get(local, hdr->addr1); | ||
478 | if (!sta || !sta->rate_ctrl_priv) { | ||
479 | rcu_read_unlock(); | ||
480 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); | 480 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); |
481 | return; | 481 | return; |
482 | } | 482 | } |
483 | 483 | ||
484 | rs_sta = (void *)sta->rate_ctrl_priv; | ||
485 | |||
486 | rs_sta->tx_packets++; | 484 | rs_sta->tx_packets++; |
487 | 485 | ||
488 | scale_rate_index = first_index; | 486 | scale_rate_index = first_index; |
@@ -549,8 +547,6 @@ static void rs_tx_status(void *priv_rate, | |||
549 | 547 | ||
550 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 548 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
551 | 549 | ||
552 | rcu_read_unlock(); | ||
553 | |||
554 | IWL_DEBUG_RATE("leave\n"); | 550 | IWL_DEBUG_RATE("leave\n"); |
555 | 551 | ||
556 | return; | 552 | return; |
@@ -634,16 +630,15 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, | |||
634 | * rate table and must reference the driver allocated rate table | 630 | * rate table and must reference the driver allocated rate table |
635 | * | 631 | * |
636 | */ | 632 | */ |
637 | static void rs_get_rate(void *priv_rate, struct net_device *dev, | 633 | static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, |
638 | struct ieee80211_supported_band *sband, | 634 | struct ieee80211_sta *sta, void *priv_sta, |
639 | struct sk_buff *skb, | 635 | struct sk_buff *skb, struct rate_selection *sel) |
640 | struct rate_selection *sel) | ||
641 | { | 636 | { |
642 | u8 low = IWL_RATE_INVALID; | 637 | u8 low = IWL_RATE_INVALID; |
643 | u8 high = IWL_RATE_INVALID; | 638 | u8 high = IWL_RATE_INVALID; |
644 | u16 high_low; | 639 | u16 high_low; |
645 | int index; | 640 | int index; |
646 | struct iwl3945_rs_sta *rs_sta; | 641 | struct iwl3945_rs_sta *rs_sta = priv_sta; |
647 | struct iwl3945_rate_scale_data *window = NULL; | 642 | struct iwl3945_rate_scale_data *window = NULL; |
648 | int current_tpt = IWL_INV_TPT; | 643 | int current_tpt = IWL_INV_TPT; |
649 | int low_tpt = IWL_INV_TPT; | 644 | int low_tpt = IWL_INV_TPT; |
@@ -651,34 +646,25 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
651 | u32 fail_count; | 646 | u32 fail_count; |
652 | s8 scale_action = 0; | 647 | s8 scale_action = 0; |
653 | unsigned long flags; | 648 | unsigned long flags; |
654 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
655 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 649 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
656 | struct sta_info *sta; | ||
657 | u16 fc, rate_mask; | 650 | u16 fc, rate_mask; |
658 | struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; | 651 | struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; |
659 | DECLARE_MAC_BUF(mac); | 652 | DECLARE_MAC_BUF(mac); |
660 | 653 | ||
661 | IWL_DEBUG_RATE("enter\n"); | 654 | IWL_DEBUG_RATE("enter\n"); |
662 | 655 | ||
663 | rcu_read_lock(); | ||
664 | |||
665 | sta = sta_info_get(local, hdr->addr1); | ||
666 | |||
667 | /* Send management frames and broadcast/multicast data using lowest | 656 | /* Send management frames and broadcast/multicast data using lowest |
668 | * rate. */ | 657 | * rate. */ |
669 | fc = le16_to_cpu(hdr->frame_control); | 658 | fc = le16_to_cpu(hdr->frame_control); |
670 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | 659 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || |
671 | is_multicast_ether_addr(hdr->addr1) || | 660 | is_multicast_ether_addr(hdr->addr1) || |
672 | !sta || !sta->rate_ctrl_priv) { | 661 | !sta || !priv_sta) { |
673 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); | 662 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); |
674 | sel->rate_idx = rate_lowest_index(local, sband, sta); | 663 | sel->rate_idx = rate_lowest_index(sband, sta); |
675 | rcu_read_unlock(); | ||
676 | return; | 664 | return; |
677 | } | 665 | } |
678 | 666 | ||
679 | rs_sta = (void *)sta->rate_ctrl_priv; | 667 | rate_mask = sta->supp_rates[sband->band]; |
680 | |||
681 | rate_mask = sta->sta.supp_rates[sband->band]; | ||
682 | index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); | 668 | index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); |
683 | 669 | ||
684 | if (sband->band == IEEE80211_BAND_5GHZ) | 670 | if (sband->band == IEEE80211_BAND_5GHZ) |
@@ -811,8 +797,6 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
811 | else | 797 | else |
812 | sel->rate_idx = rs_sta->last_txrate_idx; | 798 | sel->rate_idx = rs_sta->last_txrate_idx; |
813 | 799 | ||
814 | rcu_read_unlock(); | ||
815 | |||
816 | IWL_DEBUG_RATE("leave: %d\n", index); | 800 | IWL_DEBUG_RATE("leave: %d\n", index); |
817 | } | 801 | } |
818 | 802 | ||
@@ -829,114 +813,28 @@ static struct rate_control_ops rs_ops = { | |||
829 | .free_sta = rs_free_sta, | 813 | .free_sta = rs_free_sta, |
830 | }; | 814 | }; |
831 | 815 | ||
832 | int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) | ||
833 | { | ||
834 | struct ieee80211_local *local = hw_to_local(hw); | ||
835 | struct iwl3945_priv *priv = hw->priv; | ||
836 | struct iwl3945_rs_sta *rs_sta; | ||
837 | struct sta_info *sta; | ||
838 | unsigned long flags; | ||
839 | int count = 0, i; | ||
840 | u32 samples = 0, success = 0, good = 0; | ||
841 | unsigned long now = jiffies; | ||
842 | u32 max_time = 0; | ||
843 | |||
844 | rcu_read_lock(); | ||
845 | |||
846 | sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); | ||
847 | if (!sta || !sta->rate_ctrl_priv) { | ||
848 | if (sta) | ||
849 | IWL_DEBUG_RATE("leave - no private rate data!\n"); | ||
850 | else | ||
851 | IWL_DEBUG_RATE("leave - no station!\n"); | ||
852 | rcu_read_unlock(); | ||
853 | return sprintf(buf, "station %d not found\n", sta_id); | ||
854 | } | ||
855 | |||
856 | rs_sta = (void *)sta->rate_ctrl_priv; | ||
857 | spin_lock_irqsave(&rs_sta->lock, flags); | ||
858 | i = IWL_RATE_54M_INDEX; | ||
859 | while (1) { | ||
860 | u64 mask; | ||
861 | int j; | ||
862 | |||
863 | count += | ||
864 | sprintf(&buf[count], " %2dMbs: ", iwl3945_rates[i].ieee / 2); | ||
865 | |||
866 | mask = (1ULL << (IWL_RATE_MAX_WINDOW - 1)); | ||
867 | for (j = 0; j < IWL_RATE_MAX_WINDOW; j++, mask >>= 1) | ||
868 | buf[count++] = | ||
869 | (rs_sta->win[i].data & mask) ? '1' : '0'; | ||
870 | |||
871 | samples += rs_sta->win[i].counter; | ||
872 | good += rs_sta->win[i].success_counter; | ||
873 | success += rs_sta->win[i].success_counter * | ||
874 | iwl3945_rates[i].ieee; | ||
875 | |||
876 | if (rs_sta->win[i].stamp) { | ||
877 | int delta = | ||
878 | jiffies_to_msecs(now - rs_sta->win[i].stamp); | ||
879 | |||
880 | if (delta > max_time) | ||
881 | max_time = delta; | ||
882 | |||
883 | count += sprintf(&buf[count], "%5dms\n", delta); | ||
884 | } else | ||
885 | buf[count++] = '\n'; | ||
886 | |||
887 | j = iwl3945_get_prev_ieee_rate(i); | ||
888 | if (j == i) | ||
889 | break; | ||
890 | i = j; | ||
891 | } | ||
892 | spin_unlock_irqrestore(&rs_sta->lock, flags); | ||
893 | rcu_read_unlock(); | ||
894 | |||
895 | /* Display the average rate of all samples taken. | ||
896 | * | ||
897 | * NOTE: We multiple # of samples by 2 since the IEEE measurement | ||
898 | * added from iwl3945_rates is actually 2X the rate */ | ||
899 | if (samples) | ||
900 | count += sprintf( | ||
901 | &buf[count], | ||
902 | "\nAverage rate is %3d.%02dMbs over last %4dms\n" | ||
903 | "%3d%% success (%d good packets over %d tries)\n", | ||
904 | success / (2 * samples), (success * 5 / samples) % 10, | ||
905 | max_time, good * 100 / samples, good, samples); | ||
906 | else | ||
907 | count += sprintf(&buf[count], "\nAverage rate: 0Mbs\n"); | ||
908 | |||
909 | return count; | ||
910 | } | ||
911 | |||
912 | void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | 816 | void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) |
913 | { | 817 | { |
914 | struct iwl3945_priv *priv = hw->priv; | 818 | struct iwl3945_priv *priv = hw->priv; |
915 | s32 rssi = 0; | 819 | s32 rssi = 0; |
916 | unsigned long flags; | 820 | unsigned long flags; |
917 | struct ieee80211_local *local = hw_to_local(hw); | ||
918 | struct iwl3945_rs_sta *rs_sta; | 821 | struct iwl3945_rs_sta *rs_sta; |
919 | struct sta_info *sta; | 822 | struct ieee80211_sta *sta; |
823 | struct iwl3945_sta_priv *psta; | ||
920 | 824 | ||
921 | IWL_DEBUG_RATE("enter\n"); | 825 | IWL_DEBUG_RATE("enter\n"); |
922 | 826 | ||
923 | if (!local->rate_ctrl->ops->name || | ||
924 | strcmp(local->rate_ctrl->ops->name, RS_NAME)) { | ||
925 | IWL_WARNING("iwl-3945-rs not selected as rate control algo!\n"); | ||
926 | IWL_DEBUG_RATE("leave - mac80211 picked the wrong RC algo.\n"); | ||
927 | return; | ||
928 | } | ||
929 | |||
930 | rcu_read_lock(); | 827 | rcu_read_lock(); |
931 | 828 | ||
932 | sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); | 829 | sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr); |
933 | if (!sta || !sta->rate_ctrl_priv) { | 830 | psta = (void *) sta->drv_priv; |
831 | if (!sta || !psta) { | ||
934 | IWL_DEBUG_RATE("leave - no private rate data!\n"); | 832 | IWL_DEBUG_RATE("leave - no private rate data!\n"); |
935 | rcu_read_unlock(); | 833 | rcu_read_unlock(); |
936 | return; | 834 | return; |
937 | } | 835 | } |
938 | 836 | ||
939 | rs_sta = (void *)sta->rate_ctrl_priv; | 837 | rs_sta = psta->rs_sta; |
940 | 838 | ||
941 | spin_lock_irqsave(&rs_sta->lock, flags); | 839 | spin_lock_irqsave(&rs_sta->lock, flags); |
942 | 840 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h index f085d330bdcf..98b17ae6ef24 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h | |||
@@ -176,15 +176,6 @@ static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) | |||
176 | } | 176 | } |
177 | 177 | ||
178 | /** | 178 | /** |
179 | * iwl3945_fill_rs_info - Fill an output text buffer with the rate representation | ||
180 | * | ||
181 | * NOTE: This is provided as a quick mechanism for a user to visualize | ||
182 | * the performance of the rate control algorithm and is not meant to be | ||
183 | * parsed software. | ||
184 | */ | ||
185 | extern int iwl3945_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id); | ||
186 | |||
187 | /** | ||
188 | * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info | 179 | * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info |
189 | * | 180 | * |
190 | * The specific throughput table used is based on the type of network | 181 | * The specific throughput table used is based on the type of network |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 2a4933b5fb64..bdd32475b99c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -73,6 +73,10 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; | |||
73 | extern int iwl3945_param_hwcrypto; | 73 | extern int iwl3945_param_hwcrypto; |
74 | extern int iwl3945_param_queues_num; | 74 | extern int iwl3945_param_queues_num; |
75 | 75 | ||
76 | struct iwl3945_sta_priv { | ||
77 | struct iwl3945_rs_sta *rs_sta; | ||
78 | }; | ||
79 | |||
76 | enum iwl3945_antenna { | 80 | enum iwl3945_antenna { |
77 | IWL_ANTENNA_DIVERSITY, | 81 | IWL_ANTENNA_DIVERSITY, |
78 | IWL_ANTENNA_MAIN, | 82 | IWL_ANTENNA_MAIN, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 8b57b390c8ba..93944de923ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -35,8 +35,6 @@ | |||
35 | 35 | ||
36 | #include <linux/workqueue.h> | 36 | #include <linux/workqueue.h> |
37 | 37 | ||
38 | #include "../net/mac80211/rate.h" | ||
39 | |||
40 | #include "iwl-dev.h" | 38 | #include "iwl-dev.h" |
41 | #include "iwl-sta.h" | 39 | #include "iwl-sta.h" |
42 | #include "iwl-core.h" | 40 | #include "iwl-core.h" |
@@ -169,9 +167,9 @@ struct iwl_lq_sta { | |||
169 | }; | 167 | }; |
170 | 168 | ||
171 | static void rs_rate_scale_perform(struct iwl_priv *priv, | 169 | static void rs_rate_scale_perform(struct iwl_priv *priv, |
172 | struct net_device *dev, | ||
173 | struct ieee80211_hdr *hdr, | 170 | struct ieee80211_hdr *hdr, |
174 | struct sta_info *sta); | 171 | struct ieee80211_sta *sta, |
172 | struct iwl_lq_sta *lq_sta); | ||
175 | static void rs_fill_link_cmd(const struct iwl_priv *priv, | 173 | static void rs_fill_link_cmd(const struct iwl_priv *priv, |
176 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); | 174 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); |
177 | 175 | ||
@@ -357,20 +355,20 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) | |||
357 | 355 | ||
358 | static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | 356 | static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, |
359 | struct iwl_lq_sta *lq_data, u8 tid, | 357 | struct iwl_lq_sta *lq_data, u8 tid, |
360 | struct sta_info *sta) | 358 | struct ieee80211_sta *sta) |
361 | { | 359 | { |
362 | DECLARE_MAC_BUF(mac); | 360 | DECLARE_MAC_BUF(mac); |
363 | 361 | ||
364 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { | 362 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { |
365 | IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n", | 363 | IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n", |
366 | print_mac(mac, sta->sta.addr), tid); | 364 | print_mac(mac, sta->addr), tid); |
367 | ieee80211_start_tx_ba_session(priv->hw, sta->sta.addr, tid); | 365 | ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); |
368 | } | 366 | } |
369 | } | 367 | } |
370 | 368 | ||
371 | static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, | 369 | static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, |
372 | struct iwl_lq_sta *lq_data, | 370 | struct iwl_lq_sta *lq_data, |
373 | struct sta_info *sta) | 371 | struct ieee80211_sta *sta) |
374 | { | 372 | { |
375 | if ((tid < TID_MAX_LOAD_COUNT)) | 373 | if ((tid < TID_MAX_LOAD_COUNT)) |
376 | rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); | 374 | rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); |
@@ -770,7 +768,8 @@ out: | |||
770 | /* | 768 | /* |
771 | * mac80211 sends us Tx status | 769 | * mac80211 sends us Tx status |
772 | */ | 770 | */ |
773 | static void rs_tx_status(void *priv_rate, struct net_device *dev, | 771 | static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, |
772 | struct ieee80211_sta *sta, void *priv_sta, | ||
774 | struct sk_buff *skb) | 773 | struct sk_buff *skb) |
775 | { | 774 | { |
776 | int status; | 775 | int status; |
@@ -778,11 +777,9 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, | |||
778 | int rs_index, index = 0; | 777 | int rs_index, index = 0; |
779 | struct iwl_lq_sta *lq_sta; | 778 | struct iwl_lq_sta *lq_sta; |
780 | struct iwl_link_quality_cmd *table; | 779 | struct iwl_link_quality_cmd *table; |
781 | struct sta_info *sta; | ||
782 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 780 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
783 | struct iwl_priv *priv = (struct iwl_priv *)priv_rate; | 781 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
784 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 782 | struct ieee80211_hw *hw = priv->hw; |
785 | struct ieee80211_hw *hw = local_to_hw(local); | ||
786 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 783 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
787 | struct iwl_rate_scale_data *window = NULL; | 784 | struct iwl_rate_scale_data *window = NULL; |
788 | struct iwl_rate_scale_data *search_win = NULL; | 785 | struct iwl_rate_scale_data *search_win = NULL; |
@@ -808,15 +805,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, | |||
808 | if (retries > 15) | 805 | if (retries > 15) |
809 | retries = 15; | 806 | retries = 15; |
810 | 807 | ||
811 | rcu_read_lock(); | 808 | lq_sta = (struct iwl_lq_sta *)priv_sta; |
812 | |||
813 | sta = sta_info_get(local, hdr->addr1); | ||
814 | |||
815 | if (!sta || !sta->rate_ctrl_priv) | ||
816 | goto out; | ||
817 | |||
818 | |||
819 | lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; | ||
820 | 809 | ||
821 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | 810 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && |
822 | !lq_sta->ibss_sta_added) | 811 | !lq_sta->ibss_sta_added) |
@@ -962,9 +951,8 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, | |||
962 | } | 951 | } |
963 | 952 | ||
964 | /* See if there's a better rate or modulation mode to try. */ | 953 | /* See if there's a better rate or modulation mode to try. */ |
965 | rs_rate_scale_perform(priv, dev, hdr, sta); | 954 | rs_rate_scale_perform(priv, hdr, sta, lq_sta); |
966 | out: | 955 | out: |
967 | rcu_read_unlock(); | ||
968 | return; | 956 | return; |
969 | } | 957 | } |
970 | 958 | ||
@@ -1140,7 +1128,7 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, | |||
1140 | static int rs_switch_to_mimo2(struct iwl_priv *priv, | 1128 | static int rs_switch_to_mimo2(struct iwl_priv *priv, |
1141 | struct iwl_lq_sta *lq_sta, | 1129 | struct iwl_lq_sta *lq_sta, |
1142 | struct ieee80211_conf *conf, | 1130 | struct ieee80211_conf *conf, |
1143 | struct sta_info *sta, | 1131 | struct ieee80211_sta *sta, |
1144 | struct iwl_scale_tbl_info *tbl, int index) | 1132 | struct iwl_scale_tbl_info *tbl, int index) |
1145 | { | 1133 | { |
1146 | u16 rate_mask; | 1134 | u16 rate_mask; |
@@ -1148,10 +1136,10 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, | |||
1148 | s8 is_green = lq_sta->is_green; | 1136 | s8 is_green = lq_sta->is_green; |
1149 | 1137 | ||
1150 | if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || | 1138 | if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || |
1151 | !sta->sta.ht_info.ht_supported) | 1139 | !sta->ht_info.ht_supported) |
1152 | return -1; | 1140 | return -1; |
1153 | 1141 | ||
1154 | if (((sta->sta.ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2) | 1142 | if (((sta->ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2) |
1155 | == WLAN_HT_CAP_SM_PS_STATIC) | 1143 | == WLAN_HT_CAP_SM_PS_STATIC) |
1156 | return -1; | 1144 | return -1; |
1157 | 1145 | ||
@@ -1208,7 +1196,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, | |||
1208 | static int rs_switch_to_siso(struct iwl_priv *priv, | 1196 | static int rs_switch_to_siso(struct iwl_priv *priv, |
1209 | struct iwl_lq_sta *lq_sta, | 1197 | struct iwl_lq_sta *lq_sta, |
1210 | struct ieee80211_conf *conf, | 1198 | struct ieee80211_conf *conf, |
1211 | struct sta_info *sta, | 1199 | struct ieee80211_sta *sta, |
1212 | struct iwl_scale_tbl_info *tbl, int index) | 1200 | struct iwl_scale_tbl_info *tbl, int index) |
1213 | { | 1201 | { |
1214 | u16 rate_mask; | 1202 | u16 rate_mask; |
@@ -1216,7 +1204,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, | |||
1216 | s32 rate; | 1204 | s32 rate; |
1217 | 1205 | ||
1218 | if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || | 1206 | if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || |
1219 | !sta->sta.ht_info.ht_supported) | 1207 | !sta->ht_info.ht_supported) |
1220 | return -1; | 1208 | return -1; |
1221 | 1209 | ||
1222 | IWL_DEBUG_RATE("LQ: try to switch to SISO\n"); | 1210 | IWL_DEBUG_RATE("LQ: try to switch to SISO\n"); |
@@ -1268,7 +1256,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, | |||
1268 | static int rs_move_legacy_other(struct iwl_priv *priv, | 1256 | static int rs_move_legacy_other(struct iwl_priv *priv, |
1269 | struct iwl_lq_sta *lq_sta, | 1257 | struct iwl_lq_sta *lq_sta, |
1270 | struct ieee80211_conf *conf, | 1258 | struct ieee80211_conf *conf, |
1271 | struct sta_info *sta, | 1259 | struct ieee80211_sta *sta, |
1272 | int index) | 1260 | int index) |
1273 | { | 1261 | { |
1274 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1262 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
@@ -1376,7 +1364,7 @@ out: | |||
1376 | static int rs_move_siso_to_other(struct iwl_priv *priv, | 1364 | static int rs_move_siso_to_other(struct iwl_priv *priv, |
1377 | struct iwl_lq_sta *lq_sta, | 1365 | struct iwl_lq_sta *lq_sta, |
1378 | struct ieee80211_conf *conf, | 1366 | struct ieee80211_conf *conf, |
1379 | struct sta_info *sta, int index) | 1367 | struct ieee80211_sta *sta, int index) |
1380 | { | 1368 | { |
1381 | u8 is_green = lq_sta->is_green; | 1369 | u8 is_green = lq_sta->is_green; |
1382 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1370 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
@@ -1487,7 +1475,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1487 | static int rs_move_mimo_to_other(struct iwl_priv *priv, | 1475 | static int rs_move_mimo_to_other(struct iwl_priv *priv, |
1488 | struct iwl_lq_sta *lq_sta, | 1476 | struct iwl_lq_sta *lq_sta, |
1489 | struct ieee80211_conf *conf, | 1477 | struct ieee80211_conf *conf, |
1490 | struct sta_info *sta, int index) | 1478 | struct ieee80211_sta *sta, int index) |
1491 | { | 1479 | { |
1492 | s8 is_green = lq_sta->is_green; | 1480 | s8 is_green = lq_sta->is_green; |
1493 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1481 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
@@ -1680,12 +1668,11 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) | |||
1680 | * Do rate scaling and search for new modulation mode. | 1668 | * Do rate scaling and search for new modulation mode. |
1681 | */ | 1669 | */ |
1682 | static void rs_rate_scale_perform(struct iwl_priv *priv, | 1670 | static void rs_rate_scale_perform(struct iwl_priv *priv, |
1683 | struct net_device *dev, | ||
1684 | struct ieee80211_hdr *hdr, | 1671 | struct ieee80211_hdr *hdr, |
1685 | struct sta_info *sta) | 1672 | struct ieee80211_sta *sta, |
1673 | struct iwl_lq_sta *lq_sta) | ||
1686 | { | 1674 | { |
1687 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1675 | struct ieee80211_hw *hw = priv->hw; |
1688 | struct ieee80211_hw *hw = local_to_hw(local); | ||
1689 | struct ieee80211_conf *conf = &hw->conf; | 1676 | struct ieee80211_conf *conf = &hw->conf; |
1690 | int low = IWL_RATE_INVALID; | 1677 | int low = IWL_RATE_INVALID; |
1691 | int high = IWL_RATE_INVALID; | 1678 | int high = IWL_RATE_INVALID; |
@@ -1700,7 +1687,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
1700 | __le16 fc; | 1687 | __le16 fc; |
1701 | u16 rate_mask; | 1688 | u16 rate_mask; |
1702 | u8 update_lq = 0; | 1689 | u8 update_lq = 0; |
1703 | struct iwl_lq_sta *lq_sta; | ||
1704 | struct iwl_scale_tbl_info *tbl, *tbl1; | 1690 | struct iwl_scale_tbl_info *tbl, *tbl1; |
1705 | u16 rate_scale_index_msk = 0; | 1691 | u16 rate_scale_index_msk = 0; |
1706 | u32 rate; | 1692 | u32 rate; |
@@ -1721,11 +1707,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
1721 | return; | 1707 | return; |
1722 | } | 1708 | } |
1723 | 1709 | ||
1724 | if (!sta || !sta->rate_ctrl_priv) | 1710 | if (!sta || !lq_sta) |
1725 | return; | 1711 | return; |
1726 | 1712 | ||
1727 | lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; | 1713 | lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; |
1728 | lq_sta->supp_rates = sta->sta.supp_rates[lq_sta->band]; | ||
1729 | 1714 | ||
1730 | tid = rs_tl_add_packet(lq_sta, hdr); | 1715 | tid = rs_tl_add_packet(lq_sta, hdr); |
1731 | 1716 | ||
@@ -2064,9 +2049,9 @@ out: | |||
2064 | 2049 | ||
2065 | static void rs_initialize_lq(struct iwl_priv *priv, | 2050 | static void rs_initialize_lq(struct iwl_priv *priv, |
2066 | struct ieee80211_conf *conf, | 2051 | struct ieee80211_conf *conf, |
2067 | struct sta_info *sta) | 2052 | struct ieee80211_sta *sta, |
2053 | struct iwl_lq_sta *lq_sta) | ||
2068 | { | 2054 | { |
2069 | struct iwl_lq_sta *lq_sta; | ||
2070 | struct iwl_scale_tbl_info *tbl; | 2055 | struct iwl_scale_tbl_info *tbl; |
2071 | int rate_idx; | 2056 | int rate_idx; |
2072 | int i; | 2057 | int i; |
@@ -2075,10 +2060,9 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2075 | u8 active_tbl = 0; | 2060 | u8 active_tbl = 0; |
2076 | u8 valid_tx_ant; | 2061 | u8 valid_tx_ant; |
2077 | 2062 | ||
2078 | if (!sta || !sta->rate_ctrl_priv) | 2063 | if (!sta || !lq_sta) |
2079 | goto out; | 2064 | goto out; |
2080 | 2065 | ||
2081 | lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; | ||
2082 | i = lq_sta->last_txrate_idx; | 2066 | i = lq_sta->last_txrate_idx; |
2083 | 2067 | ||
2084 | if ((lq_sta->lq.sta_id == 0xff) && | 2068 | if ((lq_sta->lq.sta_id == 0xff) && |
@@ -2119,37 +2103,30 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2119 | return; | 2103 | return; |
2120 | } | 2104 | } |
2121 | 2105 | ||
2122 | static void rs_get_rate(void *priv_rate, struct net_device *dev, | 2106 | static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, |
2123 | struct ieee80211_supported_band *sband, | 2107 | struct ieee80211_sta *sta, void *priv_sta, |
2124 | struct sk_buff *skb, | 2108 | struct sk_buff *skb, struct rate_selection *sel) |
2125 | struct rate_selection *sel) | ||
2126 | { | 2109 | { |
2127 | 2110 | ||
2128 | int i; | 2111 | int i; |
2129 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2112 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
2130 | struct ieee80211_conf *conf = &local->hw.conf; | 2113 | struct ieee80211_conf *conf = &priv->hw->conf; |
2131 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 2114 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
2132 | struct sta_info *sta; | ||
2133 | __le16 fc; | 2115 | __le16 fc; |
2134 | struct iwl_priv *priv = (struct iwl_priv *)priv_rate; | ||
2135 | struct iwl_lq_sta *lq_sta; | 2116 | struct iwl_lq_sta *lq_sta; |
2136 | 2117 | ||
2137 | IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); | 2118 | IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); |
2138 | 2119 | ||
2139 | rcu_read_lock(); | ||
2140 | |||
2141 | sta = sta_info_get(local, hdr->addr1); | ||
2142 | |||
2143 | /* Send management frames and broadcast/multicast data using lowest | 2120 | /* Send management frames and broadcast/multicast data using lowest |
2144 | * rate. */ | 2121 | * rate. */ |
2145 | fc = hdr->frame_control; | 2122 | fc = hdr->frame_control; |
2146 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || | 2123 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || |
2147 | !sta || !sta->rate_ctrl_priv) { | 2124 | !sta || !priv_sta) { |
2148 | sel->rate_idx = rate_lowest_index(local, sband, sta); | 2125 | sel->rate_idx = rate_lowest_index(sband, sta); |
2149 | goto out; | 2126 | return; |
2150 | } | 2127 | } |
2151 | 2128 | ||
2152 | lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; | 2129 | lq_sta = (struct iwl_lq_sta *)priv_sta; |
2153 | i = lq_sta->last_txrate_idx; | 2130 | i = lq_sta->last_txrate_idx; |
2154 | 2131 | ||
2155 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | 2132 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && |
@@ -2167,23 +2144,22 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
2167 | lq_sta->lq.sta_id = sta_id; | 2144 | lq_sta->lq.sta_id = sta_id; |
2168 | lq_sta->lq.rs_table[0].rate_n_flags = 0; | 2145 | lq_sta->lq.rs_table[0].rate_n_flags = 0; |
2169 | lq_sta->ibss_sta_added = 1; | 2146 | lq_sta->ibss_sta_added = 1; |
2170 | rs_initialize_lq(priv, conf, sta); | 2147 | rs_initialize_lq(priv, conf, sta, lq_sta); |
2171 | } | 2148 | } |
2172 | } | 2149 | } |
2173 | 2150 | ||
2174 | if ((i < 0) || (i > IWL_RATE_COUNT)) { | 2151 | if ((i < 0) || (i > IWL_RATE_COUNT)) { |
2175 | sel->rate_idx = rate_lowest_index(local, sband, sta); | 2152 | sel->rate_idx = rate_lowest_index(sband, sta); |
2176 | goto out; | 2153 | return; |
2177 | } | 2154 | } |
2178 | 2155 | ||
2179 | if (sband->band == IEEE80211_BAND_5GHZ) | 2156 | if (sband->band == IEEE80211_BAND_5GHZ) |
2180 | i -= IWL_FIRST_OFDM_RATE; | 2157 | i -= IWL_FIRST_OFDM_RATE; |
2181 | sel->rate_idx = i; | 2158 | sel->rate_idx = i; |
2182 | out: | ||
2183 | rcu_read_unlock(); | ||
2184 | } | 2159 | } |
2185 | 2160 | ||
2186 | static void *rs_alloc_sta(void *priv_rate, gfp_t gfp) | 2161 | static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, |
2162 | gfp_t gfp) | ||
2187 | { | 2163 | { |
2188 | struct iwl_lq_sta *lq_sta; | 2164 | struct iwl_lq_sta *lq_sta; |
2189 | struct iwl_priv *priv; | 2165 | struct iwl_priv *priv; |
@@ -2206,20 +2182,16 @@ static void *rs_alloc_sta(void *priv_rate, gfp_t gfp) | |||
2206 | return lq_sta; | 2182 | return lq_sta; |
2207 | } | 2183 | } |
2208 | 2184 | ||
2209 | static void rs_rate_init(void *priv_rate, void *priv_sta, | 2185 | static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, |
2210 | struct ieee80211_local *local, | 2186 | struct ieee80211_sta *sta, void *priv_sta) |
2211 | struct sta_info *sta) | ||
2212 | { | 2187 | { |
2213 | int i, j; | 2188 | int i, j; |
2214 | struct ieee80211_conf *conf = &local->hw.conf; | 2189 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
2215 | struct ieee80211_supported_band *sband; | 2190 | struct ieee80211_conf *conf = &priv->hw->conf; |
2216 | struct iwl_priv *priv = (struct iwl_priv *)priv_rate; | ||
2217 | struct iwl_lq_sta *lq_sta = priv_sta; | 2191 | struct iwl_lq_sta *lq_sta = priv_sta; |
2218 | 2192 | ||
2219 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
2220 | |||
2221 | lq_sta->flush_timer = 0; | 2193 | lq_sta->flush_timer = 0; |
2222 | lq_sta->supp_rates = sta->sta.supp_rates[sband->band]; | 2194 | lq_sta->supp_rates = sta->supp_rates[sband->band]; |
2223 | for (j = 0; j < LQ_SIZE; j++) | 2195 | for (j = 0; j < LQ_SIZE; j++) |
2224 | for (i = 0; i < IWL_RATE_COUNT; i++) | 2196 | for (i = 0; i < IWL_RATE_COUNT; i++) |
2225 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | 2197 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); |
@@ -2232,17 +2204,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, | |||
2232 | 2204 | ||
2233 | lq_sta->ibss_sta_added = 0; | 2205 | lq_sta->ibss_sta_added = 0; |
2234 | if (priv->iw_mode == NL80211_IFTYPE_AP) { | 2206 | if (priv->iw_mode == NL80211_IFTYPE_AP) { |
2235 | u8 sta_id = iwl_find_station(priv, sta->sta.addr); | 2207 | u8 sta_id = iwl_find_station(priv, sta->addr); |
2236 | DECLARE_MAC_BUF(mac); | 2208 | DECLARE_MAC_BUF(mac); |
2237 | 2209 | ||
2238 | /* for IBSS the call are from tasklet */ | 2210 | /* for IBSS the call are from tasklet */ |
2239 | IWL_DEBUG_RATE("LQ: ADD station %s\n", | 2211 | IWL_DEBUG_RATE("LQ: ADD station %s\n", |
2240 | print_mac(mac, sta->sta.addr)); | 2212 | print_mac(mac, sta->addr)); |
2241 | 2213 | ||
2242 | if (sta_id == IWL_INVALID_STATION) { | 2214 | if (sta_id == IWL_INVALID_STATION) { |
2243 | IWL_DEBUG_RATE("LQ: ADD station %s\n", | 2215 | IWL_DEBUG_RATE("LQ: ADD station %s\n", |
2244 | print_mac(mac, sta->sta.addr)); | 2216 | print_mac(mac, sta->addr)); |
2245 | sta_id = iwl_add_station_flags(priv, sta->sta.addr, | 2217 | sta_id = iwl_add_station_flags(priv, sta->addr, |
2246 | 0, CMD_ASYNC, NULL); | 2218 | 0, CMD_ASYNC, NULL); |
2247 | } | 2219 | } |
2248 | if ((sta_id != IWL_INVALID_STATION)) { | 2220 | if ((sta_id != IWL_INVALID_STATION)) { |
@@ -2256,11 +2228,11 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, | |||
2256 | /* Find highest tx rate supported by hardware and destination station */ | 2228 | /* Find highest tx rate supported by hardware and destination station */ |
2257 | lq_sta->last_txrate_idx = 3; | 2229 | lq_sta->last_txrate_idx = 3; |
2258 | for (i = 0; i < sband->n_bitrates; i++) | 2230 | for (i = 0; i < sband->n_bitrates; i++) |
2259 | if (sta->sta.supp_rates[sband->band] & BIT(i)) | 2231 | if (sta->supp_rates[sband->band] & BIT(i)) |
2260 | lq_sta->last_txrate_idx = i; | 2232 | lq_sta->last_txrate_idx = i; |
2261 | 2233 | ||
2262 | /* For MODE_IEEE80211A, skip over cck rates in global rate table */ | 2234 | /* For MODE_IEEE80211A, skip over cck rates in global rate table */ |
2263 | if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) | 2235 | if (sband->band == IEEE80211_BAND_5GHZ) |
2264 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; | 2236 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; |
2265 | 2237 | ||
2266 | lq_sta->is_dup = 0; | 2238 | lq_sta->is_dup = 0; |
@@ -2301,7 +2273,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, | |||
2301 | lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; | 2273 | lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; |
2302 | lq_sta->drv = priv; | 2274 | lq_sta->drv = priv; |
2303 | 2275 | ||
2304 | rs_initialize_lq(priv, conf, sta); | 2276 | rs_initialize_lq(priv, conf, sta, lq_sta); |
2305 | } | 2277 | } |
2306 | 2278 | ||
2307 | static void rs_fill_link_cmd(const struct iwl_priv *priv, | 2279 | static void rs_fill_link_cmd(const struct iwl_priv *priv, |
@@ -2423,9 +2395,9 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, | |||
2423 | lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000); | 2395 | lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000); |
2424 | } | 2396 | } |
2425 | 2397 | ||
2426 | static void *rs_alloc(struct ieee80211_local *local) | 2398 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
2427 | { | 2399 | { |
2428 | return local->hw.priv; | 2400 | return hw->priv; |
2429 | } | 2401 | } |
2430 | /* rate scale requires free function to be implemented */ | 2402 | /* rate scale requires free function to be implemented */ |
2431 | static void rs_free(void *priv_rate) | 2403 | static void rs_free(void *priv_rate) |
@@ -2446,12 +2418,12 @@ static void rs_clear(void *priv_rate) | |||
2446 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 2418 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
2447 | } | 2419 | } |
2448 | 2420 | ||
2449 | static void rs_free_sta(void *priv_rate, void *priv_sta) | 2421 | static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, |
2422 | void *priv_sta) | ||
2450 | { | 2423 | { |
2451 | struct iwl_lq_sta *lq_sta = priv_sta; | 2424 | struct iwl_lq_sta *lq_sta = priv_sta; |
2452 | struct iwl_priv *priv; | 2425 | struct iwl_priv *priv = priv_r; |
2453 | 2426 | ||
2454 | priv = (struct iwl_priv *)priv_rate; | ||
2455 | IWL_DEBUG_RATE("enter\n"); | 2427 | IWL_DEBUG_RATE("enter\n"); |
2456 | kfree(lq_sta); | 2428 | kfree(lq_sta); |
2457 | IWL_DEBUG_RATE("leave\n"); | 2429 | IWL_DEBUG_RATE("leave\n"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 273762769767..7330890fd05e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -2504,8 +2504,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) | |||
2504 | 2504 | ||
2505 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 2505 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2506 | 2506 | ||
2507 | if (priv->current_ht_config.is_ht) | 2507 | iwl_set_rxon_ht(priv, &priv->current_ht_config); |
2508 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
2509 | 2508 | ||
2510 | iwl_set_rxon_chain(priv); | 2509 | iwl_set_rxon_chain(priv); |
2511 | priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); | 2510 | priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); |
@@ -2568,8 +2567,6 @@ static void iwl4965_post_associate(struct iwl_priv *priv) | |||
2568 | iwl_chain_noise_reset(priv); | 2567 | iwl_chain_noise_reset(priv); |
2569 | priv->start_calib = 1; | 2568 | priv->start_calib = 1; |
2570 | 2569 | ||
2571 | /* we have just associated, don't start scan too early */ | ||
2572 | priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; | ||
2573 | } | 2570 | } |
2574 | 2571 | ||
2575 | static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); | 2572 | static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); |
@@ -3171,6 +3168,10 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, | |||
3171 | priv->power_data.dtim_period = bss_conf->dtim_period; | 3168 | priv->power_data.dtim_period = bss_conf->dtim_period; |
3172 | priv->timestamp = bss_conf->timestamp; | 3169 | priv->timestamp = bss_conf->timestamp; |
3173 | priv->assoc_capability = bss_conf->assoc_capability; | 3170 | priv->assoc_capability = bss_conf->assoc_capability; |
3171 | |||
3172 | /* we have just associated, don't start scan too early | ||
3173 | * leave time for EAPOL exchange to complete | ||
3174 | */ | ||
3174 | priv->next_scan_jiffies = jiffies + | 3175 | priv->next_scan_jiffies = jiffies + |
3175 | IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; | 3176 | IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; |
3176 | mutex_lock(&priv->mutex); | 3177 | mutex_lock(&priv->mutex); |
@@ -3189,9 +3190,9 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, | |||
3189 | 3190 | ||
3190 | static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len) | 3191 | static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len) |
3191 | { | 3192 | { |
3192 | int ret; | ||
3193 | unsigned long flags; | 3193 | unsigned long flags; |
3194 | struct iwl_priv *priv = hw->priv; | 3194 | struct iwl_priv *priv = hw->priv; |
3195 | int ret; | ||
3195 | 3196 | ||
3196 | IWL_DEBUG_MAC80211("enter\n"); | 3197 | IWL_DEBUG_MAC80211("enter\n"); |
3197 | 3198 | ||
@@ -3210,20 +3211,27 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len) | |||
3210 | goto out_unlock; | 3211 | goto out_unlock; |
3211 | } | 3212 | } |
3212 | 3213 | ||
3213 | /* we don't schedule scan within next_scan_jiffies period */ | 3214 | /* We don't schedule scan within next_scan_jiffies period. |
3215 | * Avoid scanning during possible EAPOL exchange, return | ||
3216 | * success immediately. | ||
3217 | */ | ||
3214 | if (priv->next_scan_jiffies && | 3218 | if (priv->next_scan_jiffies && |
3215 | time_after(priv->next_scan_jiffies, jiffies)) { | 3219 | time_after(priv->next_scan_jiffies, jiffies)) { |
3216 | IWL_DEBUG_SCAN("scan rejected: within next scan period\n"); | 3220 | IWL_DEBUG_SCAN("scan rejected: within next scan period\n"); |
3217 | ret = -EAGAIN; | 3221 | queue_work(priv->workqueue, &priv->scan_completed); |
3222 | ret = 0; | ||
3218 | goto out_unlock; | 3223 | goto out_unlock; |
3219 | } | 3224 | } |
3225 | |||
3220 | /* if we just finished scan ask for delay */ | 3226 | /* if we just finished scan ask for delay */ |
3221 | if (iwl_is_associated(priv) && priv->last_scan_jiffies && | 3227 | if (iwl_is_associated(priv) && priv->last_scan_jiffies && |
3222 | time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) { | 3228 | time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) { |
3223 | IWL_DEBUG_SCAN("scan rejected: within previous scan period\n"); | 3229 | IWL_DEBUG_SCAN("scan rejected: within previous scan period\n"); |
3224 | ret = -EAGAIN; | 3230 | queue_work(priv->workqueue, &priv->scan_completed); |
3231 | ret = 0; | ||
3225 | goto out_unlock; | 3232 | goto out_unlock; |
3226 | } | 3233 | } |
3234 | |||
3227 | if (ssid_len) { | 3235 | if (ssid_len) { |
3228 | priv->one_direct_scan = 1; | 3236 | priv->one_direct_scan = 1; |
3229 | priv->direct_ssid_len = min_t(u8, ssid_len, IW_ESSID_MAX_SIZE); | 3237 | priv->direct_ssid_len = min_t(u8, ssid_len, IW_ESSID_MAX_SIZE); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d80184ee911c..4c312c55f90c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -646,8 +646,14 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) | |||
646 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | 646 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; |
647 | u32 val; | 647 | u32 val; |
648 | 648 | ||
649 | if (!ht_info->is_ht) | 649 | if (!ht_info->is_ht) { |
650 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | | ||
651 | RXON_FLG_CHANNEL_MODE_PURE_40_MSK | | ||
652 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | | ||
653 | RXON_FLG_FAT_PROT_MSK | | ||
654 | RXON_FLG_HT_PROT_MSK); | ||
650 | return; | 655 | return; |
656 | } | ||
651 | 657 | ||
652 | /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */ | 658 | /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */ |
653 | if (iwl_is_fat_tx_allowed(priv, NULL)) | 659 | if (iwl_is_fat_tx_allowed(priv, NULL)) |
@@ -697,8 +703,12 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) | |||
697 | } | 703 | } |
698 | EXPORT_SYMBOL(iwl_set_rxon_ht); | 704 | EXPORT_SYMBOL(iwl_set_rxon_ht); |
699 | 705 | ||
700 | /* | 706 | #define IWL_NUM_RX_CHAINS_MULTIPLE 3 |
701 | * Determine how many receiver/antenna chains to use. | 707 | #define IWL_NUM_RX_CHAINS_SINGLE 2 |
708 | #define IWL_NUM_IDLE_CHAINS_DUAL 2 | ||
709 | #define IWL_NUM_IDLE_CHAINS_SINGLE 1 | ||
710 | |||
711 | /* Determine how many receiver/antenna chains to use. | ||
702 | * More provides better reception via diversity. Fewer saves power. | 712 | * More provides better reception via diversity. Fewer saves power. |
703 | * MIMO (dual stream) requires at least 2, but works better with 3. | 713 | * MIMO (dual stream) requires at least 2, but works better with 3. |
704 | * This does not determine *which* chains to use, just how many. | 714 | * This does not determine *which* chains to use, just how many. |
@@ -711,9 +721,9 @@ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) | |||
711 | /* # of Rx chains to use when expecting MIMO. */ | 721 | /* # of Rx chains to use when expecting MIMO. */ |
712 | if (is_single || (!is_cam && (priv->current_ht_config.sm_ps == | 722 | if (is_single || (!is_cam && (priv->current_ht_config.sm_ps == |
713 | WLAN_HT_CAP_SM_PS_STATIC))) | 723 | WLAN_HT_CAP_SM_PS_STATIC))) |
714 | return 2; | 724 | return IWL_NUM_RX_CHAINS_SINGLE; |
715 | else | 725 | else |
716 | return 3; | 726 | return IWL_NUM_RX_CHAINS_MULTIPLE; |
717 | } | 727 | } |
718 | 728 | ||
719 | static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) | 729 | static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) |
@@ -724,10 +734,11 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) | |||
724 | switch (priv->current_ht_config.sm_ps) { | 734 | switch (priv->current_ht_config.sm_ps) { |
725 | case WLAN_HT_CAP_SM_PS_STATIC: | 735 | case WLAN_HT_CAP_SM_PS_STATIC: |
726 | case WLAN_HT_CAP_SM_PS_DYNAMIC: | 736 | case WLAN_HT_CAP_SM_PS_DYNAMIC: |
727 | idle_cnt = (is_cam) ? 2 : 1; | 737 | idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL : |
738 | IWL_NUM_IDLE_CHAINS_SINGLE; | ||
728 | break; | 739 | break; |
729 | case WLAN_HT_CAP_SM_PS_DISABLED: | 740 | case WLAN_HT_CAP_SM_PS_DISABLED: |
730 | idle_cnt = (is_cam) ? active_cnt : 1; | 741 | idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE; |
731 | break; | 742 | break; |
732 | case WLAN_HT_CAP_SM_PS_INVALID: | 743 | case WLAN_HT_CAP_SM_PS_INVALID: |
733 | default: | 744 | default: |
@@ -796,7 +807,7 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) | |||
796 | 807 | ||
797 | priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); | 808 | priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); |
798 | 809 | ||
799 | if (!is_single && (active_rx_cnt >= 2) && is_cam) | 810 | if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) |
800 | priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; | 811 | priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; |
801 | else | 812 | else |
802 | priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; | 813 | priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 09c264be0496..bf855c35b0c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -463,11 +463,6 @@ void iwl_init_scan_params(struct iwl_priv *priv) | |||
463 | 463 | ||
464 | int iwl_scan_initiate(struct iwl_priv *priv) | 464 | int iwl_scan_initiate(struct iwl_priv *priv) |
465 | { | 465 | { |
466 | if (priv->iw_mode == NL80211_IFTYPE_AP) { | ||
467 | IWL_ERROR("APs don't scan.\n"); | ||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | if (!iwl_is_ready_rf(priv)) { | 466 | if (!iwl_is_ready_rf(priv)) { |
472 | IWL_DEBUG_SCAN("Aborting scan due to not ready.\n"); | 467 | IWL_DEBUG_SCAN("Aborting scan due to not ready.\n"); |
473 | return -EIO; | 468 | return -EIO; |
@@ -479,8 +474,7 @@ int iwl_scan_initiate(struct iwl_priv *priv) | |||
479 | } | 474 | } |
480 | 475 | ||
481 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | 476 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { |
482 | IWL_DEBUG_SCAN("Scan request while abort pending. " | 477 | IWL_DEBUG_SCAN("Scan request while abort pending\n"); |
483 | "Queuing.\n"); | ||
484 | return -EAGAIN; | 478 | return -EAGAIN; |
485 | } | 479 | } |
486 | 480 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index e9feca4033f9..907a53ebc6e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -1200,10 +1200,9 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1200 | /* If a Tx command is being handled and it isn't in the actual | 1200 | /* If a Tx command is being handled and it isn't in the actual |
1201 | * command queue then there a command routing bug has been introduced | 1201 | * command queue then there a command routing bug has been introduced |
1202 | * in the queue management code. */ | 1202 | * in the queue management code. */ |
1203 | if (txq_id != IWL_CMD_QUEUE_NUM) | 1203 | if (WARN(txq_id != IWL_CMD_QUEUE_NUM, |
1204 | IWL_ERROR("Error wrong command queue %d command id 0x%X\n", | 1204 | "wrong command queue %d, command id 0x%X\n", txq_id, pkt->hdr.cmd)) |
1205 | txq_id, pkt->hdr.cmd); | 1205 | return; |
1206 | BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); | ||
1207 | 1206 | ||
1208 | cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); | 1207 | cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); |
1209 | cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; | 1208 | cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 62b26befddc5..d15a2c997954 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -7370,15 +7370,6 @@ static ssize_t show_temperature(struct device *d, | |||
7370 | 7370 | ||
7371 | static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); | 7371 | static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); |
7372 | 7372 | ||
7373 | static ssize_t show_rs_window(struct device *d, | ||
7374 | struct device_attribute *attr, | ||
7375 | char *buf) | ||
7376 | { | ||
7377 | struct iwl3945_priv *priv = d->driver_data; | ||
7378 | return iwl3945_fill_rs_info(priv->hw, buf, IWL_AP_ID); | ||
7379 | } | ||
7380 | static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL); | ||
7381 | |||
7382 | static ssize_t show_tx_power(struct device *d, | 7373 | static ssize_t show_tx_power(struct device *d, |
7383 | struct device_attribute *attr, char *buf) | 7374 | struct device_attribute *attr, char *buf) |
7384 | { | 7375 | { |
@@ -7840,7 +7831,6 @@ static struct attribute *iwl3945_sysfs_entries[] = { | |||
7840 | #endif | 7831 | #endif |
7841 | &dev_attr_power_level.attr, | 7832 | &dev_attr_power_level.attr, |
7842 | &dev_attr_retry_rate.attr, | 7833 | &dev_attr_retry_rate.attr, |
7843 | &dev_attr_rs_window.attr, | ||
7844 | &dev_attr_statistics.attr, | 7834 | &dev_attr_statistics.attr, |
7845 | &dev_attr_status.attr, | 7835 | &dev_attr_status.attr, |
7846 | &dev_attr_temperature.attr, | 7836 | &dev_attr_temperature.attr, |
@@ -7908,6 +7898,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
7908 | SET_IEEE80211_DEV(hw, &pdev->dev); | 7898 | SET_IEEE80211_DEV(hw, &pdev->dev); |
7909 | 7899 | ||
7910 | hw->rate_control_algorithm = "iwl-3945-rs"; | 7900 | hw->rate_control_algorithm = "iwl-3945-rs"; |
7901 | hw->sta_data_size = sizeof(struct iwl3945_sta_priv); | ||
7911 | 7902 | ||
7912 | IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); | 7903 | IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); |
7913 | priv = hw->priv; | 7904 | priv = hw->priv; |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index acb889e25900..f6f3753da303 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -58,6 +58,7 @@ struct lbs_802_11_security { | |||
58 | u8 WPA2enabled; | 58 | u8 WPA2enabled; |
59 | u8 wep_enabled; | 59 | u8 wep_enabled; |
60 | u8 auth_mode; | 60 | u8 auth_mode; |
61 | u32 key_mgmt; | ||
61 | }; | 62 | }; |
62 | 63 | ||
63 | /** Current Basic Service Set State Structure */ | 64 | /** Current Basic Service Set State Structure */ |
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 11297dcf9fc3..6ebdd7f161f1 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c | |||
@@ -1598,8 +1598,20 @@ static int lbs_set_encodeext(struct net_device *dev, | |||
1598 | } | 1598 | } |
1599 | 1599 | ||
1600 | out: | 1600 | out: |
1601 | if (ret == 0) { /* key installation is time critical: postpone not! */ | 1601 | if (ret == 0) { |
1602 | lbs_do_association_work(priv); | 1602 | /* 802.1x and WPA rekeying must happen as quickly as possible, |
1603 | * especially during the 4-way handshake; thus if in | ||
1604 | * infrastructure mode, and either (a) 802.1x is enabled or | ||
1605 | * (b) WPA is being used, set the key right away. | ||
1606 | */ | ||
1607 | if (assoc_req->mode == IW_MODE_INFRA && | ||
1608 | ((assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_802_1X) || | ||
1609 | (assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_PSK) || | ||
1610 | assoc_req->secinfo.WPAenabled || | ||
1611 | assoc_req->secinfo.WPA2enabled)) { | ||
1612 | lbs_do_association_work(priv); | ||
1613 | } else | ||
1614 | lbs_postpone_association_work(priv); | ||
1603 | } else { | 1615 | } else { |
1604 | lbs_cancel_association_work(priv); | 1616 | lbs_cancel_association_work(priv); |
1605 | } | 1617 | } |
@@ -1707,13 +1719,17 @@ static int lbs_set_auth(struct net_device *dev, | |||
1707 | case IW_AUTH_TKIP_COUNTERMEASURES: | 1719 | case IW_AUTH_TKIP_COUNTERMEASURES: |
1708 | case IW_AUTH_CIPHER_PAIRWISE: | 1720 | case IW_AUTH_CIPHER_PAIRWISE: |
1709 | case IW_AUTH_CIPHER_GROUP: | 1721 | case IW_AUTH_CIPHER_GROUP: |
1710 | case IW_AUTH_KEY_MGMT: | ||
1711 | case IW_AUTH_DROP_UNENCRYPTED: | 1722 | case IW_AUTH_DROP_UNENCRYPTED: |
1712 | /* | 1723 | /* |
1713 | * libertas does not use these parameters | 1724 | * libertas does not use these parameters |
1714 | */ | 1725 | */ |
1715 | break; | 1726 | break; |
1716 | 1727 | ||
1728 | case IW_AUTH_KEY_MGMT: | ||
1729 | assoc_req->secinfo.key_mgmt = dwrq->value; | ||
1730 | updated = 1; | ||
1731 | break; | ||
1732 | |||
1717 | case IW_AUTH_WPA_VERSION: | 1733 | case IW_AUTH_WPA_VERSION: |
1718 | if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) { | 1734 | if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) { |
1719 | assoc_req->secinfo.WPAenabled = 0; | 1735 | assoc_req->secinfo.WPAenabled = 0; |
@@ -1793,6 +1809,10 @@ static int lbs_get_auth(struct net_device *dev, | |||
1793 | lbs_deb_enter(LBS_DEB_WEXT); | 1809 | lbs_deb_enter(LBS_DEB_WEXT); |
1794 | 1810 | ||
1795 | switch (dwrq->flags & IW_AUTH_INDEX) { | 1811 | switch (dwrq->flags & IW_AUTH_INDEX) { |
1812 | case IW_AUTH_KEY_MGMT: | ||
1813 | dwrq->value = priv->secinfo.key_mgmt; | ||
1814 | break; | ||
1815 | |||
1796 | case IW_AUTH_WPA_VERSION: | 1816 | case IW_AUTH_WPA_VERSION: |
1797 | dwrq->value = 0; | 1817 | dwrq->value = 0; |
1798 | if (priv->secinfo.WPAenabled) | 1818 | if (priv->secinfo.WPAenabled) |
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index f479c1af6782..25bae7933aa5 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c | |||
@@ -398,7 +398,7 @@ static int netwave_probe(struct pcmcia_device *link) | |||
398 | link->io.IOAddrLines = 5; | 398 | link->io.IOAddrLines = 5; |
399 | 399 | ||
400 | /* Interrupt setup */ | 400 | /* Interrupt setup */ |
401 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | 401 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; |
402 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 402 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
403 | link->irq.Handler = &netwave_interrupt; | 403 | link->irq.Handler = &netwave_interrupt; |
404 | 404 | ||
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 9a2fcc0163d6..50904771f291 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
@@ -5291,7 +5291,7 @@ static int orinoco_ioctl_getrid(struct net_device *dev, | |||
5291 | /* Trigger a scan (look for other cells in the vicinity) */ | 5291 | /* Trigger a scan (look for other cells in the vicinity) */ |
5292 | static int orinoco_ioctl_setscan(struct net_device *dev, | 5292 | static int orinoco_ioctl_setscan(struct net_device *dev, |
5293 | struct iw_request_info *info, | 5293 | struct iw_request_info *info, |
5294 | struct iw_param *srq, | 5294 | struct iw_point *srq, |
5295 | char *extra) | 5295 | char *extra) |
5296 | { | 5296 | { |
5297 | struct orinoco_private *priv = netdev_priv(dev); | 5297 | struct orinoco_private *priv = netdev_priv(dev); |
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 1ccf5a40cf06..9eaa252c2430 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c | |||
@@ -121,7 +121,7 @@ orinoco_cs_probe(struct pcmcia_device *link) | |||
121 | link->priv = dev; | 121 | link->priv = dev; |
122 | 122 | ||
123 | /* Interrupt setup */ | 123 | /* Interrupt setup */ |
124 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | 124 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; |
125 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 125 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
126 | link->irq.Handler = orinoco_interrupt; | 126 | link->irq.Handler = orinoco_interrupt; |
127 | link->irq.Instance = dev; | 127 | link->irq.Instance = dev; |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 963960dc30f2..44da0d19b5c8 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -325,7 +325,7 @@ static int ray_probe(struct pcmcia_device *p_dev) | |||
325 | p_dev->io.IOAddrLines = 5; | 325 | p_dev->io.IOAddrLines = 5; |
326 | 326 | ||
327 | /* Interrupt setup. For PCMCIA, driver takes what's given */ | 327 | /* Interrupt setup. For PCMCIA, driver takes what's given */ |
328 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | 328 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; |
329 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; | 329 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
330 | p_dev->irq.Handler = &ray_interrupt; | 330 | p_dev->irq.Handler = &ray_interrupt; |
331 | 331 | ||
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 00e965b9da75..2b414899dfa0 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -1627,7 +1627,6 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, | |||
1627 | static int rndis_iw_set_scan(struct net_device *dev, | 1627 | static int rndis_iw_set_scan(struct net_device *dev, |
1628 | struct iw_request_info *info, union iwreq_data *wrqu, char *extra) | 1628 | struct iw_request_info *info, union iwreq_data *wrqu, char *extra) |
1629 | { | 1629 | { |
1630 | struct iw_param *param = &wrqu->param; | ||
1631 | struct usbnet *usbdev = dev->priv; | 1630 | struct usbnet *usbdev = dev->priv; |
1632 | union iwreq_data evt; | 1631 | union iwreq_data evt; |
1633 | int ret = -EINVAL; | 1632 | int ret = -EINVAL; |
@@ -1635,7 +1634,7 @@ static int rndis_iw_set_scan(struct net_device *dev, | |||
1635 | 1634 | ||
1636 | devdbg(usbdev, "SIOCSIWSCAN"); | 1635 | devdbg(usbdev, "SIOCSIWSCAN"); |
1637 | 1636 | ||
1638 | if (param->flags == 0) { | 1637 | if (wrqu->data.flags == 0) { |
1639 | tmp = ccpu2(1); | 1638 | tmp = ccpu2(1); |
1640 | ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, | 1639 | ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, |
1641 | sizeof(tmp)); | 1640 | sizeof(tmp)); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 485c40de5cc0..2c6cc5c374ff 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -543,7 +543,8 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
543 | * provided but key 0 is not, then the key is not found | 543 | * provided but key 0 is not, then the key is not found |
544 | * by the hardware during RX). | 544 | * by the hardware during RX). |
545 | */ | 545 | */ |
546 | key->hw_key_idx = 0; | 546 | if (cmd == SET_KEY) |
547 | key->hw_key_idx = 0; | ||
547 | 548 | ||
548 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) | 549 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) |
549 | set_key = rt2x00dev->ops->lib->config_pairwise_key; | 550 | set_key = rt2x00dev->ops->lib->config_pairwise_key; |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 2c36b91ff4c7..a461620b489f 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -381,7 +381,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev, | |||
381 | if (reg && reg == mask) | 381 | if (reg && reg == mask) |
382 | return -ENOSPC; | 382 | return -ENOSPC; |
383 | 383 | ||
384 | key->hw_key_idx += reg ? (ffz(reg) - 1) : 0; | 384 | key->hw_key_idx += reg ? ffz(reg) : 0; |
385 | 385 | ||
386 | /* | 386 | /* |
387 | * Upload key to hardware | 387 | * Upload key to hardware |
@@ -477,7 +477,7 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |||
477 | return -ENOSPC; | 477 | return -ENOSPC; |
478 | } | 478 | } |
479 | 479 | ||
480 | key->hw_key_idx += reg ? (ffz(reg) - 1) : 0; | 480 | key->hw_key_idx += reg ? ffz(reg) : 0; |
481 | 481 | ||
482 | /* | 482 | /* |
483 | * Upload key to hardware | 483 | * Upload key to hardware |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 27dde3e34603..934f8e03c5aa 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -393,7 +393,7 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, | |||
393 | if (reg && reg == mask) | 393 | if (reg && reg == mask) |
394 | return -ENOSPC; | 394 | return -ENOSPC; |
395 | 395 | ||
396 | key->hw_key_idx += reg ? (ffz(reg) - 1) : 0; | 396 | key->hw_key_idx += reg ? ffz(reg) : 0; |
397 | 397 | ||
398 | /* | 398 | /* |
399 | * Upload key to hardware | 399 | * Upload key to hardware |
@@ -494,7 +494,7 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |||
494 | return -ENOSPC; | 494 | return -ENOSPC; |
495 | } | 495 | } |
496 | 496 | ||
497 | key->hw_key_idx += reg ? (ffz(reg) - 1) : 0; | 497 | key->hw_key_idx += reg ? ffz(reg) : 0; |
498 | 498 | ||
499 | /* | 499 | /* |
500 | * Upload key to hardware | 500 | * Upload key to hardware |
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index e368759d1d89..67b26d3c3cd5 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c | |||
@@ -195,7 +195,7 @@ spectrum_cs_probe(struct pcmcia_device *link) | |||
195 | link->priv = dev; | 195 | link->priv = dev; |
196 | 196 | ||
197 | /* Interrupt setup */ | 197 | /* Interrupt setup */ |
198 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | 198 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; |
199 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 199 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
200 | link->irq.Handler = orinoco_interrupt; | 200 | link->irq.Handler = orinoco_interrupt; |
201 | link->irq.Instance = dev; | 201 | link->irq.Instance = dev; |
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 00a3559e5aa4..b5de38a9b791 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c | |||
@@ -4496,7 +4496,7 @@ wavelan_probe(struct pcmcia_device *p_dev) | |||
4496 | p_dev->io.IOAddrLines = 3; | 4496 | p_dev->io.IOAddrLines = 3; |
4497 | 4497 | ||
4498 | /* Interrupt setup */ | 4498 | /* Interrupt setup */ |
4499 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | 4499 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; |
4500 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; | 4500 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
4501 | p_dev->irq.Handler = wavelan_interrupt; | 4501 | p_dev->irq.Handler = wavelan_interrupt; |
4502 | 4502 | ||
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index b6d4e04b8ab4..74a5ad2f1223 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c | |||
@@ -1917,7 +1917,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev) | |||
1917 | p_dev->io.IOAddrLines = 5; | 1917 | p_dev->io.IOAddrLines = 5; |
1918 | 1918 | ||
1919 | /* Interrupt setup */ | 1919 | /* Interrupt setup */ |
1920 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | 1920 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; |
1921 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; | 1921 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
1922 | p_dev->irq.Handler = wl3501_interrupt; | 1922 | p_dev->irq.Handler = wl3501_interrupt; |
1923 | 1923 | ||
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index abc1abc63bf0..14126bc36641 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -471,6 +471,11 @@ struct ieee80211s_hdr { | |||
471 | u8 eaddr3[6]; | 471 | u8 eaddr3[6]; |
472 | } __attribute__ ((packed)); | 472 | } __attribute__ ((packed)); |
473 | 473 | ||
474 | /* Mesh flags */ | ||
475 | #define MESH_FLAGS_AE_A4 0x1 | ||
476 | #define MESH_FLAGS_AE_A5_A6 0x2 | ||
477 | #define MESH_FLAGS_PS_DEEP 0x4 | ||
478 | |||
474 | /** | 479 | /** |
475 | * struct ieee80211_quiet_ie | 480 | * struct ieee80211_quiet_ie |
476 | * | 481 | * |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 9f40c4d417d7..0e85ec39b638 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -363,11 +363,13 @@ struct wiphy; | |||
363 | * wireless extensions but this is subject to reevaluation as soon as this | 363 | * wireless extensions but this is subject to reevaluation as soon as this |
364 | * code is used more widely and we have a first user without wext. | 364 | * code is used more widely and we have a first user without wext. |
365 | * | 365 | * |
366 | * @add_virtual_intf: create a new virtual interface with the given name | 366 | * @add_virtual_intf: create a new virtual interface with the given name, |
367 | * must set the struct wireless_dev's iftype. | ||
367 | * | 368 | * |
368 | * @del_virtual_intf: remove the virtual interface determined by ifindex. | 369 | * @del_virtual_intf: remove the virtual interface determined by ifindex. |
369 | * | 370 | * |
370 | * @change_virtual_intf: change type of virtual interface | 371 | * @change_virtual_intf: change type/configuration of virtual interface, |
372 | * keep the struct wireless_dev's iftype updated. | ||
371 | * | 373 | * |
372 | * @add_key: add a key with the given parameters. @mac_addr will be %NULL | 374 | * @add_key: add a key with the given parameters. @mac_addr will be %NULL |
373 | * when adding a group key. | 375 | * when adding a group key. |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 003e4a03874e..f5f5b1ff1584 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1800,4 +1800,72 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, | |||
1800 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, | 1800 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, |
1801 | const u8 *addr); | 1801 | const u8 *addr); |
1802 | 1802 | ||
1803 | |||
1804 | /* Rate control API */ | ||
1805 | /** | ||
1806 | * struct rate_selection - rate information for/from rate control algorithms | ||
1807 | * | ||
1808 | * @rate_idx: selected transmission rate index | ||
1809 | * @nonerp_idx: Non-ERP rate to use instead if ERP cannot be used | ||
1810 | * @probe_idx: rate for probing (or -1) | ||
1811 | * @max_rate_idx: maximum rate index that can be used, this is | ||
1812 | * input to the algorithm and will be enforced | ||
1813 | */ | ||
1814 | struct rate_selection { | ||
1815 | s8 rate_idx, nonerp_idx, probe_idx, max_rate_idx; | ||
1816 | }; | ||
1817 | |||
1818 | struct rate_control_ops { | ||
1819 | struct module *module; | ||
1820 | const char *name; | ||
1821 | void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir); | ||
1822 | void (*clear)(void *priv); | ||
1823 | void (*free)(void *priv); | ||
1824 | |||
1825 | void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp); | ||
1826 | void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, | ||
1827 | struct ieee80211_sta *sta, void *priv_sta); | ||
1828 | void (*free_sta)(void *priv, struct ieee80211_sta *sta, | ||
1829 | void *priv_sta); | ||
1830 | |||
1831 | void (*tx_status)(void *priv, struct ieee80211_supported_band *sband, | ||
1832 | struct ieee80211_sta *sta, void *priv_sta, | ||
1833 | struct sk_buff *skb); | ||
1834 | void (*get_rate)(void *priv, struct ieee80211_supported_band *sband, | ||
1835 | struct ieee80211_sta *sta, void *priv_sta, | ||
1836 | struct sk_buff *skb, | ||
1837 | struct rate_selection *sel); | ||
1838 | |||
1839 | void (*add_sta_debugfs)(void *priv, void *priv_sta, | ||
1840 | struct dentry *dir); | ||
1841 | void (*remove_sta_debugfs)(void *priv, void *priv_sta); | ||
1842 | }; | ||
1843 | |||
1844 | static inline int rate_supported(struct ieee80211_sta *sta, | ||
1845 | enum ieee80211_band band, | ||
1846 | int index) | ||
1847 | { | ||
1848 | return (sta == NULL || sta->supp_rates[band] & BIT(index)); | ||
1849 | } | ||
1850 | |||
1851 | static inline s8 | ||
1852 | rate_lowest_index(struct ieee80211_supported_band *sband, | ||
1853 | struct ieee80211_sta *sta) | ||
1854 | { | ||
1855 | int i; | ||
1856 | |||
1857 | for (i = 0; i < sband->n_bitrates; i++) | ||
1858 | if (rate_supported(sta, sband->band, i)) | ||
1859 | return i; | ||
1860 | |||
1861 | /* warn when we cannot find a rate. */ | ||
1862 | WARN_ON(1); | ||
1863 | |||
1864 | return 0; | ||
1865 | } | ||
1866 | |||
1867 | |||
1868 | int ieee80211_rate_control_register(struct rate_control_ops *ops); | ||
1869 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops); | ||
1870 | |||
1803 | #endif /* MAC80211_H */ | 1871 | #endif /* MAC80211_H */ |
diff --git a/include/net/wireless.h b/include/net/wireless.h index e4378cc6bf8e..721efb363db7 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h | |||
@@ -223,9 +223,11 @@ struct wiphy { | |||
223 | * the netdev.) | 223 | * the netdev.) |
224 | * | 224 | * |
225 | * @wiphy: pointer to hardware description | 225 | * @wiphy: pointer to hardware description |
226 | * @iftype: interface type | ||
226 | */ | 227 | */ |
227 | struct wireless_dev { | 228 | struct wireless_dev { |
228 | struct wiphy *wiphy; | 229 | struct wiphy *wiphy; |
230 | enum nl80211_iftype iftype; | ||
229 | 231 | ||
230 | /* private to the generic wireless code */ | 232 | /* private to the generic wireless code */ |
231 | struct list_head list; | 233 | struct list_head list; |
@@ -329,6 +331,15 @@ extern int ieee80211_frequency_to_channel(int freq); | |||
329 | extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy, | 331 | extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy, |
330 | int freq); | 332 | int freq); |
331 | /** | 333 | /** |
334 | * ieee80211_get_channel - get channel struct from wiphy for specified frequency | ||
335 | */ | ||
336 | static inline struct ieee80211_channel * | ||
337 | ieee80211_get_channel(struct wiphy *wiphy, int freq) | ||
338 | { | ||
339 | return __ieee80211_get_channel(wiphy, freq); | ||
340 | } | ||
341 | |||
342 | /** | ||
332 | * __regulatory_hint - hint to the wireless core a regulatory domain | 343 | * __regulatory_hint - hint to the wireless core a regulatory domain |
333 | * @wiphy: if a driver is providing the hint this is the driver's very | 344 | * @wiphy: if a driver is providing the hint this is the driver's very |
334 | * own &struct wiphy | 345 | * own &struct wiphy |
@@ -380,13 +391,4 @@ extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, | |||
380 | */ | 391 | */ |
381 | extern int regulatory_hint(struct wiphy *wiphy, | 392 | extern int regulatory_hint(struct wiphy *wiphy, |
382 | const char *alpha2, struct ieee80211_regdomain *rd); | 393 | const char *alpha2, struct ieee80211_regdomain *rd); |
383 | |||
384 | /** | ||
385 | * ieee80211_get_channel - get channel struct from wiphy for specified frequency | ||
386 | */ | ||
387 | static inline struct ieee80211_channel * | ||
388 | ieee80211_get_channel(struct wiphy *wiphy, int freq) | ||
389 | { | ||
390 | return __ieee80211_get_channel(wiphy, freq); | ||
391 | } | ||
392 | #endif /* __NET_WIRELESS_H */ | 394 | #endif /* __NET_WIRELESS_H */ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e2574885db4a..855126a3039d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -82,7 +82,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
82 | enum nl80211_iftype type, u32 *flags, | 82 | enum nl80211_iftype type, u32 *flags, |
83 | struct vif_params *params) | 83 | struct vif_params *params) |
84 | { | 84 | { |
85 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
86 | struct net_device *dev; | 85 | struct net_device *dev; |
87 | struct ieee80211_sub_if_data *sdata; | 86 | struct ieee80211_sub_if_data *sdata; |
88 | int ret; | 87 | int ret; |
@@ -95,15 +94,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
95 | if (!nl80211_type_check(type)) | 94 | if (!nl80211_type_check(type)) |
96 | return -EINVAL; | 95 | return -EINVAL; |
97 | 96 | ||
98 | if (dev == local->mdev) | ||
99 | return -EOPNOTSUPP; | ||
100 | |||
101 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 97 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
102 | 98 | ||
103 | ret = ieee80211_if_change_type(sdata, type); | 99 | ret = ieee80211_if_change_type(sdata, type); |
104 | if (ret) | 100 | if (ret) |
105 | return ret; | 101 | return ret; |
106 | 102 | ||
103 | if (netif_running(sdata->dev)) | ||
104 | return -EBUSY; | ||
105 | |||
107 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) | 106 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) |
108 | ieee80211_sdata_set_mesh_id(sdata, | 107 | ieee80211_sdata_set_mesh_id(sdata, |
109 | params->mesh_id_len, | 108 | params->mesh_id_len, |
@@ -120,16 +119,12 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
120 | u8 key_idx, u8 *mac_addr, | 119 | u8 key_idx, u8 *mac_addr, |
121 | struct key_params *params) | 120 | struct key_params *params) |
122 | { | 121 | { |
123 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
124 | struct ieee80211_sub_if_data *sdata; | 122 | struct ieee80211_sub_if_data *sdata; |
125 | struct sta_info *sta = NULL; | 123 | struct sta_info *sta = NULL; |
126 | enum ieee80211_key_alg alg; | 124 | enum ieee80211_key_alg alg; |
127 | struct ieee80211_key *key; | 125 | struct ieee80211_key *key; |
128 | int err; | 126 | int err; |
129 | 127 | ||
130 | if (dev == local->mdev) | ||
131 | return -EOPNOTSUPP; | ||
132 | |||
133 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 128 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
134 | 129 | ||
135 | switch (params->cipher) { | 130 | switch (params->cipher) { |
@@ -174,14 +169,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
174 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | 169 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
175 | u8 key_idx, u8 *mac_addr) | 170 | u8 key_idx, u8 *mac_addr) |
176 | { | 171 | { |
177 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
178 | struct ieee80211_sub_if_data *sdata; | 172 | struct ieee80211_sub_if_data *sdata; |
179 | struct sta_info *sta; | 173 | struct sta_info *sta; |
180 | int ret; | 174 | int ret; |
181 | 175 | ||
182 | if (dev == local->mdev) | ||
183 | return -EOPNOTSUPP; | ||
184 | |||
185 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 176 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
186 | 177 | ||
187 | rcu_read_lock(); | 178 | rcu_read_lock(); |
@@ -222,7 +213,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
222 | void (*callback)(void *cookie, | 213 | void (*callback)(void *cookie, |
223 | struct key_params *params)) | 214 | struct key_params *params)) |
224 | { | 215 | { |
225 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
226 | struct ieee80211_sub_if_data *sdata; | 216 | struct ieee80211_sub_if_data *sdata; |
227 | struct sta_info *sta = NULL; | 217 | struct sta_info *sta = NULL; |
228 | u8 seq[6] = {0}; | 218 | u8 seq[6] = {0}; |
@@ -232,9 +222,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
232 | u16 iv16; | 222 | u16 iv16; |
233 | int err = -ENOENT; | 223 | int err = -ENOENT; |
234 | 224 | ||
235 | if (dev == local->mdev) | ||
236 | return -EOPNOTSUPP; | ||
237 | |||
238 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 225 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
239 | 226 | ||
240 | rcu_read_lock(); | 227 | rcu_read_lock(); |
@@ -310,12 +297,8 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, | |||
310 | struct net_device *dev, | 297 | struct net_device *dev, |
311 | u8 key_idx) | 298 | u8 key_idx) |
312 | { | 299 | { |
313 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
314 | struct ieee80211_sub_if_data *sdata; | 300 | struct ieee80211_sub_if_data *sdata; |
315 | 301 | ||
316 | if (dev == local->mdev) | ||
317 | return -EOPNOTSUPP; | ||
318 | |||
319 | rcu_read_lock(); | 302 | rcu_read_lock(); |
320 | 303 | ||
321 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 304 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -496,13 +479,9 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
496 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | 479 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, |
497 | struct beacon_parameters *params) | 480 | struct beacon_parameters *params) |
498 | { | 481 | { |
499 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
500 | struct ieee80211_sub_if_data *sdata; | 482 | struct ieee80211_sub_if_data *sdata; |
501 | struct beacon_data *old; | 483 | struct beacon_data *old; |
502 | 484 | ||
503 | if (dev == local->mdev) | ||
504 | return -EOPNOTSUPP; | ||
505 | |||
506 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 485 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
507 | 486 | ||
508 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 487 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
@@ -519,13 +498,9 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
519 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | 498 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, |
520 | struct beacon_parameters *params) | 499 | struct beacon_parameters *params) |
521 | { | 500 | { |
522 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
523 | struct ieee80211_sub_if_data *sdata; | 501 | struct ieee80211_sub_if_data *sdata; |
524 | struct beacon_data *old; | 502 | struct beacon_data *old; |
525 | 503 | ||
526 | if (dev == local->mdev) | ||
527 | return -EOPNOTSUPP; | ||
528 | |||
529 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 504 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
530 | 505 | ||
531 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 506 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
@@ -541,13 +516,9 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
541 | 516 | ||
542 | static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | 517 | static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) |
543 | { | 518 | { |
544 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
545 | struct ieee80211_sub_if_data *sdata; | 519 | struct ieee80211_sub_if_data *sdata; |
546 | struct beacon_data *old; | 520 | struct beacon_data *old; |
547 | 521 | ||
548 | if (dev == local->mdev) | ||
549 | return -EOPNOTSUPP; | ||
550 | |||
551 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 522 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
552 | 523 | ||
553 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 524 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
@@ -695,9 +666,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
695 | struct ieee80211_sub_if_data *sdata; | 666 | struct ieee80211_sub_if_data *sdata; |
696 | int err; | 667 | int err; |
697 | 668 | ||
698 | if (dev == local->mdev || params->vlan == local->mdev) | ||
699 | return -EOPNOTSUPP; | ||
700 | |||
701 | /* Prevent a race with changing the rate control algorithm */ | 669 | /* Prevent a race with changing the rate control algorithm */ |
702 | if (!netif_running(dev)) | 670 | if (!netif_running(dev)) |
703 | return -ENETDOWN; | 671 | return -ENETDOWN; |
@@ -725,7 +693,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
725 | 693 | ||
726 | sta_apply_parameters(local, sta, params); | 694 | sta_apply_parameters(local, sta, params); |
727 | 695 | ||
728 | rate_control_rate_init(sta, local); | 696 | rate_control_rate_init(sta); |
729 | 697 | ||
730 | rcu_read_lock(); | 698 | rcu_read_lock(); |
731 | 699 | ||
@@ -752,9 +720,6 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
752 | struct ieee80211_sub_if_data *sdata; | 720 | struct ieee80211_sub_if_data *sdata; |
753 | struct sta_info *sta; | 721 | struct sta_info *sta; |
754 | 722 | ||
755 | if (dev == local->mdev) | ||
756 | return -EOPNOTSUPP; | ||
757 | |||
758 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 723 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
759 | 724 | ||
760 | if (mac) { | 725 | if (mac) { |
@@ -786,9 +751,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
786 | struct sta_info *sta; | 751 | struct sta_info *sta; |
787 | struct ieee80211_sub_if_data *vlansdata; | 752 | struct ieee80211_sub_if_data *vlansdata; |
788 | 753 | ||
789 | if (dev == local->mdev || params->vlan == local->mdev) | ||
790 | return -EOPNOTSUPP; | ||
791 | |||
792 | rcu_read_lock(); | 754 | rcu_read_lock(); |
793 | 755 | ||
794 | /* XXX: get sta belonging to dev */ | 756 | /* XXX: get sta belonging to dev */ |
@@ -828,9 +790,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
828 | struct sta_info *sta; | 790 | struct sta_info *sta; |
829 | int err; | 791 | int err; |
830 | 792 | ||
831 | if (dev == local->mdev) | ||
832 | return -EOPNOTSUPP; | ||
833 | |||
834 | if (!netif_running(dev)) | 793 | if (!netif_running(dev)) |
835 | return -ENETDOWN; | 794 | return -ENETDOWN; |
836 | 795 | ||
@@ -884,9 +843,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
884 | struct mesh_path *mpath; | 843 | struct mesh_path *mpath; |
885 | struct sta_info *sta; | 844 | struct sta_info *sta; |
886 | 845 | ||
887 | if (dev == local->mdev) | ||
888 | return -EOPNOTSUPP; | ||
889 | |||
890 | if (!netif_running(dev)) | 846 | if (!netif_running(dev)) |
891 | return -ENETDOWN; | 847 | return -ENETDOWN; |
892 | 848 | ||
@@ -958,13 +914,9 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
958 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo) | 914 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo) |
959 | 915 | ||
960 | { | 916 | { |
961 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
962 | struct ieee80211_sub_if_data *sdata; | 917 | struct ieee80211_sub_if_data *sdata; |
963 | struct mesh_path *mpath; | 918 | struct mesh_path *mpath; |
964 | 919 | ||
965 | if (dev == local->mdev) | ||
966 | return -EOPNOTSUPP; | ||
967 | |||
968 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 920 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
969 | 921 | ||
970 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | 922 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
@@ -986,13 +938,9 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
986 | int idx, u8 *dst, u8 *next_hop, | 938 | int idx, u8 *dst, u8 *next_hop, |
987 | struct mpath_info *pinfo) | 939 | struct mpath_info *pinfo) |
988 | { | 940 | { |
989 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
990 | struct ieee80211_sub_if_data *sdata; | 941 | struct ieee80211_sub_if_data *sdata; |
991 | struct mesh_path *mpath; | 942 | struct mesh_path *mpath; |
992 | 943 | ||
993 | if (dev == local->mdev) | ||
994 | return -EOPNOTSUPP; | ||
995 | |||
996 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 944 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
997 | 945 | ||
998 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | 946 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
@@ -1015,13 +963,9 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1015 | struct net_device *dev, | 963 | struct net_device *dev, |
1016 | struct bss_parameters *params) | 964 | struct bss_parameters *params) |
1017 | { | 965 | { |
1018 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1019 | struct ieee80211_sub_if_data *sdata; | 966 | struct ieee80211_sub_if_data *sdata; |
1020 | u32 changed = 0; | 967 | u32 changed = 0; |
1021 | 968 | ||
1022 | if (dev == local->mdev) | ||
1023 | return -EOPNOTSUPP; | ||
1024 | |||
1025 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 969 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1026 | 970 | ||
1027 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 971 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 81f350eaf8a3..b9902e425f09 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -173,8 +173,7 @@ static ssize_t sta_agg_status_write(struct file *file, | |||
173 | const char __user *user_buf, size_t count, loff_t *ppos) | 173 | const char __user *user_buf, size_t count, loff_t *ppos) |
174 | { | 174 | { |
175 | struct sta_info *sta = file->private_data; | 175 | struct sta_info *sta = file->private_data; |
176 | struct net_device *dev = sta->sdata->dev; | 176 | struct ieee80211_local *local = sta->sdata->local; |
177 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
178 | struct ieee80211_hw *hw = &local->hw; | 177 | struct ieee80211_hw *hw = &local->hw; |
179 | u8 *da = sta->sta.addr; | 178 | u8 *da = sta->sta.addr; |
180 | static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, | 179 | static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3912fba6d3d0..8025b294588b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -573,6 +573,10 @@ enum { | |||
573 | /* maximum number of hardware queues we support. */ | 573 | /* maximum number of hardware queues we support. */ |
574 | #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) | 574 | #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) |
575 | 575 | ||
576 | struct ieee80211_master_priv { | ||
577 | struct ieee80211_local *local; | ||
578 | }; | ||
579 | |||
576 | struct ieee80211_local { | 580 | struct ieee80211_local { |
577 | /* embed the driver visible part. | 581 | /* embed the driver visible part. |
578 | * don't cast (use the static inlines below), but we keep | 582 | * don't cast (use the static inlines below), but we keep |
@@ -720,6 +724,8 @@ struct ieee80211_local { | |||
720 | 724 | ||
721 | #ifdef CONFIG_MAC80211_DEBUGFS | 725 | #ifdef CONFIG_MAC80211_DEBUGFS |
722 | struct local_debugfsdentries { | 726 | struct local_debugfsdentries { |
727 | struct dentry *rcdir; | ||
728 | struct dentry *rcname; | ||
723 | struct dentry *frequency; | 729 | struct dentry *frequency; |
724 | struct dentry *antenna_sel_tx; | 730 | struct dentry *antenna_sel_tx; |
725 | struct dentry *antenna_sel_rx; | 731 | struct dentry *antenna_sel_rx; |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a72fbebb8ea2..b5cd91e89712 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -625,6 +625,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
625 | /* and set some type-dependent values */ | 625 | /* and set some type-dependent values */ |
626 | sdata->vif.type = type; | 626 | sdata->vif.type = type; |
627 | sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; | 627 | sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; |
628 | sdata->wdev.iftype = type; | ||
628 | 629 | ||
629 | /* only monitor differs */ | 630 | /* only monitor differs */ |
630 | sdata->dev->type = ARPHRD_ETHER; | 631 | sdata->dev->type = ARPHRD_ETHER; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c307dba7ec03..d608c44047c0 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -106,7 +106,8 @@ static const struct header_ops ieee80211_header_ops = { | |||
106 | 106 | ||
107 | static int ieee80211_master_open(struct net_device *dev) | 107 | static int ieee80211_master_open(struct net_device *dev) |
108 | { | 108 | { |
109 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 109 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
110 | struct ieee80211_local *local = mpriv->local; | ||
110 | struct ieee80211_sub_if_data *sdata; | 111 | struct ieee80211_sub_if_data *sdata; |
111 | int res = -EOPNOTSUPP; | 112 | int res = -EOPNOTSUPP; |
112 | 113 | ||
@@ -128,7 +129,8 @@ static int ieee80211_master_open(struct net_device *dev) | |||
128 | 129 | ||
129 | static int ieee80211_master_stop(struct net_device *dev) | 130 | static int ieee80211_master_stop(struct net_device *dev) |
130 | { | 131 | { |
131 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 132 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
133 | struct ieee80211_local *local = mpriv->local; | ||
132 | struct ieee80211_sub_if_data *sdata; | 134 | struct ieee80211_sub_if_data *sdata; |
133 | 135 | ||
134 | /* we hold the RTNL here so can safely walk the list */ | 136 | /* we hold the RTNL here so can safely walk the list */ |
@@ -141,7 +143,8 @@ static int ieee80211_master_stop(struct net_device *dev) | |||
141 | 143 | ||
142 | static void ieee80211_master_set_multicast_list(struct net_device *dev) | 144 | static void ieee80211_master_set_multicast_list(struct net_device *dev) |
143 | { | 145 | { |
144 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 146 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
147 | struct ieee80211_local *local = mpriv->local; | ||
145 | 148 | ||
146 | ieee80211_configure_filter(local); | 149 | ieee80211_configure_filter(local); |
147 | } | 150 | } |
@@ -539,6 +542,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
539 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 542 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
540 | u16 frag, type; | 543 | u16 frag, type; |
541 | __le16 fc; | 544 | __le16 fc; |
545 | struct ieee80211_supported_band *sband; | ||
542 | struct ieee80211_tx_status_rtap_hdr *rthdr; | 546 | struct ieee80211_tx_status_rtap_hdr *rthdr; |
543 | struct ieee80211_sub_if_data *sdata; | 547 | struct ieee80211_sub_if_data *sdata; |
544 | struct net_device *prev_dev = NULL; | 548 | struct net_device *prev_dev = NULL; |
@@ -585,7 +589,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
585 | sta->tx_retry_count += info->status.retry_count; | 589 | sta->tx_retry_count += info->status.retry_count; |
586 | } | 590 | } |
587 | 591 | ||
588 | rate_control_tx_status(local->mdev, skb); | 592 | sband = local->hw.wiphy->bands[info->band]; |
593 | rate_control_tx_status(local, sband, sta, skb); | ||
589 | } | 594 | } |
590 | 595 | ||
591 | rcu_read_unlock(); | 596 | rcu_read_unlock(); |
@@ -787,7 +792,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
787 | int result; | 792 | int result; |
788 | enum ieee80211_band band; | 793 | enum ieee80211_band band; |
789 | struct net_device *mdev; | 794 | struct net_device *mdev; |
790 | struct wireless_dev *mwdev; | 795 | struct ieee80211_master_priv *mpriv; |
791 | 796 | ||
792 | /* | 797 | /* |
793 | * generic code guarantees at least one band, | 798 | * generic code guarantees at least one band, |
@@ -829,16 +834,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
829 | if (hw->queues < 4) | 834 | if (hw->queues < 4) |
830 | hw->ampdu_queues = 0; | 835 | hw->ampdu_queues = 0; |
831 | 836 | ||
832 | mdev = alloc_netdev_mq(sizeof(struct wireless_dev), | 837 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), |
833 | "wmaster%d", ether_setup, | 838 | "wmaster%d", ether_setup, |
834 | ieee80211_num_queues(hw)); | 839 | ieee80211_num_queues(hw)); |
835 | if (!mdev) | 840 | if (!mdev) |
836 | goto fail_mdev_alloc; | 841 | goto fail_mdev_alloc; |
837 | 842 | ||
838 | mwdev = netdev_priv(mdev); | 843 | mpriv = netdev_priv(mdev); |
839 | mdev->ieee80211_ptr = mwdev; | 844 | mpriv->local = local; |
840 | mwdev->wiphy = local->hw.wiphy; | ||
841 | |||
842 | local->mdev = mdev; | 845 | local->mdev = mdev; |
843 | 846 | ||
844 | ieee80211_rx_bss_list_init(local); | 847 | ieee80211_rx_bss_list_init(local); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 30cf891fd3a8..8013277924f2 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -351,7 +351,7 @@ static void ieee80211_mesh_path_timer(unsigned long data) | |||
351 | struct ieee80211_sub_if_data *sdata = | 351 | struct ieee80211_sub_if_data *sdata = |
352 | (struct ieee80211_sub_if_data *) data; | 352 | (struct ieee80211_sub_if_data *) data; |
353 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 353 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
354 | struct ieee80211_local *local = wdev_priv(&sdata->wdev); | 354 | struct ieee80211_local *local = sdata->local; |
355 | 355 | ||
356 | queue_work(local->hw.workqueue, &ifmsh->work); | 356 | queue_work(local->hw.workqueue, &ifmsh->work); |
357 | } | 357 | } |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 8ee414a0447c..e10471c6ba42 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -71,6 +71,7 @@ enum mesh_path_flags { | |||
71 | */ | 71 | */ |
72 | struct mesh_path { | 72 | struct mesh_path { |
73 | u8 dst[ETH_ALEN]; | 73 | u8 dst[ETH_ALEN]; |
74 | u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ | ||
74 | struct ieee80211_sub_if_data *sdata; | 75 | struct ieee80211_sub_if_data *sdata; |
75 | struct sta_info *next_hop; | 76 | struct sta_info *next_hop; |
76 | struct timer_list timer; | 77 | struct timer_list timer; |
@@ -226,6 +227,9 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
226 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); | 227 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); |
227 | struct mesh_path *mesh_path_lookup(u8 *dst, | 228 | struct mesh_path *mesh_path_lookup(u8 *dst, |
228 | struct ieee80211_sub_if_data *sdata); | 229 | struct ieee80211_sub_if_data *sdata); |
230 | struct mesh_path *mpp_path_lookup(u8 *dst, | ||
231 | struct ieee80211_sub_if_data *sdata); | ||
232 | int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata); | ||
229 | struct mesh_path *mesh_path_lookup_by_idx(int idx, | 233 | struct mesh_path *mesh_path_lookup_by_idx(int idx, |
230 | struct ieee80211_sub_if_data *sdata); | 234 | struct ieee80211_sub_if_data *sdata); |
231 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); | 235 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index e4fa2905fadc..3c72557df45a 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -36,6 +36,7 @@ struct mpath_node { | |||
36 | }; | 36 | }; |
37 | 37 | ||
38 | static struct mesh_table *mesh_paths; | 38 | static struct mesh_table *mesh_paths; |
39 | static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ | ||
39 | 40 | ||
40 | /* This lock will have the grow table function as writer and add / delete nodes | 41 | /* This lock will have the grow table function as writer and add / delete nodes |
41 | * as readers. When reading the table (i.e. doing lookups) we are well protected | 42 | * as readers. When reading the table (i.e. doing lookups) we are well protected |
@@ -94,6 +95,34 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
94 | return NULL; | 95 | return NULL; |
95 | } | 96 | } |
96 | 97 | ||
98 | struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | ||
99 | { | ||
100 | struct mesh_path *mpath; | ||
101 | struct hlist_node *n; | ||
102 | struct hlist_head *bucket; | ||
103 | struct mesh_table *tbl; | ||
104 | struct mpath_node *node; | ||
105 | |||
106 | tbl = rcu_dereference(mpp_paths); | ||
107 | |||
108 | bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; | ||
109 | hlist_for_each_entry_rcu(node, n, bucket, list) { | ||
110 | mpath = node->mpath; | ||
111 | if (mpath->sdata == sdata && | ||
112 | memcmp(dst, mpath->dst, ETH_ALEN) == 0) { | ||
113 | if (MPATH_EXPIRED(mpath)) { | ||
114 | spin_lock_bh(&mpath->state_lock); | ||
115 | if (MPATH_EXPIRED(mpath)) | ||
116 | mpath->flags &= ~MESH_PATH_ACTIVE; | ||
117 | spin_unlock_bh(&mpath->state_lock); | ||
118 | } | ||
119 | return mpath; | ||
120 | } | ||
121 | } | ||
122 | return NULL; | ||
123 | } | ||
124 | |||
125 | |||
97 | /** | 126 | /** |
98 | * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index | 127 | * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index |
99 | * @idx: index | 128 | * @idx: index |
@@ -226,6 +255,91 @@ err_path_alloc: | |||
226 | } | 255 | } |
227 | 256 | ||
228 | 257 | ||
258 | int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | ||
259 | { | ||
260 | struct mesh_path *mpath, *new_mpath; | ||
261 | struct mpath_node *node, *new_node; | ||
262 | struct hlist_head *bucket; | ||
263 | struct hlist_node *n; | ||
264 | int grow = 0; | ||
265 | int err = 0; | ||
266 | u32 hash_idx; | ||
267 | |||
268 | |||
269 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) | ||
270 | /* never add ourselves as neighbours */ | ||
271 | return -ENOTSUPP; | ||
272 | |||
273 | if (is_multicast_ether_addr(dst)) | ||
274 | return -ENOTSUPP; | ||
275 | |||
276 | err = -ENOMEM; | ||
277 | new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); | ||
278 | if (!new_mpath) | ||
279 | goto err_path_alloc; | ||
280 | |||
281 | new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); | ||
282 | if (!new_node) | ||
283 | goto err_node_alloc; | ||
284 | |||
285 | read_lock(&pathtbl_resize_lock); | ||
286 | memcpy(new_mpath->dst, dst, ETH_ALEN); | ||
287 | memcpy(new_mpath->mpp, mpp, ETH_ALEN); | ||
288 | new_mpath->sdata = sdata; | ||
289 | new_mpath->flags = 0; | ||
290 | skb_queue_head_init(&new_mpath->frame_queue); | ||
291 | new_node->mpath = new_mpath; | ||
292 | new_mpath->exp_time = jiffies; | ||
293 | spin_lock_init(&new_mpath->state_lock); | ||
294 | |||
295 | hash_idx = mesh_table_hash(dst, sdata, mpp_paths); | ||
296 | bucket = &mpp_paths->hash_buckets[hash_idx]; | ||
297 | |||
298 | spin_lock(&mpp_paths->hashwlock[hash_idx]); | ||
299 | |||
300 | err = -EEXIST; | ||
301 | hlist_for_each_entry(node, n, bucket, list) { | ||
302 | mpath = node->mpath; | ||
303 | if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) | ||
304 | goto err_exists; | ||
305 | } | ||
306 | |||
307 | hlist_add_head_rcu(&new_node->list, bucket); | ||
308 | if (atomic_inc_return(&mpp_paths->entries) >= | ||
309 | mpp_paths->mean_chain_len * (mpp_paths->hash_mask + 1)) | ||
310 | grow = 1; | ||
311 | |||
312 | spin_unlock(&mpp_paths->hashwlock[hash_idx]); | ||
313 | read_unlock(&pathtbl_resize_lock); | ||
314 | if (grow) { | ||
315 | struct mesh_table *oldtbl, *newtbl; | ||
316 | |||
317 | write_lock(&pathtbl_resize_lock); | ||
318 | oldtbl = mpp_paths; | ||
319 | newtbl = mesh_table_grow(mpp_paths); | ||
320 | if (!newtbl) { | ||
321 | write_unlock(&pathtbl_resize_lock); | ||
322 | return 0; | ||
323 | } | ||
324 | rcu_assign_pointer(mpp_paths, newtbl); | ||
325 | write_unlock(&pathtbl_resize_lock); | ||
326 | |||
327 | synchronize_rcu(); | ||
328 | mesh_table_free(oldtbl, false); | ||
329 | } | ||
330 | return 0; | ||
331 | |||
332 | err_exists: | ||
333 | spin_unlock(&mpp_paths->hashwlock[hash_idx]); | ||
334 | read_unlock(&pathtbl_resize_lock); | ||
335 | kfree(new_node); | ||
336 | err_node_alloc: | ||
337 | kfree(new_mpath); | ||
338 | err_path_alloc: | ||
339 | return err; | ||
340 | } | ||
341 | |||
342 | |||
229 | /** | 343 | /** |
230 | * mesh_plink_broken - deactivates paths and sends perr when a link breaks | 344 | * mesh_plink_broken - deactivates paths and sends perr when a link breaks |
231 | * | 345 | * |
@@ -475,11 +589,21 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) | |||
475 | int mesh_pathtbl_init(void) | 589 | int mesh_pathtbl_init(void) |
476 | { | 590 | { |
477 | mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); | 591 | mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); |
592 | if (!mesh_paths) | ||
593 | return -ENOMEM; | ||
478 | mesh_paths->free_node = &mesh_path_node_free; | 594 | mesh_paths->free_node = &mesh_path_node_free; |
479 | mesh_paths->copy_node = &mesh_path_node_copy; | 595 | mesh_paths->copy_node = &mesh_path_node_copy; |
480 | mesh_paths->mean_chain_len = MEAN_CHAIN_LEN; | 596 | mesh_paths->mean_chain_len = MEAN_CHAIN_LEN; |
481 | if (!mesh_paths) | 597 | |
598 | mpp_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); | ||
599 | if (!mpp_paths) { | ||
600 | mesh_table_free(mesh_paths, true); | ||
482 | return -ENOMEM; | 601 | return -ENOMEM; |
602 | } | ||
603 | mpp_paths->free_node = &mesh_path_node_free; | ||
604 | mpp_paths->copy_node = &mesh_path_node_copy; | ||
605 | mpp_paths->mean_chain_len = MEAN_CHAIN_LEN; | ||
606 | |||
483 | return 0; | 607 | return 0; |
484 | } | 608 | } |
485 | 609 | ||
@@ -511,4 +635,5 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) | |||
511 | void mesh_pathtbl_unregister(void) | 635 | void mesh_pathtbl_unregister(void) |
512 | { | 636 | { |
513 | mesh_table_free(mesh_paths, true); | 637 | mesh_table_free(mesh_paths, true); |
638 | mesh_table_free(mpp_paths, true); | ||
514 | } | 639 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 8611a8318c9c..e859a0ab6162 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -942,8 +942,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, | |||
942 | disassoc = 1; | 942 | disassoc = 1; |
943 | } else | 943 | } else |
944 | ieee80211_send_probe_req(sdata, ifsta->bssid, | 944 | ieee80211_send_probe_req(sdata, ifsta->bssid, |
945 | local->scan_ssid, | 945 | ifsta->ssid, |
946 | local->scan_ssid_len); | 946 | ifsta->ssid_len); |
947 | ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; | 947 | ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; |
948 | } else { | 948 | } else { |
949 | ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL; | 949 | ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL; |
@@ -1323,7 +1323,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1323 | ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); | 1323 | ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); |
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | rate_control_rate_init(sta, local); | 1326 | rate_control_rate_init(sta); |
1327 | 1327 | ||
1328 | if (elems.wmm_param) { | 1328 | if (elems.wmm_param) { |
1329 | set_sta_flags(sta, WLAN_STA_WME); | 1329 | set_sta_flags(sta, WLAN_STA_WME); |
@@ -1452,6 +1452,8 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1452 | ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; | 1452 | ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; |
1453 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); | 1453 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); |
1454 | 1454 | ||
1455 | ieee80211_led_assoc(local, true); | ||
1456 | |||
1455 | memset(&wrqu, 0, sizeof(wrqu)); | 1457 | memset(&wrqu, 0, sizeof(wrqu)); |
1456 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); | 1458 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); |
1457 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); | 1459 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); |
@@ -2342,7 +2344,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
2342 | sta->sta.supp_rates[band] = supp_rates | | 2344 | sta->sta.supp_rates[band] = supp_rates | |
2343 | ieee80211_mandatory_rates(local, band); | 2345 | ieee80211_mandatory_rates(local, band); |
2344 | 2346 | ||
2345 | rate_control_rate_init(sta, local); | 2347 | rate_control_rate_init(sta); |
2346 | 2348 | ||
2347 | if (sta_info_insert(sta)) | 2349 | if (sta_info_insert(sta)) |
2348 | return NULL; | 2350 | return NULL; |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 0388c090dfe9..5d786720d935 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/rtnetlink.h> | 12 | #include <linux/rtnetlink.h> |
13 | #include "rate.h" | 13 | #include "rate.h" |
14 | #include "ieee80211_i.h" | 14 | #include "ieee80211_i.h" |
15 | #include "debugfs.h" | ||
15 | 16 | ||
16 | struct rate_control_alg { | 17 | struct rate_control_alg { |
17 | struct list_head list; | 18 | struct list_head list; |
@@ -127,19 +128,46 @@ static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops) | |||
127 | module_put(ops->module); | 128 | module_put(ops->module); |
128 | } | 129 | } |
129 | 130 | ||
131 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
132 | static ssize_t rcname_read(struct file *file, char __user *userbuf, | ||
133 | size_t count, loff_t *ppos) | ||
134 | { | ||
135 | struct rate_control_ref *ref = file->private_data; | ||
136 | int len = strlen(ref->ops->name); | ||
137 | |||
138 | return simple_read_from_buffer(userbuf, count, ppos, | ||
139 | ref->ops->name, len); | ||
140 | } | ||
141 | |||
142 | static const struct file_operations rcname_ops = { | ||
143 | .read = rcname_read, | ||
144 | .open = mac80211_open_file_generic, | ||
145 | }; | ||
146 | #endif | ||
147 | |||
130 | struct rate_control_ref *rate_control_alloc(const char *name, | 148 | struct rate_control_ref *rate_control_alloc(const char *name, |
131 | struct ieee80211_local *local) | 149 | struct ieee80211_local *local) |
132 | { | 150 | { |
151 | struct dentry *debugfsdir = NULL; | ||
133 | struct rate_control_ref *ref; | 152 | struct rate_control_ref *ref; |
134 | 153 | ||
135 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); | 154 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); |
136 | if (!ref) | 155 | if (!ref) |
137 | goto fail_ref; | 156 | goto fail_ref; |
138 | kref_init(&ref->kref); | 157 | kref_init(&ref->kref); |
158 | ref->local = local; | ||
139 | ref->ops = ieee80211_rate_control_ops_get(name); | 159 | ref->ops = ieee80211_rate_control_ops_get(name); |
140 | if (!ref->ops) | 160 | if (!ref->ops) |
141 | goto fail_ops; | 161 | goto fail_ops; |
142 | ref->priv = ref->ops->alloc(local); | 162 | |
163 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
164 | debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); | ||
165 | local->debugfs.rcdir = debugfsdir; | ||
166 | local->debugfs.rcname = debugfs_create_file("name", 0400, debugfsdir, | ||
167 | ref, &rcname_ops); | ||
168 | #endif | ||
169 | |||
170 | ref->priv = ref->ops->alloc(&local->hw, debugfsdir); | ||
143 | if (!ref->priv) | 171 | if (!ref->priv) |
144 | goto fail_priv; | 172 | goto fail_priv; |
145 | return ref; | 173 | return ref; |
@@ -158,29 +186,46 @@ static void rate_control_release(struct kref *kref) | |||
158 | 186 | ||
159 | ctrl_ref = container_of(kref, struct rate_control_ref, kref); | 187 | ctrl_ref = container_of(kref, struct rate_control_ref, kref); |
160 | ctrl_ref->ops->free(ctrl_ref->priv); | 188 | ctrl_ref->ops->free(ctrl_ref->priv); |
189 | |||
190 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
191 | debugfs_remove(ctrl_ref->local->debugfs.rcname); | ||
192 | ctrl_ref->local->debugfs.rcname = NULL; | ||
193 | debugfs_remove(ctrl_ref->local->debugfs.rcdir); | ||
194 | ctrl_ref->local->debugfs.rcdir = NULL; | ||
195 | #endif | ||
196 | |||
161 | ieee80211_rate_control_ops_put(ctrl_ref->ops); | 197 | ieee80211_rate_control_ops_put(ctrl_ref->ops); |
162 | kfree(ctrl_ref); | 198 | kfree(ctrl_ref); |
163 | } | 199 | } |
164 | 200 | ||
165 | void rate_control_get_rate(struct net_device *dev, | 201 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
166 | struct ieee80211_supported_band *sband, | 202 | struct ieee80211_supported_band *sband, |
167 | struct sk_buff *skb, | 203 | struct sta_info *sta, struct sk_buff *skb, |
168 | struct rate_selection *sel) | 204 | struct rate_selection *sel) |
169 | { | 205 | { |
170 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 206 | struct rate_control_ref *ref = sdata->local->rate_ctrl; |
171 | struct rate_control_ref *ref = local->rate_ctrl; | 207 | void *priv_sta = NULL; |
172 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 208 | struct ieee80211_sta *ista = NULL; |
173 | struct sta_info *sta; | ||
174 | int i; | 209 | int i; |
175 | 210 | ||
176 | rcu_read_lock(); | ||
177 | sta = sta_info_get(local, hdr->addr1); | ||
178 | |||
179 | sel->rate_idx = -1; | 211 | sel->rate_idx = -1; |
180 | sel->nonerp_idx = -1; | 212 | sel->nonerp_idx = -1; |
181 | sel->probe_idx = -1; | 213 | sel->probe_idx = -1; |
214 | sel->max_rate_idx = sdata->max_ratectrl_rateidx; | ||
215 | |||
216 | if (sta) { | ||
217 | ista = &sta->sta; | ||
218 | priv_sta = sta->rate_ctrl_priv; | ||
219 | } | ||
220 | |||
221 | if (sta && sdata->force_unicast_rateidx > -1) | ||
222 | sel->rate_idx = sdata->force_unicast_rateidx; | ||
223 | else | ||
224 | ref->ops->get_rate(ref->priv, sband, ista, priv_sta, skb, sel); | ||
182 | 225 | ||
183 | ref->ops->get_rate(ref->priv, dev, sband, skb, sel); | 226 | if (sdata->max_ratectrl_rateidx > -1 && |
227 | sel->rate_idx > sdata->max_ratectrl_rateidx) | ||
228 | sel->rate_idx = sdata->max_ratectrl_rateidx; | ||
184 | 229 | ||
185 | BUG_ON(sel->rate_idx < 0); | 230 | BUG_ON(sel->rate_idx < 0); |
186 | 231 | ||
@@ -191,13 +236,11 @@ void rate_control_get_rate(struct net_device *dev, | |||
191 | if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate) | 236 | if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate) |
192 | break; | 237 | break; |
193 | 238 | ||
194 | if (rate_supported(sta, sband->band, i) && | 239 | if (rate_supported(ista, sband->band, i) && |
195 | !(rate->flags & IEEE80211_RATE_ERP_G)) | 240 | !(rate->flags & IEEE80211_RATE_ERP_G)) |
196 | sel->nonerp_idx = i; | 241 | sel->nonerp_idx = i; |
197 | } | 242 | } |
198 | } | 243 | } |
199 | |||
200 | rcu_read_unlock(); | ||
201 | } | 244 | } |
202 | 245 | ||
203 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) | 246 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 5f18c27eb900..eb94e584d24e 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -19,77 +19,48 @@ | |||
19 | #include "ieee80211_i.h" | 19 | #include "ieee80211_i.h" |
20 | #include "sta_info.h" | 20 | #include "sta_info.h" |
21 | 21 | ||
22 | /** | ||
23 | * struct rate_selection - rate selection for rate control algos | ||
24 | * @rate: selected transmission rate index | ||
25 | * @nonerp: Non-ERP rate to use instead if ERP cannot be used | ||
26 | * @probe: rate for probing (or -1) | ||
27 | * | ||
28 | */ | ||
29 | struct rate_selection { | ||
30 | s8 rate_idx, nonerp_idx, probe_idx; | ||
31 | }; | ||
32 | |||
33 | struct rate_control_ops { | ||
34 | struct module *module; | ||
35 | const char *name; | ||
36 | void (*tx_status)(void *priv, struct net_device *dev, | ||
37 | struct sk_buff *skb); | ||
38 | void (*get_rate)(void *priv, struct net_device *dev, | ||
39 | struct ieee80211_supported_band *band, | ||
40 | struct sk_buff *skb, | ||
41 | struct rate_selection *sel); | ||
42 | void (*rate_init)(void *priv, void *priv_sta, | ||
43 | struct ieee80211_local *local, struct sta_info *sta); | ||
44 | void (*clear)(void *priv); | ||
45 | |||
46 | void *(*alloc)(struct ieee80211_local *local); | ||
47 | void (*free)(void *priv); | ||
48 | void *(*alloc_sta)(void *priv, gfp_t gfp); | ||
49 | void (*free_sta)(void *priv, void *priv_sta); | ||
50 | |||
51 | int (*add_attrs)(void *priv, struct kobject *kobj); | ||
52 | void (*remove_attrs)(void *priv, struct kobject *kobj); | ||
53 | void (*add_sta_debugfs)(void *priv, void *priv_sta, | ||
54 | struct dentry *dir); | ||
55 | void (*remove_sta_debugfs)(void *priv, void *priv_sta); | ||
56 | }; | ||
57 | |||
58 | struct rate_control_ref { | 22 | struct rate_control_ref { |
23 | struct ieee80211_local *local; | ||
59 | struct rate_control_ops *ops; | 24 | struct rate_control_ops *ops; |
60 | void *priv; | 25 | void *priv; |
61 | struct kref kref; | 26 | struct kref kref; |
62 | }; | 27 | }; |
63 | 28 | ||
64 | int ieee80211_rate_control_register(struct rate_control_ops *ops); | ||
65 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops); | ||
66 | |||
67 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the | 29 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the |
68 | * first available algorithm. */ | 30 | * first available algorithm. */ |
69 | struct rate_control_ref *rate_control_alloc(const char *name, | 31 | struct rate_control_ref *rate_control_alloc(const char *name, |
70 | struct ieee80211_local *local); | 32 | struct ieee80211_local *local); |
71 | void rate_control_get_rate(struct net_device *dev, | 33 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
72 | struct ieee80211_supported_band *sband, | 34 | struct ieee80211_supported_band *sband, |
73 | struct sk_buff *skb, | 35 | struct sta_info *sta, struct sk_buff *skb, |
74 | struct rate_selection *sel); | 36 | struct rate_selection *sel); |
75 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); | 37 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); |
76 | void rate_control_put(struct rate_control_ref *ref); | 38 | void rate_control_put(struct rate_control_ref *ref); |
77 | 39 | ||
78 | static inline void rate_control_tx_status(struct net_device *dev, | 40 | static inline void rate_control_tx_status(struct ieee80211_local *local, |
41 | struct ieee80211_supported_band *sband, | ||
42 | struct sta_info *sta, | ||
79 | struct sk_buff *skb) | 43 | struct sk_buff *skb) |
80 | { | 44 | { |
81 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
82 | struct rate_control_ref *ref = local->rate_ctrl; | 45 | struct rate_control_ref *ref = local->rate_ctrl; |
46 | struct ieee80211_sta *ista = &sta->sta; | ||
47 | void *priv_sta = sta->rate_ctrl_priv; | ||
83 | 48 | ||
84 | ref->ops->tx_status(ref->priv, dev, skb); | 49 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); |
85 | } | 50 | } |
86 | 51 | ||
87 | 52 | ||
88 | static inline void rate_control_rate_init(struct sta_info *sta, | 53 | static inline void rate_control_rate_init(struct sta_info *sta) |
89 | struct ieee80211_local *local) | ||
90 | { | 54 | { |
55 | struct ieee80211_local *local = sta->sdata->local; | ||
91 | struct rate_control_ref *ref = sta->rate_ctrl; | 56 | struct rate_control_ref *ref = sta->rate_ctrl; |
92 | ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta); | 57 | struct ieee80211_sta *ista = &sta->sta; |
58 | void *priv_sta = sta->rate_ctrl_priv; | ||
59 | struct ieee80211_supported_band *sband; | ||
60 | |||
61 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
62 | |||
63 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); | ||
93 | } | 64 | } |
94 | 65 | ||
95 | 66 | ||
@@ -100,15 +71,19 @@ static inline void rate_control_clear(struct ieee80211_local *local) | |||
100 | } | 71 | } |
101 | 72 | ||
102 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, | 73 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, |
74 | struct ieee80211_sta *sta, | ||
103 | gfp_t gfp) | 75 | gfp_t gfp) |
104 | { | 76 | { |
105 | return ref->ops->alloc_sta(ref->priv, gfp); | 77 | return ref->ops->alloc_sta(ref->priv, sta, gfp); |
106 | } | 78 | } |
107 | 79 | ||
108 | static inline void rate_control_free_sta(struct rate_control_ref *ref, | 80 | static inline void rate_control_free_sta(struct sta_info *sta) |
109 | void *priv) | ||
110 | { | 81 | { |
111 | ref->ops->free_sta(ref->priv, priv); | 82 | struct rate_control_ref *ref = sta->rate_ctrl; |
83 | struct ieee80211_sta *ista = &sta->sta; | ||
84 | void *priv_sta = sta->rate_ctrl_priv; | ||
85 | |||
86 | ref->ops->free_sta(ref->priv, ista, priv_sta); | ||
112 | } | 87 | } |
113 | 88 | ||
114 | static inline void rate_control_add_sta_debugfs(struct sta_info *sta) | 89 | static inline void rate_control_add_sta_debugfs(struct sta_info *sta) |
@@ -130,31 +105,6 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) | |||
130 | #endif | 105 | #endif |
131 | } | 106 | } |
132 | 107 | ||
133 | static inline int rate_supported(struct sta_info *sta, | ||
134 | enum ieee80211_band band, | ||
135 | int index) | ||
136 | { | ||
137 | return (sta == NULL || sta->sta.supp_rates[band] & BIT(index)); | ||
138 | } | ||
139 | |||
140 | static inline s8 | ||
141 | rate_lowest_index(struct ieee80211_local *local, | ||
142 | struct ieee80211_supported_band *sband, | ||
143 | struct sta_info *sta) | ||
144 | { | ||
145 | int i; | ||
146 | |||
147 | for (i = 0; i < sband->n_bitrates; i++) | ||
148 | if (rate_supported(sta, sband->band, i)) | ||
149 | return i; | ||
150 | |||
151 | /* warn when we cannot find a rate. */ | ||
152 | WARN_ON(1); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | |||
158 | /* functions for rate control related to a device */ | 108 | /* functions for rate control related to a device */ |
159 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 109 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
160 | const char *name); | 110 | const char *name); |
diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h index ffafc5da572e..01d64d53f3b9 100644 --- a/net/mac80211/rc80211_pid.h +++ b/net/mac80211/rc80211_pid.h | |||
@@ -124,7 +124,6 @@ struct rc_pid_events_file_info { | |||
124 | * struct rc_pid_debugfs_entries - tunable parameters | 124 | * struct rc_pid_debugfs_entries - tunable parameters |
125 | * | 125 | * |
126 | * Algorithm parameters, tunable via debugfs. | 126 | * Algorithm parameters, tunable via debugfs. |
127 | * @dir: the debugfs directory for a specific phy | ||
128 | * @target: target percentage for failed frames | 127 | * @target: target percentage for failed frames |
129 | * @sampling_period: error sampling interval in milliseconds | 128 | * @sampling_period: error sampling interval in milliseconds |
130 | * @coeff_p: absolute value of the proportional coefficient | 129 | * @coeff_p: absolute value of the proportional coefficient |
@@ -143,7 +142,6 @@ struct rc_pid_events_file_info { | |||
143 | * ordering of rates) | 142 | * ordering of rates) |
144 | */ | 143 | */ |
145 | struct rc_pid_debugfs_entries { | 144 | struct rc_pid_debugfs_entries { |
146 | struct dentry *dir; | ||
147 | struct dentry *target; | 145 | struct dentry *target; |
148 | struct dentry *sampling_period; | 146 | struct dentry *sampling_period; |
149 | struct dentry *coeff_p; | 147 | struct dentry *coeff_p; |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index bc1c4569caa1..86eb374e3b87 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -68,18 +68,14 @@ | |||
68 | * exhibited a worse failed frames behaviour and we'll choose the highest rate | 68 | * exhibited a worse failed frames behaviour and we'll choose the highest rate |
69 | * whose failed frames behaviour is not worse than the one of the original rate | 69 | * whose failed frames behaviour is not worse than the one of the original rate |
70 | * target. While at it, check that the new rate is valid. */ | 70 | * target. While at it, check that the new rate is valid. */ |
71 | static void rate_control_pid_adjust_rate(struct ieee80211_local *local, | 71 | static void rate_control_pid_adjust_rate(struct ieee80211_supported_band *sband, |
72 | struct sta_info *sta, int adj, | 72 | struct ieee80211_sta *sta, |
73 | struct rc_pid_sta_info *spinfo, int adj, | ||
73 | struct rc_pid_rateinfo *rinfo) | 74 | struct rc_pid_rateinfo *rinfo) |
74 | { | 75 | { |
75 | struct ieee80211_sub_if_data *sdata; | ||
76 | struct ieee80211_supported_band *sband; | ||
77 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; | 76 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; |
78 | struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; | ||
79 | int cur = spinfo->txrate_idx; | 77 | int cur = spinfo->txrate_idx; |
80 | 78 | ||
81 | sdata = sta->sdata; | ||
82 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
83 | band = sband->band; | 79 | band = sband->band; |
84 | n_bitrates = sband->n_bitrates; | 80 | n_bitrates = sband->n_bitrates; |
85 | 81 | ||
@@ -146,13 +142,11 @@ static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l) | |||
146 | } | 142 | } |
147 | 143 | ||
148 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, | 144 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, |
149 | struct ieee80211_local *local, | 145 | struct ieee80211_supported_band *sband, |
150 | struct sta_info *sta) | 146 | struct ieee80211_sta *sta, |
147 | struct rc_pid_sta_info *spinfo) | ||
151 | { | 148 | { |
152 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
153 | struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; | ||
154 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; | 149 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; |
155 | struct ieee80211_supported_band *sband; | ||
156 | u32 pf; | 150 | u32 pf; |
157 | s32 err_avg; | 151 | s32 err_avg; |
158 | u32 err_prop; | 152 | u32 err_prop; |
@@ -161,9 +155,6 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
161 | int adj, i, j, tmp; | 155 | int adj, i, j, tmp; |
162 | unsigned long period; | 156 | unsigned long period; |
163 | 157 | ||
164 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
165 | spinfo = sta->rate_ctrl_priv; | ||
166 | |||
167 | /* In case nothing happened during the previous control interval, turn | 158 | /* In case nothing happened during the previous control interval, turn |
168 | * the sharpening factor on. */ | 159 | * the sharpening factor on. */ |
169 | period = (HZ * pinfo->sampling_period + 500) / 1000; | 160 | period = (HZ * pinfo->sampling_period + 500) / 1000; |
@@ -179,11 +170,15 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
179 | if (unlikely(spinfo->tx_num_xmit == 0)) | 170 | if (unlikely(spinfo->tx_num_xmit == 0)) |
180 | pf = spinfo->last_pf; | 171 | pf = spinfo->last_pf; |
181 | else { | 172 | else { |
173 | /* XXX: BAD HACK!!! */ | ||
174 | struct sta_info *si = container_of(sta, struct sta_info, sta); | ||
175 | |||
182 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; | 176 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; |
183 | if (ieee80211_vif_is_mesh(&sdata->vif) && pf == 100) | 177 | |
184 | mesh_plink_broken(sta); | 178 | if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100) |
179 | mesh_plink_broken(si); | ||
185 | pf <<= RC_PID_ARITH_SHIFT; | 180 | pf <<= RC_PID_ARITH_SHIFT; |
186 | sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) | 181 | si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) |
187 | >> RC_PID_ARITH_SHIFT; | 182 | >> RC_PID_ARITH_SHIFT; |
188 | } | 183 | } |
189 | 184 | ||
@@ -229,43 +224,25 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
229 | 224 | ||
230 | /* Change rate. */ | 225 | /* Change rate. */ |
231 | if (adj) | 226 | if (adj) |
232 | rate_control_pid_adjust_rate(local, sta, adj, rinfo); | 227 | rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo); |
233 | } | 228 | } |
234 | 229 | ||
235 | static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | 230 | static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_band *sband, |
231 | struct ieee80211_sta *sta, void *priv_sta, | ||
236 | struct sk_buff *skb) | 232 | struct sk_buff *skb) |
237 | { | 233 | { |
238 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
239 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
240 | struct ieee80211_sub_if_data *sdata; | ||
241 | struct rc_pid_info *pinfo = priv; | 234 | struct rc_pid_info *pinfo = priv; |
242 | struct sta_info *sta; | 235 | struct rc_pid_sta_info *spinfo = priv_sta; |
243 | struct rc_pid_sta_info *spinfo; | ||
244 | unsigned long period; | 236 | unsigned long period; |
245 | struct ieee80211_supported_band *sband; | ||
246 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 237 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
247 | 238 | ||
248 | rcu_read_lock(); | 239 | if (!spinfo) |
249 | 240 | return; | |
250 | sta = sta_info_get(local, hdr->addr1); | ||
251 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
252 | |||
253 | if (!sta) | ||
254 | goto unlock; | ||
255 | |||
256 | spinfo = sta->rate_ctrl_priv; | ||
257 | |||
258 | /* Don't update the state if we're not controlling the rate. */ | ||
259 | sdata = sta->sdata; | ||
260 | if (sdata->force_unicast_rateidx > -1) { | ||
261 | spinfo->txrate_idx = sdata->max_ratectrl_rateidx; | ||
262 | goto unlock; | ||
263 | } | ||
264 | 241 | ||
265 | /* Ignore all frames that were sent with a different rate than the rate | 242 | /* Ignore all frames that were sent with a different rate than the rate |
266 | * we currently advise mac80211 to use. */ | 243 | * we currently advise mac80211 to use. */ |
267 | if (info->tx_rate_idx != spinfo->txrate_idx) | 244 | if (info->tx_rate_idx != spinfo->txrate_idx) |
268 | goto unlock; | 245 | return; |
269 | 246 | ||
270 | spinfo->tx_num_xmit++; | 247 | spinfo->tx_num_xmit++; |
271 | 248 | ||
@@ -289,78 +266,63 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | |||
289 | if (!period) | 266 | if (!period) |
290 | period = 1; | 267 | period = 1; |
291 | if (time_after(jiffies, spinfo->last_sample + period)) | 268 | if (time_after(jiffies, spinfo->last_sample + period)) |
292 | rate_control_pid_sample(pinfo, local, sta); | 269 | rate_control_pid_sample(pinfo, sband, sta, spinfo); |
293 | |||
294 | unlock: | ||
295 | rcu_read_unlock(); | ||
296 | } | 270 | } |
297 | 271 | ||
298 | static void rate_control_pid_get_rate(void *priv, struct net_device *dev, | 272 | static void |
299 | struct ieee80211_supported_band *sband, | 273 | rate_control_pid_get_rate(void *priv, struct ieee80211_supported_band *sband, |
300 | struct sk_buff *skb, | 274 | struct ieee80211_sta *sta, void *priv_sta, |
301 | struct rate_selection *sel) | 275 | struct sk_buff *skb, |
276 | struct rate_selection *sel) | ||
302 | { | 277 | { |
303 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
304 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 278 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
305 | struct ieee80211_sub_if_data *sdata; | 279 | struct rc_pid_sta_info *spinfo = priv_sta; |
306 | struct rc_pid_sta_info *spinfo; | ||
307 | struct sta_info *sta; | ||
308 | int rateidx; | 280 | int rateidx; |
309 | u16 fc; | 281 | u16 fc; |
310 | 282 | ||
311 | rcu_read_lock(); | ||
312 | |||
313 | sta = sta_info_get(local, hdr->addr1); | ||
314 | |||
315 | /* Send management frames and broadcast/multicast data using lowest | 283 | /* Send management frames and broadcast/multicast data using lowest |
316 | * rate. */ | 284 | * rate. */ |
317 | fc = le16_to_cpu(hdr->frame_control); | 285 | fc = le16_to_cpu(hdr->frame_control); |
318 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | 286 | if (!sta || !spinfo || |
319 | is_multicast_ether_addr(hdr->addr1) || !sta) { | 287 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || |
320 | sel->rate_idx = rate_lowest_index(local, sband, sta); | 288 | is_multicast_ether_addr(hdr->addr1)) { |
321 | rcu_read_unlock(); | 289 | sel->rate_idx = rate_lowest_index(sband, sta); |
322 | return; | 290 | return; |
323 | } | 291 | } |
324 | 292 | ||
325 | /* If a forced rate is in effect, select it. */ | ||
326 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
327 | spinfo = (struct rc_pid_sta_info *)sta->rate_ctrl_priv; | ||
328 | if (sdata->force_unicast_rateidx > -1) | ||
329 | spinfo->txrate_idx = sdata->force_unicast_rateidx; | ||
330 | |||
331 | rateidx = spinfo->txrate_idx; | 293 | rateidx = spinfo->txrate_idx; |
332 | 294 | ||
333 | if (rateidx >= sband->n_bitrates) | 295 | if (rateidx >= sband->n_bitrates) |
334 | rateidx = sband->n_bitrates - 1; | 296 | rateidx = sband->n_bitrates - 1; |
335 | 297 | ||
336 | rcu_read_unlock(); | ||
337 | |||
338 | sel->rate_idx = rateidx; | 298 | sel->rate_idx = rateidx; |
339 | 299 | ||
340 | #ifdef CONFIG_MAC80211_DEBUGFS | 300 | #ifdef CONFIG_MAC80211_DEBUGFS |
341 | rate_control_pid_event_tx_rate( | 301 | rate_control_pid_event_tx_rate(&spinfo->events, |
342 | &((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events, | ||
343 | rateidx, sband->bitrates[rateidx].bitrate); | 302 | rateidx, sband->bitrates[rateidx].bitrate); |
344 | #endif | 303 | #endif |
345 | } | 304 | } |
346 | 305 | ||
347 | static void rate_control_pid_rate_init(void *priv, void *priv_sta, | 306 | static void |
348 | struct ieee80211_local *local, | 307 | rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, |
349 | struct sta_info *sta) | 308 | struct ieee80211_sta *sta, void *priv_sta) |
350 | { | 309 | { |
310 | struct rc_pid_sta_info *spinfo = priv_sta; | ||
311 | struct sta_info *si; | ||
312 | |||
351 | /* TODO: This routine should consider using RSSI from previous packets | 313 | /* TODO: This routine should consider using RSSI from previous packets |
352 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. | 314 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. |
353 | * Until that method is implemented, we will use the lowest supported | 315 | * Until that method is implemented, we will use the lowest supported |
354 | * rate as a workaround. */ | 316 | * rate as a workaround. */ |
355 | struct ieee80211_supported_band *sband; | ||
356 | struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; | ||
357 | 317 | ||
358 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 318 | spinfo->txrate_idx = rate_lowest_index(sband, sta); |
359 | spinfo->txrate_idx = rate_lowest_index(local, sband, sta); | 319 | /* HACK */ |
360 | sta->fail_avg = 0; | 320 | si = container_of(sta, struct sta_info, sta); |
321 | si->fail_avg = 0; | ||
361 | } | 322 | } |
362 | 323 | ||
363 | static void *rate_control_pid_alloc(struct ieee80211_local *local) | 324 | static void *rate_control_pid_alloc(struct ieee80211_hw *hw, |
325 | struct dentry *debugfsdir) | ||
364 | { | 326 | { |
365 | struct rc_pid_info *pinfo; | 327 | struct rc_pid_info *pinfo; |
366 | struct rc_pid_rateinfo *rinfo; | 328 | struct rc_pid_rateinfo *rinfo; |
@@ -371,7 +333,7 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) | |||
371 | struct rc_pid_debugfs_entries *de; | 333 | struct rc_pid_debugfs_entries *de; |
372 | #endif | 334 | #endif |
373 | 335 | ||
374 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 336 | sband = hw->wiphy->bands[hw->conf.channel->band]; |
375 | 337 | ||
376 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); | 338 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); |
377 | if (!pinfo) | 339 | if (!pinfo) |
@@ -426,30 +388,28 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) | |||
426 | 388 | ||
427 | #ifdef CONFIG_MAC80211_DEBUGFS | 389 | #ifdef CONFIG_MAC80211_DEBUGFS |
428 | de = &pinfo->dentries; | 390 | de = &pinfo->dentries; |
429 | de->dir = debugfs_create_dir("rc80211_pid", | ||
430 | local->hw.wiphy->debugfsdir); | ||
431 | de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, | 391 | de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, |
432 | de->dir, &pinfo->target); | 392 | debugfsdir, &pinfo->target); |
433 | de->sampling_period = debugfs_create_u32("sampling_period", | 393 | de->sampling_period = debugfs_create_u32("sampling_period", |
434 | S_IRUSR | S_IWUSR, de->dir, | 394 | S_IRUSR | S_IWUSR, debugfsdir, |
435 | &pinfo->sampling_period); | 395 | &pinfo->sampling_period); |
436 | de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, | 396 | de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, |
437 | de->dir, &pinfo->coeff_p); | 397 | debugfsdir, &pinfo->coeff_p); |
438 | de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, | 398 | de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, |
439 | de->dir, &pinfo->coeff_i); | 399 | debugfsdir, &pinfo->coeff_i); |
440 | de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, | 400 | de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, |
441 | de->dir, &pinfo->coeff_d); | 401 | debugfsdir, &pinfo->coeff_d); |
442 | de->smoothing_shift = debugfs_create_u32("smoothing_shift", | 402 | de->smoothing_shift = debugfs_create_u32("smoothing_shift", |
443 | S_IRUSR | S_IWUSR, de->dir, | 403 | S_IRUSR | S_IWUSR, debugfsdir, |
444 | &pinfo->smoothing_shift); | 404 | &pinfo->smoothing_shift); |
445 | de->sharpen_factor = debugfs_create_u32("sharpen_factor", | 405 | de->sharpen_factor = debugfs_create_u32("sharpen_factor", |
446 | S_IRUSR | S_IWUSR, de->dir, | 406 | S_IRUSR | S_IWUSR, debugfsdir, |
447 | &pinfo->sharpen_factor); | 407 | &pinfo->sharpen_factor); |
448 | de->sharpen_duration = debugfs_create_u32("sharpen_duration", | 408 | de->sharpen_duration = debugfs_create_u32("sharpen_duration", |
449 | S_IRUSR | S_IWUSR, de->dir, | 409 | S_IRUSR | S_IWUSR, debugfsdir, |
450 | &pinfo->sharpen_duration); | 410 | &pinfo->sharpen_duration); |
451 | de->norm_offset = debugfs_create_u32("norm_offset", | 411 | de->norm_offset = debugfs_create_u32("norm_offset", |
452 | S_IRUSR | S_IWUSR, de->dir, | 412 | S_IRUSR | S_IWUSR, debugfsdir, |
453 | &pinfo->norm_offset); | 413 | &pinfo->norm_offset); |
454 | #endif | 414 | #endif |
455 | 415 | ||
@@ -471,7 +431,6 @@ static void rate_control_pid_free(void *priv) | |||
471 | debugfs_remove(de->coeff_p); | 431 | debugfs_remove(de->coeff_p); |
472 | debugfs_remove(de->sampling_period); | 432 | debugfs_remove(de->sampling_period); |
473 | debugfs_remove(de->target); | 433 | debugfs_remove(de->target); |
474 | debugfs_remove(de->dir); | ||
475 | #endif | 434 | #endif |
476 | 435 | ||
477 | kfree(pinfo->rinfo); | 436 | kfree(pinfo->rinfo); |
@@ -482,7 +441,8 @@ static void rate_control_pid_clear(void *priv) | |||
482 | { | 441 | { |
483 | } | 442 | } |
484 | 443 | ||
485 | static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) | 444 | static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta, |
445 | gfp_t gfp) | ||
486 | { | 446 | { |
487 | struct rc_pid_sta_info *spinfo; | 447 | struct rc_pid_sta_info *spinfo; |
488 | 448 | ||
@@ -500,10 +460,10 @@ static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) | |||
500 | return spinfo; | 460 | return spinfo; |
501 | } | 461 | } |
502 | 462 | ||
503 | static void rate_control_pid_free_sta(void *priv, void *priv_sta) | 463 | static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta, |
464 | void *priv_sta) | ||
504 | { | 465 | { |
505 | struct rc_pid_sta_info *spinfo = priv_sta; | 466 | kfree(priv_sta); |
506 | kfree(spinfo); | ||
507 | } | 467 | } |
508 | 468 | ||
509 | static struct rate_control_ops mac80211_rcpid = { | 469 | static struct rate_control_ops mac80211_rcpid = { |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 92d898b901e9..c489865761bc 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -650,32 +650,28 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
650 | return result; | 650 | return result; |
651 | } | 651 | } |
652 | 652 | ||
653 | static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) | 653 | static void ap_sta_ps_start(struct sta_info *sta) |
654 | { | 654 | { |
655 | struct ieee80211_sub_if_data *sdata; | 655 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
656 | DECLARE_MAC_BUF(mac); | 656 | DECLARE_MAC_BUF(mac); |
657 | 657 | ||
658 | sdata = sta->sdata; | ||
659 | |||
660 | atomic_inc(&sdata->bss->num_sta_ps); | 658 | atomic_inc(&sdata->bss->num_sta_ps); |
661 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); | 659 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); |
662 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 660 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
663 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", | 661 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", |
664 | dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); | 662 | sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); |
665 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 663 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
666 | } | 664 | } |
667 | 665 | ||
668 | static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | 666 | static int ap_sta_ps_end(struct sta_info *sta) |
669 | { | 667 | { |
670 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 668 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
669 | struct ieee80211_local *local = sdata->local; | ||
671 | struct sk_buff *skb; | 670 | struct sk_buff *skb; |
672 | int sent = 0; | 671 | int sent = 0; |
673 | struct ieee80211_sub_if_data *sdata; | ||
674 | struct ieee80211_tx_info *info; | 672 | struct ieee80211_tx_info *info; |
675 | DECLARE_MAC_BUF(mac); | 673 | DECLARE_MAC_BUF(mac); |
676 | 674 | ||
677 | sdata = sta->sdata; | ||
678 | |||
679 | atomic_dec(&sdata->bss->num_sta_ps); | 675 | atomic_dec(&sdata->bss->num_sta_ps); |
680 | 676 | ||
681 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); | 677 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); |
@@ -685,7 +681,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
685 | 681 | ||
686 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 682 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
687 | printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", | 683 | printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", |
688 | dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); | 684 | sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); |
689 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 685 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
690 | 686 | ||
691 | /* Send all buffered frames to the station */ | 687 | /* Send all buffered frames to the station */ |
@@ -701,7 +697,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
701 | sent++; | 697 | sent++; |
702 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 698 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
703 | printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " | 699 | printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " |
704 | "since STA not sleeping anymore\n", dev->name, | 700 | "since STA not sleeping anymore\n", sdata->dev->name, |
705 | print_mac(mac, sta->sta.addr), sta->sta.aid); | 701 | print_mac(mac, sta->sta.addr), sta->sta.aid); |
706 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 702 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
707 | info->flags |= IEEE80211_TX_CTL_REQUEUE; | 703 | info->flags |= IEEE80211_TX_CTL_REQUEUE; |
@@ -715,7 +711,6 @@ static ieee80211_rx_result debug_noinline | |||
715 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | 711 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) |
716 | { | 712 | { |
717 | struct sta_info *sta = rx->sta; | 713 | struct sta_info *sta = rx->sta; |
718 | struct net_device *dev = rx->dev; | ||
719 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 714 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
720 | 715 | ||
721 | if (!sta) | 716 | if (!sta) |
@@ -757,10 +752,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
757 | * exchange sequence */ | 752 | * exchange sequence */ |
758 | if (test_sta_flags(sta, WLAN_STA_PS) && | 753 | if (test_sta_flags(sta, WLAN_STA_PS) && |
759 | !ieee80211_has_pm(hdr->frame_control)) | 754 | !ieee80211_has_pm(hdr->frame_control)) |
760 | rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); | 755 | rx->sent_ps_buffered += ap_sta_ps_end(sta); |
761 | else if (!test_sta_flags(sta, WLAN_STA_PS) && | 756 | else if (!test_sta_flags(sta, WLAN_STA_PS) && |
762 | ieee80211_has_pm(hdr->frame_control)) | 757 | ieee80211_has_pm(hdr->frame_control)) |
763 | ap_sta_ps_start(dev, sta); | 758 | ap_sta_ps_start(sta); |
764 | } | 759 | } |
765 | 760 | ||
766 | /* Drop data::nullfunc frames silently, since they are used only to | 761 | /* Drop data::nullfunc frames silently, since they are used only to |
@@ -1112,10 +1107,6 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1112 | 1107 | ||
1113 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1108 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1114 | 1109 | ||
1115 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
1116 | hdrlen += ieee80211_get_mesh_hdrlen( | ||
1117 | (struct ieee80211s_hdr *) (skb->data + hdrlen)); | ||
1118 | |||
1119 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet | 1110 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet |
1120 | * header | 1111 | * header |
1121 | * IEEE 802.11 address fields: | 1112 | * IEEE 802.11 address fields: |
@@ -1139,6 +1130,15 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1139 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && | 1130 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && |
1140 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) | 1131 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) |
1141 | return -1; | 1132 | return -1; |
1133 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
1134 | struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) | ||
1135 | (skb->data + hdrlen); | ||
1136 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | ||
1137 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { | ||
1138 | memcpy(dst, meshdr->eaddr1, ETH_ALEN); | ||
1139 | memcpy(src, meshdr->eaddr2, ETH_ALEN); | ||
1140 | } | ||
1141 | } | ||
1142 | break; | 1142 | break; |
1143 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): | 1143 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): |
1144 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | 1144 | if (sdata->vif.type != NL80211_IFTYPE_STATION || |
@@ -1398,6 +1398,25 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1398 | /* illegal frame */ | 1398 | /* illegal frame */ |
1399 | return RX_DROP_MONITOR; | 1399 | return RX_DROP_MONITOR; |
1400 | 1400 | ||
1401 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ | ||
1402 | struct ieee80211_sub_if_data *sdata; | ||
1403 | struct mesh_path *mppath; | ||
1404 | |||
1405 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1406 | rcu_read_lock(); | ||
1407 | mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); | ||
1408 | if (!mppath) { | ||
1409 | mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata); | ||
1410 | } else { | ||
1411 | spin_lock_bh(&mppath->state_lock); | ||
1412 | mppath->exp_time = jiffies; | ||
1413 | if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0) | ||
1414 | memcpy(mppath->mpp, hdr->addr4, ETH_ALEN); | ||
1415 | spin_unlock_bh(&mppath->state_lock); | ||
1416 | } | ||
1417 | rcu_read_unlock(); | ||
1418 | } | ||
1419 | |||
1401 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) | 1420 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) |
1402 | return RX_CONTINUE; | 1421 | return RX_CONTINUE; |
1403 | 1422 | ||
@@ -1538,7 +1557,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1538 | */ | 1557 | */ |
1539 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 1558 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
1540 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | 1559 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1541 | return RX_DROP_MONITOR; | 1560 | return RX_CONTINUE; |
1542 | 1561 | ||
1543 | switch (mgmt->u.action.category) { | 1562 | switch (mgmt->u.action.category) { |
1544 | case WLAN_CATEGORY_BACK: | 1563 | case WLAN_CATEGORY_BACK: |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d9774ac2e0f7..9b72d15bc8dc 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -93,8 +93,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
93 | } | 93 | } |
94 | 94 | ||
95 | /* protected by RCU */ | 95 | /* protected by RCU */ |
96 | static struct sta_info *__sta_info_find(struct ieee80211_local *local, | 96 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) |
97 | const u8 *addr) | ||
98 | { | 97 | { |
99 | struct sta_info *sta; | 98 | struct sta_info *sta; |
100 | 99 | ||
@@ -107,12 +106,6 @@ static struct sta_info *__sta_info_find(struct ieee80211_local *local, | |||
107 | return sta; | 106 | return sta; |
108 | } | 107 | } |
109 | 108 | ||
110 | struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr) | ||
111 | { | ||
112 | return __sta_info_find(local, addr); | ||
113 | } | ||
114 | EXPORT_SYMBOL(sta_info_get); | ||
115 | |||
116 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, | 109 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, |
117 | struct net_device *dev) | 110 | struct net_device *dev) |
118 | { | 111 | { |
@@ -146,7 +139,7 @@ static void __sta_info_free(struct ieee80211_local *local, | |||
146 | { | 139 | { |
147 | DECLARE_MAC_BUF(mbuf); | 140 | DECLARE_MAC_BUF(mbuf); |
148 | 141 | ||
149 | rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); | 142 | rate_control_free_sta(sta); |
150 | rate_control_put(sta->rate_ctrl); | 143 | rate_control_put(sta->rate_ctrl); |
151 | 144 | ||
152 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 145 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -244,7 +237,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
244 | 237 | ||
245 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); | 238 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); |
246 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, | 239 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, |
247 | gfp); | 240 | &sta->sta, gfp); |
248 | if (!sta->rate_ctrl_priv) { | 241 | if (!sta->rate_ctrl_priv) { |
249 | rate_control_put(sta->rate_ctrl); | 242 | rate_control_put(sta->rate_ctrl); |
250 | kfree(sta); | 243 | kfree(sta); |
@@ -308,7 +301,7 @@ int sta_info_insert(struct sta_info *sta) | |||
308 | 301 | ||
309 | spin_lock_irqsave(&local->sta_lock, flags); | 302 | spin_lock_irqsave(&local->sta_lock, flags); |
310 | /* check if STA exists already */ | 303 | /* check if STA exists already */ |
311 | if (__sta_info_find(local, sta->sta.addr)) { | 304 | if (sta_info_get(local, sta->sta.addr)) { |
312 | spin_unlock_irqrestore(&local->sta_lock, flags); | 305 | spin_unlock_irqrestore(&local->sta_lock, flags); |
313 | err = -EEXIST; | 306 | err = -EEXIST; |
314 | goto out_free; | 307 | goto out_free; |
@@ -834,7 +827,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
834 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, | 827 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, |
835 | const u8 *addr) | 828 | const u8 *addr) |
836 | { | 829 | { |
837 | struct sta_info *sta = __sta_info_find(hw_to_local(hw), addr); | 830 | struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); |
838 | 831 | ||
839 | if (!sta) | 832 | if (!sta) |
840 | return NULL; | 833 | return NULL; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index daedfa9e1c63..c3f436964621 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -416,7 +416,7 @@ static inline u32 get_sta_flags(struct sta_info *sta) | |||
416 | /* | 416 | /* |
417 | * Get a STA info, must have be under RCU read lock. | 417 | * Get a STA info, must have be under RCU read lock. |
418 | */ | 418 | */ |
419 | struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr); | 419 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr); |
420 | /* | 420 | /* |
421 | * Get STA info by index, BROKEN! | 421 | * Get STA info by index, BROKEN! |
422 | */ | 422 | */ |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 20d683641b42..0cc2e23f082c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -165,11 +165,10 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
165 | return cpu_to_le16(dur); | 165 | return cpu_to_le16(dur); |
166 | } | 166 | } |
167 | 167 | ||
168 | static int inline is_ieee80211_device(struct net_device *dev, | 168 | static int inline is_ieee80211_device(struct ieee80211_local *local, |
169 | struct net_device *master) | 169 | struct net_device *dev) |
170 | { | 170 | { |
171 | return (wdev_priv(dev->ieee80211_ptr) == | 171 | return local == wdev_priv(dev->ieee80211_ptr); |
172 | wdev_priv(master->ieee80211_ptr)); | ||
173 | } | 172 | } |
174 | 173 | ||
175 | /* tx handlers */ | 174 | /* tx handlers */ |
@@ -447,7 +446,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
447 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 446 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
448 | 447 | ||
449 | if (likely(tx->rate_idx < 0)) { | 448 | if (likely(tx->rate_idx < 0)) { |
450 | rate_control_get_rate(tx->dev, sband, tx->skb, &rsel); | 449 | rate_control_get_rate(tx->sdata, sband, tx->sta, |
450 | tx->skb, &rsel); | ||
451 | if (tx->sta) | 451 | if (tx->sta) |
452 | tx->sta->last_txrate_idx = rsel.rate_idx; | 452 | tx->sta->last_txrate_idx = rsel.rate_idx; |
453 | tx->rate_idx = rsel.rate_idx; | 453 | tx->rate_idx = rsel.rate_idx; |
@@ -1001,14 +1001,14 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1001 | /* | 1001 | /* |
1002 | * NB: @tx is uninitialised when passed in here | 1002 | * NB: @tx is uninitialised when passed in here |
1003 | */ | 1003 | */ |
1004 | static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | 1004 | static int ieee80211_tx_prepare(struct ieee80211_local *local, |
1005 | struct sk_buff *skb, | 1005 | struct ieee80211_tx_data *tx, |
1006 | struct net_device *mdev) | 1006 | struct sk_buff *skb) |
1007 | { | 1007 | { |
1008 | struct net_device *dev; | 1008 | struct net_device *dev; |
1009 | 1009 | ||
1010 | dev = dev_get_by_index(&init_net, skb->iif); | 1010 | dev = dev_get_by_index(&init_net, skb->iif); |
1011 | if (unlikely(dev && !is_ieee80211_device(dev, mdev))) { | 1011 | if (unlikely(dev && !is_ieee80211_device(local, dev))) { |
1012 | dev_put(dev); | 1012 | dev_put(dev); |
1013 | dev = NULL; | 1013 | dev = NULL; |
1014 | } | 1014 | } |
@@ -1258,6 +1258,8 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, | |||
1258 | int ieee80211_master_start_xmit(struct sk_buff *skb, | 1258 | int ieee80211_master_start_xmit(struct sk_buff *skb, |
1259 | struct net_device *dev) | 1259 | struct net_device *dev) |
1260 | { | 1260 | { |
1261 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
1262 | struct ieee80211_local *local = mpriv->local; | ||
1261 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1263 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1262 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1264 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1263 | struct net_device *odev = NULL; | 1265 | struct net_device *odev = NULL; |
@@ -1273,7 +1275,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1273 | 1275 | ||
1274 | if (skb->iif) | 1276 | if (skb->iif) |
1275 | odev = dev_get_by_index(&init_net, skb->iif); | 1277 | odev = dev_get_by_index(&init_net, skb->iif); |
1276 | if (unlikely(odev && !is_ieee80211_device(odev, dev))) { | 1278 | if (unlikely(odev && !is_ieee80211_device(local, odev))) { |
1277 | dev_put(odev); | 1279 | dev_put(odev); |
1278 | odev = NULL; | 1280 | odev = NULL; |
1279 | } | 1281 | } |
@@ -1449,8 +1451,8 @@ fail: | |||
1449 | int ieee80211_subif_start_xmit(struct sk_buff *skb, | 1451 | int ieee80211_subif_start_xmit(struct sk_buff *skb, |
1450 | struct net_device *dev) | 1452 | struct net_device *dev) |
1451 | { | 1453 | { |
1452 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1454 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1453 | struct ieee80211_sub_if_data *sdata; | 1455 | struct ieee80211_local *local = sdata->local; |
1454 | int ret = 1, head_need; | 1456 | int ret = 1, head_need; |
1455 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1457 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1456 | __le16 fc; | 1458 | __le16 fc; |
@@ -1462,7 +1464,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1462 | struct sta_info *sta; | 1464 | struct sta_info *sta; |
1463 | u32 sta_flags = 0; | 1465 | u32 sta_flags = 0; |
1464 | 1466 | ||
1465 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1466 | if (unlikely(skb->len < ETH_HLEN)) { | 1467 | if (unlikely(skb->len < ETH_HLEN)) { |
1467 | ret = 0; | 1468 | ret = 0; |
1468 | goto fail; | 1469 | goto fail; |
@@ -1498,18 +1499,50 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1498 | #ifdef CONFIG_MAC80211_MESH | 1499 | #ifdef CONFIG_MAC80211_MESH |
1499 | case NL80211_IFTYPE_MESH_POINT: | 1500 | case NL80211_IFTYPE_MESH_POINT: |
1500 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1501 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1501 | /* RA TA DA SA */ | ||
1502 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1503 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1504 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1505 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | ||
1506 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { | 1502 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { |
1507 | /* Do not send frames with mesh_ttl == 0 */ | 1503 | /* Do not send frames with mesh_ttl == 0 */ |
1508 | sdata->u.mesh.mshstats.dropped_frames_ttl++; | 1504 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
1509 | ret = 0; | 1505 | ret = 0; |
1510 | goto fail; | 1506 | goto fail; |
1511 | } | 1507 | } |
1512 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | 1508 | memset(&mesh_hdr, 0, sizeof(mesh_hdr)); |
1509 | |||
1510 | if (compare_ether_addr(dev->dev_addr, | ||
1511 | skb->data + ETH_ALEN) == 0) { | ||
1512 | /* RA TA DA SA */ | ||
1513 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1514 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1515 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1516 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | ||
1517 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | ||
1518 | } else { | ||
1519 | /* packet from other interface */ | ||
1520 | struct mesh_path *mppath; | ||
1521 | |||
1522 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1523 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1524 | memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN); | ||
1525 | |||
1526 | if (is_multicast_ether_addr(skb->data)) | ||
1527 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1528 | else { | ||
1529 | rcu_read_lock(); | ||
1530 | mppath = mpp_path_lookup(skb->data, sdata); | ||
1531 | if (mppath) | ||
1532 | memcpy(hdr.addr3, mppath->mpp, ETH_ALEN); | ||
1533 | else | ||
1534 | memset(hdr.addr3, 0xff, ETH_ALEN); | ||
1535 | rcu_read_unlock(); | ||
1536 | } | ||
1537 | |||
1538 | mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6; | ||
1539 | mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | ||
1540 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum); | ||
1541 | memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN); | ||
1542 | memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN); | ||
1543 | sdata->u.mesh.mesh_seqnum++; | ||
1544 | meshhdrlen = 18; | ||
1545 | } | ||
1513 | hdrlen = 30; | 1546 | hdrlen = 30; |
1514 | break; | 1547 | break; |
1515 | #endif | 1548 | #endif |
@@ -1923,7 +1956,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1923 | skb->do_not_encrypt = 1; | 1956 | skb->do_not_encrypt = 1; |
1924 | 1957 | ||
1925 | info->band = band; | 1958 | info->band = band; |
1926 | rate_control_get_rate(local->mdev, sband, skb, &rsel); | 1959 | rate_control_get_rate(sdata, sband, NULL, skb, &rsel); |
1927 | 1960 | ||
1928 | if (unlikely(rsel.rate_idx < 0)) { | 1961 | if (unlikely(rsel.rate_idx < 0)) { |
1929 | if (net_ratelimit()) { | 1962 | if (net_ratelimit()) { |
@@ -2032,7 +2065,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2032 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 2065 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
2033 | } | 2066 | } |
2034 | 2067 | ||
2035 | if (!ieee80211_tx_prepare(&tx, skb, local->mdev)) | 2068 | if (!ieee80211_tx_prepare(local, &tx, skb)) |
2036 | break; | 2069 | break; |
2037 | dev_kfree_skb_any(skb); | 2070 | dev_kfree_skb_any(skb); |
2038 | } | 2071 | } |
diff --git a/net/wireless/core.c b/net/wireless/core.c index a910cd2d0fd1..5cadbeb76a14 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -29,113 +29,11 @@ MODULE_AUTHOR("Johannes Berg"); | |||
29 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
30 | MODULE_DESCRIPTION("wireless configuration support"); | 30 | MODULE_DESCRIPTION("wireless configuration support"); |
31 | 31 | ||
32 | struct list_head regulatory_requests; | ||
33 | |||
34 | /* Central wireless core regulatory domains, we only need two, | ||
35 | * the current one and a world regulatory domain in case we have no | ||
36 | * information to give us an alpha2 */ | ||
37 | struct ieee80211_regdomain *cfg80211_regdomain; | ||
38 | |||
39 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | ||
40 | const struct ieee80211_regdomain world_regdom = { | ||
41 | .n_reg_rules = 1, | ||
42 | .alpha2 = "00", | ||
43 | .reg_rules = { | ||
44 | REG_RULE(2402, 2472, 40, 6, 20, | ||
45 | NL80211_RRF_PASSIVE_SCAN | | ||
46 | NL80211_RRF_NO_IBSS), | ||
47 | } | ||
48 | }; | ||
49 | |||
50 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
51 | /* All this fucking static junk will be removed soon, so | ||
52 | * don't fucking count on it !@#$ */ | ||
53 | |||
54 | static char *ieee80211_regdom = "US"; | ||
55 | module_param(ieee80211_regdom, charp, 0444); | ||
56 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | ||
57 | |||
58 | /* We assume 40 MHz bandwidth for the old regulatory work. | ||
59 | * We make emphasis we are using the exact same frequencies | ||
60 | * as before */ | ||
61 | |||
62 | const struct ieee80211_regdomain us_regdom = { | ||
63 | .n_reg_rules = 6, | ||
64 | .alpha2 = "US", | ||
65 | .reg_rules = { | ||
66 | /* IEEE 802.11b/g, channels 1..11 */ | ||
67 | REG_RULE(2412-20, 2462+20, 40, 6, 27, 0), | ||
68 | /* IEEE 802.11a, channel 36 */ | ||
69 | REG_RULE(5180-20, 5180+20, 40, 6, 23, 0), | ||
70 | /* IEEE 802.11a, channel 40 */ | ||
71 | REG_RULE(5200-20, 5200+20, 40, 6, 23, 0), | ||
72 | /* IEEE 802.11a, channel 44 */ | ||
73 | REG_RULE(5220-20, 5220+20, 40, 6, 23, 0), | ||
74 | /* IEEE 802.11a, channels 48..64 */ | ||
75 | REG_RULE(5240-20, 5320+20, 40, 6, 23, 0), | ||
76 | /* IEEE 802.11a, channels 149..165, outdoor */ | ||
77 | REG_RULE(5745-20, 5825+20, 40, 6, 30, 0), | ||
78 | } | ||
79 | }; | ||
80 | |||
81 | const struct ieee80211_regdomain jp_regdom = { | ||
82 | .n_reg_rules = 3, | ||
83 | .alpha2 = "JP", | ||
84 | .reg_rules = { | ||
85 | /* IEEE 802.11b/g, channels 1..14 */ | ||
86 | REG_RULE(2412-20, 2484+20, 40, 6, 20, 0), | ||
87 | /* IEEE 802.11a, channels 34..48 */ | ||
88 | REG_RULE(5170-20, 5240+20, 40, 6, 20, | ||
89 | NL80211_RRF_PASSIVE_SCAN), | ||
90 | /* IEEE 802.11a, channels 52..64 */ | ||
91 | REG_RULE(5260-20, 5320+20, 40, 6, 20, | ||
92 | NL80211_RRF_NO_IBSS | | ||
93 | NL80211_RRF_DFS), | ||
94 | } | ||
95 | }; | ||
96 | |||
97 | const struct ieee80211_regdomain eu_regdom = { | ||
98 | .n_reg_rules = 6, | ||
99 | /* This alpha2 is bogus, we leave it here just for stupid | ||
100 | * backward compatibility */ | ||
101 | .alpha2 = "EU", | ||
102 | .reg_rules = { | ||
103 | /* IEEE 802.11b/g, channels 1..13 */ | ||
104 | REG_RULE(2412-20, 2472+20, 40, 6, 20, 0), | ||
105 | /* IEEE 802.11a, channel 36 */ | ||
106 | REG_RULE(5180-20, 5180+20, 40, 6, 23, | ||
107 | NL80211_RRF_PASSIVE_SCAN), | ||
108 | /* IEEE 802.11a, channel 40 */ | ||
109 | REG_RULE(5200-20, 5200+20, 40, 6, 23, | ||
110 | NL80211_RRF_PASSIVE_SCAN), | ||
111 | /* IEEE 802.11a, channel 44 */ | ||
112 | REG_RULE(5220-20, 5220+20, 40, 6, 23, | ||
113 | NL80211_RRF_PASSIVE_SCAN), | ||
114 | /* IEEE 802.11a, channels 48..64 */ | ||
115 | REG_RULE(5240-20, 5320+20, 40, 6, 20, | ||
116 | NL80211_RRF_NO_IBSS | | ||
117 | NL80211_RRF_DFS), | ||
118 | /* IEEE 802.11a, channels 100..140 */ | ||
119 | REG_RULE(5500-20, 5700+20, 40, 6, 30, | ||
120 | NL80211_RRF_NO_IBSS | | ||
121 | NL80211_RRF_DFS), | ||
122 | } | ||
123 | }; | ||
124 | |||
125 | #endif | ||
126 | |||
127 | struct ieee80211_regdomain *cfg80211_world_regdom = | ||
128 | (struct ieee80211_regdomain *) &world_regdom; | ||
129 | |||
130 | LIST_HEAD(regulatory_requests); | ||
131 | DEFINE_MUTEX(cfg80211_reg_mutex); | ||
132 | |||
133 | /* RCU might be appropriate here since we usually | 32 | /* RCU might be appropriate here since we usually |
134 | * only read the list, and that can happen quite | 33 | * only read the list, and that can happen quite |
135 | * often because we need to do it for each command */ | 34 | * often because we need to do it for each command */ |
136 | LIST_HEAD(cfg80211_drv_list); | 35 | LIST_HEAD(cfg80211_drv_list); |
137 | DEFINE_MUTEX(cfg80211_drv_mutex); | 36 | DEFINE_MUTEX(cfg80211_drv_mutex); |
138 | static int wiphy_counter; | ||
139 | 37 | ||
140 | /* for debugfs */ | 38 | /* for debugfs */ |
141 | static struct dentry *ieee80211_debugfs_dir; | 39 | static struct dentry *ieee80211_debugfs_dir; |
@@ -307,6 +205,8 @@ out_unlock: | |||
307 | 205 | ||
308 | struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) | 206 | struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) |
309 | { | 207 | { |
208 | static int wiphy_counter; | ||
209 | |||
310 | struct cfg80211_registered_device *drv; | 210 | struct cfg80211_registered_device *drv; |
311 | int alloc_size; | 211 | int alloc_size; |
312 | 212 | ||
@@ -323,21 +223,18 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) | |||
323 | 223 | ||
324 | mutex_lock(&cfg80211_drv_mutex); | 224 | mutex_lock(&cfg80211_drv_mutex); |
325 | 225 | ||
326 | drv->idx = wiphy_counter; | 226 | drv->idx = wiphy_counter++; |
327 | |||
328 | /* now increase counter for the next device unless | ||
329 | * it has wrapped previously */ | ||
330 | if (wiphy_counter >= 0) | ||
331 | wiphy_counter++; | ||
332 | |||
333 | mutex_unlock(&cfg80211_drv_mutex); | ||
334 | 227 | ||
335 | if (unlikely(drv->idx < 0)) { | 228 | if (unlikely(drv->idx < 0)) { |
229 | wiphy_counter--; | ||
230 | mutex_unlock(&cfg80211_drv_mutex); | ||
336 | /* ugh, wrapped! */ | 231 | /* ugh, wrapped! */ |
337 | kfree(drv); | 232 | kfree(drv); |
338 | return NULL; | 233 | return NULL; |
339 | } | 234 | } |
340 | 235 | ||
236 | mutex_unlock(&cfg80211_drv_mutex); | ||
237 | |||
341 | /* give it a proper name */ | 238 | /* give it a proper name */ |
342 | snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE, | 239 | snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE, |
343 | PHY_NAME "%d", drv->idx); | 240 | PHY_NAME "%d", drv->idx); |
@@ -485,6 +382,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
485 | 382 | ||
486 | rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); | 383 | rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); |
487 | 384 | ||
385 | WARN_ON(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_UNSPECIFIED); | ||
386 | |||
488 | switch (state) { | 387 | switch (state) { |
489 | case NETDEV_REGISTER: | 388 | case NETDEV_REGISTER: |
490 | mutex_lock(&rdev->devlist_mtx); | 389 | mutex_lock(&rdev->devlist_mtx); |
@@ -514,34 +413,10 @@ static struct notifier_block cfg80211_netdev_notifier = { | |||
514 | .notifier_call = cfg80211_netdev_notifier_call, | 413 | .notifier_call = cfg80211_netdev_notifier_call, |
515 | }; | 414 | }; |
516 | 415 | ||
517 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
518 | const struct ieee80211_regdomain *static_regdom(char *alpha2) | ||
519 | { | ||
520 | if (alpha2[0] == 'U' && alpha2[1] == 'S') | ||
521 | return &us_regdom; | ||
522 | if (alpha2[0] == 'J' && alpha2[1] == 'P') | ||
523 | return &jp_regdom; | ||
524 | if (alpha2[0] == 'E' && alpha2[1] == 'U') | ||
525 | return &eu_regdom; | ||
526 | /* Default, as per the old rules */ | ||
527 | return &us_regdom; | ||
528 | } | ||
529 | #endif | ||
530 | |||
531 | static int cfg80211_init(void) | 416 | static int cfg80211_init(void) |
532 | { | 417 | { |
533 | int err; | 418 | int err; |
534 | 419 | ||
535 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
536 | cfg80211_regdomain = | ||
537 | (struct ieee80211_regdomain *) static_regdom(ieee80211_regdom); | ||
538 | /* Used during reset_regdomains_static() */ | ||
539 | cfg80211_world_regdom = cfg80211_regdomain; | ||
540 | #else | ||
541 | cfg80211_regdomain = | ||
542 | (struct ieee80211_regdomain *) cfg80211_world_regdom; | ||
543 | #endif | ||
544 | |||
545 | err = wiphy_sysfs_init(); | 420 | err = wiphy_sysfs_init(); |
546 | if (err) | 421 | if (err) |
547 | goto out_fail_sysfs; | 422 | goto out_fail_sysfs; |
@@ -560,25 +435,6 @@ static int cfg80211_init(void) | |||
560 | if (err) | 435 | if (err) |
561 | goto out_fail_reg; | 436 | goto out_fail_reg; |
562 | 437 | ||
563 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
564 | printk(KERN_INFO "cfg80211: Using old static regulatory domain:\n"); | ||
565 | print_regdomain_info(cfg80211_regdomain); | ||
566 | /* The old code still requests for a new regdomain and if | ||
567 | * you have CRDA you get it updated, otherwise you get | ||
568 | * stuck with the static values. We ignore "EU" code as | ||
569 | * that is not a valid ISO / IEC 3166 alpha2 */ | ||
570 | if (ieee80211_regdom[0] != 'E' && | ||
571 | ieee80211_regdom[1] != 'U') | ||
572 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, | ||
573 | ieee80211_regdom, NULL); | ||
574 | #else | ||
575 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); | ||
576 | if (err) | ||
577 | printk(KERN_ERR "cfg80211: calling CRDA failed - " | ||
578 | "unable to update world regulatory domain, " | ||
579 | "using static definition\n"); | ||
580 | #endif | ||
581 | |||
582 | return 0; | 438 | return 0; |
583 | 439 | ||
584 | out_fail_reg: | 440 | out_fail_reg: |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1221d726ed50..572793c8c7ab 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -299,7 +299,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
299 | 299 | ||
300 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | 300 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
301 | NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); | 301 | NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); |
302 | /* TODO: interface type */ | 302 | NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); |
303 | return genlmsg_end(msg, hdr); | 303 | return genlmsg_end(msg, hdr); |
304 | 304 | ||
305 | nla_put_failure: | 305 | nla_put_failure: |
@@ -418,41 +418,56 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
418 | int err, ifindex; | 418 | int err, ifindex; |
419 | enum nl80211_iftype type; | 419 | enum nl80211_iftype type; |
420 | struct net_device *dev; | 420 | struct net_device *dev; |
421 | u32 flags; | 421 | u32 _flags, *flags = NULL; |
422 | 422 | ||
423 | memset(¶ms, 0, sizeof(params)); | 423 | memset(¶ms, 0, sizeof(params)); |
424 | 424 | ||
425 | if (info->attrs[NL80211_ATTR_IFTYPE]) { | ||
426 | type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); | ||
427 | if (type > NL80211_IFTYPE_MAX) | ||
428 | return -EINVAL; | ||
429 | } else | ||
430 | return -EINVAL; | ||
431 | |||
432 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 425 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
433 | if (err) | 426 | if (err) |
434 | return err; | 427 | return err; |
435 | ifindex = dev->ifindex; | 428 | ifindex = dev->ifindex; |
429 | type = dev->ieee80211_ptr->iftype; | ||
436 | dev_put(dev); | 430 | dev_put(dev); |
437 | 431 | ||
432 | err = -EINVAL; | ||
433 | if (info->attrs[NL80211_ATTR_IFTYPE]) { | ||
434 | type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); | ||
435 | if (type > NL80211_IFTYPE_MAX) | ||
436 | goto unlock; | ||
437 | } | ||
438 | |||
438 | if (!drv->ops->change_virtual_intf || | 439 | if (!drv->ops->change_virtual_intf || |
439 | !(drv->wiphy.interface_modes & (1 << type))) { | 440 | !(drv->wiphy.interface_modes & (1 << type))) { |
440 | err = -EOPNOTSUPP; | 441 | err = -EOPNOTSUPP; |
441 | goto unlock; | 442 | goto unlock; |
442 | } | 443 | } |
443 | 444 | ||
444 | if (type == NL80211_IFTYPE_MESH_POINT && | 445 | if (info->attrs[NL80211_ATTR_MESH_ID]) { |
445 | info->attrs[NL80211_ATTR_MESH_ID]) { | 446 | if (type != NL80211_IFTYPE_MESH_POINT) { |
447 | err = -EINVAL; | ||
448 | goto unlock; | ||
449 | } | ||
446 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); | 450 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); |
447 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); | 451 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); |
448 | } | 452 | } |
449 | 453 | ||
454 | if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { | ||
455 | if (type != NL80211_IFTYPE_MONITOR) { | ||
456 | err = -EINVAL; | ||
457 | goto unlock; | ||
458 | } | ||
459 | err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], | ||
460 | &_flags); | ||
461 | if (!err) | ||
462 | flags = &_flags; | ||
463 | } | ||
450 | rtnl_lock(); | 464 | rtnl_lock(); |
451 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? | ||
452 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, | ||
453 | &flags); | ||
454 | err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, | 465 | err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, |
455 | type, err ? NULL : &flags, ¶ms); | 466 | type, flags, ¶ms); |
467 | |||
468 | dev = __dev_get_by_index(&init_net, ifindex); | ||
469 | WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); | ||
470 | |||
456 | rtnl_unlock(); | 471 | rtnl_unlock(); |
457 | 472 | ||
458 | unlock: | 473 | unlock: |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 592b2e391d42..626dbb688499 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -42,6 +42,18 @@ | |||
42 | #include "core.h" | 42 | #include "core.h" |
43 | #include "reg.h" | 43 | #include "reg.h" |
44 | 44 | ||
45 | /* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */ | ||
46 | struct regulatory_request { | ||
47 | struct list_head list; | ||
48 | struct wiphy *wiphy; | ||
49 | int granted; | ||
50 | enum reg_set_by initiator; | ||
51 | char alpha2[2]; | ||
52 | }; | ||
53 | |||
54 | static LIST_HEAD(regulatory_requests); | ||
55 | DEFINE_MUTEX(cfg80211_reg_mutex); | ||
56 | |||
45 | /* To trigger userspace events */ | 57 | /* To trigger userspace events */ |
46 | static struct platform_device *reg_pdev; | 58 | static struct platform_device *reg_pdev; |
47 | 59 | ||
@@ -51,7 +63,156 @@ static u32 supported_bandwidths[] = { | |||
51 | MHZ_TO_KHZ(20), | 63 | MHZ_TO_KHZ(20), |
52 | }; | 64 | }; |
53 | 65 | ||
54 | bool is_world_regdom(char *alpha2) | 66 | static struct list_head regulatory_requests; |
67 | |||
68 | /* Central wireless core regulatory domains, we only need two, | ||
69 | * the current one and a world regulatory domain in case we have no | ||
70 | * information to give us an alpha2 */ | ||
71 | static const struct ieee80211_regdomain *cfg80211_regdomain; | ||
72 | |||
73 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | ||
74 | static const struct ieee80211_regdomain world_regdom = { | ||
75 | .n_reg_rules = 1, | ||
76 | .alpha2 = "00", | ||
77 | .reg_rules = { | ||
78 | REG_RULE(2412-10, 2462+10, 40, 6, 20, | ||
79 | NL80211_RRF_PASSIVE_SCAN | | ||
80 | NL80211_RRF_NO_IBSS), | ||
81 | } | ||
82 | }; | ||
83 | |||
84 | static const struct ieee80211_regdomain *cfg80211_world_regdom = | ||
85 | &world_regdom; | ||
86 | |||
87 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
88 | static char *ieee80211_regdom = "US"; | ||
89 | module_param(ieee80211_regdom, charp, 0444); | ||
90 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | ||
91 | |||
92 | /* We assume 40 MHz bandwidth for the old regulatory work. | ||
93 | * We make emphasis we are using the exact same frequencies | ||
94 | * as before */ | ||
95 | |||
96 | static const struct ieee80211_regdomain us_regdom = { | ||
97 | .n_reg_rules = 6, | ||
98 | .alpha2 = "US", | ||
99 | .reg_rules = { | ||
100 | /* IEEE 802.11b/g, channels 1..11 */ | ||
101 | REG_RULE(2412-10, 2462+10, 40, 6, 27, 0), | ||
102 | /* IEEE 802.11a, channel 36 */ | ||
103 | REG_RULE(5180-10, 5180+10, 40, 6, 23, 0), | ||
104 | /* IEEE 802.11a, channel 40 */ | ||
105 | REG_RULE(5200-10, 5200+10, 40, 6, 23, 0), | ||
106 | /* IEEE 802.11a, channel 44 */ | ||
107 | REG_RULE(5220-10, 5220+10, 40, 6, 23, 0), | ||
108 | /* IEEE 802.11a, channels 48..64 */ | ||
109 | REG_RULE(5240-10, 5320+10, 40, 6, 23, 0), | ||
110 | /* IEEE 802.11a, channels 149..165, outdoor */ | ||
111 | REG_RULE(5745-10, 5825+10, 40, 6, 30, 0), | ||
112 | } | ||
113 | }; | ||
114 | |||
115 | static const struct ieee80211_regdomain jp_regdom = { | ||
116 | .n_reg_rules = 3, | ||
117 | .alpha2 = "JP", | ||
118 | .reg_rules = { | ||
119 | /* IEEE 802.11b/g, channels 1..14 */ | ||
120 | REG_RULE(2412-10, 2484+10, 40, 6, 20, 0), | ||
121 | /* IEEE 802.11a, channels 34..48 */ | ||
122 | REG_RULE(5170-10, 5240+10, 40, 6, 20, | ||
123 | NL80211_RRF_PASSIVE_SCAN), | ||
124 | /* IEEE 802.11a, channels 52..64 */ | ||
125 | REG_RULE(5260-10, 5320+10, 40, 6, 20, | ||
126 | NL80211_RRF_NO_IBSS | | ||
127 | NL80211_RRF_DFS), | ||
128 | } | ||
129 | }; | ||
130 | |||
131 | static const struct ieee80211_regdomain eu_regdom = { | ||
132 | .n_reg_rules = 6, | ||
133 | /* This alpha2 is bogus, we leave it here just for stupid | ||
134 | * backward compatibility */ | ||
135 | .alpha2 = "EU", | ||
136 | .reg_rules = { | ||
137 | /* IEEE 802.11b/g, channels 1..13 */ | ||
138 | REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), | ||
139 | /* IEEE 802.11a, channel 36 */ | ||
140 | REG_RULE(5180-10, 5180+10, 40, 6, 23, | ||
141 | NL80211_RRF_PASSIVE_SCAN), | ||
142 | /* IEEE 802.11a, channel 40 */ | ||
143 | REG_RULE(5200-10, 5200+10, 40, 6, 23, | ||
144 | NL80211_RRF_PASSIVE_SCAN), | ||
145 | /* IEEE 802.11a, channel 44 */ | ||
146 | REG_RULE(5220-10, 5220+10, 40, 6, 23, | ||
147 | NL80211_RRF_PASSIVE_SCAN), | ||
148 | /* IEEE 802.11a, channels 48..64 */ | ||
149 | REG_RULE(5240-10, 5320+10, 40, 6, 20, | ||
150 | NL80211_RRF_NO_IBSS | | ||
151 | NL80211_RRF_DFS), | ||
152 | /* IEEE 802.11a, channels 100..140 */ | ||
153 | REG_RULE(5500-10, 5700+10, 40, 6, 30, | ||
154 | NL80211_RRF_NO_IBSS | | ||
155 | NL80211_RRF_DFS), | ||
156 | } | ||
157 | }; | ||
158 | |||
159 | static const struct ieee80211_regdomain *static_regdom(char *alpha2) | ||
160 | { | ||
161 | if (alpha2[0] == 'U' && alpha2[1] == 'S') | ||
162 | return &us_regdom; | ||
163 | if (alpha2[0] == 'J' && alpha2[1] == 'P') | ||
164 | return &jp_regdom; | ||
165 | if (alpha2[0] == 'E' && alpha2[1] == 'U') | ||
166 | return &eu_regdom; | ||
167 | /* Default, as per the old rules */ | ||
168 | return &us_regdom; | ||
169 | } | ||
170 | |||
171 | static bool is_old_static_regdom(const struct ieee80211_regdomain *rd) | ||
172 | { | ||
173 | if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom) | ||
174 | return true; | ||
175 | return false; | ||
176 | } | ||
177 | #else | ||
178 | static inline bool is_old_static_regdom(const struct ieee80211_regdomain *rd) | ||
179 | { | ||
180 | return false; | ||
181 | } | ||
182 | #endif | ||
183 | |||
184 | static void reset_regdomains(void) | ||
185 | { | ||
186 | /* avoid freeing static information or freeing something twice */ | ||
187 | if (cfg80211_regdomain == cfg80211_world_regdom) | ||
188 | cfg80211_regdomain = NULL; | ||
189 | if (cfg80211_world_regdom == &world_regdom) | ||
190 | cfg80211_world_regdom = NULL; | ||
191 | if (cfg80211_regdomain == &world_regdom) | ||
192 | cfg80211_regdomain = NULL; | ||
193 | if (is_old_static_regdom(cfg80211_regdomain)) | ||
194 | cfg80211_regdomain = NULL; | ||
195 | |||
196 | kfree(cfg80211_regdomain); | ||
197 | kfree(cfg80211_world_regdom); | ||
198 | |||
199 | cfg80211_world_regdom = &world_regdom; | ||
200 | cfg80211_regdomain = NULL; | ||
201 | } | ||
202 | |||
203 | /* Dynamic world regulatory domain requested by the wireless | ||
204 | * core upon initialization */ | ||
205 | static void update_world_regdomain(const struct ieee80211_regdomain *rd) | ||
206 | { | ||
207 | BUG_ON(list_empty(®ulatory_requests)); | ||
208 | |||
209 | reset_regdomains(); | ||
210 | |||
211 | cfg80211_world_regdom = rd; | ||
212 | cfg80211_regdomain = rd; | ||
213 | } | ||
214 | |||
215 | bool is_world_regdom(const char *alpha2) | ||
55 | { | 216 | { |
56 | if (!alpha2) | 217 | if (!alpha2) |
57 | return false; | 218 | return false; |
@@ -60,7 +221,7 @@ bool is_world_regdom(char *alpha2) | |||
60 | return false; | 221 | return false; |
61 | } | 222 | } |
62 | 223 | ||
63 | static bool is_alpha2_set(char *alpha2) | 224 | static bool is_alpha2_set(const char *alpha2) |
64 | { | 225 | { |
65 | if (!alpha2) | 226 | if (!alpha2) |
66 | return false; | 227 | return false; |
@@ -77,7 +238,7 @@ static bool is_alpha_upper(char letter) | |||
77 | return false; | 238 | return false; |
78 | } | 239 | } |
79 | 240 | ||
80 | static bool is_unknown_alpha2(char *alpha2) | 241 | static bool is_unknown_alpha2(const char *alpha2) |
81 | { | 242 | { |
82 | if (!alpha2) | 243 | if (!alpha2) |
83 | return false; | 244 | return false; |
@@ -88,7 +249,7 @@ static bool is_unknown_alpha2(char *alpha2) | |||
88 | return false; | 249 | return false; |
89 | } | 250 | } |
90 | 251 | ||
91 | static bool is_an_alpha2(char *alpha2) | 252 | static bool is_an_alpha2(const char *alpha2) |
92 | { | 253 | { |
93 | if (!alpha2) | 254 | if (!alpha2) |
94 | return false; | 255 | return false; |
@@ -97,7 +258,7 @@ static bool is_an_alpha2(char *alpha2) | |||
97 | return false; | 258 | return false; |
98 | } | 259 | } |
99 | 260 | ||
100 | static bool alpha2_equal(char *alpha2_x, char *alpha2_y) | 261 | static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y) |
101 | { | 262 | { |
102 | if (!alpha2_x || !alpha2_y) | 263 | if (!alpha2_x || !alpha2_y) |
103 | return false; | 264 | return false; |
@@ -107,7 +268,7 @@ static bool alpha2_equal(char *alpha2_x, char *alpha2_y) | |||
107 | return false; | 268 | return false; |
108 | } | 269 | } |
109 | 270 | ||
110 | static bool regdom_changed(char *alpha2) | 271 | static bool regdom_changed(const char *alpha2) |
111 | { | 272 | { |
112 | if (!cfg80211_regdomain) | 273 | if (!cfg80211_regdomain) |
113 | return true; | 274 | return true; |
@@ -130,12 +291,8 @@ static int call_crda(const char *alpha2) | |||
130 | printk(KERN_INFO "cfg80211: Calling CRDA for country: %c%c\n", | 291 | printk(KERN_INFO "cfg80211: Calling CRDA for country: %c%c\n", |
131 | alpha2[0], alpha2[1]); | 292 | alpha2[0], alpha2[1]); |
132 | else | 293 | else |
133 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
134 | return -EINVAL; | ||
135 | #else | ||
136 | printk(KERN_INFO "cfg80211: Calling CRDA to update world " | 294 | printk(KERN_INFO "cfg80211: Calling CRDA to update world " |
137 | "regulatory domain\n"); | 295 | "regulatory domain\n"); |
138 | #endif | ||
139 | 296 | ||
140 | country_env[8] = alpha2[0]; | 297 | country_env[8] = alpha2[0]; |
141 | country_env[9] = alpha2[1]; | 298 | country_env[9] = alpha2[1]; |
@@ -238,7 +395,7 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, | |||
238 | } | 395 | } |
239 | } | 396 | } |
240 | 397 | ||
241 | static bool __reg_is_valid_request(char *alpha2, | 398 | static bool __reg_is_valid_request(const char *alpha2, |
242 | struct regulatory_request **request) | 399 | struct regulatory_request **request) |
243 | { | 400 | { |
244 | struct regulatory_request *req; | 401 | struct regulatory_request *req; |
@@ -254,16 +411,16 @@ static bool __reg_is_valid_request(char *alpha2, | |||
254 | } | 411 | } |
255 | 412 | ||
256 | /* Used by nl80211 before kmalloc'ing our regulatory domain */ | 413 | /* Used by nl80211 before kmalloc'ing our regulatory domain */ |
257 | bool reg_is_valid_request(char *alpha2) | 414 | bool reg_is_valid_request(const char *alpha2) |
258 | { | 415 | { |
259 | struct regulatory_request *request = NULL; | 416 | struct regulatory_request *request = NULL; |
260 | return __reg_is_valid_request(alpha2, &request); | 417 | return __reg_is_valid_request(alpha2, &request); |
261 | } | 418 | } |
262 | 419 | ||
263 | /* Sanity check on a regulatory rule */ | 420 | /* Sanity check on a regulatory rule */ |
264 | static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule) | 421 | static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule) |
265 | { | 422 | { |
266 | struct ieee80211_freq_range *freq_range = &rule->freq_range; | 423 | const struct ieee80211_freq_range *freq_range = &rule->freq_range; |
267 | u32 freq_diff; | 424 | u32 freq_diff; |
268 | 425 | ||
269 | if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0) | 426 | if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0) |
@@ -280,9 +437,9 @@ static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule) | |||
280 | return true; | 437 | return true; |
281 | } | 438 | } |
282 | 439 | ||
283 | static bool is_valid_rd(struct ieee80211_regdomain *rd) | 440 | static bool is_valid_rd(const struct ieee80211_regdomain *rd) |
284 | { | 441 | { |
285 | struct ieee80211_reg_rule *reg_rule = NULL; | 442 | const struct ieee80211_reg_rule *reg_rule = NULL; |
286 | unsigned int i; | 443 | unsigned int i; |
287 | 444 | ||
288 | if (!rd->n_reg_rules) | 445 | if (!rd->n_reg_rules) |
@@ -494,12 +651,12 @@ unlock_and_exit: | |||
494 | EXPORT_SYMBOL(regulatory_hint); | 651 | EXPORT_SYMBOL(regulatory_hint); |
495 | 652 | ||
496 | 653 | ||
497 | static void print_rd_rules(struct ieee80211_regdomain *rd) | 654 | static void print_rd_rules(const struct ieee80211_regdomain *rd) |
498 | { | 655 | { |
499 | unsigned int i; | 656 | unsigned int i; |
500 | struct ieee80211_reg_rule *reg_rule = NULL; | 657 | const struct ieee80211_reg_rule *reg_rule = NULL; |
501 | struct ieee80211_freq_range *freq_range = NULL; | 658 | const struct ieee80211_freq_range *freq_range = NULL; |
502 | struct ieee80211_power_rule *power_rule = NULL; | 659 | const struct ieee80211_power_rule *power_rule = NULL; |
503 | 660 | ||
504 | printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), " | 661 | printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), " |
505 | "(max_antenna_gain, max_eirp)\n"); | 662 | "(max_antenna_gain, max_eirp)\n"); |
@@ -529,7 +686,7 @@ static void print_rd_rules(struct ieee80211_regdomain *rd) | |||
529 | } | 686 | } |
530 | } | 687 | } |
531 | 688 | ||
532 | static void print_regdomain(struct ieee80211_regdomain *rd) | 689 | static void print_regdomain(const struct ieee80211_regdomain *rd) |
533 | { | 690 | { |
534 | 691 | ||
535 | if (is_world_regdom(rd->alpha2)) | 692 | if (is_world_regdom(rd->alpha2)) |
@@ -548,85 +705,25 @@ static void print_regdomain(struct ieee80211_regdomain *rd) | |||
548 | print_rd_rules(rd); | 705 | print_rd_rules(rd); |
549 | } | 706 | } |
550 | 707 | ||
551 | void print_regdomain_info(struct ieee80211_regdomain *rd) | 708 | void print_regdomain_info(const struct ieee80211_regdomain *rd) |
552 | { | 709 | { |
553 | printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", | 710 | printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", |
554 | rd->alpha2[0], rd->alpha2[1]); | 711 | rd->alpha2[0], rd->alpha2[1]); |
555 | print_rd_rules(rd); | 712 | print_rd_rules(rd); |
556 | } | 713 | } |
557 | 714 | ||
558 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 715 | static int __set_regdom(const struct ieee80211_regdomain *rd) |
559 | |||
560 | static bool is_old_static_regdom(struct ieee80211_regdomain *rd) | ||
561 | { | ||
562 | if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom) | ||
563 | return true; | ||
564 | return false; | ||
565 | } | ||
566 | |||
567 | /* The old crap never deals with a world regulatory domain, it only | ||
568 | * deals with the static regulatory domain passed and if possible | ||
569 | * an updated "US" or "JP" regulatory domain. We do however store the | ||
570 | * old static regulatory domain in cfg80211_world_regdom for convenience | ||
571 | * of use here */ | ||
572 | static void reset_regdomains_static(void) | ||
573 | { | ||
574 | if (!is_old_static_regdom(cfg80211_regdomain)) | ||
575 | kfree(cfg80211_regdomain); | ||
576 | /* This is setting the regdom to the old static regdom */ | ||
577 | cfg80211_regdomain = | ||
578 | (struct ieee80211_regdomain *) cfg80211_world_regdom; | ||
579 | } | ||
580 | #else | ||
581 | static void reset_regdomains(void) | ||
582 | { | ||
583 | if (cfg80211_world_regdom && cfg80211_world_regdom != &world_regdom) { | ||
584 | if (cfg80211_world_regdom == cfg80211_regdomain) { | ||
585 | kfree(cfg80211_regdomain); | ||
586 | } else { | ||
587 | kfree(cfg80211_world_regdom); | ||
588 | kfree(cfg80211_regdomain); | ||
589 | } | ||
590 | } else if (cfg80211_regdomain && cfg80211_regdomain != &world_regdom) | ||
591 | kfree(cfg80211_regdomain); | ||
592 | |||
593 | cfg80211_world_regdom = (struct ieee80211_regdomain *) &world_regdom; | ||
594 | cfg80211_regdomain = NULL; | ||
595 | } | ||
596 | |||
597 | /* Dynamic world regulatory domain requested by the wireless | ||
598 | * core upon initialization */ | ||
599 | static void update_world_regdomain(struct ieee80211_regdomain *rd) | ||
600 | { | ||
601 | BUG_ON(list_empty(®ulatory_requests)); | ||
602 | |||
603 | reset_regdomains(); | ||
604 | |||
605 | cfg80211_world_regdom = rd; | ||
606 | cfg80211_regdomain = rd; | ||
607 | } | ||
608 | #endif | ||
609 | |||
610 | static int __set_regdom(struct ieee80211_regdomain *rd) | ||
611 | { | 716 | { |
612 | struct regulatory_request *request = NULL; | 717 | struct regulatory_request *request = NULL; |
613 | 718 | ||
614 | /* Some basic sanity checks first */ | 719 | /* Some basic sanity checks first */ |
615 | 720 | ||
616 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
617 | /* We ignore the world regdom with the old static regdomains setup | ||
618 | * as there is no point to it with satic regulatory definitions :( | ||
619 | * Don't worry this shit will be removed soon... */ | ||
620 | if (is_world_regdom(rd->alpha2)) | ||
621 | return -EINVAL; | ||
622 | #else | ||
623 | if (is_world_regdom(rd->alpha2)) { | 721 | if (is_world_regdom(rd->alpha2)) { |
624 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) | 722 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) |
625 | return -EINVAL; | 723 | return -EINVAL; |
626 | update_world_regdomain(rd); | 724 | update_world_regdomain(rd); |
627 | return 0; | 725 | return 0; |
628 | } | 726 | } |
629 | #endif | ||
630 | 727 | ||
631 | if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && | 728 | if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && |
632 | !is_unknown_alpha2(rd->alpha2)) | 729 | !is_unknown_alpha2(rd->alpha2)) |
@@ -635,15 +732,10 @@ static int __set_regdom(struct ieee80211_regdomain *rd) | |||
635 | if (list_empty(®ulatory_requests)) | 732 | if (list_empty(®ulatory_requests)) |
636 | return -EINVAL; | 733 | return -EINVAL; |
637 | 734 | ||
638 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 735 | /* allow overriding the static definitions if CRDA is present */ |
639 | /* Static "US" and "JP" will be overridden, but just once */ | ||
640 | if (!is_old_static_regdom(cfg80211_regdomain) && | 736 | if (!is_old_static_regdom(cfg80211_regdomain) && |
641 | !regdom_changed(rd->alpha2)) | 737 | !regdom_changed(rd->alpha2)) |
642 | return -EINVAL; | ||
643 | #else | ||
644 | if (!regdom_changed(rd->alpha2)) | ||
645 | return -EINVAL; | 738 | return -EINVAL; |
646 | #endif | ||
647 | 739 | ||
648 | /* Now lets set the regulatory domain, update all driver channels | 740 | /* Now lets set the regulatory domain, update all driver channels |
649 | * and finally inform them of what we have done, in case they want | 741 | * and finally inform them of what we have done, in case they want |
@@ -653,11 +745,7 @@ static int __set_regdom(struct ieee80211_regdomain *rd) | |||
653 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) | 745 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) |
654 | return -EINVAL; | 746 | return -EINVAL; |
655 | 747 | ||
656 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
657 | reset_regdomains_static(); | ||
658 | #else | ||
659 | reset_regdomains(); | 748 | reset_regdomains(); |
660 | #endif | ||
661 | 749 | ||
662 | /* Country IE parsing coming soon */ | 750 | /* Country IE parsing coming soon */ |
663 | switch (request->initiator) { | 751 | switch (request->initiator) { |
@@ -689,7 +777,7 @@ static int __set_regdom(struct ieee80211_regdomain *rd) | |||
689 | * multiple drivers can be ironed out later. Caller must've already | 777 | * multiple drivers can be ironed out later. Caller must've already |
690 | * kmalloc'd the rd structure. If this calls fails you should kfree() | 778 | * kmalloc'd the rd structure. If this calls fails you should kfree() |
691 | * the passed rd. Caller must hold cfg80211_drv_mutex */ | 779 | * the passed rd. Caller must hold cfg80211_drv_mutex */ |
692 | int set_regdom(struct ieee80211_regdomain *rd) | 780 | int set_regdom(const struct ieee80211_regdomain *rd) |
693 | { | 781 | { |
694 | struct regulatory_request *this_request = NULL, *prev_request = NULL; | 782 | struct regulatory_request *this_request = NULL, *prev_request = NULL; |
695 | int r; | 783 | int r; |
@@ -735,25 +823,50 @@ int set_regdom(struct ieee80211_regdomain *rd) | |||
735 | 823 | ||
736 | int regulatory_init(void) | 824 | int regulatory_init(void) |
737 | { | 825 | { |
826 | int err; | ||
827 | |||
738 | reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); | 828 | reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); |
739 | if (IS_ERR(reg_pdev)) | 829 | if (IS_ERR(reg_pdev)) |
740 | return PTR_ERR(reg_pdev); | 830 | return PTR_ERR(reg_pdev); |
831 | |||
832 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
833 | cfg80211_regdomain = static_regdom(ieee80211_regdom); | ||
834 | |||
835 | printk(KERN_INFO "cfg80211: Using static regulatory domain info\n"); | ||
836 | print_regdomain_info(cfg80211_regdomain); | ||
837 | /* The old code still requests for a new regdomain and if | ||
838 | * you have CRDA you get it updated, otherwise you get | ||
839 | * stuck with the static values. We ignore "EU" code as | ||
840 | * that is not a valid ISO / IEC 3166 alpha2 */ | ||
841 | if (ieee80211_regdom[0] != 'E' && ieee80211_regdom[1] != 'U') | ||
842 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, | ||
843 | ieee80211_regdom, NULL); | ||
844 | #else | ||
845 | cfg80211_regdomain = cfg80211_world_regdom; | ||
846 | |||
847 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); | ||
848 | if (err) | ||
849 | printk(KERN_ERR "cfg80211: calling CRDA failed - " | ||
850 | "unable to update world regulatory domain, " | ||
851 | "using static definition\n"); | ||
852 | #endif | ||
853 | |||
741 | return 0; | 854 | return 0; |
742 | } | 855 | } |
743 | 856 | ||
744 | void regulatory_exit(void) | 857 | void regulatory_exit(void) |
745 | { | 858 | { |
746 | struct regulatory_request *req, *req_tmp; | 859 | struct regulatory_request *req, *req_tmp; |
860 | |||
747 | mutex_lock(&cfg80211_drv_mutex); | 861 | mutex_lock(&cfg80211_drv_mutex); |
748 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 862 | |
749 | reset_regdomains_static(); | ||
750 | #else | ||
751 | reset_regdomains(); | 863 | reset_regdomains(); |
752 | #endif | 864 | |
753 | list_for_each_entry_safe(req, req_tmp, ®ulatory_requests, list) { | 865 | list_for_each_entry_safe(req, req_tmp, ®ulatory_requests, list) { |
754 | list_del(&req->list); | 866 | list_del(&req->list); |
755 | kfree(req); | 867 | kfree(req); |
756 | } | 868 | } |
757 | platform_device_unregister(reg_pdev); | 869 | platform_device_unregister(reg_pdev); |
870 | |||
758 | mutex_unlock(&cfg80211_drv_mutex); | 871 | mutex_unlock(&cfg80211_drv_mutex); |
759 | } | 872 | } |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index d75fd0232972..a33362872f3c 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -1,44 +1,13 @@ | |||
1 | #ifndef __NET_WIRELESS_REG_H | 1 | #ifndef __NET_WIRELESS_REG_H |
2 | #define __NET_WIRELESS_REG_H | 2 | #define __NET_WIRELESS_REG_H |
3 | 3 | ||
4 | extern const struct ieee80211_regdomain world_regdom; | 4 | extern struct mutex cfg80211_reg_mutex; |
5 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 5 | bool is_world_regdom(const char *alpha2); |
6 | extern const struct ieee80211_regdomain us_regdom; | 6 | bool reg_is_valid_request(const char *alpha2); |
7 | extern const struct ieee80211_regdomain jp_regdom; | ||
8 | extern const struct ieee80211_regdomain eu_regdom; | ||
9 | #endif | ||
10 | |||
11 | extern struct ieee80211_regdomain *cfg80211_regdomain; | ||
12 | extern struct ieee80211_regdomain *cfg80211_world_regdom; | ||
13 | extern struct list_head regulatory_requests; | ||
14 | |||
15 | struct regdom_last_setby { | ||
16 | struct wiphy *wiphy; | ||
17 | u8 initiator; | ||
18 | }; | ||
19 | |||
20 | /* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */ | ||
21 | struct regulatory_request { | ||
22 | struct list_head list; | ||
23 | struct wiphy *wiphy; | ||
24 | int granted; | ||
25 | enum reg_set_by initiator; | ||
26 | char alpha2[2]; | ||
27 | }; | ||
28 | |||
29 | bool is_world_regdom(char *alpha2); | ||
30 | bool reg_is_valid_request(char *alpha2); | ||
31 | |||
32 | int set_regdom(struct ieee80211_regdomain *rd); | ||
33 | int __regulatory_hint_alpha2(struct wiphy *wiphy, enum reg_set_by set_by, | ||
34 | const char *alpha2); | ||
35 | 7 | ||
36 | int regulatory_init(void); | 8 | int regulatory_init(void); |
37 | void regulatory_exit(void); | 9 | void regulatory_exit(void); |
38 | 10 | ||
39 | void print_regdomain_info(struct ieee80211_regdomain *); | 11 | int set_regdom(const struct ieee80211_regdomain *rd); |
40 | |||
41 | /* If a char is A-Z */ | ||
42 | #define IS_ALPHA(letter) (letter >= 65 && letter <= 90) | ||
43 | 12 | ||
44 | #endif /* __NET_WIRELESS_REG_H */ | 13 | #endif /* __NET_WIRELESS_REG_H */ |