Commit 7f3704e9 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

b43legacy: implement short slot and basic rate handling

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.

(port from b43)
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 3e4127fa
...@@ -145,6 +145,10 @@ ...@@ -145,6 +145,10 @@
#define B43legacy_SHM_SH_PRMAXTIME 0x0074 /* Probe Response max time */ #define B43legacy_SHM_SH_PRMAXTIME 0x0074 /* Probe Response max time */
#define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */ #define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */
/* SHM_SHARED rate tables */ /* SHM_SHARED rate tables */
#define B43legacy_SHM_SH_OFDMDIRECT 0x0480 /* Pointer to OFDM direct map */
#define B43legacy_SHM_SH_OFDMBASIC 0x04A0 /* Pointer to OFDM basic rate map */
#define B43legacy_SHM_SH_CCKDIRECT 0x04C0 /* Pointer to CCK direct map */
#define B43legacy_SHM_SH_CCKBASIC 0x04E0 /* Pointer to CCK basic rate map */
/* SHM_SHARED microcode soft registers */ /* SHM_SHARED microcode soft registers */
#define B43legacy_SHM_SH_UCODEREV 0x0000 /* Microcode revision */ #define B43legacy_SHM_SH_UCODEREV 0x0000 /* Microcode revision */
#define B43legacy_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */ #define B43legacy_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */
...@@ -663,7 +667,6 @@ struct b43legacy_wldev { ...@@ -663,7 +667,6 @@ struct b43legacy_wldev {
bool bad_frames_preempt;/* Use "Bad Frames Preemption". */ bool bad_frames_preempt;/* Use "Bad Frames Preemption". */
bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM). */ bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM). */
bool short_preamble; /* TRUE if using short preamble. */ bool short_preamble; /* TRUE if using short preamble. */
bool short_slot; /* TRUE if using short slot timing. */
bool radio_hw_enable; /* State of radio hardware enable bit. */ bool radio_hw_enable; /* State of radio hardware enable bit. */
/* PHY/Radio device. */ /* PHY/Radio device. */
......
...@@ -576,13 +576,11 @@ static void b43legacy_set_slot_time(struct b43legacy_wldev *dev, ...@@ -576,13 +576,11 @@ static void b43legacy_set_slot_time(struct b43legacy_wldev *dev,
static void b43legacy_short_slot_timing_enable(struct b43legacy_wldev *dev) static void b43legacy_short_slot_timing_enable(struct b43legacy_wldev *dev)
{ {
b43legacy_set_slot_time(dev, 9); b43legacy_set_slot_time(dev, 9);
dev->short_slot = 1;
} }
static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev) static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev)
{ {
b43legacy_set_slot_time(dev, 20); b43legacy_set_slot_time(dev, 20);
dev->short_slot = 0;
} }
/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. /* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
...@@ -2608,16 +2606,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, ...@@ -2608,16 +2606,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
if (conf->channel->hw_value != phy->channel) if (conf->channel->hw_value != phy->channel)
b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0); b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0);
/* Enable/Disable ShortSlot timing. */
if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME))
!= dev->short_slot) {
B43legacy_WARN_ON(phy->type != B43legacy_PHYTYPE_G);
if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)
b43legacy_short_slot_timing_enable(dev);
else
b43legacy_short_slot_timing_disable(dev);
}
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP); dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
/* Adjust the desired TX power level. */ /* Adjust the desired TX power level. */
...@@ -2662,6 +2650,104 @@ out_unlock_mutex: ...@@ -2662,6 +2650,104 @@ out_unlock_mutex:
return err; return err;
} }
static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u64 brates)
{
struct ieee80211_supported_band *sband =
dev->wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ];
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 (b43legacy_is_cck_rate(rate->hw_value)) {
direct = B43legacy_SHM_SH_CCKDIRECT;
basic = B43legacy_SHM_SH_CCKBASIC;
offset = b43legacy_plcp_get_ratecode_cck(rate->hw_value);
offset &= 0xF;
} else {
direct = B43legacy_SHM_SH_OFDMDIRECT;
basic = B43legacy_SHM_SH_OFDMBASIC;
offset = b43legacy_plcp_get_ratecode_ofdm(rate->hw_value);
offset &= 0xF;
}
rate = ieee80211_get_response_rate(sband, brates, rate->bitrate);
if (b43legacy_is_cck_rate(rate->hw_value)) {
basic_offset = b43legacy_plcp_get_ratecode_cck(rate->hw_value);
basic_offset &= 0xF;
} else {
basic_offset = b43legacy_plcp_get_ratecode_ofdm(rate->hw_value);
basic_offset &= 0xF;
}
/*
* Get the pointer that we need to point to
* from the direct map
*/
rateptr = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
direct + 2 * basic_offset);
/* and write it to the basic map */
b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
basic + 2 * offset, rateptr);
}
}
static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *conf,
u32 changed)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
struct b43legacy_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 (b43legacy_status(dev) < B43legacy_STAT_STARTED) {
spin_unlock_irqrestore(&wl->irq_lock, flags);
goto out_unlock_mutex;
}
savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL);
spin_unlock_irqrestore(&wl->irq_lock, flags);
b43legacy_synchronize_irq(dev);
b43legacy_mac_suspend(dev);
if (changed & BSS_CHANGED_BASIC_RATES)
b43legacy_update_basic_rates(dev, conf->basic_rates);
if (changed & BSS_CHANGED_ERP_SLOT) {
if (conf->use_short_slot)
b43legacy_short_slot_timing_enable(dev);
else
b43legacy_short_slot_timing_disable(dev);
}
b43legacy_mac_enable(dev);
spin_lock_irqsave(&wl->irq_lock, flags);
b43legacy_interrupt_enable(dev, savedirqs);
/* XXX: why? */
mmiowb();
spin_unlock_irqrestore(&wl->irq_lock, flags);
out_unlock_mutex:
mutex_unlock(&wl->mutex);
return;
}
static void b43legacy_op_configure_filter(struct ieee80211_hw *hw, static void b43legacy_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed, unsigned int changed,
unsigned int *fflags, unsigned int *fflags,
...@@ -3370,6 +3456,7 @@ static const struct ieee80211_ops b43legacy_hw_ops = { ...@@ -3370,6 +3456,7 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
.add_interface = b43legacy_op_add_interface, .add_interface = b43legacy_op_add_interface,
.remove_interface = b43legacy_op_remove_interface, .remove_interface = b43legacy_op_remove_interface,
.config = b43legacy_op_dev_config, .config = b43legacy_op_dev_config,
.bss_info_changed = b43legacy_op_bss_info_changed,
.config_interface = b43legacy_op_config_interface, .config_interface = b43legacy_op_config_interface,
.configure_filter = b43legacy_op_configure_filter, .configure_filter = b43legacy_op_configure_filter,
.get_stats = b43legacy_op_get_stats, .get_stats = b43legacy_op_get_stats,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment