aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/main.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-08-29 17:02:13 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-29 17:02:13 -0400
commit143b11c03cd42f2284efe5128afc057d8fc86c78 (patch)
tree8186830c461b7933c26cdd00b69e4c737c5c88e7 /drivers/net/wireless/b43/main.c
parentaf01d537463714e36e2c96d2da35902b76cd6827 (diff)
parent18c8adeb0244f823ba78a51e23f813fe68bc3c54 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
-rw-r--r--drivers/net/wireless/b43/main.c184
1 files changed, 52 insertions, 132 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 7205a936ec74..63bafc2f3f0a 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -44,7 +44,8 @@
44#include "b43.h" 44#include "b43.h"
45#include "main.h" 45#include "main.h"
46#include "debugfs.h" 46#include "debugfs.h"
47#include "phy.h" 47#include "phy_common.h"
48#include "phy_g.h"
48#include "nphy.h" 49#include "nphy.h"
49#include "dma.h" 50#include "dma.h"
50#include "pio.h" 51#include "pio.h"
@@ -1174,6 +1175,8 @@ static void b43_calculate_link_quality(struct b43_wldev *dev)
1174{ 1175{
1175 /* Top half of Link Quality calculation. */ 1176 /* Top half of Link Quality calculation. */
1176 1177
1178 if (dev->phy.type != B43_PHYTYPE_G)
1179 return;
1177 if (dev->noisecalc.calculation_running) 1180 if (dev->noisecalc.calculation_running)
1178 return; 1181 return;
1179 dev->noisecalc.calculation_running = 1; 1182 dev->noisecalc.calculation_running = 1;
@@ -1184,7 +1187,7 @@ static void b43_calculate_link_quality(struct b43_wldev *dev)
1184 1187
1185static void handle_irq_noise(struct b43_wldev *dev) 1188static void handle_irq_noise(struct b43_wldev *dev)
1186{ 1189{
1187 struct b43_phy *phy = &dev->phy; 1190 struct b43_phy_g *phy = dev->phy.g;
1188 u16 tmp; 1191 u16 tmp;
1189 u8 noise[4]; 1192 u8 noise[4];
1190 u8 i, j; 1193 u8 i, j;
@@ -1192,6 +1195,9 @@ static void handle_irq_noise(struct b43_wldev *dev)
1192 1195
1193 /* Bottom half of Link Quality calculation. */ 1196 /* Bottom half of Link Quality calculation. */
1194 1197
1198 if (dev->phy.type != B43_PHYTYPE_G)
1199 return;
1200
1195 /* Possible race condition: It might be possible that the user 1201 /* Possible race condition: It might be possible that the user
1196 * changed to a different channel in the meantime since we 1202 * changed to a different channel in the meantime since we
1197 * started the calculation. We ignore that fact, since it's 1203 * started the calculation. We ignore that fact, since it's
@@ -2688,9 +2694,7 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
2688/* This is the opposite of b43_chip_init() */ 2694/* This is the opposite of b43_chip_init() */
2689static void b43_chip_exit(struct b43_wldev *dev) 2695static void b43_chip_exit(struct b43_wldev *dev)
2690{ 2696{
2691 b43_radio_turn_off(dev, 1);
2692 b43_gpio_cleanup(dev); 2697 b43_gpio_cleanup(dev);
2693 b43_lo_g_cleanup(dev);
2694 /* firmware is released later */ 2698 /* firmware is released later */
2695} 2699}
2696 2700
@@ -2700,7 +2704,7 @@ static void b43_chip_exit(struct b43_wldev *dev)
2700static int b43_chip_init(struct b43_wldev *dev) 2704static int b43_chip_init(struct b43_wldev *dev)
2701{ 2705{
2702 struct b43_phy *phy = &dev->phy; 2706 struct b43_phy *phy = &dev->phy;
2703 int err, tmp; 2707 int err;
2704 u32 value32, macctl; 2708 u32 value32, macctl;
2705 u16 value16; 2709 u16 value16;
2706 2710
@@ -2725,19 +2729,19 @@ static int b43_chip_init(struct b43_wldev *dev)
2725 err = b43_upload_initvals(dev); 2729 err = b43_upload_initvals(dev);
2726 if (err) 2730 if (err)
2727 goto err_gpio_clean; 2731 goto err_gpio_clean;
2728 b43_radio_turn_on(dev);
2729 2732
2730 b43_write16(dev, 0x03E6, 0x0000); 2733 b43_write16(dev, 0x03E6, 0x0000);
2731 err = b43_phy_init(dev); 2734 err = b43_phy_init(dev);
2732 if (err) 2735 if (err)
2733 goto err_radio_off; 2736 goto err_gpio_clean;
2734 2737
2735 /* Select initial Interference Mitigation. */ 2738 /* Disable Interference Mitigation. */
2736 tmp = phy->interfmode; 2739 if (phy->ops->interf_mitigation)
2737 phy->interfmode = B43_INTERFMODE_NONE; 2740 phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE);
2738 b43_radio_set_interference_mitigation(dev, tmp);
2739 2741
2740 b43_set_rx_antenna(dev, B43_ANTENNA_DEFAULT); 2742 /* Select the antennae */
2743 if (phy->ops->set_rx_antenna)
2744 phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
2741 b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT); 2745 b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT);
2742 2746
2743 if (phy->type == B43_PHYTYPE_B) { 2747 if (phy->type == B43_PHYTYPE_B) {
@@ -2790,8 +2794,6 @@ static int b43_chip_init(struct b43_wldev *dev)
2790out: 2794out:
2791 return err; 2795 return err;
2792 2796
2793err_radio_off:
2794 b43_radio_turn_off(dev, 1);
2795err_gpio_clean: 2797err_gpio_clean:
2796 b43_gpio_cleanup(dev); 2798 b43_gpio_cleanup(dev);
2797 return err; 2799 return err;
@@ -2799,25 +2801,13 @@ err_gpio_clean:
2799 2801
2800static void b43_periodic_every60sec(struct b43_wldev *dev) 2802static void b43_periodic_every60sec(struct b43_wldev *dev)
2801{ 2803{
2802 struct b43_phy *phy = &dev->phy; 2804 const struct b43_phy_operations *ops = dev->phy.ops;
2803 2805
2804 if (phy->type != B43_PHYTYPE_G) 2806 if (ops->pwork_60sec)
2805 return; 2807 ops->pwork_60sec(dev);
2806 if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) { 2808
2807 b43_mac_suspend(dev); 2809 /* Force check the TX power emission now. */
2808 b43_calc_nrssi_slope(dev); 2810 b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME);
2809 if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) {
2810 u8 old_chan = phy->channel;
2811
2812 /* VCO Calibration */
2813 if (old_chan >= 8)
2814 b43_radio_selectchannel(dev, 1, 0);
2815 else
2816 b43_radio_selectchannel(dev, 13, 0);
2817 b43_radio_selectchannel(dev, old_chan, 0);
2818 }
2819 b43_mac_enable(dev);
2820 }
2821} 2811}
2822 2812
2823static void b43_periodic_every30sec(struct b43_wldev *dev) 2813static void b43_periodic_every30sec(struct b43_wldev *dev)
@@ -2845,32 +2835,8 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
2845 } 2835 }
2846 } 2836 }
2847 2837
2848 if (phy->type == B43_PHYTYPE_G) { 2838 if (phy->ops->pwork_15sec)
2849 //TODO: update_aci_moving_average 2839 phy->ops->pwork_15sec(dev);
2850 if (phy->aci_enable && phy->aci_wlan_automatic) {
2851 b43_mac_suspend(dev);
2852 if (!phy->aci_enable && 1 /*TODO: not scanning? */ ) {
2853 if (0 /*TODO: bunch of conditions */ ) {
2854 b43_radio_set_interference_mitigation
2855 (dev, B43_INTERFMODE_MANUALWLAN);
2856 }
2857 } else if (1 /*TODO*/) {
2858 /*
2859 if ((aci_average > 1000) && !(b43_radio_aci_scan(dev))) {
2860 b43_radio_set_interference_mitigation(dev,
2861 B43_INTERFMODE_NONE);
2862 }
2863 */
2864 }
2865 b43_mac_enable(dev);
2866 } else if (phy->interfmode == B43_INTERFMODE_NONWLAN &&
2867 phy->rev == 1) {
2868 //TODO: implement rev1 workaround
2869 }
2870 }
2871 b43_phy_xmitpower(dev); //FIXME: unless scanning?
2872 b43_lo_g_maintanance_work(dev);
2873 //TODO for APHY (temperature?)
2874 2840
2875 atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); 2841 atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
2876 wmb(); 2842 wmb();
@@ -3401,7 +3367,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
3401 /* Switch to the requested channel. 3367 /* Switch to the requested channel.
3402 * The firmware takes care of races with the TX handler. */ 3368 * The firmware takes care of races with the TX handler. */
3403 if (conf->channel->hw_value != phy->channel) 3369 if (conf->channel->hw_value != phy->channel)
3404 b43_radio_selectchannel(dev, conf->channel->hw_value, 0); 3370 b43_switch_channel(dev, conf->channel->hw_value);
3405 3371
3406 /* Enable/Disable ShortSlot timing. */ 3372 /* Enable/Disable ShortSlot timing. */
3407 if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) != 3373 if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) !=
@@ -3417,17 +3383,21 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
3417 3383
3418 /* Adjust the desired TX power level. */ 3384 /* Adjust the desired TX power level. */
3419 if (conf->power_level != 0) { 3385 if (conf->power_level != 0) {
3420 if (conf->power_level != phy->power_level) { 3386 spin_lock_irqsave(&wl->irq_lock, flags);
3421 phy->power_level = conf->power_level; 3387 if (conf->power_level != phy->desired_txpower) {
3422 b43_phy_xmitpower(dev); 3388 phy->desired_txpower = conf->power_level;
3389 b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME |
3390 B43_TXPWR_IGNORE_TSSI);
3423 } 3391 }
3392 spin_unlock_irqrestore(&wl->irq_lock, flags);
3424 } 3393 }
3425 3394
3426 /* Antennas for RX and management frame TX. */ 3395 /* Antennas for RX and management frame TX. */
3427 antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx); 3396 antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx);
3428 b43_mgmtframe_txantenna(dev, antenna); 3397 b43_mgmtframe_txantenna(dev, antenna);
3429 antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx); 3398 antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx);
3430 b43_set_rx_antenna(dev, antenna); 3399 if (phy->ops->set_rx_antenna)
3400 phy->ops->set_rx_antenna(dev, antenna);
3431 3401
3432 /* Update templates for AP/mesh mode. */ 3402 /* Update templates for AP/mesh mode. */
3433 if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || 3403 if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) ||
@@ -3436,7 +3406,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
3436 3406
3437 if (!!conf->radio_enabled != phy->radio_on) { 3407 if (!!conf->radio_enabled != phy->radio_on) {
3438 if (conf->radio_enabled) { 3408 if (conf->radio_enabled) {
3439 b43_radio_turn_on(dev); 3409 b43_software_rfkill(dev, RFKILL_STATE_UNBLOCKED);
3440 b43info(dev->wl, "Radio turned on by software\n"); 3410 b43info(dev->wl, "Radio turned on by software\n");
3441 if (!dev->radio_hw_enable) { 3411 if (!dev->radio_hw_enable) {
3442 b43info(dev->wl, "The hardware RF-kill button " 3412 b43info(dev->wl, "The hardware RF-kill button "
@@ -3444,7 +3414,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
3444 "Press the button to turn it on.\n"); 3414 "Press the button to turn it on.\n");
3445 } 3415 }
3446 } else { 3416 } else {
3447 b43_radio_turn_off(dev, 0); 3417 b43_software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
3448 b43info(dev->wl, "Radio turned off by software\n"); 3418 b43info(dev->wl, "Radio turned off by software\n");
3449 } 3419 }
3450 } 3420 }
@@ -3818,48 +3788,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
3818static void setup_struct_phy_for_init(struct b43_wldev *dev, 3788static void setup_struct_phy_for_init(struct b43_wldev *dev,
3819 struct b43_phy *phy) 3789 struct b43_phy *phy)
3820{ 3790{
3821 struct b43_txpower_lo_control *lo;
3822 int i;
3823
3824 memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
3825 memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
3826
3827 phy->aci_enable = 0;
3828 phy->aci_wlan_automatic = 0;
3829 phy->aci_hw_rssi = 0;
3830
3831 phy->radio_off_context.valid = 0;
3832
3833 lo = phy->lo_control;
3834 if (lo) {
3835 memset(lo, 0, sizeof(*(phy->lo_control)));
3836 lo->tx_bias = 0xFF;
3837 INIT_LIST_HEAD(&lo->calib_list);
3838 }
3839 phy->max_lb_gain = 0;
3840 phy->trsw_rx_gain = 0;
3841 phy->txpwr_offset = 0;
3842
3843 /* NRSSI */
3844 phy->nrssislope = 0;
3845 for (i = 0; i < ARRAY_SIZE(phy->nrssi); i++)
3846 phy->nrssi[i] = -1000;
3847 for (i = 0; i < ARRAY_SIZE(phy->nrssi_lt); i++)
3848 phy->nrssi_lt[i] = i;
3849
3850 phy->lofcal = 0xFFFF;
3851 phy->initval = 0xFFFF;
3852
3853 phy->interfmode = B43_INTERFMODE_NONE;
3854 phy->channel = 0xFF;
3855
3856 phy->hardware_power_control = !!modparam_hwpctl; 3791 phy->hardware_power_control = !!modparam_hwpctl;
3857 3792 phy->next_txpwr_check_time = jiffies;
3858 /* PHY TX errors counter. */ 3793 /* PHY TX errors counter. */
3859 atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); 3794 atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
3860
3861 /* OFDM-table address caching. */
3862 phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_UNKNOWN;
3863} 3795}
3864 3796
3865static void setup_struct_wldev_for_init(struct b43_wldev *dev) 3797static void setup_struct_wldev_for_init(struct b43_wldev *dev)
@@ -3995,7 +3927,6 @@ static void b43_set_pretbtt(struct b43_wldev *dev)
3995/* Locking: wl->mutex */ 3927/* Locking: wl->mutex */
3996static void b43_wireless_core_exit(struct b43_wldev *dev) 3928static void b43_wireless_core_exit(struct b43_wldev *dev)
3997{ 3929{
3998 struct b43_phy *phy = &dev->phy;
3999 u32 macctl; 3930 u32 macctl;
4000 3931
4001 B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED); 3932 B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED);
@@ -4016,16 +3947,12 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
4016 b43_dma_free(dev); 3947 b43_dma_free(dev);
4017 b43_pio_free(dev); 3948 b43_pio_free(dev);
4018 b43_chip_exit(dev); 3949 b43_chip_exit(dev);
4019 b43_radio_turn_off(dev, 1);
4020 b43_switch_analog(dev, 0); 3950 b43_switch_analog(dev, 0);
4021 if (phy->dyn_tssi_tbl)
4022 kfree(phy->tssi2dbm);
4023 kfree(phy->lo_control);
4024 phy->lo_control = NULL;
4025 if (dev->wl->current_beacon) { 3951 if (dev->wl->current_beacon) {
4026 dev_kfree_skb_any(dev->wl->current_beacon); 3952 dev_kfree_skb_any(dev->wl->current_beacon);
4027 dev->wl->current_beacon = NULL; 3953 dev->wl->current_beacon = NULL;
4028 } 3954 }
3955 b43_phy_exit(dev);
4029 3956
4030 ssb_device_disable(dev->dev, 0); 3957 ssb_device_disable(dev->dev, 0);
4031 ssb_bus_may_powerdown(dev->dev->bus); 3958 ssb_bus_may_powerdown(dev->dev->bus);
@@ -4052,29 +3979,24 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
4052 b43_wireless_core_reset(dev, tmp); 3979 b43_wireless_core_reset(dev, tmp);
4053 } 3980 }
4054 3981
4055 if ((phy->type == B43_PHYTYPE_B) || (phy->type == B43_PHYTYPE_G)) {
4056 phy->lo_control =
4057 kzalloc(sizeof(*(phy->lo_control)), GFP_KERNEL);
4058 if (!phy->lo_control) {
4059 err = -ENOMEM;
4060 goto err_busdown;
4061 }
4062 }
4063 setup_struct_wldev_for_init(dev); 3982 setup_struct_wldev_for_init(dev);
4064 3983 err = b43_phy_operations_setup(dev);
4065 err = b43_phy_init_tssi2dbm_table(dev);
4066 if (err) 3984 if (err)
4067 goto err_kfree_lo_control; 3985 goto err_busdown;
4068 3986
4069 /* Enable IRQ routing to this device. */ 3987 /* Enable IRQ routing to this device. */
4070 ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); 3988 ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev);
4071 3989
4072 b43_imcfglo_timeouts_workaround(dev); 3990 b43_imcfglo_timeouts_workaround(dev);
4073 b43_bluetooth_coext_disable(dev); 3991 b43_bluetooth_coext_disable(dev);
4074 b43_phy_early_init(dev); 3992 if (phy->ops->prepare) {
3993 err = phy->ops->prepare(dev);
3994 if (err)
3995 goto err_phy_exit;
3996 }
4075 err = b43_chip_init(dev); 3997 err = b43_chip_init(dev);
4076 if (err) 3998 if (err)
4077 goto err_kfree_tssitbl; 3999 goto err_phy_exit;
4078 b43_shm_write16(dev, B43_SHM_SHARED, 4000 b43_shm_write16(dev, B43_SHM_SHARED,
4079 B43_SHM_SH_WLCOREREV, dev->dev->id.revision); 4001 B43_SHM_SH_WLCOREREV, dev->dev->id.revision);
4080 hf = b43_hf_read(dev); 4002 hf = b43_hf_read(dev);
@@ -4140,15 +4062,11 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
4140out: 4062out:
4141 return err; 4063 return err;
4142 4064
4143 err_chip_exit: 4065err_chip_exit:
4144 b43_chip_exit(dev); 4066 b43_chip_exit(dev);
4145 err_kfree_tssitbl: 4067err_phy_exit:
4146 if (phy->dyn_tssi_tbl) 4068 b43_phy_exit(dev);
4147 kfree(phy->tssi2dbm); 4069err_busdown:
4148 err_kfree_lo_control:
4149 kfree(phy->lo_control);
4150 phy->lo_control = NULL;
4151 err_busdown:
4152 ssb_bus_may_powerdown(bus); 4070 ssb_bus_may_powerdown(bus);
4153 B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT); 4071 B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
4154 return err; 4072 return err;
@@ -4291,6 +4209,8 @@ static void b43_op_stop(struct ieee80211_hw *hw)
4291 b43_wireless_core_stop(dev); 4209 b43_wireless_core_stop(dev);
4292 b43_wireless_core_exit(dev); 4210 b43_wireless_core_exit(dev);
4293 mutex_unlock(&wl->mutex); 4211 mutex_unlock(&wl->mutex);
4212
4213 cancel_work_sync(&(wl->txpower_adjust_work));
4294} 4214}
4295 4215
4296static int b43_op_set_retry_limit(struct ieee80211_hw *hw, 4216static int b43_op_set_retry_limit(struct ieee80211_hw *hw,
@@ -4511,7 +4431,6 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
4511 wl->current_dev = dev; 4431 wl->current_dev = dev;
4512 INIT_WORK(&dev->restart_work, b43_chip_reset); 4432 INIT_WORK(&dev->restart_work, b43_chip_reset);
4513 4433
4514 b43_radio_turn_off(dev, 1);
4515 b43_switch_analog(dev, 0); 4434 b43_switch_analog(dev, 0);
4516 ssb_device_disable(dev->dev, 0); 4435 ssb_device_disable(dev->dev, 0);
4517 ssb_bus_may_powerdown(bus); 4436 ssb_bus_may_powerdown(bus);
@@ -4669,6 +4588,7 @@ static int b43_wireless_init(struct ssb_device *dev)
4669 INIT_LIST_HEAD(&wl->devlist); 4588 INIT_LIST_HEAD(&wl->devlist);
4670 INIT_WORK(&wl->qos_update_work, b43_qos_update_work); 4589 INIT_WORK(&wl->qos_update_work, b43_qos_update_work);
4671 INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); 4590 INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
4591 INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work);
4672 4592
4673 ssb_set_devtypedata(dev, wl); 4593 ssb_set_devtypedata(dev, wl);
4674 b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); 4594 b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);