summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/b43/b43.h11
-rw-r--r--drivers/net/wireless/b43/main.c17
-rw-r--r--drivers/net/wireless/b43/phy.c48
3 files changed, 63 insertions, 13 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 270a2112de2a..a22435ade8ca 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -459,7 +459,6 @@ struct b43_phy {
u16 radio_ver; /* Radio version */
u8 radio_rev; /* Radio revision */
- bool radio_on; /* Radio switched on/off */
bool locked; /* Only used in b43_phy_{un}lock() */
bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */
@@ -468,6 +467,16 @@ struct b43_phy {
bool aci_wlan_automatic;
bool aci_hw_rssi;
+ /* Radio switched on/off */
+ bool radio_on;
+ struct {
+ /* Values saved when turning the radio off.
+ * They are needed when turning it on again. */
+ bool valid;
+ u16 rfover;
+ u16 rfoverval;
+ } radio_off_context;
+
u16 minlowsig[2];
u16 minlowsigpos[2];
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index cc5285407e88..b44c9f928848 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2874,6 +2874,21 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
b43_set_beacon_int(dev, conf->beacon_int);
+ if (!!conf->radio_enabled != phy->radio_on) {
+ if (conf->radio_enabled) {
+ b43_radio_turn_on(dev);
+ b43info(dev->wl, "Radio turned on by software\n");
+ if (!dev->radio_hw_enable) {
+ b43info(dev->wl, "The hardware RF-kill button "
+ "still turns the radio physically off. "
+ "Press the button to turn it on.\n");
+ }
+ } else {
+ b43_radio_turn_off(dev);
+ b43info(dev->wl, "Radio turned off by software\n");
+ }
+ }
+
spin_lock_irqsave(&wl->irq_lock, flags);
b43_interrupt_enable(dev, savedirqs);
mmiowb();
@@ -3218,6 +3233,8 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
phy->aci_wlan_automatic = 0;
phy->aci_hw_rssi = 0;
+ phy->radio_off_context.valid = 0;
+
lo = phy->lo_control;
if (lo) {
memset(lo, 0, sizeof(*(phy->lo_control)));
diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c
index 3282893021b0..354d18238752 100644
--- a/drivers/net/wireless/b43/phy.c
+++ b/drivers/net/wireless/b43/phy.c
@@ -1205,10 +1205,7 @@ static void b43_phy_initb2(struct b43_wldev *dev)
val -= 0x0202;
}
b43_phy_write(dev, 0x03E4, 0x3000);
- if (phy->channel == 0xFF)
- b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_BG, 0);
- else
- b43_radio_selectchannel(dev, phy->channel, 0);
+ b43_radio_selectchannel(dev, phy->channel, 0);
if (phy->radio_ver != 0x2050) {
b43_radio_write16(dev, 0x0075, 0x0080);
b43_radio_write16(dev, 0x0079, 0x0081);
@@ -1256,10 +1253,7 @@ static void b43_phy_initb4(struct b43_wldev *dev)
val -= 0x0202;
}
b43_phy_write(dev, 0x03E4, 0x3000);
- if (phy->channel == 0xFF)
- b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_BG, 0);
- else
- b43_radio_selectchannel(dev, phy->channel, 0);
+ b43_radio_selectchannel(dev, phy->channel, 0);
if (phy->radio_ver != 0x2050) {
b43_radio_write16(dev, 0x0075, 0x0080);
b43_radio_write16(dev, 0x0079, 0x0081);
@@ -4110,6 +4104,20 @@ int b43_radio_selectchannel(struct b43_wldev *dev,
u16 freq;
u16 channelcookie;
+ if (channel == 0xFF) {
+ switch (phy->type) {
+ case B43_PHYTYPE_A:
+ channel = B43_DEFAULT_CHANNEL_A;
+ break;
+ case B43_PHYTYPE_B:
+ case B43_PHYTYPE_G:
+ channel = B43_DEFAULT_CHANNEL_BG;
+ break;
+ default:
+ B43_WARN_ON(1);
+ }
+ }
+
/* First we set the channel radio code to prevent the
* firmware from sending ghost packets.
*/
@@ -4302,6 +4310,7 @@ void b43_radio_turn_on(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
int err;
+ u8 channel;
might_sleep();
@@ -4321,14 +4330,23 @@ void b43_radio_turn_on(struct b43_wldev *dev)
b43_phy_write(dev, 0x0015, 0x8000);
b43_phy_write(dev, 0x0015, 0xCC00);
b43_phy_write(dev, 0x0015, (phy->gmode ? 0x00C0 : 0x0000));
+ if (phy->radio_off_context.valid) {
+ /* Restore the RFover values. */
+ b43_phy_write(dev, B43_PHY_RFOVER,
+ phy->radio_off_context.rfover);
+ b43_phy_write(dev, B43_PHY_RFOVERVAL,
+ phy->radio_off_context.rfoverval);
+ phy->radio_off_context.valid = 0;
+ }
+ channel = phy->channel;
err = b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_BG, 1);
+ err |= b43_radio_selectchannel(dev, channel, 0);
B43_WARN_ON(err);
break;
default:
B43_WARN_ON(1);
}
phy->radio_on = 1;
- b43dbg(dev->wl, "Radio turned on\n");
}
void b43_radio_turn_off(struct b43_wldev *dev)
@@ -4342,10 +4360,16 @@ void b43_radio_turn_off(struct b43_wldev *dev)
b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) | 0x0008);
}
if (phy->type == B43_PHYTYPE_G && dev->dev->id.revision >= 5) {
- b43_phy_write(dev, 0x0811, b43_phy_read(dev, 0x0811) | 0x008C);
- b43_phy_write(dev, 0x0812, b43_phy_read(dev, 0x0812) & 0xFF73);
+ u16 rfover, rfoverval;
+
+ rfover = b43_phy_read(dev, B43_PHY_RFOVER);
+ rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL);
+ phy->radio_off_context.rfover = rfover;
+ phy->radio_off_context.rfoverval = rfoverval;
+ phy->radio_off_context.valid = 1;
+ b43_phy_write(dev, B43_PHY_RFOVER, rfover | 0x008C);
+ b43_phy_write(dev, B43_PHY_RFOVERVAL, rfoverval & 0xFF73);
} else
b43_phy_write(dev, 0x0015, 0xAA00);
phy->radio_on = 0;
- b43dbg(dev->wl, "Radio turned off\n");
}