Skip to content

Commit

Permalink
b43: implement short slot and basic rate handling
Browse files Browse the repository at this point in the history
This implements proper short slot handling and adds code to
program the hardware for the correct response rates derived
from the basic rate set for the current BSS.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Nov 10, 2008
1 parent bd81525 commit c7ab5ef
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 13 deletions.
1 change: 0 additions & 1 deletion drivers/net/wireless/b43/b43.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
111 changes: 99 additions & 12 deletions drivers/net/wireless/b43/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -3361,16 +3359,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
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. */
Expand Down Expand Up @@ -3421,6 +3409,104 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
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;
struct b43_phy *phy;
unsigned long flags;
u32 savedirqs;

mutex_lock(&wl->mutex);

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 & 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);

spin_lock_irqsave(&wl->irq_lock, flags);
b43_interrupt_enable(dev, savedirqs);
/* XXX: why? */
mmiowb();
spin_unlock_irqrestore(&wl->irq_lock, flags);
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)
Expand Down Expand Up @@ -4210,6 +4296,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,
Expand Down

0 comments on commit c7ab5ef

Please sign in to comment.