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
This commit is contained in:
Kalle Valo 2017-01-01 20:48:37 +02:00
commit 50913e32c6
27 changed files with 732 additions and 399 deletions

View File

@ -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", "boot get otp board id result 0x%08x board_id %d chip_id %d\n",
result, board_id, chip_id); 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; return -EOPNOTSUPP;
}
ar->id.bmi_ids_valid = true; ar->id.bmi_ids_valid = true;
ar->id.bmi_board_id = board_id; 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) static void ath10k_core_restart(struct work_struct *work)
{ {
struct ath10k *ar = container_of(work, struct ath10k, restart_work); struct ath10k *ar = container_of(work, struct ath10k, restart_work);
int ret;
set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); 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); 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) static void ath10k_core_set_coverage_class_work(struct work_struct *work)

View File

@ -46,7 +46,7 @@
#define WMI_READY_TIMEOUT (5 * HZ) #define WMI_READY_TIMEOUT (5 * HZ)
#define ATH10K_FLUSH_TIMEOUT_HZ (5 * HZ) #define ATH10K_FLUSH_TIMEOUT_HZ (5 * HZ)
#define ATH10K_CONNECTION_LOSS_HZ (3 * HZ) #define ATH10K_CONNECTION_LOSS_HZ (3 * HZ)
#define ATH10K_NUM_CHANS 39 #define ATH10K_NUM_CHANS 40
/* Antenna noise floor */ /* Antenna noise floor */
#define ATH10K_DEFAULT_NOISE_FLOOR -95 #define ATH10K_DEFAULT_NOISE_FLOOR -95

View File

@ -21,6 +21,7 @@
#include <linux/utsname.h> #include <linux/utsname.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/devcoredump.h>
#include "core.h" #include "core.h"
#include "debug.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); 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_fw_crash_data *crash_data = ar->debug.fw_crash_data;
struct ath10k_dump_file_data *dump_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)); sizeof(crash_data->registers));
sofar += sizeof(*dump_tlv) + 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); spin_unlock_bh(&ar->data_lock);
return dump_data; 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) static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file)
{ {
struct ath10k *ar = inode->i_private; struct ath10k *ar = inode->i_private;
struct ath10k_dump_file_data *dump; 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) if (!dump)
return -ENODATA; return -ENODATA;

View File

@ -84,6 +84,9 @@ struct ath10k_fw_crash_data *
ath10k_debug_get_new_fw_crash_data(struct ath10k *ar); ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len); 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++) #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
void ath10k_debug_get_et_strings(struct ieee80211_hw *hw, 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; 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_DFS_STAT_INC(ar, c) do { } while (0)
#define ath10k_debug_get_et_strings NULL #define ath10k_debug_get_et_strings NULL

View File

@ -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); size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf);
dma_free_coherent(ar->dev, size, htt->txbuf.vaddr, htt->txbuf.paddr); 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) 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, size,
htt->frag_desc.vaddr, htt->frag_desc.vaddr,
htt->frag_desc.paddr); htt->frag_desc.paddr);
htt->frag_desc.vaddr = NULL;
} }
static int ath10k_htt_tx_alloc_cont_frag_desc(struct ath10k_htt *htt) static int ath10k_htt_tx_alloc_cont_frag_desc(struct ath10k_htt *htt)

View File

@ -512,7 +512,7 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
/* Target specific defines for WMI-TLV firmware */ /* Target specific defines for WMI-TLV firmware */
#define TARGET_TLV_NUM_VDEVS 4 #define TARGET_TLV_NUM_VDEVS 4
#define TARGET_TLV_NUM_STATIONS 32 #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_TDLS_VDEVS 1
#define TARGET_TLV_NUM_TIDS ((TARGET_TLV_NUM_PEERS) * 2) #define TARGET_TLV_NUM_TIDS ((TARGET_TLV_NUM_PEERS) * 2)
#define TARGET_TLV_NUM_MSDU_DESC (1024 + 32) #define TARGET_TLV_NUM_MSDU_DESC (1024 + 32)

View File

@ -1227,6 +1227,36 @@ static int ath10k_monitor_recalc(struct ath10k *ar)
return ath10k_monitor_stop(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) static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif)
{ {
struct ath10k *ar = arvif->ar; 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, rts_cts |= SM(WMI_RTSCTS_FOR_SECOND_RATESERIES,
WMI_RTSCTS_PROFILE); 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, return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
rts_cts); rts_cts);
} }
@ -3495,7 +3528,6 @@ static int ath10k_mac_tx_submit(struct ath10k *ar,
*/ */
static int ath10k_mac_tx(struct ath10k *ar, static int ath10k_mac_tx(struct ath10k *ar,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
enum ath10k_hw_txrx_mode txmode, enum ath10k_hw_txrx_mode txmode,
enum ath10k_mac_tx_path txpath, enum ath10k_mac_tx_path txpath,
struct sk_buff *skb) 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); txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); 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) { if (ret) {
ath10k_warn(ar, "failed to transmit offchannel frame: %d\n", ath10k_warn(ar, "failed to transmit offchannel frame: %d\n",
ret); ret);
@ -3824,7 +3856,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
spin_unlock_bh(&ar->htt.tx_lock); 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)) { if (unlikely(ret)) {
ath10k_warn(ar, "failed to push frame: %d\n", 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); 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) { if (ret) {
ath10k_warn(ar, "failed to transmit frame: %d\n", ret); ath10k_warn(ar, "failed to transmit frame: %d\n", ret);
if (is_htt) { if (is_htt) {
@ -4669,7 +4701,8 @@ static int ath10k_mac_txpower_recalc(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
list_for_each_entry(arvif, &ar->arvifs, list) { list_for_each_entry(arvif, &ar->arvifs, list) {
WARN_ON(arvif->txpower < 0); if (arvif->txpower <= 0)
continue;
if (txpower == -1) if (txpower == -1)
txpower = arvif->txpower; txpower = arvif->txpower;
@ -4677,8 +4710,8 @@ static int ath10k_mac_txpower_recalc(struct ath10k *ar)
txpower = min(txpower, arvif->txpower); txpower = min(txpower, arvif->txpower);
} }
if (WARN_ON(txpower == -1)) if (txpower == -1)
return -EINVAL; return 0;
ret = ath10k_mac_txpower_setup(ar, txpower); ret = ath10k_mac_txpower_setup(ar, txpower);
if (ret) { 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); 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); spin_lock_bh(&ar->htt.tx_lock);
ath10k_mac_vif_tx_unlock_all(arvif); ath10k_mac_vif_tx_unlock_all(arvif);
spin_unlock_bh(&ar->htt.tx_lock); 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) { if (changed & BSS_CHANGED_ERP_CTS_PROT) {
arvif->use_cts_prot = info->use_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); ret = ath10k_recalc_rtscts_prot(arvif);
if (ret) if (ret)
ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n", ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n",
arvif->vdev_id, ret); arvif->vdev_id, ret);
vdev_param = ar->wmi.vdev_param->protection_mode; if (ath10k_mac_can_set_cts_prot(arvif)) {
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, ret = ath10k_mac_set_cts_prot(arvif);
info->use_cts_prot ? 1 : 0);
if (ret) if (ret)
ath10k_warn(ar, "failed to set protection mode %d on vdev %i: %d\n", ath10k_warn(ar, "failed to set cts protection for vdev %d: %d\n",
info->use_cts_prot, arvif->vdev_id, ret); arvif->vdev_id, ret);
}
} }
if (changed & BSS_CHANGED_ERP_SLOT) { if (changed & BSS_CHANGED_ERP_SLOT) {
@ -7364,6 +7399,13 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
arvif->is_up = true; 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); mutex_unlock(&ar->conf_mutex);
return 0; return 0;
@ -7548,6 +7590,7 @@ static const struct ieee80211_channel ath10k_5ghz_channels[] = {
CHAN5G(157, 5785, 0), CHAN5G(157, 5785, 0),
CHAN5G(161, 5805, 0), CHAN5G(161, 5805, 0),
CHAN5G(165, 5825, 0), CHAN5G(165, 5825, 0),
CHAN5G(169, 5845, 0),
}; };
struct ath10k *ath10k_mac_create(size_t priv_size) struct ath10k *ath10k_mac_create(size_t priv_size)

View File

@ -1973,7 +1973,7 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar)
} }
break; break;
case QCA9377_1_0_DEVICE_ID: case QCA9377_1_0_DEVICE_ID:
return 2; return 4;
} }
ath10k_warn(ar, "unknown number of banks, assuming 1\n"); 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, setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry,
(unsigned long)ar); (unsigned long)ar);
if (QCA_REV_6174(ar)) if (QCA_REV_6174(ar) || QCA_REV_9377(ar))
ath10k_pci_override_ce_config(ar); ath10k_pci_override_ce_config(ar);
ret = ath10k_pci_alloc_pipes(ar); ret = ath10k_pci_alloc_pipes(ar);

View File

@ -1105,8 +1105,10 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
struct ath10k_fw_stats_pdev *dst; struct ath10k_fw_stats_pdev *dst;
src = data; src = data;
if (data_len < sizeof(*src)) if (data_len < sizeof(*src)) {
kfree(tb);
return -EPROTO; return -EPROTO;
}
data += sizeof(*src); data += sizeof(*src);
data_len -= 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; struct ath10k_fw_stats_vdev *dst;
src = data; src = data;
if (data_len < sizeof(*src)) if (data_len < sizeof(*src)) {
kfree(tb);
return -EPROTO; return -EPROTO;
}
data += sizeof(*src); data += sizeof(*src);
data_len -= 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; struct ath10k_fw_stats_peer *dst;
src = data; src = data;
if (data_len < sizeof(*src)) if (data_len < sizeof(*src)) {
kfree(tb);
return -EPROTO; return -EPROTO;
}
data += sizeof(*src); data += sizeof(*src);
data_len -= sizeof(*src); data_len -= sizeof(*src);

View File

@ -524,7 +524,7 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
return true; return true;
/* Setup rf parameters */ /* 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++) for (i = 0; i < ah->iniBank6.ia_rows; i++)
ah->analogBank6Data[i] = INI_RA(&ah->iniBank6, i, modesIndex); ah->analogBank6Data[i] = INI_RA(&ah->iniBank6, i, modesIndex);

View File

@ -108,8 +108,7 @@ static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
{ {
u32 rxgain_type; u32 rxgain_type;
if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_17) {
AR5416_EEP_MINOR_VER_17) {
rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE); rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) 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) 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) >= if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) {
AR5416_EEP_MINOR_VER_19) {
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_high_power_tx_gain_9280_2); ar9280Modes_high_power_tx_gain_9280_2);

View File

@ -53,7 +53,7 @@ static const struct ar9300_eeprom ar9300_default = {
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
.opCapFlags = { .opCapFlags = {
.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0, .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN,
}, },
.rfSilent = 0, .rfSilent = 0,
.blueToothOptions = 0, .blueToothOptions = 0,
@ -631,7 +631,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
.opCapFlags = { .opCapFlags = {
.opFlags = AR5416_OPFLAGS_11A, .opFlags = AR5416_OPFLAGS_11A,
.eepMisc = 0, .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN,
}, },
.rfSilent = 0, .rfSilent = 0,
.blueToothOptions = 0, .blueToothOptions = 0,
@ -1210,7 +1210,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
.opCapFlags = { .opCapFlags = {
.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0, .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN,
}, },
.rfSilent = 0, .rfSilent = 0,
.blueToothOptions = 0, .blueToothOptions = 0,
@ -1789,7 +1789,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
.opCapFlags = { .opCapFlags = {
.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0, .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN,
}, },
.rfSilent = 0, .rfSilent = 0,
.blueToothOptions = 0, .blueToothOptions = 0,
@ -2367,7 +2367,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
.txrxMask = 0x33, /* 4 bits tx and 4 bits rx */ .txrxMask = 0x33, /* 4 bits tx and 4 bits rx */
.opCapFlags = { .opCapFlags = {
.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0, .eepMisc = AR9300_EEPMISC_LITTLE_ENDIAN,
}, },
.rfSilent = 0, .rfSilent = 0,
.blueToothOptions = 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)); AR5416_OPFLAGS_N_5G_HT20));
PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags.opFlags & PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags.opFlags &
AR5416_OPFLAGS_N_5G_HT40)); 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("RF Silent", pBase->rfSilent);
PR_EEP("BT option", pBase->blueToothOptions); PR_EEP("BT option", pBase->blueToothOptions);
PR_EEP("Device Cap", pBase->deviceCap); 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 = { const struct eeprom_ops eep_ar9300_ops = {
.check_eeprom = ath9k_hw_ar9300_check_eeprom, .check_eeprom = ath9k_hw_ar9300_check_eeprom,
.get_eeprom = ath9k_hw_ar9300_get_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_board_values = ath9k_hw_ar9300_set_board_values,
.set_addac = ath9k_hw_ar9300_set_addac, .set_addac = ath9k_hw_ar9300_set_addac,
.set_txpower = ath9k_hw_ar9300_set_txpower, .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
}; };

View File

@ -38,7 +38,6 @@
#define AR9300_NUM_CTLS_2G 12 #define AR9300_NUM_CTLS_2G 12
#define AR9300_NUM_BAND_EDGES_5G 8 #define AR9300_NUM_BAND_EDGES_5G 8
#define AR9300_NUM_BAND_EDGES_2G 4 #define AR9300_NUM_BAND_EDGES_2G 4
#define AR9300_EEPMISC_BIG_ENDIAN 0x01
#define AR9300_EEPMISC_WOW 0x02 #define AR9300_EEPMISC_WOW 0x02
#define AR9300_CUSTOMER_DATA_SIZE 20 #define AR9300_CUSTOMER_DATA_SIZE 20
@ -70,6 +69,9 @@
#define AR9300_BASE_ADDR 0x3ff #define AR9300_BASE_ADDR 0x3ff
#define AR9300_BASE_ADDR_512 0x1ff #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 \ #define AR9300_OTP_BASE \
((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30000 : 0x14000) ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30000 : 0x14000)
#define AR9300_OTP_STATUS \ #define AR9300_OTP_STATUS \

View File

@ -112,6 +112,8 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
#define ATH_TXFIFO_DEPTH 8 #define ATH_TXFIFO_DEPTH 8
#define ATH_TX_ERROR 0x01 #define ATH_TX_ERROR 0x01
#define ATH_AIRTIME_QUANTUM 300 /* usec */
/* Stop tx traffic 1ms before the GO goes away */ /* Stop tx traffic 1ms before the GO goes away */
#define ATH_P2P_PS_STOP_TIME 1000 #define ATH_P2P_PS_STOP_TIME 1000
@ -247,6 +249,9 @@ struct ath_atx_tid {
bool has_queued; 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_node {
struct ath_softc *sc; struct ath_softc *sc;
struct ieee80211_sta *sta; /* station struct we're part of */ struct ieee80211_sta *sta; /* station struct we're part of */
@ -258,9 +263,12 @@ struct ath_node {
bool sleeping; bool sleeping;
bool no_ps_filter; bool no_ps_filter;
s64 airtime_deficit[IEEE80211_NUM_ACS];
u32 airtime_rx_start;
#ifdef CONFIG_ATH9K_STATION_STATISTICS #ifdef CONFIG_ATH9K_STATION_STATISTICS
struct ath_rx_rate_stats rx_rate_stats; struct ath_rx_rate_stats rx_rate_stats;
struct ath_airtime_stats airtime_stats;
#endif #endif
u8 key_idx[4]; u8 key_idx[4];
@ -317,10 +325,16 @@ struct ath_rx {
/* Channel Context */ /* Channel Context */
/*******************/ /*******************/
struct ath_acq {
struct list_head acq_new;
struct list_head acq_old;
spinlock_t lock;
};
struct ath_chanctx { struct ath_chanctx {
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
struct list_head vifs; struct list_head vifs;
struct list_head acq[IEEE80211_NUM_ACS]; struct ath_acq acq[IEEE80211_NUM_ACS];
int hw_queue_base; int hw_queue_base;
/* do not dereference, use for comparison only */ /* 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 */ #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); void ath_startrecv(struct ath_softc *sc);
bool ath_stoprecv(struct ath_softc *sc); bool ath_stoprecv(struct ath_softc *sc);
u32 ath_calcrxfilter(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); void ath_rx_cleanup(struct ath_softc *sc);
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp); 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); 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_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq);
void ath_tx_cleanupq(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); 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_tx_init(struct ath_softc *sc, int nbufs);
int ath_txq_update(struct ath_softc *sc, int qnum, int ath_txq_update(struct ath_softc *sc, int qnum,
struct ath9k_tx_queue_info *q); 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_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop);
void ath_assign_seq(struct ath_common *common, struct sk_buff *skb); void ath_assign_seq(struct ath_common *common, struct sk_buff *skb);
int ath_tx_start(struct ieee80211_hw *hw, 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 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 ath_softc {
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct device *dev; struct device *dev;
@ -1005,6 +1033,8 @@ struct ath_softc {
short nbcnvifs; short nbcnvifs;
unsigned long ps_usecount; unsigned long ps_usecount;
u16 airtime_flags; /* AIRTIME_* */
struct ath_rx rx; struct ath_rx rx;
struct ath_tx tx; struct ath_tx tx;
struct ath_beacon beacon; struct ath_beacon beacon;

View File

@ -118,8 +118,11 @@ void ath_chanctx_init(struct ath_softc *sc)
INIT_LIST_HEAD(&ctx->vifs); INIT_LIST_HEAD(&ctx->vifs);
ctx->txpower = ATH_TXPOWER_MAX; ctx->txpower = ATH_TXPOWER_MAX;
ctx->flush_timeout = HZ / 5; /* 200ms */ ctx->flush_timeout = HZ / 5; /* 200ms */
for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) {
INIT_LIST_HEAD(&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; ctx->txpower = ATH_TXPOWER_MAX;
cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20); cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
for (i = 0; i < ARRAY_SIZE(ctx->acq); i++) for (i = 0; i < ARRAY_SIZE(ctx->acq); i++) {
INIT_LIST_HEAD(&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; sc->offchannel.chan.offchannel = true;
} }

View File

@ -1399,5 +1399,8 @@ int ath9k_init_debug(struct ath_hw *ah)
debugfs_create_file("tpc", S_IRUSR | S_IWUSR, debugfs_create_file("tpc", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc, &fops_tpc); 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; return 0;
} }

View File

@ -221,6 +221,11 @@ struct ath_rx_rate_stats {
} cck_stats[4]; } cck_stats[4];
}; };
struct ath_airtime_stats {
u32 rx_airtime;
u32 tx_airtime;
};
#define ANT_MAIN 0 #define ANT_MAIN 0
#define ANT_ALT 1 #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, void ath_debug_rate_stats(struct ath_softc *sc,
struct ath_rx_status *rs, struct ath_rx_status *rs,
struct sk_buff *skb); struct sk_buff *skb);
void ath_debug_airtime(struct ath_softc *sc,
struct ath_node *an,
u32 rx, u32 tx);
#else #else
static inline void ath_debug_rate_stats(struct ath_softc *sc, static inline void ath_debug_rate_stats(struct ath_softc *sc,
struct ath_rx_status *rs, struct ath_rx_status *rs,
struct sk_buff *skb) 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 /* CONFIG_ATH9K_STATION_STATISTICS */
#endif /* DEBUG_H */ #endif /* DEBUG_H */

View File

@ -242,6 +242,59 @@ static const struct file_operations fops_node_recv = {
.llseek = default_llseek, .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, void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, 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_aggr", S_IRUGO, dir, an, &fops_node_aggr);
debugfs_create_file("node_recv", S_IRUGO, dir, an, &fops_node_recv); debugfs_create_file("node_recv", S_IRUGO, dir, an, &fops_node_recv);
debugfs_create_file("airtime", S_IRUGO, dir, an, &fops_airtime);
} }

View File

@ -160,6 +160,7 @@ int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size)
u16 magic; u16 magic;
u16 *eepdata; u16 *eepdata;
int i; int i;
bool needs_byteswap = false;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
@ -167,32 +168,41 @@ int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size)
return -EIO; return -EIO;
} }
*swap_needed = false;
if (swab16(magic) == AR5416_EEPROM_MAGIC) { 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) { if (ah->ah_flags & AH_NO_EEP_SWAP) {
ath_info(common, ath_info(common,
"Ignoring endianness difference in EEPROM magic bytes.\n"); "Ignoring endianness difference in EEPROM magic bytes.\n");
} else { } else {
*swap_needed = true;
}
} else if (magic != AR5416_EEPROM_MAGIC) {
if (ath9k_hw_use_flash(ah))
return 0;
ath_err(common,
"Invalid EEPROM Magic (0x%04x).\n", magic);
return -EINVAL;
}
eepdata = (u16 *)(&ah->eeprom); eepdata = (u16 *)(&ah->eeprom);
if (*swap_needed) {
ath_dbg(common, EEPROM,
"EEPROM Endianness is not native.. Changing.\n");
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
eepdata[i] = swab16(eepdata[i]); eepdata[i] = swab16(eepdata[i]);
} }
}
if (ah->eep_ops->get_eepmisc(ah) & AR5416_EEPMISC_BIG_ENDIAN) {
*swap_needed = true;
ath_dbg(common, EEPROM,
"Big Endian EEPROM detected according to EEPMISC register.\n");
} else {
*swap_needed = false;
}
return 0; return 0;
} }

View File

@ -23,6 +23,17 @@
#include <net/cfg80211.h> #include <net/cfg80211.h>
#include "ar9003_eeprom.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 #ifdef __BIG_ENDIAN
#define AR5416_EEPROM_MAGIC 0x5aa5 #define AR5416_EEPROM_MAGIC 0x5aa5
#else #else
@ -99,7 +110,6 @@
#define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x)) #define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x))
#define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM)) #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) && \ #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \ #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_NO_BACK_VER 0x1
#define AR5416_EEP_VER 0xE #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_VER_MINOR_MASK 0x0FFF
#define AR5416_EEP_MINOR_VER_2 0x2 #define AR5416_EEP_MINOR_VER_2 0x2
#define AR5416_EEP_MINOR_VER_3 0x3 #define AR5416_EEP_MINOR_VER_3 0x3
@ -161,6 +173,9 @@
#define AR5416_EEP_TXGAIN_ORIGINAL 0 #define AR5416_EEP_TXGAIN_ORIGINAL 0
#define AR5416_EEP_TXGAIN_HIGH_POWER 1 #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_START_LOC 64
#define AR5416_EEP4K_NUM_2G_CAL_PIERS 3 #define AR5416_EEP4K_NUM_2G_CAL_PIERS 3
#define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3 #define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3
@ -174,7 +189,6 @@
#define AR9280_TX_GAIN_TABLE_SIZE 22 #define AR9280_TX_GAIN_TABLE_SIZE 22
#define AR9287_EEP_VER 0xE #define AR9287_EEP_VER 0xE
#define AR9287_EEP_VER_MINOR_MASK 0xFFF
#define AR9287_EEP_MINOR_VER_1 0x1 #define AR9287_EEP_MINOR_VER_1 0x1
#define AR9287_EEP_MINOR_VER_2 0x2 #define AR9287_EEP_MINOR_VER_2 0x2
#define AR9287_EEP_MINOR_VER_3 0x3 #define AR9287_EEP_MINOR_VER_3 0x3
@ -191,7 +205,6 @@
#define AR9287_NUM_CTLS 12 #define AR9287_NUM_CTLS 12
#define AR9287_NUM_BAND_EDGES 4 #define AR9287_NUM_BAND_EDGES 4
#define AR9287_PD_GAIN_ICEPTS 1 #define AR9287_PD_GAIN_ICEPTS 1
#define AR9287_EEPMISC_BIG_ENDIAN 0x01
#define AR9287_EEPMISC_WOW 0x02 #define AR9287_EEPMISC_WOW 0x02
#define AR9287_MAX_CHAINS 2 #define AR9287_MAX_CHAINS 2
#define AR9287_ANT_16S 32 #define AR9287_ANT_16S 32
@ -228,7 +241,6 @@ enum eeprom_param {
EEP_DB_5, EEP_DB_5,
EEP_OB_2, EEP_OB_2,
EEP_DB_2, EEP_DB_2,
EEP_MINOR_REV,
EEP_TX_MASK, EEP_TX_MASK,
EEP_RX_MASK, EEP_RX_MASK,
EEP_FSTCLK_5G, EEP_FSTCLK_5G,
@ -269,19 +281,19 @@ enum ath9k_hal_freq_band {
}; };
struct base_eep_header { struct base_eep_header {
u16 length; __le16 length;
u16 checksum; __le16 checksum;
u16 version; __le16 version;
u8 opCapFlags; u8 opCapFlags;
u8 eepMisc; u8 eepMisc;
u16 regDmn[2]; __le16 regDmn[2];
u8 macAddr[6]; u8 macAddr[6];
u8 rxMask; u8 rxMask;
u8 txMask; u8 txMask;
u16 rfSilent; __le16 rfSilent;
u16 blueToothOptions; __le16 blueToothOptions;
u16 deviceCap; __le16 deviceCap;
u32 binBuildNumber; __le32 binBuildNumber;
u8 deviceType; u8 deviceType;
u8 pwdclkind; u8 pwdclkind;
u8 fastClk5g; u8 fastClk5g;
@ -299,33 +311,33 @@ struct base_eep_header {
} __packed; } __packed;
struct base_eep_header_4k { struct base_eep_header_4k {
u16 length; __le16 length;
u16 checksum; __le16 checksum;
u16 version; __le16 version;
u8 opCapFlags; u8 opCapFlags;
u8 eepMisc; u8 eepMisc;
u16 regDmn[2]; __le16 regDmn[2];
u8 macAddr[6]; u8 macAddr[6];
u8 rxMask; u8 rxMask;
u8 txMask; u8 txMask;
u16 rfSilent; __le16 rfSilent;
u16 blueToothOptions; __le16 blueToothOptions;
u16 deviceCap; __le16 deviceCap;
u32 binBuildNumber; __le32 binBuildNumber;
u8 deviceType; u8 deviceType;
u8 txGainType; u8 txGainType;
} __packed; } __packed;
struct spur_chan { struct spur_chan {
u16 spurChan; __le16 spurChan;
u8 spurRangeLow; u8 spurRangeLow;
u8 spurRangeHigh; u8 spurRangeHigh;
} __packed; } __packed;
struct modal_eep_header { struct modal_eep_header {
u32 antCtrlChain[AR5416_MAX_CHAINS]; __le32 antCtrlChain[AR5416_MAX_CHAINS];
u32 antCtrlCommon; __le32 antCtrlCommon;
u8 antennaGainCh[AR5416_MAX_CHAINS]; u8 antennaGainCh[AR5416_MAX_CHAINS];
u8 switchSettling; u8 switchSettling;
u8 txRxAttenCh[AR5416_MAX_CHAINS]; u8 txRxAttenCh[AR5416_MAX_CHAINS];
@ -360,7 +372,7 @@ struct modal_eep_header {
u8 db_ch1; u8 db_ch1;
u8 lna_ctl; u8 lna_ctl;
u8 miscBits; u8 miscBits;
u16 xpaBiasLvlFreq[3]; __le16 xpaBiasLvlFreq[3];
u8 futureModal[6]; u8 futureModal[6];
struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS]; struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
@ -374,8 +386,8 @@ struct calDataPerFreqOpLoop {
} __packed; } __packed;
struct modal_eep_4k_header { struct modal_eep_4k_header {
u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; __le32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
u32 antCtrlCommon; __le32 antCtrlCommon;
u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS]; u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS];
u8 switchSettling; u8 switchSettling;
u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS]; u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS];
@ -439,19 +451,19 @@ struct modal_eep_4k_header {
} __packed; } __packed;
struct base_eep_ar9287_header { struct base_eep_ar9287_header {
u16 length; __le16 length;
u16 checksum; __le16 checksum;
u16 version; __le16 version;
u8 opCapFlags; u8 opCapFlags;
u8 eepMisc; u8 eepMisc;
u16 regDmn[2]; __le16 regDmn[2];
u8 macAddr[6]; u8 macAddr[6];
u8 rxMask; u8 rxMask;
u8 txMask; u8 txMask;
u16 rfSilent; __le16 rfSilent;
u16 blueToothOptions; __le16 blueToothOptions;
u16 deviceCap; __le16 deviceCap;
u32 binBuildNumber; __le32 binBuildNumber;
u8 deviceType; u8 deviceType;
u8 openLoopPwrCntl; u8 openLoopPwrCntl;
int8_t pwrTableOffset; int8_t pwrTableOffset;
@ -461,8 +473,8 @@ struct base_eep_ar9287_header {
} __packed; } __packed;
struct modal_eep_ar9287_header { struct modal_eep_ar9287_header {
u32 antCtrlChain[AR9287_MAX_CHAINS]; __le32 antCtrlChain[AR9287_MAX_CHAINS];
u32 antCtrlCommon; __le32 antCtrlCommon;
int8_t antennaGainCh[AR9287_MAX_CHAINS]; int8_t antennaGainCh[AR9287_MAX_CHAINS];
u8 switchSettling; u8 switchSettling;
u8 txRxAttenCh[AR9287_MAX_CHAINS]; u8 txRxAttenCh[AR9287_MAX_CHAINS];
@ -653,6 +665,7 @@ struct eeprom_ops {
u16 cfgCtl, u8 twiceAntennaReduction, u16 cfgCtl, u8 twiceAntennaReduction,
u8 powerLimit, bool test); u8 powerLimit, bool test);
u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); 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); void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val);

View File

@ -20,12 +20,17 @@
static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah) 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) 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)) #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, static u32 ath9k_dump_4k_modal_eeprom(char *buf, u32 len, u32 size,
struct modal_eep_4k_header *modal_hdr) struct modal_eep_4k_header *modal_hdr)
{ {
PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]); PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon); PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]); PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
PR_EEP("Switch Settle", modal_hdr->switchSettling); PR_EEP("Switch Settle", modal_hdr->switchSettling);
PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]); 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 ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
struct base_eep_header_4k *pBase = &eep->baseEepHeader; struct base_eep_header_4k *pBase = &eep->baseEepHeader;
u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber);
if (!dump_base_hdr) { if (!dump_base_hdr) {
len += scnprintf(buf + len, size - len, 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; goto out;
} }
PR_EEP("Major Version", pBase->version >> 12); PR_EEP("Major Version", ath9k_hw_4k_get_eeprom_ver(ah));
PR_EEP("Minor Version", pBase->version & 0xFFF); PR_EEP("Minor Version", ath9k_hw_4k_get_eeprom_rev(ah));
PR_EEP("Checksum", pBase->checksum); PR_EEP("Checksum", le16_to_cpu(pBase->checksum));
PR_EEP("Length", pBase->length); PR_EEP("Length", le16_to_cpu(pBase->length));
PR_EEP("RegDomain1", pBase->regDmn[0]); PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));
PR_EEP("RegDomain2", pBase->regDmn[1]); PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));
PR_EEP("TX Mask", pBase->txMask); PR_EEP("TX Mask", pBase->txMask);
PR_EEP("RX Mask", pBase->rxMask); PR_EEP("RX Mask", pBase->rxMask);
PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); 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)); AR5416_OPFLAGS_N_5G_HT20));
PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags & PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
AR5416_OPFLAGS_N_5G_HT40)); AR5416_OPFLAGS_N_5G_HT40));
PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01)); PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN));
PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF); PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF);
PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF); PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF);
PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF);
PR_EEP("TX Gain type", pBase->txGainType); PR_EEP("TX Gain type", pBase->txGainType);
len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", 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; return err;
if (need_swap) if (need_swap)
el = swab16(eep->baseEepHeader.length); el = swab16((__force u16)eep->baseEepHeader.length);
else else
el = eep->baseEepHeader.length; el = le16_to_cpu(eep->baseEepHeader.length);
el = min(el / sizeof(u16), SIZE_EEPROM_4K); el = min(el / sizeof(u16), SIZE_EEPROM_4K);
if (!ath9k_hw_nvram_validate_checksum(ah, el)) if (!ath9k_hw_nvram_validate_checksum(ah, el))
return -EINVAL; return -EINVAL;
if (need_swap) { if (need_swap) {
u32 integer; EEPROM_FIELD_SWAB16(eep->baseEepHeader.length);
u16 word; 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);
word = swab16(eep->baseEepHeader.length); for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++)
eep->baseEepHeader.length = word; EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlChain[i]);
word = swab16(eep->baseEepHeader.checksum); for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++)
eep->baseEepHeader.checksum = word; EEPROM_FIELD_SWAB16(
eep->modalHeader.spurChans[i].spurChan);
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;
}
} }
if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER, 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 ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
struct modal_eep_4k_header *pModal = &eep->modalHeader; struct modal_eep_4k_header *pModal = &eep->modalHeader;
struct base_eep_header_4k *pBase = &eep->baseEepHeader; struct base_eep_header_4k *pBase = &eep->baseEepHeader;
u16 ver_minor;
ver_minor = pBase->version & AR5416_EEP_VER_MINOR_MASK;
switch (param) { switch (param) {
case EEP_NFTHRESH_2: case EEP_NFTHRESH_2:
@ -268,19 +248,17 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
case EEP_MAC_MSW: case EEP_MAC_MSW:
return get_unaligned_be16(pBase->macAddr + 4); return get_unaligned_be16(pBase->macAddr + 4);
case EEP_REG_0: case EEP_REG_0:
return pBase->regDmn[0]; return le16_to_cpu(pBase->regDmn[0]);
case EEP_OP_CAP: case EEP_OP_CAP:
return pBase->deviceCap; return le16_to_cpu(pBase->deviceCap);
case EEP_OP_MODE: case EEP_OP_MODE:
return pBase->opCapFlags; return pBase->opCapFlags;
case EEP_RF_SILENT: case EEP_RF_SILENT:
return pBase->rfSilent; return le16_to_cpu(pBase->rfSilent);
case EEP_OB_2: case EEP_OB_2:
return pModal->ob_0; return pModal->ob_0;
case EEP_DB_2: case EEP_DB_2:
return pModal->db1_1; return pModal->db1_1;
case EEP_MINOR_REV:
return ver_minor;
case EEP_TX_MASK: case EEP_TX_MASK:
return pBase->txMask; return pBase->txMask;
case EEP_RX_MASK: 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; xpdMask = pEepData->modalHeader.xpdGain;
if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2)
AR5416_EEP_MINOR_VER_2) {
pdGainOverlap_t2 = pdGainOverlap_t2 =
pEepData->modalHeader.pdGainOverlap; pEepData->modalHeader.pdGainOverlap;
} else { else
pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
}
pCalBChans = pEepData->calFreqPier2G; pCalBChans = pEepData->calFreqPier2G;
numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS; 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)); memset(ratesArray, 0, sizeof(ratesArray));
if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2)
AR5416_EEP_MINOR_VER_2) {
ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
}
ath9k_hw_set_4k_power_per_rate_table(ah, chan, ath9k_hw_set_4k_power_per_rate_table(ah, chan,
&ratesArray[0], cfgCtl, &ratesArray[0], cfgCtl,
@ -728,15 +702,14 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
{ {
ENABLE_REG_RMW_BUFFER(ah); ENABLE_REG_RMW_BUFFER(ah);
REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 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), REG_RMW(ah, AR_PHY_TIMING_CTRL4(0),
SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_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); 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) >= if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {
AR5416_EEP_MINOR_VER_3) {
txRxAttenLocal = pModal->txRxAttenCh[0]; txRxAttenLocal = pModal->txRxAttenCh[0];
REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, 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; pModal = &eep->modalHeader;
txRxAttenLocal = 23; 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*/ /* Single chain for 4K EEPROM*/
ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal); 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, REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
pModal->thresh62); pModal->thresh62);
if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) {
AR5416_EEP_MINOR_VER_2) {
REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START, REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
pModal->txFrameToDataStart); pModal->txFrameToDataStart);
REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
pModal->txFrameToPaOn); pModal->txFrameToPaOn);
} }
if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {
AR5416_EEP_MINOR_VER_3) {
if (IS_CHAN_HT40(chan)) if (IS_CHAN_HT40(chan))
REG_RMW_FIELD(ah, AR_PHY_SETTLING, REG_RMW_FIELD(ah, AR_PHY_SETTLING,
AR_PHY_SETTLING_SWITCH, 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) 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 = { 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, .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
.set_board_values = ath9k_hw_4k_set_board_values, .set_board_values = ath9k_hw_4k_set_board_values,
.set_txpower = ath9k_hw_4k_set_txpower, .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
}; };

View File

@ -22,12 +22,17 @@
static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah) 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) 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) 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, static u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size,
struct modal_eep_ar9287_header *modal_hdr) struct modal_eep_ar9287_header *modal_hdr)
{ {
PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]); PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]); PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon); PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]); PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]); PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
PR_EEP("Switch Settle", modal_hdr->switchSettling); 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 ar9287_eeprom *eep = &ah->eeprom.map9287;
struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber);
if (!dump_base_hdr) { if (!dump_base_hdr) {
len += scnprintf(buf + len, size - len, 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; goto out;
} }
PR_EEP("Major Version", pBase->version >> 12); PR_EEP("Major Version", ath9k_hw_ar9287_get_eeprom_ver(ah));
PR_EEP("Minor Version", pBase->version & 0xFFF); PR_EEP("Minor Version", ath9k_hw_ar9287_get_eeprom_rev(ah));
PR_EEP("Checksum", pBase->checksum); PR_EEP("Checksum", le16_to_cpu(pBase->checksum));
PR_EEP("Length", pBase->length); PR_EEP("Length", le16_to_cpu(pBase->length));
PR_EEP("RegDomain1", pBase->regDmn[0]); PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));
PR_EEP("RegDomain2", pBase->regDmn[1]); PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));
PR_EEP("TX Mask", pBase->txMask); PR_EEP("TX Mask", pBase->txMask);
PR_EEP("RX Mask", pBase->rxMask); PR_EEP("RX Mask", pBase->rxMask);
PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); 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)); AR5416_OPFLAGS_N_5G_HT20));
PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags & PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
AR5416_OPFLAGS_N_5G_HT40)); AR5416_OPFLAGS_N_5G_HT40));
PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01)); PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN));
PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF); PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF);
PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF); PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF);
PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF);
PR_EEP("Power Table Offset", pBase->pwrTableOffset); PR_EEP("Power Table Offset", pBase->pwrTableOffset);
PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl); 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) static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
{ {
u32 el, integer; u32 el;
u16 word;
int i, err; int i, err;
bool need_swap; bool need_swap;
struct ar9287_eeprom *eep = &ah->eeprom.map9287; struct ar9287_eeprom *eep = &ah->eeprom.map9287;
@ -188,51 +193,31 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
return err; return err;
if (need_swap) if (need_swap)
el = swab16(eep->baseEepHeader.length); el = swab16((__force u16)eep->baseEepHeader.length);
else else
el = eep->baseEepHeader.length; el = le16_to_cpu(eep->baseEepHeader.length);
el = min(el / sizeof(u16), SIZE_EEPROM_AR9287); el = min(el / sizeof(u16), SIZE_EEPROM_AR9287);
if (!ath9k_hw_nvram_validate_checksum(ah, el)) if (!ath9k_hw_nvram_validate_checksum(ah, el))
return -EINVAL; return -EINVAL;
if (need_swap) { if (need_swap) {
word = swab16(eep->baseEepHeader.length); EEPROM_FIELD_SWAB16(eep->baseEepHeader.length);
eep->baseEepHeader.length = word; 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);
word = swab16(eep->baseEepHeader.checksum); for (i = 0; i < AR9287_MAX_CHAINS; i++)
eep->baseEepHeader.checksum = word; EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlChain[i]);
word = swab16(eep->baseEepHeader.version); for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++)
eep->baseEepHeader.version = word; EEPROM_FIELD_SWAB16(
eep->modalHeader.spurChans[i].spurChan);
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;
}
} }
if (!ath9k_hw_nvram_check_version(ah, AR9287_EEP_VER, 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 ar9287_eeprom *eep = &ah->eeprom.map9287;
struct modal_eep_ar9287_header *pModal = &eep->modalHeader; struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
u16 ver_minor; u16 ver_minor = ath9k_hw_ar9287_get_eeprom_rev(ah);
ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK;
switch (param) { switch (param) {
case EEP_NFTHRESH_2: case EEP_NFTHRESH_2:
@ -264,15 +247,13 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
case EEP_MAC_MSW: case EEP_MAC_MSW:
return get_unaligned_be16(pBase->macAddr + 4); return get_unaligned_be16(pBase->macAddr + 4);
case EEP_REG_0: case EEP_REG_0:
return pBase->regDmn[0]; return le16_to_cpu(pBase->regDmn[0]);
case EEP_OP_CAP: case EEP_OP_CAP:
return pBase->deviceCap; return le16_to_cpu(pBase->deviceCap);
case EEP_OP_MODE: case EEP_OP_MODE:
return pBase->opCapFlags; return pBase->opCapFlags;
case EEP_RF_SILENT: case EEP_RF_SILENT:
return pBase->rfSilent; return le16_to_cpu(pBase->rfSilent);
case EEP_MINOR_REV:
return ver_minor;
case EEP_TX_MASK: case EEP_TX_MASK:
return pBase->txMask; return pBase->txMask;
case EEP_RX_MASK: 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; xpdMask = pEepData->modalHeader.xpdGain;
if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= if (ath9k_hw_ar9287_get_eeprom_rev(ah) >= AR9287_EEP_MINOR_VER_2)
AR9287_EEP_MINOR_VER_2)
pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap;
else else
pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), 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)); memset(ratesArray, 0, sizeof(ratesArray));
if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= if (ath9k_hw_ar9287_get_eeprom_rev(ah) >= AR9287_EEP_MINOR_VER_2)
AR9287_EEP_MINOR_VER_2)
ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
ath9k_hw_set_ar9287_power_per_rate_table(ah, chan, 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; 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++) { for (i = 0; i < AR9287_MAX_CHAINS; i++) {
regChainOffset = i * 0x1000; regChainOffset = i * 0x1000;
REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, 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_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
(REG_READ(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, static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
u16 i, bool is2GHz) 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 = { 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, .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev,
.set_board_values = ath9k_hw_ar9287_set_board_values, .set_board_values = ath9k_hw_ar9287_set_board_values,
.set_txpower = ath9k_hw_ar9287_set_txpower, .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
}; };

View File

@ -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) 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) 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)) #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, static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
struct modal_eep_header *modal_hdr) struct modal_eep_header *modal_hdr)
{ {
PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]); PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]); PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
PR_EEP("Chain2 Ant. Control", modal_hdr->antCtrlChain[2]); PR_EEP("Chain2 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[2]));
PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon); PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]); PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]); PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
PR_EEP("Chain2 Ant. Gain", modal_hdr->antennaGainCh[2]); 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 OutputBias", modal_hdr->ob_ch1);
PR_EEP("Chain1 DriverBias", modal_hdr->db_ch1); PR_EEP("Chain1 DriverBias", modal_hdr->db_ch1);
PR_EEP("LNA Control", modal_hdr->lna_ctl); PR_EEP("LNA Control", modal_hdr->lna_ctl);
PR_EEP("XPA Bias Freq0", modal_hdr->xpaBiasLvlFreq[0]); PR_EEP("XPA Bias Freq0", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[0]));
PR_EEP("XPA Bias Freq1", modal_hdr->xpaBiasLvlFreq[1]); PR_EEP("XPA Bias Freq1", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[1]));
PR_EEP("XPA Bias Freq2", modal_hdr->xpaBiasLvlFreq[2]); PR_EEP("XPA Bias Freq2", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[2]));
return len; 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 ar5416_eeprom_def *eep = &ah->eeprom.def;
struct base_eep_header *pBase = &eep->baseEepHeader; struct base_eep_header *pBase = &eep->baseEepHeader;
u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber);
if (!dump_base_hdr) { if (!dump_base_hdr) {
len += scnprintf(buf + len, size - len, 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; goto out;
} }
PR_EEP("Major Version", pBase->version >> 12); PR_EEP("Major Version", ath9k_hw_def_get_eeprom_ver(ah));
PR_EEP("Minor Version", pBase->version & 0xFFF); PR_EEP("Minor Version", ath9k_hw_def_get_eeprom_rev(ah));
PR_EEP("Checksum", pBase->checksum); PR_EEP("Checksum", le16_to_cpu(pBase->checksum));
PR_EEP("Length", pBase->length); PR_EEP("Length", le16_to_cpu(pBase->length));
PR_EEP("RegDomain1", pBase->regDmn[0]); PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));
PR_EEP("RegDomain2", pBase->regDmn[1]); PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));
PR_EEP("TX Mask", pBase->txMask); PR_EEP("TX Mask", pBase->txMask);
PR_EEP("RX Mask", pBase->rxMask); PR_EEP("RX Mask", pBase->rxMask);
PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); 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)); AR5416_OPFLAGS_N_5G_HT20));
PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags & PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
AR5416_OPFLAGS_N_5G_HT40)); AR5416_OPFLAGS_N_5G_HT40));
PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01)); PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN));
PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF); PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF);
PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF); PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF);
PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF);
PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl); PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", 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; return err;
if (need_swap) if (need_swap)
el = swab16(eep->baseEepHeader.length); el = swab16((__force u16)eep->baseEepHeader.length);
else else
el = eep->baseEepHeader.length; el = le16_to_cpu(eep->baseEepHeader.length);
el = min(el / sizeof(u16), SIZE_EEPROM_DEF); el = min(el / sizeof(u16), SIZE_EEPROM_DEF);
if (!ath9k_hw_nvram_validate_checksum(ah, el)) if (!ath9k_hw_nvram_validate_checksum(ah, el))
return -EINVAL; return -EINVAL;
if (need_swap) { if (need_swap) {
u32 integer, j; u32 j;
u16 word;
word = swab16(eep->baseEepHeader.length); EEPROM_FIELD_SWAB16(eep->baseEepHeader.length);
eep->baseEepHeader.length = word; EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum);
EEPROM_FIELD_SWAB16(eep->baseEepHeader.version);
word = swab16(eep->baseEepHeader.checksum); EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]);
eep->baseEepHeader.checksum = word; EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]);
EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent);
word = swab16(eep->baseEepHeader.version); EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions);
eep->baseEepHeader.version = word; EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap);
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;
for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) { for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
struct modal_eep_header *pModal = struct modal_eep_header *pModal =
&eep->modalHeader[j]; &eep->modalHeader[j];
integer = swab32(pModal->antCtrlCommon); EEPROM_FIELD_SWAB32(pModal->antCtrlCommon);
pModal->antCtrlCommon = integer;
for (i = 0; i < AR5416_MAX_CHAINS; i++) { for (i = 0; i < AR5416_MAX_CHAINS; i++)
integer = swab32(pModal->antCtrlChain[i]); EEPROM_FIELD_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 < AR_EEPROM_MODAL_SPURS; i++) { for (i = 0; i < 3; i++)
word = swab16(pModal->spurChans[i].spurChan); EEPROM_FIELD_SWAB16(pModal->xpaBiasLvlFreq[i]);
pModal->spurChans[i].spurChan = word;
} 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 */ /* Enable fixup for AR_AN_TOP2 if necessary */
if ((ah->hw_version.devid == AR9280_DEVID_PCI) && 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)) (eep->baseEepHeader.pwdclkind == 0))
ah->need_an_top2_fixup = true; 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: case EEP_MAC_MSW:
return get_unaligned_be16(pBase->macAddr + 4); return get_unaligned_be16(pBase->macAddr + 4);
case EEP_REG_0: case EEP_REG_0:
return pBase->regDmn[0]; return le16_to_cpu(pBase->regDmn[0]);
case EEP_OP_CAP: case EEP_OP_CAP:
return pBase->deviceCap; return le16_to_cpu(pBase->deviceCap);
case EEP_OP_MODE: case EEP_OP_MODE:
return pBase->opCapFlags; return pBase->opCapFlags;
case EEP_RF_SILENT: case EEP_RF_SILENT:
return pBase->rfSilent; return le16_to_cpu(pBase->rfSilent);
case EEP_OB_5: case EEP_OB_5:
return pModal[0].ob; return pModal[0].ob;
case EEP_DB_5: case EEP_DB_5:
@ -380,8 +365,6 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
return pModal[1].ob; return pModal[1].ob;
case EEP_DB_2: case EEP_DB_2:
return pModal[1].db; return pModal[1].db;
case EEP_MINOR_REV:
return AR5416_VER_MASK;
case EEP_TX_MASK: case EEP_TX_MASK:
return pBase->txMask; return pBase->txMask;
case EEP_RX_MASK: case EEP_RX_MASK:
@ -393,27 +376,27 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
case EEP_TXGAIN_TYPE: case EEP_TXGAIN_TYPE:
return pBase->txGainType; return pBase->txGainType;
case EEP_OL_PWRCTRL: 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; return pBase->openLoopPwrCntl ? true : false;
else else
return false; return false;
case EEP_RC_CHAIN_MASK: 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; return pBase->rcChainMask;
else else
return 0; return 0;
case EEP_DAC_HPWR_5G: 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; return pBase->dacHiPwrMode_5G;
else else
return 0; return 0;
case EEP_FRAC_N_5G: 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; return pBase->frac_n_5g;
else else
return 0; return 0;
case EEP_PWR_TABLE_OFFSET: 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; return pBase->pwr_table_offset;
else else
return AR5416_PWR_TABLE_OFFSET_DB; 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) u8 txRxAttenLocal, int regChainOffset, int i)
{ {
ENABLE_REG_RMW_BUFFER(ah); 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]; txRxAttenLocal = pModal->txRxAttenCh[i];
if (AR_SREV_9280_20_OR_LATER(ah)) { 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; struct ar5416_eeprom_def *eep = &ah->eeprom.def;
int i, regChainOffset; int i, regChainOffset;
u8 txRxAttenLocal; u8 txRxAttenLocal;
u32 antCtrlCommon;
pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; 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++) { for (i = 0; i < AR5416_MAX_CHAINS; i++) {
if (AR_SREV_9280(ah)) { if (AR_SREV_9280(ah)) {
@ -505,7 +490,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
regChainOffset = i * 0x1000; regChainOffset = i * 0x1000;
REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, 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_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
(REG_READ(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); 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, REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
AR_PHY_TX_END_DATA_START, AR_PHY_TX_END_DATA_START,
pModal->txFrameToDataStart); pModal->txFrameToDataStart);
@ -613,7 +598,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
pModal->txFrameToPaOn); 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)) if (IS_CHAN_HT40(chan))
REG_RMW_FIELD(ah, AR_PHY_SETTLING, REG_RMW_FIELD(ah, AR_PHY_SETTLING,
AR_PHY_SETTLING_SWITCH, 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) && 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, REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
pModal->miscBits); 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)) if (IS_CHAN_2GHZ(chan))
REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
eep->baseEepHeader.dacLpMode); 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, static void ath9k_hw_def_set_addac(struct ath_hw *ah,
struct ath9k_channel *chan) 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 modal_eep_header *pModal;
struct ar5416_eeprom_def *eep = &ah->eeprom.def; struct ar5416_eeprom_def *eep = &ah->eeprom.def;
u8 biaslevel; 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); pwr_table_offset = ah->eep_ops->get_eeprom(ah, EEP_PWR_TABLE_OFFSET);
if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) {
AR5416_EEP_MINOR_VER_2) {
pdGainOverlap_t2 = pdGainOverlap_t2 =
pEepData->modalHeader[modalIdx].pdGainOverlap; pEepData->modalHeader[modalIdx].pdGainOverlap;
} else { } else {
@ -1171,10 +1156,8 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
memset(ratesArray, 0, sizeof(ratesArray)); memset(ratesArray, 0, sizeof(ratesArray));
if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2)
AR5416_EEP_MINOR_VER_2) {
ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
}
ath9k_hw_set_def_power_per_rate_table(ah, chan, ath9k_hw_set_def_power_per_rate_table(ah, chan,
&ratesArray[0], cfgCtl, &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) 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 = { 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_board_values = ath9k_hw_def_set_board_values,
.set_addac = ath9k_hw_def_set_addac, .set_addac = ath9k_hw_def_set_addac,
.set_txpower = ath9k_hw_def_set_txpower, .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
}; };

View File

@ -620,6 +620,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
/* Will be cleared in ath9k_start() */ /* Will be cleared in ath9k_start() */
set_bit(ATH_OP_INVALID, &common->op_flags); 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->sc_ah = ah;
sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET); sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);

View File

@ -70,10 +70,10 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq,
goto out; goto out;
if (txq->mac80211_qnum >= 0) { if (txq->mac80211_qnum >= 0) {
struct list_head *list; struct ath_acq *acq;
list = &sc->cur_chan->acq[txq->mac80211_qnum]; acq = &sc->cur_chan->acq[txq->mac80211_qnum];
if (!list_empty(list)) if (!list_empty(&acq->acq_new) || !list_empty(&acq->acq_old))
pending = true; pending = true;
} }
out: out:

View File

@ -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) int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
{ {
struct ath_rxbuf *bf; 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_antenna_check(sc, &rs);
ath9k_apply_ampdu_details(sc, &rs, rxs); ath9k_apply_ampdu_details(sc, &rs, rxs);
ath_debug_rate_stats(sc, &rs, skb); ath_debug_rate_stats(sc, &rs, skb);
ath_rx_count_airtime(sc, &rs, skb);
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_ack(hdr->frame_control)) if (ieee80211_is_ack(hdr->frame_control))

View File

@ -97,18 +97,6 @@ static void ath_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
dev_kfree_skb(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) void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
__releases(&txq->axq_lock) __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); ath_tx_status(hw, skb);
} }
static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq, void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
struct ath_atx_tid *tid)
{ {
struct list_head *list;
struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv; struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
struct ath_chanctx *ctx = avp->chanctx; 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; return;
list = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
if (list_empty(&tid->list)) acq = &ctx->acq[acno];
list_add_tail(&tid->list, list); 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) void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue)
{ {
struct ath_softc *sc = hw->priv; 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); ath_txq_lock(sc, txq);
tid->has_queued = true; tid->has_queued = true;
ath_tx_queue_tid(sc, txq, tid); ath_tx_queue_tid(sc, tid);
ath_txq_schedule(sc, txq); ath_txq_schedule(sc, txq);
ath_txq_unlock(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); skb_queue_splice_tail(&bf_pending, &tid->retry_q);
if (!an->sleeping) { 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)) if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
tid->clear_ps_filter = true; 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); 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, static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
struct ath_tx_status *ts, struct ath_buf *bf, struct ath_tx_status *ts, struct ath_buf *bf,
struct list_head *bf_head) 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->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc,
ts->ts_rateindex); ts->ts_rateindex);
ath_tx_count_airtime(sc, txq, bf, ts);
hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data; hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
@ -1068,7 +1127,7 @@ finish:
* width - 0 for 20 MHz, 1 for 40 MHz * width - 0 for 20 MHz, 1 for 40 MHz
* half_gi - to use 4us v/s 3.6 us for symbol time * 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, u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
int width, int half_gi, bool shortPreamble) int width, int half_gi, bool shortPreamble)
{ {
u32 nbits, nsymbits, duration, nsymbols; u32 nbits, nsymbits, duration, nsymbols;
@ -1151,8 +1210,9 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
if (is_40) { if (is_40) {
u8 power_ht40delta; u8 power_ht40delta;
struct ar5416_eeprom_def *eep = &ah->eeprom.def; 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; bool is_2ghz;
struct modal_eep_header *pmodal; 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, 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 ath_buf *bf;
struct ieee80211_tx_info *tx_info; 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) || if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
(!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) { (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
__skb_queue_tail(&tid->retry_q, bf->bf_mpdu); __skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
*stop = true;
return false; return false;
} }
@ -1613,7 +1672,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
ath_txq_lock(sc, txq); ath_txq_lock(sc, txq);
tid->clear_ps_filter = true; tid->clear_ps_filter = true;
if (ath_tid_has_buffered(tid)) { 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_schedule(sc, txq);
} }
ath_txq_unlock_complete(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) void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
{ {
struct ath_common *common = ath9k_hw_common(sc->sc_ah); 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; struct list_head *tid_list;
bool sent = false; struct ath_acq *acq;
bool active = AIRTIME_ACTIVE(sc->airtime_flags);
if (txq->mac80211_qnum < 0) if (txq->mac80211_qnum < 0)
return; return;
@ -1923,48 +1983,55 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
return; return;
spin_lock_bh(&sc->chan_lock); 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(); 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) if (sc->cur_chan->stopped)
break; goto out;
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); tid = list_first_entry(tid_list, struct ath_atx_tid, list);
list_del_init(&tid->list);
if (ath_tx_sched_aggr(sc, txq, tid, &stop)) if (active && tid->an->airtime_deficit[txq->mac80211_qnum] <= 0) {
sent = true; 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 (!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;
}
/* /*
* add tid to round-robin queue if more frames * If we succeed in scheduling something, immediately restart to make
* are pending for the tid * sure we keep the HW busy.
*/ */
if (ath_tid_has_buffered(tid)) if(ath_tx_sched_aggr(sc, txq, tid)) {
ath_tx_queue_tid(sc, txq, tid); if (!active) {
spin_lock_bh(&acq->lock);
if (stop) list_move_tail(&tid->list, &acq->acq_old);
break; spin_unlock_bh(&acq->lock);
if (tid == last_tid) {
if (!sent)
break;
sent = false;
last_tid = list_entry(tid_list->prev,
struct ath_atx_tid, list);
} }
goto begin;
} }
out:
rcu_read_unlock(); rcu_read_unlock();
spin_unlock_bh(&sc->chan_lock); 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; struct ath_atx_tid *tid;
int tidno, acno; 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++) { for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
tid = ath_node_to_tid(an, tidno); tid = ath_node_to_tid(an, tidno);
tid->an = an; tid->an = an;