aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/zd1211rw/zd_mac.c
diff options
context:
space:
mode:
authorDaniel Drake <dsd@gentoo.org>2006-11-21 19:06:48 -0500
committerJeff Garzik <jeff@garzik.org>2006-12-02 00:12:05 -0500
commitb1382edef9c06eca337e8982e6040e0699abab82 (patch)
treeffd9b959db655b6f06bdb09e1ef6ce245ffa8457 /drivers/net/wireless/zd1211rw/zd_mac.c
parentb1cd84167b92de0f9fc7aad9cf272261496f4d0b (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/net/wireless/zd1211rw/zd_mac.c')
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c270
1 files changed, 215 insertions, 55 deletions
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
33static void ieee_init(struct ieee80211_device *ieee); 33static void ieee_init(struct ieee80211_device *ieee);
34static void softmac_init(struct ieee80211softmac_device *sm); 34static void softmac_init(struct ieee80211softmac_device *sm);
35static void set_rts_cts_work(void *d);
36static void set_basic_rates_work(void *d);
35 37
36static void housekeeping_init(struct zd_mac *mac); 38static void housekeeping_init(struct zd_mac *mac);
37static void housekeeping_enable(struct zd_mac *mac); 39static 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. */
301static 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
330static 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
359static 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
369static 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
390static 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
409static 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
289static void set_channel(struct net_device *netdev, u8 channel) 480static 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. */
350static 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
379int zd_mac_set_mode(struct zd_mac *mac, u32 mode) 540int 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
562static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, 729static 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)
985static void softmac_init(struct ieee80211softmac_device *sm) 1144static 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
990struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) 1150struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev)