mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-14 16:56:49 +07:00
Merge ath-next from ath.git
ath.git patches for 4.8. Major changes: ath10k * enable btcoex support without restarting firmware * enable ipq4019 support using AHB bus * add QCA9887 chipset support * retrieve calibration data from EEPROM, currently only for QCA9887 wil6210 * add pm_notify handling
This commit is contained in:
commit
1bb57c8a5e
@ -25,10 +25,9 @@
|
||||
#include "ahb.h"
|
||||
|
||||
static const struct of_device_id ath10k_ahb_of_match[] = {
|
||||
/* TODO: enable this entry once everything in place.
|
||||
* { .compatible = "qcom,ipq4019-wifi",
|
||||
* .data = (void *)ATH10K_HW_QCA4019 },
|
||||
*/
|
||||
{ .compatible = "qcom,ipq4019-wifi",
|
||||
.data = (void *)ATH10K_HW_QCA4019
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -476,6 +475,7 @@ static irqreturn_t ath10k_ahb_interrupt_handler(int irq, void *arg)
|
||||
|
||||
static int ath10k_ahb_request_irq_legacy(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
int ret;
|
||||
|
||||
@ -487,6 +487,7 @@ static int ath10k_ahb_request_irq_legacy(struct ath10k *ar)
|
||||
ar_ahb->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
ar_pci->oper_irq_mode = ATH10K_PCI_IRQ_LEGACY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -918,8 +919,6 @@ int ath10k_ahb_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk(KERN_ERR "AHB support is still work in progress\n");
|
||||
|
||||
ret = platform_driver_register(&ath10k_ahb_driver);
|
||||
if (ret)
|
||||
printk(KERN_ERR "failed to register ath10k ahb driver: %d\n",
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/of.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "mac.h"
|
||||
@ -55,7 +56,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.name = "qca988x hw2.0",
|
||||
.patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.has_shifted_cc_wraparound = true,
|
||||
.cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
|
||||
.otp_exe_param = 0,
|
||||
.channel_counters_freq_hz = 88000,
|
||||
.max_probe_resp_desc_thres = 0,
|
||||
@ -68,6 +69,25 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
},
|
||||
{
|
||||
.id = QCA9887_HW_1_0_VERSION,
|
||||
.dev_id = QCA9887_1_0_DEVICE_ID,
|
||||
.name = "qca9887 hw1.0",
|
||||
.patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
|
||||
.otp_exe_param = 0,
|
||||
.channel_counters_freq_hz = 88000,
|
||||
.max_probe_resp_desc_thres = 0,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
|
||||
.cal_data_len = 2116,
|
||||
.fw = {
|
||||
.dir = QCA9887_HW_1_0_FW_DIR,
|
||||
.board = QCA9887_HW_1_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA9887_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9887_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_2_1_VERSION,
|
||||
.dev_id = QCA6164_2_1_DEVICE_ID,
|
||||
@ -148,6 +168,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.uart_pin = 7,
|
||||
.otp_exe_param = 0x00000700,
|
||||
.continuous_frag_desc = true,
|
||||
.cck_rate_map_rev2 = true,
|
||||
.channel_counters_freq_hz = 150000,
|
||||
.max_probe_resp_desc_thres = 24,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
@ -162,6 +183,29 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
},
|
||||
{
|
||||
.id = QCA9984_HW_1_0_DEV_VERSION,
|
||||
.dev_id = QCA9984_1_0_DEVICE_ID,
|
||||
.name = "qca9984/qca9994 hw1.0",
|
||||
.patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.otp_exe_param = 0x00000700,
|
||||
.continuous_frag_desc = true,
|
||||
.cck_rate_map_rev2 = true,
|
||||
.channel_counters_freq_hz = 150000,
|
||||
.max_probe_resp_desc_thres = 24,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
.tx_chain_mask = 0xf,
|
||||
.rx_chain_mask = 0xf,
|
||||
.max_spatial_stream = 4,
|
||||
.cal_data_len = 12064,
|
||||
.fw = {
|
||||
.dir = QCA9984_HW_1_0_FW_DIR,
|
||||
.board = QCA9984_HW_1_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA99X0_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
},
|
||||
{
|
||||
.id = QCA9377_HW_1_0_DEV_VERSION,
|
||||
.dev_id = QCA9377_1_0_DEVICE_ID,
|
||||
@ -202,9 +246,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.name = "qca4019 hw1.0",
|
||||
.patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.has_shifted_cc_wraparound = true,
|
||||
.cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
|
||||
.otp_exe_param = 0x0010000,
|
||||
.continuous_frag_desc = true,
|
||||
.cck_rate_map_rev2 = true,
|
||||
.channel_counters_freq_hz = 125000,
|
||||
.max_probe_resp_desc_thres = 24,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
@ -236,6 +281,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
|
||||
[ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca",
|
||||
[ATH10K_FW_FEATURE_MFP_SUPPORT] = "mfp",
|
||||
[ATH10K_FW_FEATURE_PEER_FLOW_CONTROL] = "peer-flow-ctrl",
|
||||
[ATH10K_FW_FEATURE_BTCOEX_PARAM] = "btcoex-param",
|
||||
};
|
||||
|
||||
static unsigned int ath10k_core_get_fw_feature_str(char *buf,
|
||||
@ -531,6 +577,35 @@ static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_download_cal_eeprom(struct ath10k *ar)
|
||||
{
|
||||
size_t data_len;
|
||||
void *data = NULL;
|
||||
int ret;
|
||||
|
||||
ret = ath10k_hif_fetch_cal_eeprom(ar, &data, &data_len);
|
||||
if (ret) {
|
||||
if (ret != -EOPNOTSUPP)
|
||||
ath10k_warn(ar, "failed to read calibration data from EEPROM: %d\n",
|
||||
ret);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = ath10k_download_board_data(ar, data, data_len);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to download calibration data from EEPROM: %d\n",
|
||||
ret);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out_free:
|
||||
kfree(data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
|
||||
{
|
||||
u32 result, address;
|
||||
@ -1293,7 +1368,17 @@ static int ath10k_download_cal_data(struct ath10k *ar)
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"boot did not find DT entry, try OTP next: %d\n",
|
||||
"boot did not find DT entry, try target EEPROM next: %d\n",
|
||||
ret);
|
||||
|
||||
ret = ath10k_download_cal_eeprom(ar);
|
||||
if (ret == 0) {
|
||||
ar->cal_mode = ATH10K_CAL_MODE_EEPROM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"boot did not find target EEPROM entry, try OTP next: %d\n",
|
||||
ret);
|
||||
|
||||
ret = ath10k_download_and_run_otp(ar);
|
||||
@ -1733,6 +1818,16 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
if (test_bit(WMI_SERVICE_BSS_CHANNEL_INFO_64, ar->wmi.svc_map))
|
||||
val |= WMI_10_4_BSS_CHANNEL_INFO_64;
|
||||
|
||||
/* 10.4 firmware supports BT-Coex without reloading firmware
|
||||
* via pdev param. To support Bluetooth coexistence pdev param,
|
||||
* WMI_COEX_GPIO_SUPPORT of extended resource config should be
|
||||
* enabled always.
|
||||
*/
|
||||
if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map) &&
|
||||
test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
val |= WMI_10_4_COEX_GPIO_SUPPORT;
|
||||
|
||||
status = ath10k_mac_ext_resource_config(ar, val);
|
||||
if (status) {
|
||||
ath10k_err(ar,
|
||||
@ -2062,6 +2157,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
||||
|
||||
switch (hw_rev) {
|
||||
case ATH10K_HW_QCA988X:
|
||||
case ATH10K_HW_QCA9887:
|
||||
ar->regs = &qca988x_regs;
|
||||
ar->hw_values = &qca988x_values;
|
||||
break;
|
||||
@ -2071,6 +2167,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
||||
ar->hw_values = &qca6174_values;
|
||||
break;
|
||||
case ATH10K_HW_QCA99X0:
|
||||
case ATH10K_HW_QCA9984:
|
||||
ar->regs = &qca99x0_regs;
|
||||
ar->hw_values = &qca99x0_values;
|
||||
break;
|
||||
@ -2159,5 +2256,5 @@ void ath10k_core_destroy(struct ath10k *ar)
|
||||
EXPORT_SYMBOL(ath10k_core_destroy);
|
||||
|
||||
MODULE_AUTHOR("Qualcomm Atheros");
|
||||
MODULE_DESCRIPTION("Core module for QCA988X PCIe devices.");
|
||||
MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11ac wireless LAN cards.");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
@ -535,6 +535,13 @@ enum ath10k_fw_features {
|
||||
*/
|
||||
ATH10K_FW_FEATURE_PEER_FLOW_CONTROL = 13,
|
||||
|
||||
/* Firmware supports BT-Coex without reloading firmware via pdev param.
|
||||
* To support Bluetooth coexistence pdev param, WMI_COEX_GPIO_SUPPORT of
|
||||
* extended resource config should be enabled always. This firmware IE
|
||||
* is used to configure WMI_COEX_GPIO_SUPPORT.
|
||||
*/
|
||||
ATH10K_FW_FEATURE_BTCOEX_PARAM = 14,
|
||||
|
||||
/* keep last */
|
||||
ATH10K_FW_FEATURE_COUNT,
|
||||
};
|
||||
@ -571,6 +578,7 @@ enum ath10k_cal_mode {
|
||||
ATH10K_CAL_MODE_DT,
|
||||
ATH10K_PRE_CAL_MODE_FILE,
|
||||
ATH10K_PRE_CAL_MODE_DT,
|
||||
ATH10K_CAL_MODE_EEPROM,
|
||||
};
|
||||
|
||||
enum ath10k_crypt_mode {
|
||||
@ -593,6 +601,8 @@ static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
|
||||
return "pre-cal-file";
|
||||
case ATH10K_PRE_CAL_MODE_DT:
|
||||
return "pre-cal-dt";
|
||||
case ATH10K_CAL_MODE_EEPROM:
|
||||
return "eeprom";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
@ -703,12 +713,10 @@ struct ath10k {
|
||||
int uart_pin;
|
||||
u32 otp_exe_param;
|
||||
|
||||
/* This is true if given HW chip has a quirky Cycle Counter
|
||||
* wraparound which resets to 0x7fffffff instead of 0. All
|
||||
* other CC related counters (e.g. Rx Clear Count) are divided
|
||||
* by 2 so they never wraparound themselves.
|
||||
/* Type of hw cycle counter wraparound logic, for more info
|
||||
* refer enum ath10k_hw_cc_wraparound_type.
|
||||
*/
|
||||
bool has_shifted_cc_wraparound;
|
||||
enum ath10k_hw_cc_wraparound_type cc_wraparound_type;
|
||||
|
||||
/* Some of chip expects fragment descriptor to be continuous
|
||||
* memory for any TX operation. Set continuous_frag_desc flag
|
||||
@ -716,6 +724,12 @@ struct ath10k {
|
||||
*/
|
||||
bool continuous_frag_desc;
|
||||
|
||||
/* CCK hardware rate table mapping for the newer chipsets
|
||||
* like QCA99X0, QCA4019 got revised. The CCK h/w rate values
|
||||
* are in a proper order with respect to the rate/preamble
|
||||
*/
|
||||
bool cck_rate_map_rev2;
|
||||
|
||||
u32 channel_counters_freq_hz;
|
||||
|
||||
/* Mgmt tx descriptors threshold for limiting probe response
|
||||
|
@ -609,25 +609,23 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
|
||||
char buf[32];
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
|
||||
|
||||
/* make sure that buf is null terminated */
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
|
||||
/* drop the possible '\n' from the end */
|
||||
if (buf[count - 1] == '\n')
|
||||
buf[count - 1] = 0;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON &&
|
||||
ar->state != ATH10K_STATE_RESTARTED) {
|
||||
ret = -ENETDOWN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* drop the possible '\n' from the end */
|
||||
if (buf[count - 1] == '\n') {
|
||||
buf[count - 1] = 0;
|
||||
count--;
|
||||
}
|
||||
|
||||
if (!strcmp(buf, "soft")) {
|
||||
ath10k_info(ar, "simulating soft firmware crash\n");
|
||||
ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
|
||||
@ -2127,6 +2125,7 @@ static ssize_t ath10k_write_btcoex(struct file *file,
|
||||
size_t buf_size;
|
||||
int ret;
|
||||
bool val;
|
||||
u32 pdev_param;
|
||||
|
||||
buf_size = min(count, (sizeof(buf) - 1));
|
||||
if (copy_from_user(buf, ubuf, buf_size))
|
||||
@ -2150,14 +2149,25 @@ static ssize_t ath10k_write_btcoex(struct file *file,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pdev_param = ar->wmi.pdev_param->enable_btcoex;
|
||||
if (test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM,
|
||||
ar->running_fw->fw_file.fw_features)) {
|
||||
ret = ath10k_wmi_pdev_set_param(ar, pdev_param, val);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to enable btcoex: %d\n", ret);
|
||||
ret = count;
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
ath10k_info(ar, "restarting firmware due to btcoex change");
|
||||
queue_work(ar->workqueue, &ar->restart_work);
|
||||
}
|
||||
|
||||
if (val)
|
||||
set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
|
||||
else
|
||||
clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
|
||||
|
||||
ath10k_info(ar, "restarting firmware due to btcoex change");
|
||||
|
||||
queue_work(ar->workqueue, &ar->restart_work);
|
||||
ret = count;
|
||||
|
||||
exit:
|
||||
|
@ -87,6 +87,10 @@ struct ath10k_hif_ops {
|
||||
|
||||
int (*suspend)(struct ath10k *ar);
|
||||
int (*resume)(struct ath10k *ar);
|
||||
|
||||
/* fetch calibration data from target eeprom */
|
||||
int (*fetch_cal_eeprom)(struct ath10k *ar, void **data,
|
||||
size_t *data_len);
|
||||
};
|
||||
|
||||
static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
|
||||
@ -202,4 +206,14 @@ static inline void ath10k_hif_write32(struct ath10k *ar,
|
||||
ar->hif.ops->write32(ar, address, data);
|
||||
}
|
||||
|
||||
static inline int ath10k_hif_fetch_cal_eeprom(struct ath10k *ar,
|
||||
void **data,
|
||||
size_t *data_len)
|
||||
{
|
||||
if (!ar->hif.ops->fetch_cal_eeprom)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar->hif.ops->fetch_cal_eeprom(ar, data, data_len);
|
||||
}
|
||||
|
||||
#endif /* _HIF_H_ */
|
||||
|
@ -485,10 +485,10 @@ struct htt_mgmt_tx_completion {
|
||||
__le32 status;
|
||||
} __packed;
|
||||
|
||||
#define HTT_RX_INDICATION_INFO0_EXT_TID_MASK (0x3F)
|
||||
#define HTT_RX_INDICATION_INFO0_EXT_TID_MASK (0x1F)
|
||||
#define HTT_RX_INDICATION_INFO0_EXT_TID_LSB (0)
|
||||
#define HTT_RX_INDICATION_INFO0_FLUSH_VALID (1 << 6)
|
||||
#define HTT_RX_INDICATION_INFO0_RELEASE_VALID (1 << 7)
|
||||
#define HTT_RX_INDICATION_INFO0_FLUSH_VALID (1 << 5)
|
||||
#define HTT_RX_INDICATION_INFO0_RELEASE_VALID (1 << 6)
|
||||
|
||||
#define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_MASK 0x0000003F
|
||||
#define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_LSB 0
|
||||
|
@ -748,7 +748,7 @@ ath10k_htt_rx_h_peer_channel(struct ath10k *ar, struct htt_rx_desc *rxd)
|
||||
if (WARN_ON_ONCE(!arvif))
|
||||
return NULL;
|
||||
|
||||
if (WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def)))
|
||||
if (WARN_ON_ONCE(ath10k_mac_vif_chan(arvif->vif, &def)))
|
||||
return NULL;
|
||||
|
||||
return def.chan;
|
||||
@ -939,7 +939,8 @@ static void ath10k_process_rx(struct ath10k *ar,
|
||||
is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
|
||||
"mcast" : "ucast",
|
||||
(__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4,
|
||||
status->flag == 0 ? "legacy" : "",
|
||||
(status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) == 0 ?
|
||||
"legacy" : "",
|
||||
status->flag & RX_FLAG_HT ? "ht" : "",
|
||||
status->flag & RX_FLAG_VHT ? "vht" : "",
|
||||
status->flag & RX_FLAG_40MHZ ? "40" : "",
|
||||
@ -2182,34 +2183,6 @@ static void ath10k_htt_rx_tx_mode_switch_ind(struct ath10k *ar,
|
||||
ath10k_mac_tx_push_pending(ar);
|
||||
}
|
||||
|
||||
static inline enum nl80211_band phy_mode_to_band(u32 phy_mode)
|
||||
{
|
||||
enum nl80211_band band;
|
||||
|
||||
switch (phy_mode) {
|
||||
case MODE_11A:
|
||||
case MODE_11NA_HT20:
|
||||
case MODE_11NA_HT40:
|
||||
case MODE_11AC_VHT20:
|
||||
case MODE_11AC_VHT40:
|
||||
case MODE_11AC_VHT80:
|
||||
band = NL80211_BAND_5GHZ;
|
||||
break;
|
||||
case MODE_11G:
|
||||
case MODE_11B:
|
||||
case MODE_11GONLY:
|
||||
case MODE_11NG_HT20:
|
||||
case MODE_11NG_HT40:
|
||||
case MODE_11AC_VHT20_2G:
|
||||
case MODE_11AC_VHT40_2G:
|
||||
case MODE_11AC_VHT80_2G:
|
||||
default:
|
||||
band = NL80211_BAND_2GHZ;
|
||||
}
|
||||
|
||||
return band;
|
||||
}
|
||||
|
||||
void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
bool release;
|
||||
@ -2291,7 +2264,6 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
ath10k_htt_tx_mgmt_dec_pending(htt);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
}
|
||||
ath10k_mac_tx_push_pending(ar);
|
||||
break;
|
||||
}
|
||||
case HTT_T2H_MSG_TYPE_TX_COMPL_IND:
|
||||
@ -2442,8 +2414,6 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr)
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
ath10k_mac_tx_push_pending(ar);
|
||||
|
||||
num_mpdus = atomic_read(&htt->num_mpdus_ready);
|
||||
|
||||
while (num_mpdus) {
|
||||
|
@ -179,17 +179,35 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev)
|
||||
{
|
||||
u32 cc_fix = 0;
|
||||
u32 rcc_fix = 0;
|
||||
enum ath10k_hw_cc_wraparound_type wraparound_type;
|
||||
|
||||
survey->filled |= SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_BUSY;
|
||||
|
||||
if (ar->hw_params.has_shifted_cc_wraparound && cc < cc_prev) {
|
||||
cc_fix = 0x7fffffff;
|
||||
survey->filled &= ~SURVEY_INFO_TIME_BUSY;
|
||||
wraparound_type = ar->hw_params.cc_wraparound_type;
|
||||
|
||||
if (cc < cc_prev || rcc < rcc_prev) {
|
||||
switch (wraparound_type) {
|
||||
case ATH10K_HW_CC_WRAP_SHIFTED_ALL:
|
||||
if (cc < cc_prev) {
|
||||
cc_fix = 0x7fffffff;
|
||||
survey->filled &= ~SURVEY_INFO_TIME_BUSY;
|
||||
}
|
||||
break;
|
||||
case ATH10K_HW_CC_WRAP_SHIFTED_EACH:
|
||||
if (cc < cc_prev)
|
||||
cc_fix = 0x7fffffff;
|
||||
else
|
||||
rcc_fix = 0x7fffffff;
|
||||
break;
|
||||
case ATH10K_HW_CC_WRAP_DISABLED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cc -= cc_prev - cc_fix;
|
||||
rcc -= rcc_prev;
|
||||
rcc -= rcc_prev - rcc_fix;
|
||||
|
||||
survey->time = CCNT_TO_MSEC(ar, cc);
|
||||
survey->time_busy = CCNT_TO_MSEC(ar, rcc);
|
||||
|
@ -26,7 +26,9 @@
|
||||
#define QCA6164_2_1_DEVICE_ID (0x0041)
|
||||
#define QCA6174_2_1_DEVICE_ID (0x003e)
|
||||
#define QCA99X0_2_0_DEVICE_ID (0x0040)
|
||||
#define QCA9984_1_0_DEVICE_ID (0x0046)
|
||||
#define QCA9377_1_0_DEVICE_ID (0x0042)
|
||||
#define QCA9887_1_0_DEVICE_ID (0x0050)
|
||||
|
||||
/* QCA988X 1.0 definitions (unsupported) */
|
||||
#define QCA988X_HW_1_0_CHIP_ID_REV 0x0
|
||||
@ -38,6 +40,13 @@
|
||||
#define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9887 1.0 definitions */
|
||||
#define QCA9887_HW_1_0_VERSION 0x4100016d
|
||||
#define QCA9887_HW_1_0_CHIP_ID_REV 0
|
||||
#define QCA9887_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9887/hw1.0"
|
||||
#define QCA9887_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9887_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA6174 target BMI version signatures */
|
||||
#define QCA6174_HW_1_0_VERSION 0x05000000
|
||||
#define QCA6174_HW_1_1_VERSION 0x05000001
|
||||
@ -91,6 +100,14 @@ enum qca9377_chip_id_rev {
|
||||
#define QCA99X0_HW_2_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9984 1.0 defines */
|
||||
#define QCA9984_HW_1_0_DEV_VERSION 0x1000000
|
||||
#define QCA9984_HW_DEV_TYPE 0xa
|
||||
#define QCA9984_HW_1_0_CHIP_ID_REV 0x0
|
||||
#define QCA9984_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9984/hw1.0"
|
||||
#define QCA9984_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9984_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9377 1.0 definitions */
|
||||
#define QCA9377_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9377/hw1.0"
|
||||
#define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
@ -193,8 +210,10 @@ enum ath10k_hw_rev {
|
||||
ATH10K_HW_QCA988X,
|
||||
ATH10K_HW_QCA6174,
|
||||
ATH10K_HW_QCA99X0,
|
||||
ATH10K_HW_QCA9984,
|
||||
ATH10K_HW_QCA9377,
|
||||
ATH10K_HW_QCA4019,
|
||||
ATH10K_HW_QCA9887,
|
||||
};
|
||||
|
||||
struct ath10k_hw_regs {
|
||||
@ -247,8 +266,10 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev);
|
||||
|
||||
#define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X)
|
||||
#define QCA_REV_9887(ar) ((ar)->hw_rev == ATH10K_HW_QCA9887)
|
||||
#define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174)
|
||||
#define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0)
|
||||
#define QCA_REV_9984(ar) ((ar)->hw_rev == ATH10K_HW_QCA9984)
|
||||
#define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377)
|
||||
#define QCA_REV_40XX(ar) ((ar)->hw_rev == ATH10K_HW_QCA4019)
|
||||
|
||||
@ -315,11 +336,41 @@ enum ath10k_hw_rate_cck {
|
||||
ATH10K_HW_RATE_CCK_SP_2M,
|
||||
};
|
||||
|
||||
enum ath10k_hw_rate_rev2_cck {
|
||||
ATH10K_HW_RATE_REV2_CCK_LP_1M = 1,
|
||||
ATH10K_HW_RATE_REV2_CCK_LP_2M,
|
||||
ATH10K_HW_RATE_REV2_CCK_LP_5_5M,
|
||||
ATH10K_HW_RATE_REV2_CCK_LP_11M,
|
||||
ATH10K_HW_RATE_REV2_CCK_SP_2M,
|
||||
ATH10K_HW_RATE_REV2_CCK_SP_5_5M,
|
||||
ATH10K_HW_RATE_REV2_CCK_SP_11M,
|
||||
};
|
||||
|
||||
enum ath10k_hw_4addr_pad {
|
||||
ATH10K_HW_4ADDR_PAD_AFTER,
|
||||
ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
};
|
||||
|
||||
enum ath10k_hw_cc_wraparound_type {
|
||||
ATH10K_HW_CC_WRAP_DISABLED = 0,
|
||||
|
||||
/* This type is when the HW chip has a quirky Cycle Counter
|
||||
* wraparound which resets to 0x7fffffff instead of 0. All
|
||||
* other CC related counters (e.g. Rx Clear Count) are divided
|
||||
* by 2 so they never wraparound themselves.
|
||||
*/
|
||||
ATH10K_HW_CC_WRAP_SHIFTED_ALL = 1,
|
||||
|
||||
/* Each hw counter wrapsaround independently. When the
|
||||
* counter overflows the repestive counter is right shifted
|
||||
* by 1, i.e reset to 0x7fffffff, and other counters will be
|
||||
* running unaffected. In this type of wraparound, it should
|
||||
* be possible to report accurate Rx busy time unlike the
|
||||
* first type.
|
||||
*/
|
||||
ATH10K_HW_CC_WRAP_SHIFTED_EACH = 2,
|
||||
};
|
||||
|
||||
/* Target specific defines for MAIN firmware */
|
||||
#define TARGET_NUM_VDEVS 8
|
||||
#define TARGET_NUM_PEER_AST 2
|
||||
@ -547,7 +598,10 @@ enum ath10k_hw_4addr_pad {
|
||||
#define WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001
|
||||
|
||||
#define WLAN_GPIO_PIN0_ADDRESS 0x00000028
|
||||
#define WLAN_GPIO_PIN0_CONFIG_LSB 11
|
||||
#define WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800
|
||||
#define WLAN_GPIO_PIN0_PAD_PULL_LSB 5
|
||||
#define WLAN_GPIO_PIN0_PAD_PULL_MASK 0x00000060
|
||||
#define WLAN_GPIO_PIN1_ADDRESS 0x0000002c
|
||||
#define WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800
|
||||
#define WLAN_GPIO_PIN10_ADDRESS 0x00000050
|
||||
@ -560,6 +614,8 @@ enum ath10k_hw_4addr_pad {
|
||||
#define CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0
|
||||
|
||||
#define SI_CONFIG_OFFSET 0x00000000
|
||||
#define SI_CONFIG_ERR_INT_LSB 19
|
||||
#define SI_CONFIG_ERR_INT_MASK 0x00080000
|
||||
#define SI_CONFIG_BIDIR_OD_DATA_LSB 18
|
||||
#define SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000
|
||||
#define SI_CONFIG_I2C_LSB 16
|
||||
@ -573,7 +629,9 @@ enum ath10k_hw_4addr_pad {
|
||||
#define SI_CONFIG_DIVIDER_LSB 0
|
||||
#define SI_CONFIG_DIVIDER_MASK 0x0000000f
|
||||
#define SI_CS_OFFSET 0x00000004
|
||||
#define SI_CS_DONE_ERR_LSB 10
|
||||
#define SI_CS_DONE_ERR_MASK 0x00000400
|
||||
#define SI_CS_DONE_INT_LSB 9
|
||||
#define SI_CS_DONE_INT_MASK 0x00000200
|
||||
#define SI_CS_START_LSB 8
|
||||
#define SI_CS_START_MASK 0x00000100
|
||||
@ -624,7 +682,10 @@ enum ath10k_hw_4addr_pad {
|
||||
#define GPIO_BASE_ADDRESS WLAN_GPIO_BASE_ADDRESS
|
||||
#define GPIO_PIN0_OFFSET WLAN_GPIO_PIN0_ADDRESS
|
||||
#define GPIO_PIN1_OFFSET WLAN_GPIO_PIN1_ADDRESS
|
||||
#define GPIO_PIN0_CONFIG_LSB WLAN_GPIO_PIN0_CONFIG_LSB
|
||||
#define GPIO_PIN0_CONFIG_MASK WLAN_GPIO_PIN0_CONFIG_MASK
|
||||
#define GPIO_PIN0_PAD_PULL_LSB WLAN_GPIO_PIN0_PAD_PULL_LSB
|
||||
#define GPIO_PIN0_PAD_PULL_MASK WLAN_GPIO_PIN0_PAD_PULL_MASK
|
||||
#define GPIO_PIN1_CONFIG_MASK WLAN_GPIO_PIN1_CONFIG_MASK
|
||||
#define SI_BASE_ADDRESS WLAN_SI_BASE_ADDRESS
|
||||
#define SCRATCH_BASE_ADDRESS SOC_CORE_BASE_ADDRESS
|
||||
@ -679,6 +740,18 @@ enum ath10k_hw_4addr_pad {
|
||||
#define WINDOW_READ_ADDR_ADDRESS MISSING
|
||||
#define WINDOW_WRITE_ADDR_ADDRESS MISSING
|
||||
|
||||
#define QCA9887_1_0_I2C_SDA_GPIO_PIN 5
|
||||
#define QCA9887_1_0_I2C_SDA_PIN_CONFIG 3
|
||||
#define QCA9887_1_0_SI_CLK_GPIO_PIN 17
|
||||
#define QCA9887_1_0_SI_CLK_PIN_CONFIG 3
|
||||
#define QCA9887_1_0_GPIO_ENABLE_W1TS_LOW_ADDRESS 0x00000010
|
||||
|
||||
#define QCA9887_EEPROM_SELECT_READ 0xa10000a0
|
||||
#define QCA9887_EEPROM_ADDR_HI_MASK 0x0000ff00
|
||||
#define QCA9887_EEPROM_ADDR_HI_LSB 8
|
||||
#define QCA9887_EEPROM_ADDR_LO_MASK 0x00ff0000
|
||||
#define QCA9887_EEPROM_ADDR_LO_LSB 16
|
||||
|
||||
#define RTC_STATE_V_GET(x) (((x) & RTC_STATE_V_MASK) >> RTC_STATE_V_LSB)
|
||||
|
||||
#endif /* _HW_H_ */
|
||||
|
@ -62,6 +62,32 @@ static struct ieee80211_rate ath10k_rates[] = {
|
||||
{ .bitrate = 540, .hw_value = ATH10K_HW_RATE_OFDM_54M },
|
||||
};
|
||||
|
||||
static struct ieee80211_rate ath10k_rates_rev2[] = {
|
||||
{ .bitrate = 10,
|
||||
.hw_value = ATH10K_HW_RATE_REV2_CCK_LP_1M },
|
||||
{ .bitrate = 20,
|
||||
.hw_value = ATH10K_HW_RATE_REV2_CCK_LP_2M,
|
||||
.hw_value_short = ATH10K_HW_RATE_REV2_CCK_SP_2M,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE },
|
||||
{ .bitrate = 55,
|
||||
.hw_value = ATH10K_HW_RATE_REV2_CCK_LP_5_5M,
|
||||
.hw_value_short = ATH10K_HW_RATE_REV2_CCK_SP_5_5M,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE },
|
||||
{ .bitrate = 110,
|
||||
.hw_value = ATH10K_HW_RATE_REV2_CCK_LP_11M,
|
||||
.hw_value_short = ATH10K_HW_RATE_REV2_CCK_SP_11M,
|
||||
.flags = IEEE80211_RATE_SHORT_PREAMBLE },
|
||||
|
||||
{ .bitrate = 60, .hw_value = ATH10K_HW_RATE_OFDM_6M },
|
||||
{ .bitrate = 90, .hw_value = ATH10K_HW_RATE_OFDM_9M },
|
||||
{ .bitrate = 120, .hw_value = ATH10K_HW_RATE_OFDM_12M },
|
||||
{ .bitrate = 180, .hw_value = ATH10K_HW_RATE_OFDM_18M },
|
||||
{ .bitrate = 240, .hw_value = ATH10K_HW_RATE_OFDM_24M },
|
||||
{ .bitrate = 360, .hw_value = ATH10K_HW_RATE_OFDM_36M },
|
||||
{ .bitrate = 480, .hw_value = ATH10K_HW_RATE_OFDM_48M },
|
||||
{ .bitrate = 540, .hw_value = ATH10K_HW_RATE_OFDM_54M },
|
||||
};
|
||||
|
||||
#define ATH10K_MAC_FIRST_OFDM_RATE_IDX 4
|
||||
|
||||
#define ath10k_a_rates (ath10k_rates + ATH10K_MAC_FIRST_OFDM_RATE_IDX)
|
||||
@ -70,6 +96,9 @@ static struct ieee80211_rate ath10k_rates[] = {
|
||||
#define ath10k_g_rates (ath10k_rates + 0)
|
||||
#define ath10k_g_rates_size (ARRAY_SIZE(ath10k_rates))
|
||||
|
||||
#define ath10k_g_rates_rev2 (ath10k_rates_rev2 + 0)
|
||||
#define ath10k_g_rates_rev2_size (ARRAY_SIZE(ath10k_rates_rev2))
|
||||
|
||||
static bool ath10k_mac_bitrate_is_cck(int bitrate)
|
||||
{
|
||||
switch (bitrate) {
|
||||
@ -3781,6 +3810,9 @@ void ath10k_mac_tx_push_pending(struct ath10k *ar)
|
||||
int ret;
|
||||
int max;
|
||||
|
||||
if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&ar->txqs_lock);
|
||||
rcu_read_lock();
|
||||
|
||||
@ -4051,9 +4083,7 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
|
||||
list_add_tail(&artxq->list, &ar->txqs);
|
||||
spin_unlock_bh(&ar->txqs_lock);
|
||||
|
||||
if (ath10k_mac_tx_can_push(hw, txq))
|
||||
tasklet_schedule(&ar->htt.txrx_compl_task);
|
||||
|
||||
ath10k_mac_tx_push_pending(ar);
|
||||
ath10k_htt_tx_txq_update(hw, txq);
|
||||
}
|
||||
|
||||
@ -4467,6 +4497,19 @@ static int ath10k_start(struct ieee80211_hw *hw)
|
||||
}
|
||||
}
|
||||
|
||||
param = ar->wmi.pdev_param->enable_btcoex;
|
||||
if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map) &&
|
||||
test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM,
|
||||
ar->running_fw->fw_file.fw_features)) {
|
||||
ret = ath10k_wmi_pdev_set_param(ar, param, 0);
|
||||
if (ret) {
|
||||
ath10k_warn(ar,
|
||||
"failed to set btcoex param: %d\n", ret);
|
||||
goto err_core_stop;
|
||||
}
|
||||
clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
|
||||
}
|
||||
|
||||
ar->num_started_vdevs = 0;
|
||||
ath10k_regd_update(ar);
|
||||
|
||||
@ -7695,8 +7738,14 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
band = &ar->mac.sbands[NL80211_BAND_2GHZ];
|
||||
band->n_channels = ARRAY_SIZE(ath10k_2ghz_channels);
|
||||
band->channels = channels;
|
||||
band->n_bitrates = ath10k_g_rates_size;
|
||||
band->bitrates = ath10k_g_rates;
|
||||
|
||||
if (ar->hw_params.cck_rate_map_rev2) {
|
||||
band->n_bitrates = ath10k_g_rates_rev2_size;
|
||||
band->bitrates = ath10k_g_rates_rev2;
|
||||
} else {
|
||||
band->n_bitrates = ath10k_g_rates_size;
|
||||
band->bitrates = ath10k_g_rates;
|
||||
}
|
||||
|
||||
ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band;
|
||||
}
|
||||
|
@ -56,7 +56,9 @@ static const struct pci_device_id ath10k_pci_id_table[] = {
|
||||
{ PCI_VDEVICE(ATHEROS, QCA6164_2_1_DEVICE_ID) }, /* PCI-E QCA6164 V2.1 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA99X0_2_0_DEVICE_ID) }, /* PCI-E QCA99X0 V2 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA9984_1_0_DEVICE_ID) }, /* PCI-E QCA9984 V1 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA9377_1_0_DEVICE_ID) }, /* PCI-E QCA9377 V1 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA9887_1_0_DEVICE_ID) }, /* PCI-E QCA9887 */
|
||||
{0}
|
||||
};
|
||||
|
||||
@ -81,8 +83,12 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = {
|
||||
|
||||
{ QCA99X0_2_0_DEVICE_ID, QCA99X0_HW_2_0_CHIP_ID_REV },
|
||||
|
||||
{ QCA9984_1_0_DEVICE_ID, QCA9984_HW_1_0_CHIP_ID_REV },
|
||||
|
||||
{ QCA9377_1_0_DEVICE_ID, QCA9377_HW_1_0_CHIP_ID_REV },
|
||||
{ QCA9377_1_0_DEVICE_ID, QCA9377_HW_1_1_CHIP_ID_REV },
|
||||
|
||||
{ QCA9887_1_0_DEVICE_ID, QCA9887_HW_1_0_CHIP_ID_REV },
|
||||
};
|
||||
|
||||
static void ath10k_pci_buffer_cleanup(struct ath10k *ar);
|
||||
@ -837,6 +843,7 @@ static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
|
||||
|
||||
switch (ar->hw_rev) {
|
||||
case ATH10K_HW_QCA988X:
|
||||
case ATH10K_HW_QCA9887:
|
||||
case ATH10K_HW_QCA6174:
|
||||
case ATH10K_HW_QCA9377:
|
||||
val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
|
||||
@ -844,6 +851,7 @@ static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
|
||||
0x7ff) << 21;
|
||||
break;
|
||||
case ATH10K_HW_QCA99X0:
|
||||
case ATH10K_HW_QCA9984:
|
||||
case ATH10K_HW_QCA4019:
|
||||
val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS);
|
||||
break;
|
||||
@ -864,7 +872,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
int ret = 0;
|
||||
u32 *buf;
|
||||
unsigned int completed_nbytes, orig_nbytes, remaining_bytes;
|
||||
unsigned int completed_nbytes, alloc_nbytes, remaining_bytes;
|
||||
struct ath10k_ce_pipe *ce_diag;
|
||||
/* Host buffer address in CE space */
|
||||
u32 ce_data;
|
||||
@ -882,9 +890,10 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
||||
* 1) 4-byte alignment
|
||||
* 2) Buffer in DMA-able space
|
||||
*/
|
||||
orig_nbytes = nbytes;
|
||||
alloc_nbytes = min_t(unsigned int, nbytes, DIAG_TRANSFER_LIMIT);
|
||||
|
||||
data_buf = (unsigned char *)dma_alloc_coherent(ar->dev,
|
||||
orig_nbytes,
|
||||
alloc_nbytes,
|
||||
&ce_data_base,
|
||||
GFP_ATOMIC);
|
||||
|
||||
@ -892,9 +901,9 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
memset(data_buf, 0, orig_nbytes);
|
||||
memset(data_buf, 0, alloc_nbytes);
|
||||
|
||||
remaining_bytes = orig_nbytes;
|
||||
remaining_bytes = nbytes;
|
||||
ce_data = ce_data_base;
|
||||
while (remaining_bytes) {
|
||||
nbytes = min_t(unsigned int, remaining_bytes,
|
||||
@ -954,19 +963,22 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
||||
}
|
||||
|
||||
remaining_bytes -= nbytes;
|
||||
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to read diag value at 0x%x: %d\n",
|
||||
address, ret);
|
||||
break;
|
||||
}
|
||||
memcpy(data, data_buf, nbytes);
|
||||
|
||||
address += nbytes;
|
||||
ce_data += nbytes;
|
||||
data += nbytes;
|
||||
}
|
||||
|
||||
done:
|
||||
if (ret == 0)
|
||||
memcpy(data, data_buf, orig_nbytes);
|
||||
else
|
||||
ath10k_warn(ar, "failed to read diag value at 0x%x: %d\n",
|
||||
address, ret);
|
||||
|
||||
if (data_buf)
|
||||
dma_free_coherent(ar->dev, orig_nbytes, data_buf,
|
||||
dma_free_coherent(ar->dev, alloc_nbytes, data_buf,
|
||||
ce_data_base);
|
||||
|
||||
spin_unlock_bh(&ar_pci->ce_lock);
|
||||
@ -1560,6 +1572,7 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
|
||||
|
||||
switch (ar->hw_rev) {
|
||||
case ATH10K_HW_QCA988X:
|
||||
case ATH10K_HW_QCA9887:
|
||||
case ATH10K_HW_QCA6174:
|
||||
case ATH10K_HW_QCA9377:
|
||||
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
|
||||
@ -1569,6 +1582,7 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
|
||||
CORE_CTRL_ADDRESS, val);
|
||||
break;
|
||||
case ATH10K_HW_QCA99X0:
|
||||
case ATH10K_HW_QCA9984:
|
||||
case ATH10K_HW_QCA4019:
|
||||
/* TODO: Find appropriate register configuration for QCA99X0
|
||||
* to mask irq/MSI.
|
||||
@ -1583,6 +1597,7 @@ static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar)
|
||||
|
||||
switch (ar->hw_rev) {
|
||||
case ATH10K_HW_QCA988X:
|
||||
case ATH10K_HW_QCA9887:
|
||||
case ATH10K_HW_QCA6174:
|
||||
case ATH10K_HW_QCA9377:
|
||||
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
|
||||
@ -1592,6 +1607,7 @@ static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar)
|
||||
CORE_CTRL_ADDRESS, val);
|
||||
break;
|
||||
case ATH10K_HW_QCA99X0:
|
||||
case ATH10K_HW_QCA9984:
|
||||
case ATH10K_HW_QCA4019:
|
||||
/* TODO: Find appropriate register configuration for QCA99X0
|
||||
* to unmask irq/MSI.
|
||||
@ -1932,6 +1948,8 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar)
|
||||
switch (ar_pci->pdev->device) {
|
||||
case QCA988X_2_0_DEVICE_ID:
|
||||
case QCA99X0_2_0_DEVICE_ID:
|
||||
case QCA9984_1_0_DEVICE_ID:
|
||||
case QCA9887_1_0_DEVICE_ID:
|
||||
return 1;
|
||||
case QCA6164_2_1_DEVICE_ID:
|
||||
case QCA6174_2_1_DEVICE_ID:
|
||||
@ -2293,16 +2311,20 @@ static int ath10k_pci_warm_reset(struct ath10k *ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_pci_qca99x0_soft_chip_reset(struct ath10k *ar)
|
||||
{
|
||||
ath10k_pci_irq_disable(ar);
|
||||
return ath10k_pci_qca99x0_chip_reset(ar);
|
||||
}
|
||||
|
||||
static int ath10k_pci_safe_chip_reset(struct ath10k *ar)
|
||||
{
|
||||
if (QCA_REV_988X(ar) || QCA_REV_6174(ar)) {
|
||||
return ath10k_pci_warm_reset(ar);
|
||||
} else if (QCA_REV_99X0(ar)) {
|
||||
ath10k_pci_irq_disable(ar);
|
||||
return ath10k_pci_qca99x0_chip_reset(ar);
|
||||
} else {
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
||||
if (!ar_pci->pci_soft_reset)
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return ar_pci->pci_soft_reset(ar);
|
||||
}
|
||||
|
||||
static int ath10k_pci_qca988x_chip_reset(struct ath10k *ar)
|
||||
@ -2437,16 +2459,12 @@ static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar)
|
||||
|
||||
static int ath10k_pci_chip_reset(struct ath10k *ar)
|
||||
{
|
||||
if (QCA_REV_988X(ar))
|
||||
return ath10k_pci_qca988x_chip_reset(ar);
|
||||
else if (QCA_REV_6174(ar))
|
||||
return ath10k_pci_qca6174_chip_reset(ar);
|
||||
else if (QCA_REV_9377(ar))
|
||||
return ath10k_pci_qca6174_chip_reset(ar);
|
||||
else if (QCA_REV_99X0(ar))
|
||||
return ath10k_pci_qca99x0_chip_reset(ar);
|
||||
else
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
||||
if (WARN_ON(!ar_pci->pci_hard_reset))
|
||||
return -ENOTSUPP;
|
||||
|
||||
return ar_pci->pci_hard_reset(ar);
|
||||
}
|
||||
|
||||
static int ath10k_pci_hif_power_up(struct ath10k *ar)
|
||||
@ -2559,6 +2577,144 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool ath10k_pci_validate_cal(void *data, size_t size)
|
||||
{
|
||||
__le16 *cal_words = data;
|
||||
u16 checksum = 0;
|
||||
size_t i;
|
||||
|
||||
if (size % 2 != 0)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < size / 2; i++)
|
||||
checksum ^= le16_to_cpu(cal_words[i]);
|
||||
|
||||
return checksum == 0xffff;
|
||||
}
|
||||
|
||||
static void ath10k_pci_enable_eeprom(struct ath10k *ar)
|
||||
{
|
||||
/* Enable SI clock */
|
||||
ath10k_pci_soc_write32(ar, CLOCK_CONTROL_OFFSET, 0x0);
|
||||
|
||||
/* Configure GPIOs for I2C operation */
|
||||
ath10k_pci_write32(ar,
|
||||
GPIO_BASE_ADDRESS + GPIO_PIN0_OFFSET +
|
||||
4 * QCA9887_1_0_I2C_SDA_GPIO_PIN,
|
||||
SM(QCA9887_1_0_I2C_SDA_PIN_CONFIG,
|
||||
GPIO_PIN0_CONFIG) |
|
||||
SM(1, GPIO_PIN0_PAD_PULL));
|
||||
|
||||
ath10k_pci_write32(ar,
|
||||
GPIO_BASE_ADDRESS + GPIO_PIN0_OFFSET +
|
||||
4 * QCA9887_1_0_SI_CLK_GPIO_PIN,
|
||||
SM(QCA9887_1_0_SI_CLK_PIN_CONFIG, GPIO_PIN0_CONFIG) |
|
||||
SM(1, GPIO_PIN0_PAD_PULL));
|
||||
|
||||
ath10k_pci_write32(ar,
|
||||
GPIO_BASE_ADDRESS +
|
||||
QCA9887_1_0_GPIO_ENABLE_W1TS_LOW_ADDRESS,
|
||||
1u << QCA9887_1_0_SI_CLK_GPIO_PIN);
|
||||
|
||||
/* In Swift ASIC - EEPROM clock will be (110MHz/512) = 214KHz */
|
||||
ath10k_pci_write32(ar,
|
||||
SI_BASE_ADDRESS + SI_CONFIG_OFFSET,
|
||||
SM(1, SI_CONFIG_ERR_INT) |
|
||||
SM(1, SI_CONFIG_BIDIR_OD_DATA) |
|
||||
SM(1, SI_CONFIG_I2C) |
|
||||
SM(1, SI_CONFIG_POS_SAMPLE) |
|
||||
SM(1, SI_CONFIG_INACTIVE_DATA) |
|
||||
SM(1, SI_CONFIG_INACTIVE_CLK) |
|
||||
SM(8, SI_CONFIG_DIVIDER));
|
||||
}
|
||||
|
||||
static int ath10k_pci_read_eeprom(struct ath10k *ar, u16 addr, u8 *out)
|
||||
{
|
||||
u32 reg;
|
||||
int wait_limit;
|
||||
|
||||
/* set device select byte and for the read operation */
|
||||
reg = QCA9887_EEPROM_SELECT_READ |
|
||||
SM(addr, QCA9887_EEPROM_ADDR_LO) |
|
||||
SM(addr >> 8, QCA9887_EEPROM_ADDR_HI);
|
||||
ath10k_pci_write32(ar, SI_BASE_ADDRESS + SI_TX_DATA0_OFFSET, reg);
|
||||
|
||||
/* write transmit data, transfer length, and START bit */
|
||||
ath10k_pci_write32(ar, SI_BASE_ADDRESS + SI_CS_OFFSET,
|
||||
SM(1, SI_CS_START) | SM(1, SI_CS_RX_CNT) |
|
||||
SM(4, SI_CS_TX_CNT));
|
||||
|
||||
/* wait max 1 sec */
|
||||
wait_limit = 100000;
|
||||
|
||||
/* wait for SI_CS_DONE_INT */
|
||||
do {
|
||||
reg = ath10k_pci_read32(ar, SI_BASE_ADDRESS + SI_CS_OFFSET);
|
||||
if (MS(reg, SI_CS_DONE_INT))
|
||||
break;
|
||||
|
||||
wait_limit--;
|
||||
udelay(10);
|
||||
} while (wait_limit > 0);
|
||||
|
||||
if (!MS(reg, SI_CS_DONE_INT)) {
|
||||
ath10k_err(ar, "timeout while reading device EEPROM at %04x\n",
|
||||
addr);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* clear SI_CS_DONE_INT */
|
||||
ath10k_pci_write32(ar, SI_BASE_ADDRESS + SI_CS_OFFSET, reg);
|
||||
|
||||
if (MS(reg, SI_CS_DONE_ERR)) {
|
||||
ath10k_err(ar, "failed to read device EEPROM at %04x\n", addr);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* extract receive data */
|
||||
reg = ath10k_pci_read32(ar, SI_BASE_ADDRESS + SI_RX_DATA0_OFFSET);
|
||||
*out = reg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_pci_hif_fetch_cal_eeprom(struct ath10k *ar, void **data,
|
||||
size_t *data_len)
|
||||
{
|
||||
u8 *caldata = NULL;
|
||||
size_t calsize, i;
|
||||
int ret;
|
||||
|
||||
if (!QCA_REV_9887(ar))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
calsize = ar->hw_params.cal_data_len;
|
||||
caldata = kmalloc(calsize, GFP_KERNEL);
|
||||
if (!caldata)
|
||||
return -ENOMEM;
|
||||
|
||||
ath10k_pci_enable_eeprom(ar);
|
||||
|
||||
for (i = 0; i < calsize; i++) {
|
||||
ret = ath10k_pci_read_eeprom(ar, i, &caldata[i]);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if (!ath10k_pci_validate_cal(caldata, calsize))
|
||||
goto err_free;
|
||||
|
||||
*data = caldata;
|
||||
*data_len = calsize;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
kfree(data);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
|
||||
.tx_sg = ath10k_pci_hif_tx_sg,
|
||||
.diag_read = ath10k_pci_hif_diag_read,
|
||||
@ -2578,6 +2734,7 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
|
||||
.suspend = ath10k_pci_hif_suspend,
|
||||
.resume = ath10k_pci_hif_resume,
|
||||
#endif
|
||||
.fetch_cal_eeprom = ath10k_pci_hif_fetch_cal_eeprom,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -2976,24 +3133,47 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
enum ath10k_hw_rev hw_rev;
|
||||
u32 chip_id;
|
||||
bool pci_ps;
|
||||
int (*pci_soft_reset)(struct ath10k *ar);
|
||||
int (*pci_hard_reset)(struct ath10k *ar);
|
||||
|
||||
switch (pci_dev->device) {
|
||||
case QCA988X_2_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA988X;
|
||||
pci_ps = false;
|
||||
pci_soft_reset = ath10k_pci_warm_reset;
|
||||
pci_hard_reset = ath10k_pci_qca988x_chip_reset;
|
||||
break;
|
||||
case QCA9887_1_0_DEVICE_ID:
|
||||
dev_warn(&pdev->dev, "QCA9887 support is still experimental, there are likely bugs. You have been warned.\n");
|
||||
hw_rev = ATH10K_HW_QCA9887;
|
||||
pci_ps = false;
|
||||
pci_soft_reset = ath10k_pci_warm_reset;
|
||||
pci_hard_reset = ath10k_pci_qca988x_chip_reset;
|
||||
break;
|
||||
case QCA6164_2_1_DEVICE_ID:
|
||||
case QCA6174_2_1_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA6174;
|
||||
pci_ps = true;
|
||||
pci_soft_reset = ath10k_pci_warm_reset;
|
||||
pci_hard_reset = ath10k_pci_qca6174_chip_reset;
|
||||
break;
|
||||
case QCA99X0_2_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA99X0;
|
||||
pci_ps = false;
|
||||
pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset;
|
||||
pci_hard_reset = ath10k_pci_qca99x0_chip_reset;
|
||||
break;
|
||||
case QCA9984_1_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA9984;
|
||||
pci_ps = false;
|
||||
pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset;
|
||||
pci_hard_reset = ath10k_pci_qca99x0_chip_reset;
|
||||
break;
|
||||
case QCA9377_1_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA9377;
|
||||
pci_ps = true;
|
||||
pci_soft_reset = NULL;
|
||||
pci_hard_reset = ath10k_pci_qca6174_chip_reset;
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
@ -3018,6 +3198,8 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
ar->dev_id = pci_dev->device;
|
||||
ar_pci->pci_ps = pci_ps;
|
||||
ar_pci->bus_ops = &ath10k_pci_bus_ops;
|
||||
ar_pci->pci_soft_reset = pci_soft_reset;
|
||||
ar_pci->pci_hard_reset = pci_hard_reset;
|
||||
|
||||
ar->id.vendor = pdev->vendor;
|
||||
ar->id.device = pdev->device;
|
||||
@ -3169,7 +3351,7 @@ static void __exit ath10k_pci_exit(void)
|
||||
module_exit(ath10k_pci_exit);
|
||||
|
||||
MODULE_AUTHOR("Qualcomm Atheros");
|
||||
MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices");
|
||||
MODULE_DESCRIPTION("Driver support for Qualcomm Atheros 802.11ac WLAN PCIe/AHB devices");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
/* QCA988x 2.0 firmware files */
|
||||
@ -3180,6 +3362,11 @@ MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API5_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_BOARD_API2_FILE);
|
||||
|
||||
/* QCA9887 1.0 firmware files */
|
||||
MODULE_FIRMWARE(QCA9887_HW_1_0_FW_DIR "/" ATH10K_FW_API5_FILE);
|
||||
MODULE_FIRMWARE(QCA9887_HW_1_0_FW_DIR "/" QCA9887_HW_1_0_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(QCA9887_HW_1_0_FW_DIR "/" ATH10K_BOARD_API2_FILE);
|
||||
|
||||
/* QCA6174 2.1 firmware files */
|
||||
MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API4_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API5_FILE);
|
||||
|
@ -234,6 +234,12 @@ struct ath10k_pci {
|
||||
|
||||
const struct ath10k_bus_ops *bus_ops;
|
||||
|
||||
/* Chip specific pci reset routine used to do a safe reset */
|
||||
int (*pci_soft_reset)(struct ath10k *ar);
|
||||
|
||||
/* Chip specific pci full reset function */
|
||||
int (*pci_hard_reset)(struct ath10k *ar);
|
||||
|
||||
/* Keep this entry in the last, memory for struct ath10k_ahb is
|
||||
* allocated (ahb support enabled case) in the continuation of
|
||||
* this struct.
|
||||
|
@ -656,26 +656,6 @@ struct rx_msdu_end {
|
||||
* Reserved: HW should fill with zero. FW should ignore.
|
||||
*/
|
||||
|
||||
#define RX_PPDU_START_SIG_RATE_SELECT_OFDM 0
|
||||
#define RX_PPDU_START_SIG_RATE_SELECT_CCK 1
|
||||
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_48 0
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_24 1
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_12 2
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_6 3
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_54 4
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_36 5
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_18 6
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_9 7
|
||||
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_LP_11 0
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_LP_5_5 1
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_LP_2 2
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_LP_1 3
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_SP_11 4
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_SP_5_5 5
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_SP_2 6
|
||||
|
||||
#define HTT_RX_PPDU_START_PREAMBLE_LEGACY 0x04
|
||||
#define HTT_RX_PPDU_START_PREAMBLE_HT 0x08
|
||||
#define HTT_RX_PPDU_START_PREAMBLE_HT_WITH_TXBF 0x09
|
||||
@ -711,25 +691,6 @@ struct rx_msdu_end {
|
||||
/* No idea what this flag means. It seems to be always set in rate. */
|
||||
#define RX_PPDU_START_RATE_FLAG BIT(3)
|
||||
|
||||
enum rx_ppdu_start_rate {
|
||||
RX_PPDU_START_RATE_OFDM_48M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_48M,
|
||||
RX_PPDU_START_RATE_OFDM_24M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_24M,
|
||||
RX_PPDU_START_RATE_OFDM_12M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_12M,
|
||||
RX_PPDU_START_RATE_OFDM_6M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_6M,
|
||||
RX_PPDU_START_RATE_OFDM_54M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_54M,
|
||||
RX_PPDU_START_RATE_OFDM_36M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_36M,
|
||||
RX_PPDU_START_RATE_OFDM_18M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_18M,
|
||||
RX_PPDU_START_RATE_OFDM_9M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_9M,
|
||||
|
||||
RX_PPDU_START_RATE_CCK_LP_11M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_11M,
|
||||
RX_PPDU_START_RATE_CCK_LP_5_5M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_5_5M,
|
||||
RX_PPDU_START_RATE_CCK_LP_2M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_2M,
|
||||
RX_PPDU_START_RATE_CCK_LP_1M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_1M,
|
||||
RX_PPDU_START_RATE_CCK_SP_11M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_SP_11M,
|
||||
RX_PPDU_START_RATE_CCK_SP_5_5M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_SP_5_5M,
|
||||
RX_PPDU_START_RATE_CCK_SP_2M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_SP_2M,
|
||||
};
|
||||
|
||||
struct rx_ppdu_start {
|
||||
struct {
|
||||
u8 pri20_mhz;
|
||||
@ -994,7 +955,41 @@ struct rx_pkt_end {
|
||||
__le32 info0; /* %RX_PKT_END_INFO0_ */
|
||||
__le32 phy_timestamp_1;
|
||||
__le32 phy_timestamp_2;
|
||||
__le32 rx_location_info; /* %RX_LOCATION_INFO_ */
|
||||
} __packed;
|
||||
|
||||
#define RX_LOCATION_INFO0_RTT_FAC_LEGACY_MASK 0x00003fff
|
||||
#define RX_LOCATION_INFO0_RTT_FAC_LEGACY_LSB 0
|
||||
#define RX_LOCATION_INFO0_RTT_FAC_VHT_MASK 0x1fff8000
|
||||
#define RX_LOCATION_INFO0_RTT_FAC_VHT_LSB 15
|
||||
#define RX_LOCATION_INFO0_RTT_STRONGEST_CHAIN_MASK 0xc0000000
|
||||
#define RX_LOCATION_INFO0_RTT_STRONGEST_CHAIN_LSB 30
|
||||
#define RX_LOCATION_INFO0_RTT_FAC_LEGACY_STATUS BIT(14)
|
||||
#define RX_LOCATION_INFO0_RTT_FAC_VHT_STATUS BIT(29)
|
||||
|
||||
#define RX_LOCATION_INFO1_RTT_PREAMBLE_TYPE_MASK 0x0000000c
|
||||
#define RX_LOCATION_INFO1_RTT_PREAMBLE_TYPE_LSB 2
|
||||
#define RX_LOCATION_INFO1_PKT_BW_MASK 0x00000030
|
||||
#define RX_LOCATION_INFO1_PKT_BW_LSB 4
|
||||
#define RX_LOCATION_INFO1_SKIP_P_SKIP_BTCF_MASK 0x0000ff00
|
||||
#define RX_LOCATION_INFO1_SKIP_P_SKIP_BTCF_LSB 8
|
||||
#define RX_LOCATION_INFO1_RTT_MSC_RATE_MASK 0x000f0000
|
||||
#define RX_LOCATION_INFO1_RTT_MSC_RATE_LSB 16
|
||||
#define RX_LOCATION_INFO1_RTT_PBD_LEG_BW_MASK 0x00300000
|
||||
#define RX_LOCATION_INFO1_RTT_PBD_LEG_BW_LSB 20
|
||||
#define RX_LOCATION_INFO1_TIMING_BACKOFF_MASK 0x07c00000
|
||||
#define RX_LOCATION_INFO1_TIMING_BACKOFF_LSB 22
|
||||
#define RX_LOCATION_INFO1_RTT_TX_FRAME_PHASE_MASK 0x18000000
|
||||
#define RX_LOCATION_INFO1_RTT_TX_FRAME_PHASE_LSB 27
|
||||
#define RX_LOCATION_INFO1_RTT_CFR_STATUS BIT(0)
|
||||
#define RX_LOCATION_INFO1_RTT_CIR_STATUS BIT(1)
|
||||
#define RX_LOCATION_INFO1_RTT_GI_TYPE BIT(7)
|
||||
#define RX_LOCATION_INFO1_RTT_MAC_PHY_PHASE BIT(29)
|
||||
#define RX_LOCATION_INFO1_RTT_TX_DATA_START_X_PHASE BIT(30)
|
||||
#define RX_LOCATION_INFO1_RX_LOCATION_VALID BIT(31)
|
||||
|
||||
struct rx_location_info {
|
||||
__le32 rx_location_info0; /* %RX_LOCATION_INFO0_ */
|
||||
__le32 rx_location_info1; /* %RX_LOCATION_INFO1_ */
|
||||
} __packed;
|
||||
|
||||
enum rx_phy_ppdu_end_info0 {
|
||||
@ -1067,6 +1062,17 @@ struct rx_phy_ppdu_end {
|
||||
|
||||
struct rx_ppdu_end_qca99x0 {
|
||||
struct rx_pkt_end rx_pkt_end;
|
||||
__le32 rx_location_info; /* %RX_LOCATION_INFO_ */
|
||||
struct rx_phy_ppdu_end rx_phy_ppdu_end;
|
||||
__le32 rx_timing_offset; /* %RX_PPDU_END_RX_TIMING_OFFSET_ */
|
||||
__le32 rx_info; /* %RX_PPDU_END_RX_INFO_ */
|
||||
__le16 bb_length;
|
||||
__le16 info1; /* %RX_PPDU_END_INFO1_ */
|
||||
} __packed;
|
||||
|
||||
struct rx_ppdu_end_qca9984 {
|
||||
struct rx_pkt_end rx_pkt_end;
|
||||
struct rx_location_info rx_location_info;
|
||||
struct rx_phy_ppdu_end rx_phy_ppdu_end;
|
||||
__le32 rx_timing_offset; /* %RX_PPDU_END_RX_TIMING_OFFSET_ */
|
||||
__le32 rx_info; /* %RX_PPDU_END_RX_INFO_ */
|
||||
@ -1080,6 +1086,7 @@ struct rx_ppdu_end {
|
||||
struct rx_ppdu_end_qca988x qca988x;
|
||||
struct rx_ppdu_end_qca6174 qca6174;
|
||||
struct rx_ppdu_end_qca99x0 qca99x0;
|
||||
struct rx_ppdu_end_qca9984 qca9984;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
|
@ -447,6 +447,9 @@ Fw Mode/SubMode Mask
|
||||
#define QCA988X_BOARD_DATA_SZ 7168
|
||||
#define QCA988X_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
#define QCA9887_BOARD_DATA_SZ 7168
|
||||
#define QCA9887_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
#define QCA6174_BOARD_DATA_SZ 8192
|
||||
#define QCA6174_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
|
@ -117,6 +117,9 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
|
||||
ieee80211_tx_status(htt->ar->hw, msdu);
|
||||
/* we do not own the msdu anymore */
|
||||
|
||||
ath10k_mac_tx_push_pending(ar);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1104,6 +1104,7 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = {
|
||||
.wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
};
|
||||
|
||||
static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
|
||||
@ -1199,6 +1200,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
|
||||
.wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
};
|
||||
|
||||
static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
|
||||
@ -1294,6 +1296,7 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
|
||||
.wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
};
|
||||
|
||||
/* firmware 10.2 specific mappings */
|
||||
@ -1550,6 +1553,7 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
|
||||
.wapi_mbssid_offset = WMI_10_4_PDEV_PARAM_WAPI_MBSSID_OFFSET,
|
||||
.arp_srcaddr = WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
|
||||
.arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
|
||||
.enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
|
||||
};
|
||||
|
||||
static const struct wmi_peer_flags_map wmi_peer_flags_map = {
|
||||
|
@ -3447,6 +3447,7 @@ struct wmi_pdev_param_map {
|
||||
u32 wapi_mbssid_offset;
|
||||
u32 arp_srcaddr;
|
||||
u32 arp_dstaddr;
|
||||
u32 enable_btcoex;
|
||||
};
|
||||
|
||||
#define WMI_PDEV_PARAM_UNSUPPORTED 0
|
||||
@ -3760,6 +3761,9 @@ enum wmi_10_4_pdev_param {
|
||||
WMI_10_4_PDEV_PARAM_ATF_OBSS_NOISE_SCH,
|
||||
WMI_10_4_PDEV_PARAM_ATF_OBSS_NOISE_SCALING_FACTOR,
|
||||
WMI_10_4_PDEV_PARAM_CUST_TXPOWER_SCALE,
|
||||
WMI_10_4_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
|
||||
WMI_10_4_PDEV_PARAM_ATF_SSID_GROUP_POLICY,
|
||||
WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
|
||||
};
|
||||
|
||||
struct wmi_pdev_set_param_cmd {
|
||||
|
@ -219,8 +219,8 @@ ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
|
||||
sifs = AR5K_INIT_SIFS_QUARTER_RATE;
|
||||
break;
|
||||
case AR5K_BWMODE_DEFAULT:
|
||||
sifs = AR5K_INIT_SIFS_DEFAULT_BG;
|
||||
default:
|
||||
sifs = AR5K_INIT_SIFS_DEFAULT_BG;
|
||||
if (channel->band == NL80211_BAND_5GHZ)
|
||||
sifs = AR5K_INIT_SIFS_DEFAULT_A;
|
||||
break;
|
||||
|
@ -148,7 +148,7 @@ enum ath6kl_fw_capability {
|
||||
/* ratetable is the 2 stream version (max MCS15) */
|
||||
ATH6KL_FW_CAPABILITY_RATETABLE_MCS15,
|
||||
|
||||
/* firmare doesn't support IP checksumming */
|
||||
/* firmware doesn't support IP checksumming */
|
||||
ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM,
|
||||
|
||||
/* this needs to be last */
|
||||
|
@ -2544,8 +2544,7 @@ int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi, u8 if_idx,
|
||||
s32 nominal_phy = 0;
|
||||
int ret;
|
||||
|
||||
if (!((params->user_pri < 8) &&
|
||||
(params->user_pri <= 0x7) &&
|
||||
if (!((params->user_pri <= 0x7) &&
|
||||
(up_to_ac[params->user_pri & 0x7] == params->traffic_class) &&
|
||||
(params->traffic_direc == UPLINK_TRAFFIC ||
|
||||
params->traffic_direc == DNLINK_TRAFFIC ||
|
||||
|
@ -3202,8 +3202,7 @@ static int ar9300_compress_decision(struct ath_hw *ah,
|
||||
it, length);
|
||||
break;
|
||||
case _CompressBlock:
|
||||
if (reference == 0) {
|
||||
} else {
|
||||
if (reference != 0) {
|
||||
eep = ar9003_eeprom_struct_find_by_id(reference);
|
||||
if (eep == NULL) {
|
||||
ath_dbg(common, EEPROM,
|
||||
|
@ -132,7 +132,6 @@ static int ath9k_tx99_init(struct ath_softc *sc)
|
||||
ath9k_ps_wakeup(sc);
|
||||
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
atomic_set(&ah->intr_ref_cnt, -1);
|
||||
ath_drain_all_txq(sc);
|
||||
ath_stoprecv(sc);
|
||||
|
||||
@ -266,7 +265,7 @@ static const struct file_operations fops_tx99_power = {
|
||||
|
||||
void ath9k_tx99_init_debug(struct ath_softc *sc)
|
||||
{
|
||||
if (!AR_SREV_9300_20_OR_LATER(sc->sc_ah))
|
||||
if (!AR_SREV_9280_20_OR_LATER(sc->sc_ah))
|
||||
return;
|
||||
|
||||
debugfs_create_file("tx99", S_IRUSR | S_IWUSR,
|
||||
|
@ -378,6 +378,10 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
||||
/* social scan on P2P_DEVICE is handled as p2p search */
|
||||
if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE &&
|
||||
wil_p2p_is_social_scan(request)) {
|
||||
if (!wil->p2p.p2p_dev_started) {
|
||||
wil_err(wil, "P2P search requested on stopped P2P device\n");
|
||||
return -EIO;
|
||||
}
|
||||
wil->scan_request = request;
|
||||
wil->radio_wdev = wdev;
|
||||
rc = wil_p2p_search(wil, request);
|
||||
@ -1351,6 +1355,7 @@ static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy,
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
|
||||
wil_dbg_misc(wil, "%s: entered\n", __func__);
|
||||
wil->p2p.p2p_dev_started = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1358,8 +1363,19 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev)
|
||||
{
|
||||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
u8 started;
|
||||
|
||||
wil_dbg_misc(wil, "%s: entered\n", __func__);
|
||||
mutex_lock(&wil->mutex);
|
||||
started = wil_p2p_stop_discovery(wil);
|
||||
if (started && wil->scan_request) {
|
||||
cfg80211_scan_done(wil->scan_request, 1);
|
||||
wil->scan_request = NULL;
|
||||
wil->radio_wdev = wil->wdev;
|
||||
}
|
||||
mutex_unlock(&wil->mutex);
|
||||
|
||||
wil->p2p.p2p_dev_started = 0;
|
||||
}
|
||||
|
||||
static struct cfg80211_ops wil_cfg80211_ops = {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2013,2016 Qualcomm Atheros, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -19,34 +19,31 @@
|
||||
|
||||
void __wil_err(struct wil6210_priv *wil, const char *fmt, ...)
|
||||
{
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct va_format vaf = {
|
||||
.fmt = fmt,
|
||||
};
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
netdev_err(ndev, "%pV", &vaf);
|
||||
netdev_err(wil_to_ndev(wil), "%pV", &vaf);
|
||||
trace_wil6210_log_err(&vaf);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...)
|
||||
{
|
||||
if (net_ratelimit()) {
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct va_format vaf = {
|
||||
.fmt = fmt,
|
||||
};
|
||||
va_list args;
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.va = &args;
|
||||
netdev_err(ndev, "%pV", &vaf);
|
||||
trace_wil6210_log_err(&vaf);
|
||||
va_end(args);
|
||||
}
|
||||
if (!net_ratelimit())
|
||||
return;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
netdev_err(wil_to_ndev(wil), "%pV", &vaf);
|
||||
trace_wil6210_log_err(&vaf);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...)
|
||||
@ -67,27 +64,24 @@ void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...)
|
||||
|
||||
void __wil_info(struct wil6210_priv *wil, const char *fmt, ...)
|
||||
{
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct va_format vaf = {
|
||||
.fmt = fmt,
|
||||
};
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
netdev_info(ndev, "%pV", &vaf);
|
||||
netdev_info(wil_to_ndev(wil), "%pV", &vaf);
|
||||
trace_wil6210_log_info(&vaf);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf = {
|
||||
.fmt = fmt,
|
||||
};
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
trace_wil6210_log_dbg(&vaf);
|
||||
va_end(args);
|
||||
|
@ -114,8 +114,10 @@ int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration,
|
||||
u8 channel = P2P_DMG_SOCIAL_CHANNEL;
|
||||
int rc;
|
||||
|
||||
if (chan)
|
||||
channel = chan->hw_value;
|
||||
if (!chan)
|
||||
return -EINVAL;
|
||||
|
||||
channel = chan->hw_value;
|
||||
|
||||
wil_dbg_misc(wil, "%s: duration %d\n", __func__, duration);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2015 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -18,13 +18,20 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <linux/suspend.h>
|
||||
#include "wil6210.h"
|
||||
|
||||
static bool use_msi = true;
|
||||
module_param(use_msi, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(use_msi, " Use MSI interrupt, default - true");
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int wil6210_pm_notify(struct notifier_block *notify_block,
|
||||
unsigned long mode, void *unused);
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static
|
||||
void wil_set_capabilities(struct wil6210_priv *wil)
|
||||
{
|
||||
@ -238,6 +245,18 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
goto bus_disable;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
wil->pm_notify.notifier_call = wil6210_pm_notify;
|
||||
rc = register_pm_notifier(&wil->pm_notify);
|
||||
if (rc)
|
||||
/* Do not fail the driver initialization, as suspend can
|
||||
* be prevented in a later phase if needed
|
||||
*/
|
||||
wil_err(wil, "register_pm_notifier failed: %d\n", rc);
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
wil6210_debugfs_init(wil);
|
||||
|
||||
|
||||
@ -267,6 +286,12 @@ static void wil_pcie_remove(struct pci_dev *pdev)
|
||||
|
||||
wil_dbg_misc(wil, "%s()\n", __func__);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
unregister_pm_notifier(&wil->pm_notify);
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
wil6210_debugfs_remove(wil);
|
||||
wil_if_remove(wil);
|
||||
wil_if_pcie_disable(wil);
|
||||
@ -335,6 +360,45 @@ static int wil6210_resume(struct device *dev, bool is_runtime)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int wil6210_pm_notify(struct notifier_block *notify_block,
|
||||
unsigned long mode, void *unused)
|
||||
{
|
||||
struct wil6210_priv *wil = container_of(
|
||||
notify_block, struct wil6210_priv, pm_notify);
|
||||
int rc = 0;
|
||||
enum wil_platform_event evt;
|
||||
|
||||
wil_dbg_pm(wil, "%s: mode (%ld)\n", __func__, mode);
|
||||
|
||||
switch (mode) {
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
case PM_SUSPEND_PREPARE:
|
||||
case PM_RESTORE_PREPARE:
|
||||
rc = wil_can_suspend(wil, false);
|
||||
if (rc)
|
||||
break;
|
||||
evt = WIL_PLATFORM_EVT_PRE_SUSPEND;
|
||||
if (wil->platform_ops.notify)
|
||||
rc = wil->platform_ops.notify(wil->platform_handle,
|
||||
evt);
|
||||
break;
|
||||
case PM_POST_SUSPEND:
|
||||
case PM_POST_HIBERNATION:
|
||||
case PM_POST_RESTORE:
|
||||
evt = WIL_PLATFORM_EVT_POST_SUSPEND;
|
||||
if (wil->platform_ops.notify)
|
||||
rc = wil->platform_ops.notify(wil->platform_handle,
|
||||
evt);
|
||||
break;
|
||||
default:
|
||||
wil_dbg_pm(wil, "unhandled notify mode %ld\n", mode);
|
||||
break;
|
||||
}
|
||||
|
||||
wil_dbg_pm(wil, "notification mode %ld: rc (%d)\n", mode, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int wil6210_pm_suspend(struct device *dev)
|
||||
{
|
||||
return wil6210_suspend(dev, false);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2014,2016 Qualcomm Atheros, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -24,10 +24,32 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime)
|
||||
wil_dbg_pm(wil, "%s(%s)\n", __func__,
|
||||
is_runtime ? "runtime" : "system");
|
||||
|
||||
if (!netif_running(wil_to_ndev(wil))) {
|
||||
/* can always sleep when down */
|
||||
wil_dbg_pm(wil, "Interface is down\n");
|
||||
goto out;
|
||||
}
|
||||
if (test_bit(wil_status_resetting, wil->status)) {
|
||||
wil_dbg_pm(wil, "Delay suspend when resetting\n");
|
||||
rc = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
if (wil->recovery_state != fw_recovery_idle) {
|
||||
wil_dbg_pm(wil, "Delay suspend during recovery\n");
|
||||
rc = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* interface is running */
|
||||
switch (wdev->iftype) {
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
if (test_bit(wil_status_fwconnecting, wil->status)) {
|
||||
wil_dbg_pm(wil, "Delay suspend when connecting\n");
|
||||
rc = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
/* AP-like interface - can't suspend */
|
||||
default:
|
||||
@ -36,6 +58,7 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
wil_dbg_pm(wil, "%s(%s) => %s (%d)\n", __func__,
|
||||
is_runtime ? "runtime" : "system", rc ? "No" : "Yes", rc);
|
||||
|
||||
|
@ -184,6 +184,13 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
|
||||
&vring->va[vring->swtail].tx;
|
||||
|
||||
ctx = &vring->ctx[vring->swtail];
|
||||
if (!ctx) {
|
||||
wil_dbg_txrx(wil,
|
||||
"ctx(%d) was already completed\n",
|
||||
vring->swtail);
|
||||
vring->swtail = wil_vring_next_tail(vring);
|
||||
continue;
|
||||
}
|
||||
*d = *_d;
|
||||
wil_txdesc_unmap(dev, d, ctx);
|
||||
if (ctx->skb)
|
||||
@ -544,6 +551,12 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* make sure all writes to descriptors (shared memory) are done before
|
||||
* committing them to HW
|
||||
*/
|
||||
wmb();
|
||||
|
||||
wil_w(wil, v->hwtail, v->swtail);
|
||||
|
||||
return rc;
|
||||
@ -969,6 +982,13 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
|
||||
txdata->dot1x_open = false;
|
||||
txdata->enabled = 0; /* no Tx can be in progress or start anew */
|
||||
spin_unlock_bh(&txdata->lock);
|
||||
/* napi_synchronize waits for completion of the current NAPI but will
|
||||
* not prevent the next NAPI run.
|
||||
* Add a memory barrier to guarantee that txdata->enabled is zeroed
|
||||
* before napi_synchronize so that the next scheduled NAPI will not
|
||||
* handle this vring
|
||||
*/
|
||||
wmb();
|
||||
/* make sure NAPI won't touch this vring */
|
||||
if (test_bit(wil_status_napi_en, wil->status))
|
||||
napi_synchronize(&wil->napi_tx);
|
||||
@ -1551,6 +1571,13 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
|
||||
vring_index, used, used + descs_used);
|
||||
}
|
||||
|
||||
/* Make sure to advance the head only after descriptor update is done.
|
||||
* This will prevent a race condition where the completion thread
|
||||
* will see the DU bit set from previous run and will handle the
|
||||
* skb before it was completed.
|
||||
*/
|
||||
wmb();
|
||||
|
||||
/* advance swhead */
|
||||
wil_vring_advance_head(vring, descs_used);
|
||||
wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead);
|
||||
@ -1567,7 +1594,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
|
||||
while (descs_used > 0) {
|
||||
struct wil_ctx *ctx;
|
||||
|
||||
i = (swhead + descs_used) % vring->size;
|
||||
i = (swhead + descs_used - 1) % vring->size;
|
||||
d = (struct vring_tx_desc *)&vring->va[i].tx;
|
||||
_desc = &vring->va[i].tx;
|
||||
*d = *_desc;
|
||||
@ -1691,6 +1718,13 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
||||
vring_index, used, used + nr_frags + 1);
|
||||
}
|
||||
|
||||
/* Make sure to advance the head only after descriptor update is done.
|
||||
* This will prevent a race condition where the completion thread
|
||||
* will see the DU bit set from previous run and will handle the
|
||||
* skb before it was completed.
|
||||
*/
|
||||
wmb();
|
||||
|
||||
/* advance swhead */
|
||||
wil_vring_advance_head(vring, nr_frags + 1);
|
||||
wil_dbg_txrx(wil, "Tx[%2d] swhead %d -> %d\n", vring_index, swhead,
|
||||
@ -1914,6 +1948,12 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
||||
wil_consume_skb(skb, d->dma.error == 0);
|
||||
}
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
/* Make sure the ctx is zeroed before updating the tail
|
||||
* to prevent a case where wil_tx_vring will see
|
||||
* this descriptor as used and handle it before ctx zero
|
||||
* is completed.
|
||||
*/
|
||||
wmb();
|
||||
/* There is no need to touch HW descriptor:
|
||||
* - ststus bit TX_DMA_STATUS_DU is set by design,
|
||||
* so hardware will not try to process this desc.,
|
||||
|
@ -458,6 +458,7 @@ struct wil_tid_crypto_rx {
|
||||
struct wil_p2p_info {
|
||||
struct ieee80211_channel listen_chan;
|
||||
u8 discovery_started;
|
||||
u8 p2p_dev_started;
|
||||
u64 cookie;
|
||||
struct timer_list discovery_timer; /* listen/search duration */
|
||||
struct work_struct discovery_expired_work; /* listen/search expire */
|
||||
@ -662,6 +663,11 @@ struct wil6210_priv {
|
||||
/* High Access Latency Policy voting */
|
||||
struct wil_halp halp;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
struct notifier_block pm_notify;
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
#endif /* CONFIG_PM */
|
||||
};
|
||||
|
||||
#define wil_to_wiphy(i) (i->wdev->wiphy)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2015 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2014-2016 Qualcomm Atheros, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -23,6 +23,8 @@ enum wil_platform_event {
|
||||
WIL_PLATFORM_EVT_FW_CRASH = 0,
|
||||
WIL_PLATFORM_EVT_PRE_RESET = 1,
|
||||
WIL_PLATFORM_EVT_FW_RDY = 2,
|
||||
WIL_PLATFORM_EVT_PRE_SUSPEND = 3,
|
||||
WIL_PLATFORM_EVT_POST_SUSPEND = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user