aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/b43')
-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 {
459 u16 radio_ver; /* Radio version */ 459 u16 radio_ver; /* Radio version */
460 u8 radio_rev; /* Radio revision */ 460 u8 radio_rev; /* Radio revision */
461 461
462 bool radio_on; /* Radio switched on/off */
463 bool locked; /* Only used in b43_phy_{un}lock() */ 462 bool locked; /* Only used in b43_phy_{un}lock() */
464 bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */ 463 bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */
465 464
@@ -468,6 +467,16 @@ struct b43_phy {
468 bool aci_wlan_automatic; 467 bool aci_wlan_automatic;
469 bool aci_hw_rssi; 468 bool aci_hw_rssi;
470 469
470 /* Radio switched on/off */
471 bool radio_on;
472 struct {
473 /* Values saved when turning the radio off.
474 * They are needed when turning it on again. */
475 bool valid;
476 u16 rfover;
477 u16 rfoverval;
478 } radio_off_context;
479
471 u16 minlowsig[2]; 480 u16 minlowsig[2];
472 u16 minlowsigpos[2]; 481 u16 minlowsigpos[2];
473 482
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)
2874 if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) 2874 if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
2875 b43_set_beacon_int(dev, conf->beacon_int); 2875 b43_set_beacon_int(dev, conf->beacon_int);
2876 2876
2877 if (!!conf->radio_enabled != phy->radio_on) {
2878 if (conf->radio_enabled) {
2879 b43_radio_turn_on(dev);
2880 b43info(dev->wl, "Radio turned on by software\n");
2881 if (!dev->radio_hw_enable) {
2882 b43info(dev->wl, "The hardware RF-kill button "
2883 "still turns the radio physically off. "
2884 "Press the button to turn it on.\n");
2885 }
2886 } else {
2887 b43_radio_turn_off(dev);
2888 b43info(dev->wl, "Radio turned off by software\n");
2889 }
2890 }
2891
2877 spin_lock_irqsave(&wl->irq_lock, flags); 2892 spin_lock_irqsave(&wl->irq_lock, flags);
2878 b43_interrupt_enable(dev, savedirqs); 2893 b43_interrupt_enable(dev, savedirqs);
2879 mmiowb(); 2894 mmiowb();
@@ -3218,6 +3233,8 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
3218 phy->aci_wlan_automatic = 0; 3233 phy->aci_wlan_automatic = 0;
3219 phy->aci_hw_rssi = 0; 3234 phy->aci_hw_rssi = 0;
3220 3235
3236 phy->radio_off_context.valid = 0;
3237
3221 lo = phy->lo_control; 3238 lo = phy->lo_control;
3222 if (lo) { 3239 if (lo) {
3223 memset(lo, 0, sizeof(*(phy->lo_control))); 3240 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)
1205 val -= 0x0202; 1205 val -= 0x0202;
1206 } 1206 }
1207 b43_phy_write(dev, 0x03E4, 0x3000); 1207 b43_phy_write(dev, 0x03E4, 0x3000);
1208 if (phy->channel == 0xFF) 1208 b43_radio_selectchannel(dev, phy->channel, 0);
1209 b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_BG, 0);
1210 else
1211 b43_radio_selectchannel(dev, phy->channel, 0);
1212 if (phy->radio_ver != 0x2050) { 1209 if (phy->radio_ver != 0x2050) {
1213 b43_radio_write16(dev, 0x0075, 0x0080); 1210 b43_radio_write16(dev, 0x0075, 0x0080);
1214 b43_radio_write16(dev, 0x0079, 0x0081); 1211 b43_radio_write16(dev, 0x0079, 0x0081);
@@ -1256,10 +1253,7 @@ static void b43_phy_initb4(struct b43_wldev *dev)
1256 val -= 0x0202; 1253 val -= 0x0202;
1257 } 1254 }
1258 b43_phy_write(dev, 0x03E4, 0x3000); 1255 b43_phy_write(dev, 0x03E4, 0x3000);
1259 if (phy->channel == 0xFF) 1256 b43_radio_selectchannel(dev, phy->channel, 0);
1260 b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_BG, 0);
1261 else
1262 b43_radio_selectchannel(dev, phy->channel, 0);
1263 if (phy->radio_ver != 0x2050) { 1257 if (phy->radio_ver != 0x2050) {
1264 b43_radio_write16(dev, 0x0075, 0x0080); 1258 b43_radio_write16(dev, 0x0075, 0x0080);
1265 b43_radio_write16(dev, 0x0079, 0x0081); 1259 b43_radio_write16(dev, 0x0079, 0x0081);
@@ -4110,6 +4104,20 @@ int b43_radio_selectchannel(struct b43_wldev *dev,
4110 u16 freq; 4104 u16 freq;
4111 u16 channelcookie; 4105 u16 channelcookie;
4112 4106
4107 if (channel == 0xFF) {
4108 switch (phy->type) {
4109 case B43_PHYTYPE_A:
4110 channel = B43_DEFAULT_CHANNEL_A;
4111 break;
4112 case B43_PHYTYPE_B:
4113 case B43_PHYTYPE_G:
4114 channel = B43_DEFAULT_CHANNEL_BG;
4115 break;
4116 default:
4117 B43_WARN_ON(1);
4118 }
4119 }
4120
4113 /* First we set the channel radio code to prevent the 4121 /* First we set the channel radio code to prevent the
4114 * firmware from sending ghost packets. 4122 * firmware from sending ghost packets.
4115 */ 4123 */
@@ -4302,6 +4310,7 @@ void b43_radio_turn_on(struct b43_wldev *dev)
4302{ 4310{
4303 struct b43_phy *phy = &dev->phy; 4311 struct b43_phy *phy = &dev->phy;
4304 int err; 4312 int err;
4313 u8 channel;
4305 4314
4306 might_sleep(); 4315 might_sleep();
4307 4316
@@ -4321,14 +4330,23 @@ void b43_radio_turn_on(struct b43_wldev *dev)
4321 b43_phy_write(dev, 0x0015, 0x8000); 4330 b43_phy_write(dev, 0x0015, 0x8000);
4322 b43_phy_write(dev, 0x0015, 0xCC00); 4331 b43_phy_write(dev, 0x0015, 0xCC00);
4323 b43_phy_write(dev, 0x0015, (phy->gmode ? 0x00C0 : 0x0000)); 4332 b43_phy_write(dev, 0x0015, (phy->gmode ? 0x00C0 : 0x0000));
4333 if (phy->radio_off_context.valid) {
4334 /* Restore the RFover values. */
4335 b43_phy_write(dev, B43_PHY_RFOVER,
4336 phy->radio_off_context.rfover);
4337 b43_phy_write(dev, B43_PHY_RFOVERVAL,
4338 phy->radio_off_context.rfoverval);
4339 phy->radio_off_context.valid = 0;
4340 }
4341 channel = phy->channel;
4324 err = b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_BG, 1); 4342 err = b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_BG, 1);
4343 err |= b43_radio_selectchannel(dev, channel, 0);
4325 B43_WARN_ON(err); 4344 B43_WARN_ON(err);
4326 break; 4345 break;
4327 default: 4346 default:
4328 B43_WARN_ON(1); 4347 B43_WARN_ON(1);
4329 } 4348 }
4330 phy->radio_on = 1; 4349 phy->radio_on = 1;
4331 b43dbg(dev->wl, "Radio turned on\n");
4332} 4350}
4333 4351
4334void b43_radio_turn_off(struct b43_wldev *dev) 4352void b43_radio_turn_off(struct b43_wldev *dev)
@@ -4342,10 +4360,16 @@ void b43_radio_turn_off(struct b43_wldev *dev)
4342 b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) | 0x0008); 4360 b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) | 0x0008);
4343 } 4361 }
4344 if (phy->type == B43_PHYTYPE_G && dev->dev->id.revision >= 5) { 4362 if (phy->type == B43_PHYTYPE_G && dev->dev->id.revision >= 5) {
4345 b43_phy_write(dev, 0x0811, b43_phy_read(dev, 0x0811) | 0x008C); 4363 u16 rfover, rfoverval;
4346 b43_phy_write(dev, 0x0812, b43_phy_read(dev, 0x0812) & 0xFF73); 4364
4365 rfover = b43_phy_read(dev, B43_PHY_RFOVER);
4366 rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL);
4367 phy->radio_off_context.rfover = rfover;
4368 phy->radio_off_context.rfoverval = rfoverval;
4369 phy->radio_off_context.valid = 1;
4370 b43_phy_write(dev, B43_PHY_RFOVER, rfover | 0x008C);
4371 b43_phy_write(dev, B43_PHY_RFOVERVAL, rfoverval & 0xFF73);
4347 } else 4372 } else
4348 b43_phy_write(dev, 0x0015, 0xAA00); 4373 b43_phy_write(dev, 0x0015, 0xAA00);
4349 phy->radio_on = 0; 4374 phy->radio_on = 0;
4350 b43dbg(dev->wl, "Radio turned off\n");
4351} 4375}