Commit f79683de authored by Kalle Valo's avatar Kalle Valo

Merge ath-next from ath.git

Major changes in ath10k:

* add spectral scan support for 10.4 firmware
* add qca6164 support
* implement mesh support using firmware raw mode
parents 1f9c6e1b b8402d82
...@@ -34,16 +34,19 @@ unsigned int ath10k_debug_mask; ...@@ -34,16 +34,19 @@ unsigned int ath10k_debug_mask;
static unsigned int ath10k_cryptmode_param; static unsigned int ath10k_cryptmode_param;
static bool uart_print; static bool uart_print;
static bool skip_otp; static bool skip_otp;
static bool rawmode;
module_param_named(debug_mask, ath10k_debug_mask, uint, 0644); module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644); module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644);
module_param(uart_print, bool, 0644); module_param(uart_print, bool, 0644);
module_param(skip_otp, bool, 0644); module_param(skip_otp, bool, 0644);
module_param(rawmode, bool, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask"); MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(uart_print, "Uart target debugging"); MODULE_PARM_DESC(uart_print, "Uart target debugging");
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode"); MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software"); MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath");
static const struct ath10k_hw_params ath10k_hw_params_list[] = { static const struct ath10k_hw_params ath10k_hw_params_list[] = {
{ {
...@@ -54,6 +57,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -54,6 +57,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.has_shifted_cc_wraparound = true, .has_shifted_cc_wraparound = true,
.otp_exe_param = 0, .otp_exe_param = 0,
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0,
.fw = { .fw = {
.dir = QCA988X_HW_2_0_FW_DIR, .dir = QCA988X_HW_2_0_FW_DIR,
.fw = QCA988X_HW_2_0_FW_FILE, .fw = QCA988X_HW_2_0_FW_FILE,
...@@ -70,6 +74,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -70,6 +74,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.uart_pin = 6, .uart_pin = 6,
.otp_exe_param = 0, .otp_exe_param = 0,
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0,
.fw = { .fw = {
.dir = QCA6174_HW_2_1_FW_DIR, .dir = QCA6174_HW_2_1_FW_DIR,
.fw = QCA6174_HW_2_1_FW_FILE, .fw = QCA6174_HW_2_1_FW_FILE,
...@@ -86,6 +91,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -86,6 +91,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.uart_pin = 6, .uart_pin = 6,
.otp_exe_param = 0, .otp_exe_param = 0,
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0,
.fw = { .fw = {
.dir = QCA6174_HW_3_0_FW_DIR, .dir = QCA6174_HW_3_0_FW_DIR,
.fw = QCA6174_HW_3_0_FW_FILE, .fw = QCA6174_HW_3_0_FW_FILE,
...@@ -102,6 +108,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -102,6 +108,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.uart_pin = 6, .uart_pin = 6,
.otp_exe_param = 0, .otp_exe_param = 0,
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0,
.fw = { .fw = {
/* uses same binaries as hw3.0 */ /* uses same binaries as hw3.0 */
.dir = QCA6174_HW_3_0_FW_DIR, .dir = QCA6174_HW_3_0_FW_DIR,
...@@ -120,6 +127,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -120,6 +127,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.otp_exe_param = 0x00000700, .otp_exe_param = 0x00000700,
.continuous_frag_desc = true, .continuous_frag_desc = true,
.channel_counters_freq_hz = 150000, .channel_counters_freq_hz = 150000,
.max_probe_resp_desc_thres = 24,
.fw = { .fw = {
.dir = QCA99X0_HW_2_0_FW_DIR, .dir = QCA99X0_HW_2_0_FW_DIR,
.fw = QCA99X0_HW_2_0_FW_FILE, .fw = QCA99X0_HW_2_0_FW_FILE,
...@@ -142,12 +150,17 @@ static const char *const ath10k_core_fw_feature_str[] = { ...@@ -142,12 +150,17 @@ static const char *const ath10k_core_fw_feature_str[] = {
[ATH10K_FW_FEATURE_IGNORE_OTP_RESULT] = "ignore-otp", [ATH10K_FW_FEATURE_IGNORE_OTP_RESULT] = "ignore-otp",
[ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad", [ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad",
[ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init", [ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init",
[ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode",
}; };
static unsigned int ath10k_core_get_fw_feature_str(char *buf, static unsigned int ath10k_core_get_fw_feature_str(char *buf,
size_t buf_len, size_t buf_len,
enum ath10k_fw_features feat) enum ath10k_fw_features feat)
{ {
/* make sure that ath10k_core_fw_feature_str[] gets updated */
BUILD_BUG_ON(ARRAY_SIZE(ath10k_core_fw_feature_str) !=
ATH10K_FW_FEATURE_COUNT);
if (feat >= ARRAY_SIZE(ath10k_core_fw_feature_str) || if (feat >= ARRAY_SIZE(ath10k_core_fw_feature_str) ||
WARN_ON(!ath10k_core_fw_feature_str[feat])) { WARN_ON(!ath10k_core_fw_feature_str[feat])) {
return scnprintf(buf, buf_len, "bit%d", feat); return scnprintf(buf, buf_len, "bit%d", feat);
...@@ -1117,6 +1130,15 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ...@@ -1117,6 +1130,15 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT; ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT;
ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT; ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT;
if (rawmode) {
if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
ar->fw_features)) {
ath10k_err(ar, "rawmode = 1 requires support from firmware");
return -EINVAL;
}
set_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);
}
if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_RAW; ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_RAW;
...@@ -1714,6 +1736,7 @@ void ath10k_core_destroy(struct ath10k *ar) ...@@ -1714,6 +1736,7 @@ void ath10k_core_destroy(struct ath10k *ar)
destroy_workqueue(ar->workqueue_aux); destroy_workqueue(ar->workqueue_aux);
ath10k_debug_destroy(ar); ath10k_debug_destroy(ar);
ath10k_wmi_free_host_mem(ar);
ath10k_mac_destroy(ar); ath10k_mac_destroy(ar);
} }
EXPORT_SYMBOL(ath10k_core_destroy); EXPORT_SYMBOL(ath10k_core_destroy);
......
...@@ -612,6 +612,11 @@ struct ath10k { ...@@ -612,6 +612,11 @@ struct ath10k {
u32 channel_counters_freq_hz; u32 channel_counters_freq_hz;
/* Mgmt tx descriptors threshold for limiting probe response
* frames.
*/
u32 max_probe_resp_desc_thres;
struct ath10k_hw_params_fw { struct ath10k_hw_params_fw {
const char *dir; const char *dir;
const char *fw; const char *fw;
......
...@@ -1485,6 +1485,7 @@ struct ath10k_htt { ...@@ -1485,6 +1485,7 @@ struct ath10k_htt {
spinlock_t tx_lock; spinlock_t tx_lock;
int max_num_pending_tx; int max_num_pending_tx;
int num_pending_tx; int num_pending_tx;
int num_pending_mgmt_tx;
struct idr pending_tx; struct idr pending_tx;
wait_queue_head_t empty_tx_wq; wait_queue_head_t empty_tx_wq;
struct dma_pool *tx_pool; struct dma_pool *tx_pool;
...@@ -1587,7 +1588,7 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, ...@@ -1587,7 +1588,7 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
u8 max_subfrms_ampdu, u8 max_subfrms_ampdu,
u8 max_subfrms_amsdu); u8 max_subfrms_amsdu);
void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc);
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb); int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb);
void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id); void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id);
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *);
......
...@@ -643,6 +643,8 @@ struct amsdu_subframe_hdr { ...@@ -643,6 +643,8 @@ struct amsdu_subframe_hdr {
__be16 len; __be16 len;
} __packed; } __packed;
#define GROUP_ID_IS_SU_MIMO(x) ((x) == 0 || (x) == 63)
static void ath10k_htt_rx_h_rates(struct ath10k *ar, static void ath10k_htt_rx_h_rates(struct ath10k *ar,
struct ieee80211_rx_status *status, struct ieee80211_rx_status *status,
struct htt_rx_desc *rxd) struct htt_rx_desc *rxd)
...@@ -650,6 +652,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, ...@@ -650,6 +652,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
u8 cck, rate, bw, sgi, mcs, nss; u8 cck, rate, bw, sgi, mcs, nss;
u8 preamble = 0; u8 preamble = 0;
u8 group_id;
u32 info1, info2, info3; u32 info1, info2, info3;
info1 = __le32_to_cpu(rxd->ppdu_start.info1); info1 = __le32_to_cpu(rxd->ppdu_start.info1);
...@@ -692,10 +695,50 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, ...@@ -692,10 +695,50 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
case HTT_RX_VHT_WITH_TXBF: case HTT_RX_VHT_WITH_TXBF:
/* VHT-SIG-A1 in info2, VHT-SIG-A2 in info3 /* VHT-SIG-A1 in info2, VHT-SIG-A2 in info3
TODO check this */ TODO check this */
mcs = (info3 >> 4) & 0x0F;
nss = ((info2 >> 10) & 0x07) + 1;
bw = info2 & 3; bw = info2 & 3;
sgi = info3 & 1; sgi = info3 & 1;
group_id = (info2 >> 4) & 0x3F;
if (GROUP_ID_IS_SU_MIMO(group_id)) {
mcs = (info3 >> 4) & 0x0F;
nss = ((info2 >> 10) & 0x07) + 1;
} else {
/* Hardware doesn't decode VHT-SIG-B into Rx descriptor
* so it's impossible to decode MCS. Also since
* firmware consumes Group Id Management frames host
* has no knowledge regarding group/user position
* mapping so it's impossible to pick the correct Nsts
* from VHT-SIG-A1.
*
* Bandwidth and SGI are valid so report the rateinfo
* on best-effort basis.
*/
mcs = 0;
nss = 1;
}
if (mcs > 0x09) {
ath10k_warn(ar, "invalid MCS received %u\n", mcs);
ath10k_warn(ar, "rxd %08x mpdu start %08x %08x msdu start %08x %08x ppdu start %08x %08x %08x %08x %08x\n",
__le32_to_cpu(rxd->attention.flags),
__le32_to_cpu(rxd->mpdu_start.info0),
__le32_to_cpu(rxd->mpdu_start.info1),
__le32_to_cpu(rxd->msdu_start.common.info0),
__le32_to_cpu(rxd->msdu_start.common.info1),
rxd->ppdu_start.info0,
__le32_to_cpu(rxd->ppdu_start.info1),
__le32_to_cpu(rxd->ppdu_start.info2),
__le32_to_cpu(rxd->ppdu_start.info3),
__le32_to_cpu(rxd->ppdu_start.info4));
ath10k_warn(ar, "msdu end %08x mpdu end %08x\n",
__le32_to_cpu(rxd->msdu_end.common.info0),
__le32_to_cpu(rxd->mpdu_end.info0));
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL,
"rx desc msdu payload: ",
rxd->msdu_payload, 50);
}
status->rate_idx = mcs; status->rate_idx = mcs;
status->vht_nss = nss; status->vht_nss = nss;
......
...@@ -22,22 +22,28 @@ ...@@ -22,22 +22,28 @@
#include "txrx.h" #include "txrx.h"
#include "debug.h" #include "debug.h"
void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc)
{ {
if (limit_mgmt_desc)
htt->num_pending_mgmt_tx--;
htt->num_pending_tx--; htt->num_pending_tx--;
if (htt->num_pending_tx == htt->max_num_pending_tx - 1) if (htt->num_pending_tx == htt->max_num_pending_tx - 1)
ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
} }
static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt,
bool limit_mgmt_desc)
{ {
spin_lock_bh(&htt->tx_lock); spin_lock_bh(&htt->tx_lock);
__ath10k_htt_tx_dec_pending(htt); __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
spin_unlock_bh(&htt->tx_lock); spin_unlock_bh(&htt->tx_lock);
} }
static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt,
bool limit_mgmt_desc, bool is_probe_resp)
{ {
struct ath10k *ar = htt->ar;
int ret = 0; int ret = 0;
spin_lock_bh(&htt->tx_lock); spin_lock_bh(&htt->tx_lock);
...@@ -47,6 +53,15 @@ static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) ...@@ -47,6 +53,15 @@ static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt)
goto exit; goto exit;
} }
if (limit_mgmt_desc) {
if (is_probe_resp && (htt->num_pending_mgmt_tx >
ar->hw_params.max_probe_resp_desc_thres)) {
ret = -EBUSY;
goto exit;
}
htt->num_pending_mgmt_tx++;
}
htt->num_pending_tx++; htt->num_pending_tx++;
if (htt->num_pending_tx == htt->max_num_pending_tx) if (htt->num_pending_tx == htt->max_num_pending_tx)
ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
...@@ -417,8 +432,19 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -417,8 +432,19 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
int len = 0; int len = 0;
int msdu_id = -1; int msdu_id = -1;
int res; int res;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
bool limit_mgmt_desc = false;
bool is_probe_resp = false;
if (ar->hw_params.max_probe_resp_desc_thres) {
limit_mgmt_desc = true;
if (ieee80211_is_probe_resp(hdr->frame_control))
is_probe_resp = true;
}
res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp);
res = ath10k_htt_tx_inc_pending(htt);
if (res) if (res)
goto err; goto err;
...@@ -476,7 +502,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -476,7 +502,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
ath10k_htt_tx_free_msdu_id(htt, msdu_id); ath10k_htt_tx_free_msdu_id(htt, msdu_id);
spin_unlock_bh(&htt->tx_lock); spin_unlock_bh(&htt->tx_lock);
err_tx_dec: err_tx_dec:
ath10k_htt_tx_dec_pending(htt); ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
err: err:
return res; return res;
} }
...@@ -498,8 +524,18 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -498,8 +524,18 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
dma_addr_t paddr = 0; dma_addr_t paddr = 0;
u32 frags_paddr = 0; u32 frags_paddr = 0;
struct htt_msdu_ext_desc *ext_desc = NULL; struct htt_msdu_ext_desc *ext_desc = NULL;
bool limit_mgmt_desc = false;
bool is_probe_resp = false;
if (unlikely(ieee80211_is_mgmt(hdr->frame_control)) &&
ar->hw_params.max_probe_resp_desc_thres) {
limit_mgmt_desc = true;
if (ieee80211_is_probe_resp(hdr->frame_control))
is_probe_resp = true;
}
res = ath10k_htt_tx_inc_pending(htt); res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp);
if (res) if (res)
goto err; goto err;
...@@ -528,7 +564,8 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -528,7 +564,8 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
ieee80211_has_protected(hdr->frame_control)) { ieee80211_has_protected(hdr->frame_control)) {
skb_put(msdu, IEEE80211_CCMP_MIC_LEN); skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
} else if (!skb_cb->htt.nohwcrypt && } else if (!skb_cb->htt.nohwcrypt &&
skb_cb->txmode == ATH10K_HW_TXRX_RAW) { skb_cb->txmode == ATH10K_HW_TXRX_RAW &&
ieee80211_has_protected(hdr->frame_control)) {
skb_put(msdu, IEEE80211_CCMP_MIC_LEN); skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
} }
...@@ -678,7 +715,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -678,7 +715,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
ath10k_htt_tx_free_msdu_id(htt, msdu_id); ath10k_htt_tx_free_msdu_id(htt, msdu_id);
spin_unlock_bh(&htt->tx_lock); spin_unlock_bh(&htt->tx_lock);
err_tx_dec: err_tx_dec:
ath10k_htt_tx_dec_pending(htt); ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
err: err:
return res; return res;
} }
...@@ -413,16 +413,6 @@ enum ath10k_hw_rate_cck { ...@@ -413,16 +413,6 @@ enum ath10k_hw_rate_cck {
/* Number of Copy Engines supported */ /* Number of Copy Engines supported */
#define CE_COUNT ar->hw_values->ce_count #define CE_COUNT ar->hw_values->ce_count
/*
* Total number of PCIe MSI interrupts requested for all interrupt sources.
* PCIe standard forces this to be a power of 2.
* Some Host OS's limit MSI requests that can be granted to 8
* so for now we abide by this limit and avoid requesting more
* than that.
*/
#define MSI_NUM_REQUEST_LOG2 3
#define MSI_NUM_REQUEST (1<<MSI_NUM_REQUEST_LOG2)
/* /*
* Granted MSIs are assigned as follows: * Granted MSIs are assigned as follows:
* Firmware uses the first * Firmware uses the first
......
This diff is collapsed.
...@@ -2609,12 +2609,9 @@ static int ath10k_pci_request_irq(struct ath10k *ar) ...@@ -2609,12 +2609,9 @@ static int ath10k_pci_request_irq(struct ath10k *ar)
return ath10k_pci_request_irq_legacy(ar); return ath10k_pci_request_irq_legacy(ar);
case 1: case 1:
return ath10k_pci_request_irq_msi(ar); return ath10k_pci_request_irq_msi(ar);
case MSI_NUM_REQUEST: default:
return ath10k_pci_request_irq_msix(ar); return ath10k_pci_request_irq_msix(ar);
} }
ath10k_warn(ar, "unknown irq configuration upon request\n");
return -EINVAL;
} }
static void ath10k_pci_free_irq(struct ath10k *ar) static void ath10k_pci_free_irq(struct ath10k *ar)
...@@ -2657,7 +2654,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar) ...@@ -2657,7 +2654,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar)
/* Try MSI-X */ /* Try MSI-X */
if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO) { if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO) {
ar_pci->num_msi_intrs = MSI_NUM_REQUEST; ar_pci->num_msi_intrs = MSI_ASSIGN_CE_MAX + 1;
ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs, ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs,
ar_pci->num_msi_intrs); ar_pci->num_msi_intrs);
if (ret > 0) if (ret > 0)
...@@ -2705,18 +2702,13 @@ static int ath10k_pci_deinit_irq(struct ath10k *ar) ...@@ -2705,18 +2702,13 @@ static int ath10k_pci_deinit_irq(struct ath10k *ar)
switch (ar_pci->num_msi_intrs) { switch (ar_pci->num_msi_intrs) {
case 0: case 0:
ath10k_pci_deinit_irq_legacy(ar); ath10k_pci_deinit_irq_legacy(ar);
return 0; break;
case 1:
/* fall-through */
case MSI_NUM_REQUEST:
pci_disable_msi(ar_pci->pdev);
return 0;
default: default:
pci_disable_msi(ar_pci->pdev); pci_disable_msi(ar_pci->pdev);
break;
} }
ath10k_warn(ar, "unknown irq configuration upon deinit\n"); return 0;
return -EINVAL;
} }
static int ath10k_pci_wait_for_target_init(struct ath10k *ar) static int ath10k_pci_wait_for_target_init(struct ath10k *ar)
......
...@@ -52,6 +52,9 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, ...@@ -52,6 +52,9 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
struct ath10k_skb_cb *skb_cb; struct ath10k_skb_cb *skb_cb;
struct sk_buff *msdu; struct sk_buff *msdu;
struct ieee80211_hdr *hdr;
__le16 fc;
bool limit_mgmt_desc = false;
ath10k_dbg(ar, ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt tx completion msdu_id %u discard %d no_ack %d success %d\n", "htt tx completion msdu_id %u discard %d no_ack %d success %d\n",
...@@ -72,14 +75,21 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, ...@@ -72,14 +75,21 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
spin_unlock_bh(&htt->tx_lock); spin_unlock_bh(&htt->tx_lock);
return; return;
} }
hdr = (struct ieee80211_hdr *)msdu->data;
fc = hdr->frame_control;
if (unlikely(ieee80211_is_mgmt(fc)) &&
ar->hw_params.max_probe_resp_desc_thres)
limit_mgmt_desc = true;
ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
__ath10k_htt_tx_dec_pending(htt); __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
if (htt->num_pending_tx == 0) if (htt->num_pending_tx == 0)
wake_up(&htt->empty_tx_wq); wake_up(&htt->empty_tx_wq);
spin_unlock_bh(&htt->tx_lock); spin_unlock_bh(&htt->tx_lock);
skb_cb = ATH10K_SKB_CB(msdu); skb_cb = ATH10K_SKB_CB(msdu);
dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
if (skb_cb->htt.txbuf) if (skb_cb->htt.txbuf)
......
...@@ -3917,6 +3917,53 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, ...@@ -3917,6 +3917,53 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
return 0; return 0;
} }
static bool
ath10k_wmi_is_host_mem_allocated(struct ath10k *ar,
const struct wlan_host_mem_req **mem_reqs,
u32 num_mem_reqs)
{
u32 req_id, num_units, unit_size, num_unit_info;
u32 pool_size;
int i, j;
bool found;
if (ar->wmi.num_mem_chunks != num_mem_reqs)
return false;
for (i = 0; i < num_mem_reqs; ++i) {
req_id = __le32_to_cpu(mem_reqs[i]->req_id);
num_units = __le32_to_cpu(mem_reqs[i]->num_units);
unit_size = __le32_to_cpu(mem_reqs[i]->unit_size);
num_unit_info = __le32_to_cpu(mem_reqs[i]->num_unit_info);
if (num_unit_info & NUM_UNITS_IS_NUM_ACTIVE_PEERS) {
if (ar->num_active_peers)
num_units = ar->num_active_peers + 1;
else
num_units = ar->max_num_peers + 1;
} else if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) {
num_units = ar->max_num_peers + 1;
} else if (num_unit_info & NUM_UNITS_IS_NUM_VDEVS) {
num_units = ar->max_num_vdevs + 1;
}
found = false;
for (j = 0; j < ar->wmi.num_mem_chunks; j++) {
if (ar->wmi.mem_chunks[j].req_id == req_id) {
pool_size = num_units * round_up(unit_size, 4);
if (ar->wmi.mem_chunks[j].len == pool_size) {
found = true;
break;
}
}
}
if (!found)
return false;
}
return true;
}
static int static int
ath10k_wmi_main_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb, ath10k_wmi_main_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
struct wmi_svc_rdy_ev_arg *arg) struct wmi_svc_rdy_ev_arg *arg)
...@@ -3997,6 +4044,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) ...@@ -3997,6 +4044,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
struct wmi_svc_rdy_ev_arg arg = {}; struct wmi_svc_rdy_ev_arg arg = {};
u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i; u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
int ret; int ret;
bool allocated;
if (!skb) { if (!skb) {
ath10k_warn(ar, "invalid service ready event skb\n"); ath10k_warn(ar, "invalid service ready event skb\n");
...@@ -4073,6 +4121,18 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) ...@@ -4073,6 +4121,18 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
* and WMI_SERVICE_IRAM_TIDS, etc. * and WMI_SERVICE_IRAM_TIDS, etc.
*/ */
allocated = ath10k_wmi_is_host_mem_allocated(ar, arg.mem_reqs,
num_mem_reqs);
if (allocated)
goto skip_mem_alloc;
/* Either this event is received during boot time or there is a change
* in memory requirement from firmware when compared to last request.
* Free any old memory and do a fresh allocation based on the current
* memory requirement.
*/
ath10k_wmi_free_host_mem(ar);
for (i = 0; i < num_mem_reqs; ++i) { for (i = 0; i < num_mem_reqs; ++i) {
req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id); req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id);
num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units); num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units);
...@@ -4108,6 +4168,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) ...@@ -4108,6 +4168,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
return; return;
} }
skip_mem_alloc:
ath10k_dbg(ar, ATH10K_DBG_WMI, ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x fw_build 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n", "wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x fw_build 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n",
__le32_to_cpu(arg.min_tx_power), __le32_to_cpu(arg.min_tx_power),
...@@ -6660,15 +6721,10 @@ int ath10k_wmi_attach(struct ath10k *ar) ...@@ -6660,15 +6721,10 @@ int ath10k_wmi_attach(struct ath10k *ar)
return 0; return 0;
} }
void ath10k_wmi_detach(struct ath10k *ar) void ath10k_wmi_free_host_mem(struct ath10k *ar)
{ {
int i; int i;
cancel_work_sync(&ar->svc_rdy_work);
if (ar->svc_rdy_skb)
dev_kfree_skb(ar->svc_rdy_skb);
/* free the host memory chunks requested by firmware */ /* free the host memory chunks requested by firmware */
for (i = 0; i < ar->wmi.num_mem_chunks; i++) { for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
dma_free_coherent(ar->dev, dma_free_coherent(ar->dev,
...@@ -6679,3 +6735,11 @@ void ath10k_wmi_detach(struct ath10k *ar) ...@@ -6679,3 +6735,11 @@ void ath10k_wmi_detach(struct ath10k *ar)
ar->wmi.num_mem_chunks = 0; ar->wmi.num_mem_chunks = 0;
} }
void ath10k_wmi_detach(struct ath10k *ar)
{
cancel_work_sync(&ar->svc_rdy_work);
if (ar->svc_rdy_skb)
dev_kfree_skb(ar->svc_rdy_skb);
}
...@@ -6067,6 +6067,7 @@ struct ath10k_fw_stats_peer; ...@@ -6067,6 +6067,7 @@ struct ath10k_fw_stats_peer;
int ath10k_wmi_attach(struct ath10k *ar); int ath10k_wmi_attach(struct ath10k *ar);
void ath10k_wmi_detach(struct ath10k *ar); void ath10k_wmi_detach(struct ath10k *ar);
void ath10k_wmi_free_host_mem(struct ath10k *ar);
int ath10k_wmi_wait_for_service_ready(struct ath10k *ar); int ath10k_wmi_wait_for_service_ready(struct ath10k *ar);
int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar); int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
......
...@@ -21,12 +21,6 @@ ...@@ -21,12 +21,6 @@
#include "dfs_pri_detector.h" #include "dfs_pri_detector.h"
#include "ath.h" #include "ath.h"
/*
* tolerated deviation of radar time stamp in usecs on both sides
* TODO: this might need to be HW-dependent
*/
#define PRI_TOLERANCE 16
/** /**
* struct radar_types - contains array of patterns defined for one DFS domain * struct radar_types - contains array of patterns defined for one DFS domain
* @domain: DFS regulatory domain * @domain: DFS regulatory domain
...@@ -121,7 +115,7 @@ static const struct radar_detector_specs jp_radar_ref_types[] = { ...@@ -121,7 +115,7 @@ static const struct radar_detector_specs jp_radar_ref_types[] = {
JP_PATTERN(4, 0, 5, 150, 230, 1, 23, 50, false), JP_PATTERN(4, 0, 5, 150, 230, 1, 23, 50, false),
JP_PATTERN(5, 6, 10, 200, 500, 1, 16, 50, false), JP_PATTERN(5, 6, 10, 200, 500, 1, 16, 50, false),
JP_PATTERN(6, 11, 20, 200, 500, 1, 12, 50, false), JP_PATTERN(6, 11, 20, 200, 500, 1, 12, 50, false),
JP_PATTERN(7, 50, 100, 1000, 2000, 1, 20, 50, false), JP_PATTERN(7, 50, 100, 1000, 2000, 1, 3, 50, false),
JP_PATTERN(5, 0, 1, 333, 333, 1, 9, 50, false), JP_PATTERN(5, 0, 1, 333, 333, 1, 9, 50, false),
}; };
......
...@@ -21,6 +21,11 @@ ...@@ -21,6 +21,11 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/nl80211.h> #include <linux/nl80211.h>
/* tolerated deviation of radar time stamp in usecs on both sides
* TODO: this might need to be HW-dependent
*/
#define PRI_TOLERANCE 16
/** /**
* struct ath_dfs_pool_stats - DFS Statistics for global pools * struct ath_dfs_pool_stats - DFS Statistics for global pools
*/ */
......
...@@ -25,6 +25,9 @@ struct ath_dfs_pool_stats global_dfs_pool_stats = {}; ...@@ -25,6 +25,9 @@ struct ath_dfs_pool_stats global_dfs_pool_stats = {};
#define DFS_POOL_STAT_INC(c) (global_dfs_pool_stats.c++) #define DFS_POOL_STAT_INC(c) (global_dfs_pool_stats.c++)
#define DFS_POOL_STAT_DEC(c) (global_dfs_pool_stats.c--) #define DFS_POOL_STAT_DEC(c) (global_dfs_pool_stats.c--)
#define GET_PRI_TO_USE(MIN, MAX, RUNTIME) \
(MIN + PRI_TOLERANCE == MAX - PRI_TOLERANCE ? \
MIN + PRI_TOLERANCE : RUNTIME)
/** /**
* struct pulse_elem - elements in pulse queue * struct pulse_elem - elements in pulse queue
...@@ -243,7 +246,8 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde, ...@@ -243,7 +246,8 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde,
ps.count_falses = 0; ps.count_falses = 0;
ps.first_ts = p->ts; ps.first_ts = p->ts;
ps.last_ts = ts; ps.last_ts = ts;
ps.pri = ts - p->ts; ps.pri = GET_PRI_TO_USE(pde->rs->pri_min,
pde->rs->pri_max, ts - p->ts);
ps.dur = ps.pri * (pde->rs->ppb - 1) ps.dur = ps.pri * (pde->rs->ppb - 1)
+ 2 * pde->rs->max_pri_tolerance; + 2 * pde->rs->max_pri_tolerance;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment