diff options
author | Kalle Valo | 2017-01-01 20:48:37 +0200 |
---|---|---|
committer | Kalle Valo | 2017-01-01 20:48:37 +0200 |
commit | 50913e32c6cf8f76f5a47365b025e26fcff87595 (patch) | |
tree | 3d850d83c73ba962aba78ed0c5c1876a0363f9a0 | |
parent | ad334bbb07b07e2873942571b0c9f3c34571bd47 (diff) | |
parent | 34c30b0a5e97e3f9e1e166f56654a1261b722611 (diff) |
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for 4.11. Major changes:
ath9k
* cleanup eeprom endian handling
* add airtime fairness scheduling
ath10k
* fix issues for new QCA9377 firmware version
* support dev_coredump() for firmware crash dump
* enable channel 169 on 5 GHz band
27 files changed, 732 insertions, 399 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 749e381edd38..874c2a755c66 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -694,8 +694,11 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) "boot get otp board id result 0x%08x board_id %d chip_id %d\n", result, board_id, chip_id); - if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0) + if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0 || + (board_id == 0)) { + ath10k_warn(ar, "board id is not exist in otp, ignore it\n"); return -EOPNOTSUPP; + } ar->id.bmi_ids_valid = true; ar->id.bmi_board_id = board_id; @@ -1510,6 +1513,7 @@ static int ath10k_init_hw_params(struct ath10k *ar) static void ath10k_core_restart(struct work_struct *work) { struct ath10k *ar = container_of(work, struct ath10k, restart_work); + int ret; set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); @@ -1561,6 +1565,11 @@ static void ath10k_core_restart(struct work_struct *work) } mutex_unlock(&ar->conf_mutex); + + ret = ath10k_debug_fw_devcoredump(ar); + if (ret) + ath10k_warn(ar, "failed to send firmware crash dump via devcoredump: %d", + ret); } static void ath10k_core_set_coverage_class_work(struct work_struct *work) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 09ff8b8a6441..c7664d6569fa 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -46,7 +46,7 @@ #define WMI_READY_TIMEOUT (5 * HZ) #define ATH10K_FLUSH_TIMEOUT_HZ (5 * HZ) #define ATH10K_CONNECTION_LOSS_HZ (3 * HZ) -#define ATH10K_NUM_CHANS 39 +#define ATH10K_NUM_CHANS 40 /* Antenna noise floor */ #define ATH10K_DEFAULT_NOISE_FLOOR -95 diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 82a4c67f3672..e1a70dffc52a 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -21,6 +21,7 @@ #include <linux/utsname.h> #include <linux/crc32.h> #include <linux/firmware.h> +#include <linux/devcoredump.h> #include "core.h" #include "debug.h" @@ -721,7 +722,8 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar) } EXPORT_SYMBOL(ath10k_debug_get_new_fw_crash_data); -static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar) +static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar, + bool mark_read) { struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data; struct ath10k_dump_file_data *dump_data; @@ -790,19 +792,54 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar) sizeof(crash_data->registers)); sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers); - ar->debug.fw_crash_data->crashed_since_read = false; + ar->debug.fw_crash_data->crashed_since_read = !mark_read; spin_unlock_bh(&ar->data_lock); return dump_data; } +int ath10k_debug_fw_devcoredump(struct ath10k *ar) +{ + struct ath10k_dump_file_data *dump; + void *dump_ptr; + u32 dump_len; + + /* To keep the dump file available also for debugfs don't mark the + * file read, only debugfs should do that. + */ + dump = ath10k_build_dump_file(ar, false); + if (!dump) { + ath10k_warn(ar, "no crash dump data found for devcoredump"); + return -ENODATA; + } + + /* Make a copy of the dump file for dev_coredumpv() as during the + * transition period we need to own the original file. Once + * fw_crash_dump debugfs file is removed no need to have a copy + * anymore. + */ + dump_len = le32_to_cpu(dump->len); + dump_ptr = vzalloc(dump_len); + + if (!dump_ptr) + return -ENOMEM; + + memcpy(dump_ptr, dump, dump_len); + + dev_coredumpv(ar->dev, dump_ptr, dump_len, GFP_KERNEL); + + return 0; +} + static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file) { struct ath10k *ar = inode->i_private; struct ath10k_dump_file_data *dump; - dump = ath10k_build_dump_file(ar); + ath10k_warn(ar, "fw_crash_dump debugfs file is deprecated, please use /sys/class/devcoredump instead."); + + dump = ath10k_build_dump_file(ar, true); if (!dump) return -ENODATA; diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 335512b11ca2..2368f47314ae 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -84,6 +84,9 @@ struct ath10k_fw_crash_data * ath10k_debug_get_new_fw_crash_data(struct ath10k *ar); void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len); + +int ath10k_debug_fw_devcoredump(struct ath10k *ar); + #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++) void ath10k_debug_get_et_strings(struct ieee80211_hw *hw, @@ -166,6 +169,11 @@ static inline u32 ath10k_debug_get_fw_dbglog_level(struct ath10k *ar) return 0; } +static inline int ath10k_debug_fw_devcoredump(struct ath10k *ar) +{ + return 0; +} + #define ATH10K_DFS_STAT_INC(ar, c) do { } while (0) #define ath10k_debug_get_et_strings NULL diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 27e49db4287a..86b427f5e2bc 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -239,6 +239,7 @@ static void ath10k_htt_tx_free_cont_txbuf(struct ath10k_htt *htt) size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf); dma_free_coherent(ar->dev, size, htt->txbuf.vaddr, htt->txbuf.paddr); + htt->txbuf.vaddr = NULL; } static int ath10k_htt_tx_alloc_cont_txbuf(struct ath10k_htt *htt) @@ -268,6 +269,7 @@ static void ath10k_htt_tx_free_cont_frag_desc(struct ath10k_htt *htt) size, htt->frag_desc.vaddr, htt->frag_desc.paddr); + htt->frag_desc.vaddr = NULL; } static int ath10k_htt_tx_alloc_cont_frag_desc(struct ath10k_htt *htt) diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 883547f3347c..7feffec531cc 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -512,7 +512,7 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw, /* Target specific defines for WMI-TLV firmware */ #define TARGET_TLV_NUM_VDEVS 4 #define TARGET_TLV_NUM_STATIONS 32 -#define TARGET_TLV_NUM_PEERS 35 +#define TARGET_TLV_NUM_PEERS 33 #define TARGET_TLV_NUM_TDLS_VDEVS 1 #define TARGET_TLV_NUM_TIDS ((TARGET_TLV_NUM_PEERS) * 2) #define TARGET_TLV_NUM_MSDU_DESC (1024 + 32) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index aa545a1dbdc7..d1b7edba5e49 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1227,6 +1227,36 @@ static int ath10k_monitor_recalc(struct ath10k *ar) return ath10k_monitor_stop(ar); } +static bool ath10k_mac_can_set_cts_prot(struct ath10k_vif *arvif) +{ + struct ath10k *ar = arvif->ar; + + lockdep_assert_held(&ar->conf_mutex); + + if (!arvif->is_started) { + ath10k_dbg(ar, ATH10K_DBG_MAC, "defer cts setup, vdev is not ready yet\n"); + return false; + } + + return true; +} + +static int ath10k_mac_set_cts_prot(struct ath10k_vif *arvif) +{ + struct ath10k *ar = arvif->ar; + u32 vdev_param; + + lockdep_assert_held(&ar->conf_mutex); + + vdev_param = ar->wmi.vdev_param->protection_mode; + + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d cts_protection %d\n", + arvif->vdev_id, arvif->use_cts_prot); + + return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, + arvif->use_cts_prot ? 1 : 0); +} + static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif) { struct ath10k *ar = arvif->ar; @@ -1245,6 +1275,9 @@ static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif) rts_cts |= SM(WMI_RTSCTS_FOR_SECOND_RATESERIES, WMI_RTSCTS_PROFILE); + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d recalc rts/cts prot %d\n", + arvif->vdev_id, rts_cts); + return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, rts_cts); } @@ -3495,7 +3528,6 @@ static int ath10k_mac_tx_submit(struct ath10k *ar, */ static int ath10k_mac_tx(struct ath10k *ar, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, enum ath10k_hw_txrx_mode txmode, enum ath10k_mac_tx_path txpath, struct sk_buff *skb) @@ -3637,7 +3669,7 @@ void ath10k_offchan_tx_work(struct work_struct *work) txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); - ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb); + ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb); if (ret) { ath10k_warn(ar, "failed to transmit offchannel frame: %d\n", ret); @@ -3824,7 +3856,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, spin_unlock_bh(&ar->htt.tx_lock); } - ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb); + ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb); if (unlikely(ret)) { ath10k_warn(ar, "failed to push frame: %d\n", ret); @@ -4105,7 +4137,7 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, spin_unlock_bh(&ar->htt.tx_lock); } - ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb); + ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb); if (ret) { ath10k_warn(ar, "failed to transmit frame: %d\n", ret); if (is_htt) { @@ -4669,7 +4701,8 @@ static int ath10k_mac_txpower_recalc(struct ath10k *ar) lockdep_assert_held(&ar->conf_mutex); list_for_each_entry(arvif, &ar->arvifs, list) { - WARN_ON(arvif->txpower < 0); + if (arvif->txpower <= 0) + continue; if (txpower == -1) txpower = arvif->txpower; @@ -4677,8 +4710,8 @@ static int ath10k_mac_txpower_recalc(struct ath10k *ar) txpower = min(txpower, arvif->txpower); } - if (WARN_ON(txpower == -1)) - return -EINVAL; + if (txpower == -1) + return 0; ret = ath10k_mac_txpower_setup(ar, txpower); if (ret) { @@ -5194,6 +5227,10 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, ath10k_warn(ar, "failed to recalc monitor: %d\n", ret); } + ret = ath10k_mac_txpower_recalc(ar); + if (ret) + ath10k_warn(ar, "failed to recalc tx power: %d\n", ret); + spin_lock_bh(&ar->htt.tx_lock); ath10k_mac_vif_tx_unlock_all(arvif); spin_unlock_bh(&ar->htt.tx_lock); @@ -5328,20 +5365,18 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ERP_CTS_PROT) { arvif->use_cts_prot = info->use_cts_prot; - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d cts_prot %d\n", - arvif->vdev_id, info->use_cts_prot); ret = ath10k_recalc_rtscts_prot(arvif); if (ret) ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n", arvif->vdev_id, ret); - vdev_param = ar->wmi.vdev_param->protection_mode; - ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, - info->use_cts_prot ? 1 : 0); - if (ret) - ath10k_warn(ar, "failed to set protection mode %d on vdev %i: %d\n", - info->use_cts_prot, arvif->vdev_id, ret); + if (ath10k_mac_can_set_cts_prot(arvif)) { + ret = ath10k_mac_set_cts_prot(arvif); + if (ret) + ath10k_warn(ar, "failed to set cts protection for vdev %d: %d\n", + arvif->vdev_id, ret); + } } if (changed & BSS_CHANGED_ERP_SLOT) { @@ -7364,6 +7399,13 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, arvif->is_up = true; } + if (ath10k_mac_can_set_cts_prot(arvif)) { + ret = ath10k_mac_set_cts_prot(arvif); + if (ret) + ath10k_warn(ar, "failed to set cts protection for vdev %d: %d\n", + arvif->vdev_id, ret); + } + mutex_unlock(&ar->conf_mutex); return 0; @@ -7548,6 +7590,7 @@ static const struct ieee80211_channel ath10k_5ghz_channels[] = { CHAN5G(157, 5785, 0), CHAN5G(161, 5805, 0), CHAN5G(165, 5825, 0), + CHAN5G(169, 5845, 0), }; struct ath10k *ath10k_mac_create(size_t priv_size) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 0457e315d336..85367006a80a 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1973,7 +1973,7 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar) } break; case QCA9377_1_0_DEVICE_ID: - return 2; + return 4; } ath10k_warn(ar, "unknown number of banks, assuming 1\n"); @@ -3132,7 +3132,7 @@ int ath10k_pci_setup_resource(struct ath10k *ar) setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, (unsigned long)ar); - if (QCA_REV_6174(ar)) + if (QCA_REV_6174(ar) || QCA_REV_9377(ar)) ath10k_pci_override_ce_config(ar); ret = ath10k_pci_alloc_pipes(ar); diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index f304f6632c4f..1f6bb9e8bb01 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1105,8 +1105,10 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, struct ath10k_fw_stats_pdev *dst; src = data; - if (data_len < sizeof(*src)) + if (data_len < sizeof(*src)) { + kfree(tb); return -EPROTO; + } data += sizeof(*src); data_len -= sizeof(*src); @@ -1126,8 +1128,10 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, struct ath10k_fw_stats_vdev *dst; src = data; - if (data_len < sizeof(*src)) + if (data_len < sizeof(*src)) { + kfree(tb); return -EPROTO; + } data += sizeof(*src); data_len -= sizeof(*src); @@ -1145,8 +1149,10 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, struct ath10k_fw_stats_peer *dst; src = data; - if (data_len < sizeof(*src)) + if (data_len < sizeof(*src)) { + kfree(tb); return -EPROTO; + } data += sizeof(*src); data_len -= sizeof(*src); diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 8eea8d22e72e..7922550c2159 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -524,7 +524,7 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah, return true; /* Setup rf parameters */ - eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); + eepMinorRev = ah->eep_ops->get_eeprom_rev(ah); for (i = 0; i < ah->iniBank6.ia_rows; i++) ah->analogBank6Data[i] = INI_RA(&ah->iniBank6, i, modesIndex); diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index d480d2f3e185..ae68f674829b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -108,8 +108,7 @@ static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah) { u32 rxgain_type; - if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= - AR5416_EEP_MINOR_VER_17) { + if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_17) { rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE); if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) @@ -129,8 +128,7 @@ static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah) static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type) { - if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= - AR5416_EEP_MINOR_VER_19) { + if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) { if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9280Modes_high_power_tx_gain_9280_2); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 08607d7fdb56..3dbfd86ebe36 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -53,7 +53,7 @@ static const struct ar9300_eeprom ar9300_default = { .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ .opCapFlags = { .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, - .eepMisc = 0, + .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN, }, .rfSilent = 0, .blueToothOptions = 0, @@ -631,7 +631,7 @@ static const struct ar9300_eeprom ar9300_x113 = { .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ .opCapFlags = { .opFlags = AR5416_OPFLAGS_11A, - .eepMisc = 0, + .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN, }, .rfSilent = 0, .blueToothOptions = 0, @@ -1210,7 +1210,7 @@ static const struct ar9300_eeprom ar9300_h112 = { .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ .opCapFlags = { .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, - .eepMisc = 0, + .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN, }, .rfSilent = 0, .blueToothOptions = 0, @@ -1789,7 +1789,7 @@ static const struct ar9300_eeprom ar9300_x112 = { .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ .opCapFlags = { .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, - .eepMisc = 0, + .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN, }, .rfSilent = 0, .blueToothOptions = 0, @@ -2367,7 +2367,7 @@ static const struct ar9300_eeprom ar9300_h116 = { .txrxMask = 0x33, /* 4 bits tx and 4 bits rx */ .opCapFlags = { .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, - .eepMisc = 0, + .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN, }, .rfSilent = 0, .blueToothOptions = 0, @@ -3468,7 +3468,8 @@ static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, AR5416_OPFLAGS_N_5G_HT20)); PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags.opFlags & AR5416_OPFLAGS_N_5G_HT40)); - PR_EEP("Big Endian", !!(pBase->opCapFlags.eepMisc & 0x01)); + PR_EEP("Big Endian", !!(pBase->opCapFlags.eepMisc & + AR5416_EEPMISC_BIG_ENDIAN)); PR_EEP("RF Silent", pBase->rfSilent); PR_EEP("BT option", pBase->blueToothOptions); PR_EEP("Device Cap", pBase->deviceCap); @@ -5497,6 +5498,11 @@ unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah, } } +static u8 ar9003_get_eepmisc(struct ath_hw *ah) +{ + return ah->eeprom.map4k.baseEepHeader.eepMisc; +} + const struct eeprom_ops eep_ar9300_ops = { .check_eeprom = ath9k_hw_ar9300_check_eeprom, .get_eeprom = ath9k_hw_ar9300_get_eeprom, @@ -5507,5 +5513,6 @@ const struct eeprom_ops eep_ar9300_ops = { .set_board_values = ath9k_hw_ar9300_set_board_values, .set_addac = ath9k_hw_ar9300_set_addac, .set_txpower = ath9k_hw_ar9300_set_txpower, - .get_spur_channel = ath9k_hw_ar9300_get_spur_channel + .get_spur_channel = ath9k_hw_ar9300_get_spur_channel, + .get_eepmisc = ar9003_get_eepmisc }; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 107bcfbbe0fb..7dc7205dc877 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -38,7 +38,6 @@ #define AR9300_NUM_CTLS_2G 12 #define AR9300_NUM_BAND_EDGES_5G 8 #define AR9300_NUM_BAND_EDGES_2G 4 -#define AR9300_EEPMISC_BIG_ENDIAN 0x01 #define AR9300_EEPMISC_WOW 0x02 #define AR9300_CUSTOMER_DATA_SIZE 20 @@ -70,6 +69,9 @@ #define AR9300_BASE_ADDR 0x3ff #define AR9300_BASE_ADDR_512 0x1ff +/* AR5416_EEPMISC_BIG_ENDIAN not set indicates little endian */ +#define AR9300_EEPMISC_LITTLE_ENDIAN 0 + #define AR9300_OTP_BASE \ ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30000 : 0x14000) #define AR9300_OTP_STATUS \ diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 378d3458fddb..331947b6a667 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -112,6 +112,8 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, #define ATH_TXFIFO_DEPTH 8 #define ATH_TX_ERROR 0x01 +#define ATH_AIRTIME_QUANTUM 300 /* usec */ + /* Stop tx traffic 1ms before the GO goes away */ #define ATH_P2P_PS_STOP_TIME 1000 @@ -247,6 +249,9 @@ struct ath_atx_tid { bool has_queued; }; +void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid); +void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid); + struct ath_node { struct ath_softc *sc; struct ieee80211_sta *sta; /* station struct we're part of */ @@ -258,9 +263,12 @@ struct ath_node { bool sleeping; bool no_ps_filter; + s64 airtime_deficit[IEEE80211_NUM_ACS]; + u32 airtime_rx_start; #ifdef CONFIG_ATH9K_STATION_STATISTICS struct ath_rx_rate_stats rx_rate_stats; + struct ath_airtime_stats airtime_stats; #endif u8 key_idx[4]; @@ -317,10 +325,16 @@ struct ath_rx { /* Channel Context */ /*******************/ +struct ath_acq { + struct list_head acq_new; + struct list_head acq_old; + spinlock_t lock; +}; + struct ath_chanctx { struct cfg80211_chan_def chandef; struct list_head vifs; - struct list_head acq[IEEE80211_NUM_ACS]; + struct ath_acq acq[IEEE80211_NUM_ACS]; int hw_queue_base; /* do not dereference, use for comparison only */ @@ -555,6 +569,15 @@ static inline void ath_chanctx_check_active(struct ath_softc *sc, #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */ +static inline void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq) +{ + spin_lock_bh(&txq->axq_lock); +} +static inline void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq) +{ + spin_unlock_bh(&txq->axq_lock); +} + void ath_startrecv(struct ath_softc *sc); bool ath_stoprecv(struct ath_softc *sc); u32 ath_calcrxfilter(struct ath_softc *sc); @@ -562,8 +585,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs); void ath_rx_cleanup(struct ath_softc *sc); int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp); struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); -void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq); -void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq); void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq); void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); bool ath_drain_all_txq(struct ath_softc *sc); @@ -575,6 +596,8 @@ void ath_txq_schedule_all(struct ath_softc *sc); int ath_tx_init(struct ath_softc *sc, int nbufs); int ath_txq_update(struct ath_softc *sc, int qnum, struct ath9k_tx_queue_info *q); +u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, + int width, int half_gi, bool shortPreamble); void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop); void ath_assign_seq(struct ath_common *common, struct sk_buff *skb); int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, @@ -963,6 +986,11 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ +#define AIRTIME_USE_TX BIT(0) +#define AIRTIME_USE_RX BIT(1) +#define AIRTIME_USE_NEW_QUEUES BIT(2) +#define AIRTIME_ACTIVE(flags) (!!(flags & (AIRTIME_USE_TX|AIRTIME_USE_RX))) + struct ath_softc { struct ieee80211_hw *hw; struct device *dev; @@ -1005,6 +1033,8 @@ struct ath_softc { short nbcnvifs; unsigned long ps_usecount; + u16 airtime_flags; /* AIRTIME_* */ + struct ath_rx rx; struct ath_tx tx; struct ath_beacon beacon; diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 929dd70f48eb..b84539d89f1a 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -118,8 +118,11 @@ void ath_chanctx_init(struct ath_softc *sc) INIT_LIST_HEAD(&ctx->vifs); ctx->txpower = ATH_TXPOWER_MAX; ctx->flush_timeout = HZ / 5; /* 200ms */ - for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) - INIT_LIST_HEAD(&ctx->acq[j]); + for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) { + INIT_LIST_HEAD(&ctx->acq[j].acq_new); + INIT_LIST_HEAD(&ctx->acq[j].acq_old); + spin_lock_init(&ctx->acq[j].lock); + } } } @@ -1345,8 +1348,11 @@ void ath9k_offchannel_init(struct ath_softc *sc) ctx->txpower = ATH_TXPOWER_MAX; cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20); - for (i = 0; i < ARRAY_SIZE(ctx->acq); i++) - INIT_LIST_HEAD(&ctx->acq[i]); + for (i = 0; i < ARRAY_SIZE(ctx->acq); i++) { + INIT_LIST_HEAD(&ctx->acq[i].acq_new); + INIT_LIST_HEAD(&ctx->acq[i].acq_old); + spin_lock_init(&ctx->acq[i].lock); + } sc->offchannel.chan.offchannel = true; } diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 89a94dd5f2cb..43930c336987 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1399,5 +1399,8 @@ int ath9k_init_debug(struct ath_hw *ah) debugfs_create_file("tpc", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_tpc); + debugfs_create_u16("airtime_flags", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, &sc->airtime_flags); + return 0; } diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index a078cdd3170d..249f8141cd00 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -221,6 +221,11 @@ struct ath_rx_rate_stats { } cck_stats[4]; }; +struct ath_airtime_stats { + u32 rx_airtime; + u32 tx_airtime; +}; + #define ANT_MAIN 0 #define ANT_ALT 1 @@ -314,12 +319,20 @@ ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause) void ath_debug_rate_stats(struct ath_softc *sc, struct ath_rx_status *rs, struct sk_buff *skb); +void ath_debug_airtime(struct ath_softc *sc, + struct ath_node *an, + u32 rx, u32 tx); #else static inline void ath_debug_rate_stats(struct ath_softc *sc, struct ath_rx_status *rs, struct sk_buff *skb) { } +static inline void ath_debug_airtime(struct ath_softc *sc, + struct ath_node *an, + u32 rx, u32 tx) +{ +} #endif /* CONFIG_ATH9K_STATION_STATISTICS */ #endif /* DEBUG_H */ diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c index 2a3a3c4671bc..524cbf13ca9c 100644 --- a/drivers/net/wireless/ath/ath9k/debug_sta.c +++ b/drivers/net/wireless/ath/ath9k/debug_sta.c @@ -242,6 +242,59 @@ static const struct file_operations fops_node_recv = { .llseek = default_llseek, }; +void ath_debug_airtime(struct ath_softc *sc, + struct ath_node *an, + u32 rx, + u32 tx) +{ + struct ath_airtime_stats *astats = &an->airtime_stats; + + astats->rx_airtime += rx; + astats->tx_airtime += tx; +} + +static ssize_t read_airtime(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_node *an = file->private_data; + struct ath_airtime_stats *astats; + static const char *qname[4] = { + "VO", "VI", "BE", "BK" + }; + u32 len = 0, size = 256; + char *buf; + size_t retval; + int i; + + buf = kzalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + astats = &an->airtime_stats; + + len += scnprintf(buf + len, size - len, "RX: %u us\n", astats->rx_airtime); + len += scnprintf(buf + len, size - len, "TX: %u us\n", astats->tx_airtime); + len += scnprintf(buf + len, size - len, "Deficit: "); + for (i = 0; i < 4; i++) + len += scnprintf(buf+len, size - len, "%s: %lld us ", qname[i], an->airtime_deficit[i]); + if (len < size) + buf[len++] = '\n'; + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + + return retval; +} + + +static const struct file_operations fops_airtime = { + .read = read_airtime, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + + void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -251,4 +304,5 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, debugfs_create_file("node_aggr", S_IRUGO, dir, an, &fops_node_aggr); debugfs_create_file("node_recv", S_IRUGO, dir, an, &fops_node_recv); + debugfs_create_file("airtime", S_IRUGO, dir, an, &fops_airtime); } diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index a449588a8009..fb80ec86e53d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -160,6 +160,7 @@ int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size) u16 magic; u16 *eepdata; int i; + bool needs_byteswap = false; struct ath_common *common = ath9k_hw_common(ah); if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { @@ -167,31 +168,40 @@ int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size) return -EIO; } - *swap_needed = false; if (swab16(magic) == AR5416_EEPROM_MAGIC) { + needs_byteswap = true; + ath_dbg(common, EEPROM, + "EEPROM needs byte-swapping to correct endianness.\n"); + } else if (magic != AR5416_EEPROM_MAGIC) { + if (ath9k_hw_use_flash(ah)) { + ath_dbg(common, EEPROM, + "Ignoring invalid EEPROM magic (0x%04x).\n", + magic); + } else { + ath_err(common, + "Invalid EEPROM magic (0x%04x).\n", magic); + return -EINVAL; + } + } + + if (needs_byteswap) { if (ah->ah_flags & AH_NO_EEP_SWAP) { ath_info(common, "Ignoring endianness difference in EEPROM magic bytes.\n"); } else { - *swap_needed = true; - } - } else if (magic != AR5416_EEPROM_MAGIC) { - if (ath9k_hw_use_flash(ah)) - return 0; + eepdata = (u16 *)(&ah->eeprom); - ath_err(common, - "Invalid EEPROM Magic (0x%04x).\n", magic); - return -EINVAL; + for (i = 0; i < size; i++) + eepdata[i] = swab16(eepdata[i]); + } } - eepdata = (u16 *)(&ah->eeprom); - - if (*swap_needed) { + if (ah->eep_ops->get_eepmisc(ah) & AR5416_EEPMISC_BIG_ENDIAN) { + *swap_needed = true; ath_dbg(common, EEPROM, - "EEPROM Endianness is not native.. Changing.\n"); - - for (i = 0; i < size; i++) - eepdata[i] = swab16(eepdata[i]); + "Big Endian EEPROM detected according to EEPMISC register.\n"); + } else { + *swap_needed = false; } return 0; diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 4465c6566f20..30bf722e33ed 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -23,6 +23,17 @@ #include <net/cfg80211.h> #include "ar9003_eeprom.h" +/* helpers to swap EEPROM fields, which are stored as __le16 or __le32. Since + * we are 100% sure about it we __force these to u16/u32 for the swab calls to + * silence the sparse checks. These macros are used when we have a Big Endian + * EEPROM (according to AR5416_EEPMISC_BIG_ENDIAN) and need to convert the + * fields to __le16/__le32. + */ +#define EEPROM_FIELD_SWAB16(field) \ + (field = (__force __le16)swab16((__force u16)field)) +#define EEPROM_FIELD_SWAB32(field) \ + (field = (__force __le32)swab32((__force u32)field)) + #ifdef __BIG_ENDIAN #define AR5416_EEPROM_MAGIC 0x5aa5 #else @@ -99,7 +110,6 @@ #define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x)) #define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM)) -#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) #define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \ @@ -121,6 +131,8 @@ #define AR5416_EEP_NO_BACK_VER 0x1 #define AR5416_EEP_VER 0xE +#define AR5416_EEP_VER_MAJOR_SHIFT 12 +#define AR5416_EEP_VER_MAJOR_MASK 0xF000 #define AR5416_EEP_VER_MINOR_MASK 0x0FFF #define AR5416_EEP_MINOR_VER_2 0x2 #define AR5416_EEP_MINOR_VER_3 0x3 @@ -161,6 +173,9 @@ #define AR5416_EEP_TXGAIN_ORIGINAL 0 #define AR5416_EEP_TXGAIN_HIGH_POWER 1 +/* Endianness of EEPROM content */ +#define AR5416_EEPMISC_BIG_ENDIAN 0x01 + #define AR5416_EEP4K_START_LOC 64 #define AR5416_EEP4K_NUM_2G_CAL_PIERS 3 #define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3 @@ -174,7 +189,6 @@ #define AR9280_TX_GAIN_TABLE_SIZE 22 #define AR9287_EEP_VER 0xE -#define AR9287_EEP_VER_MINOR_MASK 0xFFF #define AR9287_EEP_MINOR_VER_1 0x1 #define AR9287_EEP_MINOR_VER_2 0x2 #define AR9287_EEP_MINOR_VER_3 0x3 @@ -191,7 +205,6 @@ #define AR9287_NUM_CTLS 12 #define AR9287_NUM_BAND_EDGES 4 #define AR9287_PD_GAIN_ICEPTS 1 -#define AR9287_EEPMISC_BIG_ENDIAN 0x01 #define AR9287_EEPMISC_WOW 0x02 #define AR9287_MAX_CHAINS 2 #define AR9287_ANT_16S 32 @@ -228,7 +241,6 @@ enum eeprom_param { EEP_DB_5, EEP_OB_2, EEP_DB_2, - EEP_MINOR_REV, EEP_TX_MASK, EEP_RX_MASK, EEP_FSTCLK_5G, @@ -269,19 +281,19 @@ enum ath9k_hal_freq_band { }; struct base_eep_header { - u16 length; - u16 checksum; - u16 version; + __le16 length; + __le16 checksum; + __le16 version; u8 opCapFlags; u8 eepMisc; - u16 regDmn[2]; + __le16 regDmn[2]; u8 macAddr[6]; u8 rxMask; u8 txMask; - u16 rfSilent; - u16 blueToothOptions; - u16 deviceCap; - u32 binBuildNumber; + __le16 rfSilent; + __le16 blueToothOptions; + __le16 deviceCap; + __le32 binBuildNumber; u8 deviceType; u8 pwdclkind; u8 fastClk5g; @@ -299,33 +311,33 @@ struct base_eep_header { } __packed; struct base_eep_header_4k { - u16 length; - u16 checksum; - u16 version; + __le16 length; + __le16 checksum; + __le16 version; u8 opCapFlags; u8 eepMisc; - u16 regDmn[2]; + __le16 regDmn[2]; u8 macAddr[6]; u8 rxMask; u8 txMask; - u16 rfSilent; - u16 blueToothOptions; - u16 deviceCap; - u32 binBuildNumber; + __le16 rfSilent; + __le16 blueToothOptions; + __le16 deviceCap; + __le32 binBuildNumber; u8 deviceType; u8 txGainType; } __packed; struct spur_chan { - u16 spurChan; + __le16 spurChan; u8 spurRangeLow; u8 spurRangeHigh; } __packed; struct modal_eep_header { - u32 antCtrlChain[AR5416_MAX_CHAINS]; - u32 antCtrlCommon; + __le32 antCtrlChain[AR5416_MAX_CHAINS]; + __le32 antCtrlCommon; u8 antennaGainCh[AR5416_MAX_CHAINS]; u8 switchSettling; u8 txRxAttenCh[AR5416_MAX_CHAINS]; @@ -360,7 +372,7 @@ struct modal_eep_header { u8 db_ch1; u8 lna_ctl; u8 miscBits; - u16 xpaBiasLvlFreq[3]; + __le16 xpaBiasLvlFreq[3]; u8 futureModal[6]; struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS]; @@ -374,8 +386,8 @@ struct calDataPerFreqOpLoop { } __packed; struct modal_eep_4k_header { - u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; - u32 antCtrlCommon; + __le32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; + __le32 antCtrlCommon; u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS]; u8 switchSettling; u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS]; @@ -439,19 +451,19 @@ struct modal_eep_4k_header { } __packed; struct base_eep_ar9287_header { - u16 length; - u16 checksum; - u16 version; + __le16 length; + __le16 checksum; + __le16 version; u8 opCapFlags; u8 eepMisc; - u16 regDmn[2]; + __le16 regDmn[2]; u8 macAddr[6]; u8 rxMask; u8 txMask; - u16 rfSilent; - u16 blueToothOptions; - u16 deviceCap; - u32 binBuildNumber; + __le16 rfSilent; + __le16 blueToothOptions; + __le16 deviceCap; + __le32 binBuildNumber; u8 deviceType; u8 openLoopPwrCntl; int8_t pwrTableOffset; @@ -461,8 +473,8 @@ struct base_eep_ar9287_header { } __packed; struct modal_eep_ar9287_header { - u32 antCtrlChain[AR9287_MAX_CHAINS]; - u32 antCtrlCommon; + __le32 antCtrlChain[AR9287_MAX_CHAINS]; + __le32 antCtrlCommon; int8_t antennaGainCh[AR9287_MAX_CHAINS]; u8 switchSettling; u8 txRxAttenCh[AR9287_MAX_CHAINS]; @@ -653,6 +665,7 @@ struct eeprom_ops { u16 cfgCtl, u8 twiceAntennaReduction, u8 powerLimit, bool test); u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); + u8 (*get_eepmisc)(struct ath_hw *ah); }; void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val); diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 5da0826bf1be..4a01ebe53053 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -20,12 +20,17 @@ static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah) { - return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF); + u16 version = le16_to_cpu(ah->eeprom.map4k.baseEepHeader.version); + + return (version & AR5416_EEP_VER_MAJOR_MASK) >> + AR5416_EEP_VER_MAJOR_SHIFT; } static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) { - return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF); + u16 version = le16_to_cpu(ah->eeprom.map4k.baseEepHeader.version); + + return version & AR5416_EEP_VER_MINOR_MASK; } #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) @@ -71,8 +76,8 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) static u32 ath9k_dump_4k_modal_eeprom(char *buf, u32 len, u32 size, struct modal_eep_4k_header *modal_hdr) { - PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]); - PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon); + PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0])); + PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon)); PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]); PR_EEP("Switch Settle", modal_hdr->switchSettling); PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]); @@ -127,6 +132,7 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, { struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; struct base_eep_header_4k *pBase = &eep->baseEepHeader; + u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber); if (!dump_base_hdr) { len += scnprintf(buf + len, size - len, @@ -136,12 +142,12 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, goto out; } - PR_EEP("Major Version", pBase->version >> 12); - PR_EEP("Minor Version", pBase->version & 0xFFF); - PR_EEP("Checksum", pBase->checksum); - PR_EEP("Length", pBase->length); - PR_EEP("RegDomain1", pBase->regDmn[0]); - PR_EEP("RegDomain2", pBase->regDmn[1]); + PR_EEP("Major Version", ath9k_hw_4k_get_eeprom_ver(ah)); + PR_EEP("Minor Version", ath9k_hw_4k_get_eeprom_rev(ah)); + PR_EEP("Checksum", le16_to_cpu(pBase->checksum)); + PR_EEP("Length", le16_to_cpu(pBase->length)); + PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0])); + PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1])); PR_EEP("TX Mask", pBase->txMask); PR_EEP("RX Mask", pBase->rxMask); PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); @@ -154,10 +160,10 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, AR5416_OPFLAGS_N_5G_HT20)); PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT40)); - PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01)); - PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF); - PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF); - PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); + PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN)); + PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF); + PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF); + PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF); PR_EEP("TX Gain type", pBase->txGainType); len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", @@ -189,54 +195,31 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) return err; if (need_swap) - el = swab16(eep->baseEepHeader.length); + el = swab16((__force u16)eep->baseEepHeader.length); else - el = eep->baseEepHeader.length; + el = le16_to_cpu(eep->baseEepHeader.length); el = min(el / sizeof(u16), SIZE_EEPROM_4K); if (!ath9k_hw_nvram_validate_checksum(ah, el)) return -EINVAL; if (need_swap) { - u32 integer; - u16 word; - - word = swab16(eep->baseEepHeader.length); - eep->baseEepHeader.length = word; - - word = swab16(eep->baseEepHeader.checksum); - eep->baseEepHeader.checksum = word; - - word = swab16(eep->baseEepHeader.version); - eep->baseEepHeader.version = word; - - word = swab16(eep->baseEepHeader.regDmn[0]); - eep->baseEepHeader.regDmn[0] = word; - - word = swab16(eep->baseEepHeader.regDmn[1]); - eep->baseEepHeader.regDmn[1] = word; - - word = swab16(eep->baseEepHeader.rfSilent); - eep->baseEepHeader.rfSilent = word; - - word = swab16(eep->baseEepHeader.blueToothOptions); - eep->baseEepHeader.blueToothOptions = word; - - word = swab16(eep->baseEepHeader.deviceCap); - eep->baseEepHeader.deviceCap = word; - - integer = swab32(eep->modalHeader.antCtrlCommon); - eep->modalHeader.antCtrlCommon = integer; - - for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { - integer = swab32(eep->modalHeader.antCtrlChain[i]); - eep->modalHeader.antCtrlChain[i] = integer; - } - - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - word = swab16(eep->modalHeader.spurChans[i].spurChan); - eep->modalHeader.spurChans[i].spurChan = word; - } + EEPROM_FIELD_SWAB16(eep->baseEepHeader.length); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.version); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap); + EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlCommon); + + for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) + EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlChain[i]); + + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) + EEPROM_FIELD_SWAB16( + eep->modalHeader.spurChans[i].spurChan); } if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER, @@ -254,9 +237,6 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; struct modal_eep_4k_header *pModal = &eep->modalHeader; struct base_eep_header_4k *pBase = &eep->baseEepHeader; - u16 ver_minor; - - ver_minor = pBase->version & AR5416_EEP_VER_MINOR_MASK; switch (param) { case EEP_NFTHRESH_2: @@ -268,19 +248,17 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, case EEP_MAC_MSW: return get_unaligned_be16(pBase->macAddr + 4); case EEP_REG_0: - return pBase->regDmn[0]; + return le16_to_cpu(pBase->regDmn[0]); case EEP_OP_CAP: - return pBase->deviceCap; + return le16_to_cpu(pBase->deviceCap); case EEP_OP_MODE: return pBase->opCapFlags; case EEP_RF_SILENT: - return pBase->rfSilent; + return le16_to_cpu(pBase->rfSilent); case EEP_OB_2: return pModal->ob_0; case EEP_DB_2: return pModal->db1_1; - case EEP_MINOR_REV: - return ver_minor; case EEP_TX_MASK: return pBase->txMask; case EEP_RX_MASK: @@ -319,14 +297,12 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, xpdMask = pEepData->modalHeader.xpdGain; - if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { + if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; - } else { + else pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); - } pCalBChans = pEepData->calFreqPier2G; numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS; @@ -612,10 +588,8 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, memset(ratesArray, 0, sizeof(ratesArray)); - if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { + if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; - } ath9k_hw_set_4k_power_per_rate_table(ah, chan, &ratesArray[0], cfgCtl, @@ -728,15 +702,14 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah, { ENABLE_REG_RMW_BUFFER(ah); REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, - pModal->antCtrlChain[0], 0); + le32_to_cpu(pModal->antCtrlChain[0]), 0); REG_RMW(ah, AR_PHY_TIMING_CTRL4(0), SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF), AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF); - if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_3) { + if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) { txRxAttenLocal = pModal->txRxAttenCh[0]; REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, @@ -795,7 +768,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, pModal = &eep->modalHeader; txRxAttenLocal = 23; - REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); + REG_WRITE(ah, AR_PHY_SWITCH_COM, le32_to_cpu(pModal->antCtrlCommon)); /* Single chain for 4K EEPROM*/ ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal); @@ -1014,16 +987,14 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62); - if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { + if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) { REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart); REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn); } - if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_3) { + if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) { if (IS_CHAN_HT40(chan)) REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, @@ -1061,7 +1032,12 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) { - return ah->eeprom.map4k.modalHeader.spurChans[i].spurChan; + return le16_to_cpu(ah->eeprom.map4k.modalHeader.spurChans[i].spurChan); +} + +static u8 ath9k_hw_4k_get_eepmisc(struct ath_hw *ah) +{ + return ah->eeprom.map4k.baseEepHeader.eepMisc; } const struct eeprom_ops eep_4k_ops = { @@ -1073,5 +1049,6 @@ const struct eeprom_ops eep_4k_ops = { .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, .set_board_values = ath9k_hw_4k_set_board_values, .set_txpower = ath9k_hw_4k_set_txpower, - .get_spur_channel = ath9k_hw_4k_get_spur_channel + .get_spur_channel = ath9k_hw_4k_get_spur_channel, + .get_eepmisc = ath9k_hw_4k_get_eepmisc }; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 1a019a39eda1..9611f020f7c0 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -22,12 +22,17 @@ static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah) { - return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF; + u16 version = le16_to_cpu(ah->eeprom.map9287.baseEepHeader.version); + + return (version & AR5416_EEP_VER_MAJOR_MASK) >> + AR5416_EEP_VER_MAJOR_SHIFT; } static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah) { - return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF; + u16 version = le16_to_cpu(ah->eeprom.map9287.baseEepHeader.version); + + return version & AR5416_EEP_VER_MINOR_MASK; } static bool __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) @@ -74,9 +79,9 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) static u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size, struct modal_eep_ar9287_header *modal_hdr) { - PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]); - PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]); - PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon); + PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0])); + PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1])); + PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon)); PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]); PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]); PR_EEP("Switch Settle", modal_hdr->switchSettling); @@ -123,6 +128,7 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, { struct ar9287_eeprom *eep = &ah->eeprom.map9287; struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; + u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber); if (!dump_base_hdr) { len += scnprintf(buf + len, size - len, @@ -132,12 +138,12 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, goto out; } - PR_EEP("Major Version", pBase->version >> 12); - PR_EEP("Minor Version", pBase->version & 0xFFF); - PR_EEP("Checksum", pBase->checksum); - PR_EEP("Length", pBase->length); - PR_EEP("RegDomain1", pBase->regDmn[0]); - PR_EEP("RegDomain2", pBase->regDmn[1]); + PR_EEP("Major Version", ath9k_hw_ar9287_get_eeprom_ver(ah)); + PR_EEP("Minor Version", ath9k_hw_ar9287_get_eeprom_rev(ah)); + PR_EEP("Checksum", le16_to_cpu(pBase->checksum)); + PR_EEP("Length", le16_to_cpu(pBase->length)); + PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0])); + PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1])); PR_EEP("TX Mask", pBase->txMask); PR_EEP("RX Mask", pBase->rxMask); PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); @@ -150,10 +156,10 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, AR5416_OPFLAGS_N_5G_HT20)); PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT40)); - PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01)); - PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF); - PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF); - PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); + PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN)); + PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF); + PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF); + PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF); PR_EEP("Power Table Offset", pBase->pwrTableOffset); PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl); @@ -177,8 +183,7 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) { - u32 el, integer; - u16 word; + u32 el; int i, err; bool need_swap; struct ar9287_eeprom *eep = &ah->eeprom.map9287; @@ -188,51 +193,31 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) return err; if (need_swap) - el = swab16(eep->baseEepHeader.length); + el = swab16((__force u16)eep->baseEepHeader.length); else - el = eep->baseEepHeader.length; + el = le16_to_cpu(eep->baseEepHeader.length); el = min(el / sizeof(u16), SIZE_EEPROM_AR9287); if (!ath9k_hw_nvram_validate_checksum(ah, el)) return -EINVAL; if (need_swap) { - word = swab16(eep->baseEepHeader.length); - eep->baseEepHeader.length = word; - - word = swab16(eep->baseEepHeader.checksum); - eep->baseEepHeader.checksum = word; - - word = swab16(eep->baseEepHeader.version); - eep->baseEepHeader.version = word; - - word = swab16(eep->baseEepHeader.regDmn[0]); - eep->baseEepHeader.regDmn[0] = word; - - word = swab16(eep->baseEepHeader.regDmn[1]); - eep->baseEepHeader.regDmn[1] = word; - - word = swab16(eep->baseEepHeader.rfSilent); - eep->baseEepHeader.rfSilent = word; - - word = swab16(eep->baseEepHeader.blueToothOptions); - eep->baseEepHeader.blueToothOptions = word; - - word = swab16(eep->baseEepHeader.deviceCap); - eep->baseEepHeader.deviceCap = word; - - integer = swab32(eep->modalHeader.antCtrlCommon); - eep->modalHeader.antCtrlCommon = integer; - - for (i = 0; i < AR9287_MAX_CHAINS; i++) { - integer = swab32(eep->modalHeader.antCtrlChain[i]); - eep->modalHeader.antCtrlChain[i] = integer; - } - - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - word = swab16(eep->modalHeader.spurChans[i].spurChan); - eep->modalHeader.spurChans[i].spurChan = word; - } + EEPROM_FIELD_SWAB16(eep->baseEepHeader.length); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.version); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap); + EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlCommon); + + for (i = 0; i < AR9287_MAX_CHAINS; i++) + EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlChain[i]); + + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) + EEPROM_FIELD_SWAB16( + eep->modalHeader.spurChans[i].spurChan); } if (!ath9k_hw_nvram_check_version(ah, AR9287_EEP_VER, @@ -250,9 +235,7 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah, struct ar9287_eeprom *eep = &ah->eeprom.map9287; struct modal_eep_ar9287_header *pModal = &eep->modalHeader; struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; - u16 ver_minor; - - ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK; + u16 ver_minor = ath9k_hw_ar9287_get_eeprom_rev(ah); switch (param) { case EEP_NFTHRESH_2: @@ -264,15 +247,13 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah, case EEP_MAC_MSW: return get_unaligned_be16(pBase->macAddr + 4); case EEP_REG_0: - return pBase->regDmn[0]; + return le16_to_cpu(pBase->regDmn[0]); case EEP_OP_CAP: - return pBase->deviceCap; + return le16_to_cpu(pBase->deviceCap); case EEP_OP_MODE: return pBase->opCapFlags; case EEP_RF_SILENT: - return pBase->rfSilent; - case EEP_MINOR_REV: - return ver_minor; + return le16_to_cpu(pBase->rfSilent); case EEP_TX_MASK: return pBase->txMask; case EEP_RX_MASK: @@ -387,8 +368,7 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, xpdMask = pEepData->modalHeader.xpdGain; - if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= - AR9287_EEP_MINOR_VER_2) + if (ath9k_hw_ar9287_get_eeprom_rev(ah) >= AR9287_EEP_MINOR_VER_2) pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; else pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), @@ -737,8 +717,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, memset(ratesArray, 0, sizeof(ratesArray)); - if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= - AR9287_EEP_MINOR_VER_2) + if (ath9k_hw_ar9287_get_eeprom_rev(ah) >= AR9287_EEP_MINOR_VER_2) ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; ath9k_hw_set_ar9287_power_per_rate_table(ah, chan, @@ -879,13 +858,13 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, pModal = &eep->modalHeader; - REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); + REG_WRITE(ah, AR_PHY_SWITCH_COM, le32_to_cpu(pModal->antCtrlCommon)); for (i = 0; i < AR9287_MAX_CHAINS; i++) { regChainOffset = i * 0x1000; REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, - pModal->antCtrlChain[i]); + le32_to_cpu(pModal->antCtrlChain[i])); REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) @@ -983,7 +962,14 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) { - return ah->eeprom.map9287.modalHeader.spurChans[i].spurChan; + __le16 spur_ch = ah->eeprom.map9287.modalHeader.spurChans[i].spurChan; + + return le16_to_cpu(spur_ch); +} + +static u8 ath9k_hw_ar9287_get_eepmisc(struct ath_hw *ah) +{ + return ah->eeprom.map9287.baseEepHeader.eepMisc; } const struct eeprom_ops eep_ar9287_ops = { @@ -995,5 +981,6 @@ const struct eeprom_ops eep_ar9287_ops = { .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev, .set_board_values = ath9k_hw_ar9287_set_board_values, .set_txpower = ath9k_hw_ar9287_set_txpower, - .get_spur_channel = ath9k_hw_ar9287_get_spur_channel + .get_spur_channel = ath9k_hw_ar9287_get_spur_channel, + .get_eepmisc = ath9k_hw_ar9287_get_eepmisc }; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 959682f7909c..7d5223451ce9 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -79,12 +79,17 @@ static void ath9k_olc_get_pdadcs(struct ath_hw *ah, static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah) { - return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF); + u16 version = le16_to_cpu(ah->eeprom.def.baseEepHeader.version); + + return (version & AR5416_EEP_VER_MAJOR_MASK) >> + AR5416_EEP_VER_MAJOR_SHIFT; } static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) { - return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF); + u16 version = le16_to_cpu(ah->eeprom.def.baseEepHeader.version); + + return version & AR5416_EEP_VER_MINOR_MASK; } #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) @@ -130,10 +135,10 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size, struct modal_eep_header *modal_hdr) { - PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]); - PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]); - PR_EEP("Chain2 Ant. Control", modal_hdr->antCtrlChain[2]); - PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon); + PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0])); + PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1])); + PR_EEP("Chain2 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[2])); + PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon)); PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]); PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]); PR_EEP("Chain2 Ant. Gain", modal_hdr->antennaGainCh[2]); @@ -189,9 +194,9 @@ static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size, PR_EEP("Chain1 OutputBias", modal_hdr->ob_ch1); PR_EEP("Chain1 DriverBias", modal_hdr->db_ch1); PR_EEP("LNA Control", modal_hdr->lna_ctl); - PR_EEP("XPA Bias Freq0", modal_hdr->xpaBiasLvlFreq[0]); - PR_EEP("XPA Bias Freq1", modal_hdr->xpaBiasLvlFreq[1]); - PR_EEP("XPA Bias Freq2", modal_hdr->xpaBiasLvlFreq[2]); + PR_EEP("XPA Bias Freq0", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[0])); + PR_EEP("XPA Bias Freq1", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[1])); + PR_EEP("XPA Bias Freq2", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[2])); return len; } @@ -201,6 +206,7 @@ static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, { struct ar5416_eeprom_def *eep = &ah->eeprom.def; struct base_eep_header *pBase = &eep->baseEepHeader; + u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber); if (!dump_base_hdr) { len += scnprintf(buf + len, size - len, @@ -214,12 +220,12 @@ static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, goto out; } - PR_EEP("Major Version", pBase->version >> 12); - PR_EEP("Minor Version", pBase->version & 0xFFF); - PR_EEP("Checksum", pBase->checksum); - PR_EEP("Length", pBase->length); - PR_EEP("RegDomain1", pBase->regDmn[0]); - PR_EEP("RegDomain2", pBase->regDmn[1]); + PR_EEP("Major Version", ath9k_hw_def_get_eeprom_ver(ah)); + PR_EEP("Minor Version", ath9k_hw_def_get_eeprom_rev(ah)); + PR_EEP("Checksum", le16_to_cpu(pBase->checksum)); + PR_EEP("Length", le16_to_cpu(pBase->length)); + PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0])); + PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1])); PR_EEP("TX Mask", pBase->txMask); PR_EEP("RX Mask", pBase->rxMask); PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); @@ -232,10 +238,10 @@ static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, AR5416_OPFLAGS_N_5G_HT20)); PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT40)); - PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01)); - PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF); - PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF); - PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); + PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN)); + PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF); + PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF); + PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF); PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl); len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", @@ -268,61 +274,40 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) return err; if (need_swap) - el = swab16(eep->baseEepHeader.length); + el = swab16((__force u16)eep->baseEepHeader.length); else - el = eep->baseEepHeader.length; + el = le16_to_cpu(eep->baseEepHeader.length); el = min(el / sizeof(u16), SIZE_EEPROM_DEF); if (!ath9k_hw_nvram_validate_checksum(ah, el)) return -EINVAL; if (need_swap) { - u32 integer, j; - u16 word; - - word = swab16(eep->baseEepHeader.length); - eep->baseEepHeader.length = word; - - word = swab16(eep->baseEepHeader.checksum); - eep->baseEepHeader.checksum = word; - - word = swab16(eep->baseEepHeader.version); - eep->baseEepHeader.version = word; - - word = swab16(eep->baseEepHeader.regDmn[0]); - eep->baseEepHeader.regDmn[0] = word; - - word = swab16(eep->baseEepHeader.regDmn[1]); - eep->baseEepHeader.regDmn[1] = word; - - word = swab16(eep->baseEepHeader.rfSilent); - eep->baseEepHeader.rfSilent = word; - - word = swab16(eep->baseEepHeader.blueToothOptions); - eep->baseEepHeader.blueToothOptions = word; + u32 j; - word = swab16(eep->baseEepHeader.deviceCap); - eep->baseEepHeader.deviceCap = word; + EEPROM_FIELD_SWAB16(eep->baseEepHeader.length); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.version); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions); + EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap); for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) { struct modal_eep_header *pModal = &eep->modalHeader[j]; - integer = swab32(pModal->antCtrlCommon); - pModal->antCtrlCommon = integer; + EEPROM_FIELD_SWAB32(pModal->antCtrlCommon); - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - integer = swab32(pModal->antCtrlChain[i]); - pModal->antCtrlChain[i] = integer; - } - for (i = 0; i < 3; i++) { - word = swab16(pModal->xpaBiasLvlFreq[i]); - pModal->xpaBiasLvlFreq[i] = word; - } + for (i = 0; i < AR5416_MAX_CHAINS; i++) + EEPROM_FIELD_SWAB32(pModal->antCtrlChain[i]); - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - word = swab16(pModal->spurChans[i].spurChan); - pModal->spurChans[i].spurChan = word; - } + for (i = 0; i < 3; i++) + EEPROM_FIELD_SWAB16(pModal->xpaBiasLvlFreq[i]); + + for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) + EEPROM_FIELD_SWAB16( + pModal->spurChans[i].spurChan); } } @@ -332,7 +317,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) /* Enable fixup for AR_AN_TOP2 if necessary */ if ((ah->hw_version.devid == AR9280_DEVID_PCI) && - ((eep->baseEepHeader.version & 0xff) > 0x0a) && + ((le16_to_cpu(eep->baseEepHeader.version) & 0xff) > 0x0a) && (eep->baseEepHeader.pwdclkind == 0)) ah->need_an_top2_fixup = true; @@ -365,13 +350,13 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, case EEP_MAC_MSW: return get_unaligned_be16(pBase->macAddr + 4); case EEP_REG_0: - return pBase->regDmn[0]; + return le16_to_cpu(pBase->regDmn[0]); case EEP_OP_CAP: - return pBase->deviceCap; + return le16_to_cpu(pBase->deviceCap); case EEP_OP_MODE: return pBase->opCapFlags; case EEP_RF_SILENT: - return pBase->rfSilent; + return le16_to_cpu(pBase->rfSilent); case EEP_OB_5: return pModal[0].ob; case EEP_DB_5: @@ -380,8 +365,6 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, return pModal[1].ob; case EEP_DB_2: return pModal[1].db; - case EEP_MINOR_REV: - return AR5416_VER_MASK; case EEP_TX_MASK: return pBase->txMask; case EEP_RX_MASK: @@ -393,27 +376,27 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, case EEP_TXGAIN_TYPE: return pBase->txGainType; case EEP_OL_PWRCTRL: - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) + if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) return pBase->openLoopPwrCntl ? true : false; else return false; case EEP_RC_CHAIN_MASK: - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) + if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) return pBase->rcChainMask; else return 0; case EEP_DAC_HPWR_5G: - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) + if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_20) return pBase->dacHiPwrMode_5G; else return 0; case EEP_FRAC_N_5G: - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22) + if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_22) return pBase->frac_n_5g; else return 0; case EEP_PWR_TABLE_OFFSET: - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_21) + if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_21) return pBase->pwr_table_offset; else return AR5416_PWR_TABLE_OFFSET_DB; @@ -436,7 +419,7 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah, u8 txRxAttenLocal, int regChainOffset, int i) { ENABLE_REG_RMW_BUFFER(ah); - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { + if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) { txRxAttenLocal = pModal->txRxAttenCh[i]; if (AR_SREV_9280_20_OR_LATER(ah)) { @@ -487,11 +470,13 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, struct ar5416_eeprom_def *eep = &ah->eeprom.def; int i, regChainOffset; u8 txRxAttenLocal; + u32 antCtrlCommon; pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; + antCtrlCommon = le32_to_cpu(pModal->antCtrlCommon); - REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon & 0xffff); + REG_WRITE(ah, AR_PHY_SWITCH_COM, antCtrlCommon & 0xffff); for (i = 0; i < AR5416_MAX_CHAINS; i++) { if (AR_SREV_9280(ah)) { @@ -505,7 +490,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, regChainOffset = i * 0x1000; REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, - pModal->antCtrlChain[i]); + le32_to_cpu(pModal->antCtrlChain[i])); REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & @@ -605,7 +590,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, pModal->thresh62); } - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) { + if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) { REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart); @@ -613,7 +598,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, pModal->txFrameToPaOn); } - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { + if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) { if (IS_CHAN_HT40(chan)) REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, @@ -621,13 +606,14 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, } if (AR_SREV_9280_20_OR_LATER(ah) && - AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) + ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL, AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, pModal->miscBits); - if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) { + if (AR_SREV_9280_20(ah) && + ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_20) { if (IS_CHAN_2GHZ(chan)) REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, eep->baseEepHeader.dacLpMode); @@ -651,7 +637,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, static void ath9k_hw_def_set_addac(struct ath_hw *ah, struct ath9k_channel *chan) { -#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt]) +#define XPA_LVL_FREQ(cnt) (le16_to_cpu(pModal->xpaBiasLvlFreq[cnt])) struct modal_eep_header *pModal; struct ar5416_eeprom_def *eep = &ah->eeprom.def; u8 biaslevel; @@ -798,8 +784,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, pwr_table_offset = ah->eep_ops->get_eeprom(ah, EEP_PWR_TABLE_OFFSET); - if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { + if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) { pdGainOverlap_t2 = pEepData->modalHeader[modalIdx].pdGainOverlap; } else { @@ -1171,10 +1156,8 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, memset(ratesArray, 0, sizeof(ratesArray)); - if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { + if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; - } ath9k_hw_set_def_power_per_rate_table(ah, chan, &ratesArray[0], cfgCtl, @@ -1314,7 +1297,14 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) { - return ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan; + __le16 spch = ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan; + + return le16_to_cpu(spch); +} + +static u8 ath9k_hw_def_get_eepmisc(struct ath_hw *ah) +{ + return ah->eeprom.def.baseEepHeader.eepMisc; } const struct eeprom_ops eep_def_ops = { @@ -1327,5 +1317,6 @@ const struct eeprom_ops eep_def_ops = { .set_board_values = ath9k_hw_def_set_board_values, .set_addac = ath9k_hw_def_set_addac, .set_txpower = ath9k_hw_def_set_txpower, - .get_spur_channel = ath9k_hw_def_get_spur_channel + .get_spur_channel = ath9k_hw_def_get_spur_channel, + .get_eepmisc = ath9k_hw_def_get_eepmisc }; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 20794660d6ae..084ad1bd495f 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -620,6 +620,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, /* Will be cleared in ath9k_start() */ set_bit(ATH_OP_INVALID, &common->op_flags); + sc->airtime_flags = (AIRTIME_USE_TX | AIRTIME_USE_RX | + AIRTIME_USE_NEW_QUEUES); sc->sc_ah = ah; sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 59e3bd0f4c20..58f06ce9a4cf 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -70,10 +70,10 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq, goto out; if (txq->mac80211_qnum >= 0) { - struct list_head *list; + struct ath_acq *acq; - list = &sc->cur_chan->acq[txq->mac80211_qnum]; - if (!list_empty(list)) + acq = &sc->cur_chan->acq[txq->mac80211_qnum]; + if (!list_empty(&acq->acq_new) || !list_empty(&acq->acq_old)) pending = true; } out: diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index fb4ba27d92b7..d79837fe333f 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1002,6 +1002,70 @@ static void ath9k_apply_ampdu_details(struct ath_softc *sc, } } +static void ath_rx_count_airtime(struct ath_softc *sc, + struct ath_rx_status *rs, + struct sk_buff *skb) +{ + struct ath_node *an; + struct ath_acq *acq; + struct ath_vif *avp; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_sta *sta; + struct ieee80211_rx_status *rxs; + const struct ieee80211_rate *rate; + bool is_sgi, is_40, is_sp; + int phy; + u16 len = rs->rs_datalen; + u32 airtime = 0; + u8 tidno, acno; + + if (!ieee80211_is_data(hdr->frame_control)) + return; + + rcu_read_lock(); + + sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL); + if (!sta) + goto exit; + an = (struct ath_node *) sta->drv_priv; + avp = (struct ath_vif *) an->vif->drv_priv; + tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK; + acno = TID_TO_WME_AC(tidno); + acq = &avp->chanctx->acq[acno]; + + rxs = IEEE80211_SKB_RXCB(skb); + + is_sgi = !!(rxs->flag & RX_FLAG_SHORT_GI); + is_40 = !!(rxs->flag & RX_FLAG_40MHZ); + is_sp = !!(rxs->flag & RX_FLAG_SHORTPRE); + + if (!!(rxs->flag & RX_FLAG_HT)) { + /* MCS rates */ + + airtime += ath_pkt_duration(sc, rxs->rate_idx, len, + is_40, is_sgi, is_sp); + } else { + + phy = IS_CCK_RATE(rs->rs_rate) ? WLAN_RC_PHY_CCK : WLAN_RC_PHY_OFDM; + rate = &common->sbands[rxs->band].bitrates[rxs->rate_idx]; + airtime += ath9k_hw_computetxtime(ah, phy, rate->bitrate * 100, + len, rxs->rate_idx, is_sp); + } + + if (!!(sc->airtime_flags & AIRTIME_USE_RX)) { + spin_lock_bh(&acq->lock); + an->airtime_deficit[acno] -= airtime; + if (an->airtime_deficit[acno] <= 0) + __ath_tx_queue_tid(sc, ATH_AN_2_TID(an, tidno)); + spin_unlock_bh(&acq->lock); + } + ath_debug_airtime(sc, an, airtime, 0); +exit: + rcu_read_unlock(); +} + int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) { struct ath_rxbuf *bf; @@ -1148,6 +1212,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ath9k_antenna_check(sc, &rs); ath9k_apply_ampdu_details(sc, &rs, rxs); ath_debug_rate_stats(sc, &rs, skb); + ath_rx_count_airtime(sc, &rs, skb); hdr = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_ack(hdr->frame_control)) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 486afa98a5b8..b727f34796af 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -97,18 +97,6 @@ static void ath_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) dev_kfree_skb(skb); } -void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq) - __acquires(&txq->axq_lock) -{ - spin_lock_bh(&txq->axq_lock); -} - -void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq) - __releases(&txq->axq_lock) -{ - spin_unlock_bh(&txq->axq_lock); -} - void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq) __releases(&txq->axq_lock) { @@ -124,21 +112,44 @@ void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq) ath_tx_status(hw, skb); } -static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid) +void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { - struct list_head *list; struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv; struct ath_chanctx *ctx = avp->chanctx; + struct ath_acq *acq; + struct list_head *tid_list; + u8 acno = TID_TO_WME_AC(tid->tidno); - if (!ctx) + if (!ctx || !list_empty(&tid->list)) return; - list = &ctx->acq[TID_TO_WME_AC(tid->tidno)]; - if (list_empty(&tid->list)) - list_add_tail(&tid->list, list); + + acq = &ctx->acq[acno]; + if ((sc->airtime_flags & AIRTIME_USE_NEW_QUEUES) && + tid->an->airtime_deficit[acno] > 0) + tid_list = &acq->acq_new; + else + tid_list = &acq->acq_old; + + list_add_tail(&tid->list, tid_list); } +void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid) +{ + struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv; + struct ath_chanctx *ctx = avp->chanctx; + struct ath_acq *acq; + + if (!ctx || !list_empty(&tid->list)) + return; + + acq = &ctx->acq[TID_TO_WME_AC(tid->tidno)]; + spin_lock_bh(&acq->lock); + __ath_tx_queue_tid(sc, tid); + spin_unlock_bh(&acq->lock); +} + + void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue) { struct ath_softc *sc = hw->priv; @@ -153,7 +164,7 @@ void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue) ath_txq_lock(sc, txq); tid->has_queued = true; - ath_tx_queue_tid(sc, txq, tid); + ath_tx_queue_tid(sc, tid); ath_txq_schedule(sc, txq); ath_txq_unlock(sc, txq); @@ -660,7 +671,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, skb_queue_splice_tail(&bf_pending, &tid->retry_q); if (!an->sleeping) { - ath_tx_queue_tid(sc, txq, tid); + ath_tx_queue_tid(sc, tid); if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY)) tid->clear_ps_filter = true; @@ -688,6 +699,53 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf) return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); } +static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_txq *txq, + struct ath_buf *bf, struct ath_tx_status *ts) +{ + struct ath_node *an; + struct ath_acq *acq = &sc->cur_chan->acq[txq->mac80211_qnum]; + struct sk_buff *skb; + struct ieee80211_hdr *hdr; + struct ieee80211_hw *hw = sc->hw; + struct ieee80211_tx_rate rates[4]; + struct ieee80211_sta *sta; + int i; + u32 airtime = 0; + + skb = bf->bf_mpdu; + if(!skb) + return; + + hdr = (struct ieee80211_hdr *)skb->data; + memcpy(rates, bf->rates, sizeof(rates)); + + rcu_read_lock(); + + sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); + if(!sta) + goto exit; + + + an = (struct ath_node *) sta->drv_priv; + + airtime += ts->duration * (ts->ts_longretry + 1); + + for(i=0; i < ts->ts_rateindex; i++) + airtime += ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, i) * rates[i].count; + + if (!!(sc->airtime_flags & AIRTIME_USE_TX)) { + spin_lock_bh(&acq->lock); + an->airtime_deficit[txq->mac80211_qnum] -= airtime; + if (an->airtime_deficit[txq->mac80211_qnum] <= 0) + __ath_tx_queue_tid(sc, ath_get_skb_tid(sc, an, skb)); + spin_unlock_bh(&acq->lock); + } + ath_debug_airtime(sc, an, 0, airtime); + +exit: + rcu_read_unlock(); +} + static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, struct ath_tx_status *ts, struct ath_buf *bf, struct list_head *bf_head) @@ -709,6 +767,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, ts->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, ts->ts_rateindex); + ath_tx_count_airtime(sc, txq, bf, ts); hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data; sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); @@ -1068,8 +1127,8 @@ finish: * width - 0 for 20 MHz, 1 for 40 MHz * half_gi - to use 4us v/s 3.6 us for symbol time */ -static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, - int width, int half_gi, bool shortPreamble) +u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, + int width, int half_gi, bool shortPreamble) { u32 nbits, nsymbits, duration, nsymbols; int streams; @@ -1151,8 +1210,9 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf, if (is_40) { u8 power_ht40delta; struct ar5416_eeprom_def *eep = &ah->eeprom.def; + u16 eeprom_rev = ah->eep_ops->get_eeprom_rev(ah); - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) { + if (eeprom_rev >= AR5416_EEP_MINOR_VER_2) { bool is_2ghz; struct modal_eep_header *pmodal; @@ -1467,7 +1527,7 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq, } static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, bool *stop) + struct ath_atx_tid *tid) { struct ath_buf *bf; struct ieee80211_tx_info *tx_info; @@ -1489,7 +1549,6 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) || (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) { __skb_queue_tail(&tid->retry_q, bf->bf_mpdu); - *stop = true; return false; } @@ -1613,7 +1672,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) ath_txq_lock(sc, txq); tid->clear_ps_filter = true; if (ath_tid_has_buffered(tid)) { - ath_tx_queue_tid(sc, txq, tid); + ath_tx_queue_tid(sc, tid); ath_txq_schedule(sc, txq); } ath_txq_unlock_complete(sc, txq); @@ -1912,9 +1971,10 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_atx_tid *tid, *last_tid; + struct ath_atx_tid *tid; struct list_head *tid_list; - bool sent = false; + struct ath_acq *acq; + bool active = AIRTIME_ACTIVE(sc->airtime_flags); if (txq->mac80211_qnum < 0) return; @@ -1923,48 +1983,55 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) return; spin_lock_bh(&sc->chan_lock); - tid_list = &sc->cur_chan->acq[txq->mac80211_qnum]; - - if (list_empty(tid_list)) { - spin_unlock_bh(&sc->chan_lock); - return; - } - rcu_read_lock(); + acq = &sc->cur_chan->acq[txq->mac80211_qnum]; - last_tid = list_entry(tid_list->prev, struct ath_atx_tid, list); - while (!list_empty(tid_list)) { - bool stop = false; - - if (sc->cur_chan->stopped) - break; - - tid = list_first_entry(tid_list, struct ath_atx_tid, list); - list_del_init(&tid->list); + if (sc->cur_chan->stopped) + goto out; - if (ath_tx_sched_aggr(sc, txq, tid, &stop)) - sent = true; +begin: + tid_list = &acq->acq_new; + if (list_empty(tid_list)) { + tid_list = &acq->acq_old; + if (list_empty(tid_list)) + goto out; + } + tid = list_first_entry(tid_list, struct ath_atx_tid, list); - /* - * add tid to round-robin queue if more frames - * are pending for the tid - */ - if (ath_tid_has_buffered(tid)) - ath_tx_queue_tid(sc, txq, tid); + if (active && tid->an->airtime_deficit[txq->mac80211_qnum] <= 0) { + spin_lock_bh(&acq->lock); + tid->an->airtime_deficit[txq->mac80211_qnum] += ATH_AIRTIME_QUANTUM; + list_move_tail(&tid->list, &acq->acq_old); + spin_unlock_bh(&acq->lock); + goto begin; + } - if (stop) - break; + if (!ath_tid_has_buffered(tid)) { + spin_lock_bh(&acq->lock); + if ((tid_list == &acq->acq_new) && !list_empty(&acq->acq_old)) + list_move_tail(&tid->list, &acq->acq_old); + else { + list_del_init(&tid->list); + } + spin_unlock_bh(&acq->lock); + goto begin; + } - if (tid == last_tid) { - if (!sent) - break; - sent = false; - last_tid = list_entry(tid_list->prev, - struct ath_atx_tid, list); + /* + * If we succeed in scheduling something, immediately restart to make + * sure we keep the HW busy. + */ + if(ath_tx_sched_aggr(sc, txq, tid)) { + if (!active) { + spin_lock_bh(&acq->lock); + list_move_tail(&tid->list, &acq->acq_old); + spin_unlock_bh(&acq->lock); } + goto begin; } +out: rcu_read_unlock(); spin_unlock_bh(&sc->chan_lock); } @@ -2818,6 +2885,9 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) struct ath_atx_tid *tid; int tidno, acno; + for (acno = 0; acno < IEEE80211_NUM_ACS; acno++) + an->airtime_deficit[acno] = ATH_AIRTIME_QUANTUM; + for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { tid = ath_node_to_tid(an, tidno); tid->an = an; |