diff options
author | Daniel Drake <dsd@gentoo.org> | 2006-11-21 19:06:48 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-12-02 00:12:05 -0500 |
commit | b1382edef9c06eca337e8982e6040e0699abab82 (patch) | |
tree | ffd9b959db655b6f06bdb09e1ef6ce245ffa8457 /drivers | |
parent | b1cd84167b92de0f9fc7aad9cf272261496f4d0b (diff) |
[PATCH] zd1211rw: Use softmac ERP handling functionality
This adds zd1211rw driver support for the softmac functionality I
added a while back. We now obey changes in basic rates, use short
preamble if it is available (but long if the AP says it's not),
and send self-CTS in the proper situations.
Locking fixed and improved by Ulrich Kunitz.
Signed-off-by: Daniel Drake <dsd@gentoo.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_chip.c | 38 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_chip.h | 24 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.c | 270 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.h | 19 |
4 files changed, 286 insertions, 65 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index aa661b2b76c7..8be99ebbe1cd 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
@@ -1076,6 +1076,31 @@ static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std) | |||
1076 | return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL); | 1076 | return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL); |
1077 | } | 1077 | } |
1078 | 1078 | ||
1079 | int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip, | ||
1080 | u8 rts_rate, int preamble) | ||
1081 | { | ||
1082 | int rts_mod = ZD_RX_CCK; | ||
1083 | u32 value = 0; | ||
1084 | |||
1085 | /* Modulation bit */ | ||
1086 | if (ZD_CS_TYPE(rts_rate) == ZD_CS_OFDM) | ||
1087 | rts_mod = ZD_RX_OFDM; | ||
1088 | |||
1089 | dev_dbg_f(zd_chip_dev(chip), "rts_rate=%x preamble=%x\n", | ||
1090 | rts_rate, preamble); | ||
1091 | |||
1092 | value |= rts_rate << RTSCTS_SH_RTS_RATE; | ||
1093 | value |= rts_mod << RTSCTS_SH_RTS_MOD_TYPE; | ||
1094 | value |= preamble << RTSCTS_SH_RTS_PMB_TYPE; | ||
1095 | value |= preamble << RTSCTS_SH_CTS_PMB_TYPE; | ||
1096 | |||
1097 | /* We always send 11M self-CTS messages, like the vendor driver. */ | ||
1098 | value |= ZD_CCK_RATE_11M << RTSCTS_SH_CTS_RATE; | ||
1099 | value |= ZD_RX_CCK << RTSCTS_SH_CTS_MOD_TYPE; | ||
1100 | |||
1101 | return zd_iowrite32_locked(chip, value, CR_RTS_CTS_RATE); | ||
1102 | } | ||
1103 | |||
1079 | int zd_chip_enable_hwint(struct zd_chip *chip) | 1104 | int zd_chip_enable_hwint(struct zd_chip *chip) |
1080 | { | 1105 | { |
1081 | int r; | 1106 | int r; |
@@ -1355,17 +1380,12 @@ out: | |||
1355 | return r; | 1380 | return r; |
1356 | } | 1381 | } |
1357 | 1382 | ||
1358 | int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates) | 1383 | int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates) |
1359 | { | 1384 | { |
1360 | int r; | 1385 | ZD_ASSERT((cr_rates & ~(CR_RATES_80211B | CR_RATES_80211G)) == 0); |
1361 | 1386 | dev_dbg_f(zd_chip_dev(chip), "%x\n", cr_rates); | |
1362 | if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G)) | ||
1363 | return -EINVAL; | ||
1364 | 1387 | ||
1365 | mutex_lock(&chip->mutex); | 1388 | return zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL); |
1366 | r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL); | ||
1367 | mutex_unlock(&chip->mutex); | ||
1368 | return r; | ||
1369 | } | 1389 | } |
1370 | 1390 | ||
1371 | static int ofdm_qual_db(u8 status_quality, u8 rate, unsigned int size) | 1391 | static int ofdm_qual_db(u8 status_quality, u8 rate, unsigned int size) |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index f441cf40f74b..ca892b9a6448 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h | |||
@@ -420,6 +420,15 @@ | |||
420 | #define CR_MANDATORY_RATE_TBL CTL_REG(0x0634) | 420 | #define CR_MANDATORY_RATE_TBL CTL_REG(0x0634) |
421 | #define CR_RTS_CTS_RATE CTL_REG(0x0638) | 421 | #define CR_RTS_CTS_RATE CTL_REG(0x0638) |
422 | 422 | ||
423 | /* These are all bit indexes in CR_RTS_CTS_RATE, so remember to shift. */ | ||
424 | #define RTSCTS_SH_RTS_RATE 0 | ||
425 | #define RTSCTS_SH_EXP_CTS_RATE 4 | ||
426 | #define RTSCTS_SH_RTS_MOD_TYPE 8 | ||
427 | #define RTSCTS_SH_RTS_PMB_TYPE 9 | ||
428 | #define RTSCTS_SH_CTS_RATE 16 | ||
429 | #define RTSCTS_SH_CTS_MOD_TYPE 24 | ||
430 | #define RTSCTS_SH_CTS_PMB_TYPE 25 | ||
431 | |||
423 | #define CR_WEP_PROTECT CTL_REG(0x063C) | 432 | #define CR_WEP_PROTECT CTL_REG(0x063C) |
424 | #define CR_RX_THRESHOLD CTL_REG(0x0640) | 433 | #define CR_RX_THRESHOLD CTL_REG(0x0640) |
425 | 434 | ||
@@ -794,6 +803,9 @@ void zd_chip_disable_rx(struct zd_chip *chip); | |||
794 | int zd_chip_enable_hwint(struct zd_chip *chip); | 803 | int zd_chip_enable_hwint(struct zd_chip *chip); |
795 | int zd_chip_disable_hwint(struct zd_chip *chip); | 804 | int zd_chip_disable_hwint(struct zd_chip *chip); |
796 | 805 | ||
806 | int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip, | ||
807 | u8 rts_rate, int preamble); | ||
808 | |||
797 | static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type) | 809 | static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type) |
798 | { | 810 | { |
799 | return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type); | 811 | return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type); |
@@ -809,7 +821,17 @@ static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates) | |||
809 | return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates); | 821 | return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates); |
810 | } | 822 | } |
811 | 823 | ||
812 | int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates); | 824 | int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates); |
825 | |||
826 | static inline int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates) | ||
827 | { | ||
828 | int r; | ||
829 | |||
830 | mutex_lock(&chip->mutex); | ||
831 | r = zd_chip_set_basic_rates_locked(chip, cr_rates); | ||
832 | mutex_unlock(&chip->mutex); | ||
833 | return r; | ||
834 | } | ||
813 | 835 | ||
814 | static inline int zd_chip_set_rx_filter(struct zd_chip *chip, u32 filter) | 836 | static inline int zd_chip_set_rx_filter(struct zd_chip *chip, u32 filter) |
815 | { | 837 | { |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index e6af18304bac..2696f95b9278 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -32,6 +32,8 @@ | |||
32 | 32 | ||
33 | static void ieee_init(struct ieee80211_device *ieee); | 33 | static void ieee_init(struct ieee80211_device *ieee); |
34 | static void softmac_init(struct ieee80211softmac_device *sm); | 34 | static void softmac_init(struct ieee80211softmac_device *sm); |
35 | static void set_rts_cts_work(void *d); | ||
36 | static void set_basic_rates_work(void *d); | ||
35 | 37 | ||
36 | static void housekeeping_init(struct zd_mac *mac); | 38 | static void housekeeping_init(struct zd_mac *mac); |
37 | static void housekeeping_enable(struct zd_mac *mac); | 39 | static void housekeeping_enable(struct zd_mac *mac); |
@@ -46,6 +48,8 @@ int zd_mac_init(struct zd_mac *mac, | |||
46 | memset(mac, 0, sizeof(*mac)); | 48 | memset(mac, 0, sizeof(*mac)); |
47 | spin_lock_init(&mac->lock); | 49 | spin_lock_init(&mac->lock); |
48 | mac->netdev = netdev; | 50 | mac->netdev = netdev; |
51 | INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work, mac); | ||
52 | INIT_WORK(&mac->set_basic_rates_work, set_basic_rates_work, mac); | ||
49 | 53 | ||
50 | ieee_init(ieee); | 54 | ieee_init(ieee); |
51 | softmac_init(ieee80211_priv(netdev)); | 55 | softmac_init(ieee80211_priv(netdev)); |
@@ -213,6 +217,13 @@ int zd_mac_stop(struct net_device *netdev) | |||
213 | housekeeping_disable(mac); | 217 | housekeeping_disable(mac); |
214 | ieee80211softmac_stop(netdev); | 218 | ieee80211softmac_stop(netdev); |
215 | 219 | ||
220 | /* Ensure no work items are running or queued from this point */ | ||
221 | cancel_delayed_work(&mac->set_rts_cts_work); | ||
222 | cancel_delayed_work(&mac->set_basic_rates_work); | ||
223 | flush_workqueue(zd_workqueue); | ||
224 | mac->updating_rts_rate = 0; | ||
225 | mac->updating_basic_rates = 0; | ||
226 | |||
216 | zd_chip_disable_hwint(chip); | 227 | zd_chip_disable_hwint(chip); |
217 | zd_chip_switch_radio_off(chip); | 228 | zd_chip_switch_radio_off(chip); |
218 | zd_chip_disable_int(chip); | 229 | zd_chip_disable_int(chip); |
@@ -286,6 +297,186 @@ u8 zd_mac_get_regdomain(struct zd_mac *mac) | |||
286 | return regdomain; | 297 | return regdomain; |
287 | } | 298 | } |
288 | 299 | ||
300 | /* Fallback to lowest rate, if rate is unknown. */ | ||
301 | static u8 rate_to_zd_rate(u8 rate) | ||
302 | { | ||
303 | switch (rate) { | ||
304 | case IEEE80211_CCK_RATE_2MB: | ||
305 | return ZD_CCK_RATE_2M; | ||
306 | case IEEE80211_CCK_RATE_5MB: | ||
307 | return ZD_CCK_RATE_5_5M; | ||
308 | case IEEE80211_CCK_RATE_11MB: | ||
309 | return ZD_CCK_RATE_11M; | ||
310 | case IEEE80211_OFDM_RATE_6MB: | ||
311 | return ZD_OFDM_RATE_6M; | ||
312 | case IEEE80211_OFDM_RATE_9MB: | ||
313 | return ZD_OFDM_RATE_9M; | ||
314 | case IEEE80211_OFDM_RATE_12MB: | ||
315 | return ZD_OFDM_RATE_12M; | ||
316 | case IEEE80211_OFDM_RATE_18MB: | ||
317 | return ZD_OFDM_RATE_18M; | ||
318 | case IEEE80211_OFDM_RATE_24MB: | ||
319 | return ZD_OFDM_RATE_24M; | ||
320 | case IEEE80211_OFDM_RATE_36MB: | ||
321 | return ZD_OFDM_RATE_36M; | ||
322 | case IEEE80211_OFDM_RATE_48MB: | ||
323 | return ZD_OFDM_RATE_48M; | ||
324 | case IEEE80211_OFDM_RATE_54MB: | ||
325 | return ZD_OFDM_RATE_54M; | ||
326 | } | ||
327 | return ZD_CCK_RATE_1M; | ||
328 | } | ||
329 | |||
330 | static u16 rate_to_cr_rate(u8 rate) | ||
331 | { | ||
332 | switch (rate) { | ||
333 | case IEEE80211_CCK_RATE_2MB: | ||
334 | return CR_RATE_1M; | ||
335 | case IEEE80211_CCK_RATE_5MB: | ||
336 | return CR_RATE_5_5M; | ||
337 | case IEEE80211_CCK_RATE_11MB: | ||
338 | return CR_RATE_11M; | ||
339 | case IEEE80211_OFDM_RATE_6MB: | ||
340 | return CR_RATE_6M; | ||
341 | case IEEE80211_OFDM_RATE_9MB: | ||
342 | return CR_RATE_9M; | ||
343 | case IEEE80211_OFDM_RATE_12MB: | ||
344 | return CR_RATE_12M; | ||
345 | case IEEE80211_OFDM_RATE_18MB: | ||
346 | return CR_RATE_18M; | ||
347 | case IEEE80211_OFDM_RATE_24MB: | ||
348 | return CR_RATE_24M; | ||
349 | case IEEE80211_OFDM_RATE_36MB: | ||
350 | return CR_RATE_36M; | ||
351 | case IEEE80211_OFDM_RATE_48MB: | ||
352 | return CR_RATE_48M; | ||
353 | case IEEE80211_OFDM_RATE_54MB: | ||
354 | return CR_RATE_54M; | ||
355 | } | ||
356 | return CR_RATE_1M; | ||
357 | } | ||
358 | |||
359 | static void try_enable_tx(struct zd_mac *mac) | ||
360 | { | ||
361 | unsigned long flags; | ||
362 | |||
363 | spin_lock_irqsave(&mac->lock, flags); | ||
364 | if (mac->updating_rts_rate == 0 && mac->updating_basic_rates == 0) | ||
365 | netif_wake_queue(mac->netdev); | ||
366 | spin_unlock_irqrestore(&mac->lock, flags); | ||
367 | } | ||
368 | |||
369 | static void set_rts_cts_work(void *d) | ||
370 | { | ||
371 | struct zd_mac *mac = d; | ||
372 | unsigned long flags; | ||
373 | u8 rts_rate; | ||
374 | unsigned int short_preamble; | ||
375 | |||
376 | mutex_lock(&mac->chip.mutex); | ||
377 | |||
378 | spin_lock_irqsave(&mac->lock, flags); | ||
379 | mac->updating_rts_rate = 0; | ||
380 | rts_rate = mac->rts_rate; | ||
381 | short_preamble = mac->short_preamble; | ||
382 | spin_unlock_irqrestore(&mac->lock, flags); | ||
383 | |||
384 | zd_chip_set_rts_cts_rate_locked(&mac->chip, rts_rate, short_preamble); | ||
385 | mutex_unlock(&mac->chip.mutex); | ||
386 | |||
387 | try_enable_tx(mac); | ||
388 | } | ||
389 | |||
390 | static void set_basic_rates_work(void *d) | ||
391 | { | ||
392 | struct zd_mac *mac = d; | ||
393 | unsigned long flags; | ||
394 | u16 basic_rates; | ||
395 | |||
396 | mutex_lock(&mac->chip.mutex); | ||
397 | |||
398 | spin_lock_irqsave(&mac->lock, flags); | ||
399 | mac->updating_basic_rates = 0; | ||
400 | basic_rates = mac->basic_rates; | ||
401 | spin_unlock_irqrestore(&mac->lock, flags); | ||
402 | |||
403 | zd_chip_set_basic_rates_locked(&mac->chip, basic_rates); | ||
404 | mutex_unlock(&mac->chip.mutex); | ||
405 | |||
406 | try_enable_tx(mac); | ||
407 | } | ||
408 | |||
409 | static void bssinfo_change(struct net_device *netdev, u32 changes) | ||
410 | { | ||
411 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
412 | struct ieee80211softmac_device *softmac = ieee80211_priv(netdev); | ||
413 | struct ieee80211softmac_bss_info *bssinfo = &softmac->bssinfo; | ||
414 | int need_set_rts_cts = 0; | ||
415 | int need_set_rates = 0; | ||
416 | u16 basic_rates; | ||
417 | unsigned long flags; | ||
418 | |||
419 | dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes); | ||
420 | |||
421 | if (changes & IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE) { | ||
422 | spin_lock_irqsave(&mac->lock, flags); | ||
423 | mac->short_preamble = bssinfo->short_preamble; | ||
424 | spin_unlock_irqrestore(&mac->lock, flags); | ||
425 | need_set_rts_cts = 1; | ||
426 | } | ||
427 | |||
428 | if (changes & IEEE80211SOFTMAC_BSSINFOCHG_RATES) { | ||
429 | /* Set RTS rate to highest available basic rate */ | ||
430 | u8 rate = ieee80211softmac_highest_supported_rate(softmac, | ||
431 | &bssinfo->supported_rates, 1); | ||
432 | rate = rate_to_zd_rate(rate); | ||
433 | |||
434 | spin_lock_irqsave(&mac->lock, flags); | ||
435 | if (rate != mac->rts_rate) { | ||
436 | mac->rts_rate = rate; | ||
437 | need_set_rts_cts = 1; | ||
438 | } | ||
439 | spin_unlock_irqrestore(&mac->lock, flags); | ||
440 | |||
441 | /* Set basic rates */ | ||
442 | need_set_rates = 1; | ||
443 | if (bssinfo->supported_rates.count == 0) { | ||
444 | /* Allow the device to be flexible */ | ||
445 | basic_rates = CR_RATES_80211B | CR_RATES_80211G; | ||
446 | } else { | ||
447 | int i = 0; | ||
448 | basic_rates = 0; | ||
449 | |||
450 | for (i = 0; i < bssinfo->supported_rates.count; i++) { | ||
451 | u16 rate = bssinfo->supported_rates.rates[i]; | ||
452 | if ((rate & IEEE80211_BASIC_RATE_MASK) == 0) | ||
453 | continue; | ||
454 | |||
455 | rate &= ~IEEE80211_BASIC_RATE_MASK; | ||
456 | basic_rates |= rate_to_cr_rate(rate); | ||
457 | } | ||
458 | } | ||
459 | spin_lock_irqsave(&mac->lock, flags); | ||
460 | mac->basic_rates = basic_rates; | ||
461 | spin_unlock_irqrestore(&mac->lock, flags); | ||
462 | } | ||
463 | |||
464 | /* Schedule any changes we made above */ | ||
465 | |||
466 | spin_lock_irqsave(&mac->lock, flags); | ||
467 | if (need_set_rts_cts && !mac->updating_rts_rate) { | ||
468 | mac->updating_rts_rate = 1; | ||
469 | netif_stop_queue(mac->netdev); | ||
470 | queue_work(zd_workqueue, &mac->set_rts_cts_work); | ||
471 | } | ||
472 | if (need_set_rates && !mac->updating_basic_rates) { | ||
473 | mac->updating_basic_rates = 1; | ||
474 | netif_stop_queue(mac->netdev); | ||
475 | queue_work(zd_workqueue, &mac->set_basic_rates_work); | ||
476 | } | ||
477 | spin_unlock_irqrestore(&mac->lock, flags); | ||
478 | } | ||
479 | |||
289 | static void set_channel(struct net_device *netdev, u8 channel) | 480 | static void set_channel(struct net_device *netdev, u8 channel) |
290 | { | 481 | { |
291 | struct zd_mac *mac = zd_netdev_mac(netdev); | 482 | struct zd_mac *mac = zd_netdev_mac(netdev); |
@@ -346,36 +537,6 @@ static u8 zd_rate_typed(u8 zd_rate) | |||
346 | return typed_rates[zd_rate & ZD_CS_RATE_MASK]; | 537 | return typed_rates[zd_rate & ZD_CS_RATE_MASK]; |
347 | } | 538 | } |
348 | 539 | ||
349 | /* Fallback to lowest rate, if rate is unknown. */ | ||
350 | static u8 rate_to_zd_rate(u8 rate) | ||
351 | { | ||
352 | switch (rate) { | ||
353 | case IEEE80211_CCK_RATE_2MB: | ||
354 | return ZD_CCK_RATE_2M; | ||
355 | case IEEE80211_CCK_RATE_5MB: | ||
356 | return ZD_CCK_RATE_5_5M; | ||
357 | case IEEE80211_CCK_RATE_11MB: | ||
358 | return ZD_CCK_RATE_11M; | ||
359 | case IEEE80211_OFDM_RATE_6MB: | ||
360 | return ZD_OFDM_RATE_6M; | ||
361 | case IEEE80211_OFDM_RATE_9MB: | ||
362 | return ZD_OFDM_RATE_9M; | ||
363 | case IEEE80211_OFDM_RATE_12MB: | ||
364 | return ZD_OFDM_RATE_12M; | ||
365 | case IEEE80211_OFDM_RATE_18MB: | ||
366 | return ZD_OFDM_RATE_18M; | ||
367 | case IEEE80211_OFDM_RATE_24MB: | ||
368 | return ZD_OFDM_RATE_24M; | ||
369 | case IEEE80211_OFDM_RATE_36MB: | ||
370 | return ZD_OFDM_RATE_36M; | ||
371 | case IEEE80211_OFDM_RATE_48MB: | ||
372 | return ZD_OFDM_RATE_48M; | ||
373 | case IEEE80211_OFDM_RATE_54MB: | ||
374 | return ZD_OFDM_RATE_54M; | ||
375 | } | ||
376 | return ZD_CCK_RATE_1M; | ||
377 | } | ||
378 | |||
379 | int zd_mac_set_mode(struct zd_mac *mac, u32 mode) | 540 | int zd_mac_set_mode(struct zd_mac *mac, u32 mode) |
380 | { | 541 | { |
381 | struct ieee80211_device *ieee; | 542 | struct ieee80211_device *ieee; |
@@ -550,37 +711,34 @@ static void cs_set_modulation(struct zd_mac *mac, struct zd_ctrlset *cs, | |||
550 | u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl)); | 711 | u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl)); |
551 | u8 rate, zd_rate; | 712 | u8 rate, zd_rate; |
552 | int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0; | 713 | int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0; |
714 | int is_multicast = is_multicast_ether_addr(hdr->addr1); | ||
715 | int short_preamble = ieee80211softmac_short_preamble_ok(softmac, | ||
716 | is_multicast, is_mgt); | ||
717 | int flags = 0; | ||
553 | 718 | ||
554 | /* FIXME: 802.11a? short preamble? */ | 719 | /* FIXME: 802.11a? */ |
555 | rate = ieee80211softmac_suggest_txrate(softmac, | 720 | rate = ieee80211softmac_suggest_txrate(softmac, is_multicast, is_mgt); |
556 | is_multicast_ether_addr(hdr->addr1), is_mgt); | 721 | |
722 | if (short_preamble) | ||
723 | flags |= R2M_SHORT_PREAMBLE; | ||
557 | 724 | ||
558 | zd_rate = rate_to_zd_rate(rate); | 725 | zd_rate = rate_to_zd_rate(rate); |
559 | cs->modulation = zd_rate_to_modulation(zd_rate, 0); | 726 | cs->modulation = zd_rate_to_modulation(zd_rate, flags); |
560 | } | 727 | } |
561 | 728 | ||
562 | static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, | 729 | static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, |
563 | struct ieee80211_hdr_4addr *header) | 730 | struct ieee80211_hdr_4addr *header) |
564 | { | 731 | { |
732 | struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev); | ||
565 | unsigned int tx_length = le16_to_cpu(cs->tx_length); | 733 | unsigned int tx_length = le16_to_cpu(cs->tx_length); |
566 | u16 fctl = le16_to_cpu(header->frame_ctl); | 734 | u16 fctl = le16_to_cpu(header->frame_ctl); |
567 | u16 ftype = WLAN_FC_GET_TYPE(fctl); | 735 | u16 ftype = WLAN_FC_GET_TYPE(fctl); |
568 | u16 stype = WLAN_FC_GET_STYPE(fctl); | 736 | u16 stype = WLAN_FC_GET_STYPE(fctl); |
569 | 737 | ||
570 | /* | 738 | /* |
571 | * CONTROL: | 739 | * CONTROL TODO: |
572 | * - start at 0x00 | ||
573 | * - if fragment 0, enable bit 0 | ||
574 | * - if backoff needed, enable bit 0 | 740 | * - if backoff needed, enable bit 0 |
575 | * - if burst (backoff not needed) disable bit 0 | 741 | * - if burst (backoff not needed) disable bit 0 |
576 | * - if multicast, enable bit 1 | ||
577 | * - if PS-POLL frame, enable bit 2 | ||
578 | * - if in INDEPENDENT_BSS mode and zd1205_DestPowerSave, then enable | ||
579 | * bit 4 (FIXME: wtf) | ||
580 | * - if frag_len > RTS threshold, set bit 5 as long if it isnt | ||
581 | * multicast or mgt | ||
582 | * - if bit 5 is set, and we are in OFDM mode, unset bit 5 and set bit | ||
583 | * 7 | ||
584 | */ | 742 | */ |
585 | 743 | ||
586 | cs->control = 0; | 744 | cs->control = 0; |
@@ -597,17 +755,18 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, | |||
597 | if (stype == IEEE80211_STYPE_PSPOLL) | 755 | if (stype == IEEE80211_STYPE_PSPOLL) |
598 | cs->control |= ZD_CS_PS_POLL_FRAME; | 756 | cs->control |= ZD_CS_PS_POLL_FRAME; |
599 | 757 | ||
758 | /* Unicast data frames over the threshold should have RTS */ | ||
600 | if (!is_multicast_ether_addr(header->addr1) && | 759 | if (!is_multicast_ether_addr(header->addr1) && |
601 | ftype != IEEE80211_FTYPE_MGMT && | 760 | ftype != IEEE80211_FTYPE_MGMT && |
602 | tx_length > zd_netdev_ieee80211(mac->netdev)->rts) | 761 | tx_length > zd_netdev_ieee80211(mac->netdev)->rts) |
603 | { | 762 | cs->control |= ZD_CS_RTS; |
604 | /* FIXME: check the logic */ | 763 | |
605 | if (ZD_CS_TYPE(cs->modulation) == ZD_CS_OFDM) { | 764 | /* Use CTS-to-self protection if required */ |
606 | /* 802.11g */ | 765 | if (ZD_CS_TYPE(cs->modulation) == ZD_CS_OFDM && |
607 | cs->control |= ZD_CS_SELF_CTS; | 766 | ieee80211softmac_protection_needed(softmac)) { |
608 | } else { /* 802.11b */ | 767 | /* FIXME: avoid sending RTS *and* self-CTS, is that correct? */ |
609 | cs->control |= ZD_CS_RTS; | 768 | cs->control &= ~ZD_CS_RTS; |
610 | } | 769 | cs->control |= ZD_CS_SELF_CTS; |
611 | } | 770 | } |
612 | 771 | ||
613 | /* FIXME: Management frame? */ | 772 | /* FIXME: Management frame? */ |
@@ -985,6 +1144,7 @@ static void ieee_init(struct ieee80211_device *ieee) | |||
985 | static void softmac_init(struct ieee80211softmac_device *sm) | 1144 | static void softmac_init(struct ieee80211softmac_device *sm) |
986 | { | 1145 | { |
987 | sm->set_channel = set_channel; | 1146 | sm->set_channel = set_channel; |
1147 | sm->bssinfo_change = bssinfo_change; | ||
988 | } | 1148 | } |
989 | 1149 | ||
990 | struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) | 1150 | struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 3c86578150b3..5dcfb251f02e 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include <linux/wireless.h> | 21 | #include <linux/wireless.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/workqueue.h> | ||
23 | #include <net/ieee80211.h> | 24 | #include <net/ieee80211.h> |
24 | #include <net/ieee80211softmac.h> | 25 | #include <net/ieee80211softmac.h> |
25 | 26 | ||
@@ -127,15 +128,33 @@ struct zd_mac { | |||
127 | struct zd_chip chip; | 128 | struct zd_chip chip; |
128 | spinlock_t lock; | 129 | spinlock_t lock; |
129 | struct net_device *netdev; | 130 | struct net_device *netdev; |
131 | |||
130 | /* Unlocked reading possible */ | 132 | /* Unlocked reading possible */ |
131 | struct iw_statistics iw_stats; | 133 | struct iw_statistics iw_stats; |
134 | |||
132 | struct housekeeping housekeeping; | 135 | struct housekeeping housekeeping; |
136 | struct work_struct set_rts_cts_work; | ||
137 | struct work_struct set_basic_rates_work; | ||
138 | |||
133 | unsigned int stats_count; | 139 | unsigned int stats_count; |
134 | u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE]; | 140 | u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE]; |
135 | u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE]; | 141 | u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE]; |
136 | u8 regdomain; | 142 | u8 regdomain; |
137 | u8 default_regdomain; | 143 | u8 default_regdomain; |
138 | u8 requested_channel; | 144 | u8 requested_channel; |
145 | |||
146 | /* A bitpattern of cr_rates */ | ||
147 | u16 basic_rates; | ||
148 | |||
149 | /* A zd_rate */ | ||
150 | u8 rts_rate; | ||
151 | |||
152 | /* Short preamble (used for RTS/CTS) */ | ||
153 | unsigned int short_preamble:1; | ||
154 | |||
155 | /* flags to indicate update in progress */ | ||
156 | unsigned int updating_rts_rate:1; | ||
157 | unsigned int updating_basic_rates:1; | ||
139 | }; | 158 | }; |
140 | 159 | ||
141 | static inline struct ieee80211_device *zd_mac_to_ieee80211(struct zd_mac *mac) | 160 | static inline struct ieee80211_device *zd_mac_to_ieee80211(struct zd_mac *mac) |