提交 b1bc81a0 编写于 作者: D David S. Miller
......@@ -437,3 +437,10 @@ Why: Superseded by tdfxfb. I2C/DDC support used to live in a separate
driver but this caused driver conflicts.
Who: Jean Delvare <khali@linux-fr.org>
Krzysztof Helt <krzysztof.h1@wp.pl>
---------------------------
What: CONFIG_RFKILL_INPUT
When: 2.6.33
Why: Should be implemented in userspace, policy daemon.
Who: Johannes Berg <johannes@sipsolutions.net>
此差异已折叠。
......@@ -4753,9 +4753,9 @@ S: Supported
F: fs/reiserfs/
RFKILL
P: Ivo van Doorn
M: IvDoorn@gmail.com
L: netdev@vger.kernel.org
P: Johannes Berg
M: johannes@sipsolutions.net
L: linux-wireless@vger.kernel.org
S: Maintained
F Documentation/rfkill.txt
F: net/rfkill/
......
......@@ -35,21 +35,25 @@ static void tosa_bt_off(struct tosa_bt_data *data)
gpio_set_value(data->gpio_reset, 0);
}
static int tosa_bt_toggle_radio(void *data, enum rfkill_state state)
static int tosa_bt_set_block(void *data, bool blocked)
{
pr_info("BT_RADIO going: %s\n",
state == RFKILL_STATE_UNBLOCKED ? "on" : "off");
pr_info("BT_RADIO going: %s\n", blocked ? "off" : "on");
if (state == RFKILL_STATE_UNBLOCKED) {
if (!blocked) {
pr_info("TOSA_BT: going ON\n");
tosa_bt_on(data);
} else {
pr_info("TOSA_BT: going OFF\n");
tosa_bt_off(data);
}
return 0;
}
static const struct rfkill_ops tosa_bt_rfkill_ops = {
.set_block = tosa_bt_set_block,
};
static int tosa_bt_probe(struct platform_device *dev)
{
int rc;
......@@ -70,18 +74,14 @@ static int tosa_bt_probe(struct platform_device *dev)
if (rc)
goto err_pwr_dir;
rfk = rfkill_allocate(&dev->dev, RFKILL_TYPE_BLUETOOTH);
rfk = rfkill_alloc("tosa-bt", &dev->dev, RFKILL_TYPE_BLUETOOTH,
&tosa_bt_rfkill_ops, data);
if (!rfk) {
rc = -ENOMEM;
goto err_rfk_alloc;
}
rfk->name = "tosa-bt";
rfk->toggle_radio = tosa_bt_toggle_radio;
rfk->data = data;
#ifdef CONFIG_RFKILL_LEDS
rfk->led_trigger.name = "tosa-bt";
#endif
rfkill_set_led_trigger_name(rfk, "tosa-bt");
rc = rfkill_register(rfk);
if (rc)
......@@ -92,9 +92,7 @@ static int tosa_bt_probe(struct platform_device *dev)
return 0;
err_rfkill:
if (rfk)
rfkill_free(rfk);
rfk = NULL;
rfkill_destroy(rfk);
err_rfk_alloc:
tosa_bt_off(data);
err_pwr_dir:
......@@ -113,8 +111,10 @@ static int __devexit tosa_bt_remove(struct platform_device *dev)
platform_set_drvdata(dev, NULL);
if (rfk)
if (rfk) {
rfkill_unregister(rfk);
rfkill_destroy(rfk);
}
rfk = NULL;
tosa_bt_off(data);
......
......@@ -31,7 +31,6 @@
#include <linux/input.h>
#include <linux/gpio.h>
#include <linux/pda_power.h>
#include <linux/rfkill.h>
#include <linux/spi/spi.h>
#include <asm/setup.h>
......
......@@ -2481,10 +2481,10 @@ static int add_net_device(struct hso_device *hso_dev)
return 0;
}
static int hso_radio_toggle(void *data, enum rfkill_state state)
static int hso_rfkill_set_block(void *data, bool blocked)
{
struct hso_device *hso_dev = data;
int enabled = (state == RFKILL_STATE_UNBLOCKED);
int enabled = !blocked;
int rv;
mutex_lock(&hso_dev->mutex);
......@@ -2498,6 +2498,10 @@ static int hso_radio_toggle(void *data, enum rfkill_state state)
return rv;
}
static const struct rfkill_ops hso_rfkill_ops = {
.set_block = hso_rfkill_set_block,
};
/* Creates and sets up everything for rfkill */
static void hso_create_rfkill(struct hso_device *hso_dev,
struct usb_interface *interface)
......@@ -2506,29 +2510,25 @@ static void hso_create_rfkill(struct hso_device *hso_dev,
struct device *dev = &hso_net->net->dev;
char *rfkn;
hso_net->rfkill = rfkill_allocate(&interface_to_usbdev(interface)->dev,
RFKILL_TYPE_WWAN);
if (!hso_net->rfkill) {
dev_err(dev, "%s - Out of memory\n", __func__);
return;
}
rfkn = kzalloc(20, GFP_KERNEL);
if (!rfkn) {
rfkill_free(hso_net->rfkill);
hso_net->rfkill = NULL;
if (!rfkn)
dev_err(dev, "%s - Out of memory\n", __func__);
return;
}
snprintf(rfkn, 20, "hso-%d",
interface->altsetting->desc.bInterfaceNumber);
hso_net->rfkill->name = rfkn;
hso_net->rfkill->state = RFKILL_STATE_UNBLOCKED;
hso_net->rfkill->data = hso_dev;
hso_net->rfkill->toggle_radio = hso_radio_toggle;
hso_net->rfkill = rfkill_alloc(rfkn,
&interface_to_usbdev(interface)->dev,
RFKILL_TYPE_WWAN,
&hso_rfkill_ops, hso_dev);
if (!hso_net->rfkill) {
dev_err(dev, "%s - Out of memory\n", __func__);
kfree(rfkn);
return;
}
if (rfkill_register(hso_net->rfkill) < 0) {
rfkill_destroy(hso_net->rfkill);
kfree(rfkn);
hso_net->rfkill->name = NULL;
rfkill_free(hso_net->rfkill);
hso_net->rfkill = NULL;
dev_err(dev, "%s - Failed to register rfkill\n", __func__);
return;
......@@ -3165,8 +3165,10 @@ static void hso_free_interface(struct usb_interface *interface)
hso_stop_net_device(network_table[i]);
cancel_work_sync(&network_table[i]->async_put_intf);
cancel_work_sync(&network_table[i]->async_get_intf);
if (rfk)
if (rfk) {
rfkill_unregister(rfk);
rfkill_destroy(rfk);
}
hso_free_net_device(network_table[i]);
}
}
......
......@@ -333,11 +333,11 @@ config USB_ZD1201
config USB_NET_RNDIS_WLAN
tristate "Wireless RNDIS USB support"
depends on USB && WLAN_80211 && EXPERIMENTAL
depends on CFG80211
select USB_USBNET
select USB_NET_CDCETHER
select USB_NET_RNDIS_HOST
select WIRELESS_EXT
select CFG80211
---help---
This is a driver for wireless RNDIS devices.
These are USB based adapters found in devices such as:
......
......@@ -91,6 +91,7 @@ struct ar9170_led {
struct led_classdev l;
char name[32];
unsigned int toggled;
bool last_state;
bool registered;
};
......@@ -101,7 +102,6 @@ enum ar9170_device_state {
AR9170_STOPPED,
AR9170_IDLE,
AR9170_STARTED,
AR9170_ASSOCIATED,
};
struct ar9170_rxstream_mpdu_merge {
......@@ -140,7 +140,7 @@ struct ar9170 {
struct work_struct filter_config_work;
u64 cur_mc_hash, want_mc_hash;
u32 cur_filter, want_filter;
unsigned int filter_changed;
unsigned long filter_changed;
unsigned int filter_state;
bool sniffer_enabled;
......@@ -195,7 +195,7 @@ struct ar9170_sta_info {
#define IS_STARTED(a) (a->state >= AR9170_STARTED)
#define IS_ACCEPTING_CMD(a) (a->state >= AR9170_IDLE)
#define AR9170_FILTER_CHANGED_PROMISC BIT(0)
#define AR9170_FILTER_CHANGED_MODE BIT(0)
#define AR9170_FILTER_CHANGED_MULTICAST BIT(1)
#define AR9170_FILTER_CHANGED_FRAMEFILTER BIT(2)
......@@ -206,6 +206,7 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb);
void ar9170_unregister(struct ar9170 *ar);
void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb,
bool update_statistics, u16 tx_status);
void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len);
/* MAC */
int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
......@@ -215,6 +216,9 @@ int ar9170_update_multicast(struct ar9170 *ar);
int ar9170_update_frame_filter(struct ar9170 *ar);
int ar9170_set_operating_mode(struct ar9170 *ar);
int ar9170_set_beacon_timers(struct ar9170 *ar);
int ar9170_set_dyn_sifs_ack(struct ar9170 *ar);
int ar9170_set_slot_time(struct ar9170 *ar);
int ar9170_set_basic_rates(struct ar9170 *ar);
int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry);
int ar9170_update_beacon(struct ar9170 *ar);
void ar9170_new_beacon(struct work_struct *work);
......
......@@ -207,7 +207,8 @@ enum ar9170_cmd {
#define AR9170_MAC_REG_AC1_AC0_TXOP (AR9170_MAC_REG_BASE + 0xB44)
#define AR9170_MAC_REG_AC3_AC2_TXOP (AR9170_MAC_REG_BASE + 0xB48)
#define AR9170_MAC_REG_AMPDU_SET (AR9170_MAC_REG_BASE + 0xba0)
#define AR9170_MAC_REG_AMPDU_FACTOR (AR9170_MAC_REG_BASE + 0xB9C)
#define AR9170_MAC_REG_AMPDU_DENSITY (AR9170_MAC_REG_BASE + 0xBA0)
#define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xC00)
#define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xC50)
......@@ -376,7 +377,6 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t)
#define AR9170_RX_ERROR_FATAL 0x80
struct ar9170_cmd_tx_status {
__le16 unkn;
u8 dst[ETH_ALEN];
__le32 rate;
__le16 status;
......@@ -394,6 +394,7 @@ struct ar9170_cmd_ba_failed_count {
struct ar9170_cmd_response {
u8 flag;
u8 type;
__le16 padding;
union {
struct ar9170_cmd_tx_status tx_status;
......
......@@ -74,7 +74,7 @@ static void ar9170_update_leds(struct work_struct *work)
mutex_lock(&ar->mutex);
for (i = 0; i < AR9170_NUM_LEDS; i++)
if (ar->leds[i].toggled) {
if (ar->leds[i].registered && ar->leds[i].toggled) {
led_val |= 1 << i;
tmp = 70 + 200 / (ar->leds[i].toggled);
......@@ -101,9 +101,15 @@ static void ar9170_led_brightness_set(struct led_classdev *led,
struct ar9170_led *arl = container_of(led, struct ar9170_led, l);
struct ar9170 *ar = arl->ar;
arl->toggled++;
if (unlikely(!arl->registered))
return ;
if (arl->last_state != !!brightness) {
arl->toggled++;
arl->last_state = !!brightness;
}
if (likely(IS_ACCEPTING_CMD(ar) && brightness))
if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10);
}
......@@ -136,13 +142,14 @@ void ar9170_unregister_leds(struct ar9170 *ar)
{
int i;
cancel_delayed_work_sync(&ar->led_work);
for (i = 0; i < AR9170_NUM_LEDS; i++)
if (ar->leds[i].registered) {
led_classdev_unregister(&ar->leds[i].l);
ar->leds[i].registered = false;
ar->leds[i].toggled = 0;
}
cancel_delayed_work_sync(&ar->led_work);
}
int ar9170_register_leds(struct ar9170 *ar)
......
......@@ -38,6 +38,55 @@
#include "ar9170.h"
#include "cmd.h"
int ar9170_set_dyn_sifs_ack(struct ar9170 *ar)
{
u32 val;
if (conf_is_ht40(&ar->hw->conf))
val = 0x010a;
else {
if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ)
val = 0x105;
else
val = 0x104;
}
return ar9170_write_reg(ar, AR9170_MAC_REG_DYNAMIC_SIFS_ACK, val);
}
int ar9170_set_slot_time(struct ar9170 *ar)
{
u32 slottime = 20;
if (!ar->vif)
return 0;
if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) ||
ar->vif->bss_conf.use_short_slot)
slottime = 9;
return ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, slottime << 10);
}
int ar9170_set_basic_rates(struct ar9170 *ar)
{
u8 cck, ofdm;
if (!ar->vif)
return 0;
ofdm = ar->vif->bss_conf.basic_rates >> 4;
/* FIXME: is still necessary? */
if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
cck = 0;
else
cck = ar->vif->bss_conf.basic_rates & 0xf;
return ar9170_write_reg(ar, AR9170_MAC_REG_BASIC_RATE,
ofdm << 8 | cck);
}
int ar9170_set_qos(struct ar9170 *ar)
{
ar9170_regwrite_begin(ar);
......@@ -84,7 +133,7 @@ static int ar9170_set_ampdu_density(struct ar9170 *ar, u8 mpdudensity)
val = 0x140a00 | (mpdudensity ? (mpdudensity + 1) : 0);
ar9170_regwrite_begin(ar);
ar9170_regwrite(AR9170_MAC_REG_AMPDU_SET, val);
ar9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, val);
ar9170_regwrite_finish();
return ar9170_regwrite_result();
......@@ -398,10 +447,10 @@ int ar9170_update_beacon(struct ar9170 *ar)
/* XXX: use skb->cb info */
if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ)
ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP,
((skb->len + 4) << (3+16)) + 0x0400);
((skb->len + 4) << (3 + 16)) + 0x0400);
else
ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP,
((skb->len + 4) << (3+16)) + 0x0400);
((skb->len + 4) << 16) + 0x001b);
ar9170_regwrite(AR9170_MAC_REG_BCN_LENGTH, skb->len + 4);
ar9170_regwrite(AR9170_MAC_REG_BCN_ADDR, AR9170_BEACON_BUFFER_ADDRESS);
......
......@@ -146,7 +146,6 @@ static struct ieee80211_channel ar9170_5ghz_chantable[] = {
{ \
.ht_supported = true, \
.cap = IEEE80211_HT_CAP_MAX_AMSDU | \
IEEE80211_HT_CAP_SM_PS | \
IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \
IEEE80211_HT_CAP_SGI_40 | \
IEEE80211_HT_CAP_DSSSCCK40 | \
......@@ -344,7 +343,6 @@ static void ar9170_tx_status_janitor(struct work_struct *work)
if (unlikely(!IS_STARTED(ar)))
return ;
mutex_lock(&ar->mutex);
/* recycle the garbage back to mac80211... one by one. */
while ((skb = skb_dequeue(&ar->global_tx_status_waste))) {
#ifdef AR9170_QUEUE_DEBUG
......@@ -370,12 +368,9 @@ static void ar9170_tx_status_janitor(struct work_struct *work)
if (skb_queue_len(&ar->global_tx_status_waste) > 0)
queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor,
msecs_to_jiffies(100));
mutex_unlock(&ar->mutex);
}
static void ar9170_handle_command_response(struct ar9170 *ar,
void *buf, u32 len)
void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
{
struct ar9170_cmd_response *cmd = (void *) buf;
......@@ -957,6 +952,8 @@ static int ar9170_op_start(struct ieee80211_hw *hw)
mutex_lock(&ar->mutex);
ar->filter_changed = 0;
/* reinitialize queues statistics */
memset(&ar->tx_stats, 0, sizeof(ar->tx_stats));
for (i = 0; i < ARRAY_SIZE(ar->tx_stats); i++)
......@@ -1012,10 +1009,10 @@ static void ar9170_op_stop(struct ieee80211_hw *hw)
flush_workqueue(ar->hw->workqueue);
mutex_lock(&ar->mutex);
cancel_delayed_work_sync(&ar->tx_status_janitor);
cancel_work_sync(&ar->filter_config_work);
cancel_work_sync(&ar->beacon_work);
mutex_lock(&ar->mutex);
skb_queue_purge(&ar->global_tx_status_waste);
skb_queue_purge(&ar->global_tx_status);
......@@ -1306,11 +1303,6 @@ static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&ar->mutex);
if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) {
/* TODO */
err = 0;
}
if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
/* TODO */
err = 0;
......@@ -1344,15 +1336,21 @@ static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed)
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
/* adjust slot time for 5 GHz */
err = ar9170_set_slot_time(ar);
if (err)
goto out;
err = ar9170_set_dyn_sifs_ack(ar);
if (err)
goto out;
err = ar9170_set_channel(ar, hw->conf.channel,
AR9170_RFI_NONE,
nl80211_to_ar9170(hw->conf.channel_type));
if (err)
goto out;
/* adjust slot time for 5 GHz */
if (hw->conf.channel->band == IEEE80211_BAND_5GHZ)
err = ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME,
9 << 10);
}
out:
......@@ -1370,20 +1368,26 @@ static void ar9170_set_filters(struct work_struct *work)
return ;
mutex_lock(&ar->mutex);
if (ar->filter_changed & AR9170_FILTER_CHANGED_PROMISC) {
if (test_and_clear_bit(AR9170_FILTER_CHANGED_MODE,
&ar->filter_changed)) {
err = ar9170_set_operating_mode(ar);
if (err)
goto unlock;
}
if (ar->filter_changed & AR9170_FILTER_CHANGED_MULTICAST) {
if (test_and_clear_bit(AR9170_FILTER_CHANGED_MULTICAST,
&ar->filter_changed)) {
err = ar9170_update_multicast(ar);
if (err)
goto unlock;
}
if (ar->filter_changed & AR9170_FILTER_CHANGED_FRAMEFILTER)
if (test_and_clear_bit(AR9170_FILTER_CHANGED_FRAMEFILTER,
&ar->filter_changed)) {
err = ar9170_update_frame_filter(ar);
if (err)
goto unlock;
}
unlock:
mutex_unlock(&ar->mutex);
......@@ -1413,7 +1417,7 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
int i;
/* always get broadcast frames */
mchash = 1ULL << (0xff>>2);
mchash = 1ULL << (0xff >> 2);
for (i = 0; i < mc_count; i++) {
if (WARN_ON(!mclist))
......@@ -1423,7 +1427,7 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
}
ar->want_mc_hash = mchash;
}
ar->filter_changed |= AR9170_FILTER_CHANGED_MULTICAST;
set_bit(AR9170_FILTER_CHANGED_MULTICAST, &ar->filter_changed);
}
if (changed_flags & FIF_CONTROL) {
......@@ -1439,12 +1443,14 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
else
ar->want_filter = ar->cur_filter & ~filter;
ar->filter_changed |= AR9170_FILTER_CHANGED_FRAMEFILTER;
set_bit(AR9170_FILTER_CHANGED_FRAMEFILTER,
&ar->filter_changed);
}
if (changed_flags & FIF_PROMISC_IN_BSS) {
ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0;
ar->filter_changed |= AR9170_FILTER_CHANGED_PROMISC;
set_bit(AR9170_FILTER_CHANGED_MODE,
&ar->filter_changed);
}
if (likely(IS_STARTED(ar)))
......@@ -1464,27 +1470,32 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BSSID) {
memcpy(ar->bssid, bss_conf->bssid, ETH_ALEN);
err = ar9170_set_operating_mode(ar);
if (err)
goto out;
}
if (changed & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) {
err = ar9170_update_beacon(ar);
if (!err)
ar9170_set_beacon_timers(ar);
}
if (err)
goto out;
ar9170_regwrite_begin(ar);
err = ar9170_set_beacon_timers(ar);
if (err)
goto out;
}
if (changed & BSS_CHANGED_ASSOC) {
ar->state = bss_conf->assoc ? AR9170_ASSOCIATED : ar->state;
#ifndef CONFIG_AR9170_LEDS
/* enable assoc LED. */
err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0);
#endif /* CONFIG_AR9170_LEDS */
}
if (changed & BSS_CHANGED_BEACON_INT)
if (changed & BSS_CHANGED_BEACON_INT) {
err = ar9170_set_beacon_timers(ar);
if (err)
goto out;
}
if (changed & BSS_CHANGED_HT) {
/* TODO */
......@@ -1492,31 +1503,18 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_ERP_SLOT) {
u32 slottime = 20;
if (bss_conf->use_short_slot)
slottime = 9;
ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, slottime << 10);
err = ar9170_set_slot_time(ar);
if (err)
goto out;
}
if (changed & BSS_CHANGED_BASIC_RATES) {
u32 cck, ofdm;
if (hw->conf.channel->band == IEEE80211_BAND_5GHZ) {
ofdm = bss_conf->basic_rates;
cck = 0;
} else {
/* four cck rates */
cck = bss_conf->basic_rates & 0xf;
ofdm = bss_conf->basic_rates >> 4;
}
ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE,
ofdm << 8 | cck);
err = ar9170_set_basic_rates(ar);
if (err)
goto out;
}
ar9170_regwrite_finish();
err = ar9170_regwrite_result();
out:
mutex_unlock(&ar->mutex);
}
......
......@@ -401,7 +401,7 @@ int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
int i, err;
u32 val;
bool is_2ghz = band == IEEE80211_BAND_2GHZ;
bool is_40mhz = false; /* XXX: for now */
bool is_40mhz = conf_is_ht40(&ar->hw->conf);
ar9170_regwrite_begin(ar);
......@@ -1200,7 +1200,7 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
return -ENOSYS;
}
if (0 /* 2 streams capable */)
if (ar->eeprom.tx_mask != 1)
tmp |= 0x100;
err = ar9170_write_reg(ar, 0x1c5804, tmp);
......@@ -1214,7 +1214,7 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
freqpar = ar9170_get_hw_dyn_params(channel, bw);
vals[0] = cpu_to_le32(channel->center_freq * 1000);
vals[1] = cpu_to_le32(bw == AR9170_BW_20 ? 0 : 1);
vals[1] = cpu_to_le32(conf_is_ht40(&ar->hw->conf));
vals[2] = cpu_to_le32(offs << 2 | 1);
vals[3] = cpu_to_le32(freqpar->coeff_exp);
vals[4] = cpu_to_le32(freqpar->coeff_man);
......
......@@ -51,9 +51,14 @@ MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless");
MODULE_FIRMWARE("ar9170.fw");
MODULE_FIRMWARE("ar9170-1.fw");
MODULE_FIRMWARE("ar9170-2.fw");
enum ar9170_requirements {
AR9170_REQ_FW1_ONLY = 1,
};
static struct usb_device_id ar9170_usb_ids[] = {
/* Atheros 9170 */
{ USB_DEVICE(0x0cf3, 0x9170) },
......@@ -81,6 +86,10 @@ static struct usb_device_id ar9170_usb_ids[] = {
{ USB_DEVICE(0x2019, 0x5304) },
/* IO-Data WNGDNUS2 */
{ USB_DEVICE(0x04bb, 0x093f) },
/* AVM FRITZ!WLAN USB Stick N */
{ USB_DEVICE(0x057C, 0x8401) },
/* AVM FRITZ!WLAN USB Stick N 2.4 */
{ USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY },
/* terminate */
{}
......@@ -93,7 +102,7 @@ static void ar9170_usb_tx_urb_complete_free(struct urb *urb)
struct ar9170_usb *aru = (struct ar9170_usb *)
usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
if (!aru) {
if (unlikely(!aru)) {
dev_kfree_skb_irq(skb);
return ;
}
......@@ -126,8 +135,8 @@ static void ar9170_usb_irq_completed(struct urb *urb)
goto resubmit;
}
print_hex_dump_bytes("ar9170 irq: ", DUMP_PREFIX_OFFSET,
urb->transfer_buffer, urb->actual_length);
ar9170_handle_command_response(&aru->common, urb->transfer_buffer,
urb->actual_length);
resubmit:
usb_anchor_urb(urb, &aru->rx_submitted);
......@@ -177,16 +186,15 @@ static void ar9170_usb_rx_completed(struct urb *urb)
usb_anchor_urb(urb, &aru->rx_submitted);
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err) {
if (unlikely(err)) {
usb_unanchor_urb(urb);
dev_kfree_skb_irq(skb);
goto free;
}
return ;
free:
dev_kfree_skb_irq(skb);
return;
}
static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru,
......@@ -337,7 +345,7 @@ static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd,
usb_anchor_urb(urb, &aru->tx_submitted);
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err) {
if (unlikely(err)) {
usb_unanchor_urb(urb);
usb_free_urb(urb);
goto err_unbuf;
......@@ -418,7 +426,7 @@ static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer)
unsigned long flags;
u32 in, out;
if (!buffer)
if (unlikely(!buffer))
return ;
in = le32_to_cpup((__le32 *)buffer);
......@@ -504,17 +512,29 @@ static int ar9170_usb_request_firmware(struct ar9170_usb *aru)
{
int err = 0;
err = request_firmware(&aru->init_values, "ar9170-1.fw",
err = request_firmware(&aru->firmware, "ar9170.fw",
&aru->udev->dev);
if (err) {
dev_err(&aru->udev->dev, "file with init values not found.\n");
return err;
if (!err) {
aru->init_values = NULL;
return 0;
}
if (aru->req_one_stage_fw) {
dev_err(&aru->udev->dev, "ar9170.fw firmware file "
"not found and is required for this device\n");
return -EINVAL;
}
dev_err(&aru->udev->dev, "ar9170.fw firmware file "
"not found, trying old firmware...\n");
err = request_firmware(&aru->init_values, "ar9170-1.fw",
&aru->udev->dev);
err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev);
if (err) {
release_firmware(aru->init_values);
dev_err(&aru->udev->dev, "firmware file not found.\n");
dev_err(&aru->udev->dev, "file with init values not found.\n");
return err;
}
......@@ -548,6 +568,9 @@ static int ar9170_usb_upload_firmware(struct ar9170_usb *aru)
{
int err;
if (!aru->init_values)
goto upload_fw_start;
/* First, upload initial values to device RAM */
err = ar9170_usb_upload(aru, aru->init_values->data,
aru->init_values->size, 0x102800, false);
......@@ -557,6 +580,8 @@ static int ar9170_usb_upload_firmware(struct ar9170_usb *aru)
return err;
}
upload_fw_start:
/* Then, upload the firmware itself and start it */
return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size,
0x200000, true);
......@@ -656,6 +681,15 @@ static int ar9170_usb_init_device(struct ar9170_usb *aru)
return err;
}
static bool ar9170_requires_one_stage(const struct usb_device_id *id)
{
if (!id->driver_info)
return false;
if (id->driver_info == AR9170_REQ_FW1_ONLY)
return true;
return false;
}
static int ar9170_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
......@@ -676,6 +710,8 @@ static int ar9170_usb_probe(struct usb_interface *intf,
aru->intf = intf;
ar = &aru->common;
aru->req_one_stage_fw = ar9170_requires_one_stage(id);
usb_set_intfdata(intf, aru);
SET_IEEE80211_DEV(ar->hw, &udev->dev);
......@@ -691,7 +727,7 @@ static int ar9170_usb_probe(struct usb_interface *intf,
#ifdef CONFIG_PM
udev->reset_resume = 1;
#endif
#endif /* CONFIG_PM */
err = ar9170_usb_reset(aru);
if (err)
goto err_freehw;
......@@ -776,11 +812,6 @@ static int ar9170_resume(struct usb_interface *intf)
usb_unpoison_anchored_urbs(&aru->rx_submitted);
usb_unpoison_anchored_urbs(&aru->tx_submitted);
/*
* FIXME: firmware upload will fail on resume.
* but this is better than a hang!
*/
err = ar9170_usb_init_device(aru);
if (err)
goto err_unrx;
......
......@@ -62,6 +62,8 @@ struct ar9170_usb {
struct usb_anchor rx_submitted;
struct usb_anchor tx_submitted;
bool req_one_stage_fw;
spinlock_t cmdlock;
struct completion cmd_wait;
int readlen;
......
......@@ -2070,6 +2070,13 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
return ret;
}
static void ath5k_beacon_disable(struct ath5k_softc *sc)
{
sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
ath5k_hw_set_imr(sc->ah, sc->imask);
ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq);
}
/*
* Transmit a beacon frame at SWBA. Dynamic updates to the
* frame contents are done as needed and the slot time is
......@@ -2757,6 +2764,7 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
goto end;
ath5k_hw_set_lladdr(sc->ah, mac);
ath5k_beacon_disable(sc);
sc->vif = NULL;
end:
mutex_unlock(&sc->lock);
......@@ -2775,11 +2783,9 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&sc->lock);
sc->bintval = conf->beacon_int;
ret = ath5k_chan_set(sc, conf->channel);
if (ret < 0)
return ret;
goto unlock;
if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
(sc->power_level != conf->power_level)) {
......@@ -2808,8 +2814,9 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
*/
ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
unlock:
mutex_unlock(&sc->lock);
return 0;
return ret;
}
#define SUPPORTED_FIF_FLAGS \
......@@ -3061,7 +3068,14 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
int ret;
struct ath5k_softc *sc = hw->priv;
struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
struct sk_buff *skb;
if (WARN_ON(!vif)) {
ret = -EINVAL;
goto out;
}
skb = ieee80211_beacon_get(hw, vif);
if (!skb) {
ret = -ENOMEM;
......
......@@ -460,12 +460,9 @@ struct ath_led {
bool registered;
};
/* Rfkill */
#define ATH_RFKILL_POLL_INTERVAL 2000 /* msecs */
struct ath_rfkill {
struct rfkill *rfkill;
struct delayed_work rfkill_poll;
struct rfkill_ops ops;
char rfkill_name[32];
};
......@@ -509,8 +506,6 @@ struct ath_rfkill {
#define SC_OP_RXFLUSH BIT(7)
#define SC_OP_LED_ASSOCIATED BIT(8)
#define SC_OP_RFKILL_REGISTERED BIT(9)
#define SC_OP_RFKILL_SW_BLOCKED BIT(10)
#define SC_OP_RFKILL_HW_BLOCKED BIT(11)
#define SC_OP_WAIT_FOR_BEACON BIT(12)
#define SC_OP_LED_ON BIT(13)
#define SC_OP_SCANNING BIT(14)
......
......@@ -411,6 +411,7 @@ void ath_beacon_tasklet(unsigned long data)
} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
DPRINTF(sc, ATH_DBG_BEACON,
"beacon is officially stuck\n");
sc->sc_flags |= SC_OP_TSF_RESET;
ath_reset(sc, false);
}
......@@ -673,6 +674,14 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
/*
* It looks like mac80211 may end up using beacon interval of zero in
* some cases (at least for mesh point). Avoid getting into an
* infinite loop by using a bit safer value instead..
*/
if (intval == 0)
intval = 100;
/* Pull nexttbtt forward to reflect the current TSF */
nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp);
......
......@@ -44,6 +44,44 @@ static int ath9k_debugfs_open(struct inode *inode, struct file *file)
return 0;
}
static ssize_t read_file_debug(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char buf[32];
unsigned int len;
len = snprintf(buf, sizeof(buf), "0x%08x\n", sc->debug.debug_mask);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
unsigned long mask;
char buf[32];
ssize_t len;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EINVAL;
buf[len] = '\0';
if (strict_strtoul(buf, 0, &mask))
return -EINVAL;
sc->debug.debug_mask = mask;
return count;
}
static const struct file_operations fops_debug = {
.read = read_file_debug,
.write = write_file_debug,
.open = ath9k_debugfs_open,
.owner = THIS_MODULE
};
static ssize_t read_file_dma(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
......@@ -224,111 +262,66 @@ static const struct file_operations fops_interrupt = {
.owner = THIS_MODULE
};
static void ath_debug_stat_11n_rc(struct ath_softc *sc, struct sk_buff *skb)
{
struct ath_tx_info_priv *tx_info_priv = NULL;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *rates = tx_info->status.rates;
int final_ts_idx, idx;
tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
final_ts_idx = tx_info_priv->tx.ts_rateindex;
idx = sc->cur_rate_table->info[rates[final_ts_idx].idx].dot11rate;
sc->debug.stats.n_rcstats[idx].success++;
}
static void ath_debug_stat_legacy_rc(struct ath_softc *sc, struct sk_buff *skb)
void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb)
{
struct ath_tx_info_priv *tx_info_priv = NULL;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *rates = tx_info->status.rates;
int final_ts_idx, idx;
struct ath_rc_stats *stats;
tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
final_ts_idx = tx_info_priv->tx.ts_rateindex;
idx = rates[final_ts_idx].idx;
sc->debug.stats.legacy_rcstats[idx].success++;
}
void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb)
{
if (conf_is_ht(&sc->hw->conf))
ath_debug_stat_11n_rc(sc, skb);
else
ath_debug_stat_legacy_rc(sc, skb);
stats = &sc->debug.stats.rcstats[idx];
stats->success++;
}
/* FIXME: legacy rates, later on .. */
void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per)
{
if (conf_is_ht(&sc->hw->conf)) {
int idx = sc->cur_rate_table->info[rix].dot11rate;
struct ath_rc_stats *stats = &sc->debug.stats.rcstats[rix];
sc->debug.stats.n_rcstats[idx].xretries += xretries;
sc->debug.stats.n_rcstats[idx].retries += retries;
sc->debug.stats.n_rcstats[idx].per = per;
}
stats->xretries += xretries;
stats->retries += retries;
stats->per = per;
}
static ssize_t ath_read_file_stat_11n_rc(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char buf[1024];
unsigned int len = 0;
char *buf;
unsigned int len = 0, max;
int i = 0;
ssize_t retval;
len += sprintf(buf, "%7s %13s %8s %8s %6s\n\n", "Rate", "Success",
"Retries", "XRetries", "PER");
for (i = 0; i <= 15; i++) {
len += snprintf(buf + len, sizeof(buf) - len,
"%5s%3d: %8u %8u %8u %8u\n", "MCS", i,
sc->debug.stats.n_rcstats[i].success,
sc->debug.stats.n_rcstats[i].retries,
sc->debug.stats.n_rcstats[i].xretries,
sc->debug.stats.n_rcstats[i].per);
}
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
if (sc->cur_rate_table == NULL)
return 0;
static ssize_t ath_read_file_stat_legacy_rc(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char buf[512];
unsigned int len = 0;
int i = 0;
max = 80 + sc->cur_rate_table->rate_cnt * 64;
buf = kmalloc(max + 1, GFP_KERNEL);
if (buf == NULL)
return 0;
buf[max] = 0;
len += sprintf(buf, "%7s %13s\n\n", "Rate", "Success");
len += sprintf(buf, "%5s %15s %8s %9s %3s\n\n", "Rate", "Success",
"Retries", "XRetries", "PER");
for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) {
len += snprintf(buf + len, sizeof(buf) - len, "%5u: %12u\n",
sc->cur_rate_table->info[i].ratekbps / 1000,
sc->debug.stats.legacy_rcstats[i].success);
u32 ratekbps = sc->cur_rate_table->info[i].ratekbps;
struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i];
len += snprintf(buf + len, max - len,
"%3u.%d: %8u %8u %8u %8u\n", ratekbps / 1000,
(ratekbps % 1000) / 100, stats->success,
stats->retries, stats->xretries,
stats->per);
}
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
if (sc->cur_rate_table == NULL)
return 0;
if (conf_is_ht(&sc->hw->conf))
return ath_read_file_stat_11n_rc(file, user_buf, count, ppos);
else
return ath_read_file_stat_legacy_rc(file, user_buf, count ,ppos);
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
}
static const struct file_operations fops_rcstat = {
......@@ -506,6 +499,11 @@ int ath9k_init_debug(struct ath_softc *sc)
if (!sc->debug.debugfs_phy)
goto err;
sc->debug.debugfs_debug = debugfs_create_file("debug",
S_IRUGO | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug);
if (!sc->debug.debugfs_debug)
goto err;
sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUGO,
sc->debug.debugfs_phy, sc, &fops_dma);
if (!sc->debug.debugfs_dma)
......@@ -543,6 +541,7 @@ void ath9k_exit_debug(struct ath_softc *sc)
debugfs_remove(sc->debug.debugfs_rcstat);
debugfs_remove(sc->debug.debugfs_interrupt);
debugfs_remove(sc->debug.debugfs_dma);
debugfs_remove(sc->debug.debugfs_debug);
debugfs_remove(sc->debug.debugfs_phy);
}
......
......@@ -80,11 +80,7 @@ struct ath_interrupt_stats {
u32 dtim;
};
struct ath_legacy_rc_stats {
u32 success;
};
struct ath_11n_rc_stats {
struct ath_rc_stats {
u32 success;
u32 retries;
u32 xretries;
......@@ -93,13 +89,13 @@ struct ath_11n_rc_stats {
struct ath_stats {
struct ath_interrupt_stats istats;
struct ath_legacy_rc_stats legacy_rcstats[12]; /* max(11a,11b,11g) */
struct ath_11n_rc_stats n_rcstats[16]; /* 0..15 MCS rates */
struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
};
struct ath9k_debug {
int debug_mask;
struct dentry *debugfs_phy;
struct dentry *debugfs_debug;
struct dentry *debugfs_dma;
struct dentry *debugfs_interrupt;
struct dentry *debugfs_rcstat;
......
......@@ -1192,120 +1192,69 @@ static bool ath_is_rfkill_set(struct ath_softc *sc)
ah->rfkill_polarity;
}
/* h/w rfkill poll function */
static void ath_rfkill_poll(struct work_struct *work)
/* s/w rfkill handlers */
static int ath_rfkill_set_block(void *data, bool blocked)
{
struct ath_softc *sc = container_of(work, struct ath_softc,
rf_kill.rfkill_poll.work);
bool radio_on;
if (sc->sc_flags & SC_OP_INVALID)
return;
radio_on = !ath_is_rfkill_set(sc);
/*
* enable/disable radio only when there is a
* state change in RF switch
*/
if (radio_on == !!(sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED)) {
enum rfkill_state state;
if (sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED) {
state = radio_on ? RFKILL_STATE_SOFT_BLOCKED
: RFKILL_STATE_HARD_BLOCKED;
} else if (radio_on) {
ath_radio_enable(sc);
state = RFKILL_STATE_UNBLOCKED;
} else {
ath_radio_disable(sc);
state = RFKILL_STATE_HARD_BLOCKED;
}
if (state == RFKILL_STATE_HARD_BLOCKED)
sc->sc_flags |= SC_OP_RFKILL_HW_BLOCKED;
else
sc->sc_flags &= ~SC_OP_RFKILL_HW_BLOCKED;
struct ath_softc *sc = data;
rfkill_force_state(sc->rf_kill.rfkill, state);
}
if (blocked)
ath_radio_disable(sc);
else
ath_radio_enable(sc);
queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll,
msecs_to_jiffies(ATH_RFKILL_POLL_INTERVAL));
return 0;
}
/* s/w rfkill handler */
static int ath_sw_toggle_radio(void *data, enum rfkill_state state)
static void ath_rfkill_poll_state(struct rfkill *rfkill, void *data)
{
struct ath_softc *sc = data;
bool blocked = !!ath_is_rfkill_set(sc);
switch (state) {
case RFKILL_STATE_SOFT_BLOCKED:
if (!(sc->sc_flags & (SC_OP_RFKILL_HW_BLOCKED |
SC_OP_RFKILL_SW_BLOCKED)))
ath_radio_disable(sc);
sc->sc_flags |= SC_OP_RFKILL_SW_BLOCKED;
return 0;
case RFKILL_STATE_UNBLOCKED:
if ((sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED)) {
sc->sc_flags &= ~SC_OP_RFKILL_SW_BLOCKED;
if (sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED) {
DPRINTF(sc, ATH_DBG_FATAL, "Can't turn on the"
"radio as it is disabled by h/w\n");
return -EPERM;
}
ath_radio_enable(sc);
}
return 0;
default:
return -EINVAL;
}
if (rfkill_set_hw_state(rfkill, blocked))
ath_radio_disable(sc);
else
ath_radio_enable(sc);
}
/* Init s/w rfkill */
static int ath_init_sw_rfkill(struct ath_softc *sc)
{
sc->rf_kill.rfkill = rfkill_allocate(wiphy_dev(sc->hw->wiphy),
RFKILL_TYPE_WLAN);
sc->rf_kill.ops.set_block = ath_rfkill_set_block;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
sc->rf_kill.ops.poll = ath_rfkill_poll_state;
snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name),
"ath9k-%s::rfkill", wiphy_name(sc->hw->wiphy));
sc->rf_kill.rfkill = rfkill_alloc(sc->rf_kill.rfkill_name,
wiphy_dev(sc->hw->wiphy),
RFKILL_TYPE_WLAN,
&sc->rf_kill.ops, sc);
if (!sc->rf_kill.rfkill) {
DPRINTF(sc, ATH_DBG_FATAL, "Failed to allocate rfkill\n");
return -ENOMEM;
}
snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name),
"ath9k-%s::rfkill", wiphy_name(sc->hw->wiphy));
sc->rf_kill.rfkill->name = sc->rf_kill.rfkill_name;
sc->rf_kill.rfkill->data = sc;
sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio;
sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED;
return 0;
}
/* Deinitialize rfkill */
static void ath_deinit_rfkill(struct ath_softc *sc)
{
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
if (sc->sc_flags & SC_OP_RFKILL_REGISTERED) {
rfkill_unregister(sc->rf_kill.rfkill);
rfkill_destroy(sc->rf_kill.rfkill);
sc->sc_flags &= ~SC_OP_RFKILL_REGISTERED;
sc->rf_kill.rfkill = NULL;
}
}
static int ath_start_rfkill_poll(struct ath_softc *sc)
{
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
queue_delayed_work(sc->hw->workqueue,
&sc->rf_kill.rfkill_poll, 0);
if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) {
if (rfkill_register(sc->rf_kill.rfkill)) {
DPRINTF(sc, ATH_DBG_FATAL,
"Unable to register rfkill\n");
rfkill_free(sc->rf_kill.rfkill);
rfkill_destroy(sc->rf_kill.rfkill);
/* Deinitialize the device */
ath_cleanup(sc);
......@@ -1678,10 +1627,6 @@ int ath_attach(u16 devid, struct ath_softc *sc)
goto error_attach;
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
/* Initialze h/w Rfkill */
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll);
/* Initialize s/w rfkill */
error = ath_init_sw_rfkill(sc);
if (error)
......@@ -2214,10 +2159,8 @@ static void ath9k_stop(struct ieee80211_hw *hw)
} else
sc->rx.rxlink = NULL;
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
#endif
rfkill_pause_polling(sc->rf_kill.rfkill);
/* disable HAL and put h/w to sleep */
ath9k_hw_disable(sc->sc_ah);
ath9k_hw_configpcipowersave(sc->sc_ah, 1);
......
......@@ -227,11 +227,6 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
#endif
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
......@@ -256,16 +251,6 @@ static int ath_pci_resume(struct pci_dev *pdev)
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
/*
* check the h/w rfkill state on resume
* and start the rfkill poll timer
*/
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
queue_delayed_work(sc->hw->workqueue,
&sc->rf_kill.rfkill_poll, 0);
#endif
return 0;
}
......
......@@ -366,11 +366,17 @@ static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg)
if (rd & COUNTRY_ERD_FLAG) {
/* EEPROM value is a country code */
u16 cc = rd & ~COUNTRY_ERD_FLAG;
printk(KERN_DEBUG
"ath: EEPROM indicates we should expect "
"a country code\n");
for (i = 0; i < ARRAY_SIZE(allCountries); i++)
if (allCountries[i].countryCode == cc)
return true;
} else {
/* EEPROM value is a regpair value */
if (rd != CTRY_DEFAULT)
printk(KERN_DEBUG "ath: EEPROM indicates we "
"should expect a direct regpair map\n");
for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
if (regDomainPairs[i].regDmnEnum == rd)
return true;
......@@ -477,6 +483,11 @@ ath_regd_init(struct ath_regulatory *reg,
struct country_code_to_enum_rd *country = NULL;
u16 regdmn;
if (!reg)
return -EINVAL;
printk(KERN_DEBUG "ath: EEPROM regdomain: 0x%0x\n", reg->current_rd);
if (!ath_regd_is_eeprom_valid(reg)) {
printk(KERN_ERR "ath: Invalid EEPROM contents\n");
return -EINVAL;
......@@ -486,20 +497,30 @@ ath_regd_init(struct ath_regulatory *reg,
reg->country_code = ath_regd_get_default_country(regdmn);
if (reg->country_code == CTRY_DEFAULT &&
regdmn == CTRY_DEFAULT)
regdmn == CTRY_DEFAULT) {
printk(KERN_DEBUG "ath: EEPROM indicates default "
"country code should be used\n");
reg->country_code = CTRY_UNITED_STATES;
}
if (reg->country_code == CTRY_DEFAULT) {
country = NULL;
} else {
printk(KERN_DEBUG "ath: doing EEPROM country->regdmn "
"map search\n");
country = ath_regd_find_country(reg->country_code);
if (country == NULL) {
printk(KERN_DEBUG
"ath: Country is NULL!!!!, cc= %d\n",
"ath: no valid country maps found for "
"country code: 0x%0x\n",
reg->country_code);
return -EINVAL;
} else
} else {
regdmn = country->regDmnEnum;
printk(KERN_DEBUG "ath: country maps to "
"regdmn code: 0x%0x\n",
regdmn);
}
}
reg->regpair = ath_get_regpair(regdmn);
......@@ -523,7 +544,7 @@ ath_regd_init(struct ath_regulatory *reg,
printk(KERN_DEBUG "ath: Country alpha2 being used: %c%c\n",
reg->alpha2[0], reg->alpha2[1]);
printk(KERN_DEBUG "ath: Regpair detected: 0x%0x\n",
printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n",
reg->regpair->regDmnEnum);
ath_regd_init_wiphy(reg, wiphy, reg_notifier);
......
......@@ -102,7 +102,7 @@ config B43_LEDS
# if it's possible.
config B43_RFKILL
bool
depends on B43 && (RFKILL = y || RFKILL = B43) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43)
depends on B43 && (RFKILL = y || RFKILL = B43)
default y
# This config option automatically enables b43 HW-RNG support,
......
......@@ -87,7 +87,7 @@ static void b43_led_brightness_set(struct led_classdev *led_dev,
}
static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
const char *name, char *default_trigger,
const char *name, const char *default_trigger,
u8 led_index, bool activelow)
{
int err;
......
......@@ -3470,7 +3470,7 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
if (!!conf->radio_enabled != phy->radio_on) {
if (conf->radio_enabled) {
b43_software_rfkill(dev, RFKILL_STATE_UNBLOCKED);
b43_software_rfkill(dev, false);
b43info(dev->wl, "Radio turned on by software\n");
if (!dev->radio_hw_enable) {
b43info(dev->wl, "The hardware RF-kill button "
......@@ -3478,7 +3478,7 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
"Press the button to turn it on.\n");
}
} else {
b43_software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
b43_software_rfkill(dev, true);
b43info(dev->wl, "Radio turned off by software\n");
}
}
......
......@@ -480,11 +480,11 @@ static bool b43_aphy_op_supports_hwpctl(struct b43_wldev *dev)
}
static void b43_aphy_op_software_rfkill(struct b43_wldev *dev,
enum rfkill_state state)
bool blocked)
{
struct b43_phy *phy = &dev->phy;
if (state == RFKILL_STATE_UNBLOCKED) {
if (!blocked) {
if (phy->radio_on)
return;
b43_radio_write16(dev, 0x0004, 0x00C0);
......
......@@ -84,7 +84,7 @@ int b43_phy_init(struct b43_wldev *dev)
phy->channel = ops->get_default_chan(dev);
ops->software_rfkill(dev, RFKILL_STATE_UNBLOCKED);
ops->software_rfkill(dev, false);
err = ops->init(dev);
if (err) {
b43err(dev->wl, "PHY init failed\n");
......@@ -104,7 +104,7 @@ int b43_phy_init(struct b43_wldev *dev)
if (ops->exit)
ops->exit(dev);
err_block_rf:
ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
ops->software_rfkill(dev, true);
return err;
}
......@@ -113,7 +113,7 @@ void b43_phy_exit(struct b43_wldev *dev)
{
const struct b43_phy_operations *ops = dev->phy.ops;
ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
ops->software_rfkill(dev, true);
if (ops->exit)
ops->exit(dev);
}
......@@ -295,18 +295,13 @@ int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
return err;
}
void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state)
void b43_software_rfkill(struct b43_wldev *dev, bool blocked)
{
struct b43_phy *phy = &dev->phy;
if (state == RFKILL_STATE_HARD_BLOCKED) {
/* We cannot hardware-block the device */
state = RFKILL_STATE_SOFT_BLOCKED;
}
b43_mac_suspend(dev);
phy->ops->software_rfkill(dev, state);
phy->radio_on = (state == RFKILL_STATE_UNBLOCKED);
phy->ops->software_rfkill(dev, blocked);
phy->radio_on = !blocked;
b43_mac_enable(dev);
}
......
......@@ -159,7 +159,7 @@ struct b43_phy_operations {
/* Radio */
bool (*supports_hwpctl)(struct b43_wldev *dev);
void (*software_rfkill)(struct b43_wldev *dev, enum rfkill_state state);
void (*software_rfkill)(struct b43_wldev *dev, bool blocked);
void (*switch_analog)(struct b43_wldev *dev, bool on);
int (*switch_channel)(struct b43_wldev *dev, unsigned int new_channel);
unsigned int (*get_default_chan)(struct b43_wldev *dev);
......@@ -364,7 +364,7 @@ int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel);
/**
* b43_software_rfkill - Turn the radio ON or OFF in software.
*/
void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state);
void b43_software_rfkill(struct b43_wldev *dev, bool blocked);
/**
* b43_phy_txpower_check - Check TX power output.
......
......@@ -2592,7 +2592,7 @@ static bool b43_gphy_op_supports_hwpctl(struct b43_wldev *dev)
}
static void b43_gphy_op_software_rfkill(struct b43_wldev *dev,
enum rfkill_state state)
bool blocked)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
......@@ -2600,7 +2600,7 @@ static void b43_gphy_op_software_rfkill(struct b43_wldev *dev,
might_sleep();
if (state == RFKILL_STATE_UNBLOCKED) {
if (!blocked) {
/* Turn radio ON */
if (phy->radio_on)
return;
......
......@@ -488,7 +488,7 @@ static void b43_lpphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
}
static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
enum rfkill_state state)
bool blocked)
{
//TODO
}
......
......@@ -579,7 +579,7 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
}
static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
enum rfkill_state state)
bool blocked)
{//TODO
}
......
......@@ -45,12 +45,11 @@ static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
}
/* The poll callback for the hardware button. */
static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
static void b43_rfkill_poll(struct rfkill *rfkill, void *data)
{
struct b43_wldev *dev = poll_dev->private;
struct b43_wldev *dev = data;
struct b43_wl *wl = dev->wl;
bool enabled;
bool report_change = 0;
mutex_lock(&wl->mutex);
if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) {
......@@ -60,68 +59,55 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
enabled = b43_is_hw_radio_enabled(dev);
if (unlikely(enabled != dev->radio_hw_enable)) {
dev->radio_hw_enable = enabled;
report_change = 1;
b43info(wl, "Radio hardware status changed to %s\n",
enabled ? "ENABLED" : "DISABLED");
enabled = !rfkill_set_hw_state(rfkill, !enabled);
if (enabled != dev->phy.radio_on)
b43_software_rfkill(dev, !enabled);
}
mutex_unlock(&wl->mutex);
/* 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. */
static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state)
static int b43_rfkill_soft_set(void *data, bool blocked)
{
struct b43_wldev *dev = data;
struct b43_wl *wl = dev->wl;
int err = -EBUSY;
int err = -EINVAL;
if (!wl->rfkill.registered)
return 0;
if (WARN_ON(!wl->rfkill.registered))
return -EINVAL;
mutex_lock(&wl->mutex);
if (b43_status(dev) < B43_STAT_INITIALIZED)
goto out_unlock;
if (!dev->radio_hw_enable)
goto out_unlock;
if (!blocked != dev->phy.radio_on)
b43_software_rfkill(dev, blocked);
err = 0;
switch (state) {
case RFKILL_STATE_UNBLOCKED:
if (!dev->radio_hw_enable) {
/* No luck. We can't toggle the hardware RF-kill
* button from software. */
err = -EBUSY;
goto out_unlock;
}
if (!dev->phy.radio_on)
b43_software_rfkill(dev, state);
break;
case RFKILL_STATE_SOFT_BLOCKED:
if (dev->phy.radio_on)
b43_software_rfkill(dev, state);
break;
default:
b43warn(wl, "Received unexpected rfkill state %d.\n", state);
break;
}
out_unlock:
mutex_unlock(&wl->mutex);
return err;
}
char *b43_rfkill_led_name(struct b43_wldev *dev)
const char *b43_rfkill_led_name(struct b43_wldev *dev)
{
struct b43_rfkill *rfk = &(dev->wl->rfkill);
if (!rfk->registered)
return NULL;
return rfkill_get_led_name(rfk->rfkill);
return rfkill_get_led_trigger_name(rfk->rfkill);
}
static const struct rfkill_ops b43_rfkill_ops = {
.set_block = b43_rfkill_soft_set,
.poll = b43_rfkill_poll,
};
void b43_rfkill_init(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
......@@ -130,65 +116,26 @@ void b43_rfkill_init(struct b43_wldev *dev)
rfk->registered = 0;
rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
if (!rfk->rfkill)
goto out_error;
snprintf(rfk->name, sizeof(rfk->name),
"b43-%s", wiphy_name(wl->hw->wiphy));
rfk->rfkill->name = rfk->name;
rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
rfk->rfkill->data = dev;
rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle;
rfk->poll_dev = input_allocate_polled_device();
if (!rfk->poll_dev) {
rfkill_free(rfk->rfkill);
goto err_freed_rfk;
}
rfk->poll_dev->private = 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);
rfk->rfkill = rfkill_alloc(rfk->name,
dev->dev->dev,
RFKILL_TYPE_WLAN,
&b43_rfkill_ops, dev);
if (!rfk->rfkill)
goto out_error;
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 */
#if !defined(CONFIG_RFKILL_INPUT) && !defined(CONFIG_RFKILL_INPUT_MODULE)
b43warn(wl, "The rfkill-input subsystem is not available. "
"The built-in radio LED will not work.\n");
#endif
err = input_register_polled_device(rfk->poll_dev);
if (err)
goto err_unreg_rfk;
goto err_free;
rfk->registered = 1;
return;
err_unreg_rfk:
rfkill_unregister(rfk->rfkill);
err_free_polldev:
input_free_polled_device(rfk->poll_dev);
rfk->poll_dev = NULL;
err_freed_rfk:
rfk->rfkill = NULL;
out_error:
err_free:
rfkill_destroy(rfk->rfkill);
out_error:
rfk->registered = 0;
b43warn(wl, "RF-kill button init failed\n");
}
......@@ -201,9 +148,7 @@ void b43_rfkill_exit(struct b43_wldev *dev)
return;
rfk->registered = 0;
input_unregister_polled_device(rfk->poll_dev);
rfkill_unregister(rfk->rfkill);
input_free_polled_device(rfk->poll_dev);
rfk->poll_dev = NULL;
rfkill_destroy(rfk->rfkill);
rfk->rfkill = NULL;
}
......@@ -7,14 +7,11 @@ struct b43_wldev;
#ifdef CONFIG_B43_RFKILL
#include <linux/rfkill.h>
#include <linux/input-polldev.h>
struct b43_rfkill {
/* The RFKILL subsystem data structure */
struct rfkill *rfkill;
/* The poll device for the RFKILL input button */
struct input_polled_dev *poll_dev;
/* Did initialization succeed? Used for freeing. */
bool registered;
/* The unique name of this rfkill switch */
......@@ -26,7 +23,7 @@ struct b43_rfkill {
void b43_rfkill_init(struct b43_wldev *dev);
void b43_rfkill_exit(struct b43_wldev *dev);
char * b43_rfkill_led_name(struct b43_wldev *dev);
const char *b43_rfkill_led_name(struct b43_wldev *dev);
#else /* CONFIG_B43_RFKILL */
......
......@@ -47,7 +47,7 @@ config B43LEGACY_LEDS
# if it's possible.
config B43LEGACY_RFKILL
bool
depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43LEGACY)
depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY)
default y
# This config option automatically enables b43 HW-RNG support,
......
......@@ -86,7 +86,8 @@ static void b43legacy_led_brightness_set(struct led_classdev *led_dev,
static int b43legacy_register_led(struct b43legacy_wldev *dev,
struct b43legacy_led *led,
const char *name, char *default_trigger,
const char *name,
const char *default_trigger,
u8 led_index, bool activelow)
{
int err;
......
......@@ -45,12 +45,11 @@ static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
}
/* The poll callback for the hardware button. */
static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev)
static void b43legacy_rfkill_poll(struct rfkill *rfkill, void *data)
{
struct b43legacy_wldev *dev = poll_dev->private;
struct b43legacy_wldev *dev = data;
struct b43legacy_wl *wl = dev->wl;
bool enabled;
bool report_change = 0;
mutex_lock(&wl->mutex);
if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) {
......@@ -60,71 +59,64 @@ static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev)
enabled = b43legacy_is_hw_radio_enabled(dev);
if (unlikely(enabled != dev->radio_hw_enable)) {
dev->radio_hw_enable = enabled;
report_change = 1;
b43legacyinfo(wl, "Radio hardware status changed to %s\n",
enabled ? "ENABLED" : "DISABLED");
enabled = !rfkill_set_hw_state(rfkill, !enabled);
if (enabled != dev->phy.radio_on) {
if (enabled)
b43legacy_radio_turn_on(dev);
else
b43legacy_radio_turn_off(dev, 0);
}
}
mutex_unlock(&wl->mutex);
/* 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.
* This is called without locking. */
static int b43legacy_rfkill_soft_toggle(void *data, enum rfkill_state state)
static int b43legacy_rfkill_soft_set(void *data, bool blocked)
{
struct b43legacy_wldev *dev = data;
struct b43legacy_wl *wl = dev->wl;
int err = -EBUSY;
int ret = -EINVAL;
if (!wl->rfkill.registered)
return 0;
return -EINVAL;
mutex_lock(&wl->mutex);
if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
goto out_unlock;
err = 0;
switch (state) {
case RFKILL_STATE_UNBLOCKED:
if (!dev->radio_hw_enable) {
/* No luck. We can't toggle the hardware RF-kill
* button from software. */
err = -EBUSY;
goto out_unlock;
}
if (!dev->phy.radio_on)
if (!dev->radio_hw_enable)
goto out_unlock;
if (!blocked != dev->phy.radio_on) {
if (!blocked)
b43legacy_radio_turn_on(dev);
break;
case RFKILL_STATE_SOFT_BLOCKED:
if (dev->phy.radio_on)
else
b43legacy_radio_turn_off(dev, 0);
break;
default:
b43legacywarn(wl, "Received unexpected rfkill state %d.\n",
state);
break;
}
ret = 0;
out_unlock:
mutex_unlock(&wl->mutex);
return err;
return ret;
}
char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
const char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
{
struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
if (!rfk->registered)
return NULL;
return rfkill_get_led_name(rfk->rfkill);
return rfkill_get_led_trigger_name(rfk->rfkill);
}
static const struct rfkill_ops b43legacy_rfkill_ops = {
.set_block = b43legacy_rfkill_soft_set,
.poll = b43legacy_rfkill_poll,
};
void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
{
struct b43legacy_wl *wl = dev->wl;
......@@ -133,60 +125,25 @@ void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
rfk->registered = 0;
rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
if (!rfk->rfkill)
goto out_error;
snprintf(rfk->name, sizeof(rfk->name),
"b43legacy-%s", wiphy_name(wl->hw->wiphy));
rfk->rfkill->name = rfk->name;
rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
rfk->rfkill->data = dev;
rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle;
rfk->poll_dev = input_allocate_polled_device();
if (!rfk->poll_dev) {
rfkill_free(rfk->rfkill);
goto err_freed_rfk;
}
rfk->poll_dev->private = dev;
rfk->poll_dev->poll = b43legacy_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);
rfk->rfkill = rfkill_alloc(rfk->name,
dev->dev->dev,
RFKILL_TYPE_WLAN,
&b43legacy_rfkill_ops, dev);
if (!rfk->rfkill)
goto out_error;
err = rfkill_register(rfk->rfkill);
if (err)
goto err_free_polldev;
#ifdef CONFIG_RFKILL_INPUT_MODULE
/* B43legacy RF-kill isn't useful without the rfkill-input subsystem.
* Try to load the module. */
err = request_module("rfkill-input");
if (err)
b43legacywarn(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;
goto err_free;
rfk->registered = 1;
return;
err_unreg_rfk:
rfkill_unregister(rfk->rfkill);
err_free_polldev:
input_free_polled_device(rfk->poll_dev);
rfk->poll_dev = NULL;
err_freed_rfk:
rfk->rfkill = NULL;
out_error:
err_free:
rfkill_destroy(rfk->rfkill);
out_error:
rfk->registered = 0;
b43legacywarn(wl, "RF-kill button init failed\n");
}
......@@ -199,10 +156,8 @@ void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
return;
rfk->registered = 0;
input_unregister_polled_device(rfk->poll_dev);
rfkill_unregister(rfk->rfkill);
input_free_polled_device(rfk->poll_dev);
rfk->poll_dev = NULL;
rfkill_destroy(rfk->rfkill);
rfk->rfkill = NULL;
}
......@@ -6,16 +6,12 @@ struct b43legacy_wldev;
#ifdef CONFIG_B43LEGACY_RFKILL
#include <linux/rfkill.h>
#include <linux/workqueue.h>
#include <linux/input-polldev.h>
struct b43legacy_rfkill {
/* The RFKILL subsystem data structure */
struct rfkill *rfkill;
/* The poll device for the RFKILL input button */
struct input_polled_dev *poll_dev;
/* Did initialization succeed? Used for freeing. */
bool registered;
/* The unique name of this rfkill switch */
......@@ -27,7 +23,7 @@ struct b43legacy_rfkill {
void b43legacy_rfkill_init(struct b43legacy_wldev *dev);
void b43legacy_rfkill_exit(struct b43legacy_wldev *dev);
char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev);
const char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev);
#else /* CONFIG_B43LEGACY_RFKILL */
......
......@@ -5,15 +5,14 @@ config IWLWIFI
select FW_LOADER
select MAC80211_LEDS if IWLWIFI_LEDS
select LEDS_CLASS if IWLWIFI_LEDS
select RFKILL if IWLWIFI_RFKILL
config IWLWIFI_LEDS
bool "Enable LED support in iwlagn and iwl3945 drivers"
depends on IWLWIFI
config IWLWIFI_RFKILL
bool "Enable RF kill support in iwlagn and iwl3945 drivers"
depends on IWLWIFI
def_bool y
depends on IWLWIFI && RFKILL
config IWLWIFI_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwlagn driver"
......
......@@ -167,10 +167,6 @@ static int iwl3945_led_disassociate(struct iwl_priv *priv, int led_id)
IWL_DEBUG_LED(priv, "Disassociated\n");
priv->allow_blinking = 0;
if (iwl_is_rfkill(priv))
iwl3945_led_off(priv, led_id);
else
iwl3945_led_on(priv, led_id);
return 0;
}
......
......@@ -38,6 +38,7 @@
#include "iwl-commands.h"
#include "iwl-3945.h"
#include "iwl-sta.h"
#define RS_NAME "iwl-3945-rs"
......@@ -714,13 +715,13 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!rs_sta->ibss_sta_added) {
u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
u8 sta_id = iwl_find_station(priv, hdr->addr1);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_RATE(priv, "LQ: ADD station %pm\n",
hdr->addr1);
sta_id = iwl3945_add_station(priv,
hdr->addr1, 0, CMD_ASYNC, NULL);
sta_id = iwl_add_station(priv, hdr->addr1, false,
CMD_ASYNC, NULL);
}
if (sta_id != IWL_INVALID_STATION)
rs_sta->ibss_sta_added = 1;
......@@ -975,7 +976,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
rcu_read_lock();
sta = ieee80211_find_sta(hw, priv->stations_39[sta_id].sta.sta.addr);
sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr);
if (!sta) {
rcu_read_unlock();
return;
......
......@@ -769,35 +769,6 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
return ;
}
u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *addr)
{
int i, start = IWL_AP_ID;
int ret = IWL_INVALID_STATION;
unsigned long flags;
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) ||
(priv->iw_mode == NL80211_IFTYPE_AP))
start = IWL_STA_ID;
if (is_broadcast_ether_addr(addr))
return priv->hw_params.bcast_sta_id;
spin_lock_irqsave(&priv->sta_lock, flags);
for (i = start; i < priv->hw_params.max_stations; i++)
if ((priv->stations_39[i].used) &&
(!compare_ether_addr
(priv->stations_39[i].sta.sta.addr, addr))) {
ret = i;
goto out;
}
IWL_DEBUG_INFO(priv, "can not find STA %pM (total %d)\n",
addr, priv->num_stations);
out:
spin_unlock_irqrestore(&priv->sta_lock, flags);
return ret;
}
/**
* iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
*
......@@ -875,13 +846,13 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl_cmd *cmd,
u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags)
{
unsigned long flags_spin;
struct iwl3945_station_entry *station;
struct iwl_station_entry *station;
if (sta_id == IWL_INVALID_STATION)
return IWL_INVALID_STATION;
spin_lock_irqsave(&priv->sta_lock, flags_spin);
station = &priv->stations_39[sta_id];
station = &priv->stations[sta_id];
station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK;
station->sta.rate_n_flags = cpu_to_le16(tx_rate);
......@@ -889,8 +860,7 @@ u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags)
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
iwl_send_add_sta(priv,
(struct iwl_addsta_cmd *)&station->sta, flags);
iwl_send_add_sta(priv, &station->sta, flags);
IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n",
sta_id, tx_rate);
return sta_id;
......@@ -2029,7 +1999,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
/* If we issue a new RXON command which required a tune then we must
* send a new TXPOWER command or we won't be able to Tx any frames */
......@@ -2040,7 +2010,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
}
/* Add the broadcast address so we can send broadcast frames */
if (priv->cfg->ops->smgmt->add_station(priv, iwl_bcast_addr, 0, 0, NULL) ==
if (iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL) ==
IWL_INVALID_STATION) {
IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
return -EIO;
......@@ -2050,9 +2020,8 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
* add the IWL_AP_ID to the station rate table */
if (iwl_is_associated(priv) &&
(priv->iw_mode == NL80211_IFTYPE_STATION))
if (priv->cfg->ops->smgmt->add_station(priv,
priv->active_rxon.bssid_addr, 1, 0, NULL)
== IWL_INVALID_STATION) {
if (iwl_add_station(priv, priv->active_rxon.bssid_addr,
true, CMD_SYNC, NULL) == IWL_INVALID_STATION) {
IWL_ERR(priv, "Error adding AP address for transmit\n");
return -EIO;
}
......@@ -2466,13 +2435,25 @@ static u16 iwl3945_get_hcmd_size(u8 cmd_id, u16 len)
}
}
static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
{
u16 size = (u16)sizeof(struct iwl3945_addsta_cmd);
memcpy(data, cmd, size);
return size;
struct iwl3945_addsta_cmd *addsta = (struct iwl3945_addsta_cmd *)data;
addsta->mode = cmd->mode;
memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo));
addsta->station_flags = cmd->station_flags;
addsta->station_flags_msk = cmd->station_flags_msk;
addsta->tid_disable_tx = cpu_to_le16(0);
addsta->rate_n_flags = cmd->rate_n_flags;
addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
return (u16)sizeof(struct iwl3945_addsta_cmd);
}
/**
* iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table
*/
......@@ -2842,15 +2823,6 @@ static struct iwl_lib_ops iwl3945_lib = {
.config_ap = iwl3945_config_ap,
};
static struct iwl_station_mgmt_ops iwl3945_station_mgmt = {
.add_station = iwl3945_add_station,
#if 0
.remove_station = iwl3945_remove_station,
#endif
.find_station = iwl3945_hw_find_station,
.clear_station_table = iwl3945_clear_stations_table,
};
static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
.get_hcmd_size = iwl3945_get_hcmd_size,
.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
......@@ -2860,7 +2832,6 @@ static struct iwl_ops iwl3945_ops = {
.lib = &iwl3945_lib,
.hcmd = &iwl3945_hcmd,
.utils = &iwl3945_hcmd_utils,
.smgmt = &iwl3945_station_mgmt,
};
static struct iwl_cfg iwl3945_bg_cfg = {
......
......@@ -202,12 +202,6 @@ struct iwl3945_ibss_seq {
* for use by iwl-*.c
*
*****************************************************************************/
struct iwl3945_addsta_cmd;
extern int iwl3945_send_add_station(struct iwl_priv *priv,
struct iwl3945_addsta_cmd *sta, u8 flags);
extern u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *bssid,
int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info);
extern void iwl3945_clear_stations_table(struct iwl_priv *priv);
extern int iwl3945_power_init_handle(struct iwl_priv *priv);
extern int iwl3945_eeprom_init(struct iwl_priv *priv);
extern int iwl3945_calc_db_from_ratio(int sig_ratio);
......
......@@ -2221,13 +2221,6 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
cancel_work_sync(&priv->txpower_work);
}
static struct iwl_station_mgmt_ops iwl4965_station_mgmt = {
.add_station = iwl_add_station_flags,
.remove_station = iwl_remove_station,
.find_station = iwl_find_station,
.clear_station_table = iwl_clear_stations_table,
};
static struct iwl_hcmd_ops iwl4965_hcmd = {
.rxon_assoc = iwl4965_send_rxon_assoc,
.commit_rxon = iwl_commit_rxon,
......@@ -2297,7 +2290,6 @@ static struct iwl_ops iwl4965_ops = {
.lib = &iwl4965_lib,
.hcmd = &iwl4965_hcmd,
.utils = &iwl4965_hcmd_utils,
.smgmt = &iwl4965_station_mgmt,
};
struct iwl_cfg iwl4965_agn_cfg = {
......
......@@ -651,7 +651,7 @@ static void iwl5000_init_alive_start(struct iwl_priv *priv)
goto restart;
}
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
ret = priv->cfg->ops->lib->alive_notify(priv);
if (ret) {
IWL_WARN(priv,
......@@ -1049,7 +1049,10 @@ static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
{
u16 size = (u16)sizeof(struct iwl_addsta_cmd);
memcpy(data, cmd, size);
struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data;
memcpy(addsta, cmd, size);
/* resrved in 5000 */
addsta->rate_n_flags = cpu_to_le16(0);
return size;
}
......@@ -1423,13 +1426,6 @@ int iwl5000_calc_rssi(struct iwl_priv *priv,
return max_rssi - agc - IWL49_RSSI_OFFSET;
}
struct iwl_station_mgmt_ops iwl5000_station_mgmt = {
.add_station = iwl_add_station_flags,
.remove_station = iwl_remove_station,
.find_station = iwl_find_station,
.clear_station_table = iwl_clear_stations_table,
};
struct iwl_hcmd_ops iwl5000_hcmd = {
.rxon_assoc = iwl5000_send_rxon_assoc,
.commit_rxon = iwl_commit_rxon,
......@@ -1549,14 +1545,12 @@ struct iwl_ops iwl5000_ops = {
.lib = &iwl5000_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl5000_hcmd_utils,
.smgmt = &iwl5000_station_mgmt,
};
static struct iwl_ops iwl5150_ops = {
.lib = &iwl5150_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl5000_hcmd_utils,
.smgmt = &iwl5000_station_mgmt,
};
struct iwl_mod_params iwl50_mod_params = {
......
......@@ -72,7 +72,6 @@ static struct iwl_ops iwl6000_ops = {
.lib = &iwl5000_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl6000_hcmd_utils,
.smgmt = &iwl5000_station_mgmt,
};
struct iwl_cfg iwl6000_2ag_cfg = {
......
......@@ -2502,15 +2502,13 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!lq_sta->ibss_sta_added) {
u8 sta_id = priv->cfg->ops->smgmt->find_station(priv,
hdr->addr1);
u8 sta_id = iwl_find_station(priv, hdr->addr1);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n",
hdr->addr1);
sta_id = priv->cfg->ops->smgmt->add_station(priv,
hdr->addr1, 0,
CMD_ASYNC, NULL);
sta_id = iwl_add_station(priv, hdr->addr1,
false, CMD_ASYNC, NULL);
}
if ((sta_id != IWL_INVALID_STATION)) {
lq_sta->lq.sta_id = sta_id;
......@@ -2598,7 +2596,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
lq_sta->ibss_sta_added = 0;
if (priv->iw_mode == NL80211_IFTYPE_AP) {
u8 sta_id = priv->cfg->ops->smgmt->find_station(priv,
u8 sta_id = iwl_find_station(priv,
sta->addr);
/* for IBSS the call are from tasklet */
......@@ -2606,9 +2604,8 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr);
sta_id = priv->cfg->ops->smgmt->add_station(priv,
sta->addr, 0,
CMD_ASYNC, NULL);
sta_id = iwl_add_station(priv, sta->addr, false,
CMD_ASYNC, NULL);
}
if ((sta_id != IWL_INVALID_STATION)) {
lq_sta->lq.sta_id = sta_id;
......@@ -2790,9 +2787,10 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
repeat_rate--;
}
lq_cmd->agg_params.agg_frame_cnt_limit = 64;
lq_cmd->agg_params.agg_dis_start_th = 3;
lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000);
lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_MAX;
lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
lq_cmd->agg_params.agg_time_limit =
cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
}
static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
......
......@@ -188,7 +188,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
}
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
priv->start_calib = 0;
......@@ -1617,7 +1617,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
goto restart;
}
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
ret = priv->cfg->ops->lib->alive_notify(priv);
if (ret) {
IWL_WARN(priv,
......@@ -1703,7 +1703,7 @@ static void __iwl_down(struct iwl_priv *priv)
iwl_leds_unregister(priv);
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
/* Unblock any waiting calls */
wake_up_interruptible_all(&priv->wait_command_queue);
......@@ -1887,8 +1887,6 @@ static int __iwl_up(struct iwl_priv *priv)
/* clear (again), then enable host interrupts */
iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
/* enable dram interrupt */
iwl_reset_ict(priv);
iwl_enable_interrupts(priv);
/* really make sure rfkill handshake bits are cleared */
......@@ -1903,7 +1901,7 @@ static int __iwl_up(struct iwl_priv *priv)
for (i = 0; i < MAX_HW_RESTARTS; i++) {
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
/* load bootstrap state machine,
* load bootstrap program into processor's memory,
......@@ -1962,6 +1960,9 @@ static void iwl_bg_alive_start(struct work_struct *data)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
/* enable dram interrupt */
iwl_reset_ict(priv);
mutex_lock(&priv->mutex);
iwl_alive_start(priv);
mutex_unlock(&priv->mutex);
......@@ -2348,7 +2349,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return -EOPNOTSUPP;
}
addr = sta ? sta->addr : iwl_bcast_addr;
sta_id = priv->cfg->ops->smgmt->find_station(priv, addr);
sta_id = iwl_find_station(priv, addr);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
addr);
......@@ -3121,7 +3122,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
iwl_rx_queue_free(priv, &priv->rxq);
iwl_hw_txq_ctx_free(priv);
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
iwl_eeprom_free(priv);
......
......@@ -1067,7 +1067,7 @@ struct iwl_addsta_cmd {
* Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
__le16 tid_disable_tx;
__le16 reserved1;
__le16 rate_n_flags; /* 3945 only */
/* TID for which to add block-ack support.
* Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
......@@ -1913,6 +1913,18 @@ struct iwl_link_qual_general_params {
u8 start_rate_index[LINK_QUAL_AC_NUM];
} __attribute__ ((packed));
#define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */
#define LINK_QUAL_AGG_TIME_LIMIT_MAX (65535)
#define LINK_QUAL_AGG_TIME_LIMIT_MIN (0)
#define LINK_QUAL_AGG_DISABLE_START_DEF (3)
#define LINK_QUAL_AGG_DISABLE_START_MAX (255)
#define LINK_QUAL_AGG_DISABLE_START_MIN (0)
#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (31)
#define LINK_QUAL_AGG_FRAME_LIMIT_MAX (64)
#define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0)
/**
* struct iwl_link_qual_agg_params
*
......
......@@ -1389,7 +1389,7 @@ int iwl_init_drv(struct iwl_priv *priv)
mutex_init(&priv->mutex);
/* Clear the driver's (not device's) station table */
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
priv->data_retry_limit = -1;
priv->ieee_channels = NULL;
......@@ -1704,8 +1704,9 @@ static irqreturn_t iwl_isr(int irq, void *data)
{
struct iwl_priv *priv = data;
u32 inta, inta_mask;
#ifdef CONFIG_IWLWIFI_DEBUG
u32 inta_fh;
#endif
if (!priv)
return IRQ_NONE;
......@@ -2679,19 +2680,12 @@ int iwl_set_mode(struct iwl_priv *priv, int mode)
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
/* dont commit rxon if rf-kill is on*/
if (!iwl_is_ready_rf(priv))
return -EAGAIN;
cancel_delayed_work(&priv->scan_check);
if (iwl_scan_cancel_timeout(priv, 100)) {
IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
return -EAGAIN;
}
iwlcore_commit_rxon(priv);
return 0;
......
......@@ -83,15 +83,6 @@ struct iwl_cmd;
#define IWL_SKU_A 0x2
#define IWL_SKU_N 0x8
struct iwl_station_mgmt_ops {
u8 (*add_station)(struct iwl_priv *priv, const u8 *addr,
int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info);
int (*remove_station)(struct iwl_priv *priv, const u8 *addr,
int is_ap);
u8 (*find_station)(struct iwl_priv *priv, const u8 *addr);
void (*clear_station_table)(struct iwl_priv *priv);
};
struct iwl_hcmd_ops {
int (*rxon_assoc)(struct iwl_priv *priv);
int (*commit_rxon)(struct iwl_priv *priv);
......@@ -183,7 +174,6 @@ struct iwl_ops {
const struct iwl_lib_ops *lib;
const struct iwl_hcmd_ops *hcmd;
const struct iwl_hcmd_utils_ops *utils;
const struct iwl_station_mgmt_ops *smgmt;
};
struct iwl_mod_params {
......@@ -192,7 +182,7 @@ struct iwl_mod_params {
int disable_hw_scan; /* def: 0 = use h/w scan */
int num_of_queues; /* def: HW dependent */
int num_of_ampdu_queues;/* def: HW dependent */
int disable_11n; /* def: 0 = disable 11n capabilities */
int disable_11n; /* def: 0 = 11n capabilities enabled */
int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */
int antenna; /* def: 0 = both antennas (use diversity) */
int restart_fw; /* def: 1 = restart firmware */
......
......@@ -70,7 +70,6 @@ extern struct iwl_ops iwl5000_ops;
extern struct iwl_lib_ops iwl5000_lib;
extern struct iwl_hcmd_ops iwl5000_hcmd;
extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils;
extern struct iwl_station_mgmt_ops iwl5000_station_mgmt;
/* shared functions from iwl-5000.c */
extern u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len);
......@@ -290,11 +289,11 @@ struct iwl_frame {
#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
enum {
/* CMD_SIZE_NORMAL = 0, */
CMD_SYNC = 0,
CMD_SIZE_NORMAL = 0,
CMD_NO_SKB = 0,
CMD_SIZE_HUGE = (1 << 0),
/* CMD_SYNC = 0, */
CMD_ASYNC = (1 << 1),
/* CMD_NO_SKB = 0, */
CMD_WANT_SKB = (1 << 2),
};
......@@ -1119,8 +1118,6 @@ struct iwl_priv {
struct iwl3945_notif_statistics statistics_39;
struct iwl3945_station_entry stations_39[IWL_STATION_COUNT];
u32 sta_supp_rates;
}; /*iwl_priv */
......
......@@ -240,13 +240,11 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
if (ret < 0)
IWL_ERR(priv, "Time out access OTP\n");
else {
if (!ret) {
iwl_set_bits_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
udelay(5);
iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
}
iwl_set_bits_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
udelay(5);
iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
}
return ret;
}
......
......@@ -176,10 +176,6 @@ static int iwl_led_associate(struct iwl_priv *priv, int led_id)
static int iwl_led_disassociate(struct iwl_priv *priv, int led_id)
{
priv->allow_blinking = 0;
if (iwl_is_rfkill(priv))
iwl4965_led_off_reg(priv, led_id);
else
iwl4965_led_on_reg(priv, led_id);
return 0;
}
......
......@@ -36,42 +36,37 @@
#include "iwl-core.h"
/* software rf-kill from user */
static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
static int iwl_rfkill_soft_rf_kill(void *data, bool blocked)
{
struct iwl_priv *priv = data;
int err = 0;
if (!priv->rfkill)
return 0;
return -EINVAL;
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return 0;
IWL_DEBUG_RF_KILL(priv, "we received soft RFKILL set to state %d\n", state);
IWL_DEBUG_RF_KILL(priv, "received soft RFKILL: block=%d\n", blocked);
mutex_lock(&priv->mutex);
switch (state) {
case RFKILL_STATE_UNBLOCKED:
if (iwl_is_rfkill_hw(priv)) {
err = -EBUSY;
goto out_unlock;
}
if (iwl_is_rfkill_hw(priv))
goto out_unlock;
if (!blocked)
iwl_radio_kill_sw_enable_radio(priv);
break;
case RFKILL_STATE_SOFT_BLOCKED:
else
iwl_radio_kill_sw_disable_radio(priv);
break;
default:
IWL_WARN(priv, "we received unexpected RFKILL state %d\n",
state);
break;
}
out_unlock:
mutex_unlock(&priv->mutex);
return err;
return 0;
}
static const struct rfkill_ops iwl_rfkill_ops = {
.set_block = iwl_rfkill_soft_rf_kill,
};
int iwl_rfkill_init(struct iwl_priv *priv)
{
struct device *device = wiphy_dev(priv->hw->wiphy);
......@@ -80,21 +75,16 @@ int iwl_rfkill_init(struct iwl_priv *priv)
BUG_ON(device == NULL);
IWL_DEBUG_RF_KILL(priv, "Initializing RFKILL.\n");
priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
priv->rfkill = rfkill_alloc(priv->cfg->name,
device,
RFKILL_TYPE_WLAN,
&iwl_rfkill_ops, priv);
if (!priv->rfkill) {
IWL_ERR(priv, "Unable to allocate RFKILL device.\n");
ret = -ENOMEM;
goto error;
}
priv->rfkill->name = priv->cfg->name;
priv->rfkill->data = priv;
priv->rfkill->state = RFKILL_STATE_UNBLOCKED;
priv->rfkill->toggle_radio = iwl_rfkill_soft_rf_kill;
priv->rfkill->dev.class->suspend = NULL;
priv->rfkill->dev.class->resume = NULL;
ret = rfkill_register(priv->rfkill);
if (ret) {
IWL_ERR(priv, "Unable to register RFKILL: %d\n", ret);
......@@ -102,11 +92,10 @@ int iwl_rfkill_init(struct iwl_priv *priv)
}
IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n");
return ret;
return 0;
free_rfkill:
if (priv->rfkill != NULL)
rfkill_free(priv->rfkill);
rfkill_destroy(priv->rfkill);
priv->rfkill = NULL;
error:
......@@ -118,8 +107,10 @@ EXPORT_SYMBOL(iwl_rfkill_init);
void iwl_rfkill_unregister(struct iwl_priv *priv)
{
if (priv->rfkill)
if (priv->rfkill) {
rfkill_unregister(priv->rfkill);
rfkill_destroy(priv->rfkill);
}
priv->rfkill = NULL;
}
......@@ -131,14 +122,10 @@ void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
if (!priv->rfkill)
return;
if (iwl_is_rfkill_hw(priv)) {
rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED);
return;
}
if (!iwl_is_rfkill_sw(priv))
rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
if (rfkill_set_hw_state(priv->rfkill,
!!iwl_is_rfkill_hw(priv)))
iwl_radio_kill_sw_disable_radio(priv);
else
rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
iwl_radio_kill_sw_enable_radio(priv);
}
EXPORT_SYMBOL(iwl_rfkill_set_hw_state);
......@@ -75,7 +75,7 @@ int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
return IWL_AP_ID;
} else {
u8 *da = ieee80211_get_DA(hdr);
return priv->cfg->ops->smgmt->find_station(priv, da);
return iwl_find_station(priv, da);
}
}
EXPORT_SYMBOL(iwl_get_ra_sta_id);
......@@ -86,8 +86,7 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
spin_lock_irqsave(&priv->sta_lock, flags);
if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
!(priv->stations_39[sta_id].used & IWL_STA_DRIVER_ACTIVE))
if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
IWL_ERR(priv, "ACTIVATE a non DRIVER active station %d\n",
sta_id);
......@@ -228,15 +227,16 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
}
/**
* iwl_add_station_flags - Add station to tables in driver and device
* iwl_add_station - Add station to tables in driver and device
*/
u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
u8 flags, struct ieee80211_sta_ht_cap *ht_info)
u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags,
struct ieee80211_sta_ht_cap *ht_info)
{
int i;
int sta_id = IWL_INVALID_STATION;
struct iwl_station_entry *station;
unsigned long flags_spin;
int i;
int sta_id = IWL_INVALID_STATION;
u16 rate;
spin_lock_irqsave(&priv->sta_lock, flags_spin);
if (is_ap)
......@@ -288,6 +288,12 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
priv->iw_mode != NL80211_IFTYPE_ADHOC)
iwl_set_ht_add_station(priv, sta_id, ht_info);
/* 3945 only */
rate = (priv->band == IEEE80211_BAND_5GHZ) ?
IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP;
/* Turn on both antennas for the station... */
station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK);
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
/* Add station to device's station table */
......@@ -295,12 +301,12 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
return sta_id;
}
EXPORT_SYMBOL(iwl_add_station_flags);
EXPORT_SYMBOL(iwl_add_station);
static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
{
unsigned long flags;
u8 sta_id = priv->cfg->ops->smgmt->find_station(priv, addr);
u8 sta_id = iwl_find_station(priv, addr);
BUG_ON(sta_id == IWL_INVALID_STATION);
......@@ -408,7 +414,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
/**
* iwl_remove_station - Remove driver's knowledge of station.
*/
int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap)
{
int sta_id = IWL_INVALID_STATION;
int i, ret = -EINVAL;
......@@ -767,7 +773,7 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
unsigned long flags;
int i;
sta_id = priv->cfg->ops->smgmt->find_station(priv, addr);
sta_id = iwl_find_station(priv, addr);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
addr);
......@@ -946,7 +952,7 @@ EXPORT_SYMBOL(iwl_send_lq_cmd);
* calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
* which requires station table entry to exist).
*/
static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap)
static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap)
{
int i, r;
struct iwl_link_quality_cmd link_cmd = {
......@@ -979,8 +985,9 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap)
link_cmd.general_params.single_stream_ant_msk =
first_antenna(priv->hw_params.valid_tx_ant);
link_cmd.general_params.dual_stream_ant_msk = 3;
link_cmd.agg_params.agg_dis_start_th = 3;
link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000);
link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
link_cmd.agg_params.agg_time_limit =
cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
/* Update the rate scaling for control frame Tx to AP */
link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id;
......@@ -995,7 +1002,7 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap)
* there is only one AP station with id= IWL_AP_ID
* NOTE: mutex must be held before calling this function
*/
int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap)
{
struct ieee80211_sta *sta;
struct ieee80211_sta_ht_cap ht_config;
......@@ -1020,8 +1027,7 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
rcu_read_unlock();
}
sta_id = priv->cfg->ops->smgmt->add_station(priv, addr, is_ap,
0, cur_ht_config);
sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config);
/* Set up default rate scaling table in device's station table */
iwl_sta_init_lq(priv, addr, is_ap);
......@@ -1054,7 +1060,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
/* If we are an AP, then find the station, or use BCAST */
case NL80211_IFTYPE_AP:
sta_id = priv->cfg->ops->smgmt->find_station(priv, hdr->addr1);
sta_id = iwl_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
return priv->hw_params.bcast_sta_id;
......@@ -1062,13 +1068,13 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
/* If this frame is going out to an IBSS network, find the station,
* or create a new station table entry */
case NL80211_IFTYPE_ADHOC:
sta_id = priv->cfg->ops->smgmt->find_station(priv, hdr->addr1);
sta_id = iwl_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
/* Create new station table entry */
sta_id = priv->cfg->ops->smgmt->add_station(priv, hdr->addr1,
0, CMD_ASYNC, NULL);
sta_id = iwl_add_station(priv, hdr->addr1, false,
CMD_ASYNC, NULL);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
......@@ -1111,7 +1117,7 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv,
unsigned long flags;
int sta_id;
sta_id = priv->cfg->ops->smgmt->find_station(priv, addr);
sta_id = iwl_find_station(priv, addr);
if (sta_id == IWL_INVALID_STATION)
return -ENXIO;
......@@ -1133,7 +1139,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid)
unsigned long flags;
int sta_id;
sta_id = priv->cfg->ops->smgmt->find_station(priv, addr);
sta_id = iwl_find_station(priv, addr);
if (sta_id == IWL_INVALID_STATION) {
IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
return -ENXIO;
......@@ -1168,7 +1174,7 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
{
/* FIXME: need locking over ps_status ??? */
u8 sta_id = priv->cfg->ops->smgmt->find_station(priv, addr);
u8 sta_id = iwl_find_station(priv, addr);
if (sta_id != IWL_INVALID_STATION) {
u8 sta_awake = priv->stations[sta_id].
......
......@@ -51,16 +51,15 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
struct ieee80211_key_conf *keyconf,
const u8 *addr, u32 iv32, u16 *phase1key);
int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap);
int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap);
void iwl_clear_stations_table(struct iwl_priv *priv);
int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
int iwl_send_add_sta(struct iwl_priv *priv,
struct iwl_addsta_cmd *sta, u8 flags);
u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr,
int is_ap, u8 flags,
u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags,
struct ieee80211_sta_ht_cap *ht_info);
void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
int iwl_sta_rx_agg_start(struct iwl_priv *priv,
......
......@@ -95,144 +95,6 @@ struct iwl_mod_params iwl3945_mod_params = {
/* the rest are 0 by default */
};
/*************** STATION TABLE MANAGEMENT ****
* mac80211 should be examined to determine if sta_info is duplicating
* the functionality provided here
*/
/**************************************************************/
#if 0 /* temporary disable till we add real remove station */
/**
* iwl3945_remove_station - Remove driver's knowledge of station.
*
* NOTE: This does not remove station from device's station table.
*/
static u8 iwl3945_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
{
int index = IWL_INVALID_STATION;
int i;
unsigned long flags;
spin_lock_irqsave(&priv->sta_lock, flags);
if (is_ap)
index = IWL_AP_ID;
else if (is_broadcast_ether_addr(addr))
index = priv->hw_params.bcast_sta_id;
else
for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
if (priv->stations_39[i].used &&
!compare_ether_addr(priv->stations_39[i].sta.sta.addr,
addr)) {
index = i;
break;
}
if (unlikely(index == IWL_INVALID_STATION))
goto out;
if (priv->stations_39[index].used) {
priv->stations_39[index].used = 0;
priv->num_stations--;
}
BUG_ON(priv->num_stations < 0);
out:
spin_unlock_irqrestore(&priv->sta_lock, flags);
return 0;
}
#endif
/**
* iwl3945_clear_stations_table - Clear the driver's station table
*
* NOTE: This does not clear or otherwise alter the device's station table.
*/
void iwl3945_clear_stations_table(struct iwl_priv *priv)
{
unsigned long flags;
spin_lock_irqsave(&priv->sta_lock, flags);
priv->num_stations = 0;
memset(priv->stations_39, 0, sizeof(priv->stations_39));
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
/**
* iwl3945_add_station - Add station to station tables in driver and device
*/
u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info)
{
int i;
int index = IWL_INVALID_STATION;
struct iwl3945_station_entry *station;
unsigned long flags_spin;
u8 rate;
spin_lock_irqsave(&priv->sta_lock, flags_spin);
if (is_ap)
index = IWL_AP_ID;
else if (is_broadcast_ether_addr(addr))
index = priv->hw_params.bcast_sta_id;
else
for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
if (!compare_ether_addr(priv->stations_39[i].sta.sta.addr,
addr)) {
index = i;
break;
}
if (!priv->stations_39[i].used &&
index == IWL_INVALID_STATION)
index = i;
}
/* These two conditions has the same outcome but keep them separate
since they have different meaning */
if (unlikely(index == IWL_INVALID_STATION)) {
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
return index;
}
if (priv->stations_39[index].used &&
!compare_ether_addr(priv->stations_39[index].sta.sta.addr, addr)) {
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
return index;
}
IWL_DEBUG_ASSOC(priv, "Add STA ID %d: %pM\n", index, addr);
station = &priv->stations_39[index];
station->used = 1;
priv->num_stations++;
/* Set up the REPLY_ADD_STA command to send to device */
memset(&station->sta, 0, sizeof(struct iwl3945_addsta_cmd));
memcpy(station->sta.sta.addr, addr, ETH_ALEN);
station->sta.mode = 0;
station->sta.sta.sta_id = index;
station->sta.station_flags = 0;
if (priv->band == IEEE80211_BAND_5GHZ)
rate = IWL_RATE_6M_PLCP;
else
rate = IWL_RATE_1M_PLCP;
/* Turn on both antennas for the station... */
station->sta.rate_n_flags =
iwl3945_hw_set_rate_n_flags(rate, RATE_MCS_ANT_AB_MSK);
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
/* Add station to device's station table */
iwl_send_add_sta(priv,
(struct iwl_addsta_cmd *)&station->sta, flags);
return index;
}
/**
* iwl3945_get_antenna_flags - Get antenna flags for RXON command
* @priv: eeprom and antenna fields are used to determine antenna flags
......@@ -289,32 +151,31 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
key_flags &= ~STA_KEY_FLG_INVALID;
spin_lock_irqsave(&priv->sta_lock, flags);
priv->stations_39[sta_id].keyinfo.alg = keyconf->alg;
priv->stations_39[sta_id].keyinfo.keylen = keyconf->keylen;
memcpy(priv->stations_39[sta_id].keyinfo.key, keyconf->key,
priv->stations[sta_id].keyinfo.alg = keyconf->alg;
priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
keyconf->keylen);
memcpy(priv->stations_39[sta_id].sta.key.key, keyconf->key,
memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
keyconf->keylen);
if ((priv->stations_39[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
== STA_KEY_FLG_NO_ENC)
priv->stations_39[sta_id].sta.key.key_offset =
priv->stations[sta_id].sta.key.key_offset =
iwl_get_free_ucode_key_index(priv);
/* else, we are overriding an existing key => no need to allocated room
* in uCode. */
WARN(priv->stations_39[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
"no space for a new key");
priv->stations_39[sta_id].sta.key.key_flags = key_flags;
priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
priv->stations[sta_id].sta.key.key_flags = key_flags;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n");
ret = iwl_send_add_sta(priv,
(struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, CMD_ASYNC);
ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
spin_unlock_irqrestore(&priv->sta_lock, flags);
......@@ -340,17 +201,16 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
unsigned long flags;
spin_lock_irqsave(&priv->sta_lock, flags);
memset(&priv->stations_39[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
memset(&priv->stations_39[sta_id].sta.key, 0,
memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
memset(&priv->stations[sta_id].sta.key, 0,
sizeof(struct iwl4965_keyinfo));
priv->stations_39[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
spin_unlock_irqrestore(&priv->sta_lock, flags);
IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
iwl_send_add_sta(priv,
(struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, 0);
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0);
return 0;
}
......@@ -578,7 +438,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
int sta_id)
{
struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
struct iwl_hw_key *keyinfo = &priv->stations_39[sta_id].keyinfo;
struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
switch (keyinfo->alg) {
case ALG_CCMP:
......@@ -753,7 +613,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
if (ieee80211_is_data_qos(fc)) {
qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
seq_number = priv->stations_39[sta_id].tid[tid].seq_number &
seq_number = priv->stations[sta_id].tid[tid].seq_number &
IEEE80211_SCTL_SEQ;
hdr->seq_ctrl = cpu_to_le16(seq_number) |
(hdr->seq_ctrl &
......@@ -813,7 +673,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
if (!ieee80211_has_morefrags(hdr->frame_control)) {
txq->need_update = 1;
if (qc)
priv->stations_39[sta_id].tid[tid].seq_number = seq_number;
priv->stations[sta_id].tid[tid].seq_number = seq_number;
} else {
wait_write_ptr = 1;
txq->need_update = 0;
......@@ -1316,7 +1176,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
/* If we've added more space for the firmware to place data, tell it.
* Increment device's write pointer in multiples of 8. */
if ((write != (rxq->write & ~0x7))
if ((rxq->write_actual != (rxq->write & ~0x7))
|| (abs(rxq->write - rxq->read) > 7)) {
spin_lock_irqsave(&rxq->lock, flags);
rxq->need_update = 1;
......@@ -1337,7 +1197,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
* Also restock the Rx queue via iwl3945_rx_queue_restock.
* This is called as a scheduled work item (except for during initialization)
*/
static void iwl3945_rx_allocate(struct iwl_priv *priv)
static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
{
struct iwl_rx_queue *rxq = &priv->rxq;
struct list_head *element;
......@@ -1360,7 +1220,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv)
/* Alloc a new receive buffer */
rxb->skb =
alloc_skb(priv->hw_params.rx_buf_size,
GFP_KERNEL);
priority);
if (!rxb->skb) {
if (net_ratelimit())
IWL_CRIT(priv, ": Can not allocate SKB buffers\n");
......@@ -1419,6 +1279,7 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
* not restocked the Rx queue with fresh buffers */
rxq->read = rxq->write = 0;
rxq->free_count = 0;
rxq->write_actual = 0;
spin_unlock_irqrestore(&rxq->lock, flags);
}
......@@ -1427,13 +1288,21 @@ void iwl3945_rx_replenish(void *data)
struct iwl_priv *priv = data;
unsigned long flags;
iwl3945_rx_allocate(priv);
iwl3945_rx_allocate(priv, GFP_KERNEL);
spin_lock_irqsave(&priv->lock, flags);
iwl3945_rx_queue_restock(priv);
spin_unlock_irqrestore(&priv->lock, flags);
}
static void iwl3945_rx_replenish_now(struct iwl_priv *priv)
{
iwl3945_rx_allocate(priv, GFP_ATOMIC);
iwl3945_rx_queue_restock(priv);
}
/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
* If an SKB has been detached, the POOL needs to have its SKB set to NULL
* This free routine walks the list of POOL entries and if SKB is set to
......@@ -1556,13 +1425,19 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
unsigned long flags;
u8 fill_rx = 0;
u32 count = 8;
int total_empty = 0;
/* uCode's read index (stored in shared DRAM) indicates the last Rx
* buffer that the driver may process (last buffer filled by ucode). */
r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF;
i = rxq->read;
if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
/* calculate total frames need to be restock after handling RX */
total_empty = r - priv->rxq.write_actual;
if (total_empty < 0)
total_empty += RX_QUEUE_SIZE;
if (total_empty > (RX_QUEUE_SIZE / 2))
fill_rx = 1;
/* Rx interrupt, but nothing sent from uCode */
if (i == r)
......@@ -1639,7 +1514,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
count++;
if (count >= 8) {
priv->rxq.read = i;
iwl3945_rx_queue_restock(priv);
iwl3945_rx_replenish_now(priv);
count = 0;
}
}
......@@ -1647,7 +1522,10 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
/* Backtrack one entry */
priv->rxq.read = i;
iwl3945_rx_queue_restock(priv);
if (fill_rx)
iwl3945_rx_replenish_now(priv);
else
iwl3945_rx_queue_restock(priv);
}
/* call this function to flush any scheduled tasklet */
......@@ -2589,7 +2467,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
goto restart;
}
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
rfkill = iwl_read_prph(priv, APMG_RFKILL_REG);
IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill);
......@@ -2681,7 +2559,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
set_bit(STATUS_EXIT_PENDING, &priv->status);
iwl3945_led_unregister(priv);
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
/* Unblock any waiting calls */
wake_up_interruptible_all(&priv->wait_command_queue);
......@@ -2833,7 +2711,7 @@ static int __iwl3945_up(struct iwl_priv *priv)
for (i = 0; i < MAX_HW_RESTARTS; i++) {
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
/* load bootstrap state machine,
* load bootstrap program into processor's memory,
......@@ -3247,7 +3125,7 @@ void iwl3945_post_associate(struct iwl_priv *priv)
case NL80211_IFTYPE_ADHOC:
priv->assoc_id = 1;
priv->cfg->ops->smgmt->add_station(priv, priv->bssid, 0, 0, NULL);
iwl_add_station(priv, priv->bssid, 0, CMD_SYNC, NULL);
iwl3945_sync_sta(priv, IWL_STA_ID,
(priv->band == IEEE80211_BAND_5GHZ) ?
IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
......@@ -3438,7 +3316,7 @@ void iwl3945_config_ap(struct iwl_priv *priv)
/* restore RXON assoc */
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
iwlcore_commit_rxon(priv);
priv->cfg->ops->smgmt->add_station(priv, iwl_bcast_addr, 0, 0, NULL);
iwl_add_station(priv, iwl_bcast_addr, 0, CMD_SYNC, NULL);
}
iwl3945_send_beacon_cmd(priv);
......@@ -3469,7 +3347,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
static_key = !iwl_is_associated(priv);
if (!static_key) {
sta_id = priv->cfg->ops->smgmt->find_station(priv, addr);
sta_id = iwl_find_station(priv, addr);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
addr);
......@@ -4044,7 +3922,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
mutex_init(&priv->mutex);
/* Clear the driver's (not device's) station table */
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
priv->data_retry_limit = -1;
priv->ieee_channels = NULL;
......@@ -4407,7 +4285,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
iwl3945_hw_txq_ctx_free(priv);
iwl3945_unset_hw_params(priv);
priv->cfg->ops->smgmt->clear_station_table(priv);
iwl_clear_stations_table(priv);
/*netif_stop_queue(dev); */
flush_workqueue(priv->workqueue);
......
config IWM
tristate "Intel Wireless Multicomm 3200 WiFi driver"
depends on MMC && WLAN_80211 && EXPERIMENTAL
depends on CFG80211
select WIRELESS_EXT
select CFG80211
select FW_LOADER
select RFKILL
config IWM_DEBUG
bool "Enable full debugging output in iwmc3200wifi"
......
obj-$(CONFIG_IWM) := iwmc3200wifi.o
iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o
iwmc3200wifi-objs += commands.o wext.o cfg80211.o eeprom.o rfkill.o
iwmc3200wifi-objs += commands.o wext.o cfg80211.o eeprom.o
iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o
......@@ -268,7 +268,7 @@ static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
iwm->conf.frag_threshold = wiphy->frag_threshold;
ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
CFG_FRAG_THRESHOLD,
iwm->conf.frag_threshold);
if (ret < 0)
......
......@@ -72,7 +72,7 @@ static int iwm_fw_op_offset(struct iwm_priv *iwm, const struct firmware *fw,
}
if (fw->size < IWM_HDR_LEN) {
IWM_ERR(iwm, "FW is too small (%d)\n", fw->size);
IWM_ERR(iwm, "FW is too small (%zu)\n", fw->size);
return -EINVAL;
}
......
......@@ -343,8 +343,4 @@ int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size,
struct iwm_wifi_cmd *cmd);
void iwm_rx_free(struct iwm_priv *iwm);
/* RF Kill API */
int iwm_rfkill_init(struct iwm_priv *iwm);
void iwm_rfkill_exit(struct iwm_priv *iwm);
#endif
......@@ -136,17 +136,8 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev,
wdev->netdev = ndev;
ret = iwm_rfkill_init(iwm);
if (ret) {
dev_err(dev, "Failed to init rfkill\n");
goto out_rfkill;
}
return iwm;
out_rfkill:
unregister_netdev(ndev);
out_ndev:
free_netdev(ndev);
......@@ -162,7 +153,6 @@ void iwm_if_free(struct iwm_priv *iwm)
if (!iwm_to_ndev(iwm))
return;
iwm_rfkill_exit(iwm);
unregister_netdev(iwm_to_ndev(iwm));
free_netdev(iwm_to_ndev(iwm));
iwm_wdev_free(iwm);
......
/*
* Intel Wireless Multicomm 3200 WiFi driver
*
* Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
* Samuel Ortiz <samuel.ortiz@intel.com>
* Zhu Yi <yi.zhu@intel.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*/
#include <linux/rfkill.h>
#include "iwm.h"
static int iwm_rfkill_soft_toggle(void *data, enum rfkill_state state)
{
struct iwm_priv *iwm = data;
switch (state) {
case RFKILL_STATE_UNBLOCKED:
if (test_bit(IWM_RADIO_RFKILL_HW, &iwm->radio))
return -EBUSY;
if (test_and_clear_bit(IWM_RADIO_RFKILL_SW, &iwm->radio) &&
(iwm_to_ndev(iwm)->flags & IFF_UP))
iwm_up(iwm);
break;
case RFKILL_STATE_SOFT_BLOCKED:
if (!test_and_set_bit(IWM_RADIO_RFKILL_SW, &iwm->radio))
iwm_down(iwm);
break;
default:
break;
}
return 0;
}
int iwm_rfkill_init(struct iwm_priv *iwm)
{
int ret;
iwm->rfkill = rfkill_allocate(iwm_to_dev(iwm), RFKILL_TYPE_WLAN);
if (!iwm->rfkill) {
IWM_ERR(iwm, "Unable to allocate rfkill device\n");
return -ENOMEM;
}
iwm->rfkill->name = KBUILD_MODNAME;
iwm->rfkill->data = iwm;
iwm->rfkill->state = RFKILL_STATE_UNBLOCKED;
iwm->rfkill->toggle_radio = iwm_rfkill_soft_toggle;
ret = rfkill_register(iwm->rfkill);
if (ret) {
IWM_ERR(iwm, "Failed to register rfkill device\n");
goto fail;
}
return 0;
fail:
rfkill_free(iwm->rfkill);
return ret;
}
void iwm_rfkill_exit(struct iwm_priv *iwm)
{
if (iwm->rfkill)
rfkill_unregister(iwm->rfkill);
rfkill_free(iwm->rfkill);
iwm->rfkill = NULL;
}
......@@ -395,7 +395,7 @@ static struct iwm_if_ops if_sdio_ops = {
.debugfs_init = if_sdio_debugfs_init,
.debugfs_exit = if_sdio_debugfs_exit,
.umac_name = "iwmc3200wifi-umac-sdio.bin",
.calib_lmac_name = "iwmc3200wifi-lmac-calib-sdio.bin",
.calib_lmac_name = "iwmc3200wifi-calib-sdio.bin",
.lmac_name = "iwmc3200wifi-lmac-sdio.bin",
};
......
......@@ -207,7 +207,7 @@ static int generate_domain_info_11d(struct parsed_region_chan_11d
lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband);
lbs_deb_hex(LBS_DEB_11D, "domaininfo", (char *)domaininfo,
COUNTRY_CODE_LEN + 1 +
sizeof(struct ieeetypes_subbandset) * nr_subband);
sizeof(struct ieee_subbandset) * nr_subband);
return 0;
}
......@@ -302,11 +302,9 @@ static u8 lbs_region_chan_supported_11d(u8 region, u8 chan)
* @param parsed_region_chan pointer to parsed_region_chan_11d
* @return 0
*/
static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
countryinfo,
static int parse_domain_info_11d(struct ieee_ie_country_info_full_set *countryinfo,
u8 band,
struct parsed_region_chan_11d *
parsed_region_chan)
struct parsed_region_chan_11d *parsed_region_chan)
{
u8 nr_subband, nrchan;
u8 lastchan, firstchan;
......@@ -331,7 +329,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
lbs_deb_hex(LBS_DEB_11D, "countryinfo", (u8 *) countryinfo, 30);
if ((*(countryinfo->countrycode)) == 0
|| (countryinfo->len <= COUNTRY_CODE_LEN)) {
|| (countryinfo->header.len <= COUNTRY_CODE_LEN)) {
/* No region Info or Wrong region info: treat as No 11D info */
goto done;
}
......@@ -349,8 +347,8 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
memcpy(parsed_region_chan->countrycode, countryinfo->countrycode,
COUNTRY_CODE_LEN);
nr_subband = (countryinfo->len - COUNTRY_CODE_LEN) /
sizeof(struct ieeetypes_subbandset);
nr_subband = (countryinfo->header.len - COUNTRY_CODE_LEN) /
sizeof(struct ieee_subbandset);
for (j = 0, lastchan = 0; j < nr_subband; j++) {
......@@ -502,7 +500,7 @@ int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
{
struct cmd_ds_802_11d_domain_info *pdomaininfo =
&cmd->params.domaininfo;
struct mrvlietypes_domainparamset *domain = &pdomaininfo->domain;
struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain;
u8 nr_subband = priv->domainreg.nr_subband;
lbs_deb_enter(LBS_DEB_11D);
......@@ -524,16 +522,16 @@ int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
sizeof(domain->countrycode));
domain->header.len =
cpu_to_le16(nr_subband * sizeof(struct ieeetypes_subbandset) +
cpu_to_le16(nr_subband * sizeof(struct ieee_subbandset) +
sizeof(domain->countrycode));
if (nr_subband) {
memcpy(domain->subband, priv->domainreg.subband,
nr_subband * sizeof(struct ieeetypes_subbandset));
nr_subband * sizeof(struct ieee_subbandset));
cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
le16_to_cpu(domain->header.len) +
sizeof(struct mrvlietypesheader) +
sizeof(struct mrvl_ie_header) +
S_DS_GEN);
} else {
cmd->size =
......@@ -556,7 +554,7 @@ int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
{
struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp;
struct mrvlietypes_domainparamset *domain = &domaininfo->domain;
struct mrvl_ie_domain_param_set *domain = &domaininfo->domain;
u16 action = le16_to_cpu(domaininfo->action);
s16 ret = 0;
u8 nr_subband = 0;
......@@ -567,7 +565,7 @@ int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
(int)le16_to_cpu(resp->size));
nr_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
sizeof(struct ieeetypes_subbandset);
sizeof(struct ieee_subbandset);
lbs_deb_11d("domain info resp: nr_subband %d\n", nr_subband);
......
......@@ -20,35 +20,36 @@
struct cmd_ds_command;
/** Data structure for Country IE*/
struct ieeetypes_subbandset {
struct ieee_subbandset {
u8 firstchan;
u8 nrchan;
u8 maxtxpwr;
} __attribute__ ((packed));
struct ieeetypes_countryinfoset {
u8 element_id;
u8 len;
struct ieee_ie_country_info_set {
struct ieee_ie_header header;
u8 countrycode[COUNTRY_CODE_LEN];
struct ieeetypes_subbandset subband[1];
struct ieee_subbandset subband[1];
};
struct ieeetypes_countryinfofullset {
u8 element_id;
u8 len;
struct ieee_ie_country_info_full_set {
struct ieee_ie_header header;
u8 countrycode[COUNTRY_CODE_LEN];
struct ieeetypes_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
} __attribute__ ((packed));
struct mrvlietypes_domainparamset {
struct mrvlietypesheader header;
struct mrvl_ie_domain_param_set {
struct mrvl_ie_header header;
u8 countrycode[COUNTRY_CODE_LEN];
struct ieeetypes_subbandset subband[1];
struct ieee_subbandset subband[1];
} __attribute__ ((packed));
struct cmd_ds_802_11d_domain_info {
__le16 action;
struct mrvlietypes_domainparamset domain;
struct mrvl_ie_domain_param_set domain;
} __attribute__ ((packed));
/** domain regulatory information */
......@@ -57,7 +58,7 @@ struct lbs_802_11d_domain_reg {
u8 countrycode[COUNTRY_CODE_LEN];
/** No. of subband*/
u8 nr_subband;
struct ieeetypes_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
};
struct chan_power_11d {
......
......@@ -8,22 +8,9 @@
void lbs_association_worker(struct work_struct *work);
struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
struct cmd_ds_command;
int lbs_cmd_80211_authenticate(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
int lbs_adhoc_stop(struct lbs_private *priv);
int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
u8 bssid[ETH_ALEN], u16 reason);
int lbs_cmd_80211_associate(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
struct cmd_ds_command *resp);
int lbs_ret_80211_associate(struct lbs_private *priv,
struct cmd_ds_command *resp);
#endif /* _LBS_ASSOC_H */
......@@ -1220,8 +1220,7 @@ static void lbs_submit_command(struct lbs_private *priv,
command = le16_to_cpu(cmd->command);
/* These commands take longer */
if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE ||
command == CMD_802_11_AUTHENTICATE)
if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE)
timeo = 5 * HZ;
lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
......@@ -1415,15 +1414,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action);
break;
case CMD_802_11_ASSOCIATE:
case CMD_802_11_REASSOCIATE:
ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf);
break;
case CMD_802_11_AUTHENTICATE:
ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
break;
case CMD_MAC_REG_ACCESS:
case CMD_BBP_REG_ACCESS:
case CMD_RF_REG_ACCESS:
......@@ -1470,8 +1460,8 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
break;
case CMD_802_11_LED_GPIO_CTRL:
{
struct mrvlietypes_ledgpio *gpio =
(struct mrvlietypes_ledgpio*)
struct mrvl_ie_ledgpio *gpio =
(struct mrvl_ie_ledgpio*)
cmdptr->params.ledgpio.data;
memmove(&cmdptr->params.ledgpio,
......
......@@ -5,7 +5,7 @@
#include <linux/delay.h>
#include <linux/if_arp.h>
#include <linux/netdevice.h>
#include <asm/unaligned.h>
#include <net/iw_handler.h>
#include "host.h"
......@@ -154,11 +154,11 @@ static int lbs_ret_802_11_rssi(struct lbs_private *priv,
lbs_deb_enter(LBS_DEB_CMD);
/* store the non average value */
priv->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
priv->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor);
priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR);
priv->NF[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->noisefloor);
priv->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
priv->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor);
priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR);
priv->NF[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgnoisefloor);
priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
......@@ -210,12 +210,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
ret = lbs_ret_reg_access(priv, respcmd, resp);
break;
case CMD_RET_802_11_ASSOCIATE:
case CMD_RET(CMD_802_11_ASSOCIATE):
case CMD_RET(CMD_802_11_REASSOCIATE):
ret = lbs_ret_80211_associate(priv, resp);
break;
case CMD_RET(CMD_802_11_SET_AFC):
case CMD_RET(CMD_802_11_GET_AFC):
spin_lock_irqsave(&priv->driver_lock, flags);
......@@ -225,7 +219,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
break;
case CMD_RET(CMD_802_11_AUTHENTICATE):
case CMD_RET(CMD_802_11_BEACON_STOP):
break;
......
......@@ -183,12 +183,12 @@ static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
*/
static void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size)
{
struct mrvlietypesheader *tlv_h;
struct mrvl_ie_header *tlv_h;
uint16_t length;
ssize_t pos = 0;
while (pos < size) {
tlv_h = (struct mrvlietypesheader *) tlv;
tlv_h = (struct mrvl_ie_header *) tlv;
if (!tlv_h->len)
return NULL;
if (tlv_h->type == cpu_to_le16(tlv_type))
......@@ -206,7 +206,7 @@ static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
size_t count, loff_t *ppos)
{
struct cmd_ds_802_11_subscribe_event *subscribed;
struct mrvlietypes_thresholds *got;
struct mrvl_ie_thresholds *got;
struct lbs_private *priv = file->private_data;
ssize_t ret = 0;
size_t pos = 0;
......@@ -259,7 +259,7 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
loff_t *ppos)
{
struct cmd_ds_802_11_subscribe_event *events;
struct mrvlietypes_thresholds *tlv;
struct mrvl_ie_thresholds *tlv;
struct lbs_private *priv = file->private_data;
ssize_t buf_size;
int value, freq, new_mask;
......
......@@ -321,8 +321,6 @@ struct lbs_private {
u32 monitormode;
u8 fw_ready;
u8 fn_init_required;
u8 fn_shutdown_required;
};
extern struct cmd_confirm_sleep confirm_sleep;
......@@ -340,7 +338,7 @@ struct bss_descriptor {
u32 rssi;
u32 channel;
u16 beaconperiod;
u32 atimwindow;
__le16 atimwindow;
/* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
u8 mode;
......@@ -350,10 +348,10 @@ struct bss_descriptor {
unsigned long last_scanned;
union ieeetypes_phyparamset phyparamset;
union IEEEtypes_ssparamset ssparamset;
union ieee_phy_param_set phy;
union ieee_ss_param_set ss;
struct ieeetypes_countryinfofullset countryinfo;
struct ieee_ie_country_info_full_set countryinfo;
u8 wpa_ie[MAX_WPA_IE_LEN];
size_t wpa_ie_len;
......
......@@ -250,7 +250,9 @@ struct cmd_ds_gspi_bus_config {
} __attribute__ ((packed));
struct cmd_ds_802_11_authenticate {
u8 macaddr[ETH_ALEN];
struct cmd_header hdr;
u8 bssid[ETH_ALEN];
u8 authtype;
u8 reserved[10];
} __attribute__ ((packed));
......@@ -263,22 +265,23 @@ struct cmd_ds_802_11_deauthenticate {
} __attribute__ ((packed));
struct cmd_ds_802_11_associate {
u8 peerstaaddr[6];
struct cmd_header hdr;
u8 bssid[6];
__le16 capability;
__le16 listeninterval;
__le16 bcnperiod;
u8 dtimperiod;
#if 0
mrvlietypes_ssidparamset_t ssidParamSet;
mrvlietypes_phyparamset_t phyparamset;
mrvlietypes_ssparamset_t ssparamset;
mrvlietypes_ratesparamset_t ratesParamSet;
#endif
u8 iebuf[512]; /* Enough for required and most optional IEs */
} __attribute__ ((packed));
struct cmd_ds_802_11_associate_rsp {
struct ieeetypes_assocrsp assocRsp;
struct cmd_ds_802_11_associate_response {
struct cmd_header hdr;
__le16 capability;
__le16 statuscode;
__le16 aid;
u8 iebuf[512];
} __attribute__ ((packed));
struct cmd_ds_802_11_set_wep {
......@@ -535,9 +538,11 @@ struct cmd_ds_802_11_ad_hoc_start {
u8 bsstype;
__le16 beaconperiod;
u8 dtimperiod; /* Reserved on v9 and later */
union IEEEtypes_ssparamset ssparamset;
union ieeetypes_phyparamset phyparamset;
__le16 probedelay;
struct ieee_ie_ibss_param_set ibss;
u8 reserved1[4];
struct ieee_ie_ds_param_set ds;
u8 reserved2[4];
__le16 probedelay; /* Reserved on v9 and later */
__le16 capability;
u8 rates[MAX_RATES];
u8 tlv_memory_size_pad[100];
......@@ -558,8 +563,10 @@ struct adhoc_bssdesc {
u8 dtimperiod;
__le64 timestamp;
__le64 localtime;
union ieeetypes_phyparamset phyparamset;
union IEEEtypes_ssparamset ssparamset;
struct ieee_ie_ds_param_set ds;
u8 reserved1[4];
struct ieee_ie_ibss_param_set ibss;
u8 reserved2[4];
__le16 capability;
u8 rates[MAX_RATES];
......@@ -765,8 +772,6 @@ struct cmd_ds_command {
/* command Body */
union {
struct cmd_ds_802_11_ps_mode psmode;
struct cmd_ds_802_11_associate associate;
struct cmd_ds_802_11_authenticate auth;
struct cmd_ds_802_11_get_stat gstat;
struct cmd_ds_802_3_get_stat gstat_8023;
struct cmd_ds_802_11_rf_antenna rant;
......
......@@ -39,8 +39,24 @@
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "cmd.h"
#include "if_sdio.h"
/* The if_sdio_remove() callback function is called when
* user removes this module from kernel space or ejects
* the card from the slot. The driver handles these 2 cases
* differently for SD8688 combo chip.
* If the user is removing the module, the FUNC_SHUTDOWN
* command for SD8688 is sent to the firmware.
* If the card is removed, there is no need to send this command.
*
* The variable 'user_rmmod' is used to distinguish these two
* scenarios. This flag is initialized as FALSE in case the card
* is removed, and will be set to TRUE for module removal when
* module_exit function is called.
*/
static u8 user_rmmod;
static char *lbs_helper_name = NULL;
module_param_named(helper_name, lbs_helper_name, charp, 0644);
......@@ -61,7 +77,6 @@ struct if_sdio_model {
int model;
const char *helper;
const char *firmware;
struct if_sdio_card *card;
};
static struct if_sdio_model if_sdio_models[] = {
......@@ -70,21 +85,18 @@ static struct if_sdio_model if_sdio_models[] = {
.model = IF_SDIO_MODEL_8385,
.helper = "sd8385_helper.bin",
.firmware = "sd8385.bin",
.card = NULL,
},
{
/* 8686 */
.model = IF_SDIO_MODEL_8686,
.helper = "sd8686_helper.bin",
.firmware = "sd8686.bin",
.card = NULL,
},
{
/* 8688 */
.model = IF_SDIO_MODEL_8688,
.helper = "sd8688_helper.bin",
.firmware = "sd8688.bin",
.card = NULL,
},
};
......@@ -927,8 +939,6 @@ static int if_sdio_probe(struct sdio_func *func,
goto free;
}
if_sdio_models[i].card = card;
card->helper = if_sdio_models[i].helper;
card->firmware = if_sdio_models[i].firmware;
......@@ -1014,8 +1024,16 @@ static int if_sdio_probe(struct sdio_func *func,
/*
* FUNC_INIT is required for SD8688 WLAN/BT multiple functions
*/
priv->fn_init_required =
(card->model == IF_SDIO_MODEL_8688) ? 1 : 0;
if (card->model == IF_SDIO_MODEL_8688) {
struct cmd_header cmd;
memset(&cmd, 0, sizeof(cmd));
lbs_deb_sdio("send function INIT command\n");
if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd),
lbs_cmd_copyback, (unsigned long) &cmd))
lbs_pr_alert("CMD_FUNC_INIT cmd failed\n");
}
ret = lbs_start_card(priv);
if (ret)
......@@ -1057,30 +1075,39 @@ static void if_sdio_remove(struct sdio_func *func)
{
struct if_sdio_card *card;
struct if_sdio_packet *packet;
int ret;
lbs_deb_enter(LBS_DEB_SDIO);
card = sdio_get_drvdata(func);
lbs_stop_card(card->priv);
if (user_rmmod && (card->model == IF_SDIO_MODEL_8688)) {
/*
* FUNC_SHUTDOWN is required for SD8688 WLAN/BT
* multiple functions
*/
struct cmd_header cmd;
memset(&cmd, 0, sizeof(cmd));
lbs_deb_sdio("send function SHUTDOWN command\n");
if (__lbs_cmd(card->priv, CMD_FUNC_SHUTDOWN,
&cmd, sizeof(cmd), lbs_cmd_copyback,
(unsigned long) &cmd))
lbs_pr_alert("CMD_FUNC_SHUTDOWN cmd failed\n");
}
card->priv->surpriseremoved = 1;
lbs_deb_sdio("call remove card\n");
lbs_stop_card(card->priv);
lbs_remove_card(card->priv);
flush_workqueue(card->workqueue);
destroy_workqueue(card->workqueue);
sdio_claim_host(func);
/* Disable interrupts */
sdio_writeb(func, 0x00, IF_SDIO_H_INT_MASK, &ret);
sdio_release_irq(func);
sdio_disable_func(func);
sdio_release_host(func);
while (card->packets) {
......@@ -1116,6 +1143,9 @@ static int __init if_sdio_init_module(void)
ret = sdio_register_driver(&if_sdio_driver);
/* Clear the flag in case user removes the card. */
user_rmmod = 0;
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
return ret;
......@@ -1123,22 +1153,10 @@ static int __init if_sdio_init_module(void)
static void __exit if_sdio_exit_module(void)
{
int i;
struct if_sdio_card *card;
lbs_deb_enter(LBS_DEB_SDIO);
for (i = 0; i < ARRAY_SIZE(if_sdio_models); i++) {
card = if_sdio_models[i].card;
/*
* FUNC_SHUTDOWN is required for SD8688 WLAN/BT
* multiple functions
*/
if (card && card->priv)
card->priv->fn_shutdown_required =
(card->model == IF_SDIO_MODEL_8688) ? 1 : 0;
}
/* Set the flag as user is removing this module. */
user_rmmod = 1;
sdio_unregister_driver(&if_sdio_driver);
......
......@@ -119,9 +119,6 @@ static struct chip_ident chip_id_to_device_name[] = {
* First we have to put a SPU register name on the bus. Then we can
* either read from or write to that register.
*
* For 16-bit transactions, byte order on the bus is big-endian.
* We don't have to worry about that here, though.
* The translation takes place in the SPI routines.
*/
static void spu_transaction_init(struct if_spi_card *card)
......@@ -147,7 +144,7 @@ static void spu_transaction_finish(struct if_spi_card *card)
static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
{
int err = 0;
u16 reg_out = reg | IF_SPI_WRITE_OPERATION_MASK;
u16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK);
/* You must give an even number of bytes to the SPU, even if it
* doesn't care about the last one. */
......@@ -169,16 +166,10 @@ static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val)
{
return spu_write(card, reg, (u8 *)&val, sizeof(u16));
}
u16 buff;
static inline int spu_write_u32(struct if_spi_card *card, u16 reg, u32 val)
{
/* The lower 16 bits are written first. */
u16 out[2];
out[0] = val & 0xffff;
out[1] = (val & 0xffff0000) >> 16;
return spu_write(card, reg, (u8 *)&out, sizeof(u32));
buff = cpu_to_le16(val);
return spu_write(card, reg, (u8 *)&buff, sizeof(u16));
}
static inline int spu_reg_is_port_reg(u16 reg)
......@@ -198,7 +189,7 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
unsigned int i, delay;
int err = 0;
u16 zero = 0;
u16 reg_out = reg | IF_SPI_READ_OPERATION_MASK;
u16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK);
/* You must take an even number of bytes from the SPU, even if you
* don't care about the last one. */
......@@ -236,18 +227,25 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
/* Read 16 bits from an SPI register */
static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val)
{
return spu_read(card, reg, (u8 *)val, sizeof(u16));
u16 buf;
int ret;
ret = spu_read(card, reg, (u8 *)&buf, sizeof(buf));
if (ret == 0)
*val = le16_to_cpup(&buf);
return ret;
}
/* Read 32 bits from an SPI register.
* The low 16 bits are read first. */
static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val)
{
u16 buf[2];
u32 buf;
int err;
err = spu_read(card, reg, (u8 *)buf, sizeof(u32));
err = spu_read(card, reg, (u8 *)&buf, sizeof(buf));
if (!err)
*val = buf[0] | (buf[1] << 16);
*val = le32_to_cpup(&buf);
return err;
}
......
......@@ -1002,17 +1002,9 @@ static int lbs_setup_firmware(struct lbs_private *priv)
{
int ret = -1;
s16 curlevel = 0, minlevel = 0, maxlevel = 0;
struct cmd_header cmd;
lbs_deb_enter(LBS_DEB_FW);
if (priv->fn_init_required) {
memset(&cmd, 0, sizeof(cmd));
if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd),
lbs_cmd_copyback, (unsigned long) &cmd))
lbs_pr_alert("CMD_FUNC_INIT command failed\n");
}
/* Read MAC address from firmware */
memset(priv->current_addr, 0xff, ETH_ALEN);
ret = lbs_update_hw_spec(priv);
......@@ -1200,9 +1192,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
priv->mesh_open = 0;
priv->infra_open = 0;
priv->fn_init_required = 0;
priv->fn_shutdown_required = 0;
/* Setup the OS Interface to our functions */
dev->netdev_ops = &lbs_netdev_ops;
dev->watchdog_timeo = 5 * HZ;
......@@ -1384,20 +1373,11 @@ void lbs_stop_card(struct lbs_private *priv)
struct net_device *dev;
struct cmd_ctrl_node *cmdnode;
unsigned long flags;
struct cmd_header cmd;
lbs_deb_enter(LBS_DEB_MAIN);
if (!priv)
goto out;
if (priv->fn_shutdown_required) {
memset(&cmd, 0, sizeof(cmd));
if (__lbs_cmd(priv, CMD_FUNC_SHUTDOWN, &cmd, sizeof(cmd),
lbs_cmd_copyback, (unsigned long) &cmd))
lbs_pr_alert("CMD_FUNC_SHUTDOWN command failed\n");
}
dev = priv->dev;
netif_stop_queue(dev);
......
......@@ -27,12 +27,12 @@
+ 40) /* 40 for WPAIE */
//! Memory needed to store a max sized channel List TLV for a firmware scan
#define CHAN_TLV_MAX_SIZE (sizeof(struct mrvlietypesheader) \
#define CHAN_TLV_MAX_SIZE (sizeof(struct mrvl_ie_header) \
+ (MRVDRV_MAX_CHANNELS_PER_SCAN \
* sizeof(struct chanscanparamset)))
//! Memory needed to store a max number/size SSID TLV for a firmware scan
#define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset))
#define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvl_ie_ssid_param_set))
//! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max
#define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan) \
......@@ -211,7 +211,7 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
*/
static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
{
struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv;
struct mrvl_ie_ssid_param_set *ssid_tlv = (void *)tlv;
ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len);
......@@ -249,7 +249,7 @@ static int lbs_scan_add_chanlist_tlv(uint8_t *tlv,
int chan_count)
{
size_t size = sizeof(struct chanscanparamset) *chan_count;
struct mrvlietypes_chanlistparamset *chan_tlv = (void *)tlv;
struct mrvl_ie_chanlist_param_set *chan_tlv = (void *)tlv;
chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
memcpy(chan_tlv->chanscanparam, chan_list, size);
......@@ -270,7 +270,7 @@ static int lbs_scan_add_chanlist_tlv(uint8_t *tlv,
static int lbs_scan_add_rates_tlv(uint8_t *tlv)
{
int i;
struct mrvlietypes_ratesparamset *rate_tlv = (void *)tlv;
struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv;
rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
tlv += sizeof(rate_tlv->header);
......@@ -513,12 +513,12 @@ void lbs_scan_worker(struct work_struct *work)
static int lbs_process_bss(struct bss_descriptor *bss,
uint8_t **pbeaconinfo, int *bytesleft)
{
struct ieeetypes_fhparamset *pFH;
struct ieeetypes_dsparamset *pDS;
struct ieeetypes_cfparamset *pCF;
struct ieeetypes_ibssparamset *pibss;
struct ieee_ie_fh_param_set *fh;
struct ieee_ie_ds_param_set *ds;
struct ieee_ie_cf_param_set *cf;
struct ieee_ie_ibss_param_set *ibss;
DECLARE_SSID_BUF(ssid);
struct ieeetypes_countryinfoset *pcountryinfo;
struct ieee_ie_country_info_set *pcountryinfo;
uint8_t *pos, *end, *p;
uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
uint16_t beaconsize = 0;
......@@ -616,50 +616,49 @@ static int lbs_process_bss(struct bss_descriptor *bss,
break;
case WLAN_EID_FH_PARAMS:
pFH = (struct ieeetypes_fhparamset *) pos;
memmove(&bss->phyparamset.fhparamset, pFH,
sizeof(struct ieeetypes_fhparamset));
fh = (struct ieee_ie_fh_param_set *) pos;
memcpy(&bss->phy.fh, fh, sizeof(*fh));
lbs_deb_scan("got FH IE\n");
break;
case WLAN_EID_DS_PARAMS:
pDS = (struct ieeetypes_dsparamset *) pos;
bss->channel = pDS->currentchan;
memcpy(&bss->phyparamset.dsparamset, pDS,
sizeof(struct ieeetypes_dsparamset));
ds = (struct ieee_ie_ds_param_set *) pos;
bss->channel = ds->channel;
memcpy(&bss->phy.ds, ds, sizeof(*ds));
lbs_deb_scan("got DS IE, channel %d\n", bss->channel);
break;
case WLAN_EID_CF_PARAMS:
pCF = (struct ieeetypes_cfparamset *) pos;
memcpy(&bss->ssparamset.cfparamset, pCF,
sizeof(struct ieeetypes_cfparamset));
cf = (struct ieee_ie_cf_param_set *) pos;
memcpy(&bss->ss.cf, cf, sizeof(*cf));
lbs_deb_scan("got CF IE\n");
break;
case WLAN_EID_IBSS_PARAMS:
pibss = (struct ieeetypes_ibssparamset *) pos;
bss->atimwindow = le16_to_cpu(pibss->atimwindow);
memmove(&bss->ssparamset.ibssparamset, pibss,
sizeof(struct ieeetypes_ibssparamset));
ibss = (struct ieee_ie_ibss_param_set *) pos;
bss->atimwindow = ibss->atimwindow;
memcpy(&bss->ss.ibss, ibss, sizeof(*ibss));
lbs_deb_scan("got IBSS IE\n");
break;
case WLAN_EID_COUNTRY:
pcountryinfo = (struct ieeetypes_countryinfoset *) pos;
pcountryinfo = (struct ieee_ie_country_info_set *) pos;
lbs_deb_scan("got COUNTRY IE\n");
if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
|| pcountryinfo->len > 254) {
lbs_deb_scan("process_bss: 11D- Err CountryInfo len %d, min %zd, max 254\n",
pcountryinfo->len, sizeof(pcountryinfo->countrycode));
if (pcountryinfo->header.len < sizeof(pcountryinfo->countrycode)
|| pcountryinfo->header.len > 254) {
lbs_deb_scan("%s: 11D- Err CountryInfo len %d, min %zd, max 254\n",
__func__,
pcountryinfo->header.len,
sizeof(pcountryinfo->countrycode));
ret = -1;
goto done;
}
memcpy(&bss->countryinfo, pcountryinfo, pcountryinfo->len + 2);
memcpy(&bss->countryinfo, pcountryinfo,
pcountryinfo->header.len + 2);
lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo",
(uint8_t *) pcountryinfo,
(int) (pcountryinfo->len + 2));
(int) (pcountryinfo->header.len + 2));
break;
case WLAN_EID_EXT_SUPP_RATES:
......@@ -1130,7 +1129,7 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
goto done;
}
bytesleft = le16_to_cpu(scanresp->bssdescriptsize);
bytesleft = get_unaligned_le16(&scanresp->bssdescriptsize);
lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
scanrespsize = le16_to_cpu(resp->size);
......
......@@ -280,7 +280,6 @@ struct mac80211_hwsim_data {
struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)];
struct ieee80211_channel *channel;
int radio_enabled;
unsigned long beacon_int; /* in jiffies unit */
unsigned int rx_filter;
int started;
......@@ -418,8 +417,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
if (data == data2)
continue;
if (!data2->started || !data2->radio_enabled ||
!hwsim_ps_rx_ok(data2, skb) ||
if (!data2->started || !hwsim_ps_rx_ok(data2, skb) ||
data->channel->center_freq != data2->channel->center_freq ||
!(data->group & data2->group))
continue;
......@@ -441,7 +439,6 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct mac80211_hwsim_data *data = hw->priv;
bool ack;
struct ieee80211_tx_info *txi;
......@@ -453,13 +450,6 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
return NETDEV_TX_OK;
}
if (!data->radio_enabled) {
printk(KERN_DEBUG "%s: dropped TX frame since radio "
"disabled\n", wiphy_name(hw->wiphy));
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
ack = mac80211_hwsim_tx_frame(hw, skb);
txi = IEEE80211_SKB_CB(skb);
......@@ -546,7 +536,7 @@ static void mac80211_hwsim_beacon(unsigned long arg)
struct ieee80211_hw *hw = (struct ieee80211_hw *) arg;
struct mac80211_hwsim_data *data = hw->priv;
if (!data->started || !data->radio_enabled)
if (!data->started)
return;
ieee80211_iterate_active_interfaces_atomic(
......@@ -562,15 +552,14 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
struct mac80211_hwsim_data *data = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d idle=%d ps=%d)\n",
printk(KERN_DEBUG "%s:%s (freq=%d idle=%d ps=%d)\n",
wiphy_name(hw->wiphy), __func__,
conf->channel->center_freq, conf->radio_enabled,
conf->channel->center_freq,
!!(conf->flags & IEEE80211_CONF_IDLE),
!!(conf->flags & IEEE80211_CONF_PS));
data->channel = conf->channel;
data->radio_enabled = conf->radio_enabled;
if (!data->started || !data->radio_enabled || !data->beacon_int)
if (!data->started || !data->beacon_int)
del_timer(&data->beacon_timer);
else
mod_timer(&data->beacon_timer, jiffies + data->beacon_int);
......@@ -787,8 +776,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
pspoll->aid = cpu_to_le16(0xc000 | vp->aid);
memcpy(pspoll->bssid, vp->bssid, ETH_ALEN);
memcpy(pspoll->ta, mac, ETH_ALEN);
if (data->radio_enabled &&
!mac80211_hwsim_tx_frame(data->hw, skb))
if (!mac80211_hwsim_tx_frame(data->hw, skb))
printk(KERN_DEBUG "%s: PS-Poll frame not ack'ed\n", __func__);
dev_kfree_skb(skb);
}
......@@ -819,8 +807,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
memcpy(hdr->addr1, vp->bssid, ETH_ALEN);
memcpy(hdr->addr2, mac, ETH_ALEN);
memcpy(hdr->addr3, vp->bssid, ETH_ALEN);
if (data->radio_enabled &&
!mac80211_hwsim_tx_frame(data->hw, skb))
if (!mac80211_hwsim_tx_frame(data->hw, skb))
printk(KERN_DEBUG "%s: nullfunc frame not ack'ed\n", __func__);
dev_kfree_skb(skb);
}
......
......@@ -84,8 +84,8 @@ MODULE_DEVICE_TABLE(usb, p54u_table);
static const struct {
u32 intf;
enum p54u_hw_type type;
char fw[FIRMWARE_NAME_MAX];
char fw_legacy[FIRMWARE_NAME_MAX];
const char *fw;
const char *fw_legacy;
char hw[20];
} p54u_fwlist[__NUM_P54U_HWTYPES] = {
{
......
......@@ -520,7 +520,7 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
if (state == STATE_SLEEP) {
rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
(libconf->conf->beacon_int - 20) * 16);
(rt2x00dev->beacon_int - 20) * 16);
rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
libconf->conf->listen_interval - 1);
......
......@@ -569,7 +569,7 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
if (state == STATE_SLEEP) {
rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
(libconf->conf->beacon_int - 20) * 16);
(rt2x00dev->beacon_int - 20) * 16);
rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
libconf->conf->listen_interval - 1);
......
......@@ -647,7 +647,7 @@ static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev,
if (state == STATE_SLEEP) {
rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON,
libconf->conf->beacon_int - 20);
rt2x00dev->beacon_int - 20);
rt2x00_set_field16(&reg, MAC_CSR18_BEACONS_BEFORE_WAKEUP,
libconf->conf->listen_interval - 1);
......
......@@ -2927,12 +2927,17 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Edimax */
{ USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Encore */
{ USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) },
/* EnGenius */
{ USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) },
......@@ -2951,6 +2956,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) },
/* I-O DATA */
{ USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) },
/* LevelOne */
{ USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) },
......@@ -2970,6 +2977,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* Pegatron */
{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Philips */
{ USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Planex */
......@@ -2981,6 +2989,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* Quanta */
{ USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Ralink */
{ USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
......@@ -3005,6 +3014,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
/* SMC */
{ USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) },
......@@ -3029,6 +3039,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* Zinwell */
{ USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Zyxel */
{ USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) },
......
......@@ -801,6 +801,11 @@ struct rt2x00_dev {
*/
u8 calibration[2];
/*
* Beacon interval.
*/
u16 beacon_int;
/*
* Low level statistics which will have
* to be kept up to date while device is running.
......
......@@ -108,6 +108,9 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
erp.basic_rates = bss_conf->basic_rates;
erp.beacon_int = bss_conf->beacon_int;
/* Update global beacon interval time, this is needed for PS support */
rt2x00dev->beacon_int = bss_conf->beacon_int;
rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp);
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册