diff options
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r-- | drivers/net/wireless/b43/b43.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy.c | 48 |
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 | ||
4334 | void b43_radio_turn_off(struct b43_wldev *dev) | 4352 | void 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 | } |