diff options
author | David S. Miller <davem@davemloft.net> | 2009-06-07 04:24:21 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-06-07 04:24:21 -0700 |
commit | b1bc81a0ef86b86fa410dd303d84c8c7bd09a64d (patch) | |
tree | a0d2e6dd179e5d057776edd0ed865bc744dfa54d /drivers/net | |
parent | a93958ac980f0ce594ad90657ecbc595ff157a40 (diff) | |
parent | 0c0c9e7076b69f93678e4ec711e2bf237398e623 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net')
85 files changed, 1310 insertions, 1684 deletions
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 837135f0390..5ddd8c4f901 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -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]); } } diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 867324163ca..daf4c805be5 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -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: diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 17bd3eaf3e0..c7cba66b63c 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -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); diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 3293e0fb24f..3c8004fb730 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h @@ -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; diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c index 341cead7f60..63fda6cd210 100644 --- a/drivers/net/wireless/ath/ar9170/led.c +++ b/drivers/net/wireless/ath/ar9170/led.c @@ -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) diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c index 43aeb69685d..d9f1f46de18 100644 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ b/drivers/net/wireless/ath/ar9170/mac.c @@ -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); diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 99df9ddae9c..b104d7efd67 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -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); } diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c index 6ce20754b8e..df86f70cd81 100644 --- a/drivers/net/wireless/ath/ar9170/phy.c +++ b/drivers/net/wireless/ath/ar9170/phy.c @@ -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); diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index d7c13c0177c..f752698669d 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -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 @@ resubmit: 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 @@ err_out: 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; diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h index ac42586495d..69f4bceb0af 100644 --- a/drivers/net/wireless/ath/ar9170/usb.h +++ b/drivers/net/wireless/ath/ar9170/usb.h @@ -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; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index fb5193764af..85a00db4867 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2070,6 +2070,13 @@ err_unmap: 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; diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 796a3adffea..515880aa211 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -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) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index a21b21339fb..3639a2e6987 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -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); diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 97df20cbf52..6d20725d645 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -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); } diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index db845cf960c..edda15bf2c1 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -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; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 61da08a1648..f7baa406918 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -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); diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 168411d322a..ccdf20a2e9b 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -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; } diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 7a89f9fac7d..eef370bd121 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -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); diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 21572e40b79..07a99e3faf9 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -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, diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c index 76f4c7bad8b..9a498d3fc65 100644 --- a/drivers/net/wireless/b43/leds.c +++ b/drivers/net/wireless/b43/leds.c @@ -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; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index cb4a8712946..1d3e40095ad 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -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"); } } diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c index c836c077d51..816e028a262 100644 --- a/drivers/net/wireless/b43/phy_a.c +++ b/drivers/net/wireless/b43/phy_a.c @@ -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); diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index e176b6e0d9c..6d241622210 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -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 @@ err_phy_exit: 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 @@ err_restore_cookie: 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); } diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index b2d99101947..f4c2d79cbc8 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -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. diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index e7b98f013b0..5300232449f 100644 --- a/drivers/net/wireless/b43/phy_g.c +++ b/drivers/net/wireless/b43/phy_g.c @@ -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; diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 58e319d6b1e..ea0d3a3a6a6 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -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 } diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 8bcfda5f3f0..be7b5604947 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -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 } diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 9e1d00bc24d..96047843cd5 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -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; } diff --git a/drivers/net/wireless/b43/rfkill.h b/drivers/net/wireless/b43/rfkill.h index adacf936d81..da497e01bbb 100644 --- a/drivers/net/wireless/b43/rfkill.h +++ b/drivers/net/wireless/b43/rfkill.h @@ -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 */ diff --git a/drivers/net/wireless/b43legacy/Kconfig b/drivers/net/wireless/b43legacy/Kconfig index d4f628a74bb..6893f439df7 100644 --- a/drivers/net/wireless/b43legacy/Kconfig +++ b/drivers/net/wireless/b43legacy/Kconfig @@ -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, diff --git a/drivers/net/wireless/b43legacy/leds.c b/drivers/net/wireless/b43legacy/leds.c index 3ea55b18c70..538d3117594 100644 --- a/drivers/net/wireless/b43legacy/leds.c +++ b/drivers/net/wireless/b43legacy/leds.c @@ -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; diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c index 4b0c7d27a51..c6230a64505 100644 --- a/drivers/net/wireless/b43legacy/rfkill.c +++ b/drivers/net/wireless/b43legacy/rfkill.c @@ -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; } diff --git a/drivers/net/wireless/b43legacy/rfkill.h b/drivers/net/wireless/b43legacy/rfkill.h index 11150a8032f..adffc503a6a 100644 --- a/drivers/net/wireless/b43legacy/rfkill.h +++ b/drivers/net/wireless/b43legacy/rfkill.h @@ -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 */ diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 8304f6406a1..6fe259fcfb8 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -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" diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index bd7e520d98c..225e5f88934 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -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; } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 814afaf6d10..5eb538d18a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -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; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index fd65e1c3e05..46288e72488 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -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 = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index da87528f355..4d8a325ea9d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -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); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a0b29411a4b..8f3d4bc6a03 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -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 = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index ab29aab6b2d..b3c648ce8c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -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 = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 7236382aeaa..bd438d8acf5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -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 = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 23a58b00f18..ff20e5048a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -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) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0a5507cbeb3..b77208de92a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -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); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index e581dc323f0..c87033bf3ad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -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 * diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index e93ddb74457..51cae4ec26a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -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; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 87df1b76794..b52d0fb1606 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -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 */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2dafc26fb6a..28c39cf8b12 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -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 */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index cefa501e597..7d7554a2f34 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -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; } diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 19680f72087..5e64252f80f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -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; } diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index 65605ad44e4..13149936fd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -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); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 0eb939c40ac..2addf735b19 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -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]. diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 59a586b6b56..6deebade636 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -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, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 5c10b87d033..92fa1a39c44 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -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); diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig index 41bd4b2b541..1eccb6df46d 100644 --- a/drivers/net/wireless/iwmc3200wifi/Kconfig +++ b/drivers/net/wireless/iwmc3200wifi/Kconfig @@ -1,10 +1,9 @@ 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" diff --git a/drivers/net/wireless/iwmc3200wifi/Makefile b/drivers/net/wireless/iwmc3200wifi/Makefile index 7cb415e5c11..927f022545c 100644 --- a/drivers/net/wireless/iwmc3200wifi/Makefile +++ b/drivers/net/wireless/iwmc3200wifi/Makefile @@ -1,5 +1,5 @@ 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 diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 3256ad2c96c..96f714e6e12 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -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) diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c index db4ba086473..ec1a15a5a0e 100644 --- a/drivers/net/wireless/iwmc3200wifi/fw.c +++ b/drivers/net/wireless/iwmc3200wifi/fw.c @@ -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; } diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 3b29681792b..635c16ee618 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -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 diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c index eec7201e91a..68e2c3b6c7a 100644 --- a/drivers/net/wireless/iwmc3200wifi/netdev.c +++ b/drivers/net/wireless/iwmc3200wifi/netdev.c @@ -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); diff --git a/drivers/net/wireless/iwmc3200wifi/rfkill.c b/drivers/net/wireless/iwmc3200wifi/rfkill.c deleted file mode 100644 index 4ca8b495f82..00000000000 --- a/drivers/net/wireless/iwmc3200wifi/rfkill.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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; -} diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c index edc0a009105..b54da677b37 100644 --- a/drivers/net/wireless/iwmc3200wifi/sdio.c +++ b/drivers/net/wireless/iwmc3200wifi/sdio.c @@ -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", }; diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c index 4bc46a60ae2..9a5408e7d94 100644 --- a/drivers/net/wireless/libertas/11d.c +++ b/drivers/net/wireless/libertas/11d.c @@ -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 @@ done: * @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 @@ done: 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); diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h index 4f4f47f0f87..fb75d3e321a 100644 --- a/drivers/net/wireless/libertas/11d.h +++ b/drivers/net/wireless/libertas/11d.h @@ -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 { diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index a0e440cd896..b9b37411903 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -12,15 +12,14 @@ #include "scan.h" #include "cmd.h" -static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp); - static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -/* The firmware needs certain bits masked out of the beacon-derviced capability - * field when associating/joining to BSSs. +/* The firmware needs the following bits masked out of the beacon-derived + * capability field when associating/joining to a BSS: + * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused) */ #define CAPINFO_MASK (~(0xda00)) @@ -102,6 +101,295 @@ static void lbs_set_basic_rate_flags(u8 *rates, size_t len) } +static u8 iw_auth_to_ieee_auth(u8 auth) +{ + if (auth == IW_AUTH_ALG_OPEN_SYSTEM) + return 0x00; + else if (auth == IW_AUTH_ALG_SHARED_KEY) + return 0x01; + else if (auth == IW_AUTH_ALG_LEAP) + return 0x80; + + lbs_deb_join("%s: invalid auth alg 0x%X\n", __func__, auth); + return 0; +} + +/** + * @brief This function prepares the authenticate command. AUTHENTICATE only + * sets the authentication suite for future associations, as the firmware + * handles authentication internally during the ASSOCIATE command. + * + * @param priv A pointer to struct lbs_private structure + * @param bssid The peer BSSID with which to authenticate + * @param auth The authentication mode to use (from wireless.h) + * + * @return 0 or -1 + */ +static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth) +{ + struct cmd_ds_802_11_authenticate cmd; + int ret = -1; + DECLARE_MAC_BUF(mac); + + lbs_deb_enter(LBS_DEB_JOIN); + + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + memcpy(cmd.bssid, bssid, ETH_ALEN); + + cmd.authtype = iw_auth_to_ieee_auth(auth); + + lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n", + print_mac(mac, bssid), cmd.authtype); + + ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd); + + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); + return ret; +} + + +static int lbs_assoc_post(struct lbs_private *priv, + struct cmd_ds_802_11_associate_response *resp) +{ + int ret = 0; + union iwreq_data wrqu; + struct bss_descriptor *bss; + u16 status_code; + + lbs_deb_enter(LBS_DEB_ASSOC); + + if (!priv->in_progress_assoc_req) { + lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n"); + ret = -1; + goto done; + } + bss = &priv->in_progress_assoc_req->bss; + + /* + * Older FW versions map the IEEE 802.11 Status Code in the association + * response to the following values returned in resp->statuscode: + * + * IEEE Status Code Marvell Status Code + * 0 -> 0x0000 ASSOC_RESULT_SUCCESS + * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * others -> 0x0003 ASSOC_RESULT_REFUSED + * + * Other response codes: + * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) + * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for + * association response from the AP) + */ + + status_code = le16_to_cpu(resp->statuscode); + if (priv->fwrelease < 0x09000000) { + switch (status_code) { + case 0x00: + break; + case 0x01: + lbs_deb_assoc("ASSOC_RESP: invalid parameters\n"); + break; + case 0x02: + lbs_deb_assoc("ASSOC_RESP: internal timer " + "expired while waiting for the AP\n"); + break; + case 0x03: + lbs_deb_assoc("ASSOC_RESP: association " + "refused by AP\n"); + break; + case 0x04: + lbs_deb_assoc("ASSOC_RESP: authentication " + "refused by AP\n"); + break; + default: + lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x " + " unknown\n", status_code); + break; + } + } else { + /* v9+ returns the AP's association response */ + lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x\n", status_code); + } + + if (status_code) { + lbs_mac_event_disconnected(priv); + ret = -1; + goto done; + } + + lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", + (void *) (resp + sizeof (resp->hdr)), + le16_to_cpu(resp->hdr.size) - sizeof (resp->hdr)); + + /* Send a Media Connected event, according to the Spec */ + priv->connect_status = LBS_CONNECTED; + + /* Update current SSID and BSSID */ + memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); + priv->curbssparams.ssid_len = bss->ssid_len; + memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); + + priv->SNR[TYPE_RXPD][TYPE_AVG] = 0; + priv->NF[TYPE_RXPD][TYPE_AVG] = 0; + + memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); + memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); + priv->nextSNRNF = 0; + priv->numSNRNF = 0; + + netif_carrier_on(priv->dev); + if (!priv->tx_pending_len) + netif_wake_queue(priv->dev); + + memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); + +done: + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); + return ret; +} + +/** + * @brief This function prepares an association-class command. + * + * @param priv A pointer to struct lbs_private structure + * @param assoc_req The association request describing the BSS to associate + * or reassociate with + * @param command The actual command, either CMD_802_11_ASSOCIATE or + * CMD_802_11_REASSOCIATE + * + * @return 0 or -1 + */ +static int lbs_associate(struct lbs_private *priv, + struct assoc_request *assoc_req, + u16 command) +{ + struct cmd_ds_802_11_associate cmd; + int ret = 0; + struct bss_descriptor *bss = &assoc_req->bss; + u8 *pos = &(cmd.iebuf[0]); + u16 tmpcap, tmplen, tmpauth; + struct mrvl_ie_ssid_param_set *ssid; + struct mrvl_ie_ds_param_set *ds; + struct mrvl_ie_cf_param_set *cf; + struct mrvl_ie_rates_param_set *rates; + struct mrvl_ie_rsn_param_set *rsn; + struct mrvl_ie_auth_type *auth; + + lbs_deb_enter(LBS_DEB_ASSOC); + + BUG_ON((command != CMD_802_11_ASSOCIATE) && + (command != CMD_802_11_REASSOCIATE)); + + memset(&cmd, 0, sizeof(cmd)); + cmd.hdr.command = cpu_to_le16(command); + + /* Fill in static fields */ + memcpy(cmd.bssid, bss->bssid, ETH_ALEN); + cmd.listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL); + + /* Capability info */ + tmpcap = (bss->capability & CAPINFO_MASK); + if (bss->mode == IW_MODE_INFRA) + tmpcap |= WLAN_CAPABILITY_ESS; + cmd.capability = cpu_to_le16(tmpcap); + lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap); + + /* SSID */ + ssid = (struct mrvl_ie_ssid_param_set *) pos; + ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); + tmplen = bss->ssid_len; + ssid->header.len = cpu_to_le16(tmplen); + memcpy(ssid->ssid, bss->ssid, tmplen); + pos += sizeof(ssid->header) + tmplen; + + ds = (struct mrvl_ie_ds_param_set *) pos; + ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); + ds->header.len = cpu_to_le16(1); + ds->channel = bss->phy.ds.channel; + pos += sizeof(ds->header) + 1; + + cf = (struct mrvl_ie_cf_param_set *) pos; + cf->header.type = cpu_to_le16(TLV_TYPE_CF); + tmplen = sizeof(*cf) - sizeof (cf->header); + cf->header.len = cpu_to_le16(tmplen); + /* IE payload should be zeroed, firmware fills it in for us */ + pos += sizeof(*cf); + + rates = (struct mrvl_ie_rates_param_set *) pos; + rates->header.type = cpu_to_le16(TLV_TYPE_RATES); + memcpy(&rates->rates, &bss->rates, MAX_RATES); + tmplen = MAX_RATES; + if (get_common_rates(priv, rates->rates, &tmplen)) { + ret = -1; + goto done; + } + pos += sizeof(rates->header) + tmplen; + rates->header.len = cpu_to_le16(tmplen); + lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen); + + /* Copy the infra. association rates into Current BSS state structure */ + memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); + memcpy(&priv->curbssparams.rates, &rates->rates, tmplen); + + /* Set MSB on basic rates as the firmware requires, but _after_ + * copying to current bss rates. + */ + lbs_set_basic_rate_flags(rates->rates, tmplen); + + /* Firmware v9+ indicate authentication suites as a TLV */ + if (priv->fwrelease >= 0x09000000) { + DECLARE_MAC_BUF(mac); + + auth = (struct mrvl_ie_auth_type *) pos; + auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); + auth->header.len = cpu_to_le16(2); + tmpauth = iw_auth_to_ieee_auth(priv->secinfo.auth_mode); + auth->auth = cpu_to_le16(tmpauth); + pos += sizeof(auth->header) + 2; + + lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n", + print_mac(mac, bss->bssid), priv->secinfo.auth_mode); + } + + /* WPA/WPA2 IEs */ + if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { + rsn = (struct mrvl_ie_rsn_param_set *) pos; + /* WPA_IE or WPA2_IE */ + rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]); + tmplen = (u16) assoc_req->wpa_ie[1]; + rsn->header.len = cpu_to_le16(tmplen); + memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen); + lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: WPA/RSN IE", (u8 *) rsn, + sizeof(rsn->header) + tmplen); + pos += sizeof(rsn->header) + tmplen; + } + + cmd.hdr.size = cpu_to_le16((sizeof(cmd) - sizeof(cmd.iebuf)) + + (u16)(pos - (u8 *) &cmd.iebuf)); + + /* update curbssparams */ + priv->curbssparams.channel = bss->phy.ds.channel; + + if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { + ret = -1; + goto done; + } + + ret = lbs_cmd_with_response(priv, command, &cmd); + if (ret == 0) { + ret = lbs_assoc_post(priv, + (struct cmd_ds_802_11_associate_response *) &cmd); + } + +done: + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); + return ret; +} + /** * @brief Associate to a specific BSS discovered in a scan * @@ -110,7 +398,7 @@ static void lbs_set_basic_rate_flags(u8 *rates, size_t len) * * @return 0-success, otherwise fail */ -static int lbs_associate(struct lbs_private *priv, +static int lbs_try_associate(struct lbs_private *priv, struct assoc_request *assoc_req) { int ret; @@ -118,11 +406,15 @@ static int lbs_associate(struct lbs_private *priv, lbs_deb_enter(LBS_DEB_ASSOC); - ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE, - 0, CMD_OPTION_WAITFORRSP, - 0, assoc_req->bss.bssid); - if (ret) - goto out; + /* FW v9 and higher indicate authentication suites as a TLV in the + * association command, not as a separate authentication command. + */ + if (priv->fwrelease < 0x09000000) { + ret = lbs_set_authentication(priv, assoc_req->bss.bssid, + priv->secinfo.auth_mode); + if (ret) + goto out; + } /* Use short preamble only when both the BSS and firmware support it */ if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && @@ -133,14 +425,78 @@ static int lbs_associate(struct lbs_private *priv, if (ret) goto out; - ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE, - 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); + ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE); out: lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); return ret; } +static int lbs_adhoc_post(struct lbs_private *priv, + struct cmd_ds_802_11_ad_hoc_result *resp) +{ + int ret = 0; + u16 command = le16_to_cpu(resp->hdr.command); + u16 result = le16_to_cpu(resp->hdr.result); + union iwreq_data wrqu; + struct bss_descriptor *bss; + DECLARE_SSID_BUF(ssid); + + lbs_deb_enter(LBS_DEB_JOIN); + + if (!priv->in_progress_assoc_req) { + lbs_deb_join("ADHOC_RESP: no in-progress association " + "request\n"); + ret = -1; + goto done; + } + bss = &priv->in_progress_assoc_req->bss; + + /* + * Join result code 0 --> SUCCESS + */ + if (result) { + lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result); + if (priv->connect_status == LBS_CONNECTED) + lbs_mac_event_disconnected(priv); + ret = -1; + goto done; + } + + /* Send a Media Connected event, according to the Spec */ + priv->connect_status = LBS_CONNECTED; + + if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { + /* Update the created network descriptor with the new BSSID */ + memcpy(bss->bssid, resp->bssid, ETH_ALEN); + } + + /* Set the BSSID from the joined/started descriptor */ + memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); + + /* Set the new SSID to current SSID */ + memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); + priv->curbssparams.ssid_len = bss->ssid_len; + + netif_carrier_on(priv->dev); + if (!priv->tx_pending_len) + netif_wake_queue(priv->dev); + + memset(&wrqu, 0, sizeof(wrqu)); + memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); + + lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", + print_ssid(ssid, bss->ssid, bss->ssid_len), + priv->curbssparams.bssid, + priv->curbssparams.channel); + +done: + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); + return ret; +} + /** * @brief Join an adhoc network found in a previous scan * @@ -219,11 +575,10 @@ static int lbs_adhoc_join(struct lbs_private *priv, memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN); memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len); - memcpy(&cmd.bss.phyparamset, &bss->phyparamset, - sizeof(union ieeetypes_phyparamset)); + memcpy(&cmd.bss.ds, &bss->phy.ds, sizeof(struct ieee_ie_ds_param_set)); - memcpy(&cmd.bss.ssparamset, &bss->ssparamset, - sizeof(union IEEEtypes_ssparamset)); + memcpy(&cmd.bss.ibss, &bss->ss.ibss, + sizeof(struct ieee_ie_ibss_param_set)); cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK); lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", @@ -260,7 +615,7 @@ static int lbs_adhoc_join(struct lbs_private *priv, */ lbs_set_basic_rate_flags(cmd.bss.rates, ratesize); - cmd.bss.ssparamset.ibssparamset.atimwindow = cpu_to_le16(bss->atimwindow); + cmd.bss.ibss.atimwindow = bss->atimwindow; if (assoc_req->secinfo.wep_enabled) { u16 tmp = le16_to_cpu(cmd.bss.capability); @@ -287,8 +642,10 @@ static int lbs_adhoc_join(struct lbs_private *priv, } ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); - if (ret == 0) - ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd); + if (ret == 0) { + ret = lbs_adhoc_post(priv, + (struct cmd_ds_802_11_ad_hoc_result *)&cmd); + } out: lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); @@ -343,22 +700,24 @@ static int lbs_adhoc_start(struct lbs_private *priv, WARN_ON(!assoc_req->channel); /* set Physical parameter set */ - cmd.phyparamset.dsparamset.elementid = WLAN_EID_DS_PARAMS; - cmd.phyparamset.dsparamset.len = 1; - cmd.phyparamset.dsparamset.currentchan = assoc_req->channel; + cmd.ds.header.id = WLAN_EID_DS_PARAMS; + cmd.ds.header.len = 1; + cmd.ds.channel = assoc_req->channel; /* set IBSS parameter set */ - cmd.ssparamset.ibssparamset.elementid = WLAN_EID_IBSS_PARAMS; - cmd.ssparamset.ibssparamset.len = 2; - cmd.ssparamset.ibssparamset.atimwindow = 0; + cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS; + cmd.ibss.header.len = 2; + cmd.ibss.atimwindow = cpu_to_le16(0); /* set capability info */ tmpcap = WLAN_CAPABILITY_IBSS; - if (assoc_req->secinfo.wep_enabled) { - lbs_deb_join("ADHOC_START: WEP enabled, setting privacy on\n"); + if (assoc_req->secinfo.wep_enabled || + assoc_req->secinfo.WPAenabled || + assoc_req->secinfo.WPA2enabled) { + lbs_deb_join("ADHOC_START: WEP/WPA enabled, privacy on\n"); tmpcap |= WLAN_CAPABILITY_PRIVACY; } else - lbs_deb_join("ADHOC_START: WEP disabled, setting privacy off\n"); + lbs_deb_join("ADHOC_START: WEP disabled, privacy off\n"); cmd.capability = cpu_to_le16(tmpcap); @@ -395,7 +754,8 @@ static int lbs_adhoc_start(struct lbs_private *priv, ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd); if (ret == 0) - ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd); + ret = lbs_adhoc_post(priv, + (struct cmd_ds_802_11_ad_hoc_result *)&cmd); out: lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); @@ -720,7 +1080,7 @@ static int assoc_helper_essid(struct lbs_private *priv, assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel); if (bss != NULL) { memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); - ret = lbs_associate(priv, assoc_req); + ret = lbs_try_associate(priv, assoc_req); } else { lbs_deb_assoc("SSID not found; cannot associate\n"); } @@ -772,8 +1132,9 @@ static int assoc_helper_bssid(struct lbs_private *priv, memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); if (assoc_req->mode == IW_MODE_INFRA) { - ret = lbs_associate(priv, assoc_req); - lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret); + ret = lbs_try_associate(priv, assoc_req); + lbs_deb_assoc("ASSOC: lbs_try_associate(bssid) returned %d\n", + ret); } else if (assoc_req->mode == IW_MODE_ADHOC) { lbs_adhoc_join(priv, assoc_req); } @@ -1467,57 +1828,6 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv) /** - * @brief This function prepares command of authenticate. - * - * @param priv A pointer to struct lbs_private structure - * @param cmd A pointer to cmd_ds_command structure - * @param pdata_buf Void cast of pointer to a BSSID to authenticate with - * - * @return 0 or -1 - */ -int lbs_cmd_80211_authenticate(struct lbs_private *priv, - struct cmd_ds_command *cmd, - void *pdata_buf) -{ - struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth; - int ret = -1; - u8 *bssid = pdata_buf; - - lbs_deb_enter(LBS_DEB_JOIN); - - cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate) - + S_DS_GEN); - - /* translate auth mode to 802.11 defined wire value */ - switch (priv->secinfo.auth_mode) { - case IW_AUTH_ALG_OPEN_SYSTEM: - pauthenticate->authtype = 0x00; - break; - case IW_AUTH_ALG_SHARED_KEY: - pauthenticate->authtype = 0x01; - break; - case IW_AUTH_ALG_LEAP: - pauthenticate->authtype = 0x80; - break; - default: - lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n", - priv->secinfo.auth_mode); - goto out; - } - - memcpy(pauthenticate->macaddr, bssid, ETH_ALEN); - - lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", - bssid, pauthenticate->authtype); - ret = 0; - -out: - lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); - return ret; -} - -/** * @brief Deauthenticate from a specific BSS * * @param priv A pointer to struct lbs_private structure @@ -1550,285 +1860,3 @@ int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN], return ret; } -int lbs_cmd_80211_associate(struct lbs_private *priv, - struct cmd_ds_command *cmd, void *pdata_buf) -{ - struct cmd_ds_802_11_associate *passo = &cmd->params.associate; - int ret = 0; - struct assoc_request *assoc_req = pdata_buf; - struct bss_descriptor *bss = &assoc_req->bss; - u8 *pos; - u16 tmpcap, tmplen; - struct mrvlietypes_ssidparamset *ssid; - struct mrvlietypes_phyparamset *phy; - struct mrvlietypes_ssparamset *ss; - struct mrvlietypes_ratesparamset *rates; - struct mrvlietypes_rsnparamset *rsn; - - lbs_deb_enter(LBS_DEB_ASSOC); - - pos = (u8 *) passo; - - if (!priv) { - ret = -1; - goto done; - } - - cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE); - - memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr)); - pos += sizeof(passo->peerstaaddr); - - /* set the listen interval */ - passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL); - - pos += sizeof(passo->capability); - pos += sizeof(passo->listeninterval); - pos += sizeof(passo->bcnperiod); - pos += sizeof(passo->dtimperiod); - - ssid = (struct mrvlietypes_ssidparamset *) pos; - ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); - tmplen = bss->ssid_len; - ssid->header.len = cpu_to_le16(tmplen); - memcpy(ssid->ssid, bss->ssid, tmplen); - pos += sizeof(ssid->header) + tmplen; - - phy = (struct mrvlietypes_phyparamset *) pos; - phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); - tmplen = sizeof(phy->fh_ds.dsparamset); - phy->header.len = cpu_to_le16(tmplen); - memcpy(&phy->fh_ds.dsparamset, - &bss->phyparamset.dsparamset.currentchan, - tmplen); - pos += sizeof(phy->header) + tmplen; - - ss = (struct mrvlietypes_ssparamset *) pos; - ss->header.type = cpu_to_le16(TLV_TYPE_CF); - tmplen = sizeof(ss->cf_ibss.cfparamset); - ss->header.len = cpu_to_le16(tmplen); - pos += sizeof(ss->header) + tmplen; - - rates = (struct mrvlietypes_ratesparamset *) pos; - rates->header.type = cpu_to_le16(TLV_TYPE_RATES); - memcpy(&rates->rates, &bss->rates, MAX_RATES); - tmplen = MAX_RATES; - if (get_common_rates(priv, rates->rates, &tmplen)) { - ret = -1; - goto done; - } - pos += sizeof(rates->header) + tmplen; - rates->header.len = cpu_to_le16(tmplen); - lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen); - - /* Copy the infra. association rates into Current BSS state structure */ - memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); - memcpy(&priv->curbssparams.rates, &rates->rates, tmplen); - - /* Set MSB on basic rates as the firmware requires, but _after_ - * copying to current bss rates. - */ - lbs_set_basic_rate_flags(rates->rates, tmplen); - - if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { - rsn = (struct mrvlietypes_rsnparamset *) pos; - /* WPA_IE or WPA2_IE */ - rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]); - tmplen = (u16) assoc_req->wpa_ie[1]; - rsn->header.len = cpu_to_le16(tmplen); - memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen); - lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn, - sizeof(rsn->header) + tmplen); - pos += sizeof(rsn->header) + tmplen; - } - - /* update curbssparams */ - priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan; - - if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { - ret = -1; - goto done; - } - - cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN); - - /* set the capability info */ - tmpcap = (bss->capability & CAPINFO_MASK); - if (bss->mode == IW_MODE_INFRA) - tmpcap |= WLAN_CAPABILITY_ESS; - passo->capability = cpu_to_le16(tmpcap); - lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap); - -done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -int lbs_ret_80211_associate(struct lbs_private *priv, - struct cmd_ds_command *resp) -{ - int ret = 0; - union iwreq_data wrqu; - struct ieeetypes_assocrsp *passocrsp; - struct bss_descriptor *bss; - u16 status_code; - - lbs_deb_enter(LBS_DEB_ASSOC); - - if (!priv->in_progress_assoc_req) { - lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n"); - ret = -1; - goto done; - } - bss = &priv->in_progress_assoc_req->bss; - - passocrsp = (struct ieeetypes_assocrsp *) &resp->params; - - /* - * Older FW versions map the IEEE 802.11 Status Code in the association - * response to the following values returned in passocrsp->statuscode: - * - * IEEE Status Code Marvell Status Code - * 0 -> 0x0000 ASSOC_RESULT_SUCCESS - * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * others -> 0x0003 ASSOC_RESULT_REFUSED - * - * Other response codes: - * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) - * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for - * association response from the AP) - */ - - status_code = le16_to_cpu(passocrsp->statuscode); - switch (status_code) { - case 0x00: - break; - case 0x01: - lbs_deb_assoc("ASSOC_RESP: invalid parameters\n"); - break; - case 0x02: - lbs_deb_assoc("ASSOC_RESP: internal timer " - "expired while waiting for the AP\n"); - break; - case 0x03: - lbs_deb_assoc("ASSOC_RESP: association " - "refused by AP\n"); - break; - case 0x04: - lbs_deb_assoc("ASSOC_RESP: authentication " - "refused by AP\n"); - break; - default: - lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x " - " unknown\n", status_code); - break; - } - - if (status_code) { - lbs_mac_event_disconnected(priv); - ret = -1; - goto done; - } - - lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params, - le16_to_cpu(resp->size) - S_DS_GEN); - - /* Send a Media Connected event, according to the Spec */ - priv->connect_status = LBS_CONNECTED; - - /* Update current SSID and BSSID */ - memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); - priv->curbssparams.ssid_len = bss->ssid_len; - memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); - - priv->SNR[TYPE_RXPD][TYPE_AVG] = 0; - priv->NF[TYPE_RXPD][TYPE_AVG] = 0; - - memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); - memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); - priv->nextSNRNF = 0; - priv->numSNRNF = 0; - - netif_carrier_on(priv->dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->dev); - - memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - -done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp) -{ - int ret = 0; - u16 command = le16_to_cpu(resp->command); - u16 result = le16_to_cpu(resp->result); - struct cmd_ds_802_11_ad_hoc_result *adhoc_resp; - union iwreq_data wrqu; - struct bss_descriptor *bss; - DECLARE_SSID_BUF(ssid); - - lbs_deb_enter(LBS_DEB_JOIN); - - adhoc_resp = (struct cmd_ds_802_11_ad_hoc_result *) resp; - - if (!priv->in_progress_assoc_req) { - lbs_deb_join("ADHOC_RESP: no in-progress association " - "request\n"); - ret = -1; - goto done; - } - bss = &priv->in_progress_assoc_req->bss; - - /* - * Join result code 0 --> SUCCESS - */ - if (result) { - lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result); - if (priv->connect_status == LBS_CONNECTED) - lbs_mac_event_disconnected(priv); - ret = -1; - goto done; - } - - /* Send a Media Connected event, according to the Spec */ - priv->connect_status = LBS_CONNECTED; - - if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { - /* Update the created network descriptor with the new BSSID */ - memcpy(bss->bssid, adhoc_resp->bssid, ETH_ALEN); - } - - /* Set the BSSID from the joined/started descriptor */ - memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); - - /* Set the new SSID to current SSID */ - memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); - priv->curbssparams.ssid_len = bss->ssid_len; - - netif_carrier_on(priv->dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->dev); - - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - - lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", - print_ssid(ssid, bss->ssid, bss->ssid_len), - priv->curbssparams.bssid, - priv->curbssparams.channel); - -done: - lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); - return ret; -} - diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h index 8b7336dd02a..6e765e9f91a 100644 --- a/drivers/net/wireless/libertas/assoc.h +++ b/drivers/net/wireless/libertas/assoc.h @@ -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 */ diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index c455b9abbfc..01db705a38e 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -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, diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index bcf2a9756fb..c42d3faa266 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -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; diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 50e28a0cdfe..811ffc3ef41 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -183,12 +183,12 @@ out_unlock: */ 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; diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index a4455ec7c35..f9ec69e0473 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -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; diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index 391c54ab2b0..0a2e29140ad 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -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; diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index a7e3fc119b7..8cdb88c6ca2 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -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); diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 5fa55fe1f86..ea23c5de142 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -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 @@ out: 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 @@ out: /* 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; } diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index a58a1235267..89575e44801 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -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); diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 8124db36aaf..601b5424967 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -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); diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h index de03b9c9c20..99905df65b2 100644 --- a/drivers/net/wireless/libertas/types.h +++ b/drivers/net/wireless/libertas/types.h @@ -8,9 +8,14 @@ #include <asm/byteorder.h> #include <linux/wireless.h> -struct ieeetypes_cfparamset { - u8 elementid; +struct ieee_ie_header { + u8 id; u8 len; +} __attribute__ ((packed)); + +struct ieee_ie_cf_param_set { + struct ieee_ie_header header; + u8 cfpcnt; u8 cfpperiod; __le16 cfpmaxduration; @@ -18,42 +23,35 @@ struct ieeetypes_cfparamset { } __attribute__ ((packed)); -struct ieeetypes_ibssparamset { - u8 elementid; - u8 len; +struct ieee_ie_ibss_param_set { + struct ieee_ie_header header; + __le16 atimwindow; } __attribute__ ((packed)); -union IEEEtypes_ssparamset { - struct ieeetypes_cfparamset cfparamset; - struct ieeetypes_ibssparamset ibssparamset; +union ieee_ss_param_set { + struct ieee_ie_cf_param_set cf; + struct ieee_ie_ibss_param_set ibss; } __attribute__ ((packed)); -struct ieeetypes_fhparamset { - u8 elementid; - u8 len; +struct ieee_ie_fh_param_set { + struct ieee_ie_header header; + __le16 dwelltime; u8 hopset; u8 hoppattern; u8 hopindex; } __attribute__ ((packed)); -struct ieeetypes_dsparamset { - u8 elementid; - u8 len; - u8 currentchan; -} __attribute__ ((packed)); +struct ieee_ie_ds_param_set { + struct ieee_ie_header header; -union ieeetypes_phyparamset { - struct ieeetypes_fhparamset fhparamset; - struct ieeetypes_dsparamset dsparamset; + u8 channel; } __attribute__ ((packed)); -struct ieeetypes_assocrsp { - __le16 capability; - __le16 statuscode; - __le16 aid; - u8 iebuffer[1]; +union ieee_phy_param_set { + struct ieee_ie_fh_param_set fh; + struct ieee_ie_ds_param_set ds; } __attribute__ ((packed)); /** TLV type ID definition */ @@ -94,32 +92,33 @@ struct ieeetypes_assocrsp { #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) #define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23) +#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) #define TLV_TYPE_MESH_ID (PROPRIETARY_TLV_BASE_ID + 37) #define TLV_TYPE_OLD_MESH_ID (PROPRIETARY_TLV_BASE_ID + 291) /** TLV related data structures*/ -struct mrvlietypesheader { +struct mrvl_ie_header { __le16 type; __le16 len; } __attribute__ ((packed)); -struct mrvlietypes_data { - struct mrvlietypesheader header; +struct mrvl_ie_data { + struct mrvl_ie_header header; u8 Data[1]; } __attribute__ ((packed)); -struct mrvlietypes_ratesparamset { - struct mrvlietypesheader header; +struct mrvl_ie_rates_param_set { + struct mrvl_ie_header header; u8 rates[1]; } __attribute__ ((packed)); -struct mrvlietypes_ssidparamset { - struct mrvlietypesheader header; +struct mrvl_ie_ssid_param_set { + struct mrvl_ie_header header; u8 ssid[1]; } __attribute__ ((packed)); -struct mrvlietypes_wildcardssidparamset { - struct mrvlietypesheader header; +struct mrvl_ie_wildcard_ssid_param_set { + struct mrvl_ie_header header; u8 MaxSsidlength; u8 ssid[1]; } __attribute__ ((packed)); @@ -144,91 +143,72 @@ struct chanscanparamset { __le16 maxscantime; } __attribute__ ((packed)); -struct mrvlietypes_chanlistparamset { - struct mrvlietypesheader header; +struct mrvl_ie_chanlist_param_set { + struct mrvl_ie_header header; struct chanscanparamset chanscanparam[1]; } __attribute__ ((packed)); -struct cfparamset { +struct mrvl_ie_cf_param_set { + struct mrvl_ie_header header; u8 cfpcnt; u8 cfpperiod; __le16 cfpmaxduration; __le16 cfpdurationremaining; } __attribute__ ((packed)); -struct ibssparamset { - __le16 atimwindow; -} __attribute__ ((packed)); - -struct mrvlietypes_ssparamset { - struct mrvlietypesheader header; - union { - struct cfparamset cfparamset[1]; - struct ibssparamset ibssparamset[1]; - } cf_ibss; +struct mrvl_ie_ds_param_set { + struct mrvl_ie_header header; + u8 channel; } __attribute__ ((packed)); -struct fhparamset { - __le16 dwelltime; - u8 hopset; - u8 hoppattern; - u8 hopindex; -} __attribute__ ((packed)); - -struct dsparamset { - u8 currentchan; -} __attribute__ ((packed)); - -struct mrvlietypes_phyparamset { - struct mrvlietypesheader header; - union { - struct fhparamset fhparamset[1]; - struct dsparamset dsparamset[1]; - } fh_ds; -} __attribute__ ((packed)); - -struct mrvlietypes_rsnparamset { - struct mrvlietypesheader header; +struct mrvl_ie_rsn_param_set { + struct mrvl_ie_header header; u8 rsnie[1]; } __attribute__ ((packed)); -struct mrvlietypes_tsftimestamp { - struct mrvlietypesheader header; +struct mrvl_ie_tsf_timestamp { + struct mrvl_ie_header header; __le64 tsftable[1]; } __attribute__ ((packed)); +/* v9 and later firmware only */ +struct mrvl_ie_auth_type { + struct mrvl_ie_header header; + __le16 auth; +} __attribute__ ((packed)); + /** Local Power capability */ -struct mrvlietypes_powercapability { - struct mrvlietypesheader header; +struct mrvl_ie_power_capability { + struct mrvl_ie_header header; s8 minpower; s8 maxpower; } __attribute__ ((packed)); /* used in CMD_802_11_SUBSCRIBE_EVENT for SNR, RSSI and Failure */ -struct mrvlietypes_thresholds { - struct mrvlietypesheader header; +struct mrvl_ie_thresholds { + struct mrvl_ie_header header; u8 value; u8 freq; } __attribute__ ((packed)); -struct mrvlietypes_beaconsmissed { - struct mrvlietypesheader header; +struct mrvl_ie_beacons_missed { + struct mrvl_ie_header header; u8 beaconmissed; u8 reserved; } __attribute__ ((packed)); -struct mrvlietypes_numprobes { - struct mrvlietypesheader header; +struct mrvl_ie_num_probes { + struct mrvl_ie_header header; __le16 numprobes; } __attribute__ ((packed)); -struct mrvlietypes_bcastprobe { - struct mrvlietypesheader header; +struct mrvl_ie_bcast_probe { + struct mrvl_ie_header header; __le16 bcastprobe; } __attribute__ ((packed)); -struct mrvlietypes_numssidprobe { - struct mrvlietypesheader header; +struct mrvl_ie_num_ssid_probe { + struct mrvl_ie_header header; __le16 numssidprobe; } __attribute__ ((packed)); @@ -237,8 +217,8 @@ struct led_pin { u8 pin; } __attribute__ ((packed)); -struct mrvlietypes_ledgpio { - struct mrvlietypesheader header; +struct mrvl_ie_ledgpio { + struct mrvl_ie_header header; struct led_pin ledpin[1]; } __attribute__ ((packed)); @@ -250,8 +230,8 @@ struct led_bhv { } __attribute__ ((packed)); -struct mrvlietypes_ledbhv { - struct mrvlietypesheader header; +struct mrvl_ie_ledbhv { + struct mrvl_ie_header header; struct led_bhv ledbhv[1]; } __attribute__ ((packed)); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 574b8bb121e..e789c6e9938 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -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); } diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index f40c0f468b2..0e877a104a8 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -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] = { { diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 0197531bd88..435f945fe64 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -520,7 +520,7 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, if (state == STATE_SLEEP) { rt2x00pci_register_read(rt2x00dev, CSR20, ®); rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN, - (libconf->conf->beacon_int - 20) * 16); + (rt2x00dev->beacon_int - 20) * 16); rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, libconf->conf->listen_interval - 1); diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index f95cb646f85..08b30d01e67 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -569,7 +569,7 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, if (state == STATE_SLEEP) { rt2x00pci_register_read(rt2x00dev, CSR20, ®); rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN, - (libconf->conf->beacon_int - 20) * 16); + (rt2x00dev->beacon_int - 20) * 16); rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, libconf->conf->listen_interval - 1); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 69f966f1ce5..66daf68ff0e 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -647,7 +647,7 @@ static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev, if (state == STATE_SLEEP) { rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); rt2x00_set_field16(®, MAC_CSR18_DELAY_AFTER_BEACON, - libconf->conf->beacon_int - 20); + rt2x00dev->beacon_int - 20); rt2x00_set_field16(®, MAC_CSR18_BEACONS_BEFORE_WAKEUP, libconf->conf->listen_interval - 1); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 142ad34fdc4..37561667925 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -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) }, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 2b64a619869..a498dde024e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -802,6 +802,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. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index c5bbf0b6e20..3e019a12df2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -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); } diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index a8bf5c43285..49b29ff90c4 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -956,7 +956,7 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev, if (state == STATE_SLEEP) { rt2x00pci_register_read(rt2x00dev, MAC_CSR11, ®); rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, - libconf->conf->beacon_int - 10); + rt2x00dev->beacon_int - 10); rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, libconf->conf->listen_interval - 1); rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 5); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 211a3d6bc05..c18848836f2 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -852,7 +852,7 @@ static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev, if (state == STATE_SLEEP) { rt2x00usb_register_read(rt2x00dev, MAC_CSR11, ®); rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, - libconf->conf->beacon_int - 10); + rt2x00dev->beacon_int - 10); rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, libconf->conf->listen_interval - 1); rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 5); |