diff options
Diffstat (limited to 'drivers/net/wireless/ath/carl9170')
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/carl9170.h | 49 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/cmd.c | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/cmd.h | 6 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/debug.c | 12 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/fw.c | 81 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/fwcmd.h | 8 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/fwdesc.h | 3 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/hw.h | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/mac.c | 69 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/main.c | 198 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/phy.c | 121 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/rx.c | 128 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/tx.c | 435 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/usb.c | 18 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/version.h | 6 |
16 files changed, 701 insertions, 440 deletions
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig index 267d5dcf82d..1a796e5f69e 100644 --- a/drivers/net/wireless/ath/carl9170/Kconfig +++ b/drivers/net/wireless/ath/carl9170/Kconfig @@ -1,6 +1,7 @@ config CARL9170 tristate "Linux Community AR9170 802.11n USB support" - depends on USB && MAC80211 && EXPERIMENTAL + depends on USB && MAC80211 + select ATH_COMMON select FW_LOADER select CRC32 help diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 6cfbb419e2f..8596aba34f9 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -70,12 +70,6 @@ static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 }; -enum carl9170_rf_init_mode { - CARL9170_RFI_NONE, - CARL9170_RFI_WARM, - CARL9170_RFI_COLD, -}; - #define CARL9170_MAX_RX_BUFFER_SIZE 8192 enum carl9170_device_state { @@ -85,20 +79,14 @@ enum carl9170_device_state { CARL9170_STARTED, }; -#define CARL9170_NUM_TID 16 #define WME_BA_BMP_SIZE 64 #define CARL9170_TX_USER_RATE_TRIES 3 -#define WME_AC_BE 2 -#define WME_AC_BK 3 -#define WME_AC_VI 1 -#define WME_AC_VO 0 - #define TID_TO_WME_AC(_tid) \ - ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ - (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ - (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ - WME_AC_VO) + ((((_tid) == 0) || ((_tid) == 3)) ? IEEE80211_AC_BE : \ + (((_tid) == 1) || ((_tid) == 2)) ? IEEE80211_AC_BK : \ + (((_tid) == 4) || ((_tid) == 5)) ? IEEE80211_AC_VI : \ + IEEE80211_AC_VO) #define SEQ_DIFF(_start, _seq) \ (((_start) - (_seq)) & 0x0fff) @@ -145,6 +133,9 @@ struct carl9170_sta_tid { /* Preaggregation reorder queue */ struct sk_buff_head queue; + + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; }; #define CARL9170_QUEUE_TIMEOUT 256 @@ -289,6 +280,8 @@ struct ar9170 { unsigned int mem_block_size; unsigned int rx_size; unsigned int tx_seq_table; + bool ba_filter; + bool disable_offload_fw; } fw; /* interface configuration combinations */ @@ -302,6 +295,7 @@ struct ar9170 { unsigned long queue_stop_timeout[__AR9170_NUM_TXQ]; unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ]; bool needs_full_reset; + bool force_usb_reset; atomic_t pending_restarts; /* interface mode settings */ @@ -424,6 +418,11 @@ struct ar9170 { bool rx_has_plcp; struct sk_buff *rx_failover; int rx_failover_missing; + u32 ampdu_ref; + + /* FIFO for collecting outstanding BlockAckRequest */ + struct list_head bar_list[__AR9170_NUM_TXQ]; + spinlock_t bar_list_lock[__AR9170_NUM_TXQ]; #ifdef CONFIG_CARL9170_WPC struct { @@ -468,6 +467,12 @@ enum carl9170_ps_off_override_reasons { PS_OFF_BCN = BIT(1), }; +struct carl9170_bar_list_entry { + struct list_head list; + struct rcu_head head; + struct sk_buff *skb; +}; + struct carl9170_ba_stats { u8 ampdu_len; u8 ampdu_ack_len; @@ -480,8 +485,8 @@ struct carl9170_sta_info { bool sleeping; atomic_t pending_frames; unsigned int ampdu_max_len; - struct carl9170_sta_tid __rcu *agg[CARL9170_NUM_TID]; - struct carl9170_ba_stats stats[CARL9170_NUM_TID]; + struct carl9170_sta_tid __rcu *agg[IEEE80211_NUM_TIDS]; + struct carl9170_ba_stats stats[IEEE80211_NUM_TIDS]; }; struct carl9170_tx_info { @@ -559,13 +564,16 @@ int carl9170_set_hwretry_limit(struct ar9170 *ar, const u32 max_retry); int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac, const u8 ktype, const u8 keyidx, const u8 *keydata, const int keylen); int carl9170_disable_key(struct ar9170 *ar, const u8 id); +int carl9170_set_mac_tpc(struct ar9170 *ar, struct ieee80211_channel *channel); /* RX */ void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len); void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len); /* TX */ -void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +void carl9170_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb); void carl9170_tx_janitor(struct work_struct *work); void carl9170_tx_process_status(struct ar9170 *ar, const struct carl9170_rsp *cmd); @@ -588,12 +596,11 @@ int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state); /* PHY / RF */ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, - enum nl80211_channel_type bw, enum carl9170_rf_init_mode rfi); + enum nl80211_channel_type bw); int carl9170_get_noisefloor(struct ar9170 *ar); /* FW */ int carl9170_parse_firmware(struct ar9170 *ar); -int carl9170_fw_fix_eeprom(struct ar9170 *ar); extern struct ieee80211_rate __carl9170_ratetable[]; extern int modparam_noht; diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c index 195dc653811..39a63874b27 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.c +++ b/drivers/net/wireless/ath/carl9170/cmd.c @@ -138,7 +138,7 @@ int carl9170_reboot(struct ar9170 *ar) if (!cmd) return -ENOMEM; - err = __carl9170_exec_cmd(ar, (struct carl9170_cmd *)cmd, true); + err = __carl9170_exec_cmd(ar, cmd, true); return err; } diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h index 885c42778b8..65919c902f5 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.h +++ b/drivers/net/wireless/ath/carl9170/cmd.h @@ -114,7 +114,7 @@ __regwrite_out : \ #define carl9170_regwrite_result() \ __err; \ -} while (0); +} while (0) #define carl9170_async_regwrite_get_buf() \ @@ -126,7 +126,7 @@ do { \ __err = -ENOMEM; \ goto __async_regwrite_out; \ } \ -} while (0); +} while (0) #define carl9170_async_regwrite_begin(carl) \ do { \ @@ -169,6 +169,6 @@ __async_regwrite_out: \ #define carl9170_async_regwrite_result() \ __err; \ -} while (0); +} while (0) #endif /* __CMD_H */ diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c index 3c164226687..1c0af9cd9a8 100644 --- a/drivers/net/wireless/ath/carl9170/debug.c +++ b/drivers/net/wireless/ath/carl9170/debug.c @@ -37,7 +37,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/seq_file.h> @@ -48,11 +47,6 @@ #define ADD(buf, off, max, fmt, args...) \ off += snprintf(&buf[off], max - off, fmt, ##args); -static int carl9170_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} struct carl9170_debugfs_fops { unsigned int read_bufsize; @@ -178,7 +172,7 @@ static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\ .attr = _attr, \ .req_dev_state = _dstate, \ .fops = { \ - .open = carl9170_debugfs_open, \ + .open = simple_open, \ .read = carl9170_debugfs_read, \ .write = carl9170_debugfs_write, \ .owner = THIS_MODULE \ @@ -659,8 +653,8 @@ static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf, goto out; case 'P': - err = carl9170_set_channel(ar, ar->hw->conf.channel, - ar->hw->conf.channel_type, CARL9170_RFI_COLD); + err = carl9170_set_channel(ar, ar->hw->conf.chandef.chan, + cfg80211_get_chandef_type(&ar->hw->conf.chandef)); if (err < 0) count = err; diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c index 3de61adacd3..47d5c2e910a 100644 --- a/drivers/net/wireless/ath/carl9170/fw.c +++ b/drivers/net/wireless/ath/carl9170/fw.c @@ -28,11 +28,6 @@ #include "fwcmd.h" #include "version.h" -#define MAKE_STR(symbol) #symbol -#define TO_STR(symbol) MAKE_STR(symbol) -#define CARL9170FW_API_VER_STR TO_STR(CARL9170FW_API_MAX_VER) -MODULE_VERSION(CARL9170FW_API_VER_STR ":" CARL9170FW_VERSION_GIT); - static const u8 otus_magic[4] = { OTUS_MAGIC }; static const void *carl9170_fw_find_desc(struct ar9170 *ar, const u8 descid[4], @@ -220,6 +215,24 @@ static int carl9170_fw_tx_sequence(struct ar9170 *ar) return 0; } +static void carl9170_fw_set_if_combinations(struct ar9170 *ar, + u16 if_comb_types) +{ + if (ar->fw.vif_num < 2) + return; + + ar->if_comb_limits[0].max = ar->fw.vif_num; + ar->if_comb_limits[0].types = if_comb_types; + + ar->if_combs[0].num_different_channels = 1; + ar->if_combs[0].max_interfaces = ar->fw.vif_num; + ar->if_combs[0].limits = ar->if_comb_limits; + ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits); + + ar->hw->wiphy->iface_combinations = ar->if_combs; + ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs); +} + static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) { const struct carl9170fw_otus_desc *otus_desc; @@ -269,7 +282,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) if (!SUPP(CARL9170FW_COMMAND_CAM)) { dev_info(&ar->udev->dev, "crypto offloading is disabled " "by firmware.\n"); - ar->disable_offload = true; + ar->fw.disable_offload_fw = true; } if (SUPP(CARL9170FW_PSM) && SUPP(CARL9170FW_FIXED_5GHZ_PSM)) @@ -307,6 +320,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) if (SUPP(CARL9170FW_WOL)) device_set_wakeup_enable(&ar->udev->dev, true); + if (SUPP(CARL9170FW_RX_BA_FILTER)) + ar->fw.ba_filter = true; + if_comb_types = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_P2P_CLIENT); @@ -339,21 +355,23 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) if_comb_types |= BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_GO); + +#ifdef CONFIG_MAC80211_MESH + if_comb_types |= + BIT(NL80211_IFTYPE_MESH_POINT); +#endif /* CONFIG_MAC80211_MESH */ } } - ar->if_comb_limits[0].max = ar->fw.vif_num; - ar->if_comb_limits[0].types = if_comb_types; + carl9170_fw_set_if_combinations(ar, if_comb_types); - ar->if_combs[0].num_different_channels = 1; - ar->if_combs[0].max_interfaces = ar->fw.vif_num; - ar->if_combs[0].limits = ar->if_comb_limits; - ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits); + ar->hw->wiphy->interface_modes |= if_comb_types; - ar->hw->wiphy->iface_combinations = ar->if_combs; - ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs); + ar->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - ar->hw->wiphy->interface_modes |= if_comb_types; + /* As IBSS Encryption is software-based, IBSS RSN is supported. */ + ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | + WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_SUPPORTS_TDLS; #undef SUPPORTED return carl9170_fw_tx_sequence(ar); @@ -389,39 +407,6 @@ carl9170_find_fw_desc(struct ar9170 *ar, const __u8 *fw_data, const size_t len) return (void *)&fw_data[scan - found]; } -int carl9170_fw_fix_eeprom(struct ar9170 *ar) -{ - const struct carl9170fw_fix_desc *fix_desc = NULL; - unsigned int i, n, off; - u32 *data = (void *)&ar->eeprom; - - fix_desc = carl9170_fw_find_desc(ar, FIX_MAGIC, - sizeof(*fix_desc), CARL9170FW_FIX_DESC_CUR_VER); - - if (!fix_desc) - return 0; - - n = (le16_to_cpu(fix_desc->head.length) - sizeof(*fix_desc)) / - sizeof(struct carl9170fw_fix_entry); - - for (i = 0; i < n; i++) { - off = le32_to_cpu(fix_desc->data[i].address) - - AR9170_EEPROM_START; - - if (off >= sizeof(struct ar9170_eeprom) || (off & 3)) { - dev_err(&ar->udev->dev, "Skip invalid entry %d\n", i); - continue; - } - - data[off / sizeof(*data)] &= - le32_to_cpu(fix_desc->data[i].mask); - data[off / sizeof(*data)] |= - le32_to_cpu(fix_desc->data[i].value); - } - - return 0; -} - int carl9170_parse_firmware(struct ar9170 *ar) { const struct carl9170fw_desc_head *fw_desc = NULL; diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index 9443c802b25..9111d4ffc1b 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h @@ -156,6 +156,14 @@ struct carl9170_psm { } __packed; #define CARL9170_PSM_SIZE 4 +/* + * Note: If a bit in rx_filter is set, then it + * means that the particular frames which matches + * the condition are FILTERED/REMOVED/DISCARDED! + * (This is can be a bit confusing, especially + * because someone people think it's the exact + * opposite way, so watch out!) + */ struct carl9170_rx_filter_cmd { __le32 rx_filter; } __packed; diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h index 6d9c0891ce7..66848d47c88 100644 --- a/drivers/net/wireless/ath/carl9170/fwdesc.h +++ b/drivers/net/wireless/ath/carl9170/fwdesc.h @@ -78,6 +78,9 @@ enum carl9170fw_feature_list { /* HW (ANI, CCA, MIB) tally counters */ CARL9170FW_HW_COUNTERS, + /* Firmware will pass BA when BARs are queued */ + CARL9170FW_RX_BA_FILTER, + /* KEEP LAST */ __CARL9170FW_FEATURE_NUM }; diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h index fa834c1460f..0db874abde5 100644 --- a/drivers/net/wireless/ath/carl9170/hw.h +++ b/drivers/net/wireless/ath/carl9170/hw.h @@ -384,7 +384,7 @@ #define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xd84) #define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xd88) -#define AR9170_MAC_BCN_LENGTH_MAX 256 +#define AR9170_MAC_BCN_LENGTH_MAX (512 - 32) #define AR9170_MAC_REG_BCN_STATUS (AR9170_MAC_REG_BASE + 0xd8c) diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c index dfda9197099..a2f005703c0 100644 --- a/drivers/net/wireless/ath/carl9170/mac.c +++ b/drivers/net/wireless/ath/carl9170/mac.c @@ -48,7 +48,7 @@ int carl9170_set_dyn_sifs_ack(struct ar9170 *ar) if (conf_is_ht40(&ar->hw->conf)) val = 0x010a; else { - if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) + if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) val = 0x105; else val = 0x104; @@ -66,7 +66,7 @@ int carl9170_set_rts_cts_rate(struct ar9170 *ar) rts_rate = 0x1da; cts_rate = 0x10a; } else { - if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { + if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) { /* 11 mbit CCK */ rts_rate = 033; cts_rate = 003; @@ -93,7 +93,7 @@ int carl9170_set_slot_time(struct ar9170 *ar) return 0; } - if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) || + if ((ar->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ) || vif->bss_conf.use_short_slot) slottime = 9; @@ -120,7 +120,7 @@ int carl9170_set_mac_rates(struct ar9170 *ar) basic |= (vif->bss_conf.basic_rates & 0xff0) << 4; rcu_read_unlock(); - if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) + if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ) mandatory = 0xff00; /* OFDM 6/9/12/18/24/36/48/54 */ else mandatory = 0xff0f; /* OFDM (6/9../54) + CCK (1/2/5.5/11) */ @@ -304,7 +304,8 @@ int carl9170_set_operating_mode(struct ar9170 *ar) struct ath_common *common = &ar->common; u8 *mac_addr, *bssid; u32 cam_mode = AR9170_MAC_CAM_DEFAULTS; - u32 enc_mode = AR9170_MAC_ENCRYPTION_DEFAULTS; + u32 enc_mode = AR9170_MAC_ENCRYPTION_DEFAULTS | + AR9170_MAC_ENCRYPTION_MGMT_RX_SOFTWARE; u32 rx_ctrl = AR9170_MAC_RX_CTRL_DEAGG | AR9170_MAC_RX_CTRL_SHORT_FILTER; u32 sniffer = AR9170_MAC_SNIFFER_DEFAULTS; @@ -318,10 +319,10 @@ int carl9170_set_operating_mode(struct ar9170 *ar) bssid = common->curbssid; switch (vif->type) { - case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_ADHOC: cam_mode |= AR9170_MAC_CAM_IBSS; break; + case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: cam_mode |= AR9170_MAC_CAM_AP; @@ -342,7 +343,24 @@ int carl9170_set_operating_mode(struct ar9170 *ar) break; } } else { - mac_addr = NULL; + /* + * Enable monitor mode + * + * rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER; + * sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC; + * + * When the hardware is in SNIFFER_PROMISC mode, + * it generates spurious ACKs for every incoming + * frame. This confuses every peer in the + * vicinity and the network throughput will suffer + * badly. + * + * Hence, the hardware will be put into station + * mode and just the rx filters are disabled. + */ + cam_mode |= AR9170_MAC_CAM_STA; + rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST; + mac_addr = common->macaddr; bssid = NULL; } rcu_read_unlock(); @@ -354,8 +372,6 @@ int carl9170_set_operating_mode(struct ar9170 *ar) enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE; if (ar->sniffer_enabled) { - rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER; - sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC; enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE; } @@ -485,3 +501,38 @@ int carl9170_disable_key(struct ar9170 *ar, const u8 id) return carl9170_exec_cmd(ar, CARL9170_CMD_DKEY, sizeof(key), (u8 *)&key, 0, NULL); } + +int carl9170_set_mac_tpc(struct ar9170 *ar, struct ieee80211_channel *channel) +{ + unsigned int power, chains; + + if (ar->eeprom.tx_mask != 1) + chains = AR9170_TX_PHY_TXCHAIN_2; + else + chains = AR9170_TX_PHY_TXCHAIN_1; + + switch (channel->band) { + case IEEE80211_BAND_2GHZ: + power = ar->power_2G_ofdm[0] & 0x3f; + break; + case IEEE80211_BAND_5GHZ: + power = ar->power_5G_leg[0] & 0x3f; + break; + default: + BUG_ON(1); + } + + power = min_t(unsigned int, power, ar->hw->conf.power_level * 2); + + carl9170_regwrite_begin(ar); + carl9170_regwrite(AR9170_MAC_REG_ACK_TPC, + 0x3c1e | power << 20 | chains << 26); + carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_TPC, + power << 5 | chains << 11 | + power << 21 | chains << 27); + carl9170_regwrite(AR9170_MAC_REG_CFEND_QOSNULL_TPC, + power << 5 | chains << 11 | + power << 21 | chains << 27); + carl9170_regwrite_finish(); + return carl9170_regwrite_result(); +} diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index db774212161..f8ded84b7be 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -37,7 +37,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/etherdevice.h> @@ -358,8 +357,13 @@ static int carl9170_op_start(struct ieee80211_hw *hw) ar->ps.last_action = jiffies; ar->ps.last_slept = jiffies; ar->erp_mode = CARL9170_ERP_AUTO; - ar->rx_software_decryption = false; - ar->disable_offload = false; + + /* Set "disable hw crypto offload" whenever the module parameter + * nohwcrypt is true or if the firmware does not support it. + */ + ar->disable_offload = modparam_nohwcrypt | + ar->fw.disable_offload_fw; + ar->rx_software_decryption = ar->disable_offload; for (i = 0; i < ar->hw->queues; i++) { ar->queue_stop_timeout[i] = jiffies; @@ -465,27 +469,26 @@ static void carl9170_restart_work(struct work_struct *work) { struct ar9170 *ar = container_of(work, struct ar9170, restart_work); - int err; + int err = -EIO; ar->usedkeys = 0; ar->filter_state = 0; carl9170_cancel_worker(ar); mutex_lock(&ar->mutex); - err = carl9170_usb_restart(ar); - if (net_ratelimit()) { - if (err) { - dev_err(&ar->udev->dev, "Failed to restart device " - " (%d).\n", err); - } else { - dev_info(&ar->udev->dev, "device restarted " - "successfully.\n"); + if (!ar->force_usb_reset) { + err = carl9170_usb_restart(ar); + if (net_ratelimit()) { + if (err) + dev_err(&ar->udev->dev, "Failed to restart device (%d).\n", err); + else + dev_info(&ar->udev->dev, "device restarted successfully.\n"); } } - carl9170_zap_queues(ar); mutex_unlock(&ar->mutex); - if (!err) { + + if (!err && !ar->force_usb_reset) { ar->restart_counter++; atomic_set(&ar->pending_restarts, 0); @@ -526,10 +529,10 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r) if (!ar->registered) return; - if (IS_ACCEPTING_CMD(ar) && !ar->needs_full_reset) - ieee80211_queue_work(ar->hw, &ar->restart_work); - else - carl9170_usb_reset(ar); + if (!IS_ACCEPTING_CMD(ar) || ar->needs_full_reset) + ar->force_usb_reset = true; + + ieee80211_queue_work(ar->hw, &ar->restart_work); /* * At this point, the device instance might have vanished/disabled. @@ -566,12 +569,28 @@ static int carl9170_init_interface(struct ar9170 *ar, memcpy(common->macaddr, vif->addr, ETH_ALEN); - if (modparam_nohwcrypt || - ((vif->type != NL80211_IFTYPE_STATION) && - (vif->type != NL80211_IFTYPE_AP))) { - ar->rx_software_decryption = true; - ar->disable_offload = true; - } + /* We have to fall back to software crypto, whenever + * the user choose to participates in an IBSS. HW + * offload for IBSS RSN is not supported by this driver. + * + * NOTE: If the previous main interface has already + * disabled hw crypto offload, we have to keep this + * previous disable_offload setting as it was. + * Altough ideally, we should notify mac80211 and tell + * it to forget about any HW crypto offload for now. + */ + ar->disable_offload |= ((vif->type != NL80211_IFTYPE_STATION) && + (vif->type != NL80211_IFTYPE_AP)); + + /* While the driver supports HW offload in a single + * P2P client configuration, it doesn't support HW + * offload in the favourit, concurrent P2P GO+CLIENT + * configuration. Hence, HW offload will always be + * disabled for P2P. + */ + ar->disable_offload |= vif->p2p; + + ar->rx_software_decryption = ar->disable_offload; err = carl9170_set_operating_mode(ar); return err; @@ -581,7 +600,7 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv; - struct ieee80211_vif *main_vif; + struct ieee80211_vif *main_vif, *old_main = NULL; struct ar9170 *ar = hw->priv; int vif_id = -1, err = 0; @@ -603,6 +622,15 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw, goto init; } + /* Because the AR9170 HW's MAC doesn't provide full support for + * multiple, independent interfaces [of different operation modes]. + * We have to select ONE main interface [main mode of HW], but we + * can have multiple slaves [AKA: entry in the ACK-table]. + * + * The first (from HEAD/TOP) interface in the ar->vif_list is + * always the main intf. All following intfs in this list + * are considered to be slave intfs. + */ main_vif = carl9170_get_main_vif(ar); if (main_vif) { @@ -611,15 +639,29 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw, if (vif->type == NL80211_IFTYPE_STATION) break; + /* P2P GO [master] use-case + * Because the P2P GO station is selected dynamically + * by all participating peers of a WIFI Direct network, + * the driver has be able to change the main interface + * operating mode on the fly. + */ + if (main_vif->p2p && vif->p2p && + vif->type == NL80211_IFTYPE_AP) { + old_main = main_vif; + break; + } + err = -EBUSY; rcu_read_unlock(); goto unlock; + case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: if ((vif->type == NL80211_IFTYPE_STATION) || (vif->type == NL80211_IFTYPE_WDS) || - (vif->type == NL80211_IFTYPE_AP)) + (vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_MESH_POINT)) break; err = -EBUSY; @@ -647,14 +689,41 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw, vif_priv->id = vif_id; vif_priv->enable_beacon = false; ar->vifs++; - list_add_tail_rcu(&vif_priv->list, &ar->vif_list); + if (old_main) { + /* We end up in here, if the main interface is being replaced. + * Put the new main interface at the HEAD of the list and the + * previous inteface will automatically become second in line. + */ + list_add_rcu(&vif_priv->list, &ar->vif_list); + } else { + /* Add new inteface. If the list is empty, it will become the + * main inteface, otherwise it will be slave. + */ + list_add_tail_rcu(&vif_priv->list, &ar->vif_list); + } rcu_assign_pointer(ar->vif_priv[vif_id].vif, vif); init: - if (carl9170_get_main_vif(ar) == vif) { + main_vif = carl9170_get_main_vif(ar); + + if (main_vif == vif) { rcu_assign_pointer(ar->beacon_iter, vif_priv); rcu_read_unlock(); + if (old_main) { + struct carl9170_vif_info *old_main_priv = + (void *) old_main->drv_priv; + /* downgrade old main intf to slave intf. + * NOTE: We are no longer under rcu_read_lock. + * But we are still holding ar->mutex, so the + * vif data [id, addr] is safe. + */ + err = carl9170_mod_virtual_mac(ar, old_main_priv->id, + old_main->addr); + if (err) + goto unlock; + } + err = carl9170_init_interface(ar, vif); if (err) goto unlock; @@ -853,17 +922,15 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed) goto out; } - if (changed & IEEE80211_CONF_CHANGE_POWER) { - /* TODO */ - err = 0; - } - if (changed & IEEE80211_CONF_CHANGE_SMPS) { /* TODO */ err = 0; } if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + enum nl80211_channel_type channel_type = + cfg80211_get_chandef_type(&hw->conf.chandef); + /* adjust slot time for 5 GHz */ err = carl9170_set_slot_time(ar); if (err) @@ -873,8 +940,8 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed) if (err) goto out; - err = carl9170_set_channel(ar, hw->conf.channel, - hw->conf.channel_type, CARL9170_RFI_NONE); + err = carl9170_set_channel(ar, hw->conf.chandef.chan, + channel_type); if (err) goto out; @@ -891,6 +958,12 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed) goto out; } + if (changed & IEEE80211_CONF_CHANGE_POWER) { + err = carl9170_set_mac_tpc(ar, ar->hw->conf.chandef.chan); + if (err) + goto out; + } + out: mutex_unlock(&ar->mutex); return err; @@ -948,6 +1021,9 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw, if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) { u32 rx_filter = 0; + if (!ar->fw.ba_filter) + rx_filter |= CARL9170_RX_FILTER_CTL_OTHER; + if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))) rx_filter |= CARL9170_RX_FILTER_BAD; @@ -1107,9 +1183,7 @@ static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (ar->disable_offload || !vif) return -EOPNOTSUPP; - /* - * We have to fall back to software encryption, whenever - * the user choose to participates in an IBSS or is connected + /* Fall back to software encryption whenever the driver is connected * to more than one network. * * This is very unfortunate, because some machines cannot handle @@ -1143,6 +1217,7 @@ static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, break; case WLAN_CIPHER_SUITE_CCMP: ktype = AR9170_ENC_ALG_AESCCMP; + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; break; default: return -EOPNOTSUPP; @@ -1257,7 +1332,7 @@ static int carl9170_op_sta_add(struct ieee80211_hw *hw, return 0; } - for (i = 0; i < CARL9170_NUM_TID; i++) + for (i = 0; i < ARRAY_SIZE(sta_info->agg); i++) RCU_INIT_POINTER(sta_info->agg[i], NULL); sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); @@ -1281,7 +1356,7 @@ static int carl9170_op_sta_remove(struct ieee80211_hw *hw, sta_info->ht_sta = false; rcu_read_lock(); - for (i = 0; i < CARL9170_NUM_TID; i++) { + for (i = 0; i < ARRAY_SIZE(sta_info->agg); i++) { struct carl9170_sta_tid *tid_info; tid_info = rcu_dereference(sta_info->agg[i]); @@ -1372,6 +1447,8 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, tid_info->state = CARL9170_TID_STATE_PROGRESS; tid_info->tid = tid; tid_info->max = sta_info->ampdu_max_len; + tid_info->sta = sta; + tid_info->vif = vif; INIT_LIST_HEAD(&tid_info->list); INIT_LIST_HEAD(&tid_info->tmp_list); @@ -1388,7 +1465,9 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; - case IEEE80211_AMPDU_TX_STOP: + case IEEE80211_AMPDU_TX_STOP_CONT: + case IEEE80211_AMPDU_TX_STOP_FLUSH: + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: rcu_read_lock(); tid_info = rcu_dereference(sta_info->agg[tid]); if (tid_info) { @@ -1628,7 +1707,9 @@ found: return 0; } -static void carl9170_op_flush(struct ieee80211_hw *hw, bool drop) +static void carl9170_op_flush(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u32 queues, bool drop) { struct ar9170 *ar = hw->priv; unsigned int vid; @@ -1752,6 +1833,9 @@ void *carl9170_alloc(size_t priv_size) for (i = 0; i < ar->hw->queues; i++) { skb_queue_head_init(&ar->tx_status[i]); skb_queue_head_init(&ar->tx_pending[i]); + + INIT_LIST_HEAD(&ar->bar_list[i]); + spin_lock_init(&ar->bar_list_lock[i]); } INIT_WORK(&ar->ps_work, carl9170_ps_work); INIT_WORK(&ar->ping_work, carl9170_ping_work); @@ -1771,11 +1855,14 @@ void *carl9170_alloc(size_t priv_size) hw->wiphy->interface_modes = 0; hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_MFP_CAPABLE | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_NEED_DTIM_PERIOD | - IEEE80211_HW_SIGNAL_DBM; + IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | + IEEE80211_HW_SUPPORTS_RC_TABLE | + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_HT_CCK_RATES; if (!modparam_noht) { /* @@ -1795,7 +1882,6 @@ void *carl9170_alloc(size_t priv_size) for (i = 0; i < ARRAY_SIZE(ar->noise); i++) ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ - hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; return ar; err_nomem: @@ -1883,18 +1969,6 @@ static int carl9170_parse_eeprom(struct ar9170 *ar) return -ENOMEM; ar->num_channels = chans; - /* - * I measured this, a bandswitch takes roughly - * 135 ms and a frequency switch about 80. - * - * FIXME: measure these values again once EEPROM settings - * are used, that will influence them! - */ - if (bands == 2) - ar->hw->channel_change_time = 135 * 1000; - else - ar->hw->channel_change_time = 80 * 1000; - regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); /* second part of wiphy init */ @@ -1903,13 +1977,13 @@ static int carl9170_parse_eeprom(struct ar9170 *ar) return 0; } -static int carl9170_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request) +static void carl9170_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct ar9170 *ar = hw->priv; - return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory); + ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory); } int carl9170_register(struct ar9170 *ar) @@ -1931,10 +2005,6 @@ int carl9170_register(struct ar9170 *ar) if (err) return err; - err = carl9170_fw_fix_eeprom(ar); - if (err) - return err; - err = carl9170_parse_eeprom(ar); if (err) return err; diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index 472efc7e340..ab4ee7d39ad 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c @@ -1331,7 +1331,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw) * CTL_ETSI for 2GHz and CTL_FCC for 5GHz. */ ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory, - ar->hw->conf.channel->band); + ar->hw->conf.chandef.chan->band); /* ctl group not found - either invalid band (NO_CTL) or ww roaming */ if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL) @@ -1341,7 +1341,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw) /* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */ return; - if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { + if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) { modes = mode_list_2ghz; nr_modes = ARRAY_SIZE(mode_list_2ghz); } else { @@ -1426,15 +1426,15 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw) #undef EDGES } -static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq, - enum carl9170_bw bw) +static void carl9170_set_power_cal(struct ar9170 *ar, u32 freq, + enum carl9170_bw bw) { struct ar9170_calibration_target_power_legacy *ctpl; struct ar9170_calibration_target_power_ht *ctph; u8 *ctpres; int ntargets; int idx, i, n; - u8 ackpower, ackchains, f; + u8 f; u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS]; if (freq < 3000) @@ -1523,32 +1523,6 @@ static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq, /* calc. conformance test limits and apply to ar->power*[] */ carl9170_calc_ctl(ar, freq, bw); - - /* set ACK/CTS TX power */ - carl9170_regwrite_begin(ar); - - if (ar->eeprom.tx_mask != 1) - ackchains = AR9170_TX_PHY_TXCHAIN_2; - else - ackchains = AR9170_TX_PHY_TXCHAIN_1; - - if (freq < 3000) - ackpower = ar->power_2G_ofdm[0] & 0x3f; - else - ackpower = ar->power_5G_leg[0] & 0x3f; - - carl9170_regwrite(AR9170_MAC_REG_ACK_TPC, - 0x3c1e | ackpower << 20 | ackchains << 26); - carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_TPC, - ackpower << 5 | ackchains << 11 | - ackpower << 21 | ackchains << 27); - - carl9170_regwrite(AR9170_MAC_REG_CFEND_QOSNULL_TPC, - ackpower << 5 | ackchains << 11 | - ackpower << 21 | ackchains << 27); - - carl9170_regwrite_finish(); - return carl9170_regwrite_result(); } int carl9170_get_noisefloor(struct ar9170 *ar) @@ -1595,16 +1569,14 @@ static enum carl9170_bw nl80211_to_carl(enum nl80211_channel_type type) } int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, - enum nl80211_channel_type _bw, - enum carl9170_rf_init_mode rfi) + enum nl80211_channel_type _bw) { const struct carl9170_phy_freq_params *freqpar; struct carl9170_rf_init_result rf_res; struct carl9170_rf_init rf; - u32 cmd, tmp, offs = 0, new_ht = 0; + u32 tmp, offs = 0, new_ht = 0; int err; enum carl9170_bw bw; - bool warm_reset; struct ieee80211_channel *old_channel = NULL; bw = nl80211_to_carl(_bw); @@ -1618,51 +1590,27 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, /* may be NULL at first setup */ if (ar->channel) { old_channel = ar->channel; - warm_reset = (old_channel->band != channel->band) || - (old_channel->center_freq == - channel->center_freq) || - (ar->ht_settings != new_ht); - ar->channel = NULL; - } else { - warm_reset = true; } - /* HW workaround */ - if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] && - channel->center_freq <= 2417) - warm_reset = true; - - if (rfi != CARL9170_RFI_NONE || warm_reset) { - u32 val; - - if (rfi == CARL9170_RFI_COLD) - val = AR9170_PWR_RESET_BB_COLD_RESET; - else - val = AR9170_PWR_RESET_BB_WARM_RESET; - - /* warm/cold reset BB/ADDA */ - err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, val); - if (err) - return err; - - err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0); - if (err) - return err; + /* cold reset BB/ADDA */ + err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, + AR9170_PWR_RESET_BB_COLD_RESET); + if (err) + return err; - err = carl9170_init_phy(ar, channel->band); - if (err) - return err; + err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0); + if (err) + return err; - err = carl9170_init_rf_banks_0_7(ar, - channel->band == IEEE80211_BAND_5GHZ); - if (err) - return err; + err = carl9170_init_phy(ar, channel->band); + if (err) + return err; - cmd = CARL9170_CMD_RF_INIT; - } else { - cmd = CARL9170_CMD_FREQUENCY; - } + err = carl9170_init_rf_banks_0_7(ar, + channel->band == IEEE80211_BAND_5GHZ); + if (err) + return err; err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL); if (err) @@ -1674,8 +1622,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, return err; err = carl9170_init_rf_bank4_pwr(ar, - channel->band == IEEE80211_BAND_5GHZ, - channel->center_freq, bw); + channel->band == IEEE80211_BAND_5GHZ, + channel->center_freq, bw); if (err) return err; @@ -1712,7 +1660,9 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, if (err) return err; - err = carl9170_set_power_cal(ar, channel->center_freq, bw); + carl9170_set_power_cal(ar, channel->center_freq, bw); + + err = carl9170_set_mac_tpc(ar, channel); if (err) return err; @@ -1727,13 +1677,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, rf.delta_slope_coeff_man = cpu_to_le32(freqpar->coeff_man); rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi); rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi); - - if (rfi != CARL9170_RFI_NONE) - rf.finiteLoopCount = cpu_to_le32(2000); - else - rf.finiteLoopCount = cpu_to_le32(1000); - - err = carl9170_exec_cmd(ar, cmd, sizeof(rf), &rf, + rf.finiteLoopCount = cpu_to_le32(2000); + err = carl9170_exec_cmd(ar, CARL9170_CMD_RF_INIT, sizeof(rf), &rf, sizeof(rf_res), &rf_res); if (err) return err; @@ -1748,9 +1693,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, old_channel->center_freq : -1, channel->center_freq, err); - if ((rfi == CARL9170_RFI_COLD) || (ar->chan_fail > 3)) { - /* - * We have tried very hard to change to _another_ + if (ar->chan_fail > 3) { + /* We have tried very hard to change to _another_ * channel and we've failed to do so! * Chances are that the PHY/RF is no longer * operable (due to corruptions/fatal events/bugs?) @@ -1760,8 +1704,7 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, return 0; } - err = carl9170_set_channel(ar, channel, _bw, - CARL9170_RFI_COLD); + err = carl9170_set_channel(ar, channel, _bw); if (err) return err; } else { diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index dc99030ea8b..924135b8e57 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c @@ -37,7 +37,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/etherdevice.h> @@ -161,12 +160,9 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer) void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) { - struct carl9170_rsp *cmd = (void *) buf; + struct carl9170_rsp *cmd = buf; struct ieee80211_vif *vif; - if (carl9170_check_sequence(ar, cmd->hdr.seq)) - return; - if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) { if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG)) carl9170_cmd_callback(ar, len, buf); @@ -206,6 +202,7 @@ void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) case NL80211_IFTYPE_AP: case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: carl9170_update_beacon(ar, true); break; @@ -520,8 +517,9 @@ static u8 *carl9170_find_ie(u8 *data, unsigned int len, u8 ie) */ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) { - struct ieee80211_hdr *hdr = (void *) data; + struct ieee80211_hdr *hdr = data; struct ieee80211_tim_ie *tim_ie; + struct ath_common *common = &ar->common; u8 *tim; u8 tim_len; bool cam; @@ -529,17 +527,13 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) if (likely(!(ar->hw->conf.flags & IEEE80211_CONF_PS))) return; - /* check if this really is a beacon */ - if (!ieee80211_is_beacon(hdr->frame_control)) - return; - /* min. beacon length + FCS_LEN */ if (len <= 40 + FCS_LEN) return; + /* check if this really is a beacon */ /* and only beacons from the associated BSSID, please */ - if (compare_ether_addr(hdr->addr3, ar->common.curbssid) || - !ar->common.curaid) + if (!ath_is_mybeacon(common, hdr) || !common->curaid) return; ar->ps.last_beacon = jiffies; @@ -576,7 +570,55 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) } } -static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms) +static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len) +{ + struct ieee80211_bar *bar = data; + struct carl9170_bar_list_entry *entry; + unsigned int queue; + + if (likely(!ieee80211_is_back(bar->frame_control))) + return; + + if (len <= sizeof(*bar) + FCS_LEN) + return; + + queue = TID_TO_WME_AC(((le16_to_cpu(bar->control) & + IEEE80211_BAR_CTRL_TID_INFO_MASK) >> + IEEE80211_BAR_CTRL_TID_INFO_SHIFT) & 7); + + rcu_read_lock(); + list_for_each_entry_rcu(entry, &ar->bar_list[queue], list) { + struct sk_buff *entry_skb = entry->skb; + struct _carl9170_tx_superframe *super = (void *)entry_skb->data; + struct ieee80211_bar *entry_bar = (void *)super->frame_data; + +#define TID_CHECK(a, b) ( \ + ((a) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)) == \ + ((b) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK))) \ + + if (bar->start_seq_num == entry_bar->start_seq_num && + TID_CHECK(bar->control, entry_bar->control) && + ether_addr_equal_64bits(bar->ra, entry_bar->ta) && + ether_addr_equal_64bits(bar->ta, entry_bar->ra)) { + struct ieee80211_tx_info *tx_info; + + tx_info = IEEE80211_SKB_CB(entry_skb); + tx_info->flags |= IEEE80211_TX_STAT_ACK; + + spin_lock_bh(&ar->bar_list_lock[queue]); + list_del_rcu(&entry->list); + spin_unlock_bh(&ar->bar_list_lock[queue]); + kfree_rcu(entry, head); + break; + } + } + rcu_read_unlock(); + +#undef TID_CHECK +} + +static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms, + struct ieee80211_rx_status *rx_status) { __le16 fc; @@ -589,6 +631,9 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms) return true; } + rx_status->flag |= RX_FLAG_AMPDU_DETAILS | RX_FLAG_AMPDU_LAST_KNOWN; + rx_status->ampdu_reference = ar->ampdu_ref; + /* * "802.11n - 7.4a.3 A-MPDU contents" describes in which contexts * certain frame types can be part of an aMPDU. @@ -611,6 +656,35 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms) return false; } +static int carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len, + struct ieee80211_rx_status *status) +{ + struct sk_buff *skb; + + /* (driver) frame trap handler + * + * Because power-saving mode handing has to be implemented by + * the driver/firmware. We have to check each incoming beacon + * from the associated AP, if there's new data for us (either + * broadcast/multicast or unicast) we have to react quickly. + * + * So, if you have you want to add additional frame trap + * handlers, this would be the perfect place! + */ + + carl9170_ps_beacon(ar, buf, len); + + carl9170_ba_check(ar, buf, len); + + skb = carl9170_rx_copy_data(buf, len); + if (!skb) + return -ENOMEM; + + memcpy(IEEE80211_SKB_RXCB(skb), status, sizeof(*status)); + ieee80211_rx(ar->hw, skb); + return 0; +} + /* * If the frame alignment is right (or the kernel has * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there @@ -620,14 +694,12 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms) * mode, and we need to observe the proper ordering, * this is non-trivial. */ - -static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) +static void carl9170_rx_untie_data(struct ar9170 *ar, u8 *buf, int len) { struct ar9170_rx_head *head; struct ar9170_rx_macstatus *mac; struct ar9170_rx_phystatus *phy = NULL; struct ieee80211_rx_status status; - struct sk_buff *skb; int mpdu_len; u8 mac_status; @@ -637,12 +709,15 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) if (unlikely(len < sizeof(*mac))) goto drop; + memset(&status, 0, sizeof(status)); + mpdu_len = len - sizeof(*mac); mac = (void *)(buf + mpdu_len); mac_status = mac->status; switch (mac_status & AR9170_RX_STATUS_MPDU) { case AR9170_RX_STATUS_MPDU_FIRST: + ar->ampdu_ref++; /* Aggregated MPDUs start with an PLCP header */ if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) { head = (void *) buf; @@ -673,12 +748,13 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) break; case AR9170_RX_STATUS_MPDU_LAST: + status.flag |= RX_FLAG_AMPDU_IS_LAST; + /* * The last frame of an A-MPDU has an extra tail * which does contain the phy status of the whole * aggregate. */ - if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) { mpdu_len -= sizeof(struct ar9170_rx_phystatus); phy = (void *)(buf + mpdu_len); @@ -726,26 +802,21 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) if (unlikely(mpdu_len < (2 + 2 + ETH_ALEN + FCS_LEN))) goto drop; - memset(&status, 0, sizeof(status)); if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status))) goto drop; - if (!carl9170_ampdu_check(ar, buf, mac_status)) + if (!carl9170_ampdu_check(ar, buf, mac_status, &status)) goto drop; if (phy) carl9170_rx_phy_status(ar, phy, &status); + else + status.flag |= RX_FLAG_NO_SIGNAL_VAL; - carl9170_ps_beacon(ar, buf, mpdu_len); - - skb = carl9170_rx_copy_data(buf, mpdu_len); - if (!skb) + if (carl9170_handle_mpdu(ar, buf, mpdu_len, &status)) goto drop; - memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - ieee80211_rx(ar->hw, skb); return; - drop: ar->rx_dropped++; } @@ -763,6 +834,9 @@ static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf, if (unlikely(i > resplen)) break; + if (carl9170_check_sequence(ar, cmd->hdr.seq)) + break; + carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4); } @@ -794,7 +868,7 @@ static void __carl9170_rx(struct ar9170 *ar, u8 *buf, unsigned int len) if (i == 12) carl9170_rx_untie_cmds(ar, buf, len); else - carl9170_handle_mpdu(ar, buf, len); + carl9170_rx_untie_data(ar, buf, len); } static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index bbc813dee98..4cadfd48ffd 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c @@ -37,7 +37,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/etherdevice.h> @@ -277,11 +276,11 @@ static void carl9170_tx_release(struct kref *ref) return; BUILD_BUG_ON( - offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23); + offsetof(struct ieee80211_tx_info, status.ack_signal) != 20); - memset(&txinfo->status.ampdu_ack_len, 0, + memset(&txinfo->status.ack_signal, 0, sizeof(struct ieee80211_tx_info) - - offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); + offsetof(struct ieee80211_tx_info, status.ack_signal)); if (atomic_read(&ar->tx_total_queued)) ar->tx_schedule = true; @@ -387,8 +386,7 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, u8 tid; if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || - txinfo->flags & IEEE80211_TX_CTL_INJECTED || - (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) + txinfo->flags & IEEE80211_TX_CTL_INJECTED) return; rcu_read_lock(); @@ -436,6 +434,45 @@ out_rcu: rcu_read_unlock(); } +static void carl9170_tx_bar_status(struct ar9170 *ar, struct sk_buff *skb, + struct ieee80211_tx_info *tx_info) +{ + struct _carl9170_tx_superframe *super = (void *) skb->data; + struct ieee80211_bar *bar = (void *) super->frame_data; + + /* + * Unlike all other frames, the status report for BARs does + * not directly come from the hardware as it is incapable of + * matching a BA to a previously send BAR. + * Instead the RX-path will scan for incoming BAs and set the + * IEEE80211_TX_STAT_ACK if it sees one that was likely + * caused by a BAR from us. + */ + + if (unlikely(ieee80211_is_back_req(bar->frame_control)) && + !(tx_info->flags & IEEE80211_TX_STAT_ACK)) { + struct carl9170_bar_list_entry *entry; + int queue = skb_get_queue_mapping(skb); + + rcu_read_lock(); + list_for_each_entry_rcu(entry, &ar->bar_list[queue], list) { + if (entry->skb == skb) { + spin_lock_bh(&ar->bar_list_lock[queue]); + list_del_rcu(&entry->list); + spin_unlock_bh(&ar->bar_list_lock[queue]); + kfree_rcu(entry, head); + goto out; + } + } + + WARN(1, "bar not found in %d - ra:%pM ta:%pM c:%x ssn:%x\n", + queue, bar->ra, bar->ta, bar->control, + bar->start_seq_num); +out: + rcu_read_unlock(); + } +} + void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, const bool success) { @@ -445,6 +482,8 @@ void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, txinfo = IEEE80211_SKB_CB(skb); + carl9170_tx_bar_status(ar, skb, txinfo); + if (success) txinfo->flags |= IEEE80211_TX_STAT_ACK; else @@ -585,7 +624,7 @@ static void carl9170_tx_ampdu_timeout(struct ar9170 *ar) msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT))) goto unlock; - sta = __carl9170_get_tx_sta(ar, skb); + sta = iter->sta; if (WARN_ON(!sta)) goto unlock; @@ -719,6 +758,8 @@ static void carl9170_tx_rate_tpc_chains(struct ar9170 *ar, else *chains = AR9170_TX_PHY_TXCHAIN_2; } + + *tpc = min_t(unsigned int, *tpc, ar->hw->conf.power_level * 2); } static __le32 carl9170_tx_physet(struct ar9170 *ar, @@ -824,20 +865,105 @@ static bool carl9170_tx_cts_check(struct ar9170 *ar, return false; } -static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) +static void carl9170_tx_get_rates(struct ar9170 *ar, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct sk_buff *skb) +{ + struct ieee80211_tx_info *info; + + BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES); + BUILD_BUG_ON(IEEE80211_TX_MAX_RATES > IEEE80211_TX_RATE_TABLE_SIZE); + + info = IEEE80211_SKB_CB(skb); + + ieee80211_get_tx_rates(vif, sta, skb, + info->control.rates, + IEEE80211_TX_MAX_RATES); +} + +static void carl9170_tx_apply_rateset(struct ar9170 *ar, + struct ieee80211_tx_info *sinfo, + struct sk_buff *skb) +{ + struct ieee80211_tx_rate *txrate; + struct ieee80211_tx_info *info; + struct _carl9170_tx_superframe *txc = (void *) skb->data; + int i; + bool ampdu; + bool no_ack; + + info = IEEE80211_SKB_CB(skb); + ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU); + no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK); + + /* Set the rate control probe flag for all (sub-) frames. + * This is because the TX_STATS_AMPDU flag is only set on + * the last frame, so it has to be inherited. + */ + info->flags |= (sinfo->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); + + /* NOTE: For the first rate, the ERP & AMPDU flags are directly + * taken from mac_control. For all fallback rate, the firmware + * updates the mac_control flags from the rate info field. + */ + for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { + __le32 phy_set; + + txrate = &sinfo->control.rates[i]; + if (txrate->idx < 0) + break; + + phy_set = carl9170_tx_physet(ar, info, txrate); + if (i == 0) { + __le16 mac_tmp = cpu_to_le16(0); + + /* first rate - part of the hw's frame header */ + txc->f.phy_control = phy_set; + + if (ampdu && txrate->flags & IEEE80211_TX_RC_MCS) + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); + + if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); + else if (carl9170_tx_cts_check(ar, txrate)) + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); + + txc->f.mac_control |= mac_tmp; + } else { + /* fallback rates are stored in the firmware's + * retry rate set array. + */ + txc->s.rr[i - 1] = phy_set; + } + + SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i], + txrate->count); + + if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) + txc->s.ri[i] |= (AR9170_TX_MAC_PROT_RTS << + CARL9170_TX_SUPER_RI_ERP_PROT_S); + else if (carl9170_tx_cts_check(ar, txrate)) + txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << + CARL9170_TX_SUPER_RI_ERP_PROT_S); + + if (ampdu && (txrate->flags & IEEE80211_TX_RC_MCS)) + txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU; + } +} + +static int carl9170_tx_prepare(struct ar9170 *ar, + struct ieee80211_sta *sta, + struct sk_buff *skb) { struct ieee80211_hdr *hdr; struct _carl9170_tx_superframe *txc; struct carl9170_vif_info *cvif; struct ieee80211_tx_info *info; - struct ieee80211_tx_rate *txrate; - struct ieee80211_sta *sta; struct carl9170_tx_info *arinfo; unsigned int hw_queue; - int i; __le16 mac_tmp; u16 len; - bool ampdu, no_ack; BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); BUILD_BUG_ON(sizeof(struct _carl9170_tx_superdesc) != @@ -846,8 +972,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) BUILD_BUG_ON(sizeof(struct _ar9170_tx_hwdesc) != AR9170_TX_HWDESC_LEN); - BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES); - BUILD_BUG_ON(AR9170_MAX_VIRTUAL_MAC > ((CARL9170_TX_SUPER_MISC_VIF_ID >> CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1)); @@ -867,8 +991,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) else cvif = NULL; - sta = info->control.sta; - txc = (void *)skb_push(skb, sizeof(*txc)); memset(txc, 0, sizeof(*txc)); @@ -891,8 +1013,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) & AR9170_TX_MAC_QOS); - no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK); - if (unlikely(no_ack)) + if (unlikely(info->flags & IEEE80211_TX_CTL_NO_ACK)) mac_tmp |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); if (info->control.hw_key) { @@ -913,8 +1034,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) } } - ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU); - if (ampdu) { + if (info->flags & IEEE80211_TX_CTL_AMPDU) { unsigned int density, factor; if (unlikely(!sta || !cvif)) @@ -939,67 +1059,11 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, txc->s.ampdu_settings, factor); - - for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { - txrate = &info->control.rates[i]; - if (txrate->idx >= 0) { - txc->s.ri[i] = - CARL9170_TX_SUPER_RI_AMPDU; - - if (WARN_ON(!(txrate->flags & - IEEE80211_TX_RC_MCS))) { - /* - * Not sure if it's even possible - * to aggregate non-ht rates with - * this HW. - */ - goto err_out; - } - continue; - } - - txrate->idx = 0; - txrate->count = ar->hw->max_rate_tries; - } - - mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); } - /* - * NOTE: For the first rate, the ERP & AMPDU flags are directly - * taken from mac_control. For all fallback rate, the firmware - * updates the mac_control flags from the rate info field. - */ - for (i = 1; i < CARL9170_TX_MAX_RATES; i++) { - txrate = &info->control.rates[i]; - if (txrate->idx < 0) - break; - - SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i], - txrate->count); - - if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) - txc->s.ri[i] |= (AR9170_TX_MAC_PROT_RTS << - CARL9170_TX_SUPER_RI_ERP_PROT_S); - else if (carl9170_tx_cts_check(ar, txrate)) - txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << - CARL9170_TX_SUPER_RI_ERP_PROT_S); - - txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate); - } - - txrate = &info->control.rates[0]; - SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count); - - if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) - mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); - else if (carl9170_tx_cts_check(ar, txrate)) - mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); - txc->s.len = cpu_to_le16(skb->len); txc->f.length = cpu_to_le16(len + FCS_LEN); txc->f.mac_control = mac_tmp; - txc->f.phy_control = carl9170_tx_physet(ar, info, txrate); arinfo = (void *)info->rate_driver_data; arinfo->timeout = jiffies; @@ -1057,31 +1121,12 @@ static void carl9170_set_ampdu_params(struct ar9170 *ar, struct sk_buff *skb) } } -static bool carl9170_tx_rate_check(struct ar9170 *ar, struct sk_buff *_dest, - struct sk_buff *_src) -{ - struct _carl9170_tx_superframe *dest, *src; - - dest = (void *) _dest->data; - src = (void *) _src->data; - - /* - * The mac80211 rate control algorithm expects that all MPDUs in - * an AMPDU share the same tx vectors. - * This is not really obvious right now, because the hardware - * does the AMPDU setup according to its own rulebook. - * Our nicely assembled, strictly monotonic increasing mpdu - * chains will be broken up, mashed back together... - */ - - return (dest->f.phy_control == src->f.phy_control); -} - static void carl9170_tx_ampdu(struct ar9170 *ar) { struct sk_buff_head agg; struct carl9170_sta_tid *tid_info; struct sk_buff *skb, *first; + struct ieee80211_tx_info *tx_info_first; unsigned int i = 0, done_ampdus = 0; u16 seq, queue, tmpssn; @@ -1127,6 +1172,7 @@ retry: goto processed; } + tx_info_first = NULL; while ((skb = skb_peek(&tid_info->queue))) { /* strict 0, 1, ..., n - 1, n frame sequence order */ if (unlikely(carl9170_get_seq(skb) != seq)) @@ -1137,8 +1183,13 @@ retry: (tid_info->max - 1))) break; - if (!carl9170_tx_rate_check(ar, skb, first)) - break; + if (!tx_info_first) { + carl9170_tx_get_rates(ar, tid_info->vif, + tid_info->sta, first); + tx_info_first = IEEE80211_SKB_CB(first); + } + + carl9170_tx_apply_rateset(ar, tx_info_first, skb); atomic_inc(&ar->tx_ampdu_upload); tid_info->snx = seq = SEQ_NEXT(seq); @@ -1153,8 +1204,7 @@ retry: if (skb_queue_empty(&tid_info->queue) || carl9170_get_seq(skb_peek(&tid_info->queue)) != tid_info->snx) { - /* - * stop TID, if A-MPDU frames are still missing, + /* stop TID, if A-MPDU frames are still missing, * or whenever the queue is empty. */ @@ -1245,7 +1295,7 @@ static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb) tx_info = IEEE80211_SKB_CB(skb); if (unlikely(sta_info->sleeping) && - !(tx_info->flags & (IEEE80211_TX_CTL_POLL_RESPONSE | + !(tx_info->flags & (IEEE80211_TX_CTL_NO_PS_BUFFER | IEEE80211_TX_CTL_CLEAR_PS_FILT))) { rcu_read_unlock(); @@ -1263,6 +1313,26 @@ out_rcu: return false; } +static void carl9170_bar_check(struct ar9170 *ar, struct sk_buff *skb) +{ + struct _carl9170_tx_superframe *super = (void *) skb->data; + struct ieee80211_bar *bar = (void *) super->frame_data; + + if (unlikely(ieee80211_is_back_req(bar->frame_control)) && + skb->len >= sizeof(struct ieee80211_bar)) { + struct carl9170_bar_list_entry *entry; + unsigned int queue = skb_get_queue_mapping(skb); + + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); + if (!WARN_ON_ONCE(!entry)) { + entry->skb = skb; + spin_lock_bh(&ar->bar_list_lock[queue]); + list_add_tail_rcu(&entry->list, &ar->bar_list[queue]); + spin_unlock_bh(&ar->bar_list_lock[queue]); + } + } +} + static void carl9170_tx(struct ar9170 *ar) { struct sk_buff *skb; @@ -1285,6 +1355,8 @@ static void carl9170_tx(struct ar9170 *ar) if (unlikely(carl9170_tx_ps_drop(ar, skb))) continue; + carl9170_bar_check(ar, skb); + atomic_inc(&ar->tx_total_pending); q = __carl9170_get_queue(ar, i); @@ -1317,9 +1389,9 @@ static void carl9170_tx(struct ar9170 *ar) } static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, - struct ieee80211_sta *sta, struct sk_buff *skb) + struct ieee80211_sta *sta, struct sk_buff *skb, + struct ieee80211_tx_info *txinfo) { - struct _carl9170_tx_superframe *super = (void *) skb->data; struct carl9170_sta_info *sta_info; struct carl9170_sta_tid *agg; struct sk_buff *iter; @@ -1386,26 +1458,29 @@ err_unlock: err_unlock_rcu: rcu_read_unlock(); - super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR); + txinfo->flags &= ~IEEE80211_TX_CTL_AMPDU; carl9170_tx_status(ar, skb, false); ar->tx_dropped++; return false; } -void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +void carl9170_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct ar9170 *ar = hw->priv; struct ieee80211_tx_info *info; - struct ieee80211_sta *sta; + struct ieee80211_sta *sta = control->sta; + struct ieee80211_vif *vif; bool run; if (unlikely(!IS_STARTED(ar))) goto err_free; info = IEEE80211_SKB_CB(skb); - sta = info->control.sta; + vif = info->control.vif; - if (unlikely(carl9170_tx_prepare(ar, skb))) + if (unlikely(carl9170_tx_prepare(ar, sta, skb))) goto err_free; carl9170_tx_accounting(ar, skb); @@ -1420,13 +1495,22 @@ void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) } if (info->flags & IEEE80211_TX_CTL_AMPDU) { - run = carl9170_tx_ampdu_queue(ar, sta, skb); + /* to static code analyzers and reviewers: + * mac80211 guarantees that a valid "sta" + * reference is present, if a frame is to + * be part of an ampdu. Hence any extra + * sta == NULL checks are redundant in this + * special case. + */ + run = carl9170_tx_ampdu_queue(ar, sta, skb, info); if (run) carl9170_tx_ampdu(ar); } else { unsigned int queue = skb_get_queue_mapping(skb); + carl9170_tx_get_rates(ar, vif, sta, skb); + carl9170_tx_apply_rateset(ar, info, skb); skb_queue_tail(&ar->tx_pending[queue], skb); } @@ -1448,35 +1532,92 @@ void carl9170_tx_scheduler(struct ar9170 *ar) carl9170_tx(ar); } -int carl9170_update_beacon(struct ar9170 *ar, const bool submit) +/* caller has to take rcu_read_lock */ +static struct carl9170_vif_info *carl9170_pick_beaconing_vif(struct ar9170 *ar) { - struct sk_buff *skb = NULL; struct carl9170_vif_info *cvif; + int i = 1; + + /* The AR9170 hardware has no fancy beacon queue or some + * other scheduling mechanism. So, the driver has to make + * due by setting the two beacon timers (pretbtt and tbtt) + * once and then swapping the beacon address in the HW's + * register file each time the pretbtt fires. + */ + + cvif = rcu_dereference(ar->beacon_iter); + if (ar->vifs > 0 && cvif) { + do { + list_for_each_entry_continue_rcu(cvif, &ar->vif_list, + list) { + if (cvif->active && cvif->enable_beacon) + goto out; + } + } while (ar->beacon_enabled && i--); + } + +out: + rcu_assign_pointer(ar->beacon_iter, cvif); + return cvif; +} + +static bool carl9170_tx_beacon_physet(struct ar9170 *ar, struct sk_buff *skb, + u32 *ht1, u32 *plcp) +{ struct ieee80211_tx_info *txinfo; struct ieee80211_tx_rate *rate; - __le32 *data, *old = NULL; - unsigned int plcp, power, chains; - u32 word, ht1, off, addr, len; - int i = 0, err = 0; + unsigned int power, chains; + bool ht_rate; - rcu_read_lock(); - cvif = rcu_dereference(ar->beacon_iter); -retry: - if (ar->vifs == 0 || !cvif) - goto out_unlock; + txinfo = IEEE80211_SKB_CB(skb); + rate = &txinfo->control.rates[0]; + ht_rate = !!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS); + carl9170_tx_rate_tpc_chains(ar, txinfo, rate, plcp, &power, &chains); + + *ht1 = AR9170_MAC_BCN_HT1_TX_ANT0; + if (chains == AR9170_TX_PHY_TXCHAIN_2) + *ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1; + SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, *ht1, 7); + SET_VAL(AR9170_MAC_BCN_HT1_TPC, *ht1, power); + SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, *ht1, chains); + + if (ht_rate) { + *ht1 |= AR9170_MAC_BCN_HT1_HT_EN; + if (rate->flags & IEEE80211_TX_RC_SHORT_GI) + *plcp |= AR9170_MAC_BCN_HT2_SGI; - list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) { - if (cvif->active && cvif->enable_beacon) - goto found; + if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { + *ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED; + *plcp |= AR9170_MAC_BCN_HT2_BW40; + } else if (rate->flags & IEEE80211_TX_RC_DUP_DATA) { + *ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP; + *plcp |= AR9170_MAC_BCN_HT2_BW40; + } + + SET_VAL(AR9170_MAC_BCN_HT2_LEN, *plcp, skb->len + FCS_LEN); + } else { + if (*plcp <= AR9170_TX_PHY_RATE_CCK_11M) + *plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400; + else + *plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010; } - if (!ar->beacon_enabled || i++) - goto out_unlock; + return ht_rate; +} - goto retry; +int carl9170_update_beacon(struct ar9170 *ar, const bool submit) +{ + struct sk_buff *skb = NULL; + struct carl9170_vif_info *cvif; + __le32 *data, *old = NULL; + u32 word, ht1, plcp, off, addr, len; + int i = 0, err = 0; + bool ht_rate; -found: - rcu_assign_pointer(ar->beacon_iter, cvif); + rcu_read_lock(); + cvif = carl9170_pick_beaconing_vif(ar); + if (!cvif) + goto out_unlock; skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif), NULL, NULL); @@ -1486,7 +1627,6 @@ found: goto err_free; } - txinfo = IEEE80211_SKB_CB(skb); spin_lock_bh(&ar->beacon_lock); data = (__le32 *)skb->data; if (cvif->beacon) @@ -1516,43 +1656,14 @@ found: goto err_unlock; } - ht1 = AR9170_MAC_BCN_HT1_TX_ANT0; - rate = &txinfo->control.rates[0]; - carl9170_tx_rate_tpc_chains(ar, txinfo, rate, &plcp, &power, &chains); - if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS)) { - if (plcp <= AR9170_TX_PHY_RATE_CCK_11M) - plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400; - else - plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010; - } else { - ht1 |= AR9170_MAC_BCN_HT1_HT_EN; - if (rate->flags & IEEE80211_TX_RC_SHORT_GI) - plcp |= AR9170_MAC_BCN_HT2_SGI; - - if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { - ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED; - plcp |= AR9170_MAC_BCN_HT2_BW40; - } - if (rate->flags & IEEE80211_TX_RC_DUP_DATA) { - ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP; - plcp |= AR9170_MAC_BCN_HT2_BW40; - } - - SET_VAL(AR9170_MAC_BCN_HT2_LEN, plcp, skb->len + FCS_LEN); - } - - SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, ht1, 7); - SET_VAL(AR9170_MAC_BCN_HT1_TPC, ht1, power); - SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, ht1, chains); - if (chains == AR9170_TX_PHY_TXCHAIN_2) - ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1; + ht_rate = carl9170_tx_beacon_physet(ar, skb, &ht1, &plcp); carl9170_async_regwrite_begin(ar); carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT1, ht1); - if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS)) - carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp); - else + if (ht_rate) carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT2, plcp); + else + carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp); for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { /* diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c index 89821e4835c..f35c7f30f9a 100644 --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c @@ -295,6 +295,13 @@ static void carl9170_usb_rx_irq_complete(struct urb *urb) goto resubmit; } + /* + * While the carl9170 firmware does not use this EP, the + * firmware loader in the EEPROM unfortunately does. + * Therefore we need to be ready to handle out-of-band + * responses and traps in case the firmware crashed and + * the loader took over again. + */ carl9170_handle_command_response(ar, urb->transfer_buffer, urb->actual_length); @@ -766,7 +773,7 @@ void carl9170_usb_stop(struct ar9170 *ar) complete_all(&ar->cmd_wait); /* This is required to prevent an early completion on _start */ - INIT_COMPLETION(ar->cmd_wait); + reinit_completion(&ar->cmd_wait); /* * Note: @@ -1069,8 +1076,14 @@ static int carl9170_usb_probe(struct usb_interface *intf, carl9170_set_state(ar, CARL9170_STOPPED); - return request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME, + err = request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME, &ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2); + if (err) { + usb_put_dev(udev); + usb_put_dev(udev); + carl9170_free(ar); + } + return err; } static void carl9170_usb_disconnect(struct usb_interface *intf) @@ -1159,6 +1172,7 @@ static struct usb_driver carl9170_driver = { .resume = carl9170_usb_resume, .reset_resume = carl9170_usb_resume, #endif /* CONFIG_PM */ + .disable_hub_initiated_lpm = 1, }; module_usb_driver(carl9170_driver); diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h index e651db85634..2282847d4bb 100644 --- a/drivers/net/wireless/ath/carl9170/version.h +++ b/drivers/net/wireless/ath/carl9170/version.h @@ -1,7 +1,7 @@ #ifndef __CARL9170_SHARED_VERSION_H #define __CARL9170_SHARED_VERSION_H -#define CARL9170FW_VERSION_YEAR 11 -#define CARL9170FW_VERSION_MONTH 8 +#define CARL9170FW_VERSION_YEAR 12 +#define CARL9170FW_VERSION_MONTH 12 #define CARL9170FW_VERSION_DAY 15 -#define CARL9170FW_VERSION_GIT "1.9.4" +#define CARL9170FW_VERSION_GIT "1.9.7" #endif /* __CARL9170_SHARED_VERSION_H */ |
