diff options
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r-- | drivers/net/wireless/b43/b43.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/b43/debugfs.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/b43/debugfs.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/b43/dma.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 280 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_a.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_common.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_g.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/b43/pio.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/b43/xmit.c | 64 | ||||
-rw-r--r-- | drivers/net/wireless/b43/xmit.h | 5 |
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 { bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */ bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ - bool short_slot; /* TRUE, if short slot timing is enabled. */ bool radio_hw_enable; /* saved state of radio hardware enabled state */ bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */ 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) add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); add_dyn_dbg("debug_lo", B43_DBG_LO, 0); add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); + add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0); #undef add_dyn_dbg } 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 */ B43_DBG_PWORK_STOP, B43_DBG_LO, B43_DBG_FIRMWARE, + B43_DBG_KEYS, __B43_NR_DYNDBG, }; 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, info = IEEE80211_SKB_CB(meta->skb); - memset(&info->status, 0, sizeof(info->status)); - /* * Call back to inform the ieee80211 subsystem about * the status of the transmission. */ - frame_succeed = b43_fill_txstatus_report(info, status); + frame_succeed = b43_fill_txstatus_report(dev, info, status); #ifdef CONFIG_B43_DEBUG if (frame_succeed) 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) static void b43_short_slot_timing_enable(struct b43_wldev *dev) { b43_set_slot_time(dev, 9); - dev->short_slot = 1; } static void b43_short_slot_timing_disable(struct b43_wldev *dev) { b43_set_slot_time(dev, 20); - dev->short_slot = 0; } /* 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) b43_key_clear(dev, i); } +static void b43_dump_keymemory(struct b43_wldev *dev) +{ + unsigned int i, index, offset; + DECLARE_MAC_BUF(macbuf); + u8 mac[ETH_ALEN]; + u16 algo; + u32 rcmta0; + u16 rcmta1; + u64 hf; + struct b43_key *key; + + if (!b43_debug(dev, B43_DBG_KEYS)) + return; + + hf = b43_hf_read(dev); + b43dbg(dev->wl, "Hardware key memory dump: USEDEFKEYS=%u\n", + !!(hf & B43_HF_USEDEFKEYS)); + for (index = 0; index < dev->max_nr_keys; index++) { + key = &(dev->key[index]); + printk(KERN_DEBUG "Key slot %02u: %s", + index, (key->keyconf == NULL) ? " " : "*"); + offset = dev->ktp + (index * B43_SEC_KEYSIZE); + for (i = 0; i < B43_SEC_KEYSIZE; i += 2) { + u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, offset + i); + printk("%02X%02X", (tmp & 0xFF), ((tmp >> 8) & 0xFF)); + } + + algo = b43_shm_read16(dev, B43_SHM_SHARED, + B43_SHM_SH_KEYIDXBLOCK + (index * 2)); + printk(" Algo: %04X/%02X", algo, key->algorithm); + + if (index >= 4) { + rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA, + ((index - 4) * 2) + 0); + rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA, + ((index - 4) * 2) + 1); + *((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0); + *((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1); + printk(" MAC: %s", + print_mac(macbuf, mac)); + } else + printk(" DEFAULT KEY"); + printk("\n"); + } +} + void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags) { u32 macctl; @@ -1339,25 +1383,6 @@ u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev, return antenna_nr; } -static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna) -{ - antenna = b43_ieee80211_antenna_sanitize(dev, antenna); - switch (antenna) { - case 0: /* default/diversity */ - return B43_ANTENNA_DEFAULT; - case 1: /* Antenna 0 */ - return B43_ANTENNA0; - case 2: /* Antenna 1 */ - return B43_ANTENNA1; - case 3: /* Antenna 2 */ - return B43_ANTENNA2; - case 4: /* Antenna 3 */ - return B43_ANTENNA3; - default: - return B43_ANTENNA_DEFAULT; - } -} - /* Convert a b43 antenna number value to the PHY TX control value. */ static u16 b43_antenna_to_phyctl(int antenna) { @@ -1399,7 +1424,7 @@ static void b43_write_beacon_template(struct b43_wldev *dev, len, ram_offset, shm_size_offset, rate); /* Write the PHY TX control parameters. */ - antenna = b43_antenna_from_ieee80211(dev, info->antenna_sel_tx); + antenna = B43_ANTENNA_DEFAULT; antenna = b43_antenna_to_phyctl(antenna); ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); /* 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) queue_work(wl->hw->workqueue, &wl->beacon_update_trigger); } -static void b43_set_ssid(struct b43_wldev *dev, const u8 * ssid, u8 ssid_len) -{ - u32 tmp; - u16 i, len; - - len = min((u16) ssid_len, (u16) 0x100); - for (i = 0; i < len; i += sizeof(u32)) { - tmp = (u32) (ssid[i + 0]); - if (i + 1 < len) - tmp |= (u32) (ssid[i + 1]) << 8; - if (i + 2 < len) - tmp |= (u32) (ssid[i + 2]) << 16; - if (i + 3 < len) - tmp |= (u32) (ssid[i + 3]) << 24; - b43_shm_write32(dev, B43_SHM_SHARED, 0x380 + i, tmp); - } - b43_shm_write16(dev, B43_SHM_SHARED, 0x48, len); -} - static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) { b43_time_lock(dev); @@ -3339,15 +3345,31 @@ init_failure: return err; } -static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) +/* Write the short and long frame retry limit values. */ +static void b43_set_retry_limits(struct b43_wldev *dev, + unsigned int short_retry, + unsigned int long_retry) +{ + /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing + * the chip-internal counter. */ + short_retry = min(short_retry, (unsigned int)0xF); + long_retry = min(long_retry, (unsigned int)0xF); + + b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT, + short_retry); + b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT, + long_retry); +} + +static int b43_op_config(struct ieee80211_hw *hw, u32 changed) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; struct b43_phy *phy; + struct ieee80211_conf *conf = &hw->conf; unsigned long flags; int antenna; int err = 0; - u32 savedirqs; mutex_lock(&wl->mutex); @@ -3358,33 +3380,20 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) dev = wl->current_dev; phy = &dev->phy; - /* Disable IRQs while reconfiguring the device. - * This makes it possible to drop the spinlock throughout - * the reconfiguration process. */ - spin_lock_irqsave(&wl->irq_lock, flags); - if (b43_status(dev) < B43_STAT_STARTED) { - spin_unlock_irqrestore(&wl->irq_lock, flags); - goto out_unlock_mutex; - } - savedirqs = b43_interrupt_disable(dev, B43_IRQ_ALL); - spin_unlock_irqrestore(&wl->irq_lock, flags); - b43_synchronize_irq(dev); + b43_mac_suspend(dev); + + if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) + b43_set_retry_limits(dev, conf->short_frame_max_tx_count, + conf->long_frame_max_tx_count); + changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS; + if (!changed) + goto out_mac_enable; /* Switch to the requested channel. * The firmware takes care of races with the TX handler. */ if (conf->channel->hw_value != phy->channel) b43_switch_channel(dev, conf->channel->hw_value); - /* Enable/Disable ShortSlot timing. */ - if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) != - dev->short_slot) { - B43_WARN_ON(phy->type != B43_PHYTYPE_G); - if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) - b43_short_slot_timing_enable(dev); - else - b43_short_slot_timing_disable(dev); - } - dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP); /* Adjust the desired TX power level. */ @@ -3399,9 +3408,9 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) } /* Antennas for RX and management frame TX. */ - antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx); + antenna = B43_ANTENNA_DEFAULT; b43_mgmtframe_txantenna(dev, antenna); - antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx); + antenna = B43_ANTENNA_DEFAULT; if (phy->ops->set_rx_antenna) phy->ops->set_rx_antenna(dev, antenna); @@ -3425,16 +3434,91 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) } } - spin_lock_irqsave(&wl->irq_lock, flags); - b43_interrupt_enable(dev, savedirqs); - mmiowb(); - spin_unlock_irqrestore(&wl->irq_lock, flags); - out_unlock_mutex: +out_mac_enable: + b43_mac_enable(dev); +out_unlock_mutex: mutex_unlock(&wl->mutex); return err; } +static void b43_update_basic_rates(struct b43_wldev *dev, u64 brates) +{ + struct ieee80211_supported_band *sband = + dev->wl->hw->wiphy->bands[b43_current_band(dev->wl)]; + struct ieee80211_rate *rate; + int i; + u16 basic, direct, offset, basic_offset, rateptr; + + for (i = 0; i < sband->n_bitrates; i++) { + rate = &sband->bitrates[i]; + + if (b43_is_cck_rate(rate->hw_value)) { + direct = B43_SHM_SH_CCKDIRECT; + basic = B43_SHM_SH_CCKBASIC; + offset = b43_plcp_get_ratecode_cck(rate->hw_value); + offset &= 0xF; + } else { + direct = B43_SHM_SH_OFDMDIRECT; + basic = B43_SHM_SH_OFDMBASIC; + offset = b43_plcp_get_ratecode_ofdm(rate->hw_value); + offset &= 0xF; + } + + rate = ieee80211_get_response_rate(sband, brates, rate->bitrate); + + if (b43_is_cck_rate(rate->hw_value)) { + basic_offset = b43_plcp_get_ratecode_cck(rate->hw_value); + basic_offset &= 0xF; + } else { + basic_offset = b43_plcp_get_ratecode_ofdm(rate->hw_value); + basic_offset &= 0xF; + } + + /* + * Get the pointer that we need to point to + * from the direct map + */ + rateptr = b43_shm_read16(dev, B43_SHM_SHARED, + direct + 2 * basic_offset); + /* and write it to the basic map */ + b43_shm_write16(dev, B43_SHM_SHARED, basic + 2 * offset, + rateptr); + } +} + +static void b43_op_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, + u32 changed) +{ + struct b43_wl *wl = hw_to_b43_wl(hw); + struct b43_wldev *dev; + + mutex_lock(&wl->mutex); + + dev = wl->current_dev; + if (!dev || b43_status(dev) < B43_STAT_STARTED) + goto out_unlock_mutex; + b43_mac_suspend(dev); + + if (changed & BSS_CHANGED_BASIC_RATES) + b43_update_basic_rates(dev, conf->basic_rates); + + if (changed & BSS_CHANGED_ERP_SLOT) { + if (conf->use_short_slot) + b43_short_slot_timing_enable(dev); + else + b43_short_slot_timing_disable(dev); + } + + b43_mac_enable(dev); +out_unlock_mutex: + mutex_unlock(&wl->mutex); + + return; +} + static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, const u8 *local_addr, const u8 *addr, struct ieee80211_key_conf *key) @@ -3445,7 +3529,6 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, u8 algorithm; u8 index; int err; - DECLARE_MAC_BUF(mac); if (modparam_nohwcrypt) 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, default: B43_WARN_ON(1); } + out_unlock: - spin_unlock_irqrestore(&wl->irq_lock, flags); - mutex_unlock(&wl->mutex); if (!err) { b43dbg(wl, "%s hardware based encryption for keyidx: %d, " - "mac: %s\n", + "mac: %pM\n", cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, - print_mac(mac, addr)); + addr); + b43_dump_keymemory(dev); } + spin_unlock_irqrestore(&wl->irq_lock, flags); + mutex_unlock(&wl->mutex); + return err; } @@ -3598,8 +3684,6 @@ static int b43_op_config_interface(struct ieee80211_hw *hw, if (b43_is_mode(wl, NL80211_IFTYPE_AP) || b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) { B43_WARN_ON(vif->type != wl->if_type); - if (conf->changed & IEEE80211_IFCC_SSID) - b43_set_ssid(dev, conf->ssid, conf->ssid_len); if (conf->changed & IEEE80211_IFCC_BEACON) b43_update_templates(wl); } else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) { @@ -3878,22 +3962,6 @@ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev) #endif /* CONFIG_SSB_DRIVER_PCICORE */ } -/* Write the short and long frame retry limit values. */ -static void b43_set_retry_limits(struct b43_wldev *dev, - unsigned int short_retry, - unsigned int long_retry) -{ - /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing - * the chip-internal counter. */ - short_retry = min(short_retry, (unsigned int)0xF); - long_retry = min(long_retry, (unsigned int)0xF); - - b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT, - short_retry); - b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT, - long_retry); -} - static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle) { u16 pu_delay; @@ -4214,26 +4282,6 @@ static void b43_op_stop(struct ieee80211_hw *hw) cancel_work_sync(&(wl->txpower_adjust_work)); } -static int b43_op_set_retry_limit(struct ieee80211_hw *hw, - u32 short_retry_limit, u32 long_retry_limit) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - int err = 0; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (unlikely(!dev || (b43_status(dev) < B43_STAT_INITIALIZED))) { - err = -ENODEV; - goto out_unlock; - } - b43_set_retry_limits(dev, short_retry_limit, long_retry_limit); -out_unlock: - mutex_unlock(&wl->mutex); - - return err; -} - static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) { @@ -4263,6 +4311,7 @@ static const struct ieee80211_ops b43_hw_ops = { .add_interface = b43_op_add_interface, .remove_interface = b43_op_remove_interface, .config = b43_op_config, + .bss_info_changed = b43_op_bss_info_changed, .config_interface = b43_op_config_interface, .configure_filter = b43_op_configure_filter, .set_key = b43_op_set_key, @@ -4270,7 +4319,6 @@ static const struct ieee80211_ops b43_hw_ops = { .get_tx_stats = b43_op_get_tx_stats, .start = b43_op_start, .stop = b43_op_stop, - .set_retry_limit = b43_op_set_retry_limit, .set_tim = b43_op_beacon_set_tim, .sta_notify = b43_op_sta_notify, }; @@ -4588,7 +4636,7 @@ static int b43_wireless_init(struct ssb_device *dev) BIT(NL80211_IFTYPE_ADHOC); hw->queues = b43_modparam_qos ? 4 : 1; - hw->max_altrates = 1; + hw->max_rates = 2; SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) 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) } #endif -void b43_radio_set_tx_iq(struct b43_wldev *dev) +static void b43_radio_set_tx_iq(struct b43_wldev *dev) { static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; 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) //FIXME b43_phy_xmitpower(dev); } -void b43_radio_init2060(struct b43_wldev *dev) +static void b43_radio_init2060(struct b43_wldev *dev) { b43_radio_write16(dev, 0x0004, 0x00C0); 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) b43_power_saving_ctl_bits(dev, 0); } +static inline void assert_mac_suspended(struct b43_wldev *dev) +{ + if (!B43_DEBUG) + return; + if ((b43_status(dev) >= B43_STAT_INITIALIZED) && + (dev->mac_suspended <= 0)) { + b43dbg(dev->wl, "PHY/RADIO register access with " + "enabled MAC.\n"); + dump_stack(); + } +} + u16 b43_radio_read(struct b43_wldev *dev, u16 reg) { + assert_mac_suspended(dev); return dev->phy.ops->radio_read(dev, reg); } void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value) { + assert_mac_suspended(dev); dev->phy.ops->radio_write(dev, reg, value); } @@ -208,11 +222,13 @@ void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) u16 b43_phy_read(struct b43_wldev *dev, u16 reg) { + assert_mac_suspended(dev); return dev->phy.ops->phy_read(dev, reg); } void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) { + assert_mac_suspended(dev); dev->phy.ops->phy_write(dev, reg, value); } @@ -280,8 +296,10 @@ void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state) state = RFKILL_STATE_SOFT_BLOCKED; } + b43_mac_suspend(dev); phy->ops->software_rfkill(dev, state); phy->radio_on = (state == RFKILL_STATE_UNBLOCKED); + b43_mac_enable(dev); } /** 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[] = { -20, -20, -20, -20, }; -const u8 b43_radio_channel_codes_bg[] = { +static const u8 b43_radio_channel_codes_bg[] = { 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, @@ -215,9 +215,9 @@ void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev, } /* Adjust the transmission power output (G-PHY) */ -void b43_set_txpower_g(struct b43_wldev *dev, - const struct b43_bbatt *bbatt, - const struct b43_rfatt *rfatt, u8 tx_control) +static void b43_set_txpower_g(struct b43_wldev *dev, + const struct b43_bbatt *bbatt, + const struct b43_rfatt *rfatt, u8 tx_control) { struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; @@ -383,14 +383,14 @@ static void b43_set_original_gains(struct b43_wldev *dev) } /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val) +static void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val) { b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset); b43_phy_write(dev, B43_PHY_NRSSILT_DATA, (u16) val); } /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset) +static s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset) { u16 val; @@ -401,7 +401,7 @@ s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset) } /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val) +static void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val) { u16 i; s16 tmp; @@ -415,7 +415,7 @@ void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val) } /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -void b43_nrssi_mem_update(struct b43_wldev *dev) +static void b43_nrssi_mem_update(struct b43_wldev *dev) { struct b43_phy_g *gphy = dev->phy.g; s16 i, delta; @@ -589,7 +589,7 @@ static void b43_calc_nrssi_offset(struct b43_wldev *dev) b43_phy_write(dev, 0x0811, backup[1]); } -void b43_calc_nrssi_slope(struct b43_wldev *dev) +static void b43_calc_nrssi_slope(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; @@ -1354,7 +1354,7 @@ struct init2050_saved_values { u16 phy_syncctl; }; -u16 b43_radio_init2050(struct b43_wldev *dev) +static u16 b43_radio_init2050(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; struct init2050_saved_values sav; @@ -3047,6 +3047,8 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev) int rfatt, bbatt; u8 tx_control; + b43_mac_suspend(dev); + spin_lock_irq(&dev->wl->irq_lock); /* Calculate the new attenuation values. */ @@ -3103,6 +3105,8 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev) gphy->tx_control); b43_radio_unlock(dev); b43_phy_unlock(dev); + + b43_mac_enable(dev); } static 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) struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; + b43_mac_suspend(dev); //TODO: update_aci_moving_average if (gphy->aci_enable && gphy->aci_wlan_automatic) { - b43_mac_suspend(dev); if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) { if (0 /*TODO: bunch of conditions */ ) { phy->ops->interf_mitigation(dev, @@ -3227,12 +3231,12 @@ static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev) if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev)) phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE); } - b43_mac_enable(dev); } else if (gphy->interfmode == B43_INTERFMODE_NONWLAN && phy->rev == 1) { //TODO: implement rev1 workaround } b43_lo_g_maintanance_work(dev); + b43_mac_enable(dev); } static 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, spin_lock(&q->lock); /* IRQs are already disabled. */ info = IEEE80211_SKB_CB(pack->skb); - memset(&info->status, 0, sizeof(info->status)); - b43_fill_txstatus_report(info, status); + b43_fill_txstatus_report(dev, info, status); total_len = pack->skb->len + b43_txhdr_size(dev); 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) case 0x6E: return 3; } - B43_WARN_ON(1); return -1; } @@ -73,7 +72,6 @@ static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy) case 0xC: return base + 7; } - B43_WARN_ON(1); return -1; } @@ -185,7 +183,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, u8 *_txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_info *info, + struct ieee80211_tx_info *info, u16 cookie) { struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; @@ -202,6 +200,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, u16 phy_ctl = 0; u8 extra_ft = 0; struct ieee80211_rate *txrate; + struct ieee80211_tx_rate *rates; memset(txhdr, 0, sizeof(*txhdr)); @@ -291,7 +290,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, phy_ctl |= B43_TXH_PHY_ENC_OFDM; else phy_ctl |= B43_TXH_PHY_ENC_CCK; - if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) phy_ctl |= B43_TXH_PHY_SHORTPRMBL; switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) { @@ -314,6 +313,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, B43_WARN_ON(1); } + rates = info->control.rates; /* MAC control */ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) mac_ctl |= B43_TXH_MAC_ACK; @@ -324,12 +324,22 @@ int b43_generate_txhdr(struct b43_wldev *dev, mac_ctl |= B43_TXH_MAC_STMSDU; if (phy->type == B43_PHYTYPE_A) mac_ctl |= B43_TXH_MAC_5GHZ; - if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) + + /* Overwrite rates[0].count to make the retry calculation + * in the tx status easier. need the actual retry limit to + * detect whether the fallback rate was used. + */ + if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) { + rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count; mac_ctl |= B43_TXH_MAC_LONGFRAME; + } else { + rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count; + } /* Generate the RTS or CTS-to-self frame */ - if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || - (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { + if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { unsigned int len; struct ieee80211_hdr *hdr; int rts_rate, rts_rate_fb; @@ -344,7 +354,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, rts_rate_fb = b43_calc_fallback_rate(rts_rate); rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); - if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { struct ieee80211_cts *cts; 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) phytype == B43_PHYTYPE_A); else status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); + if (unlikely(status.rate_idx == -1)) + goto drop; status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); /* @@ -687,10 +699,18 @@ void b43_handle_txstatus(struct b43_wldev *dev, /* Fill out the mac80211 TXstatus report based on the b43-specific * txstatus report data. This returns a boolean whether the frame was * successfully transmitted. */ -bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, +bool b43_fill_txstatus_report(struct b43_wldev *dev, + struct ieee80211_tx_info *report, const struct b43_txstatus *status) { bool frame_success = 1; + int retry_limit; + + /* preserve the confiured retry limit before clearing the status + * The xmit function has overwritten the rc's value with the actual + * retry limit done by the hardware */ + retry_limit = report->status.rates[0].count; + ieee80211_tx_info_clear_status(report); if (status->acked) { /* The frame was ACKed. */ @@ -700,14 +720,32 @@ bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) { /* ...but we expected an ACK. */ frame_success = 0; - report->status.excessive_retries = 1; } } if (status->frame_count == 0) { /* The frame was not transmitted at all. */ - report->status.retry_count = 0; - } else - report->status.retry_count = status->frame_count - 1; + report->status.rates[0].count = 0; + } else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { + /* + * If the short retries (RTS, not data frame) have exceeded + * the limit, the hw will not have tried the selected rate, + * but will have used the fallback rate instead. + * Don't let the rate control count attempts for the selected + * rate in this case, otherwise the statistics will be off. + */ + report->status.rates[0].count = 0; + report->status.rates[1].count = status->frame_count; + } else { + if (status->frame_count > retry_limit) { + report->status.rates[0].count = retry_limit; + report->status.rates[1].count = status->frame_count - + retry_limit; + + } else { + report->status.rates[0].count = status->frame_count; + report->status.rates[1].idx = -1; + } + } return frame_success; } 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, u8 * txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_info *txctl, u16 cookie); + struct ieee80211_tx_info *txctl, u16 cookie); /* Transmit Status */ struct b43_txstatus { @@ -294,7 +294,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr); void b43_handle_txstatus(struct b43_wldev *dev, const struct b43_txstatus *status); -bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, +bool b43_fill_txstatus_report(struct b43_wldev *dev, + struct ieee80211_tx_info *report, const struct b43_txstatus *status); void b43_tx_suspend(struct b43_wldev *dev); |