aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2007-09-20 22:11:02 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:52:25 -0400
commit42a9174f541d2338d35b91869415d9ae9312ca0d (patch)
tree34e35b54b63764a39c7e087d184b1e0fca1a9c5f /drivers
parentfda9abcf1a5b6b78a4ead25729583541af9876b5 (diff)
[B43LEGACY]: Support for turning the radio off from software.
This adds support for turning the radio off in software. That's useful in environments, where you don't want the RF to radiate any signals, but don't want to bring the interface down. This patch is based on a similar patch of b43 by Michael Buesch. Signed-off-by: Larry Finger <larry.finger@lwfinger.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h11
-rw-r--r--drivers/net/wireless/b43legacy/main.c16
-rw-r--r--drivers/net/wireless/b43legacy/phy.c14
-rw-r--r--drivers/net/wireless/b43legacy/radio.c39
4 files changed, 61 insertions, 19 deletions
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index 34a6277051a1..746de2ff498c 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -411,7 +411,6 @@ struct b43legacy_phy {
411 u8 calibrated:1; 411 u8 calibrated:1;
412 u8 radio_rev; /* Radio revision */ 412 u8 radio_rev; /* Radio revision */
413 413
414 bool radio_on; /* Radio switched on/off */
415 bool locked; /* Only used in b43legacy_phy_{un}lock() */ 414 bool locked; /* Only used in b43legacy_phy_{un}lock() */
416 bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */ 415 bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */
417 416
@@ -420,6 +419,16 @@ struct b43legacy_phy {
420 bool aci_wlan_automatic; 419 bool aci_wlan_automatic;
421 bool aci_hw_rssi; 420 bool aci_hw_rssi;
422 421
422 /* Radio switched on/off */
423 bool radio_on;
424 struct {
425 /* Values saved when turning the radio off.
426 * They are needed when turning it on again. */
427 bool valid;
428 u16 rfover;
429 u16 rfoverval;
430 } radio_off_context;
431
423 u16 minlowsig[2]; 432 u16 minlowsig[2];
424 u16 minlowsigpos[2]; 433 u16 minlowsigpos[2];
425 434
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 61b94218094b..3e935d0d4b80 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -2660,6 +2660,22 @@ static int b43legacy_dev_config(struct ieee80211_hw *hw,
2660 b43legacy_set_beacon_int(dev, conf->beacon_int); 2660 b43legacy_set_beacon_int(dev, conf->beacon_int);
2661 2661
2662 2662
2663 if (!!conf->radio_enabled != phy->radio_on) {
2664 if (conf->radio_enabled) {
2665 b43legacy_radio_turn_on(dev);
2666 b43legacyinfo(dev->wl, "Radio turned on by software\n");
2667 if (!dev->radio_hw_enable)
2668 b43legacyinfo(dev->wl, "The hardware RF-kill"
2669 " button still turns the radio"
2670 " physically off. Press the"
2671 " button to turn it on.\n");
2672 } else {
2673 b43legacy_radio_turn_off(dev);
2674 b43legacyinfo(dev->wl, "Radio turned off by"
2675 " software\n");
2676 }
2677 }
2678
2663 spin_lock_irqsave(&wl->irq_lock, flags); 2679 spin_lock_irqsave(&wl->irq_lock, flags);
2664 b43legacy_interrupt_enable(dev, savedirqs); 2680 b43legacy_interrupt_enable(dev, savedirqs);
2665 mmiowb(); 2681 mmiowb();
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index f9edbd5f3009..22a4b3d0186d 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -462,12 +462,7 @@ static void b43legacy_phy_initb2(struct b43legacy_wldev *dev)
462 val -= 0x0202; 462 val -= 0x0202;
463 } 463 }
464 b43legacy_phy_write(dev, 0x03E4, 0x3000); 464 b43legacy_phy_write(dev, 0x03E4, 0x3000);
465 if (phy->channel == 0xFF) 465 b43legacy_radio_selectchannel(dev, phy->channel, 0);
466 b43legacy_radio_selectchannel(dev,
467 B43legacy_RADIO_DEFAULT_CHANNEL_BG,
468 0);
469 else
470 b43legacy_radio_selectchannel(dev, phy->channel, 0);
471 if (phy->radio_ver != 0x2050) { 466 if (phy->radio_ver != 0x2050) {
472 b43legacy_radio_write16(dev, 0x0075, 0x0080); 467 b43legacy_radio_write16(dev, 0x0075, 0x0080);
473 b43legacy_radio_write16(dev, 0x0079, 0x0081); 468 b43legacy_radio_write16(dev, 0x0079, 0x0081);
@@ -516,12 +511,7 @@ static void b43legacy_phy_initb4(struct b43legacy_wldev *dev)
516 val -= 0x0202; 511 val -= 0x0202;
517 } 512 }
518 b43legacy_phy_write(dev, 0x03E4, 0x3000); 513 b43legacy_phy_write(dev, 0x03E4, 0x3000);
519 if (phy->channel == 0xFF) 514 b43legacy_radio_selectchannel(dev, phy->channel, 0);
520 b43legacy_radio_selectchannel(dev,
521 B43legacy_RADIO_DEFAULT_CHANNEL_BG,
522 0);
523 else
524 b43legacy_radio_selectchannel(dev, phy->channel, 0);
525 if (phy->radio_ver != 0x2050) { 515 if (phy->radio_ver != 0x2050) {
526 b43legacy_radio_write16(dev, 0x0075, 0x0080); 516 b43legacy_radio_write16(dev, 0x0075, 0x0080);
527 b43legacy_radio_write16(dev, 0x0079, 0x0081); 517 b43legacy_radio_write16(dev, 0x0079, 0x0081);
diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c
index 2a11ee63f400..54067f082825 100644
--- a/drivers/net/wireless/b43legacy/radio.c
+++ b/drivers/net/wireless/b43legacy/radio.c
@@ -1767,6 +1767,17 @@ int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev,
1767{ 1767{
1768 struct b43legacy_phy *phy = &dev->phy; 1768 struct b43legacy_phy *phy = &dev->phy;
1769 1769
1770 if (channel == 0xFF) {
1771 switch (phy->type) {
1772 case B43legacy_PHYTYPE_B:
1773 case B43legacy_PHYTYPE_G:
1774 channel = B43legacy_RADIO_DEFAULT_CHANNEL_BG;
1775 break;
1776 default:
1777 B43legacy_WARN_ON(1);
1778 }
1779 }
1780
1770/* TODO: Check if channel is valid - return -EINVAL if not */ 1781/* TODO: Check if channel is valid - return -EINVAL if not */
1771 if (synthetic_pu_workaround) 1782 if (synthetic_pu_workaround)
1772 b43legacy_synth_pu_workaround(dev, channel); 1783 b43legacy_synth_pu_workaround(dev, channel);
@@ -2070,6 +2081,7 @@ void b43legacy_radio_turn_on(struct b43legacy_wldev *dev)
2070{ 2081{
2071 struct b43legacy_phy *phy = &dev->phy; 2082 struct b43legacy_phy *phy = &dev->phy;
2072 int err; 2083 int err;
2084 u8 channel;
2073 2085
2074 might_sleep(); 2086 might_sleep();
2075 2087
@@ -2083,15 +2095,24 @@ void b43legacy_radio_turn_on(struct b43legacy_wldev *dev)
2083 b43legacy_phy_write(dev, 0x0015, 0xCC00); 2095 b43legacy_phy_write(dev, 0x0015, 0xCC00);
2084 b43legacy_phy_write(dev, 0x0015, 2096 b43legacy_phy_write(dev, 0x0015,
2085 (phy->gmode ? 0x00C0 : 0x0000)); 2097 (phy->gmode ? 0x00C0 : 0x0000));
2098 if (phy->radio_off_context.valid) {
2099 /* Restore the RFover values. */
2100 b43legacy_phy_write(dev, B43legacy_PHY_RFOVER,
2101 phy->radio_off_context.rfover);
2102 b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL,
2103 phy->radio_off_context.rfoverval);
2104 phy->radio_off_context.valid = 0;
2105 }
2106 channel = phy->channel;
2086 err = b43legacy_radio_selectchannel(dev, 2107 err = b43legacy_radio_selectchannel(dev,
2087 B43legacy_RADIO_DEFAULT_CHANNEL_BG, 1); 2108 B43legacy_RADIO_DEFAULT_CHANNEL_BG, 1);
2088 B43legacy_WARN_ON(err != 0); 2109 err |= b43legacy_radio_selectchannel(dev, channel, 0);
2110 B43legacy_WARN_ON(err);
2089 break; 2111 break;
2090 default: 2112 default:
2091 B43legacy_BUG_ON(1); 2113 B43legacy_BUG_ON(1);
2092 } 2114 }
2093 phy->radio_on = 1; 2115 phy->radio_on = 1;
2094 b43legacydbg(dev->wl, "Radio turned on\n");
2095 b43legacy_leds_update(dev, 0); 2116 b43legacy_leds_update(dev, 0);
2096} 2117}
2097 2118
@@ -2100,10 +2121,16 @@ void b43legacy_radio_turn_off(struct b43legacy_wldev *dev)
2100 struct b43legacy_phy *phy = &dev->phy; 2121 struct b43legacy_phy *phy = &dev->phy;
2101 2122
2102 if (phy->type == B43legacy_PHYTYPE_G && dev->dev->id.revision >= 5) { 2123 if (phy->type == B43legacy_PHYTYPE_G && dev->dev->id.revision >= 5) {
2103 b43legacy_phy_write(dev, 0x0811, b43legacy_phy_read(dev, 0x0811) 2124 u16 rfover, rfoverval;
2104 | 0x008C); 2125
2105 b43legacy_phy_write(dev, 0x0812, b43legacy_phy_read(dev, 0x0812) 2126 rfover = b43legacy_phy_read(dev, B43legacy_PHY_RFOVER);
2106 & 0xFF73); 2127 rfoverval = b43legacy_phy_read(dev, B43legacy_PHY_RFOVERVAL);
2128 phy->radio_off_context.rfover = rfover;
2129 phy->radio_off_context.rfoverval = rfoverval;
2130 phy->radio_off_context.valid = 1;
2131 b43legacy_phy_write(dev, B43legacy_PHY_RFOVER, rfover | 0x008C);
2132 b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL,
2133 rfoverval & 0xFF73);
2107 } else 2134 } else
2108 b43legacy_phy_write(dev, 0x0015, 0xAA00); 2135 b43legacy_phy_write(dev, 0x0015, 0xAA00);
2109 phy->radio_on = 0; 2136 phy->radio_on = 0;