mirror of https://gitee.com/openkylin/linux.git
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for 4.12. Major changes: ath10k * improve firmware download time for QCA6174 and QCA9377, especially helps resume time ath9k_htc * add support AirTies 1eda:2315 AR9271 device
This commit is contained in:
commit
09e40034f3
|
@ -19,12 +19,21 @@
|
|||
#include "hif.h"
|
||||
#include "debug.h"
|
||||
#include "htc.h"
|
||||
#include "hw.h"
|
||||
|
||||
void ath10k_bmi_start(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi start\n");
|
||||
|
||||
ar->bmi.done_sent = false;
|
||||
|
||||
/* Enable hardware clock to speed up firmware download */
|
||||
if (ar->hw_params.hw_ops->enable_pll_clk) {
|
||||
ret = ar->hw_params.hw_ops->enable_pll_clk(ar);
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi enable pll ret %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
int ath10k_bmi_done(struct ath10k *ar)
|
||||
|
@ -129,6 +138,69 @@ int ath10k_bmi_read_memory(struct ath10k *ar,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val)
|
||||
{
|
||||
struct bmi_cmd cmd;
|
||||
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.write_soc_reg);
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI,
|
||||
"bmi write soc register 0x%08x val 0x%08x\n",
|
||||
address, reg_val);
|
||||
|
||||
if (ar->bmi.done_sent) {
|
||||
ath10k_warn(ar, "bmi write soc register command in progress\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
cmd.id = __cpu_to_le32(BMI_WRITE_SOC_REGISTER);
|
||||
cmd.write_soc_reg.addr = __cpu_to_le32(address);
|
||||
cmd.write_soc_reg.value = __cpu_to_le32(reg_val);
|
||||
|
||||
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "Unable to write soc register to device: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_bmi_read_soc_reg(struct ath10k *ar, u32 address, u32 *reg_val)
|
||||
{
|
||||
struct bmi_cmd cmd;
|
||||
union bmi_resp resp;
|
||||
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.read_soc_reg);
|
||||
u32 resplen = sizeof(resp.read_soc_reg);
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi read soc register 0x%08x\n",
|
||||
address);
|
||||
|
||||
if (ar->bmi.done_sent) {
|
||||
ath10k_warn(ar, "bmi read soc register command in progress\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
cmd.id = __cpu_to_le32(BMI_READ_SOC_REGISTER);
|
||||
cmd.read_soc_reg.addr = __cpu_to_le32(address);
|
||||
|
||||
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "Unable to read soc register from device: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*reg_val = __le32_to_cpu(resp.read_soc_reg.value);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi read soc register value 0x%08x\n",
|
||||
*reg_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_bmi_write_memory(struct ath10k *ar,
|
||||
u32 address, const void *buffer, u32 length)
|
||||
{
|
||||
|
|
|
@ -232,4 +232,6 @@ int ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address);
|
|||
int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length);
|
||||
int ath10k_bmi_fast_download(struct ath10k *ar, u32 address,
|
||||
const void *buffer, u32 length);
|
||||
int ath10k_bmi_read_soc_reg(struct ath10k *ar, u32 address, u32 *reg_val);
|
||||
int ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val);
|
||||
#endif /* _BMI_H_ */
|
||||
|
|
|
@ -166,7 +166,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.board_size = QCA6174_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.hw_ops = &qca988x_ops,
|
||||
.hw_ops = &qca6174_ops,
|
||||
.hw_clk = qca6174_clk,
|
||||
.target_cpu_freq = 176000000,
|
||||
.decap_align_bytes = 4,
|
||||
},
|
||||
{
|
||||
|
@ -280,7 +282,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.board_size = QCA9377_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
.hw_ops = &qca988x_ops,
|
||||
.hw_ops = &qca6174_ops,
|
||||
.hw_clk = qca6174_clk,
|
||||
.target_cpu_freq = 176000000,
|
||||
.decap_align_bytes = 4,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -775,6 +775,8 @@ struct ath10k {
|
|||
u32 num_rf_chains;
|
||||
u32 max_spatial_stream;
|
||||
/* protected by conf_mutex */
|
||||
u32 low_5ghz_chan;
|
||||
u32 high_5ghz_chan;
|
||||
bool ani_enabled;
|
||||
|
||||
bool p2p;
|
||||
|
|
|
@ -249,9 +249,6 @@ static ssize_t ath10k_read_wmi_services(struct file *file,
|
|||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (len > buf_len)
|
||||
len = buf_len;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
for (i = 0; i < WMI_SERVICE_MAX; i++) {
|
||||
enabled = test_bit(i, ar->wmi.svc_map);
|
||||
|
@ -1997,6 +1994,15 @@ static ssize_t ath10k_write_simulate_radar(struct file *file,
|
|||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
struct ath10k_vif *arvif;
|
||||
|
||||
/* Just check for for the first vif alone, as all the vifs will be
|
||||
* sharing the same channel and if the channel is disabled, all the
|
||||
* vifs will share the same 'is_started' state.
|
||||
*/
|
||||
arvif = list_first_entry(&ar->arvifs, typeof(*arvif), list);
|
||||
if (!arvif->is_started)
|
||||
return -EINVAL;
|
||||
|
||||
ieee80211_radar_detected(ar->hw);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "hw.h"
|
||||
#include "hif.h"
|
||||
#include "wmi-ops.h"
|
||||
#include "bmi.h"
|
||||
|
||||
const struct ath10k_hw_regs qca988x_regs = {
|
||||
.rtc_soc_base_address = 0x00004000,
|
||||
|
@ -72,6 +73,9 @@ const struct ath10k_hw_regs qca6174_regs = {
|
|||
.pcie_intr_fw_mask = 0x00000400,
|
||||
.pcie_intr_ce_mask_all = 0x0007f800,
|
||||
.pcie_intr_clr_address = 0x00000014,
|
||||
.cpu_pll_init_address = 0x00404020,
|
||||
.cpu_speed_address = 0x00404024,
|
||||
.core_clk_div_address = 0x00404028,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_regs qca99x0_regs = {
|
||||
|
@ -187,6 +191,73 @@ const struct ath10k_hw_values qca4019_values = {
|
|||
.ce_desc_meta_data_lsb = 4,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_clk_params qca6174_clk[ATH10K_HW_REFCLK_COUNT] = {
|
||||
{
|
||||
.refclk = 48000000,
|
||||
.div = 0xe,
|
||||
.rnfrac = 0x2aaa8,
|
||||
.settle_time = 2400,
|
||||
.refdiv = 0,
|
||||
.outdiv = 1,
|
||||
},
|
||||
{
|
||||
.refclk = 19200000,
|
||||
.div = 0x24,
|
||||
.rnfrac = 0x2aaa8,
|
||||
.settle_time = 960,
|
||||
.refdiv = 0,
|
||||
.outdiv = 1,
|
||||
},
|
||||
{
|
||||
.refclk = 24000000,
|
||||
.div = 0x1d,
|
||||
.rnfrac = 0x15551,
|
||||
.settle_time = 1200,
|
||||
.refdiv = 0,
|
||||
.outdiv = 1,
|
||||
},
|
||||
{
|
||||
.refclk = 26000000,
|
||||
.div = 0x1b,
|
||||
.rnfrac = 0x4ec4,
|
||||
.settle_time = 1300,
|
||||
.refdiv = 0,
|
||||
.outdiv = 1,
|
||||
},
|
||||
{
|
||||
.refclk = 37400000,
|
||||
.div = 0x12,
|
||||
.rnfrac = 0x34b49,
|
||||
.settle_time = 1870,
|
||||
.refdiv = 0,
|
||||
.outdiv = 1,
|
||||
},
|
||||
{
|
||||
.refclk = 38400000,
|
||||
.div = 0x12,
|
||||
.rnfrac = 0x15551,
|
||||
.settle_time = 1920,
|
||||
.refdiv = 0,
|
||||
.outdiv = 1,
|
||||
},
|
||||
{
|
||||
.refclk = 40000000,
|
||||
.div = 0x12,
|
||||
.rnfrac = 0x26665,
|
||||
.settle_time = 2000,
|
||||
.refdiv = 0,
|
||||
.outdiv = 1,
|
||||
},
|
||||
{
|
||||
.refclk = 52000000,
|
||||
.div = 0x1b,
|
||||
.rnfrac = 0x4ec4,
|
||||
.settle_time = 2600,
|
||||
.refdiv = 0,
|
||||
.outdiv = 1,
|
||||
},
|
||||
};
|
||||
|
||||
void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev)
|
||||
{
|
||||
|
@ -361,6 +432,195 @@ static void ath10k_hw_qca988x_set_coverage_class(struct ath10k *ar,
|
|||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* ath10k_hw_qca6174_enable_pll_clock() - enable the qca6174 hw pll clock
|
||||
* @ar: the ath10k blob
|
||||
*
|
||||
* This function is very hardware specific, the clock initialization
|
||||
* steps is very sensitive and could lead to unknown crash, so they
|
||||
* should be done in sequence.
|
||||
*
|
||||
* *** Be aware if you planned to refactor them. ***
|
||||
*
|
||||
* Return: 0 if successfully enable the pll, otherwise EINVAL
|
||||
*/
|
||||
static int ath10k_hw_qca6174_enable_pll_clock(struct ath10k *ar)
|
||||
{
|
||||
int ret, wait_limit;
|
||||
u32 clk_div_addr, pll_init_addr, speed_addr;
|
||||
u32 addr, reg_val, mem_val;
|
||||
struct ath10k_hw_params *hw;
|
||||
const struct ath10k_hw_clk_params *hw_clk;
|
||||
|
||||
hw = &ar->hw_params;
|
||||
|
||||
if (ar->regs->core_clk_div_address == 0 ||
|
||||
ar->regs->cpu_pll_init_address == 0 ||
|
||||
ar->regs->cpu_speed_address == 0)
|
||||
return -EINVAL;
|
||||
|
||||
clk_div_addr = ar->regs->core_clk_div_address;
|
||||
pll_init_addr = ar->regs->cpu_pll_init_address;
|
||||
speed_addr = ar->regs->cpu_speed_address;
|
||||
|
||||
/* Read efuse register to find out the right hw clock configuration */
|
||||
addr = (RTC_SOC_BASE_ADDRESS | EFUSE_OFFSET);
|
||||
ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
/* sanitize if the hw refclk index is out of the boundary */
|
||||
if (MS(reg_val, EFUSE_XTAL_SEL) > ATH10K_HW_REFCLK_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
hw_clk = &hw->hw_clk[MS(reg_val, EFUSE_XTAL_SEL)];
|
||||
|
||||
/* Set the rnfrac and outdiv params to bb_pll register */
|
||||
addr = (RTC_SOC_BASE_ADDRESS | BB_PLL_CONFIG_OFFSET);
|
||||
ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
reg_val &= ~(BB_PLL_CONFIG_FRAC_MASK | BB_PLL_CONFIG_OUTDIV_MASK);
|
||||
reg_val |= (SM(hw_clk->rnfrac, BB_PLL_CONFIG_FRAC) |
|
||||
SM(hw_clk->outdiv, BB_PLL_CONFIG_OUTDIV));
|
||||
ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
/* Set the correct settle time value to pll_settle register */
|
||||
addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_SETTLE_OFFSET);
|
||||
ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
reg_val &= ~WLAN_PLL_SETTLE_TIME_MASK;
|
||||
reg_val |= SM(hw_clk->settle_time, WLAN_PLL_SETTLE_TIME);
|
||||
ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
/* Set the clock_ctrl div to core_clk_ctrl register */
|
||||
addr = (RTC_SOC_BASE_ADDRESS | SOC_CORE_CLK_CTRL_OFFSET);
|
||||
ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
reg_val &= ~SOC_CORE_CLK_CTRL_DIV_MASK;
|
||||
reg_val |= SM(1, SOC_CORE_CLK_CTRL_DIV);
|
||||
ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
/* Set the clock_div register */
|
||||
mem_val = 1;
|
||||
ret = ath10k_bmi_write_memory(ar, clk_div_addr, &mem_val,
|
||||
sizeof(mem_val));
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
/* Configure the pll_control register */
|
||||
addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
|
||||
ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
reg_val |= (SM(hw_clk->refdiv, WLAN_PLL_CONTROL_REFDIV) |
|
||||
SM(hw_clk->div, WLAN_PLL_CONTROL_DIV) |
|
||||
SM(1, WLAN_PLL_CONTROL_NOPWD));
|
||||
ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
/* busy wait (max 1s) the rtc_sync status register indicate ready */
|
||||
wait_limit = 100000;
|
||||
addr = (RTC_WMAC_BASE_ADDRESS | RTC_SYNC_STATUS_OFFSET);
|
||||
do {
|
||||
ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
if (!MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
|
||||
break;
|
||||
|
||||
wait_limit--;
|
||||
udelay(10);
|
||||
|
||||
} while (wait_limit > 0);
|
||||
|
||||
if (MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
|
||||
return -EINVAL;
|
||||
|
||||
/* Unset the pll_bypass in pll_control register */
|
||||
addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
|
||||
ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
reg_val &= ~WLAN_PLL_CONTROL_BYPASS_MASK;
|
||||
reg_val |= SM(0, WLAN_PLL_CONTROL_BYPASS);
|
||||
ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
/* busy wait (max 1s) the rtc_sync status register indicate ready */
|
||||
wait_limit = 100000;
|
||||
addr = (RTC_WMAC_BASE_ADDRESS | RTC_SYNC_STATUS_OFFSET);
|
||||
do {
|
||||
ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
if (!MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
|
||||
break;
|
||||
|
||||
wait_limit--;
|
||||
udelay(10);
|
||||
|
||||
} while (wait_limit > 0);
|
||||
|
||||
if (MS(reg_val, RTC_SYNC_STATUS_PLL_CHANGING))
|
||||
return -EINVAL;
|
||||
|
||||
/* Enable the hardware cpu clock register */
|
||||
addr = (RTC_SOC_BASE_ADDRESS | SOC_CPU_CLOCK_OFFSET);
|
||||
ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
reg_val &= ~SOC_CPU_CLOCK_STANDARD_MASK;
|
||||
reg_val |= SM(1, SOC_CPU_CLOCK_STANDARD);
|
||||
ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
/* unset the nopwd from pll_control register */
|
||||
addr = (RTC_WMAC_BASE_ADDRESS | WLAN_PLL_CONTROL_OFFSET);
|
||||
ret = ath10k_bmi_read_soc_reg(ar, addr, ®_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
reg_val &= ~WLAN_PLL_CONTROL_NOPWD_MASK;
|
||||
ret = ath10k_bmi_write_soc_reg(ar, addr, reg_val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
/* enable the pll_init register */
|
||||
mem_val = 1;
|
||||
ret = ath10k_bmi_write_memory(ar, pll_init_addr, &mem_val,
|
||||
sizeof(mem_val));
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
/* set the target clock frequency to speed register */
|
||||
ret = ath10k_bmi_write_memory(ar, speed_addr, &hw->target_cpu_freq,
|
||||
sizeof(hw->target_cpu_freq));
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ath10k_hw_ops qca988x_ops = {
|
||||
.set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
|
||||
};
|
||||
|
@ -374,3 +634,8 @@ static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd)
|
|||
const struct ath10k_hw_ops qca99x0_ops = {
|
||||
.rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_ops qca6174_ops = {
|
||||
.set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
|
||||
.enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock,
|
||||
};
|
||||
|
|
|
@ -255,6 +255,9 @@ struct ath10k_hw_regs {
|
|||
u32 pcie_intr_fw_mask;
|
||||
u32 pcie_intr_ce_mask_all;
|
||||
u32 pcie_intr_clr_address;
|
||||
u32 cpu_pll_init_address;
|
||||
u32 cpu_speed_address;
|
||||
u32 core_clk_div_address;
|
||||
};
|
||||
|
||||
extern const struct ath10k_hw_regs qca988x_regs;
|
||||
|
@ -363,6 +366,30 @@ enum ath10k_hw_cc_wraparound_type {
|
|||
ATH10K_HW_CC_WRAP_SHIFTED_EACH = 2,
|
||||
};
|
||||
|
||||
enum ath10k_hw_refclk_speed {
|
||||
ATH10K_HW_REFCLK_UNKNOWN = -1,
|
||||
ATH10K_HW_REFCLK_48_MHZ = 0,
|
||||
ATH10K_HW_REFCLK_19_2_MHZ = 1,
|
||||
ATH10K_HW_REFCLK_24_MHZ = 2,
|
||||
ATH10K_HW_REFCLK_26_MHZ = 3,
|
||||
ATH10K_HW_REFCLK_37_4_MHZ = 4,
|
||||
ATH10K_HW_REFCLK_38_4_MHZ = 5,
|
||||
ATH10K_HW_REFCLK_40_MHZ = 6,
|
||||
ATH10K_HW_REFCLK_52_MHZ = 7,
|
||||
|
||||
/* must be the last one */
|
||||
ATH10K_HW_REFCLK_COUNT,
|
||||
};
|
||||
|
||||
struct ath10k_hw_clk_params {
|
||||
u32 refclk;
|
||||
u32 div;
|
||||
u32 rnfrac;
|
||||
u32 settle_time;
|
||||
u32 refdiv;
|
||||
u32 outdiv;
|
||||
};
|
||||
|
||||
struct ath10k_hw_params {
|
||||
u32 id;
|
||||
u16 dev_id;
|
||||
|
@ -416,6 +443,10 @@ struct ath10k_hw_params {
|
|||
|
||||
/* Number of bytes used for alignment in rx_hdr_status of rx desc. */
|
||||
int decap_align_bytes;
|
||||
|
||||
/* hw specific clock control parameters */
|
||||
const struct ath10k_hw_clk_params *hw_clk;
|
||||
int target_cpu_freq;
|
||||
};
|
||||
|
||||
struct htt_rx_desc;
|
||||
|
@ -424,10 +455,14 @@ struct htt_rx_desc;
|
|||
struct ath10k_hw_ops {
|
||||
int (*rx_desc_get_l3_pad_bytes)(struct htt_rx_desc *rxd);
|
||||
void (*set_coverage_class)(struct ath10k *ar, s16 value);
|
||||
int (*enable_pll_clk)(struct ath10k *ar);
|
||||
};
|
||||
|
||||
extern const struct ath10k_hw_ops qca988x_ops;
|
||||
extern const struct ath10k_hw_ops qca99x0_ops;
|
||||
extern const struct ath10k_hw_ops qca6174_ops;
|
||||
|
||||
extern const struct ath10k_hw_clk_params qca6174_clk[];
|
||||
|
||||
static inline int
|
||||
ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
|
||||
|
@ -847,4 +882,38 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
|
|||
#define WAVE1_PHYCLK_USEC_MASK 0x0000007F
|
||||
#define WAVE1_PHYCLK_USEC_LSB 0
|
||||
|
||||
/* qca6174 PLL offset/mask */
|
||||
#define SOC_CORE_CLK_CTRL_OFFSET 0x00000114
|
||||
#define SOC_CORE_CLK_CTRL_DIV_LSB 0
|
||||
#define SOC_CORE_CLK_CTRL_DIV_MASK 0x00000007
|
||||
|
||||
#define EFUSE_OFFSET 0x0000032c
|
||||
#define EFUSE_XTAL_SEL_LSB 8
|
||||
#define EFUSE_XTAL_SEL_MASK 0x00000700
|
||||
|
||||
#define BB_PLL_CONFIG_OFFSET 0x000002f4
|
||||
#define BB_PLL_CONFIG_FRAC_LSB 0
|
||||
#define BB_PLL_CONFIG_FRAC_MASK 0x0003ffff
|
||||
#define BB_PLL_CONFIG_OUTDIV_LSB 18
|
||||
#define BB_PLL_CONFIG_OUTDIV_MASK 0x001c0000
|
||||
|
||||
#define WLAN_PLL_SETTLE_OFFSET 0x0018
|
||||
#define WLAN_PLL_SETTLE_TIME_LSB 0
|
||||
#define WLAN_PLL_SETTLE_TIME_MASK 0x000007ff
|
||||
|
||||
#define WLAN_PLL_CONTROL_OFFSET 0x0014
|
||||
#define WLAN_PLL_CONTROL_DIV_LSB 0
|
||||
#define WLAN_PLL_CONTROL_DIV_MASK 0x000003ff
|
||||
#define WLAN_PLL_CONTROL_REFDIV_LSB 10
|
||||
#define WLAN_PLL_CONTROL_REFDIV_MASK 0x00003c00
|
||||
#define WLAN_PLL_CONTROL_BYPASS_LSB 16
|
||||
#define WLAN_PLL_CONTROL_BYPASS_MASK 0x00010000
|
||||
#define WLAN_PLL_CONTROL_NOPWD_LSB 18
|
||||
#define WLAN_PLL_CONTROL_NOPWD_MASK 0x00040000
|
||||
|
||||
#define RTC_SYNC_STATUS_OFFSET 0x0244
|
||||
#define RTC_SYNC_STATUS_PLL_CHANGING_LSB 5
|
||||
#define RTC_SYNC_STATUS_PLL_CHANGING_MASK 0x00000020
|
||||
/* qca6174 PLL offset/mask end */
|
||||
|
||||
#endif /* _HW_H_ */
|
||||
|
|
|
@ -3126,6 +3126,21 @@ static void ath10k_regd_update(struct ath10k *ar)
|
|||
ath10k_warn(ar, "failed to set pdev regdomain: %d\n", ret);
|
||||
}
|
||||
|
||||
static void ath10k_mac_update_channel_list(struct ath10k *ar,
|
||||
struct ieee80211_supported_band *band)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ar->low_5ghz_chan && ar->high_5ghz_chan) {
|
||||
for (i = 0; i < band->n_channels; i++) {
|
||||
if (band->channels[i].center_freq < ar->low_5ghz_chan ||
|
||||
band->channels[i].center_freq > ar->high_5ghz_chan)
|
||||
band->channels[i].flags |=
|
||||
IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ath10k_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
|
@ -3149,6 +3164,10 @@ static void ath10k_reg_notifier(struct wiphy *wiphy,
|
|||
if (ar->state == ATH10K_STATE_ON)
|
||||
ath10k_regd_update(ar);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY)
|
||||
ath10k_mac_update_channel_list(ar,
|
||||
ar->hw->wiphy->bands[NL80211_BAND_5GHZ]);
|
||||
}
|
||||
|
||||
/***************/
|
||||
|
@ -7129,7 +7148,7 @@ ath10k_mac_update_rx_channel(struct ath10k *ar,
|
|||
lockdep_assert_held(&ar->data_lock);
|
||||
|
||||
WARN_ON(ctx && vifs);
|
||||
WARN_ON(vifs && n_vifs != 1);
|
||||
WARN_ON(vifs && !n_vifs);
|
||||
|
||||
/* FIXME: Sort of an optimization and a workaround. Peers and vifs are
|
||||
* on a linked list now. Doing a lookup peer -> vif -> chanctx for each
|
||||
|
|
|
@ -970,12 +970,6 @@ 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;
|
||||
|
|
|
@ -3643,6 +3643,11 @@ static void ath10k_dfs_radar_report(struct ath10k *ar,
|
|||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ch = ar->rx_channel;
|
||||
|
||||
/* fetch target operating channel during channel change */
|
||||
if (!ch)
|
||||
ch = ar->tgt_oper_chan;
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
if (!ch) {
|
||||
|
@ -4593,6 +4598,8 @@ ath10k_wmi_main_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
|
|||
arg->phy_capab = ev->phy_capability;
|
||||
arg->num_rf_chains = ev->num_rf_chains;
|
||||
arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
|
||||
arg->low_5ghz_chan = ev->hal_reg_capabilities.low_5ghz_chan;
|
||||
arg->high_5ghz_chan = ev->hal_reg_capabilities.high_5ghz_chan;
|
||||
arg->num_mem_reqs = ev->num_mem_reqs;
|
||||
arg->service_map = ev->wmi_service_bitmap;
|
||||
arg->service_map_len = sizeof(ev->wmi_service_bitmap);
|
||||
|
@ -4629,6 +4636,8 @@ ath10k_wmi_10x_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
|
|||
arg->phy_capab = ev->phy_capability;
|
||||
arg->num_rf_chains = ev->num_rf_chains;
|
||||
arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
|
||||
arg->low_5ghz_chan = ev->hal_reg_capabilities.low_5ghz_chan;
|
||||
arg->high_5ghz_chan = ev->hal_reg_capabilities.high_5ghz_chan;
|
||||
arg->num_mem_reqs = ev->num_mem_reqs;
|
||||
arg->service_map = ev->wmi_service_bitmap;
|
||||
arg->service_map_len = sizeof(ev->wmi_service_bitmap);
|
||||
|
@ -4682,6 +4691,8 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
|
|||
ar->phy_capability = __le32_to_cpu(arg.phy_capab);
|
||||
ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
|
||||
ar->hw_eeprom_rd = __le32_to_cpu(arg.eeprom_rd);
|
||||
ar->low_5ghz_chan = __le32_to_cpu(arg.low_5ghz_chan);
|
||||
ar->high_5ghz_chan = __le32_to_cpu(arg.high_5ghz_chan);
|
||||
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
|
||||
arg.service_map, arg.service_map_len);
|
||||
|
|
|
@ -3182,7 +3182,7 @@ struct wmi_10_4_phyerr_event {
|
|||
|
||||
struct phyerr_radar_report {
|
||||
__le32 reg0; /* RADAR_REPORT_REG0_* */
|
||||
__le32 reg1; /* REDAR_REPORT_REG1_* */
|
||||
__le32 reg1; /* RADAR_REPORT_REG1_* */
|
||||
} __packed;
|
||||
|
||||
#define RADAR_REPORT_REG0_PULSE_IS_CHIRP_MASK 0x80000000
|
||||
|
@ -6335,6 +6335,8 @@ struct wmi_svc_rdy_ev_arg {
|
|||
__le32 num_rf_chains;
|
||||
__le32 eeprom_rd;
|
||||
__le32 num_mem_reqs;
|
||||
__le32 low_5ghz_chan;
|
||||
__le32 high_5ghz_chan;
|
||||
const __le32 *service_map;
|
||||
size_t service_map_len;
|
||||
const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
|
||||
|
|
|
@ -102,10 +102,8 @@ static struct ieee80211_channel ath6kl_2ghz_channels[] = {
|
|||
};
|
||||
|
||||
static struct ieee80211_channel ath6kl_5ghz_a_channels[] = {
|
||||
CHAN5G(34, 0), CHAN5G(36, 0),
|
||||
CHAN5G(38, 0), CHAN5G(40, 0),
|
||||
CHAN5G(42, 0), CHAN5G(44, 0),
|
||||
CHAN5G(46, 0), CHAN5G(48, 0),
|
||||
CHAN5G(36, 0), CHAN5G(40, 0),
|
||||
CHAN5G(44, 0), CHAN5G(48, 0),
|
||||
CHAN5G(52, 0), CHAN5G(56, 0),
|
||||
CHAN5G(60, 0), CHAN5G(64, 0),
|
||||
CHAN5G(100, 0), CHAN5G(104, 0),
|
||||
|
|
|
@ -742,6 +742,9 @@ void ath9k_cmn_spectral_scan_trigger(struct ath_common *common,
|
|||
return;
|
||||
}
|
||||
|
||||
if (!spec_priv->spec_config.enabled)
|
||||
return;
|
||||
|
||||
ath_ps_ops(common)->wakeup(common);
|
||||
rxfilter = ath9k_hw_getrxfilter(ah);
|
||||
ath9k_hw_setrxfilter(ah, rxfilter |
|
||||
|
|
|
@ -37,6 +37,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
|
|||
{ USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */
|
||||
{ USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */
|
||||
{ USB_DEVICE(0x0471, 0x209e) }, /* Philips (or NXP) PTA01 */
|
||||
{ USB_DEVICE(0x1eda, 0x2315) }, /* AirTies */
|
||||
|
||||
{ USB_DEVICE(0x0cf3, 0x7015),
|
||||
.driver_info = AR9287_USB }, /* Atheros */
|
||||
|
|
|
@ -337,10 +337,10 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
|
|||
wcn36xx_smd_stop(wcn);
|
||||
out_free_smd_buf:
|
||||
kfree(wcn->hal_buf);
|
||||
out_free_dxe_pool:
|
||||
wcn36xx_dxe_free_mem_pools(wcn);
|
||||
out_free_dxe_ctl:
|
||||
wcn36xx_dxe_free_ctl_blks(wcn);
|
||||
out_free_dxe_pool:
|
||||
wcn36xx_dxe_free_mem_pools(wcn);
|
||||
out_smd_close:
|
||||
wcn36xx_smd_close(wcn);
|
||||
out_err:
|
||||
|
|
|
@ -390,22 +390,23 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
|||
}
|
||||
mutex_unlock(&wil->p2p_wdev_mutex);
|
||||
|
||||
/* social scan on P2P_DEVICE is handled as p2p search */
|
||||
if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE &&
|
||||
wil_p2p_is_social_scan(request)) {
|
||||
if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
|
||||
if (!wil->p2p.p2p_dev_started) {
|
||||
wil_err(wil, "P2P search requested on stopped P2P device\n");
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
wil->scan_request = request;
|
||||
wil->radio_wdev = wdev;
|
||||
rc = wil_p2p_search(wil, request);
|
||||
if (rc) {
|
||||
wil->radio_wdev = wil_to_wdev(wil);
|
||||
wil->scan_request = NULL;
|
||||
/* social scan on P2P_DEVICE is handled as p2p search */
|
||||
if (wil_p2p_is_social_scan(request)) {
|
||||
wil->scan_request = request;
|
||||
wil->radio_wdev = wdev;
|
||||
rc = wil_p2p_search(wil, request);
|
||||
if (rc) {
|
||||
wil->radio_wdev = wil_to_wdev(wil);
|
||||
wil->scan_request = NULL;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
(void)wil_p2p_stop_discovery(wil);
|
||||
|
@ -415,9 +416,9 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
|||
|
||||
for (i = 0; i < request->n_ssids; i++) {
|
||||
wil_dbg_misc(wil, "SSID[%d]", i);
|
||||
print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
|
||||
request->ssids[i].ssid,
|
||||
request->ssids[i].ssid_len);
|
||||
wil_hex_dump_misc("SSID ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
request->ssids[i].ssid,
|
||||
request->ssids[i].ssid_len, true);
|
||||
}
|
||||
|
||||
if (request->n_ssids)
|
||||
|
@ -454,8 +455,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
|
|||
}
|
||||
|
||||
if (request->ie_len)
|
||||
print_hex_dump_bytes("Scan IE ", DUMP_PREFIX_OFFSET,
|
||||
request->ie, request->ie_len);
|
||||
wil_hex_dump_misc("Scan IE ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
request->ie, request->ie_len, true);
|
||||
else
|
||||
wil_dbg_misc(wil, "Scan has no IE's\n");
|
||||
|
||||
|
@ -679,6 +680,8 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
|
|||
rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn));
|
||||
if (rc == 0) {
|
||||
netif_carrier_on(ndev);
|
||||
wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
|
||||
wil->bss = bss;
|
||||
/* Connect can take lots of time */
|
||||
mod_timer(&wil->connect_timer,
|
||||
jiffies + msecs_to_jiffies(2000));
|
||||
|
@ -707,6 +710,7 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy,
|
|||
return 0;
|
||||
}
|
||||
|
||||
wil->locally_generated_disc = true;
|
||||
rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
|
||||
WMI_DISCONNECT_EVENTID, NULL, 0,
|
||||
WIL6210_DISCONNECT_TO_MS);
|
||||
|
@ -760,7 +764,8 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
*/
|
||||
|
||||
wil_dbg_misc(wil, "mgmt_tx\n");
|
||||
print_hex_dump_bytes("mgmt tx frame ", DUMP_PREFIX_OFFSET, buf, len);
|
||||
wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf,
|
||||
len, true);
|
||||
|
||||
cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
|
@ -1093,18 +1098,18 @@ static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len,
|
|||
|
||||
static void wil_print_bcon_data(struct cfg80211_beacon_data *b)
|
||||
{
|
||||
print_hex_dump_bytes("head ", DUMP_PREFIX_OFFSET,
|
||||
b->head, b->head_len);
|
||||
print_hex_dump_bytes("tail ", DUMP_PREFIX_OFFSET,
|
||||
b->tail, b->tail_len);
|
||||
print_hex_dump_bytes("BCON IE ", DUMP_PREFIX_OFFSET,
|
||||
b->beacon_ies, b->beacon_ies_len);
|
||||
print_hex_dump_bytes("PROBE ", DUMP_PREFIX_OFFSET,
|
||||
b->probe_resp, b->probe_resp_len);
|
||||
print_hex_dump_bytes("PROBE IE ", DUMP_PREFIX_OFFSET,
|
||||
b->proberesp_ies, b->proberesp_ies_len);
|
||||
print_hex_dump_bytes("ASSOC IE ", DUMP_PREFIX_OFFSET,
|
||||
b->assocresp_ies, b->assocresp_ies_len);
|
||||
wil_hex_dump_misc("head ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
b->head, b->head_len, true);
|
||||
wil_hex_dump_misc("tail ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
b->tail, b->tail_len, true);
|
||||
wil_hex_dump_misc("BCON IE ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
b->beacon_ies, b->beacon_ies_len, true);
|
||||
wil_hex_dump_misc("PROBE ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
b->probe_resp, b->probe_resp_len, true);
|
||||
wil_hex_dump_misc("PROBE IE ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
b->proberesp_ies, b->proberesp_ies_len, true);
|
||||
wil_hex_dump_misc("ASSOC IE ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
b->assocresp_ies, b->assocresp_ies_len, true);
|
||||
}
|
||||
|
||||
/* internal functions for device reset and starting AP */
|
||||
|
@ -1198,6 +1203,7 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
|
|||
wil->pbss = pbss;
|
||||
|
||||
netif_carrier_on(ndev);
|
||||
wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
|
||||
|
||||
rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid, is_go);
|
||||
if (rc)
|
||||
|
@ -1213,6 +1219,7 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
|
|||
wmi_pcp_stop(wil);
|
||||
err_pcp_start:
|
||||
netif_carrier_off(ndev);
|
||||
wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
|
||||
out:
|
||||
mutex_unlock(&wil->mutex);
|
||||
return rc;
|
||||
|
@ -1298,8 +1305,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
|
|||
wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval,
|
||||
info->dtim_period);
|
||||
wil_dbg_misc(wil, "PBSS %d\n", info->pbss);
|
||||
print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
|
||||
info->ssid, info->ssid_len);
|
||||
wil_hex_dump_misc("SSID ", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
info->ssid, info->ssid_len, true);
|
||||
wil_print_bcon_data(bcon);
|
||||
wil_print_crypto(wil, crypto);
|
||||
|
||||
|
@ -1319,6 +1326,7 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
|
|||
wil_dbg_misc(wil, "stop_ap\n");
|
||||
|
||||
netif_carrier_off(ndev);
|
||||
wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
|
||||
wil_set_recovery_state(wil, fw_recovery_idle);
|
||||
|
||||
mutex_lock(&wil->mutex);
|
||||
|
|
|
@ -30,8 +30,8 @@ bool debug_fw; /* = false; */
|
|||
module_param(debug_fw, bool, 0444);
|
||||
MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug");
|
||||
|
||||
static bool oob_mode;
|
||||
module_param(oob_mode, bool, 0444);
|
||||
static u8 oob_mode;
|
||||
module_param(oob_mode, byte, 0444);
|
||||
MODULE_PARM_DESC(oob_mode,
|
||||
" enable out of the box (OOB) mode in FW, for diagnostics and certification");
|
||||
|
||||
|
@ -274,15 +274,20 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
|
|||
wil_bcast_fini(wil);
|
||||
wil_update_net_queues_bh(wil, NULL, true);
|
||||
netif_carrier_off(ndev);
|
||||
wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
|
||||
|
||||
if (test_bit(wil_status_fwconnected, wil->status)) {
|
||||
clear_bit(wil_status_fwconnected, wil->status);
|
||||
cfg80211_disconnected(ndev, reason_code,
|
||||
NULL, 0, false, GFP_KERNEL);
|
||||
NULL, 0,
|
||||
wil->locally_generated_disc,
|
||||
GFP_KERNEL);
|
||||
wil->locally_generated_disc = false;
|
||||
} else if (test_bit(wil_status_fwconnecting, wil->status)) {
|
||||
cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
GFP_KERNEL);
|
||||
wil->bss = NULL;
|
||||
}
|
||||
clear_bit(wil_status_fwconnecting, wil->status);
|
||||
break;
|
||||
|
@ -304,10 +309,34 @@ static void wil_disconnect_worker(struct work_struct *work)
|
|||
{
|
||||
struct wil6210_priv *wil = container_of(work,
|
||||
struct wil6210_priv, disconnect_worker);
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
int rc;
|
||||
struct {
|
||||
struct wmi_cmd_hdr wmi;
|
||||
struct wmi_disconnect_event evt;
|
||||
} __packed reply;
|
||||
|
||||
mutex_lock(&wil->mutex);
|
||||
_wil6210_disconnect(wil, NULL, WLAN_REASON_UNSPECIFIED, false);
|
||||
mutex_unlock(&wil->mutex);
|
||||
if (test_bit(wil_status_fwconnected, wil->status))
|
||||
/* connect succeeded after all */
|
||||
return;
|
||||
|
||||
if (!test_bit(wil_status_fwconnecting, wil->status))
|
||||
/* already disconnected */
|
||||
return;
|
||||
|
||||
rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
|
||||
WMI_DISCONNECT_EVENTID, &reply, sizeof(reply),
|
||||
WIL6210_DISCONNECT_TO_MS);
|
||||
if (rc) {
|
||||
wil_err(wil, "disconnect error %d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
wil_update_net_queues_bh(wil, NULL, true);
|
||||
netif_carrier_off(ndev);
|
||||
cfg80211_connect_result(ndev, NULL, NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL);
|
||||
clear_bit(wil_status_fwconnecting, wil->status);
|
||||
}
|
||||
|
||||
static void wil_connect_timer_fn(ulong x)
|
||||
|
@ -555,6 +584,12 @@ int wil_priv_init(struct wil6210_priv *wil)
|
|||
return -EAGAIN;
|
||||
}
|
||||
|
||||
void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps)
|
||||
{
|
||||
if (wil->platform_ops.bus_request)
|
||||
wil->platform_ops.bus_request(wil->platform_handle, kbps);
|
||||
}
|
||||
|
||||
/**
|
||||
* wil6210_disconnect - disconnect one connection
|
||||
* @wil: driver context
|
||||
|
@ -607,13 +642,25 @@ static inline void wil_release_cpu(struct wil6210_priv *wil)
|
|||
wil_w(wil, RGF_USER_USER_CPU_0, 1);
|
||||
}
|
||||
|
||||
static void wil_set_oob_mode(struct wil6210_priv *wil, bool enable)
|
||||
static void wil_set_oob_mode(struct wil6210_priv *wil, u8 mode)
|
||||
{
|
||||
wil_info(wil, "enable=%d\n", enable);
|
||||
if (enable)
|
||||
wil_info(wil, "oob_mode to %d\n", mode);
|
||||
switch (mode) {
|
||||
case 0:
|
||||
wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE |
|
||||
BIT_USER_OOB_R2_MODE);
|
||||
break;
|
||||
case 1:
|
||||
wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_R2_MODE);
|
||||
wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE);
|
||||
else
|
||||
break;
|
||||
case 2:
|
||||
wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE);
|
||||
wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_R2_MODE);
|
||||
break;
|
||||
default:
|
||||
wil_err(wil, "invalid oob_mode: %d\n", mode);
|
||||
}
|
||||
}
|
||||
|
||||
static int wil_target_reset(struct wil6210_priv *wil)
|
||||
|
@ -1066,9 +1113,7 @@ int __wil_up(struct wil6210_priv *wil)
|
|||
napi_enable(&wil->napi_tx);
|
||||
set_bit(wil_status_napi_en, wil->status);
|
||||
|
||||
if (wil->platform_ops.bus_request)
|
||||
wil->platform_ops.bus_request(wil->platform_handle,
|
||||
WIL_MAX_BUS_REQUEST_KBPS);
|
||||
wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1092,8 +1137,7 @@ int __wil_down(struct wil6210_priv *wil)
|
|||
|
||||
set_bit(wil_status_resetting, wil->status);
|
||||
|
||||
if (wil->platform_ops.bus_request)
|
||||
wil->platform_ops.bus_request(wil->platform_handle, 0);
|
||||
wil6210_bus_request(wil, 0);
|
||||
|
||||
wil_disable_irq(wil);
|
||||
if (test_and_clear_bit(wil_status_napi_en, wil->status)) {
|
||||
|
@ -1154,6 +1198,7 @@ void wil_halp_vote(struct wil6210_priv *wil)
|
|||
wil->halp.ref_cnt);
|
||||
|
||||
if (++wil->halp.ref_cnt == 1) {
|
||||
reinit_completion(&wil->halp.comp);
|
||||
wil6210_set_halp(wil);
|
||||
rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies);
|
||||
if (!rc) {
|
||||
|
|
|
@ -211,6 +211,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
dev_err(dev, "wil_if_alloc failed: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
wil->pdev = pdev;
|
||||
pci_set_drvdata(pdev, wil);
|
||||
/* rollback to if_free */
|
||||
|
@ -224,6 +225,21 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
}
|
||||
/* rollback to err_plat */
|
||||
|
||||
/* device supports 48bit addresses */
|
||||
rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
|
||||
if (rc) {
|
||||
dev_err(dev, "dma_set_mask_and_coherent(48) failed: %d\n", rc);
|
||||
rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
||||
if (rc) {
|
||||
dev_err(dev,
|
||||
"dma_set_mask_and_coherent(32) failed: %d\n",
|
||||
rc);
|
||||
goto err_plat;
|
||||
}
|
||||
} else {
|
||||
wil->use_extended_dma_addr = 1;
|
||||
}
|
||||
|
||||
rc = pci_enable_device(pdev);
|
||||
if (rc) {
|
||||
wil_err(wil,
|
||||
|
|
|
@ -107,13 +107,28 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
|
|||
|
||||
/* Allocate pring buffer and descriptors.
|
||||
* vring->va should be aligned on its size rounded up to power of 2
|
||||
* This is granted by the dma_alloc_coherent
|
||||
* This is granted by the dma_alloc_coherent.
|
||||
*
|
||||
* HW has limitation that all vrings addresses must share the same
|
||||
* upper 16 msb bits part of 48 bits address. To workaround that,
|
||||
* if we are using 48 bit addresses switch to 32 bit allocation
|
||||
* before allocating vring memory.
|
||||
*
|
||||
* There's no check for the return value of dma_set_mask_and_coherent,
|
||||
* since we assume if we were able to set the mask during
|
||||
* initialization in this system it will not fail if we set it again
|
||||
*/
|
||||
if (wil->use_extended_dma_addr)
|
||||
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
||||
|
||||
pmc->pring_va = dma_alloc_coherent(dev,
|
||||
sizeof(struct vring_tx_desc) * num_descriptors,
|
||||
&pmc->pring_pa,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (wil->use_extended_dma_addr)
|
||||
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
|
||||
|
||||
wil_dbg_misc(wil,
|
||||
"pmc_alloc: allocated pring %p => %pad. %zd x %d = total %zd bytes\n",
|
||||
pmc->pring_va, &pmc->pring_pa,
|
||||
|
|
|
@ -123,15 +123,32 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
|
|||
vring->va = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* vring->va should be aligned on its size rounded up to power of 2
|
||||
* This is granted by the dma_alloc_coherent
|
||||
* This is granted by the dma_alloc_coherent.
|
||||
*
|
||||
* HW has limitation that all vrings addresses must share the same
|
||||
* upper 16 msb bits part of 48 bits address. To workaround that,
|
||||
* if we are using 48 bit addresses switch to 32 bit allocation
|
||||
* before allocating vring memory.
|
||||
*
|
||||
* There's no check for the return value of dma_set_mask_and_coherent,
|
||||
* since we assume if we were able to set the mask during
|
||||
* initialization in this system it will not fail if we set it again
|
||||
*/
|
||||
if (wil->use_extended_dma_addr)
|
||||
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
||||
|
||||
vring->va = dma_alloc_coherent(dev, sz, &vring->pa, GFP_KERNEL);
|
||||
if (!vring->va) {
|
||||
kfree(vring->ctx);
|
||||
vring->ctx = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (wil->use_extended_dma_addr)
|
||||
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
|
||||
|
||||
/* initially, all descriptors are SW owned
|
||||
* For Tx and Rx, ownership bit is at the same location, thus
|
||||
* we can use any
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2012-2017 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
|
||||
|
@ -40,6 +40,7 @@ extern bool disable_ap_sme;
|
|||
#define WIL_FW_NAME_SPARROW_PLUS "wil6210_sparrow_plus.fw" /* code Sparrow D0 */
|
||||
#define WIL_BOARD_FILE_NAME "wil6210.brd" /* board & radio parameters */
|
||||
|
||||
#define WIL_DEFAULT_BUS_REQUEST_KBPS 128000 /* ~1Gbps */
|
||||
#define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */
|
||||
|
||||
/**
|
||||
|
@ -139,6 +140,7 @@ struct RGF_ICR {
|
|||
#define RGF_USER_USAGE_1 (0x880004)
|
||||
#define RGF_USER_USAGE_6 (0x880018)
|
||||
#define BIT_USER_OOB_MODE BIT(31)
|
||||
#define BIT_USER_OOB_R2_MODE BIT(30)
|
||||
#define RGF_USER_HW_MACHINE_STATE (0x8801dc)
|
||||
#define HW_MACHINE_BOOT_DONE (0x3fffffd)
|
||||
#define RGF_USER_USER_CPU_0 (0x8801e0)
|
||||
|
@ -612,6 +614,8 @@ struct wil6210_priv {
|
|||
u16 channel; /* relevant in AP mode */
|
||||
int sinfo_gen;
|
||||
u32 ap_isolate; /* no intra-BSS communication */
|
||||
struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */
|
||||
int locally_generated_disc; /* relevant in STA mode */
|
||||
/* interrupt moderation */
|
||||
u32 tx_max_burst_duration;
|
||||
u32 tx_interframe_timeout;
|
||||
|
@ -657,6 +661,7 @@ struct wil6210_priv {
|
|||
u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */
|
||||
struct wil_sta_info sta[WIL6210_MAX_CID];
|
||||
int bcast_vring;
|
||||
bool use_extended_dma_addr; /* indicates whether we are using 48 bits */
|
||||
/* scan */
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
|
||||
|
@ -764,6 +769,12 @@ static inline void wil_c(struct wil6210_priv *wil, u32 reg, u32 val)
|
|||
print_hex_dump_debug("DBG[ WMI]" prefix_str,\
|
||||
prefix_type, rowsize, \
|
||||
groupsize, buf, len, ascii)
|
||||
|
||||
#define wil_hex_dump_misc(prefix_str, prefix_type, rowsize, \
|
||||
groupsize, buf, len, ascii) \
|
||||
print_hex_dump_debug("DBG[MISC]" prefix_str,\
|
||||
prefix_type, rowsize, \
|
||||
groupsize, buf, len, ascii)
|
||||
#else /* defined(CONFIG_DYNAMIC_DEBUG) */
|
||||
static inline
|
||||
void wil_hex_dump_txrx(const char *prefix_str, int prefix_type, int rowsize,
|
||||
|
@ -776,6 +787,12 @@ void wil_hex_dump_wmi(const char *prefix_str, int prefix_type, int rowsize,
|
|||
int groupsize, const void *buf, size_t len, bool ascii)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void wil_hex_dump_misc(const char *prefix_str, int prefix_type, int rowsize,
|
||||
int groupsize, const void *buf, size_t len, bool ascii)
|
||||
{
|
||||
}
|
||||
#endif /* defined(CONFIG_DYNAMIC_DEBUG) */
|
||||
|
||||
void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src,
|
||||
|
@ -899,7 +916,7 @@ int wmi_pcp_stop(struct wil6210_priv *wil);
|
|||
int wmi_led_cfg(struct wil6210_priv *wil, bool enable);
|
||||
int wmi_abort_scan(struct wil6210_priv *wil);
|
||||
void wil_abort_scan(struct wil6210_priv *wil, bool sync);
|
||||
|
||||
void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps);
|
||||
void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
|
||||
u16 reason_code, bool from_event);
|
||||
void wil_probe_client_flush(struct wil6210_priv *wil);
|
||||
|
|
|
@ -565,6 +565,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
|
|||
(wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
|
||||
if (rc) {
|
||||
netif_carrier_off(ndev);
|
||||
wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
|
||||
wil_err(wil, "cfg80211_connect_result with failure\n");
|
||||
cfg80211_connect_result(ndev, evt->bssid, NULL, 0,
|
||||
NULL, 0,
|
||||
|
@ -572,12 +573,16 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
|
|||
GFP_KERNEL);
|
||||
goto out;
|
||||
} else {
|
||||
cfg80211_connect_result(ndev, evt->bssid,
|
||||
assoc_req_ie, assoc_req_ielen,
|
||||
assoc_resp_ie, assoc_resp_ielen,
|
||||
WLAN_STATUS_SUCCESS,
|
||||
GFP_KERNEL);
|
||||
struct wiphy *wiphy = wil_to_wiphy(wil);
|
||||
|
||||
cfg80211_ref_bss(wiphy, wil->bss);
|
||||
cfg80211_connect_bss(ndev, evt->bssid, wil->bss,
|
||||
assoc_req_ie, assoc_req_ielen,
|
||||
assoc_resp_ie, assoc_resp_ielen,
|
||||
WLAN_STATUS_SUCCESS, GFP_KERNEL,
|
||||
NL80211_TIMEOUT_UNSPECIFIED);
|
||||
}
|
||||
wil->bss = NULL;
|
||||
} else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
|
||||
(wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
|
||||
if (rc) {
|
||||
|
@ -1492,6 +1497,7 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac,
|
|||
|
||||
wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason);
|
||||
|
||||
wil->locally_generated_disc = true;
|
||||
if (del_sta) {
|
||||
ether_addr_copy(del_sta_cmd.dst_mac, mac);
|
||||
rc = wmi_call(wil, WMI_DEL_STA_CMDID, &del_sta_cmd,
|
||||
|
@ -1733,14 +1739,19 @@ int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid)
|
|||
|
||||
void wmi_event_flush(struct wil6210_priv *wil)
|
||||
{
|
||||
ulong flags;
|
||||
struct pending_wmi_event *evt, *t;
|
||||
|
||||
wil_dbg_wmi(wil, "event_flush\n");
|
||||
|
||||
spin_lock_irqsave(&wil->wmi_ev_lock, flags);
|
||||
|
||||
list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
|
||||
list_del(&evt->list);
|
||||
kfree(evt);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
|
||||
}
|
||||
|
||||
static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
|
||||
|
|
Loading…
Reference in New Issue