Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git

ath.git patches for v5.10. Major changes:

ath10k

* support SDIO firmware codedumps

* support station specific TID configurations

ath11k

* add support for IPQ6018
This commit is contained in:
Kalle Valo 2020-09-11 18:03:00 +03:00
commit 5941d003f0
71 changed files with 2939 additions and 1143 deletions

View file

@ -65,7 +65,8 @@ Optional properties:
the length can vary between hw versions. the length can vary between hw versions.
- <supply-name>-supply: handle to the regulator device tree node - <supply-name>-supply: handle to the regulator device tree node
optional "supply-name" are "vdd-0.8-cx-mx", optional "supply-name" are "vdd-0.8-cx-mx",
"vdd-1.8-xo", "vdd-1.3-rfa" and "vdd-3.3-ch0". "vdd-1.8-xo", "vdd-1.3-rfa", "vdd-3.3-ch0",
and "vdd-3.3-ch1".
- memory-region: - memory-region:
Usage: optional Usage: optional
Value type: <phandle> Value type: <phandle>
@ -204,6 +205,7 @@ wifi@18000000 {
vdd-1.8-xo-supply = <&vreg_l7a_1p8>; vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
vdd-1.3-rfa-supply = <&vreg_l17a_1p3>; vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
vdd-3.3-ch0-supply = <&vreg_l25a_3p3>; vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
vdd-3.3-ch1-supply = <&vreg_l26a_3p3>;
memory-region = <&wifi_msa_mem>; memory-region = <&wifi_msa_mem>;
iommus = <&apps_smmu 0x0040 0x1>; iommus = <&apps_smmu 0x0040 0x1>;
qcom,msa-fixed-perm; qcom,msa-fixed-perm;

View file

@ -17,7 +17,9 @@ description: |
properties: properties:
compatible: compatible:
const: qcom,ipq8074-wifi enum:
- qcom,ipq8074-wifi
- qcom,ipq6018-wifi
reg: reg:
maxItems: 1 maxItems: 1

View file

@ -16,6 +16,7 @@ void ath10k_bmi_start(struct ath10k *ar)
ar->bmi.done_sent = false; ar->bmi.done_sent = false;
} }
EXPORT_SYMBOL(ath10k_bmi_start);
int ath10k_bmi_done(struct ath10k *ar) int ath10k_bmi_done(struct ath10k *ar)
{ {
@ -189,6 +190,7 @@ int ath10k_bmi_read_memory(struct ath10k *ar,
return 0; return 0;
} }
EXPORT_SYMBOL(ath10k_bmi_read_memory);
int ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val) int ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val)
{ {

View file

@ -481,15 +481,6 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
ath10k_ce_write32(ar, ce_ctrl_addr + wm_regs->addr, mask); ath10k_ce_write32(ar, ce_ctrl_addr + wm_regs->addr, mask);
} }
static inline bool ath10k_ce_engine_int_status_check(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int mask)
{
struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
return ath10k_ce_read32(ar, ce_ctrl_addr + wm_regs->addr) & mask;
}
/* /*
* Guts of ath10k_ce_send. * Guts of ath10k_ce_send.
* The caller takes responsibility for any needed locking. * The caller takes responsibility for any needed locking.
@ -1308,32 +1299,24 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs; struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
u32 ctrl_addr = ce_state->ctrl_addr; u32 ctrl_addr = ce_state->ctrl_addr;
spin_lock_bh(&ce->ce_lock); /*
* Clear before handling
if (ath10k_ce_engine_int_status_check(ar, ctrl_addr, *
wm_regs->cc_mask)) { * Misc CE interrupts are not being handled, but still need
/* Clear before handling */ * to be cleared.
*
* NOTE: When the last copy engine interrupt is cleared the
* hardware will go to sleep. Once this happens any access to
* the CE registers can cause a hardware fault.
*/
ath10k_ce_engine_int_status_clear(ar, ctrl_addr, ath10k_ce_engine_int_status_clear(ar, ctrl_addr,
wm_regs->cc_mask); wm_regs->cc_mask | wm_regs->wm_mask);
spin_unlock_bh(&ce->ce_lock);
if (ce_state->recv_cb) if (ce_state->recv_cb)
ce_state->recv_cb(ce_state); ce_state->recv_cb(ce_state);
if (ce_state->send_cb) if (ce_state->send_cb)
ce_state->send_cb(ce_state); ce_state->send_cb(ce_state);
spin_lock_bh(&ce->ce_lock);
}
/*
* Misc CE interrupts are not being handled, but still need
* to be cleared.
*/
ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->wm_mask);
spin_unlock_bh(&ce->ce_lock);
} }
EXPORT_SYMBOL(ath10k_ce_per_engine_service); EXPORT_SYMBOL(ath10k_ce_per_engine_service);
@ -1384,17 +1367,15 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state)
ath10k_ce_watermark_intr_disable(ar, ctrl_addr); ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
} }
int ath10k_ce_disable_interrupts(struct ath10k *ar) void ath10k_ce_disable_interrupt(struct ath10k *ar, int ce_id)
{ {
struct ath10k_ce *ce = ath10k_ce_priv(ar); struct ath10k_ce *ce = ath10k_ce_priv(ar);
struct ath10k_ce_pipe *ce_state; struct ath10k_ce_pipe *ce_state;
u32 ctrl_addr; u32 ctrl_addr;
int ce_id;
for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
ce_state = &ce->ce_states[ce_id]; ce_state = &ce->ce_states[ce_id];
if (ce_state->attr_flags & CE_ATTR_POLL) if (ce_state->attr_flags & CE_ATTR_POLL)
continue; return;
ctrl_addr = ath10k_ce_base_address(ar, ce_id); ctrl_addr = ath10k_ce_base_address(ar, ce_id);
@ -1402,27 +1383,39 @@ int ath10k_ce_disable_interrupts(struct ath10k *ar)
ath10k_ce_error_intr_disable(ar, ctrl_addr); ath10k_ce_error_intr_disable(ar, ctrl_addr);
ath10k_ce_watermark_intr_disable(ar, ctrl_addr); ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
} }
EXPORT_SYMBOL(ath10k_ce_disable_interrupt);
return 0; void ath10k_ce_disable_interrupts(struct ath10k *ar)
{
int ce_id;
for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
ath10k_ce_disable_interrupt(ar, ce_id);
} }
EXPORT_SYMBOL(ath10k_ce_disable_interrupts); EXPORT_SYMBOL(ath10k_ce_disable_interrupts);
void ath10k_ce_enable_interrupts(struct ath10k *ar) void ath10k_ce_enable_interrupt(struct ath10k *ar, int ce_id)
{ {
struct ath10k_ce *ce = ath10k_ce_priv(ar); struct ath10k_ce *ce = ath10k_ce_priv(ar);
int ce_id;
struct ath10k_ce_pipe *ce_state; struct ath10k_ce_pipe *ce_state;
ce_state = &ce->ce_states[ce_id];
if (ce_state->attr_flags & CE_ATTR_POLL)
return;
ath10k_ce_per_engine_handler_adjust(ce_state);
}
EXPORT_SYMBOL(ath10k_ce_enable_interrupt);
void ath10k_ce_enable_interrupts(struct ath10k *ar)
{
int ce_id;
/* Enable interrupts for copy engine that /* Enable interrupts for copy engine that
* are not using polling mode. * are not using polling mode.
*/ */
for (ce_id = 0; ce_id < CE_COUNT; ce_id++) { for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
ce_state = &ce->ce_states[ce_id]; ath10k_ce_enable_interrupt(ar, ce_id);
if (ce_state->attr_flags & CE_ATTR_POLL)
continue;
ath10k_ce_per_engine_handler_adjust(ce_state);
}
} }
EXPORT_SYMBOL(ath10k_ce_enable_interrupts); EXPORT_SYMBOL(ath10k_ce_enable_interrupts);

View file

@ -255,10 +255,13 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state,
/*==================CE Interrupt Handlers====================*/ /*==================CE Interrupt Handlers====================*/
void ath10k_ce_per_engine_service_any(struct ath10k *ar); void ath10k_ce_per_engine_service_any(struct ath10k *ar);
void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id); void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id);
int ath10k_ce_disable_interrupts(struct ath10k *ar); void ath10k_ce_disable_interrupt(struct ath10k *ar, int ce_id);
void ath10k_ce_disable_interrupts(struct ath10k *ar);
void ath10k_ce_enable_interrupt(struct ath10k *ar, int ce_id);
void ath10k_ce_enable_interrupts(struct ath10k *ar); void ath10k_ce_enable_interrupts(struct ath10k *ar);
void ath10k_ce_dump_registers(struct ath10k *ar, void ath10k_ce_dump_registers(struct ath10k *ar,
struct ath10k_fw_crash_data *crash_data); struct ath10k_fw_crash_data *crash_data);
void ath10k_ce_alloc_rri(struct ath10k *ar); void ath10k_ce_alloc_rri(struct ath10k *ar);
void ath10k_ce_free_rri(struct ath10k *ar); void ath10k_ce_free_rri(struct ath10k *ar);
@ -369,18 +372,14 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
(((x) & CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) >> \ (((x) & CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) >> \
CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB)
#define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 #define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000
#define CE_INTERRUPT_SUMMARY (GENMASK(CE_COUNT_MAX - 1, 0))
static inline u32 ath10k_ce_interrupt_summary(struct ath10k *ar) static inline u32 ath10k_ce_interrupt_summary(struct ath10k *ar)
{ {
struct ath10k_ce *ce = ath10k_ce_priv(ar); struct ath10k_ce *ce = ath10k_ce_priv(ar);
if (!ar->hw_params.per_ce_irq)
return CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET( return CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(
ce->bus_ops->read32((ar), CE_WRAPPER_BASE_ADDRESS + ce->bus_ops->read32((ar), CE_WRAPPER_BASE_ADDRESS +
CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS)); CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS));
else
return CE_INTERRUPT_SUMMARY;
} }
/* Host software's Copy Engine configuration. */ /* Host software's Copy Engine configuration. */

View file

@ -119,7 +119,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = 0x20, .num_wds_entries = 0x20,
.target_64bit = false, .target_64bit = false,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
.per_ce_irq = false,
.shadow_reg_support = false, .shadow_reg_support = false,
.rri_on_ddr = false, .rri_on_ddr = false,
.hw_filter_reset_required = true, .hw_filter_reset_required = true,
@ -155,7 +154,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = 0x20, .num_wds_entries = 0x20,
.target_64bit = false, .target_64bit = false,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
.per_ce_irq = false,
.shadow_reg_support = false, .shadow_reg_support = false,
.rri_on_ddr = false, .rri_on_ddr = false,
.hw_filter_reset_required = true, .hw_filter_reset_required = true,
@ -220,7 +218,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = 0x20, .num_wds_entries = 0x20,
.target_64bit = false, .target_64bit = false,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
.per_ce_irq = false,
.shadow_reg_support = false, .shadow_reg_support = false,
.rri_on_ddr = false, .rri_on_ddr = false,
.hw_filter_reset_required = true, .hw_filter_reset_required = true,
@ -255,7 +252,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = 0x20, .num_wds_entries = 0x20,
.target_64bit = false, .target_64bit = false,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
.per_ce_irq = false,
.shadow_reg_support = false, .shadow_reg_support = false,
.rri_on_ddr = false, .rri_on_ddr = false,
.hw_filter_reset_required = true, .hw_filter_reset_required = true,
@ -290,7 +286,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = 0x20, .num_wds_entries = 0x20,
.target_64bit = false, .target_64bit = false,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
.per_ce_irq = false,
.shadow_reg_support = false, .shadow_reg_support = false,
.rri_on_ddr = false, .rri_on_ddr = false,
.hw_filter_reset_required = true, .hw_filter_reset_required = true,
@ -328,7 +323,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = 0x20, .num_wds_entries = 0x20,
.target_64bit = false, .target_64bit = false,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
.per_ce_irq = false,
.shadow_reg_support = false, .shadow_reg_support = false,
.rri_on_ddr = false, .rri_on_ddr = false,
.hw_filter_reset_required = true, .hw_filter_reset_required = true,
@ -370,7 +364,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = 0x20, .num_wds_entries = 0x20,
.target_64bit = false, .target_64bit = false,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
.per_ce_irq = false,
.shadow_reg_support = false, .shadow_reg_support = false,
.rri_on_ddr = false, .rri_on_ddr = false,
.hw_filter_reset_required = true, .hw_filter_reset_required = true,
@ -418,7 +411,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = 0x20, .num_wds_entries = 0x20,
.target_64bit = false, .target_64bit = false,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
.per_ce_irq = false,
.shadow_reg_support = false, .shadow_reg_support = false,
.rri_on_ddr = false, .rri_on_ddr = false,
.hw_filter_reset_required = true, .hw_filter_reset_required = true,
@ -463,7 +455,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = 0x20, .num_wds_entries = 0x20,
.target_64bit = false, .target_64bit = false,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
.per_ce_irq = false,
.shadow_reg_support = false, .shadow_reg_support = false,
.rri_on_ddr = false, .rri_on_ddr = false,
.hw_filter_reset_required = true, .hw_filter_reset_required = true,
@ -498,7 +489,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = 0x20, .num_wds_entries = 0x20,
.target_64bit = false, .target_64bit = false,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
.per_ce_irq = false,
.shadow_reg_support = false, .shadow_reg_support = false,
.rri_on_ddr = false, .rri_on_ddr = false,
.hw_filter_reset_required = true, .hw_filter_reset_required = true,
@ -535,7 +525,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = 0x20, .num_wds_entries = 0x20,
.target_64bit = false, .target_64bit = false,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
.per_ce_irq = false,
.shadow_reg_support = false, .shadow_reg_support = false,
.rri_on_ddr = false, .rri_on_ddr = false,
.hw_filter_reset_required = true, .hw_filter_reset_required = true,
@ -604,7 +593,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = 0x20, .num_wds_entries = 0x20,
.target_64bit = false, .target_64bit = false,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
.per_ce_irq = false,
.shadow_reg_support = false, .shadow_reg_support = false,
.rri_on_ddr = false, .rri_on_ddr = false,
.hw_filter_reset_required = true, .hw_filter_reset_required = true,
@ -632,7 +620,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = TARGET_HL_TLV_NUM_WDS_ENTRIES, .num_wds_entries = TARGET_HL_TLV_NUM_WDS_ENTRIES,
.target_64bit = true, .target_64bit = true,
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC,
.per_ce_irq = true,
.shadow_reg_support = true, .shadow_reg_support = true,
.rri_on_ddr = true, .rri_on_ddr = true,
.hw_filter_reset_required = false, .hw_filter_reset_required = false,
@ -741,6 +728,16 @@ static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
if (ret) if (ret)
return ret; return ret;
ret = ath10k_bmi_read32(ar, hi_option_flag2, &param);
if (ret)
return ret;
param |= HI_OPTION_SDIO_CRASH_DUMP_ENHANCEMENT_HOST;
ret = ath10k_bmi_write32(ar, hi_option_flag2, param);
if (ret)
return ret;
return 0; return 0;
} }
@ -2805,6 +2802,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map)) if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map))
val |= WMI_10_4_REPORT_AIRTIME; val |= WMI_10_4_REPORT_AIRTIME;
if (test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
ar->wmi.svc_map))
val |= WMI_10_4_EXT_PEER_TID_CONFIGS_SUPPORT;
status = ath10k_mac_ext_resource_config(ar, val); status = ath10k_mac_ext_resource_config(ar, val);
if (status) { if (status) {
ath10k_err(ar, ath10k_err(ar,

View file

@ -82,6 +82,8 @@
/* Default Airtime weight multipler (Tuned for multiclient performance) */ /* Default Airtime weight multipler (Tuned for multiclient performance) */
#define ATH10K_AIRTIME_WEIGHT_MULTIPLIER 4 #define ATH10K_AIRTIME_WEIGHT_MULTIPLIER 4
#define ATH10K_MAX_RETRY_COUNT 30
struct ath10k; struct ath10k;
static inline const char *ath10k_bus_str(enum ath10k_bus bus) static inline const char *ath10k_bus_str(enum ath10k_bus bus)
@ -109,6 +111,7 @@ enum ath10k_skb_flags {
ATH10K_SKB_F_MGMT = BIT(3), ATH10K_SKB_F_MGMT = BIT(3),
ATH10K_SKB_F_QOS = BIT(4), ATH10K_SKB_F_QOS = BIT(4),
ATH10K_SKB_F_RAW_TX = BIT(5), ATH10K_SKB_F_RAW_TX = BIT(5),
ATH10K_SKB_F_NOACK_TID = BIT(6),
}; };
struct ath10k_skb_cb { struct ath10k_skb_cb {
@ -509,6 +512,8 @@ struct ath10k_htt_tx_stats {
u64 ack_fails; u64 ack_fails;
}; };
#define ATH10K_TID_MAX 8
struct ath10k_sta { struct ath10k_sta {
struct ath10k_vif *arvif; struct ath10k_vif *arvif;
@ -542,6 +547,13 @@ struct ath10k_sta {
#endif #endif
/* Protected with ar->data_lock */ /* Protected with ar->data_lock */
u32 peer_ps_state; u32 peer_ps_state;
struct work_struct tid_config_wk;
int noack[ATH10K_TID_MAX];
int retry_long[ATH10K_TID_MAX];
int ampdu[ATH10K_TID_MAX];
u8 rate_ctrl[ATH10K_TID_MAX];
u32 rate_code[ATH10K_TID_MAX];
int rtscts[ATH10K_TID_MAX];
}; };
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ) #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ)
@ -614,6 +626,14 @@ struct ath10k_vif {
/* For setting VHT peer fixed rate, protected by conf_mutex */ /* For setting VHT peer fixed rate, protected by conf_mutex */
int vht_num_rates; int vht_num_rates;
u8 vht_pfr; u8 vht_pfr;
u32 tid_conf_changed[ATH10K_TID_MAX];
int noack[ATH10K_TID_MAX];
int retry_long[ATH10K_TID_MAX];
int ampdu[ATH10K_TID_MAX];
u8 rate_ctrl[ATH10K_TID_MAX];
u32 rate_code[ATH10K_TID_MAX];
int rtscts[ATH10K_TID_MAX];
u32 tids_rst;
}; };
struct ath10k_vif_iter { struct ath10k_vif_iter {

View file

@ -270,6 +270,277 @@ static const struct ath10k_mem_section qca6174_hw21_register_sections[] = {
{0x80010, 0x80020}, {0x80010, 0x80020},
}; };
static const struct ath10k_mem_section qca6174_hw30_sdio_register_sections[] = {
{0x800, 0x810},
{0x820, 0x82C},
{0x830, 0x8F4},
{0x90C, 0x91C},
{0xA14, 0xA18},
{0xA84, 0xA94},
{0xAA8, 0xAD4},
{0xADC, 0xB40},
{0x1000, 0x10A4},
{0x10BC, 0x111C},
{0x1134, 0x1138},
{0x1144, 0x114C},
{0x1150, 0x115C},
{0x1160, 0x1178},
{0x1240, 0x1260},
{0x2000, 0x207C},
{0x3000, 0x3014},
{0x4000, 0x4014},
{0x5000, 0x5124},
{0x6000, 0x6040},
{0x6080, 0x60CC},
{0x6100, 0x611C},
{0x6140, 0x61D8},
{0x6200, 0x6238},
{0x6240, 0x628C},
{0x62C0, 0x62EC},
{0x6380, 0x63E8},
{0x6400, 0x6440},
{0x6480, 0x64CC},
{0x6500, 0x651C},
{0x6540, 0x6580},
{0x6600, 0x6638},
{0x6640, 0x668C},
{0x66C0, 0x66EC},
{0x6780, 0x67E8},
{0x7080, 0x708C},
{0x70C0, 0x70C8},
{0x7400, 0x741C},
{0x7440, 0x7454},
{0x7800, 0x7818},
{0x8010, 0x8060},
{0x8080, 0x8084},
{0x80A0, 0x80A4},
{0x80C0, 0x80C4},
{0x80E0, 0x80ec},
{0x8110, 0x8128},
{0x9000, 0x9004},
{0xF000, 0xF0E0},
{0xF140, 0xF190},
{0xF250, 0xF25C},
{0xF260, 0xF268},
{0xF26C, 0xF2A8},
{0x10008, 0x1000C},
{0x10014, 0x10018},
{0x1001C, 0x10020},
{0x10024, 0x10028},
{0x10030, 0x10034},
{0x10040, 0x10054},
{0x10058, 0x1007C},
{0x10080, 0x100C4},
{0x100C8, 0x10114},
{0x1012C, 0x10130},
{0x10138, 0x10144},
{0x10200, 0x10220},
{0x10230, 0x10250},
{0x10260, 0x10280},
{0x10290, 0x102B0},
{0x102C0, 0x102DC},
{0x102E0, 0x102F4},
{0x102FC, 0x1037C},
{0x10380, 0x10390},
{0x10800, 0x10828},
{0x10840, 0x10844},
{0x10880, 0x10884},
{0x108C0, 0x108E8},
{0x10900, 0x10928},
{0x10940, 0x10944},
{0x10980, 0x10984},
{0x109C0, 0x109E8},
{0x10A00, 0x10A28},
{0x10A40, 0x10A50},
{0x11000, 0x11028},
{0x11030, 0x11034},
{0x11038, 0x11068},
{0x11070, 0x11074},
{0x11078, 0x110A8},
{0x110B0, 0x110B4},
{0x110B8, 0x110E8},
{0x110F0, 0x110F4},
{0x110F8, 0x11128},
{0x11138, 0x11144},
{0x11178, 0x11180},
{0x111B8, 0x111C0},
{0x111F8, 0x11200},
{0x11238, 0x1123C},
{0x11270, 0x11274},
{0x11278, 0x1127C},
{0x112B0, 0x112B4},
{0x112B8, 0x112BC},
{0x112F0, 0x112F4},
{0x112F8, 0x112FC},
{0x11338, 0x1133C},
{0x11378, 0x1137C},
{0x113B8, 0x113BC},
{0x113F8, 0x113FC},
{0x11438, 0x11440},
{0x11478, 0x11480},
{0x114B8, 0x114BC},
{0x114F8, 0x114FC},
{0x11538, 0x1153C},
{0x11578, 0x1157C},
{0x115B8, 0x115BC},
{0x115F8, 0x115FC},
{0x11638, 0x1163C},
{0x11678, 0x1167C},
{0x116B8, 0x116BC},
{0x116F8, 0x116FC},
{0x11738, 0x1173C},
{0x11778, 0x1177C},
{0x117B8, 0x117BC},
{0x117F8, 0x117FC},
{0x17000, 0x1701C},
{0x17020, 0x170AC},
{0x18000, 0x18050},
{0x18054, 0x18074},
{0x18080, 0x180D4},
{0x180DC, 0x18104},
{0x18108, 0x1813C},
{0x18144, 0x18148},
{0x18168, 0x18174},
{0x18178, 0x18180},
{0x181C8, 0x181E0},
{0x181E4, 0x181E8},
{0x181EC, 0x1820C},
{0x1825C, 0x18280},
{0x18284, 0x18290},
{0x18294, 0x182A0},
{0x18300, 0x18304},
{0x18314, 0x18320},
{0x18328, 0x18350},
{0x1835C, 0x1836C},
{0x18370, 0x18390},
{0x18398, 0x183AC},
{0x183BC, 0x183D8},
{0x183DC, 0x183F4},
{0x18400, 0x186F4},
{0x186F8, 0x1871C},
{0x18720, 0x18790},
{0x19800, 0x19830},
{0x19834, 0x19840},
{0x19880, 0x1989C},
{0x198A4, 0x198B0},
{0x198BC, 0x19900},
{0x19C00, 0x19C88},
{0x19D00, 0x19D20},
{0x19E00, 0x19E7C},
{0x19E80, 0x19E94},
{0x19E98, 0x19EAC},
{0x19EB0, 0x19EBC},
{0x19F70, 0x19F74},
{0x19F80, 0x19F8C},
{0x19FA0, 0x19FB4},
{0x19FC0, 0x19FD8},
{0x1A000, 0x1A200},
{0x1A204, 0x1A210},
{0x1A228, 0x1A22C},
{0x1A230, 0x1A248},
{0x1A250, 0x1A270},
{0x1A280, 0x1A290},
{0x1A2A0, 0x1A2A4},
{0x1A2C0, 0x1A2EC},
{0x1A300, 0x1A3BC},
{0x1A3F0, 0x1A3F4},
{0x1A3F8, 0x1A434},
{0x1A438, 0x1A444},
{0x1A448, 0x1A468},
{0x1A580, 0x1A58C},
{0x1A644, 0x1A654},
{0x1A670, 0x1A698},
{0x1A6AC, 0x1A6B0},
{0x1A6D0, 0x1A6D4},
{0x1A6EC, 0x1A70C},
{0x1A710, 0x1A738},
{0x1A7C0, 0x1A7D0},
{0x1A7D4, 0x1A7D8},
{0x1A7DC, 0x1A7E4},
{0x1A7F0, 0x1A7F8},
{0x1A888, 0x1A89C},
{0x1A8A8, 0x1A8AC},
{0x1A8C0, 0x1A8DC},
{0x1A8F0, 0x1A8FC},
{0x1AE04, 0x1AE08},
{0x1AE18, 0x1AE24},
{0x1AF80, 0x1AF8C},
{0x1AFA0, 0x1AFB4},
{0x1B000, 0x1B200},
{0x1B284, 0x1B288},
{0x1B2D0, 0x1B2D8},
{0x1B2DC, 0x1B2EC},
{0x1B300, 0x1B340},
{0x1B374, 0x1B378},
{0x1B380, 0x1B384},
{0x1B388, 0x1B38C},
{0x1B404, 0x1B408},
{0x1B420, 0x1B428},
{0x1B440, 0x1B444},
{0x1B448, 0x1B44C},
{0x1B450, 0x1B458},
{0x1B45C, 0x1B468},
{0x1B584, 0x1B58C},
{0x1B68C, 0x1B690},
{0x1B6AC, 0x1B6B0},
{0x1B7F0, 0x1B7F8},
{0x1C800, 0x1CC00},
{0x1CE00, 0x1CE04},
{0x1CF80, 0x1CF84},
{0x1D200, 0x1D800},
{0x1E000, 0x20014},
{0x20100, 0x20124},
{0x21400, 0x217A8},
{0x21800, 0x21BA8},
{0x21C00, 0x21FA8},
{0x22000, 0x223A8},
{0x22400, 0x227A8},
{0x22800, 0x22BA8},
{0x22C00, 0x22FA8},
{0x23000, 0x233A8},
{0x24000, 0x24034},
/* EFUSE0,1,2 is disabled here
* because its state may be reset
*
* {0x24800, 0x24804},
* {0x25000, 0x25004},
* {0x25800, 0x25804},
*/
{0x26000, 0x26064},
{0x27000, 0x27024},
{0x34000, 0x3400C},
{0x34400, 0x3445C},
{0x34800, 0x3485C},
{0x34C00, 0x34C5C},
{0x35000, 0x3505C},
{0x35400, 0x3545C},
{0x35800, 0x3585C},
{0x35C00, 0x35C5C},
{0x36000, 0x3605C},
{0x38000, 0x38064},
{0x38070, 0x380E0},
{0x3A000, 0x3A074},
/* DBI windows is skipped here, it can be only accessed when pcie
* is active (not in reset) and CORE_CTRL_PCIE_LTSSM_EN = 0 &&
* PCIE_CTRL_APP_LTSSM_ENALBE=0.
* {0x3C000 , 0x3C004},
*/
{0x40000, 0x400A4},
/* SI register is skiped here.
* Because it will cause bus hang
*
* {0x50000, 0x50018},
*/
{0x80000, 0x8000C},
{0x80010, 0x80020},
};
static const struct ath10k_mem_section qca6174_hw30_register_sections[] = { static const struct ath10k_mem_section qca6174_hw30_register_sections[] = {
{0x800, 0x810}, {0x800, 0x810},
{0x820, 0x82C}, {0x820, 0x82C},
@ -602,6 +873,59 @@ static const struct ath10k_mem_region qca6174_hw21_mem_regions[] = {
}, },
}; };
static const struct ath10k_mem_region qca6174_hw30_sdio_mem_regions[] = {
{
.type = ATH10K_MEM_REGION_TYPE_DRAM,
.start = 0x400000,
.len = 0xa8000,
.name = "DRAM",
.section_table = {
.sections = NULL,
.size = 0,
},
},
{
.type = ATH10K_MEM_REGION_TYPE_AXI,
.start = 0xa0000,
.len = 0x18000,
.name = "AXI",
.section_table = {
.sections = NULL,
.size = 0,
},
},
{
.type = ATH10K_MEM_REGION_TYPE_IRAM1,
.start = 0x00980000,
.len = 0x00080000,
.name = "IRAM1",
.section_table = {
.sections = NULL,
.size = 0,
},
},
{
.type = ATH10K_MEM_REGION_TYPE_IRAM2,
.start = 0x00a00000,
.len = 0x00040000,
.name = "IRAM2",
.section_table = {
.sections = NULL,
.size = 0,
},
},
{
.type = ATH10K_MEM_REGION_TYPE_REG,
.start = 0x800,
.len = 0x80020 - 0x800,
.name = "REG_TOTAL",
.section_table = {
.sections = qca6174_hw30_sdio_register_sections,
.size = ARRAY_SIZE(qca6174_hw30_sdio_register_sections),
},
},
};
static const struct ath10k_mem_region qca6174_hw30_mem_regions[] = { static const struct ath10k_mem_region qca6174_hw30_mem_regions[] = {
{ {
.type = ATH10K_MEM_REGION_TYPE_DRAM, .type = ATH10K_MEM_REGION_TYPE_DRAM,
@ -968,6 +1292,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{ {
.hw_id = QCA6174_HW_1_0_VERSION, .hw_id = QCA6174_HW_1_0_VERSION,
.hw_rev = ATH10K_HW_QCA6174, .hw_rev = ATH10K_HW_QCA6174,
.bus = ATH10K_BUS_PCI,
.region_table = { .region_table = {
.regions = qca6174_hw10_mem_regions, .regions = qca6174_hw10_mem_regions,
.size = ARRAY_SIZE(qca6174_hw10_mem_regions), .size = ARRAY_SIZE(qca6174_hw10_mem_regions),
@ -976,6 +1301,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{ {
.hw_id = QCA6174_HW_1_1_VERSION, .hw_id = QCA6174_HW_1_1_VERSION,
.hw_rev = ATH10K_HW_QCA6174, .hw_rev = ATH10K_HW_QCA6174,
.bus = ATH10K_BUS_PCI,
.region_table = { .region_table = {
.regions = qca6174_hw10_mem_regions, .regions = qca6174_hw10_mem_regions,
.size = ARRAY_SIZE(qca6174_hw10_mem_regions), .size = ARRAY_SIZE(qca6174_hw10_mem_regions),
@ -984,6 +1310,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{ {
.hw_id = QCA6174_HW_1_3_VERSION, .hw_id = QCA6174_HW_1_3_VERSION,
.hw_rev = ATH10K_HW_QCA6174, .hw_rev = ATH10K_HW_QCA6174,
.bus = ATH10K_BUS_PCI,
.region_table = { .region_table = {
.regions = qca6174_hw10_mem_regions, .regions = qca6174_hw10_mem_regions,
.size = ARRAY_SIZE(qca6174_hw10_mem_regions), .size = ARRAY_SIZE(qca6174_hw10_mem_regions),
@ -992,6 +1319,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{ {
.hw_id = QCA6174_HW_2_1_VERSION, .hw_id = QCA6174_HW_2_1_VERSION,
.hw_rev = ATH10K_HW_QCA6174, .hw_rev = ATH10K_HW_QCA6174,
.bus = ATH10K_BUS_PCI,
.region_table = { .region_table = {
.regions = qca6174_hw21_mem_regions, .regions = qca6174_hw21_mem_regions,
.size = ARRAY_SIZE(qca6174_hw21_mem_regions), .size = ARRAY_SIZE(qca6174_hw21_mem_regions),
@ -1000,6 +1328,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{ {
.hw_id = QCA6174_HW_3_0_VERSION, .hw_id = QCA6174_HW_3_0_VERSION,
.hw_rev = ATH10K_HW_QCA6174, .hw_rev = ATH10K_HW_QCA6174,
.bus = ATH10K_BUS_PCI,
.region_table = { .region_table = {
.regions = qca6174_hw30_mem_regions, .regions = qca6174_hw30_mem_regions,
.size = ARRAY_SIZE(qca6174_hw30_mem_regions), .size = ARRAY_SIZE(qca6174_hw30_mem_regions),
@ -1008,14 +1337,25 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{ {
.hw_id = QCA6174_HW_3_2_VERSION, .hw_id = QCA6174_HW_3_2_VERSION,
.hw_rev = ATH10K_HW_QCA6174, .hw_rev = ATH10K_HW_QCA6174,
.bus = ATH10K_BUS_PCI,
.region_table = { .region_table = {
.regions = qca6174_hw30_mem_regions, .regions = qca6174_hw30_mem_regions,
.size = ARRAY_SIZE(qca6174_hw30_mem_regions), .size = ARRAY_SIZE(qca6174_hw30_mem_regions),
}, },
}, },
{
.hw_id = QCA6174_HW_3_2_VERSION,
.hw_rev = ATH10K_HW_QCA6174,
.bus = ATH10K_BUS_SDIO,
.region_table = {
.regions = qca6174_hw30_sdio_mem_regions,
.size = ARRAY_SIZE(qca6174_hw30_sdio_mem_regions),
},
},
{ {
.hw_id = QCA9377_HW_1_1_DEV_VERSION, .hw_id = QCA9377_HW_1_1_DEV_VERSION,
.hw_rev = ATH10K_HW_QCA9377, .hw_rev = ATH10K_HW_QCA9377,
.bus = ATH10K_BUS_PCI,
.region_table = { .region_table = {
.regions = qca6174_hw30_mem_regions, .regions = qca6174_hw30_mem_regions,
.size = ARRAY_SIZE(qca6174_hw30_mem_regions), .size = ARRAY_SIZE(qca6174_hw30_mem_regions),
@ -1024,6 +1364,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{ {
.hw_id = QCA988X_HW_2_0_VERSION, .hw_id = QCA988X_HW_2_0_VERSION,
.hw_rev = ATH10K_HW_QCA988X, .hw_rev = ATH10K_HW_QCA988X,
.bus = ATH10K_BUS_PCI,
.region_table = { .region_table = {
.regions = qca988x_hw20_mem_regions, .regions = qca988x_hw20_mem_regions,
.size = ARRAY_SIZE(qca988x_hw20_mem_regions), .size = ARRAY_SIZE(qca988x_hw20_mem_regions),
@ -1032,6 +1373,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{ {
.hw_id = QCA9984_HW_1_0_DEV_VERSION, .hw_id = QCA9984_HW_1_0_DEV_VERSION,
.hw_rev = ATH10K_HW_QCA9984, .hw_rev = ATH10K_HW_QCA9984,
.bus = ATH10K_BUS_PCI,
.region_table = { .region_table = {
.regions = qca9984_hw10_mem_regions, .regions = qca9984_hw10_mem_regions,
.size = ARRAY_SIZE(qca9984_hw10_mem_regions), .size = ARRAY_SIZE(qca9984_hw10_mem_regions),
@ -1040,6 +1382,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{ {
.hw_id = QCA9888_HW_2_0_DEV_VERSION, .hw_id = QCA9888_HW_2_0_DEV_VERSION,
.hw_rev = ATH10K_HW_QCA9888, .hw_rev = ATH10K_HW_QCA9888,
.bus = ATH10K_BUS_PCI,
.region_table = { .region_table = {
.regions = qca9984_hw10_mem_regions, .regions = qca9984_hw10_mem_regions,
.size = ARRAY_SIZE(qca9984_hw10_mem_regions), .size = ARRAY_SIZE(qca9984_hw10_mem_regions),
@ -1048,6 +1391,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{ {
.hw_id = QCA99X0_HW_2_0_DEV_VERSION, .hw_id = QCA99X0_HW_2_0_DEV_VERSION,
.hw_rev = ATH10K_HW_QCA99X0, .hw_rev = ATH10K_HW_QCA99X0,
.bus = ATH10K_BUS_PCI,
.region_table = { .region_table = {
.regions = qca99x0_hw20_mem_regions, .regions = qca99x0_hw20_mem_regions,
.size = ARRAY_SIZE(qca99x0_hw20_mem_regions), .size = ARRAY_SIZE(qca99x0_hw20_mem_regions),
@ -1056,6 +1400,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{ {
.hw_id = QCA4019_HW_1_0_DEV_VERSION, .hw_id = QCA4019_HW_1_0_DEV_VERSION,
.hw_rev = ATH10K_HW_QCA4019, .hw_rev = ATH10K_HW_QCA4019,
.bus = ATH10K_BUS_AHB,
.region_table = { .region_table = {
.regions = qca4019_hw10_mem_regions, .regions = qca4019_hw10_mem_regions,
.size = ARRAY_SIZE(qca4019_hw10_mem_regions), .size = ARRAY_SIZE(qca4019_hw10_mem_regions),
@ -1064,6 +1409,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
{ {
.hw_id = WCN3990_HW_1_0_DEV_VERSION, .hw_id = WCN3990_HW_1_0_DEV_VERSION,
.hw_rev = ATH10K_HW_WCN3990, .hw_rev = ATH10K_HW_WCN3990,
.bus = ATH10K_BUS_SNOC,
.region_table = { .region_table = {
.regions = wcn399x_hw10_mem_regions, .regions = wcn399x_hw10_mem_regions,
.size = ARRAY_SIZE(wcn399x_hw10_mem_regions), .size = ARRAY_SIZE(wcn399x_hw10_mem_regions),
@ -1111,7 +1457,8 @@ const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k
for (i = 0; i < ARRAY_SIZE(hw_mem_layouts); i++) { for (i = 0; i < ARRAY_SIZE(hw_mem_layouts); i++) {
if (ar->target_version == hw_mem_layouts[i].hw_id && if (ar->target_version == hw_mem_layouts[i].hw_id &&
ar->hw_rev == hw_mem_layouts[i].hw_rev) ar->hw_rev == hw_mem_layouts[i].hw_rev &&
hw_mem_layouts[i].bus == ar->hif.bus)
return &hw_mem_layouts[i]; return &hw_mem_layouts[i];
} }

View file

@ -156,6 +156,7 @@ struct ath10k_mem_region {
struct ath10k_hw_mem_layout { struct ath10k_hw_mem_layout {
u32 hw_id; u32 hw_id;
u32 hw_rev; u32 hw_rev;
enum ath10k_bus bus;
struct { struct {
const struct ath10k_mem_region *regions; const struct ath10k_mem_region *regions;

View file

@ -593,9 +593,6 @@ struct ath10k_hw_params {
/* Target rx ring fill level */ /* Target rx ring fill level */
u32 rx_ring_fill_level; u32 rx_ring_fill_level;
/* target supporting per ce IRQ */
bool per_ce_irq;
/* target supporting shadow register for ce write */ /* target supporting shadow register for ce write */
bool shadow_reg_support; bool shadow_reg_support;

View file

@ -3013,6 +3013,69 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
cancel_delayed_work_sync(&arvif->connection_loss_work); cancel_delayed_work_sync(&arvif->connection_loss_work);
} }
static int ath10k_new_peer_tid_config(struct ath10k *ar,
struct ieee80211_sta *sta,
struct ath10k_vif *arvif)
{
struct wmi_per_peer_per_tid_cfg_arg arg = {};
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
bool config_apply;
int ret, i;
for (i = 0; i < ATH10K_TID_MAX; i++) {
config_apply = false;
if (arvif->retry_long[i] || arvif->ampdu[i] ||
arvif->rate_ctrl[i] || arvif->rtscts[i]) {
config_apply = true;
arg.tid = i;
arg.vdev_id = arvif->vdev_id;
arg.retry_count = arvif->retry_long[i];
arg.aggr_control = arvif->ampdu[i];
arg.rate_ctrl = arvif->rate_ctrl[i];
arg.rcode_flags = arvif->rate_code[i];
if (arvif->rtscts[i])
arg.ext_tid_cfg_bitmap =
WMI_EXT_TID_RTS_CTS_CONFIG;
else
arg.ext_tid_cfg_bitmap = 0;
arg.rtscts_ctrl = arvif->rtscts[i];
}
if (arvif->noack[i]) {
arg.ack_policy = arvif->noack[i];
arg.rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_DEFAULT_LOWEST_RATE;
arg.aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_DISABLE;
config_apply = true;
}
/* Assign default value(-1) to newly connected station.
* This is to identify station specific tid configuration not
* configured for the station.
*/
arsta->retry_long[i] = -1;
arsta->noack[i] = -1;
arsta->ampdu[i] = -1;
if (!config_apply)
continue;
ether_addr_copy(arg.peer_macaddr.addr, sta->addr);
ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, &arg);
if (ret) {
ath10k_warn(ar, "failed to set per tid retry/aggr config for sta %pM: %d\n",
sta->addr, ret);
return ret;
}
memset(&arg, 0, sizeof(arg));
}
return 0;
}
static int ath10k_station_assoc(struct ath10k *ar, static int ath10k_station_assoc(struct ath10k *ar,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
@ -3078,7 +3141,10 @@ static int ath10k_station_assoc(struct ath10k *ar,
} }
} }
if (!test_bit(WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, ar->wmi.svc_map))
return ret; return ret;
return ath10k_new_peer_tid_config(ar, sta, arvif);
} }
static int ath10k_station_disassoc(struct ath10k *ar, static int ath10k_station_disassoc(struct ath10k *ar,
@ -3626,7 +3692,10 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
const struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); const struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
bool is_data = ieee80211_is_data(hdr->frame_control) || bool is_data = ieee80211_is_data(hdr->frame_control) ||
ieee80211_is_data_qos(hdr->frame_control); ieee80211_is_data_qos(hdr->frame_control);
struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_sta *arsta; struct ath10k_sta *arsta;
u8 tid, *qos_ctl;
bool noack = false;
cb->flags = 0; cb->flags = 0;
if (!ath10k_tx_h_use_hwcrypto(vif, skb)) if (!ath10k_tx_h_use_hwcrypto(vif, skb))
@ -3635,8 +3704,27 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
if (ieee80211_is_mgmt(hdr->frame_control)) if (ieee80211_is_mgmt(hdr->frame_control))
cb->flags |= ATH10K_SKB_F_MGMT; cb->flags |= ATH10K_SKB_F_MGMT;
if (ieee80211_is_data_qos(hdr->frame_control)) if (ieee80211_is_data_qos(hdr->frame_control)) {
cb->flags |= ATH10K_SKB_F_QOS; cb->flags |= ATH10K_SKB_F_QOS;
qos_ctl = ieee80211_get_qos_ctl(hdr);
tid = (*qos_ctl) & IEEE80211_QOS_CTL_TID_MASK;
if (arvif->noack[tid] == WMI_PEER_TID_CONFIG_NOACK)
noack = true;
if (sta) {
arsta = (struct ath10k_sta *)sta->drv_priv;
if (arsta->noack[tid] == WMI_PEER_TID_CONFIG_NOACK)
noack = true;
if (arsta->noack[tid] == WMI_PEER_TID_CONFIG_ACK)
noack = false;
}
if (noack)
cb->flags |= ATH10K_SKB_F_NOACK_TID;
}
/* Data frames encrypted in software will be posted to firmware /* Data frames encrypted in software will be posted to firmware
* with tx encap mode set to RAW. Ex: Multicast traffic generated * with tx encap mode set to RAW. Ex: Multicast traffic generated
@ -6597,6 +6685,581 @@ out:
return ret; return ret;
} }
struct ath10k_mac_iter_tid_conf_data {
struct ieee80211_vif *curr_vif;
struct ath10k *ar;
bool reset_config;
};
static bool
ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar,
enum nl80211_band band,
const struct cfg80211_bitrate_mask *mask,
int *vht_num_rates)
{
int num_rates = 0;
int i, tmp;
num_rates += hweight32(mask->control[band].legacy);
for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
num_rates += hweight8(mask->control[band].ht_mcs[i]);
*vht_num_rates = 0;
for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
tmp = hweight16(mask->control[band].vht_mcs[i]);
num_rates += tmp;
*vht_num_rates += tmp;
}
return num_rates == 1;
}
static int
ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
enum nl80211_band band,
const struct cfg80211_bitrate_mask *mask,
u8 *rate, u8 *nss, bool vht_only)
{
int rate_idx;
int i;
u16 bitrate;
u8 preamble;
u8 hw_rate;
if (vht_only)
goto next;
if (hweight32(mask->control[band].legacy) == 1) {
rate_idx = ffs(mask->control[band].legacy) - 1;
if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY)
rate_idx += ATH10K_MAC_FIRST_OFDM_RATE_IDX;
hw_rate = ath10k_wmi_legacy_rates[rate_idx].hw_value;
bitrate = ath10k_wmi_legacy_rates[rate_idx].bitrate;
if (ath10k_mac_bitrate_is_cck(bitrate))
preamble = WMI_RATE_PREAMBLE_CCK;
else
preamble = WMI_RATE_PREAMBLE_OFDM;
*nss = 1;
*rate = preamble << 6 |
(*nss - 1) << 4 |
hw_rate << 0;
return 0;
}
for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
if (hweight8(mask->control[band].ht_mcs[i]) == 1) {
*nss = i + 1;
*rate = WMI_RATE_PREAMBLE_HT << 6 |
(*nss - 1) << 4 |
(ffs(mask->control[band].ht_mcs[i]) - 1);
return 0;
}
}
next:
for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
*nss = i + 1;
*rate = WMI_RATE_PREAMBLE_VHT << 6 |
(*nss - 1) << 4 |
(ffs(mask->control[band].vht_mcs[i]) - 1);
return 0;
}
}
return -EINVAL;
}
static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
struct ieee80211_sta *sta,
u32 rate_ctrl_flag, u8 nss)
{
if (nss > sta->rx_nss) {
ath10k_warn(ar, "Invalid nss field, configured %u limit %u\n",
nss, sta->rx_nss);
return -EINVAL;
}
if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_VHT) {
if (!sta->vht_cap.vht_supported) {
ath10k_warn(ar, "Invalid VHT rate for sta %pM\n",
sta->addr);
return -EINVAL;
}
} else if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_HT) {
if (!sta->ht_cap.ht_supported || sta->vht_cap.vht_supported) {
ath10k_warn(ar, "Invalid HT rate for sta %pM\n",
sta->addr);
return -EINVAL;
}
} else {
if (sta->ht_cap.ht_supported || sta->vht_cap.vht_supported)
return -EINVAL;
}
return 0;
}
static int
ath10k_mac_tid_bitrate_config(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
u32 *rate_ctrl_flag, u8 *rate_ctrl,
enum nl80211_tx_rate_setting txrate_type,
const struct cfg80211_bitrate_mask *mask)
{
struct cfg80211_chan_def def;
enum nl80211_band band;
u8 nss, rate;
int vht_num_rates, ret;
if (WARN_ON(ath10k_mac_vif_chan(vif, &def)))
return -EINVAL;
if (txrate_type == NL80211_TX_RATE_AUTOMATIC) {
*rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_AUTO;
*rate_ctrl_flag = 0;
return 0;
}
band = def.chan->band;
if (!ath10k_mac_bitrate_mask_has_single_rate(ar, band, mask,
&vht_num_rates)) {
return -EINVAL;
}
ret = ath10k_mac_bitrate_mask_get_single_rate(ar, band, mask,
&rate, &nss, false);
if (ret) {
ath10k_warn(ar, "failed to get single rate: %d\n",
ret);
return ret;
}
*rate_ctrl_flag = rate;
if (sta && ath10k_mac_validate_rate_mask(ar, sta, *rate_ctrl_flag, nss))
return -EINVAL;
if (txrate_type == NL80211_TX_RATE_FIXED)
*rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_FIXED_RATE;
else if (txrate_type == NL80211_TX_RATE_LIMITED &&
(test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
ar->wmi.svc_map)))
*rate_ctrl = WMI_PEER_TID_CONFIG_RATE_UPPER_CAP;
else
return -EOPNOTSUPP;
return 0;
}
static int ath10k_mac_set_tid_config(struct ath10k *ar, struct ieee80211_sta *sta,
struct ieee80211_vif *vif, u32 changed,
struct wmi_per_peer_per_tid_cfg_arg *arg)
{
struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_sta *arsta;
int ret;
if (sta) {
if (!sta->wme)
return -ENOTSUPP;
arsta = (struct ath10k_sta *)sta->drv_priv;
if (changed & BIT(NL80211_TID_CONFIG_ATTR_NOACK)) {
if ((arsta->retry_long[arg->tid] > 0 ||
arsta->rate_code[arg->tid] > 0 ||
arsta->ampdu[arg->tid] ==
WMI_TID_CONFIG_AGGR_CONTROL_ENABLE) &&
arg->ack_policy == WMI_PEER_TID_CONFIG_NOACK) {
changed &= ~BIT(NL80211_TID_CONFIG_ATTR_NOACK);
arg->ack_policy = 0;
arg->aggr_control = 0;
arg->rate_ctrl = 0;
arg->rcode_flags = 0;
}
}
if (changed & BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL)) {
if (arsta->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK ||
arvif->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK) {
arg->aggr_control = 0;
changed &= ~BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG);
}
}
if (changed & (BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) |
BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE))) {
if (arsta->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK ||
arvif->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK) {
arg->rate_ctrl = 0;
arg->rcode_flags = 0;
}
}
ether_addr_copy(arg->peer_macaddr.addr, sta->addr);
ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, arg);
if (ret)
return ret;
/* Store the configured parameters in success case */
if (changed & BIT(NL80211_TID_CONFIG_ATTR_NOACK)) {
arsta->noack[arg->tid] = arg->ack_policy;
arg->ack_policy = 0;
arg->aggr_control = 0;
arg->rate_ctrl = 0;
arg->rcode_flags = 0;
}
if (changed & BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG)) {
arsta->retry_long[arg->tid] = arg->retry_count;
arg->retry_count = 0;
}
if (changed & BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL)) {
arsta->ampdu[arg->tid] = arg->aggr_control;
arg->aggr_control = 0;
}
if (changed & (BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) |
BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE))) {
arsta->rate_ctrl[arg->tid] = arg->rate_ctrl;
arg->rate_ctrl = 0;
arg->rcode_flags = 0;
}
if (changed & BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL)) {
arsta->rtscts[arg->tid] = arg->rtscts_ctrl;
arg->ext_tid_cfg_bitmap = 0;
}
} else {
if (changed & BIT(NL80211_TID_CONFIG_ATTR_NOACK)) {
if ((arvif->retry_long[arg->tid] ||
arvif->rate_code[arg->tid] ||
arvif->ampdu[arg->tid] ==
WMI_TID_CONFIG_AGGR_CONTROL_ENABLE) &&
arg->ack_policy == WMI_PEER_TID_CONFIG_NOACK) {
changed &= ~BIT(NL80211_TID_CONFIG_ATTR_NOACK);
} else {
arvif->noack[arg->tid] = arg->ack_policy;
arvif->ampdu[arg->tid] = arg->aggr_control;
arvif->rate_ctrl[arg->tid] = arg->rate_ctrl;
}
}
if (changed & BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG)) {
if (arvif->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK)
changed &= ~BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG);
else
arvif->retry_long[arg->tid] = arg->retry_count;
}
if (changed & BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL)) {
if (arvif->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK)
changed &= ~BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
else
arvif->ampdu[arg->tid] = arg->aggr_control;
}
if (changed & (BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) |
BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE))) {
if (arvif->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK) {
changed &= ~(BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) |
BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE));
} else {
arvif->rate_ctrl[arg->tid] = arg->rate_ctrl;
arvif->rate_code[arg->tid] = arg->rcode_flags;
}
}
if (changed & BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL)) {
arvif->rtscts[arg->tid] = arg->rtscts_ctrl;
arg->ext_tid_cfg_bitmap = 0;
}
if (changed)
arvif->tid_conf_changed[arg->tid] |= changed;
}
return 0;
}
static int
ath10k_mac_parse_tid_config(struct ath10k *ar,
struct ieee80211_sta *sta,
struct ieee80211_vif *vif,
struct cfg80211_tid_cfg *tid_conf,
struct wmi_per_peer_per_tid_cfg_arg *arg)
{
u32 changed = tid_conf->mask;
int ret = 0, i = 0;
if (!changed)
return -EINVAL;
while (i < ATH10K_TID_MAX) {
if (!(tid_conf->tids & BIT(i))) {
i++;
continue;
}
arg->tid = i;
if (changed & BIT(NL80211_TID_CONFIG_ATTR_NOACK)) {
if (tid_conf->noack == NL80211_TID_CONFIG_ENABLE) {
arg->ack_policy = WMI_PEER_TID_CONFIG_NOACK;
arg->rate_ctrl =
WMI_TID_CONFIG_RATE_CONTROL_DEFAULT_LOWEST_RATE;
arg->aggr_control =
WMI_TID_CONFIG_AGGR_CONTROL_DISABLE;
} else {
arg->ack_policy =
WMI_PEER_TID_CONFIG_ACK;
arg->rate_ctrl =
WMI_TID_CONFIG_RATE_CONTROL_AUTO;
arg->aggr_control =
WMI_TID_CONFIG_AGGR_CONTROL_ENABLE;
}
}
if (changed & BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG))
arg->retry_count = tid_conf->retry_long;
if (changed & BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL)) {
if (tid_conf->noack == NL80211_TID_CONFIG_ENABLE)
arg->aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_ENABLE;
else
arg->aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_DISABLE;
}
if (changed & (BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) |
BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE))) {
ret = ath10k_mac_tid_bitrate_config(ar, vif, sta,
&arg->rcode_flags,
&arg->rate_ctrl,
tid_conf->txrate_type,
&tid_conf->txrate_mask);
if (ret) {
ath10k_warn(ar, "failed to configure bitrate mask %d\n",
ret);
arg->rcode_flags = 0;
arg->rate_ctrl = 0;
}
}
if (changed & BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL)) {
if (tid_conf->rtscts)
arg->rtscts_ctrl = tid_conf->rtscts;
arg->ext_tid_cfg_bitmap = WMI_EXT_TID_RTS_CTS_CONFIG;
}
ret = ath10k_mac_set_tid_config(ar, sta, vif, changed, arg);
if (ret)
return ret;
i++;
}
return ret;
}
static int ath10k_mac_reset_tid_config(struct ath10k *ar,
struct ieee80211_sta *sta,
struct ath10k_vif *arvif,
u8 tids)
{
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
struct wmi_per_peer_per_tid_cfg_arg arg;
int ret = 0, i = 0;
arg.vdev_id = arvif->vdev_id;
while (i < ATH10K_TID_MAX) {
if (!(tids & BIT(i))) {
i++;
continue;
}
arg.tid = i;
arg.ack_policy = WMI_PEER_TID_CONFIG_ACK;
arg.retry_count = ATH10K_MAX_RETRY_COUNT;
arg.rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_AUTO;
arg.aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_ENABLE;
arg.rtscts_ctrl = WMI_TID_CONFIG_RTSCTS_CONTROL_ENABLE;
arg.ext_tid_cfg_bitmap = WMI_EXT_TID_RTS_CTS_CONFIG;
ether_addr_copy(arg.peer_macaddr.addr, sta->addr);
ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, &arg);
if (ret)
return ret;
if (!arvif->tids_rst) {
arsta->retry_long[i] = -1;
arsta->noack[i] = -1;
arsta->ampdu[i] = -1;
arsta->rate_code[i] = -1;
arsta->rate_ctrl[i] = 0;
arsta->rtscts[i] = -1;
} else {
arvif->retry_long[i] = 0;
arvif->noack[i] = 0;
arvif->ampdu[i] = 0;
arvif->rate_code[i] = 0;
arvif->rate_ctrl[i] = 0;
arvif->rtscts[i] = 0;
}
i++;
}
return ret;
}
static void ath10k_sta_tid_cfg_wk(struct work_struct *wk)
{
struct wmi_per_peer_per_tid_cfg_arg arg = {};
struct ieee80211_sta *sta;
struct ath10k_sta *arsta;
struct ath10k_vif *arvif;
struct ath10k *ar;
bool config_apply;
int ret, i;
u32 changed;
u8 nss;
arsta = container_of(wk, struct ath10k_sta, tid_config_wk);
sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
arvif = arsta->arvif;
ar = arvif->ar;
mutex_lock(&ar->conf_mutex);
if (arvif->tids_rst) {
ret = ath10k_mac_reset_tid_config(ar, sta, arvif,
arvif->tids_rst);
goto exit;
}
ether_addr_copy(arg.peer_macaddr.addr, sta->addr);
for (i = 0; i < ATH10K_TID_MAX; i++) {
config_apply = false;
changed = arvif->tid_conf_changed[i];
if (changed & BIT(NL80211_TID_CONFIG_ATTR_NOACK)) {
if (arsta->noack[i] != -1) {
arg.ack_policy = 0;
} else {
config_apply = true;
arg.ack_policy = arvif->noack[i];
arg.aggr_control = arvif->ampdu[i];
arg.rate_ctrl = arvif->rate_ctrl[i];
}
}
if (changed & BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG)) {
if (arsta->retry_long[i] != -1 ||
arsta->noack[i] == WMI_PEER_TID_CONFIG_NOACK ||
arvif->noack[i] == WMI_PEER_TID_CONFIG_NOACK) {
arg.retry_count = 0;
} else {
arg.retry_count = arvif->retry_long[i];
config_apply = true;
}
}
if (changed & BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL)) {
if (arsta->ampdu[i] != -1 ||
arsta->noack[i] == WMI_PEER_TID_CONFIG_NOACK ||
arvif->noack[i] == WMI_PEER_TID_CONFIG_NOACK) {
arg.aggr_control = 0;
} else {
arg.aggr_control = arvif->ampdu[i];
config_apply = true;
}
}
if (changed & (BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) |
BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE))) {
nss = ATH10K_HW_NSS(arvif->rate_code[i]);
ret = ath10k_mac_validate_rate_mask(ar, sta,
arvif->rate_code[i],
nss);
if (ret &&
arvif->rate_ctrl[i] > WMI_TID_CONFIG_RATE_CONTROL_AUTO) {
arg.rate_ctrl = 0;
arg.rcode_flags = 0;
}
if (arsta->rate_ctrl[i] >
WMI_TID_CONFIG_RATE_CONTROL_AUTO ||
arsta->noack[i] == WMI_PEER_TID_CONFIG_NOACK ||
arvif->noack[i] == WMI_PEER_TID_CONFIG_NOACK) {
arg.rate_ctrl = 0;
arg.rcode_flags = 0;
} else {
arg.rate_ctrl = arvif->rate_ctrl[i];
arg.rcode_flags = arvif->rate_code[i];
config_apply = true;
}
}
if (changed & BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL)) {
if (arsta->rtscts[i]) {
arg.rtscts_ctrl = 0;
arg.ext_tid_cfg_bitmap = 0;
} else {
arg.rtscts_ctrl = arvif->rtscts[i] - 1;
arg.ext_tid_cfg_bitmap =
WMI_EXT_TID_RTS_CTS_CONFIG;
config_apply = true;
}
}
arg.tid = i;
if (config_apply) {
ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, &arg);
if (ret)
ath10k_warn(ar, "failed to set per tid config for sta %pM: %d\n",
sta->addr, ret);
}
arg.ack_policy = 0;
arg.retry_count = 0;
arg.aggr_control = 0;
arg.rate_ctrl = 0;
arg.rcode_flags = 0;
}
exit:
mutex_unlock(&ar->conf_mutex);
}
static void ath10k_mac_vif_stations_tid_conf(void *data,
struct ieee80211_sta *sta)
{
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
struct ath10k_mac_iter_tid_conf_data *iter_data = data;
struct ieee80211_vif *sta_vif = arsta->arvif->vif;
if (sta_vif != iter_data->curr_vif || !sta->wme)
return;
ieee80211_queue_work(iter_data->ar->hw, &arsta->tid_config_wk);
}
static int ath10k_sta_state(struct ieee80211_hw *hw, static int ath10k_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
@ -6616,6 +7279,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
arsta->arvif = arvif; arsta->arvif = arvif;
arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED; arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk); INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk);
INIT_WORK(&arsta->tid_config_wk, ath10k_sta_tid_cfg_wk);
for (i = 0; i < ARRAY_SIZE(sta->txq); i++) for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
ath10k_mac_txq_init(sta->txq[i]); ath10k_mac_txq_init(sta->txq[i]);
@ -6623,8 +7287,10 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
/* cancel must be done outside the mutex to avoid deadlock */ /* cancel must be done outside the mutex to avoid deadlock */
if ((old_state == IEEE80211_STA_NONE && if ((old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST)) new_state == IEEE80211_STA_NOTEXIST)) {
cancel_work_sync(&arsta->update_wk); cancel_work_sync(&arsta->update_wk);
cancel_work_sync(&arsta->tid_config_wk);
}
mutex_lock(&ar->conf_mutex); mutex_lock(&ar->conf_mutex);
@ -7033,8 +7699,6 @@ exit:
return ret; return ret;
} }
#define ATH10K_ROC_TIMEOUT_HZ (2 * HZ)
static int ath10k_remain_on_channel(struct ieee80211_hw *hw, static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
@ -7346,30 +8010,6 @@ exit:
return ret; return ret;
} }
static bool
ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar,
enum nl80211_band band,
const struct cfg80211_bitrate_mask *mask,
int *vht_num_rates)
{
int num_rates = 0;
int i, tmp;
num_rates += hweight32(mask->control[band].legacy);
for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
num_rates += hweight8(mask->control[band].ht_mcs[i]);
*vht_num_rates = 0;
for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
tmp = hweight16(mask->control[band].vht_mcs[i]);
num_rates += tmp;
*vht_num_rates += tmp;
}
return num_rates == 1;
}
static bool static bool
ath10k_mac_bitrate_mask_get_single_nss(struct ath10k *ar, ath10k_mac_bitrate_mask_get_single_nss(struct ath10k *ar,
enum nl80211_band band, enum nl80211_band band,
@ -7419,69 +8059,6 @@ ath10k_mac_bitrate_mask_get_single_nss(struct ath10k *ar,
return true; return true;
} }
static int
ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
enum nl80211_band band,
const struct cfg80211_bitrate_mask *mask,
u8 *rate, u8 *nss, bool vht_only)
{
int rate_idx;
int i;
u16 bitrate;
u8 preamble;
u8 hw_rate;
if (vht_only)
goto next;
if (hweight32(mask->control[band].legacy) == 1) {
rate_idx = ffs(mask->control[band].legacy) - 1;
if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY)
rate_idx += ATH10K_MAC_FIRST_OFDM_RATE_IDX;
hw_rate = ath10k_wmi_legacy_rates[rate_idx].hw_value;
bitrate = ath10k_wmi_legacy_rates[rate_idx].bitrate;
if (ath10k_mac_bitrate_is_cck(bitrate))
preamble = WMI_RATE_PREAMBLE_CCK;
else
preamble = WMI_RATE_PREAMBLE_OFDM;
*nss = 1;
*rate = preamble << 6 |
(*nss - 1) << 4 |
hw_rate << 0;
return 0;
}
for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
if (hweight8(mask->control[band].ht_mcs[i]) == 1) {
*nss = i + 1;
*rate = WMI_RATE_PREAMBLE_HT << 6 |
(*nss - 1) << 4 |
(ffs(mask->control[band].ht_mcs[i]) - 1);
return 0;
}
}
next:
for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
*nss = i + 1;
*rate = WMI_RATE_PREAMBLE_VHT << 6 |
(*nss - 1) << 4 |
(ffs(mask->control[band].vht_mcs[i]) - 1);
return 0;
}
}
return -EINVAL;
}
static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif, static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif,
u8 rate, u8 nss, u8 sgi, u8 ldpc) u8 rate, u8 nss, u8 sgi, u8 ldpc)
{ {
@ -8567,6 +9144,76 @@ static void ath10k_sta_statistics(struct ieee80211_hw *hw,
ath10k_mac_sta_get_peer_stats_info(ar, sta, sinfo); ath10k_mac_sta_get_peer_stats_info(ar, sta, sinfo);
} }
static int ath10k_mac_op_set_tid_config(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct cfg80211_tid_config *tid_config)
{
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_mac_iter_tid_conf_data data = {};
struct wmi_per_peer_per_tid_cfg_arg arg = {};
int ret, i;
mutex_lock(&ar->conf_mutex);
arg.vdev_id = arvif->vdev_id;
arvif->tids_rst = 0;
memset(arvif->tid_conf_changed, 0, sizeof(arvif->tid_conf_changed));
for (i = 0; i < tid_config->n_tid_conf; i++) {
ret = ath10k_mac_parse_tid_config(ar, sta, vif,
&tid_config->tid_conf[i],
&arg);
if (ret)
goto exit;
}
if (sta)
goto exit;
ret = 0;
arvif->tids_rst = 0;
data.curr_vif = vif;
data.ar = ar;
ieee80211_iterate_stations_atomic(hw, ath10k_mac_vif_stations_tid_conf,
&data);
exit:
mutex_unlock(&ar->conf_mutex);
return ret;
}
static int ath10k_mac_op_reset_tid_config(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
u8 tids)
{
struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_mac_iter_tid_conf_data data = {};
struct ath10k *ar = hw->priv;
int ret = 0;
mutex_lock(&ar->conf_mutex);
if (sta) {
arvif->tids_rst = 0;
ret = ath10k_mac_reset_tid_config(ar, sta, arvif, tids);
goto exit;
}
arvif->tids_rst = tids;
data.curr_vif = vif;
data.ar = ar;
ieee80211_iterate_stations_atomic(hw, ath10k_mac_vif_stations_tid_conf,
&data);
exit:
mutex_unlock(&ar->conf_mutex);
return ret;
}
static const struct ieee80211_ops ath10k_ops = { static const struct ieee80211_ops ath10k_ops = {
.tx = ath10k_mac_op_tx, .tx = ath10k_mac_op_tx,
.wake_tx_queue = ath10k_mac_op_wake_tx_queue, .wake_tx_queue = ath10k_mac_op_wake_tx_queue,
@ -8610,6 +9257,8 @@ static const struct ieee80211_ops ath10k_ops = {
.switch_vif_chanctx = ath10k_mac_op_switch_vif_chanctx, .switch_vif_chanctx = ath10k_mac_op_switch_vif_chanctx,
.sta_pre_rcu_remove = ath10k_mac_op_sta_pre_rcu_remove, .sta_pre_rcu_remove = ath10k_mac_op_sta_pre_rcu_remove,
.sta_statistics = ath10k_sta_statistics, .sta_statistics = ath10k_sta_statistics,
.set_tid_config = ath10k_mac_op_set_tid_config,
.reset_tid_config = ath10k_mac_op_reset_tid_config,
CFG80211_TESTMODE_CMD(ath10k_tm_cmd) CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
@ -9280,6 +9929,28 @@ int ath10k_mac_register(struct ath10k *ar)
if (test_bit(WMI_SERVICE_TX_PWR_PER_PEER, ar->wmi.svc_map)) if (test_bit(WMI_SERVICE_TX_PWR_PER_PEER, ar->wmi.svc_map))
wiphy_ext_feature_set(ar->hw->wiphy, wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_STA_TX_PWR); NL80211_EXT_FEATURE_STA_TX_PWR);
if (test_bit(WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, ar->wmi.svc_map)) {
ar->hw->wiphy->tid_config_support.vif |=
BIT(NL80211_TID_CONFIG_ATTR_NOACK) |
BIT(NL80211_TID_CONFIG_ATTR_RETRY_SHORT) |
BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG) |
BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL) |
BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) |
BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE);
if (test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
ar->wmi.svc_map)) {
ar->hw->wiphy->tid_config_support.vif |=
BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL);
}
ar->hw->wiphy->tid_config_support.peer =
ar->hw->wiphy->tid_config_support.vif;
ar->hw->wiphy->max_data_retry_count = ATH10K_MAX_RETRY_COUNT;
} else {
ar->ops->set_tid_config = NULL;
}
/* /*
* on LL hardware queues are managed entirely by the FW * on LL hardware queues are managed entirely by the FW
* so we only advertise to mac we can do the queues thing * so we only advertise to mac we can do the queues thing

View file

@ -23,6 +23,9 @@
#include "targaddrs.h" #include "targaddrs.h"
#include "trace.h" #include "trace.h"
#include "sdio.h" #include "sdio.h"
#include "coredump.h"
void ath10k_sdio_fw_crashed_dump(struct ath10k *ar);
#define ATH10K_SDIO_VSG_BUF_SIZE (64 * 1024) #define ATH10K_SDIO_VSG_BUF_SIZE (64 * 1024)
@ -916,10 +919,9 @@ static int ath10k_sdio_mbox_proc_cpu_intr(struct ath10k *ar)
out: out:
mutex_unlock(&irq_data->mtx); mutex_unlock(&irq_data->mtx);
if (cpu_int_status & MBOX_CPU_STATUS_ENABLE_ASSERT_MASK) { if (cpu_int_status & MBOX_CPU_STATUS_ENABLE_ASSERT_MASK)
ath10k_err(ar, "firmware crashed!\n"); ath10k_sdio_fw_crashed_dump(ar);
queue_work(ar->workqueue, &ar->restart_work);
}
return ret; return ret;
} }
@ -2185,6 +2187,323 @@ static int ath10k_sdio_napi_poll(struct napi_struct *ctx, int budget)
return done; return done;
} }
static int ath10k_sdio_read_host_interest_value(struct ath10k *ar,
u32 item_offset,
u32 *val)
{
u32 addr;
int ret;
addr = host_interest_item_address(item_offset);
ret = ath10k_sdio_diag_read32(ar, addr, val);
if (ret)
ath10k_warn(ar, "unable to read host interest offset %d value\n",
item_offset);
return ret;
}
static int ath10k_sdio_read_mem(struct ath10k *ar, u32 address, void *buf,
u32 buf_len)
{
u32 val;
int i, ret;
for (i = 0; i < buf_len; i += 4) {
ret = ath10k_sdio_diag_read32(ar, address + i, &val);
if (ret) {
ath10k_warn(ar, "unable to read mem %d value\n", address + i);
break;
}
memcpy(buf + i, &val, 4);
}
return ret;
}
static bool ath10k_sdio_is_fast_dump_supported(struct ath10k *ar)
{
u32 param;
ath10k_sdio_read_host_interest_value(ar, HI_ITEM(hi_option_flag2), &param);
ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio hi_option_flag2 %x\n", param);
return param & HI_OPTION_SDIO_CRASH_DUMP_ENHANCEMENT_FW;
}
static void ath10k_sdio_dump_registers(struct ath10k *ar,
struct ath10k_fw_crash_data *crash_data,
bool fast_dump)
{
u32 reg_dump_values[REG_DUMP_COUNT_QCA988X] = {};
int i, ret;
u32 reg_dump_area;
ret = ath10k_sdio_read_host_interest_value(ar, HI_ITEM(hi_failure_state),
&reg_dump_area);
if (ret) {
ath10k_warn(ar, "failed to read firmware dump area: %d\n", ret);
return;
}
if (fast_dump)
ret = ath10k_bmi_read_memory(ar, reg_dump_area, reg_dump_values,
sizeof(reg_dump_values));
else
ret = ath10k_sdio_read_mem(ar, reg_dump_area, reg_dump_values,
sizeof(reg_dump_values));
if (ret) {
ath10k_warn(ar, "failed to read firmware dump value: %d\n", ret);
return;
}
ath10k_err(ar, "firmware register dump:\n");
for (i = 0; i < ARRAY_SIZE(reg_dump_values); i += 4)
ath10k_err(ar, "[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X\n",
i,
reg_dump_values[i],
reg_dump_values[i + 1],
reg_dump_values[i + 2],
reg_dump_values[i + 3]);
if (!crash_data)
return;
for (i = 0; i < ARRAY_SIZE(reg_dump_values); i++)
crash_data->registers[i] = __cpu_to_le32(reg_dump_values[i]);
}
static int ath10k_sdio_dump_memory_section(struct ath10k *ar,
const struct ath10k_mem_region *mem_region,
u8 *buf, size_t buf_len)
{
const struct ath10k_mem_section *cur_section, *next_section;
unsigned int count, section_size, skip_size;
int ret, i, j;
if (!mem_region || !buf)
return 0;
cur_section = &mem_region->section_table.sections[0];
if (mem_region->start > cur_section->start) {
ath10k_warn(ar, "incorrect memdump region 0x%x with section start address 0x%x.\n",
mem_region->start, cur_section->start);
return 0;
}
skip_size = cur_section->start - mem_region->start;
/* fill the gap between the first register section and register
* start address
*/
for (i = 0; i < skip_size; i++) {
*buf = ATH10K_MAGIC_NOT_COPIED;
buf++;
}
count = 0;
for (i = 0; cur_section; i++) {
section_size = cur_section->end - cur_section->start;
if (section_size <= 0) {
ath10k_warn(ar, "incorrect ramdump format with start address 0x%x and stop address 0x%x\n",
cur_section->start,
cur_section->end);
break;
}
if ((i + 1) == mem_region->section_table.size) {
/* last section */
next_section = NULL;
skip_size = 0;
} else {
next_section = cur_section + 1;
if (cur_section->end > next_section->start) {
ath10k_warn(ar, "next ramdump section 0x%x is smaller than current end address 0x%x\n",
next_section->start,
cur_section->end);
break;
}
skip_size = next_section->start - cur_section->end;
}
if (buf_len < (skip_size + section_size)) {
ath10k_warn(ar, "ramdump buffer is too small: %zu\n", buf_len);
break;
}
buf_len -= skip_size + section_size;
/* read section to dest memory */
ret = ath10k_sdio_read_mem(ar, cur_section->start,
buf, section_size);
if (ret) {
ath10k_warn(ar, "failed to read ramdump from section 0x%x: %d\n",
cur_section->start, ret);
break;
}
buf += section_size;
count += section_size;
/* fill in the gap between this section and the next */
for (j = 0; j < skip_size; j++) {
*buf = ATH10K_MAGIC_NOT_COPIED;
buf++;
}
count += skip_size;
if (!next_section)
/* this was the last section */
break;
cur_section = next_section;
}
return count;
}
/* if an error happened returns < 0, otherwise the length */
static int ath10k_sdio_dump_memory_generic(struct ath10k *ar,
const struct ath10k_mem_region *current_region,
u8 *buf,
bool fast_dump)
{
int ret;
if (current_region->section_table.size > 0)
/* Copy each section individually. */
return ath10k_sdio_dump_memory_section(ar,
current_region,
buf,
current_region->len);
/* No individiual memory sections defined so we can
* copy the entire memory region.
*/
if (fast_dump)
ret = ath10k_bmi_read_memory(ar,
current_region->start,
buf,
current_region->len);
else
ret = ath10k_sdio_read_mem(ar,
current_region->start,
buf,
current_region->len);
if (ret) {
ath10k_warn(ar, "failed to copy ramdump region %s: %d\n",
current_region->name, ret);
return ret;
}
return current_region->len;
}
static void ath10k_sdio_dump_memory(struct ath10k *ar,
struct ath10k_fw_crash_data *crash_data,
bool fast_dump)
{
const struct ath10k_hw_mem_layout *mem_layout;
const struct ath10k_mem_region *current_region;
struct ath10k_dump_ram_data_hdr *hdr;
u32 count;
size_t buf_len;
int ret, i;
u8 *buf;
if (!crash_data)
return;
mem_layout = ath10k_coredump_get_mem_layout(ar);
if (!mem_layout)
return;
current_region = &mem_layout->region_table.regions[0];
buf = crash_data->ramdump_buf;
buf_len = crash_data->ramdump_buf_len;
memset(buf, 0, buf_len);
for (i = 0; i < mem_layout->region_table.size; i++) {
count = 0;
if (current_region->len > buf_len) {
ath10k_warn(ar, "memory region %s size %d is larger that remaining ramdump buffer size %zu\n",
current_region->name,
current_region->len,
buf_len);
break;
}
/* Reserve space for the header. */
hdr = (void *)buf;
buf += sizeof(*hdr);
buf_len -= sizeof(*hdr);
ret = ath10k_sdio_dump_memory_generic(ar, current_region, buf,
fast_dump);
if (ret >= 0)
count = ret;
hdr->region_type = cpu_to_le32(current_region->type);
hdr->start = cpu_to_le32(current_region->start);
hdr->length = cpu_to_le32(count);
if (count == 0)
/* Note: the header remains, just with zero length. */
break;
buf += count;
buf_len -= count;
current_region++;
}
}
void ath10k_sdio_fw_crashed_dump(struct ath10k *ar)
{
struct ath10k_fw_crash_data *crash_data;
char guid[UUID_STRING_LEN + 1];
bool fast_dump;
fast_dump = ath10k_sdio_is_fast_dump_supported(ar);
if (fast_dump)
ath10k_bmi_start(ar);
ar->stats.fw_crash_counter++;
ath10k_sdio_disable_intrs(ar);
crash_data = ath10k_coredump_new(ar);
if (crash_data)
scnprintf(guid, sizeof(guid), "%pUl", &crash_data->guid);
else
scnprintf(guid, sizeof(guid), "n/a");
ath10k_err(ar, "firmware crashed! (guid %s)\n", guid);
ath10k_print_driver_info(ar);
ath10k_sdio_dump_registers(ar, crash_data, fast_dump);
ath10k_sdio_dump_memory(ar, crash_data, fast_dump);
ath10k_sdio_enable_intrs(ar);
queue_work(ar->workqueue, &ar->restart_work);
}
static int ath10k_sdio_probe(struct sdio_func *func, static int ath10k_sdio_probe(struct sdio_func *func,
const struct sdio_device_id *id) const struct sdio_device_id *id)
{ {

View file

@ -3,6 +3,7 @@
* Copyright (c) 2018 The Linux Foundation. All rights reserved. * Copyright (c) 2018 The Linux Foundation. All rights reserved.
*/ */
#include <linux/bits.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
@ -45,6 +46,7 @@ static const char * const ath10k_regulators[] = {
"vdd-1.8-xo", "vdd-1.8-xo",
"vdd-1.3-rfa", "vdd-1.3-rfa",
"vdd-3.3-ch0", "vdd-3.3-ch0",
"vdd-3.3-ch1",
}; };
static const char * const ath10k_clocks[] = { static const char * const ath10k_clocks[] = {
@ -923,6 +925,7 @@ static int ath10k_snoc_hif_start(struct ath10k *ar)
{ {
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
bitmap_clear(ar_snoc->pending_ce_irqs, 0, CE_COUNT_MAX);
napi_enable(&ar->napi); napi_enable(&ar->napi);
ath10k_snoc_irq_enable(ar); ath10k_snoc_irq_enable(ar);
ath10k_snoc_rx_post(ar); ath10k_snoc_rx_post(ar);
@ -1158,7 +1161,9 @@ static irqreturn_t ath10k_snoc_per_engine_handler(int irq, void *arg)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
ath10k_snoc_irq_disable(ar); ath10k_ce_disable_interrupt(ar, ce_id);
set_bit(ce_id, ar_snoc->pending_ce_irqs);
napi_schedule(&ar->napi); napi_schedule(&ar->napi);
return IRQ_HANDLED; return IRQ_HANDLED;
@ -1167,20 +1172,25 @@ static irqreturn_t ath10k_snoc_per_engine_handler(int irq, void *arg)
static int ath10k_snoc_napi_poll(struct napi_struct *ctx, int budget) static int ath10k_snoc_napi_poll(struct napi_struct *ctx, int budget)
{ {
struct ath10k *ar = container_of(ctx, struct ath10k, napi); struct ath10k *ar = container_of(ctx, struct ath10k, napi);
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
int done = 0; int done = 0;
int ce_id;
if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) { if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) {
napi_complete(ctx); napi_complete(ctx);
return done; return done;
} }
ath10k_ce_per_engine_service_any(ar); for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
if (test_and_clear_bit(ce_id, ar_snoc->pending_ce_irqs)) {
ath10k_ce_per_engine_service(ar, ce_id);
ath10k_ce_enable_interrupt(ar, ce_id);
}
done = ath10k_htt_txrx_compl_task(ar, budget); done = ath10k_htt_txrx_compl_task(ar, budget);
if (done < budget) { if (done < budget)
napi_complete(ctx); napi_complete(ctx);
ath10k_snoc_irq_enable(ar);
}
return done; return done;
} }

View file

@ -78,6 +78,7 @@ struct ath10k_snoc {
unsigned long flags; unsigned long flags;
bool xo_cal_supported; bool xo_cal_supported;
u32 xo_cal_data; u32 xo_cal_data;
DECLARE_BITMAP(pending_ce_irqs, CE_COUNT_MAX);
}; };
static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar) static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)

View file

@ -333,6 +333,17 @@ struct host_interest {
#define HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_FW_ACK (1 << 16) #define HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_FW_ACK (1 << 16)
#define HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_FW_ACK (1 << 17) #define HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_FW_ACK (1 << 17)
/*
* If both SDIO_CRASH_DUMP_ENHANCEMENT_HOST and SDIO_CRASH_DUMP_ENHANCEMENT_FW
* flags are set, then crashdump upload will be done using the BMI host/target
* communication channel.
*/
/* HOST to support using BMI dump FW memory when hit assert */
#define HI_OPTION_SDIO_CRASH_DUMP_ENHANCEMENT_HOST 0x400
/* FW to support using BMI dump FW memory when hit assert */
#define HI_OPTION_SDIO_CRASH_DUMP_ENHANCEMENT_FW 0x800
/* /*
* CONSOLE FLAGS * CONSOLE FLAGS
* *

View file

@ -50,6 +50,7 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
struct ath10k_skb_cb *skb_cb; struct ath10k_skb_cb *skb_cb;
struct ath10k_txq *artxq; struct ath10k_txq *artxq;
struct sk_buff *msdu; struct sk_buff *msdu;
u8 flags;
ath10k_dbg(ar, ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt tx completion msdu_id %u status %d\n", "htt tx completion msdu_id %u status %d\n",
@ -78,6 +79,7 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
artxq->num_fw_queued--; artxq->num_fw_queued--;
} }
flags = skb_cb->flags;
ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
ath10k_htt_tx_dec_pending(htt); ath10k_htt_tx_dec_pending(htt);
if (htt->num_pending_tx == 0) if (htt->num_pending_tx == 0)
@ -101,18 +103,21 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id); trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id);
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
!(flags & ATH10K_SKB_F_NOACK_TID))
info->flags |= IEEE80211_TX_STAT_ACK; info->flags |= IEEE80211_TX_STAT_ACK;
if (tx_done->status == HTT_TX_COMPL_STATE_NOACK) if (tx_done->status == HTT_TX_COMPL_STATE_NOACK)
info->flags &= ~IEEE80211_TX_STAT_ACK; info->flags &= ~IEEE80211_TX_STAT_ACK;
if ((tx_done->status == HTT_TX_COMPL_STATE_ACK) && if ((tx_done->status == HTT_TX_COMPL_STATE_ACK) &&
(info->flags & IEEE80211_TX_CTL_NO_ACK)) ((info->flags & IEEE80211_TX_CTL_NO_ACK) ||
(flags & ATH10K_SKB_F_NOACK_TID)))
info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
if (tx_done->status == HTT_TX_COMPL_STATE_DISCARD) { if (tx_done->status == HTT_TX_COMPL_STATE_DISCARD) {
if (info->flags & IEEE80211_TX_CTL_NO_ACK) if ((info->flags & IEEE80211_TX_CTL_NO_ACK) ||
(flags & ATH10K_SKB_F_NOACK_TID))
info->flags &= ~IEEE80211_TX_STAT_NOACK_TRANSMITTED; info->flags &= ~IEEE80211_TX_STAT_NOACK_TRANSMITTED;
else else
info->flags &= ~IEEE80211_TX_STAT_ACK; info->flags &= ~IEEE80211_TX_STAT_ACK;

View file

@ -224,6 +224,8 @@ struct wmi_ops {
struct sk_buff *(*gen_bb_timing) struct sk_buff *(*gen_bb_timing)
(struct ath10k *ar, (struct ath10k *ar,
const struct wmi_bb_timing_cfg_arg *arg); const struct wmi_bb_timing_cfg_arg *arg);
struct sk_buff *(*gen_per_peer_per_tid_cfg)(struct ath10k *ar,
const struct wmi_per_peer_per_tid_cfg_arg *arg);
}; };
@ -1656,4 +1658,21 @@ ath10k_wmi_pdev_bb_timing(struct ath10k *ar,
return ath10k_wmi_cmd_send(ar, skb, return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->set_bb_timing_cmdid); ar->wmi.cmd->set_bb_timing_cmdid);
} }
static inline int
ath10k_wmi_set_per_peer_per_tid_cfg(struct ath10k *ar,
const struct wmi_per_peer_per_tid_cfg_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_per_peer_per_tid_cfg)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_per_peer_per_tid_cfg(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->per_peer_per_tid_config_cmdid);
}
#endif #endif

View file

@ -740,6 +740,7 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = {
.tdls_peer_update_cmdid = WMI_10_4_TDLS_PEER_UPDATE_CMDID, .tdls_peer_update_cmdid = WMI_10_4_TDLS_PEER_UPDATE_CMDID,
.tdls_set_offchan_mode_cmdid = WMI_10_4_TDLS_SET_OFFCHAN_MODE_CMDID, .tdls_set_offchan_mode_cmdid = WMI_10_4_TDLS_SET_OFFCHAN_MODE_CMDID,
.radar_found_cmdid = WMI_10_4_RADAR_FOUND_CMDID, .radar_found_cmdid = WMI_10_4_RADAR_FOUND_CMDID,
.per_peer_per_tid_config_cmdid = WMI_10_4_PER_PEER_PER_TID_CONFIG_CMDID,
}; };
static struct wmi_peer_param_map wmi_peer_param_map = { static struct wmi_peer_param_map wmi_peer_param_map = {
@ -6551,7 +6552,7 @@ static struct sk_buff *ath10k_wmi_op_gen_init(struct ath10k *ar)
struct wmi_init_cmd *cmd; struct wmi_init_cmd *cmd;
struct sk_buff *buf; struct sk_buff *buf;
struct wmi_resource_config config = {}; struct wmi_resource_config config = {};
u32 len, val; u32 val;
config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS); config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS);
config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS); config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS);
@ -6603,10 +6604,8 @@ static struct sk_buff *ath10k_wmi_op_gen_init(struct ath10k *ar)
config.num_msdu_desc = __cpu_to_le32(TARGET_NUM_MSDU_DESC); config.num_msdu_desc = __cpu_to_le32(TARGET_NUM_MSDU_DESC);
config.max_frag_entries = __cpu_to_le32(TARGET_MAX_FRAG_ENTRIES); config.max_frag_entries = __cpu_to_le32(TARGET_MAX_FRAG_ENTRIES);
len = sizeof(*cmd) + buf = ath10k_wmi_alloc_skb(ar, struct_size(cmd, mem_chunks.items,
(sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks); ar->wmi.num_mem_chunks));
buf = ath10k_wmi_alloc_skb(ar, len);
if (!buf) if (!buf)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -6624,7 +6623,7 @@ static struct sk_buff *ath10k_wmi_10_1_op_gen_init(struct ath10k *ar)
struct wmi_init_cmd_10x *cmd; struct wmi_init_cmd_10x *cmd;
struct sk_buff *buf; struct sk_buff *buf;
struct wmi_resource_config_10x config = {}; struct wmi_resource_config_10x config = {};
u32 len, val; u32 val;
config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
@ -6668,10 +6667,8 @@ static struct sk_buff *ath10k_wmi_10_1_op_gen_init(struct ath10k *ar)
config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC); config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC);
config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES); config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES);
len = sizeof(*cmd) + buf = ath10k_wmi_alloc_skb(ar, struct_size(cmd, mem_chunks.items,
(sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks); ar->wmi.num_mem_chunks));
buf = ath10k_wmi_alloc_skb(ar, len);
if (!buf) if (!buf)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -6689,7 +6686,7 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
struct wmi_init_cmd_10_2 *cmd; struct wmi_init_cmd_10_2 *cmd;
struct sk_buff *buf; struct sk_buff *buf;
struct wmi_resource_config_10x config = {}; struct wmi_resource_config_10x config = {};
u32 len, val, features; u32 val, features;
config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS); config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS);
@ -6741,10 +6738,8 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC); config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC);
config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES); config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES);
len = sizeof(*cmd) + buf = ath10k_wmi_alloc_skb(ar, struct_size(cmd, mem_chunks.items,
(sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks); ar->wmi.num_mem_chunks));
buf = ath10k_wmi_alloc_skb(ar, len);
if (!buf) if (!buf)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -6776,7 +6771,6 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar)
struct wmi_init_cmd_10_4 *cmd; struct wmi_init_cmd_10_4 *cmd;
struct sk_buff *buf; struct sk_buff *buf;
struct wmi_resource_config_10_4 config = {}; struct wmi_resource_config_10_4 config = {};
u32 len;
config.num_vdevs = __cpu_to_le32(ar->max_num_vdevs); config.num_vdevs = __cpu_to_le32(ar->max_num_vdevs);
config.num_peers = __cpu_to_le32(ar->max_num_peers); config.num_peers = __cpu_to_le32(ar->max_num_peers);
@ -6838,10 +6832,8 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar)
config.iphdr_pad_config = __cpu_to_le32(TARGET_10_4_IPHDR_PAD_CONFIG); config.iphdr_pad_config = __cpu_to_le32(TARGET_10_4_IPHDR_PAD_CONFIG);
config.qwrap_config = __cpu_to_le32(TARGET_10_4_QWRAP_CONFIG); config.qwrap_config = __cpu_to_le32(TARGET_10_4_QWRAP_CONFIG);
len = sizeof(*cmd) + buf = ath10k_wmi_alloc_skb(ar, struct_size(cmd, mem_chunks.items,
(sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks); ar->wmi.num_mem_chunks));
buf = ath10k_wmi_alloc_skb(ar, len);
if (!buf) if (!buf)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -7549,12 +7541,9 @@ ath10k_wmi_op_gen_scan_chan_list(struct ath10k *ar,
struct sk_buff *skb; struct sk_buff *skb;
struct wmi_channel_arg *ch; struct wmi_channel_arg *ch;
struct wmi_channel *ci; struct wmi_channel *ci;
int len;
int i; int i;
len = sizeof(*cmd) + arg->n_channels * sizeof(struct wmi_channel); skb = ath10k_wmi_alloc_skb(ar, struct_size(cmd, chan_info, arg->n_channels));
skb = ath10k_wmi_alloc_skb(ar, len);
if (!skb) if (!skb)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
@ -9004,6 +8993,39 @@ ath10k_wmi_10_4_gen_radar_found(struct ath10k *ar,
return skb; return skb;
} }
static struct sk_buff *
ath10k_wmi_10_4_gen_per_peer_per_tid_cfg(struct ath10k *ar,
const struct wmi_per_peer_per_tid_cfg_arg *arg)
{
struct wmi_peer_per_tid_cfg_cmd *cmd;
struct sk_buff *skb;
skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
if (!skb)
return ERR_PTR(-ENOMEM);
memset(skb->data, 0, sizeof(*cmd));
cmd = (struct wmi_peer_per_tid_cfg_cmd *)skb->data;
cmd->vdev_id = cpu_to_le32(arg->vdev_id);
ether_addr_copy(cmd->peer_macaddr.addr, arg->peer_macaddr.addr);
cmd->tid = cpu_to_le32(arg->tid);
cmd->ack_policy = cpu_to_le32(arg->ack_policy);
cmd->aggr_control = cpu_to_le32(arg->aggr_control);
cmd->rate_control = cpu_to_le32(arg->rate_ctrl);
cmd->retry_count = cpu_to_le32(arg->retry_count);
cmd->rcode_flags = cpu_to_le32(arg->rcode_flags);
cmd->ext_tid_cfg_bitmap = cpu_to_le32(arg->ext_tid_cfg_bitmap);
cmd->rtscts_ctrl = cpu_to_le32(arg->rtscts_ctrl);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi noack tid %d vdev id %d ack_policy %d aggr %u rate_ctrl %u rcflag %u retry_count %d rtscts %d ext_tid_cfg_bitmap %d mac_addr %pM\n",
arg->tid, arg->vdev_id, arg->ack_policy, arg->aggr_control,
arg->rate_ctrl, arg->rcode_flags, arg->retry_count,
arg->rtscts_ctrl, arg->ext_tid_cfg_bitmap, arg->peer_macaddr.addr);
return skb;
}
static struct sk_buff * static struct sk_buff *
ath10k_wmi_op_gen_echo(struct ath10k *ar, u32 value) ath10k_wmi_op_gen_echo(struct ath10k *ar, u32 value)
{ {
@ -9413,6 +9435,7 @@ static const struct wmi_ops wmi_10_4_ops = {
.gen_pdev_get_tpc_table_cmdid = .gen_pdev_get_tpc_table_cmdid =
ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid, ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid,
.gen_radar_found = ath10k_wmi_10_4_gen_radar_found, .gen_radar_found = ath10k_wmi_10_4_gen_radar_found,
.gen_per_peer_per_tid_cfg = ath10k_wmi_10_4_gen_per_peer_per_tid_cfg,
/* shared with 10.2 */ /* shared with 10.2 */
.pull_echo_ev = ath10k_wmi_op_pull_echo_ev, .pull_echo_ev = ath10k_wmi_op_pull_echo_ev,

View file

@ -203,6 +203,8 @@ enum wmi_service {
WMI_SERVICE_SYNC_DELETE_CMDS, WMI_SERVICE_SYNC_DELETE_CMDS,
WMI_SERVICE_TX_PWR_PER_PEER, WMI_SERVICE_TX_PWR_PER_PEER,
WMI_SERVICE_SUPPORT_EXTEND_ADDRESS, WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT,
WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
/* Remember to add the new value to wmi_service_name()! */ /* Remember to add the new value to wmi_service_name()! */
@ -503,6 +505,8 @@ static inline char *wmi_service_name(enum wmi_service service_id)
SVCSTR(WMI_SERVICE_SYNC_DELETE_CMDS); SVCSTR(WMI_SERVICE_SYNC_DELETE_CMDS);
SVCSTR(WMI_SERVICE_TX_PWR_PER_PEER); SVCSTR(WMI_SERVICE_TX_PWR_PER_PEER);
SVCSTR(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS); SVCSTR(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS);
SVCSTR(WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT);
SVCSTR(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT);
case WMI_SERVICE_MAX: case WMI_SERVICE_MAX:
return NULL; return NULL;
@ -834,6 +838,10 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
WMI_SERVICE_TX_PWR_PER_PEER, len); WMI_SERVICE_TX_PWR_PER_PEER, len);
SVCMAP(WMI_10_4_SERVICE_RESET_CHIP, SVCMAP(WMI_10_4_SERVICE_RESET_CHIP,
WMI_SERVICE_RESET_CHIP, len); WMI_SERVICE_RESET_CHIP, len);
SVCMAP(WMI_10_4_SERVICE_PEER_TID_CONFIGS_SUPPORT,
WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, len);
SVCMAP(WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, len);
} }
#undef SVCMAP #undef SVCMAP
@ -1036,6 +1044,7 @@ struct wmi_cmd_map {
u32 tdls_set_offchan_mode_cmdid; u32 tdls_set_offchan_mode_cmdid;
u32 radar_found_cmdid; u32 radar_found_cmdid;
u32 set_bb_timing_cmdid; u32 set_bb_timing_cmdid;
u32 per_peer_per_tid_config_cmdid;
}; };
/* /*
@ -1877,6 +1886,8 @@ enum wmi_10_4_cmd_id {
WMI_10_4_PDEV_SET_BRIDGE_MACADDR_CMDID, WMI_10_4_PDEV_SET_BRIDGE_MACADDR_CMDID,
WMI_10_4_ATF_GROUP_WMM_AC_CONFIG_REQUEST_CMDID, WMI_10_4_ATF_GROUP_WMM_AC_CONFIG_REQUEST_CMDID,
WMI_10_4_RADAR_FOUND_CMDID, WMI_10_4_RADAR_FOUND_CMDID,
WMI_10_4_PEER_CFR_CAPTURE_CMDID,
WMI_10_4_PER_PEER_PER_TID_CONFIG_CMDID,
WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1, WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1,
}; };
@ -7220,6 +7231,71 @@ struct wmi_tdls_peer_event {
__le32 vdev_id; __le32 vdev_id;
} __packed; } __packed;
enum wmi_tid_aggr_control_conf {
WMI_TID_CONFIG_AGGR_CONTROL_IGNORE,
WMI_TID_CONFIG_AGGR_CONTROL_ENABLE,
WMI_TID_CONFIG_AGGR_CONTROL_DISABLE,
};
enum wmi_noack_tid_conf {
WMI_NOACK_TID_CONFIG_IGNORE_ACK_POLICY,
WMI_PEER_TID_CONFIG_ACK,
WMI_PEER_TID_CONFIG_NOACK,
};
enum wmi_tid_rate_ctrl_conf {
WMI_TID_CONFIG_RATE_CONTROL_IGNORE,
WMI_TID_CONFIG_RATE_CONTROL_AUTO,
WMI_TID_CONFIG_RATE_CONTROL_FIXED_RATE,
WMI_TID_CONFIG_RATE_CONTROL_DEFAULT_LOWEST_RATE,
WMI_PEER_TID_CONFIG_RATE_UPPER_CAP,
};
enum wmi_tid_rtscts_control_conf {
WMI_TID_CONFIG_RTSCTS_CONTROL_ENABLE,
WMI_TID_CONFIG_RTSCTS_CONTROL_DISABLE,
};
enum wmi_ext_tid_config_map {
WMI_EXT_TID_RTS_CTS_CONFIG = BIT(0),
};
struct wmi_per_peer_per_tid_cfg_arg {
u32 vdev_id;
struct wmi_mac_addr peer_macaddr;
u32 tid;
enum wmi_noack_tid_conf ack_policy;
enum wmi_tid_aggr_control_conf aggr_control;
u8 rate_ctrl;
u32 retry_count;
u32 rcode_flags;
u32 ext_tid_cfg_bitmap;
u32 rtscts_ctrl;
};
struct wmi_peer_per_tid_cfg_cmd {
__le32 vdev_id;
struct wmi_mac_addr peer_macaddr;
__le32 tid;
/* see enum wmi_noack_tid_conf */
__le32 ack_policy;
/* see enum wmi_tid_aggr_control_conf */
__le32 aggr_control;
/* see enum wmi_tid_rate_ctrl_conf */
__le32 rate_control;
__le32 rcode_flags;
__le32 retry_count;
/* See enum wmi_ext_tid_config_map */
__le32 ext_tid_cfg_bitmap;
/* see enum wmi_tid_rtscts_control_conf */
__le32 rtscts_ctrl;
} __packed;
enum wmi_txbf_conf { enum wmi_txbf_conf {
WMI_TXBF_CONF_UNSUPPORTED, WMI_TXBF_CONF_UNSUPPORTED,
WMI_TXBF_CONF_BEFORE_ASSOC, WMI_TXBF_CONF_BEFORE_ASSOC,

View file

@ -20,6 +20,9 @@ static const struct of_device_id ath11k_ahb_of_match[] = {
{ .compatible = "qcom,ipq8074-wifi", { .compatible = "qcom,ipq8074-wifi",
.data = (void *)ATH11K_HW_IPQ8074, .data = (void *)ATH11K_HW_IPQ8074,
}, },
{ .compatible = "qcom,ipq6018-wifi",
.data = (void *)ATH11K_HW_IPQ6018_HW10,
},
{ } { }
}; };
@ -32,245 +35,6 @@ static const struct ath11k_bus_params ath11k_ahb_bus_params = {
.fixed_mem_region = true, .fixed_mem_region = true,
}; };
/* Target firmware's Copy Engine configuration. */
static const struct ce_pipe_config target_ce_config_wlan[] = {
/* CE0: host->target HTC control and raw streams */
{
.pipenum = __cpu_to_le32(0),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE1: target->host HTT + HTC control */
{
.pipenum = __cpu_to_le32(1),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE2: target->host WMI */
{
.pipenum = __cpu_to_le32(2),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE3: host->target WMI */
{
.pipenum = __cpu_to_le32(3),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE4: host->target HTT */
{
.pipenum = __cpu_to_le32(4),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(256),
.nbytes_max = __cpu_to_le32(256),
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
.reserved = __cpu_to_le32(0),
},
/* CE5: target->host Pktlog */
{
.pipenum = __cpu_to_le32(5),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(0),
.reserved = __cpu_to_le32(0),
},
/* CE6: Reserved for target autonomous hif_memcpy */
{
.pipenum = __cpu_to_le32(6),
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(65535),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE7 used only by Host */
{
.pipenum = __cpu_to_le32(7),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE8 target->host used only by IPA */
{
.pipenum = __cpu_to_le32(8),
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(65535),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE9 host->target HTT */
{
.pipenum = __cpu_to_le32(9),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE10 target->host HTT */
{
.pipenum = __cpu_to_le32(10),
.pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
.nentries = __cpu_to_le32(0),
.nbytes_max = __cpu_to_le32(0),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE11 Not used */
{
.pipenum = __cpu_to_le32(0),
.pipedir = __cpu_to_le32(0),
.nentries = __cpu_to_le32(0),
.nbytes_max = __cpu_to_le32(0),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
};
/* Map from service/endpoint to Copy Engine.
* This table is derived from the CE_PCI TABLE, above.
* It is passed to the Target at startup for use by firmware.
*/
static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(7),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(9),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(0),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(1),
},
{ /* not used */
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(0),
},
{ /* not used */
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(1),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(4),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(1),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_PKT_LOG),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(5),
},
/* (Additions here) */
{ /* terminator entry */ }
};
#define ATH11K_IRQ_CE0_OFFSET 4 #define ATH11K_IRQ_CE0_OFFSET 4
static const char *irq_name[ATH11K_IRQ_NUM_MAX] = { static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
@ -444,7 +208,7 @@ static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
{ {
const struct ce_pipe_config *ce_config; const struct ce_pipe_config *ce_config;
ce_config = &target_ce_config_wlan[ce_id]; ce_config = &ab->hw_params.target_ce_config[ce_id];
if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT) if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS); ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
@ -459,7 +223,7 @@ static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
{ {
const struct ce_pipe_config *ce_config; const struct ce_pipe_config *ce_config;
ce_config = &target_ce_config_wlan[ce_id]; ce_config = &ab->hw_params.target_ce_config[ce_id];
if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT) if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS); ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
@ -577,10 +341,10 @@ static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
{ {
struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
cfg->tgt_ce_len = ARRAY_SIZE(target_ce_config_wlan) - 1; cfg->tgt_ce_len = ab->hw_params.target_ce_count;
cfg->tgt_ce = target_ce_config_wlan; cfg->tgt_ce = ab->hw_params.target_ce_config;
cfg->svc_to_ce_map_len = ARRAY_SIZE(target_service_to_ce_map_wlan); cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len;
cfg->svc_to_ce_map = target_service_to_ce_map_wlan; cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map;
ab->qmi.service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074; ab->qmi.service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074;
} }
@ -611,9 +375,9 @@ static void ath11k_ahb_free_irq(struct ath11k_base *ab)
ath11k_ahb_free_ext_irq(ab); ath11k_ahb_free_ext_irq(ab);
} }
static void ath11k_ahb_ce_tasklet(unsigned long data) static void ath11k_ahb_ce_tasklet(struct tasklet_struct *t)
{ {
struct ath11k_ce_pipe *ce_pipe = (struct ath11k_ce_pipe *)data; struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num); ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
@ -764,8 +528,7 @@ static int ath11k_ahb_config_irq(struct ath11k_base *ab)
irq_idx = ATH11K_IRQ_CE0_OFFSET + i; irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
tasklet_init(&ce_pipe->intr_tq, ath11k_ahb_ce_tasklet, tasklet_setup(&ce_pipe->intr_tq, ath11k_ahb_ce_tasklet);
(unsigned long)ce_pipe);
irq = platform_get_irq_byname(ab->pdev, irq_name[irq_idx]); irq = platform_get_irq_byname(ab->pdev, irq_name[irq_idx]);
ret = request_irq(irq, ath11k_ahb_ce_interrupt_handler, ret = request_irq(irq, ath11k_ahb_ce_interrupt_handler,
IRQF_TRIGGER_RISING, irq_name[irq_idx], IRQF_TRIGGER_RISING, irq_name[irq_idx],
@ -789,8 +552,8 @@ static int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id
bool ul_set = false, dl_set = false; bool ul_set = false, dl_set = false;
int i; int i;
for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) { for (i = 0; i < ab->hw_params.svc_to_ce_map_len; i++) {
entry = &target_service_to_ce_map_wlan[i]; entry = &ab->hw_params.svc_to_ce_map[i];
if (__le32_to_cpu(entry->service_id) != service_id) if (__le32_to_cpu(entry->service_id) != service_id)
continue; continue;

View file

@ -18,6 +18,16 @@ EXPORT_SYMBOL(ath11k_debug_mask);
module_param_named(debug_mask, ath11k_debug_mask, uint, 0644); module_param_named(debug_mask, ath11k_debug_mask, uint, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask"); MODULE_PARM_DESC(debug_mask, "Debugging mask");
static unsigned int ath11k_crypto_mode;
module_param_named(crypto_mode, ath11k_crypto_mode, uint, 0644);
MODULE_PARM_DESC(crypto_mode, "crypto mode: 0-hardware, 1-software");
/* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
MODULE_PARM_DESC(frame_mode,
"Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
static const struct ath11k_hw_params ath11k_hw_params[] = { static const struct ath11k_hw_params ath11k_hw_params[] = {
{ {
.hw_rev = ATH11K_HW_IPQ8074, .hw_rev = ATH11K_HW_IPQ8074,
@ -35,6 +45,39 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.regs = &ipq8074_regs, .regs = &ipq8074_regs,
.host_ce_config = ath11k_host_ce_config_ipq8074, .host_ce_config = ath11k_host_ce_config_ipq8074,
.ce_count = 12, .ce_count = 12,
.target_ce_config = ath11k_target_ce_config_wlan_ipq8074,
.target_ce_count = 11,
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq8074,
.svc_to_ce_map_len = 21,
.single_pdev_only = false,
.needs_band_to_mac = true,
.rxdma1_enable = true,
.num_rxmda_per_pdev = 1,
.rx_mac_buf_ring = false,
.vdev_start_delay = false,
.htt_peer_map_v2 = true,
.tcl_0_only = false,
},
{
.hw_rev = ATH11K_HW_IPQ6018_HW10,
.name = "ipq6018 hw1.0",
.fw = {
.dir = "IPQ6018/hw1.0",
.board_size = 256 * 1024,
.cal_size = 256 * 1024,
},
.max_radios = 2,
.bdf_addr = 0x4ABC0000,
.hw_ops = &ipq6018_ops,
.ring_mask = &ath11k_hw_ring_mask_ipq8074,
.internal_sleep_clock = false,
.regs = &ipq8074_regs,
.host_ce_config = ath11k_host_ce_config_ipq8074,
.ce_count = 12,
.target_ce_config = ath11k_target_ce_config_wlan_ipq8074,
.target_ce_count = 11,
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq6018,
.svc_to_ce_map_len = 19,
.single_pdev_only = false, .single_pdev_only = false,
.needs_band_to_mac = true, .needs_band_to_mac = true,
.rxdma1_enable = true, .rxdma1_enable = true,
@ -60,6 +103,10 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.regs = &qca6390_regs, .regs = &qca6390_regs,
.host_ce_config = ath11k_host_ce_config_qca6390, .host_ce_config = ath11k_host_ce_config_qca6390,
.ce_count = 9, .ce_count = 9,
.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
.target_ce_count = 9,
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
.svc_to_ce_map_len = 14,
.single_pdev_only = true, .single_pdev_only = true,
.needs_band_to_mac = false, .needs_band_to_mac = false,
.rxdma1_enable = false, .rxdma1_enable = false,
@ -580,6 +627,23 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
return ret; return ret;
} }
switch (ath11k_crypto_mode) {
case ATH11K_CRYPT_MODE_SW:
set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
break;
case ATH11K_CRYPT_MODE_HW:
clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
break;
default:
ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode);
return -EINVAL;
}
if (ath11k_frame_mode == ATH11K_HW_TXRX_RAW)
set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
mutex_lock(&ab->core_lock); mutex_lock(&ab->core_lock);
ret = ath11k_core_start(ab, ATH11K_FIRMWARE_MODE_NORMAL); ret = ath11k_core_start(ab, ATH11K_FIRMWARE_MODE_NORMAL);
if (ret) { if (ret) {
@ -784,6 +848,9 @@ static int ath11k_core_get_rproc(struct ath11k_base *ab)
struct rproc *prproc; struct rproc *prproc;
phandle rproc_phandle; phandle rproc_phandle;
if (!IS_ENABLED(CONFIG_REMOTEPROC))
return 0;
if (ab->bus_params.mhi_support) if (ab->bus_params.mhi_support)
return 0; return 0;
@ -812,12 +879,6 @@ int ath11k_core_init(struct ath11k_base *ab)
return ret; return ret;
} }
ret = ath11k_init_hw_params(ab);
if (ret) {
ath11k_err(ab, "failed to get hw params %d\n", ret);
return ret;
}
ret = ath11k_core_soc_create(ab); ret = ath11k_core_soc_create(ab);
if (ret) { if (ret) {
ath11k_err(ab, "failed to create soc core: %d\n", ret); ath11k_err(ab, "failed to create soc core: %d\n", ret);

View file

@ -35,6 +35,8 @@
#define ATH11K_INVALID_HW_MAC_ID 0xFF #define ATH11K_INVALID_HW_MAC_ID 0xFF
extern unsigned int ath11k_frame_mode;
enum ath11k_supported_bw { enum ath11k_supported_bw {
ATH11K_BW_20 = 0, ATH11K_BW_20 = 0,
ATH11K_BW_40 = 1, ATH11K_BW_40 = 1,
@ -54,6 +56,13 @@ enum wme_ac {
#define ATH11K_VHT_MCS_MAX 9 #define ATH11K_VHT_MCS_MAX 9
#define ATH11K_HE_MCS_MAX 11 #define ATH11K_HE_MCS_MAX 11
enum ath11k_crypt_mode {
/* Only use hardware crypto engine */
ATH11K_CRYPT_MODE_HW,
/* Only use software crypto */
ATH11K_CRYPT_MODE_SW,
};
static inline enum wme_ac ath11k_tid_to_ac(u32 tid) static inline enum wme_ac ath11k_tid_to_ac(u32 tid)
{ {
return (((tid == 0) || (tid == 3)) ? WME_AC_BE : return (((tid == 0) || (tid == 3)) ? WME_AC_BE :
@ -91,6 +100,7 @@ struct ath11k_skb_rxcb {
enum ath11k_hw_rev { enum ath11k_hw_rev {
ATH11K_HW_IPQ8074, ATH11K_HW_IPQ8074,
ATH11K_HW_QCA6390_HW20, ATH11K_HW_QCA6390_HW20,
ATH11K_HW_IPQ6018_HW10,
}; };
enum ath11k_firmware_mode { enum ath11k_firmware_mode {
@ -845,6 +855,13 @@ struct ath11k_fw_stats_bcn {
u32 tx_bcn_outage_cnt; u32 tx_bcn_outage_cnt;
}; };
extern const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq8074[];
extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq8074[];
extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq6018[];
extern const struct ce_pipe_config ath11k_target_ce_config_wlan_qca6390[];
extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qca6390[];
void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id); void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id);
void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id,
u8 *mac_addr, u16 ast_hash); u8 *mac_addr, u16 ast_hash);

View file

@ -1097,7 +1097,7 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file,
DP_RX_BUFFER_SIZE, &tlv_filter); DP_RX_BUFFER_SIZE, &tlv_filter);
if (ret) { if (ret) {
ath11k_warn(ab, "failed to set rx filter for moniter status ring\n"); ath11k_warn(ab, "failed to set rx filter for monitor status ring\n");
goto out; goto out;
} }
} }

View file

@ -26,6 +26,8 @@ enum ath11k_debug_mask {
ATH11K_DBG_TESTMODE = 0x00000400, ATH11K_DBG_TESTMODE = 0x00000400,
ATH11k_DBG_HAL = 0x00000800, ATH11k_DBG_HAL = 0x00000800,
ATH11K_DBG_PCI = 0x00001000, ATH11K_DBG_PCI = 0x00001000,
ATH11K_DBG_DP_TX = 0x00001000,
ATH11K_DBG_DP_RX = 0x00002000,
ATH11K_DBG_ANY = 0xffffffff, ATH11K_DBG_ANY = 0xffffffff,
}; };

View file

@ -3895,50 +3895,6 @@ static inline void htt_print_backpressure_stats_tlv_v(const u32 *tag_buf,
} }
} }
static inline void htt_htt_stats_debug_dump(const u32 *tag_buf,
struct debug_htt_stats_req *stats_req)
{
u8 *buf = stats_req->buf;
u32 len = stats_req->buf_len;
u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE;
u32 tlv_len = 0, i = 0, word_len = 0;
tlv_len = FIELD_GET(HTT_TLV_LEN, *tag_buf) + HTT_TLV_HDR_LEN;
word_len = (tlv_len % 4) == 0 ? (tlv_len / 4) : ((tlv_len / 4) + 1);
len += HTT_DBG_OUT(buf + len, buf_len - len,
"============================================");
len += HTT_DBG_OUT(buf + len, buf_len - len,
"HKDBG TLV DUMP: (tag_len=%u bytes, words=%u)",
tlv_len, word_len);
for (i = 0; i + 3 < word_len; i += 4) {
len += HTT_DBG_OUT(buf + len, buf_len - len,
"0x%08x 0x%08x 0x%08x 0x%08x",
tag_buf[i], tag_buf[i + 1],
tag_buf[i + 2], tag_buf[i + 3]);
}
if (i + 3 == word_len) {
len += HTT_DBG_OUT(buf + len, buf_len - len, "0x%08x 0x%08x 0x%08x ",
tag_buf[i], tag_buf[i + 1], tag_buf[i + 2]);
} else if (i + 2 == word_len) {
len += HTT_DBG_OUT(buf + len, buf_len - len, "0x%08x 0x%08x ",
tag_buf[i], tag_buf[i + 1]);
} else if (i + 1 == word_len) {
len += HTT_DBG_OUT(buf + len, buf_len - len, "0x%08x ",
tag_buf[i]);
}
len += HTT_DBG_OUT(buf + len, buf_len - len,
"============================================");
if (len >= buf_len)
buf[buf_len - 1] = 0;
else
buf[len] = 0;
stats_req->buf_len = len;
}
static int ath11k_dbg_htt_ext_stats_parse(struct ath11k_base *ab, static int ath11k_dbg_htt_ext_stats_parse(struct ath11k_base *ab,
u16 tag, u16 len, const void *tag_buf, u16 tag, u16 len, const void *tag_buf,
void *user_data) void *user_data)

View file

@ -2133,8 +2133,6 @@ static void ath11k_dp_rx_h_mpdu(struct ath11k *ar,
mcast = is_multicast_ether_addr(hdr->addr1); mcast = is_multicast_ether_addr(hdr->addr1);
fill_crypto_hdr = mcast; fill_crypto_hdr = mcast;
is_decrypted = ath11k_dp_rx_h_attn_is_decrypted(rx_desc);
spin_lock_bh(&ar->ab->base_lock); spin_lock_bh(&ar->ab->base_lock);
peer = ath11k_peer_find_by_addr(ar->ab, hdr->addr2); peer = ath11k_peer_find_by_addr(ar->ab, hdr->addr2);
if (peer) { if (peer) {
@ -2148,6 +2146,8 @@ static void ath11k_dp_rx_h_mpdu(struct ath11k *ar,
spin_unlock_bh(&ar->ab->base_lock); spin_unlock_bh(&ar->ab->base_lock);
err_bitmap = ath11k_dp_rx_h_attn_mpdu_err(rx_desc); err_bitmap = ath11k_dp_rx_h_attn_mpdu_err(rx_desc);
if (enctype != HAL_ENCRYPT_TYPE_OPEN && !err_bitmap)
is_decrypted = ath11k_dp_rx_h_attn_is_decrypted(rx_desc);
/* Clear per-MPDU flags while leaving per-PPDU flags intact */ /* Clear per-MPDU flags while leaving per-PPDU flags intact */
rx_status->flag &= ~(RX_FLAG_FAILED_FCS_CRC | rx_status->flag &= ~(RX_FLAG_FAILED_FCS_CRC |
@ -2350,6 +2350,9 @@ static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *nap
!!(status->flag & RX_FLAG_MMIC_ERROR), !!(status->flag & RX_FLAG_MMIC_ERROR),
!!(status->flag & RX_FLAG_AMSDU_MORE)); !!(status->flag & RX_FLAG_AMSDU_MORE));
ath11k_dbg_dump(ar->ab, ATH11K_DBG_DP_RX, NULL, "dp rx msdu: ",
msdu->data, msdu->len);
/* TODO: trace rx packet */ /* TODO: trace rx packet */
ieee80211_rx_napi(ar->hw, NULL, msdu, napi); ieee80211_rx_napi(ar->hw, NULL, msdu, napi);

View file

@ -13,6 +13,10 @@ static enum hal_tcl_encap_type
ath11k_dp_tx_get_encap_type(struct ath11k_vif *arvif, struct sk_buff *skb) ath11k_dp_tx_get_encap_type(struct ath11k_vif *arvif, struct sk_buff *skb)
{ {
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ath11k_base *ab = arvif->ar->ab;
if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
return HAL_TCL_ENCAP_TYPE_RAW;
if (tx_info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) if (tx_info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
return HAL_TCL_ENCAP_TYPE_ETHERNET; return HAL_TCL_ENCAP_TYPE_ETHERNET;
@ -79,6 +83,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
struct ath11k_dp *dp = &ab->dp; struct ath11k_dp *dp = &ab->dp;
struct hal_tx_info ti = {0}; struct hal_tx_info ti = {0};
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_key_conf *key = info->control.hw_key;
struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb); struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
struct hal_srng *tcl_ring; struct hal_srng *tcl_ring;
struct ieee80211_hdr *hdr = (void *)skb->data; struct ieee80211_hdr *hdr = (void *)skb->data;
@ -142,11 +147,17 @@ tcl_ring_sel:
ti.encap_type = ath11k_dp_tx_get_encap_type(arvif, skb); ti.encap_type = ath11k_dp_tx_get_encap_type(arvif, skb);
ti.meta_data_flags = arvif->tcl_metadata; ti.meta_data_flags = arvif->tcl_metadata;
if (info->control.hw_key) if (ti.encap_type == HAL_TCL_ENCAP_TYPE_RAW) {
if (key) {
ti.encrypt_type = ti.encrypt_type =
ath11k_dp_tx_get_encrypt_type(info->control.hw_key->cipher); ath11k_dp_tx_get_encrypt_type(key->cipher);
else
if (ieee80211_has_protected(hdr->frame_control))
skb_put(skb, IEEE80211_CCMP_MIC_LEN);
} else {
ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN; ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
}
}
ti.addr_search_flags = arvif->hal_addr_search_flags; ti.addr_search_flags = arvif->hal_addr_search_flags;
ti.search_type = arvif->search_type; ti.search_type = arvif->search_type;
@ -156,7 +167,8 @@ tcl_ring_sel:
ti.bss_ast_hash = arvif->ast_hash; ti.bss_ast_hash = arvif->ast_hash;
ti.dscp_tid_tbl_idx = 0; ti.dscp_tid_tbl_idx = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) { if (skb->ip_summed == CHECKSUM_PARTIAL &&
ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW) {
ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_IP4_CKSUM_EN, 1) | ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_IP4_CKSUM_EN, 1) |
FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_UDP4_CKSUM_EN, 1) | FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_UDP4_CKSUM_EN, 1) |
FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_UDP6_CKSUM_EN, 1) | FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_UDP6_CKSUM_EN, 1) |
@ -176,10 +188,11 @@ tcl_ring_sel:
ath11k_dp_tx_encap_nwifi(skb); ath11k_dp_tx_encap_nwifi(skb);
break; break;
case HAL_TCL_ENCAP_TYPE_RAW: case HAL_TCL_ENCAP_TYPE_RAW:
/* TODO: for CHECKSUM_PARTIAL case in raw mode, HW checksum offload if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
* is not applicable, hence manual checksum calculation using ret = -EINVAL;
* skb_checksum_help() is needed goto fail_remove_idr;
*/ }
break;
case HAL_TCL_ENCAP_TYPE_ETHERNET: case HAL_TCL_ENCAP_TYPE_ETHERNET:
/* no need to encap */ /* no need to encap */
break; break;
@ -242,6 +255,9 @@ tcl_ring_sel:
spin_unlock_bh(&tcl_ring->lock); spin_unlock_bh(&tcl_ring->lock);
ath11k_dbg_dump(ab, ATH11K_DBG_DP_TX, NULL, "dp tx msdu: ",
skb->data, skb->len);
atomic_inc(&ar->dp.num_tx_pending); atomic_inc(&ar->dp.num_tx_pending);
return 0; return 0;
@ -352,7 +368,6 @@ ath11k_dp_tx_process_htt_tx_complete(struct ath11k_base *ab,
wbm_status = FIELD_GET(HTT_TX_WBM_COMP_INFO0_STATUS, wbm_status = FIELD_GET(HTT_TX_WBM_COMP_INFO0_STATUS,
status_desc->info0); status_desc->info0);
switch (wbm_status) { switch (wbm_status) {
case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK: case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK:
case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP: case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP:

View file

@ -276,6 +276,518 @@ const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qca6390 = {
}, },
}; };
/* Target firmware's Copy Engine configuration. */
const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq8074[] = {
/* CE0: host->target HTC control and raw streams */
{
.pipenum = __cpu_to_le32(0),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE1: target->host HTT + HTC control */
{
.pipenum = __cpu_to_le32(1),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE2: target->host WMI */
{
.pipenum = __cpu_to_le32(2),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE3: host->target WMI */
{
.pipenum = __cpu_to_le32(3),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE4: host->target HTT */
{
.pipenum = __cpu_to_le32(4),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(256),
.nbytes_max = __cpu_to_le32(256),
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
.reserved = __cpu_to_le32(0),
},
/* CE5: target->host Pktlog */
{
.pipenum = __cpu_to_le32(5),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(0),
.reserved = __cpu_to_le32(0),
},
/* CE6: Reserved for target autonomous hif_memcpy */
{
.pipenum = __cpu_to_le32(6),
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(65535),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE7 used only by Host */
{
.pipenum = __cpu_to_le32(7),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE8 target->host used only by IPA */
{
.pipenum = __cpu_to_le32(8),
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(65535),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE9 host->target HTT */
{
.pipenum = __cpu_to_le32(9),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE10 target->host HTT */
{
.pipenum = __cpu_to_le32(10),
.pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
.nentries = __cpu_to_le32(0),
.nbytes_max = __cpu_to_le32(0),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE11 Not used */
};
/* Map from service/endpoint to Copy Engine.
* This table is derived from the CE_PCI TABLE, above.
* It is passed to the Target at startup for use by firmware.
*/
const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq8074[] = {
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(7),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(9),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(0),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(1),
},
{ /* not used */
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(0),
},
{ /* not used */
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(1),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(4),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(1),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_PKT_LOG),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(5),
},
/* (Additions here) */
{ /* terminator entry */ }
};
const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq6018[] = {
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(3),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(7),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(2),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(0),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(1),
},
{ /* not used */
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(0),
},
{ /* not used */
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(1),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
.pipenum = __cpu_to_le32(4),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(1),
},
{
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_PKT_LOG),
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
.pipenum = __cpu_to_le32(5),
},
/* (Additions here) */
{ /* terminator entry */ }
};
/* Target firmware's Copy Engine configuration. */
const struct ce_pipe_config ath11k_target_ce_config_wlan_qca6390[] = {
/* CE0: host->target HTC control and raw streams */
{
.pipenum = __cpu_to_le32(0),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE1: target->host HTT + HTC control */
{
.pipenum = __cpu_to_le32(1),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE2: target->host WMI */
{
.pipenum = __cpu_to_le32(2),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE3: host->target WMI */
{
.pipenum = __cpu_to_le32(3),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE4: host->target HTT */
{
.pipenum = __cpu_to_le32(4),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(256),
.nbytes_max = __cpu_to_le32(256),
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
.reserved = __cpu_to_le32(0),
},
/* CE5: target->host Pktlog */
{
.pipenum = __cpu_to_le32(5),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE6: Reserved for target autonomous hif_memcpy */
{
.pipenum = __cpu_to_le32(6),
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(16384),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE7 used only by Host */
{
.pipenum = __cpu_to_le32(7),
.pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
.nentries = __cpu_to_le32(0),
.nbytes_max = __cpu_to_le32(0),
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
.reserved = __cpu_to_le32(0),
},
/* CE8 target->host used only by IPA */
{
.pipenum = __cpu_to_le32(8),
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(16384),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE 9, 10, 11 are used by MHI driver */
};
/* Map from service/endpoint to Copy Engine.
* This table is derived from the CE_PCI TABLE, above.
* It is passed to the Target at startup for use by firmware.
*/
const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qca6390[] = {
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(3),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(2),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(3),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(2),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(3),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(2),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(3),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(2),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(3),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(2),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(0),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(2),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(4),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(1),
},
/* (Additions here) */
{ /* must be last */
__cpu_to_le32(0),
__cpu_to_le32(0),
__cpu_to_le32(0),
},
};
const struct ath11k_hw_regs ipq8074_regs = { const struct ath11k_hw_regs ipq8074_regs = {
/* SW2TCL(x) R0 ring configuration address */ /* SW2TCL(x) R0 ring configuration address */
.hal_tcl1_ring_base_lsb = 0x00000510, .hal_tcl1_ring_base_lsb = 0x00000510,

View file

@ -129,7 +129,6 @@ struct ath11k_hw_params {
} fw; } fw;
const struct ath11k_hw_ops *hw_ops; const struct ath11k_hw_ops *hw_ops;
const struct ath11k_hw_ring_mask *ring_mask; const struct ath11k_hw_ring_mask *ring_mask;
bool internal_sleep_clock; bool internal_sleep_clock;
@ -137,6 +136,10 @@ struct ath11k_hw_params {
const struct ath11k_hw_regs *regs; const struct ath11k_hw_regs *regs;
const struct ce_attr *host_ce_config; const struct ce_attr *host_ce_config;
u32 ce_count; u32 ce_count;
const struct ce_pipe_config *target_ce_config;
u32 target_ce_count;
const struct service_to_pipe *svc_to_ce_map;
u32 svc_to_ce_map_len;
bool single_pdev_only; bool single_pdev_only;

View file

@ -42,12 +42,6 @@
.max_power = 30, \ .max_power = 30, \
} }
/* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
static unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
MODULE_PARM_DESC(frame_mode,
"Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
static const struct ieee80211_channel ath11k_2ghz_channels[] = { static const struct ieee80211_channel ath11k_2ghz_channels[] = {
CHAN2G(1, 2412, 0), CHAN2G(1, 2412, 0),
CHAN2G(2, 2417, 0), CHAN2G(2, 2417, 0),
@ -1276,6 +1270,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
struct peer_assoc_params *arg) struct peer_assoc_params *arg)
{ {
const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap; const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
u8 ampdu_factor;
u16 v; u16 v;
if (!he_cap->has_he) if (!he_cap->has_he)
@ -1292,6 +1287,30 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
/* the top most byte is used to indicate BSS color info */ /* the top most byte is used to indicate BSS color info */
arg->peer_he_ops &= 0xffffff; arg->peer_he_ops &= 0xffffff;
/* As per section 26.6.1 11ax Draft5.0, if the Max AMPDU Exponent Extension
* in HE cap is zero, use the arg->peer_max_mpdu as calculated while parsing
* VHT caps(if VHT caps is present) or HT caps (if VHT caps is not present).
*
* For non-zero value of Max AMPDU Extponent Extension in HE MAC caps,
* if a HE STA sends VHT cap and HE cap IE in assoc request then, use
* MAX_AMPDU_LEN_FACTOR as 20 to calculate max_ampdu length.
* If a HE STA that does not send VHT cap, but HE and HT cap in assoc
* request, then use MAX_AMPDU_LEN_FACTOR as 16 to calculate max_ampdu
* length.
*/
ampdu_factor = (he_cap->he_cap_elem.mac_cap_info[3] &
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK) >>
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_SHIFT;
if (ampdu_factor) {
if (sta->vht_cap.vht_supported)
arg->peer_max_mpdu = (1 << (IEEE80211_HE_VHT_MAX_AMPDU_FACTOR +
ampdu_factor)) - 1;
else if (sta->ht_cap.ht_supported)
arg->peer_max_mpdu = (1 << (IEEE80211_HE_HT_MAX_AMPDU_FACTOR +
ampdu_factor)) - 1;
}
if (he_cap->he_cap_elem.phy_cap_info[6] & if (he_cap->he_cap_elem.phy_cap_info[6] &
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
int bit = 7; int bit = 7;
@ -2380,6 +2399,9 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
reinit_completion(&ar->install_key_done); reinit_completion(&ar->install_key_done);
if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
return 0;
if (cmd == DISABLE_KEY) { if (cmd == DISABLE_KEY) {
/* TODO: Check if FW expects value other than NONE for del */ /* TODO: Check if FW expects value other than NONE for del */
/* arg.key_cipher = WMI_CIPHER_NONE; */ /* arg.key_cipher = WMI_CIPHER_NONE; */
@ -2411,8 +2433,13 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if (test_bit(ATH11K_FLAG_RAW_MODE, &ar->ab->dev_flags))
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV |
IEEE80211_KEY_FLAG_RESERVE_TAILROOM;
install: install:
ret = ath11k_wmi_vdev_install_key(arvif->ar, &arg); ret = ath11k_wmi_vdev_install_key(arvif->ar, &arg);
if (ret) if (ret)
return ret; return ret;
@ -2484,6 +2511,9 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
return 1; return 1;
if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
return 1;
if (key->keyidx > WMI_MAX_KEY_INDEX) if (key->keyidx > WMI_MAX_KEY_INDEX)
return -ENOSPC; return -ENOSPC;
@ -4436,6 +4466,8 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
if (ieee80211_set_hw_80211_encap(vif, hw_encap)) if (ieee80211_set_hw_80211_encap(vif, hw_encap))
param_value = ATH11K_HW_TXRX_ETHERNET; param_value = ATH11K_HW_TXRX_ETHERNET;
else if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
param_value = ATH11K_HW_TXRX_RAW;
else else
param_value = ATH11K_HW_TXRX_NATIVE_WIFI; param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
@ -6089,7 +6121,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
ret = ath11k_mac_setup_channels_rates(ar, ret = ath11k_mac_setup_channels_rates(ar,
cap->supported_bands); cap->supported_bands);
if (ret) if (ret)
goto err_free; goto err;
ath11k_mac_setup_ht_vht_cap(ar, cap, &ht_cap); ath11k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);
ath11k_mac_setup_he_cap(ar, cap); ath11k_mac_setup_he_cap(ar, cap);
@ -6109,7 +6141,6 @@ static int __ath11k_mac_register(struct ath11k *ar)
ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL); ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL);
ieee80211_hw_set(ar->hw, AP_LINK_PS); ieee80211_hw_set(ar->hw, AP_LINK_PS);
ieee80211_hw_set(ar->hw, SPECTRUM_MGMT); ieee80211_hw_set(ar->hw, SPECTRUM_MGMT);
ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);
ieee80211_hw_set(ar->hw, CONNECTION_MONITOR); ieee80211_hw_set(ar->hw, CONNECTION_MONITOR);
ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK); ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK);
ieee80211_hw_set(ar->hw, WANT_MONITOR_VIF); ieee80211_hw_set(ar->hw, WANT_MONITOR_VIF);
@ -6176,8 +6207,11 @@ static int __ath11k_mac_register(struct ath11k *ar)
ath11k_reg_init(ar); ath11k_reg_init(ar);
/* advertise HW checksum offload capabilities */ if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
ar->hw->netdev_features = NETIF_F_HW_CSUM; ar->hw->netdev_features = NETIF_F_HW_CSUM;
ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);
}
ret = ieee80211_register_hw(ar->hw); ret = ieee80211_register_hw(ar->hw);
if (ret) { if (ret) {
@ -6203,7 +6237,9 @@ static int __ath11k_mac_register(struct ath11k *ar)
err_free: err_free:
kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels); kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels); kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);
kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
err:
SET_IEEE80211_DEV(ar->hw, NULL); SET_IEEE80211_DEV(ar->hw, NULL);
return ret; return ret;
} }

View file

@ -220,7 +220,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
mhi_ctrl = kzalloc(sizeof(*mhi_ctrl), GFP_KERNEL); mhi_ctrl = kzalloc(sizeof(*mhi_ctrl), GFP_KERNEL);
if (!mhi_ctrl) if (!mhi_ctrl)
return PTR_ERR(mhi_ctrl); return -ENOMEM;
ath11k_core_create_firmware_path(ab, ATH11K_AMSS_FILE, ath11k_core_create_firmware_path(ab, ATH11K_AMSS_FILE,
ab_pci->amss_path, ab_pci->amss_path,

View file

@ -51,187 +51,6 @@ static const struct ath11k_msi_config msi_config = {
}, },
}; };
/* Target firmware's Copy Engine configuration. */
static const struct ce_pipe_config target_ce_config_wlan[] = {
/* CE0: host->target HTC control and raw streams */
{
.pipenum = __cpu_to_le32(0),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE1: target->host HTT + HTC control */
{
.pipenum = __cpu_to_le32(1),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE2: target->host WMI */
{
.pipenum = __cpu_to_le32(2),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE3: host->target WMI */
{
.pipenum = __cpu_to_le32(3),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE4: host->target HTT */
{
.pipenum = __cpu_to_le32(4),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(256),
.nbytes_max = __cpu_to_le32(256),
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
.reserved = __cpu_to_le32(0),
},
/* CE5: target->host Pktlog */
{
.pipenum = __cpu_to_le32(5),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE6: Reserved for target autonomous hif_memcpy */
{
.pipenum = __cpu_to_le32(6),
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(16384),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE7 used only by Host */
{
.pipenum = __cpu_to_le32(7),
.pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
.nentries = __cpu_to_le32(0),
.nbytes_max = __cpu_to_le32(0),
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
.reserved = __cpu_to_le32(0),
},
/* CE8 target->host used only by IPA */
{
.pipenum = __cpu_to_le32(8),
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(16384),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE 9, 10, 11 are used by MHI driver */
};
/* Map from service/endpoint to Copy Engine.
* This table is derived from the CE_PCI TABLE, above.
* It is passed to the Target at startup for use by firmware.
*/
static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(3),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(2),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(3),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(2),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(3),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(2),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(3),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(2),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(3),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(2),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(0),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(2),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
__cpu_to_le32(4),
},
{
__cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
__cpu_to_le32(1),
},
/* (Additions here) */
{ /* must be last */
__cpu_to_le32(0),
__cpu_to_le32(0),
__cpu_to_le32(0),
},
};
static const char *irq_name[ATH11K_IRQ_NUM_MAX] = { static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
"bhi", "bhi",
"mhi-er0", "mhi-er0",
@ -648,9 +467,12 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
int i, j, ret, num_vectors = 0; int i, j, ret, num_vectors = 0;
u32 user_base_data = 0, base_vector = 0; u32 user_base_data = 0, base_vector = 0;
ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), "DP", ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), "DP",
&num_vectors, &user_base_data, &num_vectors,
&user_base_data,
&base_vector); &base_vector);
if (ret < 0)
return ret;
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
@ -754,11 +576,11 @@ static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab)
{ {
struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
cfg->tgt_ce = target_ce_config_wlan; cfg->tgt_ce = ab->hw_params.target_ce_config;
cfg->tgt_ce_len = ARRAY_SIZE(target_ce_config_wlan); cfg->tgt_ce_len = ab->hw_params.target_ce_count;
cfg->svc_to_ce_map = target_service_to_ce_map_wlan; cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map;
cfg->svc_to_ce_map_len = ARRAY_SIZE(target_service_to_ce_map_wlan); cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len;
ab->qmi.service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390; ab->qmi.service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390;
} }
@ -962,8 +784,8 @@ static int ath11k_pci_map_service_to_pipe(struct ath11k_base *ab, u16 service_id
bool ul_set = false, dl_set = false; bool ul_set = false, dl_set = false;
int i; int i;
for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) { for (i = 0; i < ab->hw_params.svc_to_ce_map_len; i++) {
entry = &target_service_to_ce_map_wlan[i]; entry = &ab->hw_params.svc_to_ce_map[i];
if (__le32_to_cpu(entry->service_id) != service_id) if (__le32_to_cpu(entry->service_id) != service_id)
continue; continue;

View file

@ -1868,16 +1868,16 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type,
const struct firmware *fw_entry; const struct firmware *fw_entry;
struct ath11k_board_data bd; struct ath11k_board_data bd;
u32 fw_size; u32 fw_size;
int ret = 0; int ret;
memset(&bd, 0, sizeof(bd));
switch (type) { switch (type) {
case ATH11K_QMI_FILE_TYPE_BDF_GOLDEN: case ATH11K_QMI_FILE_TYPE_BDF_GOLDEN:
memset(&bd, 0, sizeof(bd));
ret = ath11k_core_fetch_bdf(ab, &bd); ret = ath11k_core_fetch_bdf(ab, &bd);
if (ret) { if (ret) {
ath11k_warn(ab, "qmi failed to load BDF\n"); ath11k_warn(ab, "qmi failed to load BDF\n");
goto out; return ret;
} }
fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len); fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len);
@ -1886,10 +1886,11 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type,
break; break;
case ATH11K_QMI_FILE_TYPE_CALDATA: case ATH11K_QMI_FILE_TYPE_CALDATA:
fw_entry = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_CAL_FILE); fw_entry = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_CAL_FILE);
if (ret) { if (IS_ERR(fw_entry)) {
ret = PTR_ERR(fw_entry);
ath11k_warn(ab, "failed to load %s: %d\n", ath11k_warn(ab, "failed to load %s: %d\n",
ATH11K_DEFAULT_CAL_FILE, ret); ATH11K_DEFAULT_CAL_FILE, ret);
goto out; return ret;
} }
fw_size = min_t(u32, ab->hw_params.fw.board_size, fw_size = min_t(u32, ab->hw_params.fw.board_size,
@ -1901,14 +1902,11 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type,
release_firmware(fw_entry); release_firmware(fw_entry);
break; break;
default: default:
ret = -EINVAL; return -EINVAL;
goto out;
} }
req->total_size = fw_size; req->total_size = fw_size;
return 0;
out:
return ret;
} }
static int ath11k_qmi_load_bdf_fixed_addr(struct ath11k_base *ab) static int ath11k_qmi_load_bdf_fixed_addr(struct ath11k_base *ab)

View file

@ -773,6 +773,8 @@ static int ath11k_spectral_process_data(struct ath11k *ar,
i += sizeof(*tlv) + tlv_len; i += sizeof(*tlv) + tlv_len;
} }
ret = 0;
err: err:
kfree(fft_sample); kfree(fft_sample);
unlock: unlock:

View file

@ -3366,6 +3366,10 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
config.rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI; config.rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI;
config.rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI; config.rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI;
config.rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI; config.rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI;
if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
config.rx_decap_mode = TARGET_DECAP_MODE_RAW;
config.scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS; config.scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS;
config.bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV; config.bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV;
config.roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV; config.roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV;

View file

@ -1536,12 +1536,12 @@ ath5k_set_current_imask(struct ath5k_hw *ah)
} }
static void static void
ath5k_tasklet_rx(unsigned long data) ath5k_tasklet_rx(struct tasklet_struct *t)
{ {
struct ath5k_rx_status rs = {}; struct ath5k_rx_status rs = {};
struct sk_buff *skb, *next_skb; struct sk_buff *skb, *next_skb;
dma_addr_t next_skb_addr; dma_addr_t next_skb_addr;
struct ath5k_hw *ah = (void *)data; struct ath5k_hw *ah = from_tasklet(ah, t, rxtq);
struct ath_common *common = ath5k_hw_common(ah); struct ath_common *common = ath5k_hw_common(ah);
struct ath5k_buf *bf; struct ath5k_buf *bf;
struct ath5k_desc *ds; struct ath5k_desc *ds;
@ -1784,10 +1784,10 @@ ath5k_tx_processq(struct ath5k_hw *ah, struct ath5k_txq *txq)
} }
static void static void
ath5k_tasklet_tx(unsigned long data) ath5k_tasklet_tx(struct tasklet_struct *t)
{ {
int i; int i;
struct ath5k_hw *ah = (void *)data; struct ath5k_hw *ah = from_tasklet(ah, t, txtq);
for (i = 0; i < AR5K_NUM_TX_QUEUES; i++) for (i = 0; i < AR5K_NUM_TX_QUEUES; i++)
if (ah->txqs[i].setup && (ah->ah_txq_isr_txok_all & BIT(i))) if (ah->txqs[i].setup && (ah->ah_txq_isr_txok_all & BIT(i)))
@ -2176,9 +2176,9 @@ ath5k_beacon_config(struct ath5k_hw *ah)
spin_unlock_bh(&ah->block); spin_unlock_bh(&ah->block);
} }
static void ath5k_tasklet_beacon(unsigned long data) static void ath5k_tasklet_beacon(struct tasklet_struct *t)
{ {
struct ath5k_hw *ah = (struct ath5k_hw *) data; struct ath5k_hw *ah = from_tasklet(ah, t, beacontq);
/* /*
* Software beacon alert--time to send a beacon. * Software beacon alert--time to send a beacon.
@ -2447,9 +2447,9 @@ ath5k_calibrate_work(struct work_struct *work)
static void static void
ath5k_tasklet_ani(unsigned long data) ath5k_tasklet_ani(struct tasklet_struct *t)
{ {
struct ath5k_hw *ah = (void *)data; struct ath5k_hw *ah = from_tasklet(ah, t, ani_tasklet);
ah->ah_cal_mask |= AR5K_CALIBRATION_ANI; ah->ah_cal_mask |= AR5K_CALIBRATION_ANI;
ath5k_ani_calibration(ah); ath5k_ani_calibration(ah);
@ -3069,10 +3069,10 @@ ath5k_init(struct ieee80211_hw *hw)
hw->queues = 1; hw->queues = 1;
} }
tasklet_init(&ah->rxtq, ath5k_tasklet_rx, (unsigned long)ah); tasklet_setup(&ah->rxtq, ath5k_tasklet_rx);
tasklet_init(&ah->txtq, ath5k_tasklet_tx, (unsigned long)ah); tasklet_setup(&ah->txtq, ath5k_tasklet_tx);
tasklet_init(&ah->beacontq, ath5k_tasklet_beacon, (unsigned long)ah); tasklet_setup(&ah->beacontq, ath5k_tasklet_beacon);
tasklet_init(&ah->ani_tasklet, ath5k_tasklet_ani, (unsigned long)ah); tasklet_setup(&ah->ani_tasklet, ath5k_tasklet_ani);
INIT_WORK(&ah->reset_work, ath5k_reset_work); INIT_WORK(&ah->reset_work, ath5k_reset_work);
INIT_WORK(&ah->calib_work, ath5k_calibrate_work); INIT_WORK(&ah->calib_work, ath5k_calibrate_work);

View file

@ -73,9 +73,9 @@ ath5k_is_rfkill_set(struct ath5k_hw *ah)
} }
static void static void
ath5k_tasklet_rfkill_toggle(unsigned long data) ath5k_tasklet_rfkill_toggle(struct tasklet_struct *t)
{ {
struct ath5k_hw *ah = (void *)data; struct ath5k_hw *ah = from_tasklet(ah, t, rf_kill.toggleq);
bool blocked; bool blocked;
blocked = ath5k_is_rfkill_set(ah); blocked = ath5k_is_rfkill_set(ah);
@ -90,8 +90,7 @@ ath5k_rfkill_hw_start(struct ath5k_hw *ah)
ah->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin; ah->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;
ah->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol; ah->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;
tasklet_init(&ah->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle, tasklet_setup(&ah->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle);
(unsigned long)ah);
ath5k_rfkill_disable(ah); ath5k_rfkill_disable(ah);

View file

@ -1201,8 +1201,7 @@ static int ath6kl_wmi_pstream_timeout_event_rx(struct wmi *wmi, u8 *datap,
static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len) static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
{ {
struct wmi_bit_rate_reply *reply; struct wmi_bit_rate_reply *reply;
s32 rate; u32 index;
u32 sgi, index;
if (len < sizeof(struct wmi_bit_rate_reply)) if (len < sizeof(struct wmi_bit_rate_reply))
return -EINVAL; return -EINVAL;
@ -1211,15 +1210,10 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
ath6kl_dbg(ATH6KL_DBG_WMI, "rateindex %d\n", reply->rate_index); ath6kl_dbg(ATH6KL_DBG_WMI, "rateindex %d\n", reply->rate_index);
if (reply->rate_index == (s8) RATE_AUTO) { if (reply->rate_index != (s8) RATE_AUTO) {
rate = RATE_AUTO;
} else {
index = reply->rate_index & 0x7f; index = reply->rate_index & 0x7f;
if (WARN_ON_ONCE(index > (RATE_MCS_7_40 + 1))) if (WARN_ON_ONCE(index > (RATE_MCS_7_40 + 1)))
return -EINVAL; return -EINVAL;
sgi = (reply->rate_index & 0x80) ? 1 : 0;
rate = wmi_rate_tbl[index][sgi];
} }
ath6kl_wakeup_event(wmi->parent_dev); ath6kl_wakeup_event(wmi->parent_dev);

View file

@ -22,10 +22,10 @@ config ATH9K
tristate "Atheros 802.11n wireless cards support" tristate "Atheros 802.11n wireless cards support"
depends on MAC80211 && HAS_DMA depends on MAC80211 && HAS_DMA
select ATH9K_HW select ATH9K_HW
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS
select ATH9K_COMMON select ATH9K_COMMON
imply NEW_LEDS
imply LEDS_CLASS
imply MAC80211_LEDS
help help
This module adds support for wireless adapters based on This module adds support for wireless adapters based on
Atheros IEEE 802.11n AR5008, AR9001 and AR9002 family Atheros IEEE 802.11n AR5008, AR9001 and AR9002 family
@ -177,10 +177,10 @@ config ATH9K_HTC
tristate "Atheros HTC based wireless cards support" tristate "Atheros HTC based wireless cards support"
depends on USB && MAC80211 depends on USB && MAC80211
select ATH9K_HW select ATH9K_HW
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS
select ATH9K_COMMON select ATH9K_COMMON
imply NEW_LEDS
imply LEDS_CLASS
imply MAC80211_LEDS
help help
Support for Atheros HTC based cards. Support for Atheros HTC based cards.
Chipsets supported: AR9271 Chipsets supported: AR9271

View file

@ -459,12 +459,6 @@ static const u32 ar5416Common[][2] = {
{0x0000a3e0, 0x000001ce}, {0x0000a3e0, 0x000001ce},
}; };
static const u32 ar5416Bank0[][2] = {
/* Addr allmodes */
{0x000098b0, 0x1e5795e5},
{0x000098e0, 0x02008020},
};
static const u32 ar5416BB_RfGain[][3] = { static const u32 ar5416BB_RfGain[][3] = {
/* Addr 5G 2G */ /* Addr 5G 2G */
{0x00009a00, 0x00000000, 0x00000000}, {0x00009a00, 0x00000000, 0x00000000},
@ -533,60 +527,6 @@ static const u32 ar5416BB_RfGain[][3] = {
{0x00009afc, 0x000000f9, 0x000000f9}, {0x00009afc, 0x000000f9, 0x000000f9},
}; };
static const u32 ar5416Bank1[][2] = {
/* Addr allmodes */
{0x000098b0, 0x02108421},
{0x000098ec, 0x00000008},
};
static const u32 ar5416Bank2[][2] = {
/* Addr allmodes */
{0x000098b0, 0x0e73ff17},
{0x000098e0, 0x00000420},
};
static const u32 ar5416Bank3[][3] = {
/* Addr 5G 2G */
{0x000098f0, 0x01400018, 0x01c00018},
};
static const u32 ar5416Bank6[][3] = {
/* Addr 5G 2G */
{0x0000989c, 0x00000000, 0x00000000},
{0x0000989c, 0x00000000, 0x00000000},
{0x0000989c, 0x00000000, 0x00000000},
{0x0000989c, 0x00e00000, 0x00e00000},
{0x0000989c, 0x005e0000, 0x005e0000},
{0x0000989c, 0x00120000, 0x00120000},
{0x0000989c, 0x00620000, 0x00620000},
{0x0000989c, 0x00020000, 0x00020000},
{0x0000989c, 0x00ff0000, 0x00ff0000},
{0x0000989c, 0x00ff0000, 0x00ff0000},
{0x0000989c, 0x00ff0000, 0x00ff0000},
{0x0000989c, 0x40ff0000, 0x40ff0000},
{0x0000989c, 0x005f0000, 0x005f0000},
{0x0000989c, 0x00870000, 0x00870000},
{0x0000989c, 0x00f90000, 0x00f90000},
{0x0000989c, 0x007b0000, 0x007b0000},
{0x0000989c, 0x00ff0000, 0x00ff0000},
{0x0000989c, 0x00f50000, 0x00f50000},
{0x0000989c, 0x00dc0000, 0x00dc0000},
{0x0000989c, 0x00110000, 0x00110000},
{0x0000989c, 0x006100a8, 0x006100a8},
{0x0000989c, 0x004210a2, 0x004210a2},
{0x0000989c, 0x0014008f, 0x0014008f},
{0x0000989c, 0x00c40003, 0x00c40003},
{0x0000989c, 0x003000f2, 0x003000f2},
{0x0000989c, 0x00440016, 0x00440016},
{0x0000989c, 0x00410040, 0x00410040},
{0x0000989c, 0x0001805e, 0x0001805e},
{0x0000989c, 0x0000c0ab, 0x0000c0ab},
{0x0000989c, 0x000000f1, 0x000000f1},
{0x0000989c, 0x00002081, 0x00002081},
{0x0000989c, 0x000000d4, 0x000000d4},
{0x000098d0, 0x0000000f, 0x0010000f},
};
static const u32 ar5416Bank6TPC[][3] = { static const u32 ar5416Bank6TPC[][3] = {
/* Addr 5G 2G */ /* Addr 5G 2G */
{0x0000989c, 0x00000000, 0x00000000}, {0x0000989c, 0x00000000, 0x00000000},
@ -624,13 +564,6 @@ static const u32 ar5416Bank6TPC[][3] = {
{0x000098d0, 0x0000000f, 0x0010000f}, {0x000098d0, 0x0000000f, 0x0010000f},
}; };
static const u32 ar5416Bank7[][2] = {
/* Addr allmodes */
{0x0000989c, 0x00000500},
{0x0000989c, 0x00000800},
{0x000098cc, 0x0000000e},
};
static const u32 ar5416Addac[][2] = { static const u32 ar5416Addac[][2] = {
/* Addr allmodes */ /* Addr allmodes */
{0x0000989c, 0x00000000}, {0x0000989c, 0x00000000},
@ -671,4 +604,3 @@ static const u32 ar5416Addac[][2] = {
{0x0000989c, 0x00000000}, {0x0000989c, 0x00000000},
{0x000098c4, 0x00000000}, {0x000098c4, 0x00000000},
}; };

View file

@ -18,7 +18,6 @@
#include "hw-ops.h" #include "hw-ops.h"
#include "../regd.h" #include "../regd.h"
#include "ar9002_phy.h" #include "ar9002_phy.h"
#include "ar5008_initvals.h"
/* All code below is for AR5008, AR9001, AR9002 */ /* All code below is for AR5008, AR9001, AR9002 */
@ -51,6 +50,36 @@ static const int m2ThreshLowExt_off = 127;
static const int m1ThreshExt_off = 127; static const int m1ThreshExt_off = 127;
static const int m2ThreshExt_off = 127; static const int m2ThreshExt_off = 127;
static const u32 ar5416Bank0[][2] = {
/* Addr allmodes */
{0x000098b0, 0x1e5795e5},
{0x000098e0, 0x02008020},
};
static const u32 ar5416Bank1[][2] = {
/* Addr allmodes */
{0x000098b0, 0x02108421},
{0x000098ec, 0x00000008},
};
static const u32 ar5416Bank2[][2] = {
/* Addr allmodes */
{0x000098b0, 0x0e73ff17},
{0x000098e0, 0x00000420},
};
static const u32 ar5416Bank3[][3] = {
/* Addr 5G 2G */
{0x000098f0, 0x01400018, 0x01c00018},
};
static const u32 ar5416Bank7[][2] = {
/* Addr allmodes */
{0x0000989c, 0x00000500},
{0x0000989c, 0x00000800},
{0x000098cc, 0x0000000e},
};
static const struct ar5416IniArray bank0 = STATIC_INI_ARRAY(ar5416Bank0); static const struct ar5416IniArray bank0 = STATIC_INI_ARRAY(ar5416Bank0);
static const struct ar5416IniArray bank1 = STATIC_INI_ARRAY(ar5416Bank1); static const struct ar5416IniArray bank1 = STATIC_INI_ARRAY(ar5416Bank1);
static const struct ar5416IniArray bank2 = STATIC_INI_ARRAY(ar5416Bank2); static const struct ar5416IniArray bank2 = STATIC_INI_ARRAY(ar5416Bank2);

View file

@ -459,43 +459,6 @@ static const u32 ar5416Common_9100[][2] = {
{0x0000a3e0, 0x000001ce}, {0x0000a3e0, 0x000001ce},
}; };
static const u32 ar5416Bank6_9100[][3] = {
/* Addr 5G 2G */
{0x0000989c, 0x00000000, 0x00000000},
{0x0000989c, 0x00000000, 0x00000000},
{0x0000989c, 0x00000000, 0x00000000},
{0x0000989c, 0x00e00000, 0x00e00000},
{0x0000989c, 0x005e0000, 0x005e0000},
{0x0000989c, 0x00120000, 0x00120000},
{0x0000989c, 0x00620000, 0x00620000},
{0x0000989c, 0x00020000, 0x00020000},
{0x0000989c, 0x00ff0000, 0x00ff0000},
{0x0000989c, 0x00ff0000, 0x00ff0000},
{0x0000989c, 0x00ff0000, 0x00ff0000},
{0x0000989c, 0x00ff0000, 0x00ff0000},
{0x0000989c, 0x005f0000, 0x005f0000},
{0x0000989c, 0x00870000, 0x00870000},
{0x0000989c, 0x00f90000, 0x00f90000},
{0x0000989c, 0x007b0000, 0x007b0000},
{0x0000989c, 0x00ff0000, 0x00ff0000},
{0x0000989c, 0x00f50000, 0x00f50000},
{0x0000989c, 0x00dc0000, 0x00dc0000},
{0x0000989c, 0x00110000, 0x00110000},
{0x0000989c, 0x006100a8, 0x006100a8},
{0x0000989c, 0x004210a2, 0x004210a2},
{0x0000989c, 0x0014000f, 0x0014000f},
{0x0000989c, 0x00c40002, 0x00c40002},
{0x0000989c, 0x003000f2, 0x003000f2},
{0x0000989c, 0x00440016, 0x00440016},
{0x0000989c, 0x00410040, 0x00410040},
{0x0000989c, 0x000180d6, 0x000180d6},
{0x0000989c, 0x0000c0aa, 0x0000c0aa},
{0x0000989c, 0x000000b1, 0x000000b1},
{0x0000989c, 0x00002000, 0x00002000},
{0x0000989c, 0x000000d4, 0x000000d4},
{0x000098d0, 0x0000000f, 0x0010000f},
};
static const u32 ar5416Bank6TPC_9100[][3] = { static const u32 ar5416Bank6TPC_9100[][3] = {
/* Addr 5G 2G */ /* Addr 5G 2G */
{0x0000989c, 0x00000000, 0x00000000}, {0x0000989c, 0x00000000, 0x00000000},

View file

@ -897,20 +897,6 @@ static const u32 ar9280Modes_original_tx_gain_9280_2[][5] = {
{0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480}, {0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
}; };
static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
/* Addr allmodes */
{0x00004040, 0x9248fd00},
{0x00004040, 0x24924924},
{0x00004040, 0xa8000019},
{0x00004040, 0x13160820},
{0x00004040, 0xe5980560},
{0x00004040, 0xc01dcffc},
{0x00004040, 0x1aaabe41},
{0x00004040, 0xbe105554},
{0x00004040, 0x00043007},
{0x00004044, 0x00000000},
};
static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {
/* Addr allmodes */ /* Addr allmodes */
{0x00004040, 0x9248fd00}, {0x00004040, 0x9248fd00},

View file

@ -713,7 +713,7 @@ struct ath_beacon {
bool tx_last; bool tx_last;
}; };
void ath9k_beacon_tasklet(unsigned long data); void ath9k_beacon_tasklet(struct tasklet_struct *t);
void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *main_vif, void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *main_vif,
bool beacons); bool beacons);
void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif); void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
@ -1117,7 +1117,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
common->bus_ops->read_cachesize(common, csz); common->bus_ops->read_cachesize(common, csz);
} }
void ath9k_tasklet(unsigned long data); void ath9k_tasklet(struct tasklet_struct *t);
int ath_cabq_update(struct ath_softc *); int ath_cabq_update(struct ath_softc *);
u8 ath9k_parse_mpdudensity(u8 mpdudensity); u8 ath9k_parse_mpdudensity(u8 mpdudensity);
irqreturn_t ath_isr(int irq, void *dev); irqreturn_t ath_isr(int irq, void *dev);

View file

@ -385,9 +385,9 @@ void ath9k_csa_update(struct ath_softc *sc)
ath9k_csa_update_vif, sc); ath9k_csa_update_vif, sc);
} }
void ath9k_beacon_tasklet(unsigned long data) void ath9k_beacon_tasklet(struct tasklet_struct *t)
{ {
struct ath_softc *sc = (struct ath_softc *)data; struct ath_softc *sc = from_tasklet(sc, t, bcon_tasklet);
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
struct ath_buf *bf = NULL; struct ath_buf *bf = NULL;

View file

@ -583,14 +583,14 @@ int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv);
void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot); void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot);
void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv); void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv);
void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event); void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event);
void ath9k_tx_failed_tasklet(unsigned long data); void ath9k_tx_failed_tasklet(struct tasklet_struct *t);
void ath9k_htc_tx_cleanup_timer(struct timer_list *t); void ath9k_htc_tx_cleanup_timer(struct timer_list *t);
bool ath9k_htc_csa_is_finished(struct ath9k_htc_priv *priv); bool ath9k_htc_csa_is_finished(struct ath9k_htc_priv *priv);
int ath9k_rx_init(struct ath9k_htc_priv *priv); int ath9k_rx_init(struct ath9k_htc_priv *priv);
void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); void ath9k_rx_cleanup(struct ath9k_htc_priv *priv);
void ath9k_host_rx_init(struct ath9k_htc_priv *priv); void ath9k_host_rx_init(struct ath9k_htc_priv *priv);
void ath9k_rx_tasklet(unsigned long data); void ath9k_rx_tasklet(struct tasklet_struct *t);
u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv); u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv);
void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv); void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv);

View file

@ -645,10 +645,8 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
spin_lock_init(&priv->tx.tx_lock); spin_lock_init(&priv->tx.tx_lock);
mutex_init(&priv->mutex); mutex_init(&priv->mutex);
mutex_init(&priv->htc_pm_lock); mutex_init(&priv->htc_pm_lock);
tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, tasklet_setup(&priv->rx_tasklet, ath9k_rx_tasklet);
(unsigned long)priv); tasklet_setup(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet);
tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet,
(unsigned long)priv);
INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work); INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
INIT_WORK(&priv->ps_work, ath9k_ps_work); INIT_WORK(&priv->ps_work, ath9k_ps_work);
INIT_WORK(&priv->fatal_work, ath9k_fatal_work); INIT_WORK(&priv->fatal_work, ath9k_fatal_work);

View file

@ -570,9 +570,9 @@ void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv)
spin_unlock_bh(&priv->tx.tx_lock); spin_unlock_bh(&priv->tx.tx_lock);
} }
void ath9k_tx_failed_tasklet(unsigned long data) void ath9k_tx_failed_tasklet(struct tasklet_struct *t)
{ {
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; struct ath9k_htc_priv *priv = from_tasklet(priv, t, tx_failed_tasklet);
spin_lock(&priv->tx.tx_lock); spin_lock(&priv->tx.tx_lock);
if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
@ -1062,9 +1062,9 @@ rx_next:
/* /*
* FIXME: Handle FLUSH later on. * FIXME: Handle FLUSH later on.
*/ */
void ath9k_rx_tasklet(unsigned long data) void ath9k_rx_tasklet(struct tasklet_struct *t)
{ {
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; struct ath9k_htc_priv *priv = from_tasklet(priv, t, rx_tasklet);
struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL;
struct ieee80211_rx_status rx_status; struct ieee80211_rx_status rx_status;
struct sk_buff *skb; struct sk_buff *skb;

View file

@ -728,9 +728,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
spin_lock_init(&sc->sc_pm_lock); spin_lock_init(&sc->sc_pm_lock);
spin_lock_init(&sc->chan_lock); spin_lock_init(&sc->chan_lock);
mutex_init(&sc->mutex); mutex_init(&sc->mutex);
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_setup(&sc->intr_tq, ath9k_tasklet);
tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, tasklet_setup(&sc->bcon_tasklet, ath9k_beacon_tasklet);
(unsigned long)sc);
timer_setup(&sc->sleep_timer, ath_ps_full_sleep, 0); timer_setup(&sc->sleep_timer, ath_ps_full_sleep, 0);
INIT_WORK(&sc->hw_reset_work, ath_reset_work); INIT_WORK(&sc->hw_reset_work, ath_reset_work);

View file

@ -371,9 +371,9 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
ath_dynack_node_deinit(sc->sc_ah, an); ath_dynack_node_deinit(sc->sc_ah, an);
} }
void ath9k_tasklet(unsigned long data) void ath9k_tasklet(struct tasklet_struct *t)
{ {
struct ath_softc *sc = (struct ath_softc *)data; struct ath_softc *sc = from_tasklet(sc, t, intr_tq);
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
enum ath_reset_type type; enum ath_reset_type type;

View file

@ -106,8 +106,7 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv)
mutex_init(&wmi->multi_rmw_mutex); mutex_init(&wmi->multi_rmw_mutex);
init_completion(&wmi->cmd_wait); init_completion(&wmi->cmd_wait);
INIT_LIST_HEAD(&wmi->pending_tx_events); INIT_LIST_HEAD(&wmi->pending_tx_events);
tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet, tasklet_setup(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet);
(unsigned long)wmi);
return wmi; return wmi;
} }
@ -136,9 +135,9 @@ void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv)
spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
} }
void ath9k_wmi_event_tasklet(unsigned long data) void ath9k_wmi_event_tasklet(struct tasklet_struct *t)
{ {
struct wmi *wmi = (struct wmi *)data; struct wmi *wmi = from_tasklet(wmi, t, wmi_event_tasklet);
struct ath9k_htc_priv *priv = wmi->drv_priv; struct ath9k_htc_priv *priv = wmi->drv_priv;
struct wmi_cmd_hdr *hdr; struct wmi_cmd_hdr *hdr;
void *wmi_event; void *wmi_event;

View file

@ -185,7 +185,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
u8 *cmd_buf, u32 cmd_len, u8 *cmd_buf, u32 cmd_len,
u8 *rsp_buf, u32 rsp_len, u8 *rsp_buf, u32 rsp_len,
u32 timeout); u32 timeout);
void ath9k_wmi_event_tasklet(unsigned long data); void ath9k_wmi_event_tasklet(struct tasklet_struct *t);
void ath9k_fatal_work(struct work_struct *work); void ath9k_fatal_work(struct work_struct *work);
void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv); void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv);
void ath9k_stop_wmi(struct ath9k_htc_priv *priv); void ath9k_stop_wmi(struct ath9k_htc_priv *priv);

View file

@ -68,7 +68,10 @@
#define PAYLOAD_MAX (CARL9170_MAX_CMD_LEN / 4 - 1) #define PAYLOAD_MAX (CARL9170_MAX_CMD_LEN / 4 - 1)
static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 }; static inline u8 ar9170_qmap(u8 idx)
{
return 3 - idx; /* { 3, 2, 1, 0 } */
}
#define CARL9170_MAX_RX_BUFFER_SIZE 8192 #define CARL9170_MAX_RX_BUFFER_SIZE 8192

View file

@ -1374,7 +1374,7 @@ static int carl9170_op_conf_tx(struct ieee80211_hw *hw,
int ret; int ret;
mutex_lock(&ar->mutex); mutex_lock(&ar->mutex);
memcpy(&ar->edcf[ar9170_qmap[queue]], param, sizeof(*param)); memcpy(&ar->edcf[ar9170_qmap(queue)], param, sizeof(*param));
ret = carl9170_set_qos(ar); ret = carl9170_set_qos(ar);
mutex_unlock(&ar->mutex); mutex_unlock(&ar->mutex);
return ret; return ret;

View file

@ -766,7 +766,7 @@ static void carl9170_rx_untie_data(struct ar9170 *ar, u8 *buf, int len)
goto drop; goto drop;
} }
/* fall through */ fallthrough;
case AR9170_RX_STATUS_MPDU_MIDDLE: case AR9170_RX_STATUS_MPDU_MIDDLE:
/* These are just data + mac status */ /* These are just data + mac status */

View file

@ -663,7 +663,7 @@ static void __carl9170_tx_process_status(struct ar9170 *ar,
unsigned int r, t, q; unsigned int r, t, q;
bool success = true; bool success = true;
q = ar9170_qmap[info & CARL9170_TX_STATUS_QUEUE]; q = ar9170_qmap(info & CARL9170_TX_STATUS_QUEUE);
skb = carl9170_get_queued_skb(ar, cookie, &ar->tx_status[q]); skb = carl9170_get_queued_skb(ar, cookie, &ar->tx_status[q]);
if (!skb) { if (!skb) {
@ -830,12 +830,12 @@ static bool carl9170_tx_rts_check(struct ar9170 *ar,
case CARL9170_ERP_AUTO: case CARL9170_ERP_AUTO:
if (ampdu) if (ampdu)
break; break;
/* fall through */ fallthrough;
case CARL9170_ERP_MAC80211: case CARL9170_ERP_MAC80211:
if (!(rate->flags & IEEE80211_TX_RC_USE_RTS_CTS)) if (!(rate->flags & IEEE80211_TX_RC_USE_RTS_CTS))
break; break;
/* fall through */ fallthrough;
case CARL9170_ERP_RTS: case CARL9170_ERP_RTS:
if (likely(!multi)) if (likely(!multi))
@ -856,7 +856,7 @@ static bool carl9170_tx_cts_check(struct ar9170 *ar,
case CARL9170_ERP_MAC80211: case CARL9170_ERP_MAC80211:
if (!(rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) if (!(rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
break; break;
/* fall through */ fallthrough;
case CARL9170_ERP_CTS: case CARL9170_ERP_CTS:
return true; return true;
@ -979,7 +979,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
((CARL9170_TX_SUPER_MISC_VIF_ID >> ((CARL9170_TX_SUPER_MISC_VIF_ID >>
CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1)); CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1));
hw_queue = ar9170_qmap[carl9170_get_queue(ar, skb)]; hw_queue = ar9170_qmap(carl9170_get_queue(ar, skb));
hdr = (void *)skb->data; hdr = (void *)skb->data;
info = IEEE80211_SKB_CB(skb); info = IEEE80211_SKB_CB(skb);
@ -1279,7 +1279,7 @@ void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb)
super = (void *)skb->data; super = (void *)skb->data;
SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, q, SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, q,
ar9170_qmap[carl9170_get_queue(ar, skb)]); ar9170_qmap(carl9170_get_queue(ar, skb)));
__carl9170_tx_process_status(ar, super->s.cookie, q); __carl9170_tx_process_status(ar, super->s.cookie, q);
} }

View file

@ -377,9 +377,9 @@ void carl9170_usb_handle_tx_err(struct ar9170 *ar)
} }
} }
static void carl9170_usb_tasklet(unsigned long data) static void carl9170_usb_tasklet(struct tasklet_struct *t)
{ {
struct ar9170 *ar = (struct ar9170 *) data; struct ar9170 *ar = from_tasklet(ar, t, usb_tasklet);
if (!IS_INITIALIZED(ar)) if (!IS_INITIALIZED(ar))
return; return;
@ -1082,8 +1082,7 @@ static int carl9170_usb_probe(struct usb_interface *intf,
init_completion(&ar->cmd_wait); init_completion(&ar->cmd_wait);
init_completion(&ar->fw_boot_wait); init_completion(&ar->fw_boot_wait);
init_completion(&ar->fw_load_wait); init_completion(&ar->fw_load_wait);
tasklet_init(&ar->usb_tasklet, carl9170_usb_tasklet, tasklet_setup(&ar->usb_tasklet, carl9170_usb_tasklet);
(unsigned long)ar);
atomic_set(&ar->tx_cmd_urbs, 0); atomic_set(&ar->tx_cmd_urbs, 0);
atomic_set(&ar->tx_anch_urbs, 0); atomic_set(&ar->tx_anch_urbs, 0);

View file

@ -728,6 +728,14 @@ enum pe_stats_mask {
#define WCN36XX_HAL_CFG_ENABLE_TDLS_OXYGEN_MODE 104 #define WCN36XX_HAL_CFG_ENABLE_TDLS_OXYGEN_MODE 104
#define WCN36XX_HAL_CFG_MAX_PARAMS 105 #define WCN36XX_HAL_CFG_MAX_PARAMS 105
/* Specify the starting bitrate, 11B and 11A/G rates can be specified in
* multiples of 0.5 So for 5.5 mbps => 11. for MCS 0 - 7 rates, Bit 7 should
* set to 1 and Bit 0-6 represent the MCS index. so for MCS2 => 130.
* Any invalid non-zero value or unsupported rate will set the start rate
* to 6 mbps.
*/
#define WCN36XX_HAL_CFG_ENABLE_DYNAMIC_RA_START_RATE 210
/* Message definitons - All the messages below need to be packed */ /* Message definitons - All the messages below need to be packed */
/* Definition for HAL API Version. */ /* Definition for HAL API Version. */
@ -1405,6 +1413,76 @@ struct wcn36xx_hal_config_sta_req_msg {
struct wcn36xx_hal_config_sta_params sta_params; struct wcn36xx_hal_config_sta_params sta_params;
} __packed; } __packed;
struct wcn36xx_hal_supported_rates_v1 {
/* For Self STA Entry: this represents Self Mode.
* For Peer Stations, this represents the mode of the peer.
* On Station:
*
* --this mode is updated when PE adds the Self Entry.
*
* -- OR when PE sends 'ADD_BSS' message and station context in BSS
* is used to indicate the mode of the AP.
*
* ON AP:
*
* -- this mode is updated when PE sends 'ADD_BSS' and Sta entry
* for that BSS is used to indicate the self mode of the AP.
*
* -- OR when a station is associated, PE sends 'ADD_STA' message
* with this mode updated.
*/
enum sta_rate_mode op_rate_mode;
/* 11b, 11a and aniLegacyRates are IE rates which gives rate in
* unit of 500Kbps
*/
u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES];
u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES];
u16 legacy_rates[WCN36XX_HAL_NUM_POLARIS_RATES];
u16 reserved;
/* Taurus only supports 26 Titan Rates(no ESF/concat Rates will be
* supported) First 26 bits are reserved for those Titan rates and
* the last 4 bits(bit28-31) for Taurus, 2(bit26-27) bits are
* reserved
* Titan and Taurus Rates
*/
u32 enhanced_rate_bitmap;
/* 0-76 bits used, remaining reserved
* bits 0-15 and 32 should be set.
*/
u8 supported_mcs_set[WCN36XX_HAL_MAC_MAX_SUPPORTED_MCS_SET];
/* RX Highest Supported Data Rate defines the highest data
* rate that the STA is able to receive, in unites of 1Mbps.
* This value is derived from "Supported MCS Set field" inside
* the HT capability element.
*/
u16 rx_highest_data_rate;
/* Indicates the Maximum MCS that can be received for each spatial
* stream.
*/
u16 vht_rx_mcs_map;
/* Indicates the highest VHT data rate that the STA is able to
* receive.
*/
u16 vht_rx_highest_data_rate;
/* Indicates the Maximum MCS that can be transmitted for each spatial
* stream.
*/
u16 vht_tx_mcs_map;
/* Indicates the highest VHT data rate that the STA is able to
* transmit.
*/
u16 vht_tx_highest_data_rate;
} __packed;
struct wcn36xx_hal_config_sta_params_v1 { struct wcn36xx_hal_config_sta_params_v1 {
/* BSSID of STA */ /* BSSID of STA */
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
@ -1507,7 +1585,11 @@ struct wcn36xx_hal_config_sta_params_v1 {
u8 p2p; u8 p2p;
/* Reserved to align next field on a dword boundary */ /* Reserved to align next field on a dword boundary */
u8 reserved; u8 ht_ldpc_enabled:1;
u8 vht_ldpc_enabled:1;
u8 vht_tx_bf_enabled:1;
u8 vht_tx_mu_beamformee_capable:1;
u8 reserved:4;
/* These rates are the intersection of peer and self capabilities. */ /* These rates are the intersection of peer and self capabilities. */
struct wcn36xx_hal_supported_rates supported_rates; struct wcn36xx_hal_supported_rates supported_rates;

View file

@ -354,8 +354,6 @@ static void wcn36xx_stop(struct ieee80211_hw *hw)
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n"); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n");
cancel_work_sync(&wcn->scan_work);
mutex_lock(&wcn->scan_lock); mutex_lock(&wcn->scan_lock);
if (wcn->scan_req) { if (wcn->scan_req) {
struct cfg80211_scan_info scan_info = { struct cfg80211_scan_info scan_info = {
@ -378,11 +376,36 @@ static void wcn36xx_stop(struct ieee80211_hw *hw)
kfree(wcn->hal_buf); kfree(wcn->hal_buf);
} }
static void wcn36xx_change_ps(struct wcn36xx *wcn, bool enable)
{
struct ieee80211_vif *vif = NULL;
struct wcn36xx_vif *tmp;
list_for_each_entry(tmp, &wcn->vif_list, list) {
vif = wcn36xx_priv_to_vif(tmp);
if (enable && !wcn->sw_scan) {
if (vif->bss_conf.ps) /* ps allowed ? */
wcn36xx_pmc_enter_bmps_state(wcn, vif);
} else {
wcn36xx_pmc_exit_bmps_state(wcn, vif);
}
}
}
static void wcn36xx_change_opchannel(struct wcn36xx *wcn, int ch)
{
struct ieee80211_vif *vif = NULL;
struct wcn36xx_vif *tmp;
list_for_each_entry(tmp, &wcn->vif_list, list) {
vif = wcn36xx_priv_to_vif(tmp);
wcn36xx_smd_switch_channel(wcn, vif, ch);
}
}
static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
{ {
struct wcn36xx *wcn = hw->priv; struct wcn36xx *wcn = hw->priv;
struct ieee80211_vif *vif = NULL;
struct wcn36xx_vif *tmp;
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed); wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed);
@ -392,23 +415,28 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
int ch = WCN36XX_HW_CHANNEL(wcn); int ch = WCN36XX_HW_CHANNEL(wcn);
wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n", wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n",
ch); ch);
list_for_each_entry(tmp, &wcn->vif_list, list) {
vif = wcn36xx_priv_to_vif(tmp); if (wcn->sw_scan_opchannel == ch) {
wcn36xx_smd_switch_channel(wcn, vif, ch); /* If channel is the initial operating channel, we may
* want to receive/transmit regular data packets, then
* simply stop the scan session and exit PS mode.
*/
wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN,
wcn->sw_scan_vif);
} else if (wcn->sw_scan) {
/* A scan is ongoing, do not change the operating
* channel, but start a scan session on the channel.
*/
wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN,
wcn->sw_scan_vif);
wcn36xx_smd_start_scan(wcn, ch);
} else {
wcn36xx_change_opchannel(wcn, ch);
} }
} }
if (changed & IEEE80211_CONF_CHANGE_PS) { if (changed & IEEE80211_CONF_CHANGE_PS)
list_for_each_entry(tmp, &wcn->vif_list, list) { wcn36xx_change_ps(wcn, hw->conf.flags & IEEE80211_CONF_PS);
vif = wcn36xx_priv_to_vif(tmp);
if (hw->conf.flags & IEEE80211_CONF_PS) {
if (vif->bss_conf.ps) /* ps allowed ? */
wcn36xx_pmc_enter_bmps_state(wcn, vif);
} else {
wcn36xx_pmc_exit_bmps_state(wcn, vif);
}
}
}
mutex_unlock(&wcn->conf_mutex); mutex_unlock(&wcn->conf_mutex);
@ -582,6 +610,15 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
} }
} }
} }
/* FIXME: Only enable bmps support when encryption is enabled.
* For any reasons, when connected to open/no-security BSS,
* the wcn36xx controller in bmps mode does not forward
* 'wake-up' beacons despite AP sends DTIM with station AID.
* It could be due to a firmware issue or to the way driver
* configure the station.
*/
if (vif->type == NL80211_IFTYPE_STATION)
vif_priv->allow_bmps = true;
break; break;
case DISABLE_KEY: case DISABLE_KEY:
if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
@ -614,55 +651,26 @@ out:
return ret; return ret;
} }
static void wcn36xx_hw_scan_worker(struct work_struct *work)
{
struct wcn36xx *wcn = container_of(work, struct wcn36xx, scan_work);
struct cfg80211_scan_request *req = wcn->scan_req;
u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX];
struct cfg80211_scan_info scan_info = {};
bool aborted = false;
int i;
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", req->n_channels);
for (i = 0; i < req->n_channels; i++)
channels[i] = req->channels[i]->hw_value;
wcn36xx_smd_update_scan_params(wcn, channels, req->n_channels);
wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN);
for (i = 0; i < req->n_channels; i++) {
mutex_lock(&wcn->scan_lock);
aborted = wcn->scan_aborted;
mutex_unlock(&wcn->scan_lock);
if (aborted)
break;
wcn->scan_freq = req->channels[i]->center_freq;
wcn->scan_band = req->channels[i]->band;
wcn36xx_smd_start_scan(wcn, req->channels[i]->hw_value);
msleep(30);
wcn36xx_smd_end_scan(wcn, req->channels[i]->hw_value);
wcn->scan_freq = 0;
}
wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
scan_info.aborted = aborted;
ieee80211_scan_completed(wcn->hw, &scan_info);
mutex_lock(&wcn->scan_lock);
wcn->scan_req = NULL;
mutex_unlock(&wcn->scan_lock);
}
static int wcn36xx_hw_scan(struct ieee80211_hw *hw, static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_scan_request *hw_req) struct ieee80211_scan_request *hw_req)
{ {
struct wcn36xx *wcn = hw->priv; struct wcn36xx *wcn = hw->priv;
int i;
if (!get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
/* fallback to mac80211 software scan */
return 1;
}
/* For unknown reason, the hardware offloaded scan only works with
* 2.4Ghz channels, fallback to software scan in other cases.
*/
for (i = 0; i < hw_req->req.n_channels; i++) {
if (hw_req->req.channels[i]->band != NL80211_BAND_2GHZ)
return 1;
}
mutex_lock(&wcn->scan_lock); mutex_lock(&wcn->scan_lock);
if (wcn->scan_req) { if (wcn->scan_req) {
mutex_unlock(&wcn->scan_lock); mutex_unlock(&wcn->scan_lock);
@ -674,12 +682,6 @@ static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
mutex_unlock(&wcn->scan_lock); mutex_unlock(&wcn->scan_lock);
if (!get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
/* legacy manual/sw scan */
schedule_work(&wcn->scan_work);
return 0;
}
return wcn36xx_smd_start_hw_scan(wcn, vif, &hw_req->req); return wcn36xx_smd_start_hw_scan(wcn, vif, &hw_req->req);
} }
@ -696,16 +698,35 @@ static void wcn36xx_cancel_hw_scan(struct ieee80211_hw *hw,
/* ieee80211_scan_completed will be called on FW scan /* ieee80211_scan_completed will be called on FW scan
* indication */ * indication */
wcn36xx_smd_stop_hw_scan(wcn); wcn36xx_smd_stop_hw_scan(wcn);
} else {
struct cfg80211_scan_info scan_info = {
.aborted = true,
};
cancel_work_sync(&wcn->scan_work);
ieee80211_scan_completed(wcn->hw, &scan_info);
} }
} }
static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const u8 *mac_addr)
{
struct wcn36xx *wcn = hw->priv;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
wcn->sw_scan = true;
wcn->sw_scan_vif = vif;
if (vif_priv->sta_assoc)
wcn->sw_scan_opchannel = WCN36XX_HW_CHANNEL(wcn);
else
wcn->sw_scan_opchannel = 0;
}
static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct wcn36xx *wcn = hw->priv;
/* ensure that any scan session is finished */
wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN, wcn->sw_scan_vif);
wcn->sw_scan = false;
wcn->sw_scan_opchannel = 0;
}
static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
enum nl80211_band band) enum nl80211_band band)
{ {
@ -879,6 +900,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
vif->addr, vif->addr,
bss_conf->aid); bss_conf->aid);
vif_priv->sta_assoc = false; vif_priv->sta_assoc = false;
vif_priv->allow_bmps = false;
wcn36xx_smd_set_link_st(wcn, wcn36xx_smd_set_link_st(wcn,
bss_conf->bssid, bss_conf->bssid,
vif->addr, vif->addr,
@ -1151,6 +1173,8 @@ static const struct ieee80211_ops wcn36xx_ops = {
.set_key = wcn36xx_set_key, .set_key = wcn36xx_set_key,
.hw_scan = wcn36xx_hw_scan, .hw_scan = wcn36xx_hw_scan,
.cancel_hw_scan = wcn36xx_cancel_hw_scan, .cancel_hw_scan = wcn36xx_cancel_hw_scan,
.sw_scan_start = wcn36xx_sw_scan_start,
.sw_scan_complete = wcn36xx_sw_scan_complete,
.bss_info_changed = wcn36xx_bss_info_changed, .bss_info_changed = wcn36xx_bss_info_changed,
.set_rts_threshold = wcn36xx_set_rts_threshold, .set_rts_threshold = wcn36xx_set_rts_threshold,
.sta_add = wcn36xx_sta_add, .sta_add = wcn36xx_sta_add,
@ -1283,6 +1307,8 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
if (iris_node) { if (iris_node) {
if (of_device_is_compatible(iris_node, "qcom,wcn3620")) if (of_device_is_compatible(iris_node, "qcom,wcn3620"))
wcn->rf_id = RF_IRIS_WCN3620; wcn->rf_id = RF_IRIS_WCN3620;
if (of_device_is_compatible(iris_node, "qcom,wcn3680"))
wcn->rf_id = RF_IRIS_WCN3680;
of_node_put(iris_node); of_node_put(iris_node);
} }
@ -1329,8 +1355,6 @@ static int wcn36xx_probe(struct platform_device *pdev)
goto out_wq; goto out_wq;
} }
INIT_WORK(&wcn->scan_work, wcn36xx_hw_scan_worker);
wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process, hw); wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process, hw);
if (IS_ERR(wcn->smd_channel)) { if (IS_ERR(wcn->smd_channel)) {
wcn36xx_err("failed to open WLAN_CTRL channel\n"); wcn36xx_err("failed to open WLAN_CTRL channel\n");

View file

@ -23,7 +23,10 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn,
{ {
int ret = 0; int ret = 0;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
/* TODO: Make sure the TX chain clean */
if (!vif_priv->allow_bmps)
return -ENOTSUPP;
ret = wcn36xx_smd_enter_bmps(wcn, vif); ret = wcn36xx_smd_enter_bmps(wcn, vif);
if (!ret) { if (!ret) {
wcn36xx_dbg(WCN36XX_DBG_PMC, "Entered BMPS\n"); wcn36xx_dbg(WCN36XX_DBG_PMC, "Entered BMPS\n");

View file

@ -77,6 +77,7 @@ static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000), WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000),
WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10), WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0), WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 133), /* MCS 5 */
}; };
static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value) static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value)
@ -517,8 +518,10 @@ out:
return ret; return ret;
} }
int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode) int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode,
struct ieee80211_vif *vif)
{ {
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
struct wcn36xx_hal_init_scan_req_msg msg_body; struct wcn36xx_hal_init_scan_req_msg msg_body;
int ret; int ret;
@ -526,6 +529,13 @@ int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode)
INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ); INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ);
msg_body.mode = mode; msg_body.mode = mode;
if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX) {
/* Notify BSSID with null DATA packet */
msg_body.frame_type = 2;
msg_body.notify = 1;
msg_body.scan_entry.bss_index[0] = vif_priv->bss_index;
msg_body.scan_entry.active_bss_count = 1;
}
PREPARE_HAL_BUF(wcn->hal_buf, msg_body); PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
@ -607,8 +617,10 @@ out:
} }
int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
enum wcn36xx_hal_sys_mode mode) enum wcn36xx_hal_sys_mode mode,
struct ieee80211_vif *vif)
{ {
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
struct wcn36xx_hal_finish_scan_req_msg msg_body; struct wcn36xx_hal_finish_scan_req_msg msg_body;
int ret; int ret;
@ -616,6 +628,14 @@ int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ); INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ);
msg_body.mode = mode; msg_body.mode = mode;
msg_body.oper_channel = WCN36XX_HW_CHANNEL(wcn);
if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX) {
/* Notify BSSID with null data packet */
msg_body.notify = 1;
msg_body.frame_type = 2;
msg_body.scan_entry.bss_index[0] = vif_priv->bss_index;
msg_body.scan_entry.active_bss_count = 1;
}
PREPARE_HAL_BUF(wcn->hal_buf, msg_body); PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
@ -1279,87 +1299,71 @@ static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
sta = &bss->sta; sta = &bss->sta;
/* convert orig to v1 */ /* convert orig to v1 */
memcpy(&msg_body->bss_params.bssid, memcpy(bss->bssid, &orig->bss_params.bssid, ETH_ALEN);
&orig->bss_params.bssid, ETH_ALEN); memcpy(bss->self_mac_addr, &orig->bss_params.self_mac_addr, ETH_ALEN);
memcpy(&msg_body->bss_params.self_mac_addr,
&orig->bss_params.self_mac_addr, ETH_ALEN);
msg_body->bss_params.bss_type = orig->bss_params.bss_type; bss->bss_type = orig->bss_params.bss_type;
msg_body->bss_params.oper_mode = orig->bss_params.oper_mode; bss->oper_mode = orig->bss_params.oper_mode;
msg_body->bss_params.nw_type = orig->bss_params.nw_type; bss->nw_type = orig->bss_params.nw_type;
msg_body->bss_params.short_slot_time_supported = bss->short_slot_time_supported =
orig->bss_params.short_slot_time_supported; orig->bss_params.short_slot_time_supported;
msg_body->bss_params.lla_coexist = orig->bss_params.lla_coexist; bss->lla_coexist = orig->bss_params.lla_coexist;
msg_body->bss_params.llb_coexist = orig->bss_params.llb_coexist; bss->llb_coexist = orig->bss_params.llb_coexist;
msg_body->bss_params.llg_coexist = orig->bss_params.llg_coexist; bss->llg_coexist = orig->bss_params.llg_coexist;
msg_body->bss_params.ht20_coexist = orig->bss_params.ht20_coexist; bss->ht20_coexist = orig->bss_params.ht20_coexist;
msg_body->bss_params.lln_non_gf_coexist = bss->lln_non_gf_coexist = orig->bss_params.lln_non_gf_coexist;
orig->bss_params.lln_non_gf_coexist;
msg_body->bss_params.lsig_tx_op_protection_full_support = bss->lsig_tx_op_protection_full_support =
orig->bss_params.lsig_tx_op_protection_full_support; orig->bss_params.lsig_tx_op_protection_full_support;
msg_body->bss_params.rifs_mode = orig->bss_params.rifs_mode; bss->rifs_mode = orig->bss_params.rifs_mode;
msg_body->bss_params.beacon_interval = orig->bss_params.beacon_interval; bss->beacon_interval = orig->bss_params.beacon_interval;
msg_body->bss_params.dtim_period = orig->bss_params.dtim_period; bss->dtim_period = orig->bss_params.dtim_period;
msg_body->bss_params.tx_channel_width_set = bss->tx_channel_width_set = orig->bss_params.tx_channel_width_set;
orig->bss_params.tx_channel_width_set; bss->oper_channel = orig->bss_params.oper_channel;
msg_body->bss_params.oper_channel = orig->bss_params.oper_channel; bss->ext_channel = orig->bss_params.ext_channel;
msg_body->bss_params.ext_channel = orig->bss_params.ext_channel;
msg_body->bss_params.reserved = orig->bss_params.reserved; bss->reserved = orig->bss_params.reserved;
memcpy(&msg_body->bss_params.ssid, memcpy(&bss->ssid, &orig->bss_params.ssid,
&orig->bss_params.ssid,
sizeof(orig->bss_params.ssid)); sizeof(orig->bss_params.ssid));
msg_body->bss_params.action = orig->bss_params.action; bss->action = orig->bss_params.action;
msg_body->bss_params.rateset = orig->bss_params.rateset; bss->rateset = orig->bss_params.rateset;
msg_body->bss_params.ht = orig->bss_params.ht; bss->ht = orig->bss_params.ht;
msg_body->bss_params.obss_prot_enabled = bss->obss_prot_enabled = orig->bss_params.obss_prot_enabled;
orig->bss_params.obss_prot_enabled; bss->rmf = orig->bss_params.rmf;
msg_body->bss_params.rmf = orig->bss_params.rmf; bss->ht_oper_mode = orig->bss_params.ht_oper_mode;
msg_body->bss_params.ht_oper_mode = orig->bss_params.ht_oper_mode; bss->dual_cts_protection = orig->bss_params.dual_cts_protection;
msg_body->bss_params.dual_cts_protection =
orig->bss_params.dual_cts_protection;
msg_body->bss_params.max_probe_resp_retry_limit = bss->max_probe_resp_retry_limit =
orig->bss_params.max_probe_resp_retry_limit; orig->bss_params.max_probe_resp_retry_limit;
msg_body->bss_params.hidden_ssid = orig->bss_params.hidden_ssid; bss->hidden_ssid = orig->bss_params.hidden_ssid;
msg_body->bss_params.proxy_probe_resp = bss->proxy_probe_resp = orig->bss_params.proxy_probe_resp;
orig->bss_params.proxy_probe_resp; bss->edca_params_valid = orig->bss_params.edca_params_valid;
msg_body->bss_params.edca_params_valid =
orig->bss_params.edca_params_valid;
memcpy(&msg_body->bss_params.acbe, memcpy(&bss->acbe, &orig->bss_params.acbe,
&orig->bss_params.acbe,
sizeof(orig->bss_params.acbe)); sizeof(orig->bss_params.acbe));
memcpy(&msg_body->bss_params.acbk, memcpy(&bss->acbk, &orig->bss_params.acbk,
&orig->bss_params.acbk,
sizeof(orig->bss_params.acbk)); sizeof(orig->bss_params.acbk));
memcpy(&msg_body->bss_params.acvi, memcpy(&bss->acvi, &orig->bss_params.acvi,
&orig->bss_params.acvi,
sizeof(orig->bss_params.acvi)); sizeof(orig->bss_params.acvi));
memcpy(&msg_body->bss_params.acvo, memcpy(&bss->acvo, &orig->bss_params.acvo,
&orig->bss_params.acvo,
sizeof(orig->bss_params.acvo)); sizeof(orig->bss_params.acvo));
msg_body->bss_params.ext_set_sta_key_param_valid = bss->ext_set_sta_key_param_valid =
orig->bss_params.ext_set_sta_key_param_valid; orig->bss_params.ext_set_sta_key_param_valid;
memcpy(&msg_body->bss_params.ext_set_sta_key_param, memcpy(&bss->ext_set_sta_key_param,
&orig->bss_params.ext_set_sta_key_param, &orig->bss_params.ext_set_sta_key_param,
sizeof(orig->bss_params.acvo)); sizeof(orig->bss_params.acvo));
msg_body->bss_params.wcn36xx_hal_persona = bss->wcn36xx_hal_persona = orig->bss_params.wcn36xx_hal_persona;
orig->bss_params.wcn36xx_hal_persona; bss->spectrum_mgt_enable = orig->bss_params.spectrum_mgt_enable;
msg_body->bss_params.spectrum_mgt_enable = bss->tx_mgmt_power = orig->bss_params.tx_mgmt_power;
orig->bss_params.spectrum_mgt_enable; bss->max_tx_power = orig->bss_params.max_tx_power;
msg_body->bss_params.tx_mgmt_power = orig->bss_params.tx_mgmt_power;
msg_body->bss_params.max_tx_power = orig->bss_params.max_tx_power;
wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta, wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta, sta);
&msg_body->bss_params.sta);
PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body)); PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
@ -2080,6 +2084,8 @@ int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ); INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
set_feat_caps(msg_body.feat_caps, STA_POWERSAVE); set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
if (wcn->rf_id == RF_IRIS_WCN3680)
set_feat_caps(msg_body.feat_caps, DOT11AC);
PREPARE_HAL_BUF(wcn->hal_buf, msg_body); PREPARE_HAL_BUF(wcn->hal_buf, msg_body);

View file

@ -59,11 +59,13 @@ void wcn36xx_smd_close(struct wcn36xx *wcn);
int wcn36xx_smd_load_nv(struct wcn36xx *wcn); int wcn36xx_smd_load_nv(struct wcn36xx *wcn);
int wcn36xx_smd_start(struct wcn36xx *wcn); int wcn36xx_smd_start(struct wcn36xx *wcn);
int wcn36xx_smd_stop(struct wcn36xx *wcn); int wcn36xx_smd_stop(struct wcn36xx *wcn);
int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode);
int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel); int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel);
int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel); int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel);
int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode,
enum wcn36xx_hal_sys_mode mode); struct ieee80211_vif *vif);
int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode,
struct ieee80211_vif *vif);
int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, u8 *channels, size_t channel_count); int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, u8 *channels, size_t channel_count);
int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif, int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif,
struct cfg80211_scan_request *req); struct cfg80211_scan_request *req);

View file

@ -114,7 +114,114 @@ static const struct wcn36xx_rate wcn36xx_rate_table[] = {
{ 1215, 6, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, { 1215, 6, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
{ 1350, 7, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, { 1350, 7, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
/* TODO: AC rates */ /* 11ac reserved indices */
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
/* 11ac 20 MHz 800ns GI MCS 0-8 */
{ 65, 0, RX_ENC_HT, 0, RATE_INFO_BW_20 },
{ 130, 1, RX_ENC_HT, 0, RATE_INFO_BW_20 },
{ 195, 2, RX_ENC_HT, 0, RATE_INFO_BW_20 },
{ 260, 3, RX_ENC_HT, 0, RATE_INFO_BW_20 },
{ 390, 4, RX_ENC_HT, 0, RATE_INFO_BW_20 },
{ 520, 5, RX_ENC_HT, 0, RATE_INFO_BW_20 },
{ 585, 6, RX_ENC_HT, 0, RATE_INFO_BW_20 },
{ 650, 7, RX_ENC_HT, 0, RATE_INFO_BW_20 },
{ 780, 8, RX_ENC_HT, 0, RATE_INFO_BW_20 },
/* 11ac reserved indices */
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
/* 11ac 20 MHz 400ns SGI MCS 6-8 */
{ 655, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
{ 722, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
{ 866, 8, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
/* 11ac reserved indices */
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
/* 11ac 40 MHz 800ns GI MCS 0-9 */
{ 135, 0, RX_ENC_HT, 0, RATE_INFO_BW_40 },
{ 270, 1, RX_ENC_HT, 0, RATE_INFO_BW_40 },
{ 405, 2, RX_ENC_HT, 0, RATE_INFO_BW_40 },
{ 540, 3, RX_ENC_HT, 0, RATE_INFO_BW_40 },
{ 810, 4, RX_ENC_HT, 0, RATE_INFO_BW_40 },
{ 1080, 5, RX_ENC_HT, 0, RATE_INFO_BW_40 },
{ 1215, 6, RX_ENC_HT, 0, RATE_INFO_BW_40 },
{ 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 },
{ 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 },
{ 1620, 8, RX_ENC_HT, 0, RATE_INFO_BW_40 },
{ 1800, 9, RX_ENC_HT, 0, RATE_INFO_BW_40 },
/* 11ac reserved indices */
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
/* 11ac 40 MHz 400ns SGI MCS 5-7 */
{ 1200, 5, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1500, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
/* 11ac reserved index */
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
/* 11ac 40 MHz 400ns SGI MCS 5-7 */
{ 1800, 8, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 2000, 9, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
/* 11ac reserved index */
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
/* 11ac 80 MHz 800ns GI MCS 0-7 */
{ 292, 0, RX_ENC_HT, 0, RATE_INFO_BW_80},
{ 585, 1, RX_ENC_HT, 0, RATE_INFO_BW_80},
{ 877, 2, RX_ENC_HT, 0, RATE_INFO_BW_80},
{ 1170, 3, RX_ENC_HT, 0, RATE_INFO_BW_80},
{ 1755, 4, RX_ENC_HT, 0, RATE_INFO_BW_80},
{ 2340, 5, RX_ENC_HT, 0, RATE_INFO_BW_80},
{ 2632, 6, RX_ENC_HT, 0, RATE_INFO_BW_80},
{ 2925, 7, RX_ENC_HT, 0, RATE_INFO_BW_80},
/* 11 ac reserved index */
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
/* 11ac 80 MHz 800 ns GI MCS 8-9 */
{ 3510, 8, RX_ENC_HT, 0, RATE_INFO_BW_80},
{ 3900, 9, RX_ENC_HT, 0, RATE_INFO_BW_80},
/* 11 ac reserved indices */
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
/* 11ac 80 MHz 400 ns SGI MCS 6-7 */
{ 2925, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 },
{ 3250, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 },
/* 11ac reserved index */
{ 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
/* 11ac 80 MHz 400ns SGI MCS 8-9 */
{ 3900, 8, RX_ENC_VHT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 },
{ 4333, 9, RX_ENC_VHT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 },
}; };
int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
@ -123,6 +230,7 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
const struct wcn36xx_rate *rate; const struct wcn36xx_rate *rate;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
struct wcn36xx_rx_bd *bd; struct wcn36xx_rx_bd *bd;
struct ieee80211_supported_band *sband;
u16 fc, sn; u16 fc, sn;
/* /*
@ -144,15 +252,8 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
fc = __le16_to_cpu(hdr->frame_control); fc = __le16_to_cpu(hdr->frame_control);
sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)); sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl));
/* When scanning associate beacons to this */
if (ieee80211_is_beacon(hdr->frame_control) && wcn->scan_freq) {
status.freq = wcn->scan_freq;
status.band = wcn->scan_band;
} else {
status.freq = WCN36XX_CENTER_FREQ(wcn); status.freq = WCN36XX_CENTER_FREQ(wcn);
status.band = WCN36XX_BAND(wcn); status.band = WCN36XX_BAND(wcn);
}
status.mactime = 10; status.mactime = 10;
status.signal = -get_rssi0(bd); status.signal = -get_rssi0(bd);
status.antenna = 1; status.antenna = 1;
@ -170,6 +271,15 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
status.enc_flags = rate->encoding_flags; status.enc_flags = rate->encoding_flags;
status.bw = rate->bw; status.bw = rate->bw;
status.rate_idx = rate->mcs_or_legacy_index; status.rate_idx = rate->mcs_or_legacy_index;
sband = wcn->hw->wiphy->bands[status.band];
status.nss = 1;
if (status.band == NL80211_BAND_5GHZ &&
status.encoding == RX_ENC_LEGACY &&
status.rate_idx >= sband->n_bitrates) {
/* no dsss rates in 5Ghz rates table */
status.rate_idx -= 4;
}
} else { } else {
status.encoding = 0; status.encoding = 0;
status.bw = 0; status.bw = 0;

View file

@ -92,6 +92,7 @@ enum wcn36xx_ampdu_state {
#define RF_UNKNOWN 0x0000 #define RF_UNKNOWN 0x0000
#define RF_IRIS_WCN3620 0x3620 #define RF_IRIS_WCN3620 0x3620
#define RF_IRIS_WCN3680 0x3680
static inline void buff_to_be(u32 *buf, size_t len) static inline void buff_to_be(u32 *buf, size_t len)
{ {
@ -122,6 +123,7 @@ struct wcn36xx_vif {
enum wcn36xx_hal_bss_type bss_type; enum wcn36xx_hal_bss_type bss_type;
/* Power management */ /* Power management */
bool allow_bmps;
enum wcn36xx_power_state pw_state; enum wcn36xx_power_state pw_state;
u8 bss_index; u8 bss_index;
@ -223,10 +225,10 @@ struct wcn36xx {
spinlock_t hal_ind_lock; spinlock_t hal_ind_lock;
struct list_head hal_ind_queue; struct list_head hal_ind_queue;
struct work_struct scan_work;
struct cfg80211_scan_request *scan_req; struct cfg80211_scan_request *scan_req;
int scan_freq; bool sw_scan;
int scan_band; u8 sw_scan_opchannel;
struct ieee80211_vif *sw_scan_vif;
struct mutex scan_lock; struct mutex scan_lock;
bool scan_aborted; bool scan_aborted;

View file

@ -443,10 +443,10 @@ DEFINE_DEBUGFS_ATTRIBUTE(wil_fops_ulong, wil_debugfs_ulong_get,
/** /**
* wil6210_debugfs_init_offset - create set of debugfs files * wil6210_debugfs_init_offset - create set of debugfs files
* @wil - driver's context, used for printing * @wil: driver's context, used for printing
* @dbg - directory on the debugfs, where files will be created * @dbg: directory on the debugfs, where files will be created
* @base - base address used in address calculation * @base: base address used in address calculation
* @tbl - table with file descriptions. Should be terminated with empty element. * @tbl: table with file descriptions. Should be terminated with empty element.
* *
* Creates files accordingly to the @tbl. * Creates files accordingly to the @tbl.
*/ */

View file

@ -645,9 +645,7 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/** /* thread IRQ handler */
* thread IRQ handler
*/
static irqreturn_t wil6210_thread_irq(int irq, void *cookie) static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
{ {
struct wil6210_priv *wil = cookie; struct wil6210_priv *wil = cookie;

View file

@ -29,8 +29,7 @@ void wil_pmc_init(struct wil6210_priv *wil)
mutex_init(&wil->pmc.lock); mutex_init(&wil->pmc.lock);
} }
/** /* Allocate the physical ring (p-ring) and the required
* Allocate the physical ring (p-ring) and the required
* number of descriptors of required size. * number of descriptors of required size.
* Initialize the descriptors as required by pmc dma. * Initialize the descriptors as required by pmc dma.
* The descriptors' buffers dwords are initialized to hold * The descriptors' buffers dwords are initialized to hold
@ -221,8 +220,7 @@ no_release_err:
mutex_unlock(&pmc->lock); mutex_unlock(&pmc->lock);
} }
/** /* Traverse the p-ring and release all buffers.
* Traverse the p-ring and release all buffers.
* At the end release the p-ring memory * At the end release the p-ring memory
*/ */
void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd) void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd)
@ -299,8 +297,7 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd)
mutex_unlock(&pmc->lock); mutex_unlock(&pmc->lock);
} }
/** /* Status of the last operation requested via debugfs: alloc/free/read.
* Status of the last operation requested via debugfs: alloc/free/read.
* 0 - success or negative errno * 0 - success or negative errno
*/ */
int wil_pmc_last_cmd_status(struct wil6210_priv *wil) int wil_pmc_last_cmd_status(struct wil6210_priv *wil)
@ -311,8 +308,7 @@ int wil_pmc_last_cmd_status(struct wil6210_priv *wil)
return wil->pmc.last_cmd_status; return wil->pmc.last_cmd_status;
} }
/** /* Read from required position up to the end of current descriptor,
* Read from required position up to the end of current descriptor,
* depends on descriptor size configured during alloc request. * depends on descriptor size configured during alloc request.
*/ */
ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count, ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count,

View file

@ -249,8 +249,7 @@ static void wil_vring_free(struct wil6210_priv *wil, struct wil_ring *vring)
vring->ctx = NULL; vring->ctx = NULL;
} }
/** /* Allocate one skb for Rx VRING
* Allocate one skb for Rx VRING
* *
* Safe to call from IRQ * Safe to call from IRQ
*/ */
@ -295,8 +294,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct wil_ring *vring,
return 0; return 0;
} }
/** /* Adds radiotap header
* Adds radiotap header
* *
* Any error indicated as "Bad FCS" * Any error indicated as "Bad FCS"
* *
@ -432,8 +430,7 @@ static int wil_rx_get_cid_by_skb(struct wil6210_priv *wil, struct sk_buff *skb)
return cid; return cid;
} }
/** /* reap 1 frame from @swhead
* reap 1 frame from @swhead
* *
* Rx descriptor copied to skb->cb * Rx descriptor copied to skb->cb
* *
@ -597,8 +594,7 @@ again:
return skb; return skb;
} }
/** /* allocate and fill up to @count buffers in rx ring
* allocate and fill up to @count buffers in rx ring
* buffers posted at @swtail * buffers posted at @swtail
* Note: we have a single RX queue for servicing all VIFs, but we * Note: we have a single RX queue for servicing all VIFs, but we
* allocate skbs with headroom according to main interface only. This * allocate skbs with headroom according to main interface only. This
@ -1002,8 +998,7 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
wil_netif_rx(skb, ndev, cid, stats, true); wil_netif_rx(skb, ndev, cid, stats, true);
} }
/** /* Proceed all completed skb's from Rx VRING
* Proceed all completed skb's from Rx VRING
* *
* Safe to call from NAPI poll, i.e. softirq with interrupts enabled * Safe to call from NAPI poll, i.e. softirq with interrupts enabled
*/ */
@ -1629,8 +1624,7 @@ void wil_tx_desc_set_nr_frags(struct vring_tx_desc *d, int nr_frags)
d->mac.d[2] |= (nr_frags << MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS); d->mac.d[2] |= (nr_frags << MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS);
} }
/** /* Sets the descriptor @d up for csum and/or TSO offloading. The corresponding
* Sets the descriptor @d up for csum and/or TSO offloading. The corresponding
* @skb is used to obtain the protocol and headers length. * @skb is used to obtain the protocol and headers length.
* @tso_desc_type is a descriptor type for TSO: 0 - a header, 1 - first data, * @tso_desc_type is a descriptor type for TSO: 0 - a header, 1 - first data,
* 2 - middle, 3 - last descriptor. * 2 - middle, 3 - last descriptor.
@ -1660,8 +1654,7 @@ static void wil_tx_desc_offload_setup_tso(struct vring_tx_desc *d,
d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS); d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS);
} }
/** /* Sets the descriptor @d up for csum. The corresponding
* Sets the descriptor @d up for csum. The corresponding
* @skb is used to obtain the protocol and headers length. * @skb is used to obtain the protocol and headers length.
* Returns the protocol: 0 - not TCP, 1 - TCPv4, 2 - TCPv6. * Returns the protocol: 0 - not TCP, 1 - TCPv4, 2 - TCPv6.
* Note, if d==NULL, the function only returns the protocol result. * Note, if d==NULL, the function only returns the protocol result.
@ -2216,8 +2209,7 @@ static int wil_tx_ring(struct wil6210_priv *wil, struct wil6210_vif *vif,
return rc; return rc;
} }
/** /* Check status of tx vrings and stop/wake net queues if needed
* Check status of tx vrings and stop/wake net queues if needed
* It will start/stop net queues of a specific VIF net_device. * It will start/stop net queues of a specific VIF net_device.
* *
* This function does one of two checks: * This function does one of two checks:
@ -2419,8 +2411,7 @@ void wil_tx_latency_calc(struct wil6210_priv *wil, struct sk_buff *skb,
sta->stats.tx_latency_max_us = skb_time_us; sta->stats.tx_latency_max_us = skb_time_us;
} }
/** /* Clean up transmitted skb's from the Tx VRING
* Clean up transmitted skb's from the Tx VRING
* *
* Return number of descriptors cleared * Return number of descriptors cleared
* *
@ -2460,8 +2451,7 @@ int wil_tx_complete(struct wil6210_vif *vif, int ringid)
while (!wil_ring_is_empty(vring)) { while (!wil_ring_is_empty(vring)) {
int new_swtail; int new_swtail;
struct wil_ctx *ctx = &vring->ctx[vring->swtail]; struct wil_ctx *ctx = &vring->ctx[vring->swtail];
/** /* For the fragmented skb, HW will set DU bit only for the
* For the fragmented skb, HW will set DU bit only for the
* last fragment. look for it. * last fragment. look for it.
* In TSO the first DU will include hdr desc * In TSO the first DU will include hdr desc
*/ */

View file

@ -147,9 +147,7 @@ out_free:
return rc; return rc;
} }
/** /* Allocate one skb for Rx descriptor RING */
* Allocate one skb for Rx descriptor RING
*/
static int wil_ring_alloc_skb_edma(struct wil6210_priv *wil, static int wil_ring_alloc_skb_edma(struct wil6210_priv *wil,
struct wil_ring *ring, u32 i) struct wil_ring *ring, u32 i)
{ {
@ -1152,8 +1150,7 @@ wil_get_next_tx_status_msg(struct wil_status_ring *sring, u8 *dr_bit,
*msg = *_msg; *msg = *_msg;
} }
/** /* Clean up transmitted skb's from the Tx descriptor RING.
* Clean up transmitted skb's from the Tx descriptor RING.
* Return number of descriptors cleared. * Return number of descriptors cleared.
*/ */
int wil_tx_sring_handler(struct wil6210_priv *wil, int wil_tx_sring_handler(struct wil6210_priv *wil,
@ -1314,8 +1311,7 @@ again:
return desc_cnt; return desc_cnt;
} }
/** /* Sets the descriptor @d up for csum and/or TSO offloading. The corresponding
* Sets the descriptor @d up for csum and/or TSO offloading. The corresponding
* @skb is used to obtain the protocol and headers length. * @skb is used to obtain the protocol and headers length.
* @tso_desc_type is a descriptor type for TSO: 0 - a header, 1 - first data, * @tso_desc_type is a descriptor type for TSO: 0 - a header, 1 - first data,
* 2 - middle, 3 - last descriptor. * 2 - middle, 3 - last descriptor.

View file

@ -15,8 +15,7 @@ void wil_platform_modexit(void)
{ {
} }
/** /* wil_platform_init() - wil6210 platform module init
* wil_platform_init() - wil6210 platform module init
* *
* The function must be called before all other functions in this module. * The function must be called before all other functions in this module.
* It returns a handle which is used with the rest of the API * It returns a handle which is used with the rest of the API

View file

@ -32,7 +32,7 @@ MODULE_PARM_DESC(led_id,
#define WIL_WMI_PCP_STOP_TO_MS 5000 #define WIL_WMI_PCP_STOP_TO_MS 5000
/** /**
* WMI event receiving - theory of operations * DOC: WMI event receiving - theory of operations
* *
* When firmware about to report WMI event, it fills memory area * When firmware about to report WMI event, it fills memory area
* in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for
@ -49,7 +49,7 @@ MODULE_PARM_DESC(led_id,
*/ */
/** /**
* Addressing - theory of operations * DOC: Addressing - theory of operations
* *
* There are several buses present on the WIL6210 card. * There are several buses present on the WIL6210 card.
* Same memory areas are visible at different address on * Same memory areas are visible at different address on
@ -66,8 +66,7 @@ MODULE_PARM_DESC(led_id,
* AHB address must be used. * AHB address must be used.
*/ */
/** /* sparrow_fw_mapping provides memory remapping table for sparrow
* @sparrow_fw_mapping provides memory remapping table for sparrow
* *
* array size should be in sync with the declaration in the wil6210.h * array size should be in sync with the declaration in the wil6210.h
* *
@ -103,16 +102,14 @@ const struct fw_map sparrow_fw_mapping[] = {
{0x800000, 0x804000, 0x940000, "uc_data", false, false}, {0x800000, 0x804000, 0x940000, "uc_data", false, false},
}; };
/** /* sparrow_d0_mac_rgf_ext - mac_rgf_ext section for Sparrow D0
* @sparrow_d0_mac_rgf_ext - mac_rgf_ext section for Sparrow D0
* it is a bit larger to support extra features * it is a bit larger to support extra features
*/ */
const struct fw_map sparrow_d0_mac_rgf_ext = { const struct fw_map sparrow_d0_mac_rgf_ext = {
0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true, true 0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true, true
}; };
/** /* talyn_fw_mapping provides memory remapping table for Talyn
* @talyn_fw_mapping provides memory remapping table for Talyn
* *
* array size should be in sync with the declaration in the wil6210.h * array size should be in sync with the declaration in the wil6210.h
* *
@ -154,8 +151,7 @@ const struct fw_map talyn_fw_mapping[] = {
{0x800000, 0x808000, 0xa78000, "uc_data", false, false}, {0x800000, 0x808000, 0xa78000, "uc_data", false, false},
}; };
/** /* talyn_mb_fw_mapping provides memory remapping table for Talyn-MB
* @talyn_mb_fw_mapping provides memory remapping table for Talyn-MB
* *
* array size should be in sync with the declaration in the wil6210.h * array size should be in sync with the declaration in the wil6210.h
* *
@ -229,7 +225,7 @@ u8 led_polarity = LED_POLARITY_LOW_ACTIVE;
/** /**
* return AHB address for given firmware internal (linker) address * return AHB address for given firmware internal (linker) address
* @x - internal address * @x: internal address
* If address have no valid AHB mapping, return 0 * If address have no valid AHB mapping, return 0
*/ */
static u32 wmi_addr_remap(u32 x) static u32 wmi_addr_remap(u32 x)
@ -247,7 +243,7 @@ static u32 wmi_addr_remap(u32 x)
/** /**
* find fw_mapping entry by section name * find fw_mapping entry by section name
* @section - section name * @section: section name
* *
* Return pointer to section or NULL if not found * Return pointer to section or NULL if not found
*/ */
@ -265,8 +261,9 @@ struct fw_map *wil_find_fw_mapping(const char *section)
/** /**
* Check address validity for WMI buffer; remap if needed * Check address validity for WMI buffer; remap if needed
* @ptr - internal (linker) fw/ucode address * @wil: driver data
* @size - if non zero, validate the block does not * @ptr: internal (linker) fw/ucode address
* @size: if non zero, validate the block does not
* exceed the device memory (bar) * exceed the device memory (bar)
* *
* Valid buffer should be DWORD aligned * Valid buffer should be DWORD aligned
@ -300,9 +297,7 @@ void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_)
return wmi_buffer_block(wil, ptr_, 0); return wmi_buffer_block(wil, ptr_, 0);
} }
/** /* Check address validity */
* Check address validity
*/
void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr) void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr)
{ {
u32 off; u32 off;
@ -1577,8 +1572,7 @@ wmi_evt_link_stats(struct wil6210_vif *vif, int id, void *d, int len)
evt->payload, payload_size); evt->payload, payload_size);
} }
/** /* find cid and ringid for the station vif
* find cid and ringid for the station vif
* *
* return error, if other interfaces are used or ring was not found * return error, if other interfaces are used or ring was not found
*/ */
@ -1868,8 +1862,7 @@ wmi_evt_link_monitor(struct wil6210_vif *vif, int id, void *d, int len)
cfg80211_cqm_rssi_notify(ndev, event_type, evt->rssi_level, GFP_KERNEL); cfg80211_cqm_rssi_notify(ndev, event_type, evt->rssi_level, GFP_KERNEL);
} }
/** /* Some events are ignored for purpose; and need not be interpreted as
* Some events are ignored for purpose; and need not be interpreted as
* "unhandled events" * "unhandled events"
*/ */
static void wmi_evt_ignore(struct wil6210_vif *vif, int id, void *d, int len) static void wmi_evt_ignore(struct wil6210_vif *vif, int id, void *d, int len)
@ -2578,6 +2571,7 @@ out:
/** /**
* wmi_rxon - turn radio on/off * wmi_rxon - turn radio on/off
* @wil: driver data
* @on: turn on if true, off otherwise * @on: turn on if true, off otherwise
* *
* Only switch radio. Channel should be set separately. * Only switch radio. Channel should be set separately.