aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/main.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-10-29 15:02:12 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-11-10 15:17:35 -0500
commitc7ab5ef9bcd281135c21b4732c9be779585181be (patch)
treef8c7b1f089ec6eb97c36b6baccf24e61ccaae9ac /drivers/net/wireless/b43/main.c
parentbd815252720e4b667d9946d050d003ec89bda099 (diff)
b43: 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. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
-rw-r--r--drivers/net/wireless/b43/main.c111
1 files changed, 99 insertions, 12 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 9d1768d5fbad..ba7a5ab7fe1d 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.
@@ -3361,16 +3359,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
3361 if (conf->channel->hw_value != phy->channel) 3359 if (conf->channel->hw_value != phy->channel)
3362 b43_switch_channel(dev, conf->channel->hw_value); 3360 b43_switch_channel(dev, conf->channel->hw_value);
3363 3361
3364 /* Enable/Disable ShortSlot timing. */
3365 if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) !=
3366 dev->short_slot) {
3367 B43_WARN_ON(phy->type != B43_PHYTYPE_G);
3368 if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)
3369 b43_short_slot_timing_enable(dev);
3370 else
3371 b43_short_slot_timing_disable(dev);
3372 }
3373
3374 dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP); 3362 dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
3375 3363
3376 /* Adjust the desired TX power level. */ 3364 /* Adjust the desired TX power level. */
@@ -3421,6 +3409,104 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
3421 return err; 3409 return err;
3422} 3410}
3423 3411
3412static void b43_update_basic_rates(struct b43_wldev *dev, u64 brates)
3413{
3414 struct ieee80211_supported_band *sband =
3415 dev->wl->hw->wiphy->bands[b43_current_band(dev->wl)];
3416 struct ieee80211_rate *rate;
3417 int i;
3418 u16 basic, direct, offset, basic_offset, rateptr;
3419
3420 for (i = 0; i < sband->n_bitrates; i++) {
3421 rate = &sband->bitrates[i];
3422
3423 if (b43_is_cck_rate(rate->hw_value)) {
3424 direct = B43_SHM_SH_CCKDIRECT;
3425 basic = B43_SHM_SH_CCKBASIC;
3426 offset = b43_plcp_get_ratecode_cck(rate->hw_value);
3427 offset &= 0xF;
3428 } else {
3429 direct = B43_SHM_SH_OFDMDIRECT;
3430 basic = B43_SHM_SH_OFDMBASIC;
3431 offset = b43_plcp_get_ratecode_ofdm(rate->hw_value);
3432 offset &= 0xF;
3433 }
3434
3435 rate = ieee80211_get_response_rate(sband, brates, rate->bitrate);
3436
3437 if (b43_is_cck_rate(rate->hw_value)) {
3438 basic_offset = b43_plcp_get_ratecode_cck(rate->hw_value);
3439 basic_offset &= 0xF;
3440 } else {
3441 basic_offset = b43_plcp_get_ratecode_ofdm(rate->hw_value);
3442 basic_offset &= 0xF;
3443 }
3444
3445 /*
3446 * Get the pointer that we need to point to
3447 * from the direct map
3448 */
3449 rateptr = b43_shm_read16(dev, B43_SHM_SHARED,
3450 direct + 2 * basic_offset);
3451 /* and write it to the basic map */
3452 b43_shm_write16(dev, B43_SHM_SHARED, basic + 2 * offset,
3453 rateptr);
3454 }
3455}
3456
3457static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
3458 struct ieee80211_vif *vif,
3459 struct ieee80211_bss_conf *conf,
3460 u32 changed)
3461{
3462 struct b43_wl *wl = hw_to_b43_wl(hw);
3463 struct b43_wldev *dev;
3464 struct b43_phy *phy;
3465 unsigned long flags;
3466 u32 savedirqs;
3467
3468 mutex_lock(&wl->mutex);
3469
3470 dev = wl->current_dev;
3471 phy = &dev->phy;
3472
3473 /* Disable IRQs while reconfiguring the device.
3474 * This makes it possible to drop the spinlock throughout
3475 * the reconfiguration process. */
3476 spin_lock_irqsave(&wl->irq_lock, flags);
3477 if (b43_status(dev) < B43_STAT_STARTED) {
3478 spin_unlock_irqrestore(&wl->irq_lock, flags);
3479 goto out_unlock_mutex;
3480 }
3481 savedirqs = b43_interrupt_disable(dev, B43_IRQ_ALL);
3482 spin_unlock_irqrestore(&wl->irq_lock, flags);
3483 b43_synchronize_irq(dev);
3484
3485 b43_mac_suspend(dev);
3486
3487 if (changed & BSS_CHANGED_BASIC_RATES)
3488 b43_update_basic_rates(dev, conf->basic_rates);
3489
3490 if (changed & BSS_CHANGED_ERP_SLOT) {
3491 if (conf->use_short_slot)
3492 b43_short_slot_timing_enable(dev);
3493 else
3494 b43_short_slot_timing_disable(dev);
3495 }
3496
3497 b43_mac_enable(dev);
3498
3499 spin_lock_irqsave(&wl->irq_lock, flags);
3500 b43_interrupt_enable(dev, savedirqs);
3501 /* XXX: why? */
3502 mmiowb();
3503 spin_unlock_irqrestore(&wl->irq_lock, flags);
3504 out_unlock_mutex:
3505 mutex_unlock(&wl->mutex);
3506
3507 return;
3508}
3509
3424static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 3510static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3425 const u8 *local_addr, const u8 *addr, 3511 const u8 *local_addr, const u8 *addr,
3426 struct ieee80211_key_conf *key) 3512 struct ieee80211_key_conf *key)
@@ -4210,6 +4296,7 @@ static const struct ieee80211_ops b43_hw_ops = {
4210 .add_interface = b43_op_add_interface, 4296 .add_interface = b43_op_add_interface,
4211 .remove_interface = b43_op_remove_interface, 4297 .remove_interface = b43_op_remove_interface,
4212 .config = b43_op_config, 4298 .config = b43_op_config,
4299 .bss_info_changed = b43_op_bss_info_changed,
4213 .config_interface = b43_op_config_interface, 4300 .config_interface = b43_op_config_interface,
4214 .configure_filter = b43_op_configure_filter, 4301 .configure_filter = b43_op_configure_filter,
4215 .set_key = b43_op_set_key, 4302 .set_key = b43_op_set_key,