aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r--drivers/net/wireless/b43/b43.h1
-rw-r--r--drivers/net/wireless/b43/debugfs.c1
-rw-r--r--drivers/net/wireless/b43/debugfs.h1
-rw-r--r--drivers/net/wireless/b43/dma.c4
-rw-r--r--drivers/net/wireless/b43/main.c280
-rw-r--r--drivers/net/wireless/b43/phy_a.c4
-rw-r--r--drivers/net/wireless/b43/phy_common.c18
-rw-r--r--drivers/net/wireless/b43/phy_g.c28
-rw-r--r--drivers/net/wireless/b43/pio.c3
-rw-r--r--drivers/net/wireless/b43/xmit.c64
-rw-r--r--drivers/net/wireless/b43/xmit.h5
11 files changed, 258 insertions, 151 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 427b8203e3f9..a53c378e7484 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -718,7 +718,6 @@ struct b43_wldev {
718 718
719 bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */ 719 bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */
720 bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ 720 bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */
721 bool short_slot; /* TRUE, if short slot timing is enabled. */
722 bool radio_hw_enable; /* saved state of radio hardware enabled state */ 721 bool radio_hw_enable; /* saved state of radio hardware enabled state */
723 bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */ 722 bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */
724 723
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 06a01da80160..e04fc91f569e 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -731,6 +731,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev)
731 add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); 731 add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0);
732 add_dyn_dbg("debug_lo", B43_DBG_LO, 0); 732 add_dyn_dbg("debug_lo", B43_DBG_LO, 0);
733 add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); 733 add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0);
734 add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0);
734 735
735#undef add_dyn_dbg 736#undef add_dyn_dbg
736} 737}
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h
index 22ffd02ba554..7886cbe2d1d1 100644
--- a/drivers/net/wireless/b43/debugfs.h
+++ b/drivers/net/wireless/b43/debugfs.h
@@ -12,6 +12,7 @@ enum b43_dyndbg { /* Dynamic debugging features */
12 B43_DBG_PWORK_STOP, 12 B43_DBG_PWORK_STOP,
13 B43_DBG_LO, 13 B43_DBG_LO,
14 B43_DBG_FIRMWARE, 14 B43_DBG_FIRMWARE,
15 B43_DBG_KEYS,
15 __B43_NR_DYNDBG, 16 __B43_NR_DYNDBG,
16}; 17};
17 18
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 098f886976f6..6d65a02b7052 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1387,13 +1387,11 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
1387 1387
1388 info = IEEE80211_SKB_CB(meta->skb); 1388 info = IEEE80211_SKB_CB(meta->skb);
1389 1389
1390 memset(&info->status, 0, sizeof(info->status));
1391
1392 /* 1390 /*
1393 * Call back to inform the ieee80211 subsystem about 1391 * Call back to inform the ieee80211 subsystem about
1394 * the status of the transmission. 1392 * the status of the transmission.
1395 */ 1393 */
1396 frame_succeed = b43_fill_txstatus_report(info, status); 1394 frame_succeed = b43_fill_txstatus_report(dev, info, status);
1397#ifdef CONFIG_B43_DEBUG 1395#ifdef CONFIG_B43_DEBUG
1398 if (frame_succeed) 1396 if (frame_succeed)
1399 ring->nr_succeed_tx_packets++; 1397 ring->nr_succeed_tx_packets++;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 14c44df584d0..7b31a327b24a 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -703,13 +703,11 @@ static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time)
703static void b43_short_slot_timing_enable(struct b43_wldev *dev) 703static void b43_short_slot_timing_enable(struct b43_wldev *dev)
704{ 704{
705 b43_set_slot_time(dev, 9); 705 b43_set_slot_time(dev, 9);
706 dev->short_slot = 1;
707} 706}
708 707
709static void b43_short_slot_timing_disable(struct b43_wldev *dev) 708static void b43_short_slot_timing_disable(struct b43_wldev *dev)
710{ 709{
711 b43_set_slot_time(dev, 20); 710 b43_set_slot_time(dev, 20);
712 dev->short_slot = 0;
713} 711}
714 712
715/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. 713/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
@@ -994,6 +992,52 @@ static void b43_clear_keys(struct b43_wldev *dev)
994 b43_key_clear(dev, i); 992 b43_key_clear(dev, i);
995} 993}
996 994
995static void b43_dump_keymemory(struct b43_wldev *dev)
996{
997 unsigned int i, index, offset;
998 DECLARE_MAC_BUF(macbuf);
999 u8 mac[ETH_ALEN];
1000 u16 algo;
1001 u32 rcmta0;
1002 u16 rcmta1;
1003 u64 hf;
1004 struct b43_key *key;
1005
1006 if (!b43_debug(dev, B43_DBG_KEYS))
1007 return;
1008
1009 hf = b43_hf_read(dev);
1010 b43dbg(dev->wl, "Hardware key memory dump: USEDEFKEYS=%u\n",
1011 !!(hf & B43_HF_USEDEFKEYS));
1012 for (index = 0; index < dev->max_nr_keys; index++) {
1013 key = &(dev->key[index]);
1014 printk(KERN_DEBUG "Key slot %02u: %s",
1015 index, (key->keyconf == NULL) ? " " : "*");
1016 offset = dev->ktp + (index * B43_SEC_KEYSIZE);
1017 for (i = 0; i < B43_SEC_KEYSIZE; i += 2) {
1018 u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, offset + i);
1019 printk("%02X%02X", (tmp & 0xFF), ((tmp >> 8) & 0xFF));
1020 }
1021
1022 algo = b43_shm_read16(dev, B43_SHM_SHARED,
1023 B43_SHM_SH_KEYIDXBLOCK + (index * 2));
1024 printk(" Algo: %04X/%02X", algo, key->algorithm);
1025
1026 if (index >= 4) {
1027 rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA,
1028 ((index - 4) * 2) + 0);
1029 rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA,
1030 ((index - 4) * 2) + 1);
1031 *((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0);
1032 *((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1);
1033 printk(" MAC: %s",
1034 print_mac(macbuf, mac));
1035 } else
1036 printk(" DEFAULT KEY");
1037 printk("\n");
1038 }
1039}
1040
997void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags) 1041void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
998{ 1042{
999 u32 macctl; 1043 u32 macctl;
@@ -1339,25 +1383,6 @@ u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
1339 return antenna_nr; 1383 return antenna_nr;
1340} 1384}
1341 1385
1342static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna)
1343{
1344 antenna = b43_ieee80211_antenna_sanitize(dev, antenna);
1345 switch (antenna) {
1346 case 0: /* default/diversity */
1347 return B43_ANTENNA_DEFAULT;
1348 case 1: /* Antenna 0 */
1349 return B43_ANTENNA0;
1350 case 2: /* Antenna 1 */
1351 return B43_ANTENNA1;
1352 case 3: /* Antenna 2 */
1353 return B43_ANTENNA2;
1354 case 4: /* Antenna 3 */
1355 return B43_ANTENNA3;
1356 default:
1357 return B43_ANTENNA_DEFAULT;
1358 }
1359}
1360
1361/* Convert a b43 antenna number value to the PHY TX control value. */ 1386/* Convert a b43 antenna number value to the PHY TX control value. */
1362static u16 b43_antenna_to_phyctl(int antenna) 1387static u16 b43_antenna_to_phyctl(int antenna)
1363{ 1388{
@@ -1399,7 +1424,7 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
1399 len, ram_offset, shm_size_offset, rate); 1424 len, ram_offset, shm_size_offset, rate);
1400 1425
1401 /* Write the PHY TX control parameters. */ 1426 /* Write the PHY TX control parameters. */
1402 antenna = b43_antenna_from_ieee80211(dev, info->antenna_sel_tx); 1427 antenna = B43_ANTENNA_DEFAULT;
1403 antenna = b43_antenna_to_phyctl(antenna); 1428 antenna = b43_antenna_to_phyctl(antenna);
1404 ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); 1429 ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
1405 /* We can't send beacons with short preamble. Would get PHY errors. */ 1430 /* We can't send beacons with short preamble. Would get PHY errors. */
@@ -1693,25 +1718,6 @@ static void b43_update_templates(struct b43_wl *wl)
1693 queue_work(wl->hw->workqueue, &wl->beacon_update_trigger); 1718 queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
1694} 1719}
1695 1720
1696static void b43_set_ssid(struct b43_wldev *dev, const u8 * ssid, u8 ssid_len)
1697{
1698 u32 tmp;
1699 u16 i, len;
1700
1701 len = min((u16) ssid_len, (u16) 0x100);
1702 for (i = 0; i < len; i += sizeof(u32)) {
1703 tmp = (u32) (ssid[i + 0]);
1704 if (i + 1 < len)
1705 tmp |= (u32) (ssid[i + 1]) << 8;
1706 if (i + 2 < len)
1707 tmp |= (u32) (ssid[i + 2]) << 16;
1708 if (i + 3 < len)
1709 tmp |= (u32) (ssid[i + 3]) << 24;
1710 b43_shm_write32(dev, B43_SHM_SHARED, 0x380 + i, tmp);
1711 }
1712 b43_shm_write16(dev, B43_SHM_SHARED, 0x48, len);
1713}
1714
1715static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) 1721static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
1716{ 1722{
1717 b43_time_lock(dev); 1723 b43_time_lock(dev);
@@ -3339,15 +3345,31 @@ init_failure:
3339 return err; 3345 return err;
3340} 3346}
3341 3347
3342static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) 3348/* Write the short and long frame retry limit values. */
3349static void b43_set_retry_limits(struct b43_wldev *dev,
3350 unsigned int short_retry,
3351 unsigned int long_retry)
3352{
3353 /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
3354 * the chip-internal counter. */
3355 short_retry = min(short_retry, (unsigned int)0xF);
3356 long_retry = min(long_retry, (unsigned int)0xF);
3357
3358 b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT,
3359 short_retry);
3360 b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT,
3361 long_retry);
3362}
3363
3364static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
3343{ 3365{
3344 struct b43_wl *wl = hw_to_b43_wl(hw); 3366 struct b43_wl *wl = hw_to_b43_wl(hw);
3345 struct b43_wldev *dev; 3367 struct b43_wldev *dev;
3346 struct b43_phy *phy; 3368 struct b43_phy *phy;
3369 struct ieee80211_conf *conf = &hw->conf;
3347 unsigned long flags; 3370 unsigned long flags;
3348 int antenna; 3371 int antenna;
3349 int err = 0; 3372 int err = 0;
3350 u32 savedirqs;
3351 3373
3352 mutex_lock(&wl->mutex); 3374 mutex_lock(&wl->mutex);
3353 3375
@@ -3358,33 +3380,20 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
3358 dev = wl->current_dev; 3380 dev = wl->current_dev;
3359 phy = &dev->phy; 3381 phy = &dev->phy;
3360 3382
3361 /* Disable IRQs while reconfiguring the device. 3383 b43_mac_suspend(dev);
3362 * This makes it possible to drop the spinlock throughout 3384
3363 * the reconfiguration process. */ 3385 if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
3364 spin_lock_irqsave(&wl->irq_lock, flags); 3386 b43_set_retry_limits(dev, conf->short_frame_max_tx_count,
3365 if (b43_status(dev) < B43_STAT_STARTED) { 3387 conf->long_frame_max_tx_count);
3366 spin_unlock_irqrestore(&wl->irq_lock, flags); 3388 changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS;
3367 goto out_unlock_mutex; 3389 if (!changed)
3368 } 3390 goto out_mac_enable;
3369 savedirqs = b43_interrupt_disable(dev, B43_IRQ_ALL);
3370 spin_unlock_irqrestore(&wl->irq_lock, flags);
3371 b43_synchronize_irq(dev);
3372 3391
3373 /* Switch to the requested channel. 3392 /* Switch to the requested channel.
3374 * The firmware takes care of races with the TX handler. */ 3393 * The firmware takes care of races with the TX handler. */
3375 if (conf->channel->hw_value != phy->channel) 3394 if (conf->channel->hw_value != phy->channel)
3376 b43_switch_channel(dev, conf->channel->hw_value); 3395 b43_switch_channel(dev, conf->channel->hw_value);
3377 3396
3378 /* Enable/Disable ShortSlot timing. */
3379 if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) !=
3380 dev->short_slot) {
3381 B43_WARN_ON(phy->type != B43_PHYTYPE_G);
3382 if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)
3383 b43_short_slot_timing_enable(dev);
3384 else
3385 b43_short_slot_timing_disable(dev);
3386 }
3387
3388 dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP); 3397 dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
3389 3398
3390 /* Adjust the desired TX power level. */ 3399 /* Adjust the desired TX power level. */
@@ -3399,9 +3408,9 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
3399 } 3408 }
3400 3409
3401 /* Antennas for RX and management frame TX. */ 3410 /* Antennas for RX and management frame TX. */
3402 antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx); 3411 antenna = B43_ANTENNA_DEFAULT;
3403 b43_mgmtframe_txantenna(dev, antenna); 3412 b43_mgmtframe_txantenna(dev, antenna);
3404 antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx); 3413 antenna = B43_ANTENNA_DEFAULT;
3405 if (phy->ops->set_rx_antenna) 3414 if (phy->ops->set_rx_antenna)
3406 phy->ops->set_rx_antenna(dev, antenna); 3415 phy->ops->set_rx_antenna(dev, antenna);
3407 3416
@@ -3425,16 +3434,91 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
3425 } 3434 }
3426 } 3435 }
3427 3436
3428 spin_lock_irqsave(&wl->irq_lock, flags); 3437out_mac_enable:
3429 b43_interrupt_enable(dev, savedirqs); 3438 b43_mac_enable(dev);
3430 mmiowb(); 3439out_unlock_mutex:
3431 spin_unlock_irqrestore(&wl->irq_lock, flags);
3432 out_unlock_mutex:
3433 mutex_unlock(&wl->mutex); 3440 mutex_unlock(&wl->mutex);
3434 3441
3435 return err; 3442 return err;
3436} 3443}
3437 3444
3445static void b43_update_basic_rates(struct b43_wldev *dev, u64 brates)
3446{
3447 struct ieee80211_supported_band *sband =
3448 dev->wl->hw->wiphy->bands[b43_current_band(dev->wl)];
3449 struct ieee80211_rate *rate;
3450 int i;
3451 u16 basic, direct, offset, basic_offset, rateptr;
3452
3453 for (i = 0; i < sband->n_bitrates; i++) {
3454 rate = &sband->bitrates[i];
3455
3456 if (b43_is_cck_rate(rate->hw_value)) {
3457 direct = B43_SHM_SH_CCKDIRECT;
3458 basic = B43_SHM_SH_CCKBASIC;
3459 offset = b43_plcp_get_ratecode_cck(rate->hw_value);
3460 offset &= 0xF;
3461 } else {
3462 direct = B43_SHM_SH_OFDMDIRECT;
3463 basic = B43_SHM_SH_OFDMBASIC;
3464 offset = b43_plcp_get_ratecode_ofdm(rate->hw_value);
3465 offset &= 0xF;
3466 }
3467
3468 rate = ieee80211_get_response_rate(sband, brates, rate->bitrate);
3469
3470 if (b43_is_cck_rate(rate->hw_value)) {
3471 basic_offset = b43_plcp_get_ratecode_cck(rate->hw_value);
3472 basic_offset &= 0xF;
3473 } else {
3474 basic_offset = b43_plcp_get_ratecode_ofdm(rate->hw_value);
3475 basic_offset &= 0xF;
3476 }
3477
3478 /*
3479 * Get the pointer that we need to point to
3480 * from the direct map
3481 */
3482 rateptr = b43_shm_read16(dev, B43_SHM_SHARED,
3483 direct + 2 * basic_offset);
3484 /* and write it to the basic map */
3485 b43_shm_write16(dev, B43_SHM_SHARED, basic + 2 * offset,
3486 rateptr);
3487 }
3488}
3489
3490static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
3491 struct ieee80211_vif *vif,
3492 struct ieee80211_bss_conf *conf,
3493 u32 changed)
3494{
3495 struct b43_wl *wl = hw_to_b43_wl(hw);
3496 struct b43_wldev *dev;
3497
3498 mutex_lock(&wl->mutex);
3499
3500 dev = wl->current_dev;
3501 if (!dev || b43_status(dev) < B43_STAT_STARTED)
3502 goto out_unlock_mutex;
3503 b43_mac_suspend(dev);
3504
3505 if (changed & BSS_CHANGED_BASIC_RATES)
3506 b43_update_basic_rates(dev, conf->basic_rates);
3507
3508 if (changed & BSS_CHANGED_ERP_SLOT) {
3509 if (conf->use_short_slot)
3510 b43_short_slot_timing_enable(dev);
3511 else
3512 b43_short_slot_timing_disable(dev);
3513 }
3514
3515 b43_mac_enable(dev);
3516out_unlock_mutex:
3517 mutex_unlock(&wl->mutex);
3518
3519 return;
3520}
3521
3438static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 3522static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3439 const u8 *local_addr, const u8 *addr, 3523 const u8 *local_addr, const u8 *addr,
3440 struct ieee80211_key_conf *key) 3524 struct ieee80211_key_conf *key)
@@ -3445,7 +3529,6 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3445 u8 algorithm; 3529 u8 algorithm;
3446 u8 index; 3530 u8 index;
3447 int err; 3531 int err;
3448 DECLARE_MAC_BUF(mac);
3449 3532
3450 if (modparam_nohwcrypt) 3533 if (modparam_nohwcrypt)
3451 return -ENOSPC; /* User disabled HW-crypto */ 3534 return -ENOSPC; /* User disabled HW-crypto */
@@ -3528,15 +3611,18 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3528 default: 3611 default:
3529 B43_WARN_ON(1); 3612 B43_WARN_ON(1);
3530 } 3613 }
3614
3531out_unlock: 3615out_unlock:
3532 spin_unlock_irqrestore(&wl->irq_lock, flags);
3533 mutex_unlock(&wl->mutex);
3534 if (!err) { 3616 if (!err) {
3535 b43dbg(wl, "%s hardware based encryption for keyidx: %d, " 3617 b43dbg(wl, "%s hardware based encryption for keyidx: %d, "
3536 "mac: %s\n", 3618 "mac: %pM\n",
3537 cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, 3619 cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
3538 print_mac(mac, addr)); 3620 addr);
3621 b43_dump_keymemory(dev);
3539 } 3622 }
3623 spin_unlock_irqrestore(&wl->irq_lock, flags);
3624 mutex_unlock(&wl->mutex);
3625
3540 return err; 3626 return err;
3541} 3627}
3542 3628
@@ -3598,8 +3684,6 @@ static int b43_op_config_interface(struct ieee80211_hw *hw,
3598 if (b43_is_mode(wl, NL80211_IFTYPE_AP) || 3684 if (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
3599 b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) { 3685 b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) {
3600 B43_WARN_ON(vif->type != wl->if_type); 3686 B43_WARN_ON(vif->type != wl->if_type);
3601 if (conf->changed & IEEE80211_IFCC_SSID)
3602 b43_set_ssid(dev, conf->ssid, conf->ssid_len);
3603 if (conf->changed & IEEE80211_IFCC_BEACON) 3687 if (conf->changed & IEEE80211_IFCC_BEACON)
3604 b43_update_templates(wl); 3688 b43_update_templates(wl);
3605 } else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) { 3689 } else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) {
@@ -3878,22 +3962,6 @@ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
3878#endif /* CONFIG_SSB_DRIVER_PCICORE */ 3962#endif /* CONFIG_SSB_DRIVER_PCICORE */
3879} 3963}
3880 3964
3881/* Write the short and long frame retry limit values. */
3882static void b43_set_retry_limits(struct b43_wldev *dev,
3883 unsigned int short_retry,
3884 unsigned int long_retry)
3885{
3886 /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
3887 * the chip-internal counter. */
3888 short_retry = min(short_retry, (unsigned int)0xF);
3889 long_retry = min(long_retry, (unsigned int)0xF);
3890
3891 b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT,
3892 short_retry);
3893 b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT,
3894 long_retry);
3895}
3896
3897static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle) 3965static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle)
3898{ 3966{
3899 u16 pu_delay; 3967 u16 pu_delay;
@@ -4214,26 +4282,6 @@ static void b43_op_stop(struct ieee80211_hw *hw)
4214 cancel_work_sync(&(wl->txpower_adjust_work)); 4282 cancel_work_sync(&(wl->txpower_adjust_work));
4215} 4283}
4216 4284
4217static int b43_op_set_retry_limit(struct ieee80211_hw *hw,
4218 u32 short_retry_limit, u32 long_retry_limit)
4219{
4220 struct b43_wl *wl = hw_to_b43_wl(hw);
4221 struct b43_wldev *dev;
4222 int err = 0;
4223
4224 mutex_lock(&wl->mutex);
4225 dev = wl->current_dev;
4226 if (unlikely(!dev || (b43_status(dev) < B43_STAT_INITIALIZED))) {
4227 err = -ENODEV;
4228 goto out_unlock;
4229 }
4230 b43_set_retry_limits(dev, short_retry_limit, long_retry_limit);
4231out_unlock:
4232 mutex_unlock(&wl->mutex);
4233
4234 return err;
4235}
4236
4237static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, 4285static int b43_op_beacon_set_tim(struct ieee80211_hw *hw,
4238 struct ieee80211_sta *sta, bool set) 4286 struct ieee80211_sta *sta, bool set)
4239{ 4287{
@@ -4263,6 +4311,7 @@ static const struct ieee80211_ops b43_hw_ops = {
4263 .add_interface = b43_op_add_interface, 4311 .add_interface = b43_op_add_interface,
4264 .remove_interface = b43_op_remove_interface, 4312 .remove_interface = b43_op_remove_interface,
4265 .config = b43_op_config, 4313 .config = b43_op_config,
4314 .bss_info_changed = b43_op_bss_info_changed,
4266 .config_interface = b43_op_config_interface, 4315 .config_interface = b43_op_config_interface,
4267 .configure_filter = b43_op_configure_filter, 4316 .configure_filter = b43_op_configure_filter,
4268 .set_key = b43_op_set_key, 4317 .set_key = b43_op_set_key,
@@ -4270,7 +4319,6 @@ static const struct ieee80211_ops b43_hw_ops = {
4270 .get_tx_stats = b43_op_get_tx_stats, 4319 .get_tx_stats = b43_op_get_tx_stats,
4271 .start = b43_op_start, 4320 .start = b43_op_start,
4272 .stop = b43_op_stop, 4321 .stop = b43_op_stop,
4273 .set_retry_limit = b43_op_set_retry_limit,
4274 .set_tim = b43_op_beacon_set_tim, 4322 .set_tim = b43_op_beacon_set_tim,
4275 .sta_notify = b43_op_sta_notify, 4323 .sta_notify = b43_op_sta_notify,
4276}; 4324};
@@ -4588,7 +4636,7 @@ static int b43_wireless_init(struct ssb_device *dev)
4588 BIT(NL80211_IFTYPE_ADHOC); 4636 BIT(NL80211_IFTYPE_ADHOC);
4589 4637
4590 hw->queues = b43_modparam_qos ? 4 : 1; 4638 hw->queues = b43_modparam_qos ? 4 : 1;
4591 hw->max_altrates = 1; 4639 hw->max_rates = 2;
4592 SET_IEEE80211_DEV(hw, dev->dev); 4640 SET_IEEE80211_DEV(hw, dev->dev);
4593 if (is_valid_ether_addr(sprom->et1mac)) 4641 if (is_valid_ether_addr(sprom->et1mac))
4594 SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); 4642 SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c
index 0f1a84c9de61..7fe9d1701624 100644
--- a/drivers/net/wireless/b43/phy_a.c
+++ b/drivers/net/wireless/b43/phy_a.c
@@ -77,7 +77,7 @@ static s8 b43_aphy_estimate_power_out(struct b43_wldev *dev, s8 tssi)
77} 77}
78#endif 78#endif
79 79
80void b43_radio_set_tx_iq(struct b43_wldev *dev) 80static void b43_radio_set_tx_iq(struct b43_wldev *dev)
81{ 81{
82 static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; 82 static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
83 static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; 83 static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
@@ -147,7 +147,7 @@ static void aphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
147//FIXME b43_phy_xmitpower(dev); 147//FIXME b43_phy_xmitpower(dev);
148} 148}
149 149
150void b43_radio_init2060(struct b43_wldev *dev) 150static void b43_radio_init2060(struct b43_wldev *dev)
151{ 151{
152 b43_radio_write16(dev, 0x0004, 0x00C0); 152 b43_radio_write16(dev, 0x0004, 0x00C0);
153 b43_radio_write16(dev, 0x0005, 0x0008); 153 b43_radio_write16(dev, 0x0005, 0x0008);
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index af37abccccb3..026b61c03fb9 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -178,13 +178,27 @@ void b43_phy_unlock(struct b43_wldev *dev)
178 b43_power_saving_ctl_bits(dev, 0); 178 b43_power_saving_ctl_bits(dev, 0);
179} 179}
180 180
181static inline void assert_mac_suspended(struct b43_wldev *dev)
182{
183 if (!B43_DEBUG)
184 return;
185 if ((b43_status(dev) >= B43_STAT_INITIALIZED) &&
186 (dev->mac_suspended <= 0)) {
187 b43dbg(dev->wl, "PHY/RADIO register access with "
188 "enabled MAC.\n");
189 dump_stack();
190 }
191}
192
181u16 b43_radio_read(struct b43_wldev *dev, u16 reg) 193u16 b43_radio_read(struct b43_wldev *dev, u16 reg)
182{ 194{
195 assert_mac_suspended(dev);
183 return dev->phy.ops->radio_read(dev, reg); 196 return dev->phy.ops->radio_read(dev, reg);
184} 197}
185 198
186void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value) 199void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
187{ 200{
201 assert_mac_suspended(dev);
188 dev->phy.ops->radio_write(dev, reg, value); 202 dev->phy.ops->radio_write(dev, reg, value);
189} 203}
190 204
@@ -208,11 +222,13 @@ void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
208 222
209u16 b43_phy_read(struct b43_wldev *dev, u16 reg) 223u16 b43_phy_read(struct b43_wldev *dev, u16 reg)
210{ 224{
225 assert_mac_suspended(dev);
211 return dev->phy.ops->phy_read(dev, reg); 226 return dev->phy.ops->phy_read(dev, reg);
212} 227}
213 228
214void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) 229void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
215{ 230{
231 assert_mac_suspended(dev);
216 dev->phy.ops->phy_write(dev, reg, value); 232 dev->phy.ops->phy_write(dev, reg, value);
217} 233}
218 234
@@ -280,8 +296,10 @@ void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state)
280 state = RFKILL_STATE_SOFT_BLOCKED; 296 state = RFKILL_STATE_SOFT_BLOCKED;
281 } 297 }
282 298
299 b43_mac_suspend(dev);
283 phy->ops->software_rfkill(dev, state); 300 phy->ops->software_rfkill(dev, state);
284 phy->radio_on = (state == RFKILL_STATE_UNBLOCKED); 301 phy->radio_on = (state == RFKILL_STATE_UNBLOCKED);
302 b43_mac_enable(dev);
285} 303}
286 304
287/** 305/**
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c
index 232181f6333c..caac4a45f0bf 100644
--- a/drivers/net/wireless/b43/phy_g.c
+++ b/drivers/net/wireless/b43/phy_g.c
@@ -54,7 +54,7 @@ static const s8 b43_tssi2dbm_g_table[] = {
54 -20, -20, -20, -20, 54 -20, -20, -20, -20,
55}; 55};
56 56
57const u8 b43_radio_channel_codes_bg[] = { 57static const u8 b43_radio_channel_codes_bg[] = {
58 12, 17, 22, 27, 58 12, 17, 22, 27,
59 32, 37, 42, 47, 59 32, 37, 42, 47,
60 52, 57, 62, 67, 60 52, 57, 62, 67,
@@ -215,9 +215,9 @@ void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev,
215} 215}
216 216
217/* Adjust the transmission power output (G-PHY) */ 217/* Adjust the transmission power output (G-PHY) */
218void b43_set_txpower_g(struct b43_wldev *dev, 218static void b43_set_txpower_g(struct b43_wldev *dev,
219 const struct b43_bbatt *bbatt, 219 const struct b43_bbatt *bbatt,
220 const struct b43_rfatt *rfatt, u8 tx_control) 220 const struct b43_rfatt *rfatt, u8 tx_control)
221{ 221{
222 struct b43_phy *phy = &dev->phy; 222 struct b43_phy *phy = &dev->phy;
223 struct b43_phy_g *gphy = phy->g; 223 struct b43_phy_g *gphy = phy->g;
@@ -383,14 +383,14 @@ static void b43_set_original_gains(struct b43_wldev *dev)
383} 383}
384 384
385/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ 385/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
386void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val) 386static void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val)
387{ 387{
388 b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset); 388 b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset);
389 b43_phy_write(dev, B43_PHY_NRSSILT_DATA, (u16) val); 389 b43_phy_write(dev, B43_PHY_NRSSILT_DATA, (u16) val);
390} 390}
391 391
392/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ 392/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
393s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset) 393static s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset)
394{ 394{
395 u16 val; 395 u16 val;
396 396
@@ -401,7 +401,7 @@ s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset)
401} 401}
402 402
403/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ 403/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
404void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val) 404static void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val)
405{ 405{
406 u16 i; 406 u16 i;
407 s16 tmp; 407 s16 tmp;
@@ -415,7 +415,7 @@ void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val)
415} 415}
416 416
417/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ 417/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
418void b43_nrssi_mem_update(struct b43_wldev *dev) 418static void b43_nrssi_mem_update(struct b43_wldev *dev)
419{ 419{
420 struct b43_phy_g *gphy = dev->phy.g; 420 struct b43_phy_g *gphy = dev->phy.g;
421 s16 i, delta; 421 s16 i, delta;
@@ -589,7 +589,7 @@ static void b43_calc_nrssi_offset(struct b43_wldev *dev)
589 b43_phy_write(dev, 0x0811, backup[1]); 589 b43_phy_write(dev, 0x0811, backup[1]);
590} 590}
591 591
592void b43_calc_nrssi_slope(struct b43_wldev *dev) 592static void b43_calc_nrssi_slope(struct b43_wldev *dev)
593{ 593{
594 struct b43_phy *phy = &dev->phy; 594 struct b43_phy *phy = &dev->phy;
595 struct b43_phy_g *gphy = phy->g; 595 struct b43_phy_g *gphy = phy->g;
@@ -1354,7 +1354,7 @@ struct init2050_saved_values {
1354 u16 phy_syncctl; 1354 u16 phy_syncctl;
1355}; 1355};
1356 1356
1357u16 b43_radio_init2050(struct b43_wldev *dev) 1357static u16 b43_radio_init2050(struct b43_wldev *dev)
1358{ 1358{
1359 struct b43_phy *phy = &dev->phy; 1359 struct b43_phy *phy = &dev->phy;
1360 struct init2050_saved_values sav; 1360 struct init2050_saved_values sav;
@@ -3047,6 +3047,8 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
3047 int rfatt, bbatt; 3047 int rfatt, bbatt;
3048 u8 tx_control; 3048 u8 tx_control;
3049 3049
3050 b43_mac_suspend(dev);
3051
3050 spin_lock_irq(&dev->wl->irq_lock); 3052 spin_lock_irq(&dev->wl->irq_lock);
3051 3053
3052 /* Calculate the new attenuation values. */ 3054 /* Calculate the new attenuation values. */
@@ -3103,6 +3105,8 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
3103 gphy->tx_control); 3105 gphy->tx_control);
3104 b43_radio_unlock(dev); 3106 b43_radio_unlock(dev);
3105 b43_phy_unlock(dev); 3107 b43_phy_unlock(dev);
3108
3109 b43_mac_enable(dev);
3106} 3110}
3107 3111
3108static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev, 3112static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,
@@ -3215,9 +3219,9 @@ static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev)
3215 struct b43_phy *phy = &dev->phy; 3219 struct b43_phy *phy = &dev->phy;
3216 struct b43_phy_g *gphy = phy->g; 3220 struct b43_phy_g *gphy = phy->g;
3217 3221
3222 b43_mac_suspend(dev);
3218 //TODO: update_aci_moving_average 3223 //TODO: update_aci_moving_average
3219 if (gphy->aci_enable && gphy->aci_wlan_automatic) { 3224 if (gphy->aci_enable && gphy->aci_wlan_automatic) {
3220 b43_mac_suspend(dev);
3221 if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) { 3225 if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) {
3222 if (0 /*TODO: bunch of conditions */ ) { 3226 if (0 /*TODO: bunch of conditions */ ) {
3223 phy->ops->interf_mitigation(dev, 3227 phy->ops->interf_mitigation(dev,
@@ -3227,12 +3231,12 @@ static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev)
3227 if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev)) 3231 if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev))
3228 phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE); 3232 phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE);
3229 } 3233 }
3230 b43_mac_enable(dev);
3231 } else if (gphy->interfmode == B43_INTERFMODE_NONWLAN && 3234 } else if (gphy->interfmode == B43_INTERFMODE_NONWLAN &&
3232 phy->rev == 1) { 3235 phy->rev == 1) {
3233 //TODO: implement rev1 workaround 3236 //TODO: implement rev1 workaround
3234 } 3237 }
3235 b43_lo_g_maintanance_work(dev); 3238 b43_lo_g_maintanance_work(dev);
3239 b43_mac_enable(dev);
3236} 3240}
3237 3241
3238static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev) 3242static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 401591267592..1036bef8c4cc 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -587,9 +587,8 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
587 spin_lock(&q->lock); /* IRQs are already disabled. */ 587 spin_lock(&q->lock); /* IRQs are already disabled. */
588 588
589 info = IEEE80211_SKB_CB(pack->skb); 589 info = IEEE80211_SKB_CB(pack->skb);
590 memset(&info->status, 0, sizeof(info->status));
591 590
592 b43_fill_txstatus_report(info, status); 591 b43_fill_txstatus_report(dev, info, status);
593 592
594 total_len = pack->skb->len + b43_txhdr_size(dev); 593 total_len = pack->skb->len + b43_txhdr_size(dev);
595 total_len = roundup(total_len, 4); 594 total_len = roundup(total_len, 4);
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 2fabcf8f0474..eae9b8052658 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -46,7 +46,6 @@ static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
46 case 0x6E: 46 case 0x6E:
47 return 3; 47 return 3;
48 } 48 }
49 B43_WARN_ON(1);
50 return -1; 49 return -1;
51} 50}
52 51
@@ -73,7 +72,6 @@ static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
73 case 0xC: 72 case 0xC:
74 return base + 7; 73 return base + 7;
75 } 74 }
76 B43_WARN_ON(1);
77 return -1; 75 return -1;
78} 76}
79 77
@@ -185,7 +183,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
185 u8 *_txhdr, 183 u8 *_txhdr,
186 const unsigned char *fragment_data, 184 const unsigned char *fragment_data,
187 unsigned int fragment_len, 185 unsigned int fragment_len,
188 const struct ieee80211_tx_info *info, 186 struct ieee80211_tx_info *info,
189 u16 cookie) 187 u16 cookie)
190{ 188{
191 struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; 189 struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
@@ -202,6 +200,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
202 u16 phy_ctl = 0; 200 u16 phy_ctl = 0;
203 u8 extra_ft = 0; 201 u8 extra_ft = 0;
204 struct ieee80211_rate *txrate; 202 struct ieee80211_rate *txrate;
203 struct ieee80211_tx_rate *rates;
205 204
206 memset(txhdr, 0, sizeof(*txhdr)); 205 memset(txhdr, 0, sizeof(*txhdr));
207 206
@@ -291,7 +290,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
291 phy_ctl |= B43_TXH_PHY_ENC_OFDM; 290 phy_ctl |= B43_TXH_PHY_ENC_OFDM;
292 else 291 else
293 phy_ctl |= B43_TXH_PHY_ENC_CCK; 292 phy_ctl |= B43_TXH_PHY_ENC_CCK;
294 if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) 293 if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
295 phy_ctl |= B43_TXH_PHY_SHORTPRMBL; 294 phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
296 295
297 switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) { 296 switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) {
@@ -314,6 +313,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
314 B43_WARN_ON(1); 313 B43_WARN_ON(1);
315 } 314 }
316 315
316 rates = info->control.rates;
317 /* MAC control */ 317 /* MAC control */
318 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) 318 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
319 mac_ctl |= B43_TXH_MAC_ACK; 319 mac_ctl |= B43_TXH_MAC_ACK;
@@ -324,12 +324,22 @@ int b43_generate_txhdr(struct b43_wldev *dev,
324 mac_ctl |= B43_TXH_MAC_STMSDU; 324 mac_ctl |= B43_TXH_MAC_STMSDU;
325 if (phy->type == B43_PHYTYPE_A) 325 if (phy->type == B43_PHYTYPE_A)
326 mac_ctl |= B43_TXH_MAC_5GHZ; 326 mac_ctl |= B43_TXH_MAC_5GHZ;
327 if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) 327
328 /* Overwrite rates[0].count to make the retry calculation
329 * in the tx status easier. need the actual retry limit to
330 * detect whether the fallback rate was used.
331 */
332 if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
333 (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
334 rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
328 mac_ctl |= B43_TXH_MAC_LONGFRAME; 335 mac_ctl |= B43_TXH_MAC_LONGFRAME;
336 } else {
337 rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
338 }
329 339
330 /* Generate the RTS or CTS-to-self frame */ 340 /* Generate the RTS or CTS-to-self frame */
331 if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || 341 if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
332 (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { 342 (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
333 unsigned int len; 343 unsigned int len;
334 struct ieee80211_hdr *hdr; 344 struct ieee80211_hdr *hdr;
335 int rts_rate, rts_rate_fb; 345 int rts_rate, rts_rate_fb;
@@ -344,7 +354,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
344 rts_rate_fb = b43_calc_fallback_rate(rts_rate); 354 rts_rate_fb = b43_calc_fallback_rate(rts_rate);
345 rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); 355 rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
346 356
347 if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { 357 if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
348 struct ieee80211_cts *cts; 358 struct ieee80211_cts *cts;
349 359
350 if (b43_is_old_txhdr_format(dev)) { 360 if (b43_is_old_txhdr_format(dev)) {
@@ -596,6 +606,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
596 phytype == B43_PHYTYPE_A); 606 phytype == B43_PHYTYPE_A);
597 else 607 else
598 status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); 608 status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
609 if (unlikely(status.rate_idx == -1))
610 goto drop;
599 status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); 611 status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
600 612
601 /* 613 /*
@@ -687,10 +699,18 @@ void b43_handle_txstatus(struct b43_wldev *dev,
687/* Fill out the mac80211 TXstatus report based on the b43-specific 699/* Fill out the mac80211 TXstatus report based on the b43-specific
688 * txstatus report data. This returns a boolean whether the frame was 700 * txstatus report data. This returns a boolean whether the frame was
689 * successfully transmitted. */ 701 * successfully transmitted. */
690bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, 702bool b43_fill_txstatus_report(struct b43_wldev *dev,
703 struct ieee80211_tx_info *report,
691 const struct b43_txstatus *status) 704 const struct b43_txstatus *status)
692{ 705{
693 bool frame_success = 1; 706 bool frame_success = 1;
707 int retry_limit;
708
709 /* preserve the confiured retry limit before clearing the status
710 * The xmit function has overwritten the rc's value with the actual
711 * retry limit done by the hardware */
712 retry_limit = report->status.rates[0].count;
713 ieee80211_tx_info_clear_status(report);
694 714
695 if (status->acked) { 715 if (status->acked) {
696 /* The frame was ACKed. */ 716 /* The frame was ACKed. */
@@ -700,14 +720,32 @@ bool b43_fill_txstatus_report(struct ieee80211_tx_info *report,
700 if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) { 720 if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) {
701 /* ...but we expected an ACK. */ 721 /* ...but we expected an ACK. */
702 frame_success = 0; 722 frame_success = 0;
703 report->status.excessive_retries = 1;
704 } 723 }
705 } 724 }
706 if (status->frame_count == 0) { 725 if (status->frame_count == 0) {
707 /* The frame was not transmitted at all. */ 726 /* The frame was not transmitted at all. */
708 report->status.retry_count = 0; 727 report->status.rates[0].count = 0;
709 } else 728 } else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
710 report->status.retry_count = status->frame_count - 1; 729 /*
730 * If the short retries (RTS, not data frame) have exceeded
731 * the limit, the hw will not have tried the selected rate,
732 * but will have used the fallback rate instead.
733 * Don't let the rate control count attempts for the selected
734 * rate in this case, otherwise the statistics will be off.
735 */
736 report->status.rates[0].count = 0;
737 report->status.rates[1].count = status->frame_count;
738 } else {
739 if (status->frame_count > retry_limit) {
740 report->status.rates[0].count = retry_limit;
741 report->status.rates[1].count = status->frame_count -
742 retry_limit;
743
744 } else {
745 report->status.rates[0].count = status->frame_count;
746 report->status.rates[1].idx = -1;
747 }
748 }
711 749
712 return frame_success; 750 return frame_success;
713} 751}
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index 0215faf47541..4fb2a190f7a7 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -178,7 +178,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
178 u8 * txhdr, 178 u8 * txhdr,
179 const unsigned char *fragment_data, 179 const unsigned char *fragment_data,
180 unsigned int fragment_len, 180 unsigned int fragment_len,
181 const struct ieee80211_tx_info *txctl, u16 cookie); 181 struct ieee80211_tx_info *txctl, u16 cookie);
182 182
183/* Transmit Status */ 183/* Transmit Status */
184struct b43_txstatus { 184struct b43_txstatus {
@@ -294,7 +294,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr);
294 294
295void b43_handle_txstatus(struct b43_wldev *dev, 295void b43_handle_txstatus(struct b43_wldev *dev,
296 const struct b43_txstatus *status); 296 const struct b43_txstatus *status);
297bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, 297bool b43_fill_txstatus_report(struct b43_wldev *dev,
298 struct ieee80211_tx_info *report,
298 const struct b43_txstatus *status); 299 const struct b43_txstatus *status);
299 300
300void b43_tx_suspend(struct b43_wldev *dev); 301void b43_tx_suspend(struct b43_wldev *dev);