summaryrefslogtreecommitdiffstats
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.h2
-rw-r--r--drivers/net/wireless/b43/leds.c4
-rw-r--r--drivers/net/wireless/b43/main.c24
-rw-r--r--drivers/net/wireless/b43/main.h20
-rw-r--r--drivers/net/wireless/b43/phy.c2
-rw-r--r--drivers/net/wireless/b43/rfkill.c37
-rw-r--r--drivers/net/wireless/b43/xmit.c27
-rw-r--r--drivers/net/wireless/b43/xmit.h65
8 files changed, 110 insertions, 71 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index a28ad230d63..7b6fc1ab2b9 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -273,6 +273,8 @@ enum {
#define B43_PHYTYPE_A 0x00
#define B43_PHYTYPE_B 0x01
#define B43_PHYTYPE_G 0x02
+#define B43_PHYTYPE_N 0x04
+#define B43_PHYTYPE_LP 0x05
/* PHYRegisters */
#define B43_PHY_ILT_A_CTRL 0x0072
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
index 19e588582c7..6c0e2b9f776 100644
--- a/drivers/net/wireless/b43/leds.c
+++ b/drivers/net/wireless/b43/leds.c
@@ -163,6 +163,9 @@ static void b43_map_led(struct b43_wldev *dev,
b43_register_led(dev, &dev->led_radio, name,
b43_rfkill_led_name(dev),
led_index, activelow);
+ /* Sync the RF-kill LED state with the switch state. */
+ if (dev->radio_hw_enable)
+ b43_led_turn_on(dev, led_index, activelow);
break;
case B43_LED_WEIRD:
case B43_LED_ASSOC:
@@ -232,4 +235,5 @@ void b43_leds_exit(struct b43_wldev *dev)
b43_unregister_led(&dev->led_tx);
b43_unregister_led(&dev->led_rx);
b43_unregister_led(&dev->led_assoc);
+ b43_unregister_led(&dev->led_radio);
}
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 2b17c1dc46f..1c93b4f4bfe 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1566,7 +1566,7 @@ static void b43_release_firmware(struct b43_wldev *dev)
static void b43_print_fw_helptext(struct b43_wl *wl)
{
b43err(wl, "You must go to "
- "http://linuxwireless.org/en/users/Drivers/bcm43xx#devicefirmware "
+ "http://linuxwireless.org/en/users/Drivers/b43#devicefirmware "
"and download the correct firmware (version 4).\n");
}
@@ -2163,7 +2163,6 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
static void b43_chip_exit(struct b43_wldev *dev)
{
b43_radio_turn_off(dev, 1);
- b43_leds_exit(dev);
b43_gpio_cleanup(dev);
/* firmware is released later */
}
@@ -2191,11 +2190,10 @@ static int b43_chip_init(struct b43_wldev *dev)
err = b43_gpio_init(dev);
if (err)
goto out; /* firmware is released later */
- b43_leds_init(dev);
err = b43_upload_initvals(dev);
if (err)
- goto err_leds_exit;
+ goto err_gpio_clean;
b43_radio_turn_on(dev);
b43_write16(dev, 0x03E6, 0x0000);
@@ -2271,8 +2269,7 @@ out:
err_radio_off:
b43_radio_turn_off(dev, 1);
-err_leds_exit:
- b43_leds_exit(dev);
+err_gpio_clean:
b43_gpio_cleanup(dev);
return err;
}
@@ -3273,10 +3270,7 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
return;
b43_set_status(dev, B43_STAT_UNINIT);
- mutex_unlock(&dev->wl->mutex);
- b43_rfkill_exit(dev);
- mutex_lock(&dev->wl->mutex);
-
+ b43_leds_exit(dev);
b43_rng_exit(dev->wl);
b43_pio_free(dev);
b43_dma_free(dev);
@@ -3405,12 +3399,12 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
memset(wl->mac_addr, 0, ETH_ALEN);
b43_upload_card_macaddress(dev);
b43_security_init(dev);
- b43_rfkill_init(dev);
b43_rng_init(wl);
b43_set_status(dev, B43_STAT_INITIALIZED);
- out:
+ b43_leds_init(dev);
+out:
return err;
err_chip_exit:
@@ -3499,6 +3493,10 @@ static int b43_start(struct ieee80211_hw *hw)
int did_init = 0;
int err = 0;
+ /* First register RFkill.
+ * LEDs that are registered later depend on it. */
+ b43_rfkill_init(dev);
+
mutex_lock(&wl->mutex);
if (b43_status(dev) < B43_STAT_INITIALIZED) {
@@ -3528,6 +3526,8 @@ static void b43_stop(struct ieee80211_hw *hw)
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
+ b43_rfkill_exit(dev);
+
mutex_lock(&wl->mutex);
if (b43_status(dev) >= B43_STAT_STARTED)
b43_wireless_core_stop(dev);
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index 284d17da17d..08e2e56e48f 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -39,11 +39,11 @@
#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
-static inline u8 b43_freq_to_channel_a(int freq)
+static inline u8 b43_freq_to_channel_5ghz(int freq)
{
return ((freq - 5000) / 5);
}
-static inline u8 b43_freq_to_channel_bg(int freq)
+static inline u8 b43_freq_to_channel_2ghz(int freq)
{
u8 channel;
@@ -54,19 +54,13 @@ static inline u8 b43_freq_to_channel_bg(int freq)
return channel;
}
-static inline u8 b43_freq_to_channel(struct b43_wldev *dev, int freq)
-{
- if (dev->phy.type == B43_PHYTYPE_A)
- return b43_freq_to_channel_a(freq);
- return b43_freq_to_channel_bg(freq);
-}
/* Lightweight function to convert a channel number to a frequency (in Mhz). */
-static inline int b43_channel_to_freq_a(u8 channel)
+static inline int b43_channel_to_freq_5ghz(u8 channel)
{
return (5000 + (5 * channel));
}
-static inline int b43_channel_to_freq_bg(u8 channel)
+static inline int b43_channel_to_freq_2ghz(u8 channel)
{
int freq;
@@ -77,12 +71,6 @@ static inline int b43_channel_to_freq_bg(u8 channel)
return freq;
}
-static inline int b43_channel_to_freq(struct b43_wldev *dev, u8 channel)
-{
- if (dev->phy.type == B43_PHYTYPE_A)
- return b43_channel_to_freq_a(channel);
- return b43_channel_to_freq_bg(channel);
-}
static inline int b43_is_cck_rate(int rate)
{
diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c
index 3d4ed647c31..7ff091e69f0 100644
--- a/drivers/net/wireless/b43/phy.c
+++ b/drivers/net/wireless/b43/phy.c
@@ -2214,7 +2214,7 @@ int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev)
}
dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
if (dyn_tssi2dbm == NULL) {
- b43err(dev->wl, "Could not allocate memory"
+ b43err(dev->wl, "Could not allocate memory "
"for tssi2dbm table\n");
return -ENOMEM;
}
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index 9b1f905ffbf..98cf70c5fd4 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -25,6 +25,8 @@
#include "rfkill.h"
#include "b43.h"
+#include <linux/kmod.h>
+
/* Returns TRUE, if the radio is enabled in hardware. */
static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
@@ -50,7 +52,10 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
bool report_change = 0;
mutex_lock(&wl->mutex);
- B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED);
+ if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) {
+ mutex_unlock(&wl->mutex);
+ return;
+ }
enabled = b43_is_hw_radio_enabled(dev);
if (unlikely(enabled != dev->radio_hw_enable)) {
dev->radio_hw_enable = enabled;
@@ -60,8 +65,12 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
}
mutex_unlock(&wl->mutex);
- if (unlikely(report_change))
- input_report_key(poll_dev->input, KEY_WLAN, enabled);
+ /* send the radio switch event to the system - note both a key press
+ * and a release are required */
+ if (unlikely(report_change)) {
+ input_report_key(poll_dev->input, KEY_WLAN, 1);
+ input_report_key(poll_dev->input, KEY_WLAN, 0);
+ }
}
/* Called when the RFKILL toggled in software. */
@@ -69,13 +78,15 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state)
{
struct b43_wldev *dev = data;
struct b43_wl *wl = dev->wl;
- int err = 0;
+ int err = -EBUSY;
if (!wl->rfkill.registered)
return 0;
mutex_lock(&wl->mutex);
- B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED);
+ if (b43_status(dev) < B43_STAT_INITIALIZED)
+ goto out_unlock;
+ err = 0;
switch (state) {
case RFKILL_STATE_ON:
if (!dev->radio_hw_enable) {
@@ -133,9 +144,25 @@ void b43_rfkill_init(struct b43_wldev *dev)
rfk->poll_dev->poll = b43_rfkill_poll;
rfk->poll_dev->poll_interval = 1000; /* msecs */
+ rfk->poll_dev->input->name = rfk->name;
+ rfk->poll_dev->input->id.bustype = BUS_HOST;
+ rfk->poll_dev->input->id.vendor = dev->dev->bus->boardinfo.vendor;
+ rfk->poll_dev->input->evbit[0] = BIT(EV_KEY);
+ set_bit(KEY_WLAN, rfk->poll_dev->input->keybit);
+
err = rfkill_register(rfk->rfkill);
if (err)
goto err_free_polldev;
+
+#ifdef CONFIG_RFKILL_INPUT_MODULE
+ /* B43 RF-kill isn't useful without the rfkill-input subsystem.
+ * Try to load the module. */
+ err = request_module("rfkill-input");
+ if (err)
+ b43warn(wl, "Failed to load the rfkill-input module. "
+ "The built-in radio LED will not work.\n");
+#endif /* CONFIG_RFKILL_INPUT */
+
err = input_register_polled_device(rfk->poll_dev);
if (err)
goto err_unreg_rfk;
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 0bd6f8a348a..3307ba1856b 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -531,21 +531,32 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
switch (chanstat & B43_RX_CHAN_PHYTYPE) {
case B43_PHYTYPE_A:
status.phymode = MODE_IEEE80211A;
- status.freq = chanid;
- status.channel = b43_freq_to_channel_a(chanid);
- break;
- case B43_PHYTYPE_B:
- status.phymode = MODE_IEEE80211B;
- status.freq = chanid + 2400;
- status.channel = b43_freq_to_channel_bg(chanid + 2400);
+ B43_WARN_ON(1);
+ /* FIXME: We don't really know which value the "chanid" contains.
+ * So the following assignment might be wrong. */
+ status.channel = chanid;
+ status.freq = b43_channel_to_freq_5ghz(status.channel);
break;
case B43_PHYTYPE_G:
status.phymode = MODE_IEEE80211G;
+ /* chanid is the radio channel cookie value as used
+ * to tune the radio. */
status.freq = chanid + 2400;
- status.channel = b43_freq_to_channel_bg(chanid + 2400);
+ status.channel = b43_freq_to_channel_2ghz(status.freq);
+ break;
+ case B43_PHYTYPE_N:
+ status.phymode = 0xDEAD /*FIXME MODE_IEEE80211N*/;
+ /* chanid is the SHM channel cookie. Which is the plain
+ * channel number in b43. */
+ status.channel = chanid;
+ if (chanstat & B43_RX_CHAN_5GHZ)
+ status.freq = b43_freq_to_channel_5ghz(status.freq);
+ else
+ status.freq = b43_freq_to_channel_2ghz(status.freq);
break;
default:
B43_WARN_ON(1);
+ goto drop;
}
dev->stats.last_rx = jiffies;
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index 03bddd25161..6dc079382f7 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -142,49 +142,56 @@ struct b43_rxhdr_fw4 {
} __attribute__ ((__packed__));
/* PHY RX Status 0 */
-#define B43_RX_PHYST0_GAINCTL 0x4000 /* Gain Control */
-#define B43_RX_PHYST0_PLCPHCF 0x0200
-#define B43_RX_PHYST0_PLCPFV 0x0100
-#define B43_RX_PHYST0_SHORTPRMBL 0x0080 /* Received with Short Preamble */
+#define B43_RX_PHYST0_GAINCTL 0x4000 /* Gain Control */
+#define B43_RX_PHYST0_PLCPHCF 0x0200
+#define B43_RX_PHYST0_PLCPFV 0x0100
+#define B43_RX_PHYST0_SHORTPRMBL 0x0080 /* Received with Short Preamble */
#define B43_RX_PHYST0_LCRS 0x0040
-#define B43_RX_PHYST0_ANT 0x0020 /* Antenna */
-#define B43_RX_PHYST0_UNSRATE 0x0010
+#define B43_RX_PHYST0_ANT 0x0020 /* Antenna */
+#define B43_RX_PHYST0_UNSRATE 0x0010
#define B43_RX_PHYST0_CLIP 0x000C
#define B43_RX_PHYST0_CLIP_SHIFT 2
-#define B43_RX_PHYST0_FTYPE 0x0003 /* Frame type */
-#define B43_RX_PHYST0_CCK 0x0000 /* Frame type: CCK */
-#define B43_RX_PHYST0_OFDM 0x0001 /* Frame type: OFDM */
-#define B43_RX_PHYST0_PRE_N 0x0002 /* Pre-standard N-PHY frame */
-#define B43_RX_PHYST0_STD_N 0x0003 /* Standard N-PHY frame */
+#define B43_RX_PHYST0_FTYPE 0x0003 /* Frame type */
+#define B43_RX_PHYST0_CCK 0x0000 /* Frame type: CCK */
+#define B43_RX_PHYST0_OFDM 0x0001 /* Frame type: OFDM */
+#define B43_RX_PHYST0_PRE_N 0x0002 /* Pre-standard N-PHY frame */
+#define B43_RX_PHYST0_STD_N 0x0003 /* Standard N-PHY frame */
/* PHY RX Status 2 */
-#define B43_RX_PHYST2_LNAG 0xC000 /* LNA Gain */
+#define B43_RX_PHYST2_LNAG 0xC000 /* LNA Gain */
#define B43_RX_PHYST2_LNAG_SHIFT 14
-#define B43_RX_PHYST2_PNAG 0x3C00 /* PNA Gain */
+#define B43_RX_PHYST2_PNAG 0x3C00 /* PNA Gain */
#define B43_RX_PHYST2_PNAG_SHIFT 10
-#define B43_RX_PHYST2_FOFF 0x03FF /* F offset */
+#define B43_RX_PHYST2_FOFF 0x03FF /* F offset */
/* PHY RX Status 3 */
-#define B43_RX_PHYST3_DIGG 0x1800 /* DIG Gain */
+#define B43_RX_PHYST3_DIGG 0x1800 /* DIG Gain */
#define B43_RX_PHYST3_DIGG_SHIFT 11
-#define B43_RX_PHYST3_TRSTATE 0x0400 /* TR state */
+#define B43_RX_PHYST3_TRSTATE 0x0400 /* TR state */
/* MAC RX Status */
-#define B43_RX_MAC_BEACONSENT 0x00008000 /* Beacon send flag */
-#define B43_RX_MAC_KEYIDX 0x000007E0 /* Key index */
-#define B43_RX_MAC_KEYIDX_SHIFT 5
-#define B43_RX_MAC_DECERR 0x00000010 /* Decrypt error */
-#define B43_RX_MAC_DEC 0x00000008 /* Decryption attempted */
-#define B43_RX_MAC_PADDING 0x00000004 /* Pad bytes present */
-#define B43_RX_MAC_RESP 0x00000002 /* Response frame transmitted */
-#define B43_RX_MAC_FCSERR 0x00000001 /* FCS error */
+#define B43_RX_MAC_RXST_VALID 0x01000000 /* PHY RXST valid */
+#define B43_RX_MAC_TKIP_MICERR 0x00100000 /* TKIP MIC error */
+#define B43_RX_MAC_TKIP_MICATT 0x00080000 /* TKIP MIC attempted */
+#define B43_RX_MAC_AGGTYPE 0x00060000 /* Aggregation type */
+#define B43_RX_MAC_AGGTYPE_SHIFT 17
+#define B43_RX_MAC_AMSDU 0x00010000 /* A-MSDU mask */
+#define B43_RX_MAC_BEACONSENT 0x00008000 /* Beacon sent flag */
+#define B43_RX_MAC_KEYIDX 0x000007E0 /* Key index */
+#define B43_RX_MAC_KEYIDX_SHIFT 5
+#define B43_RX_MAC_DECERR 0x00000010 /* Decrypt error */
+#define B43_RX_MAC_DEC 0x00000008 /* Decryption attempted */
+#define B43_RX_MAC_PADDING 0x00000004 /* Pad bytes present */
+#define B43_RX_MAC_RESP 0x00000002 /* Response frame transmitted */
+#define B43_RX_MAC_FCSERR 0x00000001 /* FCS error */
/* RX channel */
-#define B43_RX_CHAN_GAIN 0xFC00 /* Gain */
-#define B43_RX_CHAN_GAIN_SHIFT 10
-#define B43_RX_CHAN_ID 0x03FC /* Channel ID */
-#define B43_RX_CHAN_ID_SHIFT 2
-#define B43_RX_CHAN_PHYTYPE 0x0003 /* PHY type */
+#define B43_RX_CHAN_40MHZ 0x1000 /* 40 Mhz channel width */
+#define B43_RX_CHAN_5GHZ 0x0800 /* 5 Ghz band */
+#define B43_RX_CHAN_ID 0x07F8 /* Channel ID */
+#define B43_RX_CHAN_ID_SHIFT 3
+#define B43_RX_CHAN_PHYTYPE 0x0007 /* PHY type */
+
u8 b43_plcp_get_ratecode_cck(const u8 bitrate);
u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate);