mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-17 14:57:36 +07:00
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for 5.5. Major changes: ath10k * add support for hardware rfkill on devices where firmware supports it
This commit is contained in:
commit
97ef12263f
@ -81,6 +81,12 @@ Optional properties:
|
||||
Definition: Name of external front end module used. Some valid FEM names
|
||||
for example: "microsemi-lx5586", "sky85703-11"
|
||||
and "sky85803" etc.
|
||||
- qcom,snoc-host-cap-8bit-quirk:
|
||||
Usage: Optional
|
||||
Value type: <empty>
|
||||
Definition: Quirk specifying that the firmware expects the 8bit version
|
||||
of the host capability QMI request
|
||||
- qcom,xo-cal-data: xo cal offset to be configured in xo trim register.
|
||||
|
||||
Example (to supply PCI based wifi block details):
|
||||
|
||||
|
@ -255,7 +255,8 @@ static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata,
|
||||
|
||||
if (flags & AR5523_CMD_FLAG_MAGIC)
|
||||
hdr->magic = cpu_to_be32(1 << 24);
|
||||
memcpy(hdr + 1, idata, ilen);
|
||||
if (ilen)
|
||||
memcpy(hdr + 1, idata, ilen);
|
||||
|
||||
cmd->odata = odata;
|
||||
cmd->olen = olen;
|
||||
|
@ -677,13 +677,22 @@ static void ath10k_send_suspend_complete(struct ath10k *ar)
|
||||
complete(&ar->target_suspend);
|
||||
}
|
||||
|
||||
static void ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
{
|
||||
int ret;
|
||||
u32 param = 0;
|
||||
|
||||
ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256);
|
||||
ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);
|
||||
ath10k_bmi_read32(ar, hi_acs_flags, ¶m);
|
||||
ret = ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ath10k_bmi_read32(ar, hi_acs_flags, ¶m);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Data transfer is not initiated, when reduced Tx completion
|
||||
* is used for SDIO. disable it until fixed
|
||||
@ -700,14 +709,23 @@ static void ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
else
|
||||
param |= HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET;
|
||||
|
||||
ath10k_bmi_write32(ar, hi_acs_flags, param);
|
||||
ret = ath10k_bmi_write32(ar, hi_acs_flags, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Explicitly set fwlog prints to zero as target may turn it on
|
||||
* based on scratch registers.
|
||||
*/
|
||||
ath10k_bmi_read32(ar, hi_option_flag, ¶m);
|
||||
ret = ath10k_bmi_read32(ar, hi_option_flag, ¶m);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
param |= HI_OPTION_DISABLE_DBGLOG;
|
||||
ath10k_bmi_write32(ar, hi_option_flag, param);
|
||||
ret = ath10k_bmi_write32(ar, hi_option_flag, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_init_configure_target(struct ath10k *ar)
|
||||
@ -2118,12 +2136,15 @@ static int ath10k_init_uart(struct ath10k *ar)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!uart_print && ar->hw_params.uart_pin_workaround) {
|
||||
ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin,
|
||||
ar->hw_params.uart_pin);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set UART TX pin: %d", ret);
|
||||
return ret;
|
||||
if (!uart_print) {
|
||||
if (ar->hw_params.uart_pin_workaround) {
|
||||
ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin,
|
||||
ar->hw_params.uart_pin);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set UART TX pin: %d",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2562,8 +2583,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
if (status)
|
||||
goto err;
|
||||
|
||||
if (ar->hif.bus == ATH10K_BUS_SDIO)
|
||||
ath10k_init_sdio(ar, mode);
|
||||
if (ar->hif.bus == ATH10K_BUS_SDIO) {
|
||||
status = ath10k_init_sdio(ar, mode);
|
||||
if (status) {
|
||||
ath10k_err(ar, "failed to init SDIO: %d\n", status);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ar->htc.htc_ops.target_send_suspend_complete =
|
||||
@ -2784,7 +2810,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
|
||||
status = ath10k_hif_set_target_log_mode(ar, fw_diag_log);
|
||||
if (status && status != -EOPNOTSUPP) {
|
||||
ath10k_warn(ar, "set traget log mode faileds: %d\n", status);
|
||||
ath10k_warn(ar, "set target log mode failed: %d\n", status);
|
||||
goto err_hif_stop;
|
||||
}
|
||||
|
||||
|
@ -169,6 +169,7 @@ struct ath10k_wmi {
|
||||
struct wmi_cmd_map *cmd;
|
||||
struct wmi_vdev_param_map *vdev_param;
|
||||
struct wmi_pdev_param_map *pdev_param;
|
||||
struct wmi_peer_param_map *peer_param;
|
||||
const struct wmi_ops *ops;
|
||||
const struct wmi_peer_flags_map *peer_flags;
|
||||
|
||||
@ -963,12 +964,20 @@ struct ath10k {
|
||||
u32 hw_eeprom_rd;
|
||||
u32 ht_cap_info;
|
||||
u32 vht_cap_info;
|
||||
u32 vht_supp_mcs;
|
||||
u32 num_rf_chains;
|
||||
u32 max_spatial_stream;
|
||||
/* protected by conf_mutex */
|
||||
u32 low_2ghz_chan;
|
||||
u32 high_2ghz_chan;
|
||||
u32 low_5ghz_chan;
|
||||
u32 high_5ghz_chan;
|
||||
bool ani_enabled;
|
||||
u32 sys_cap_info;
|
||||
|
||||
/* protected by data_lock */
|
||||
bool hw_rfkill_on;
|
||||
|
||||
/* protected by conf_mutex */
|
||||
u8 ps_state_enable;
|
||||
|
||||
|
@ -703,7 +703,7 @@ static const struct ath10k_mem_region qca99x0_hw20_mem_regions[] = {
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_REG,
|
||||
.start = 0x98000,
|
||||
.start = 0x980000,
|
||||
.len = 0x50000,
|
||||
.name = "IRAM",
|
||||
.section_table = {
|
||||
@ -786,7 +786,7 @@ static const struct ath10k_mem_region qca9984_hw10_mem_regions[] = {
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_REG,
|
||||
.start = 0x98000,
|
||||
.start = 0x980000,
|
||||
.len = 0x50000,
|
||||
.name = "IRAM",
|
||||
.section_table = {
|
||||
@ -891,7 +891,7 @@ static const struct ath10k_mem_region qca4019_hw10_mem_regions[] = {
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_REG,
|
||||
.start = 0x98000,
|
||||
.start = 0x980000,
|
||||
.len = 0x50000,
|
||||
.name = "IRAM",
|
||||
.section_table = {
|
||||
@ -951,6 +951,19 @@ static const struct ath10k_mem_region qca4019_hw10_mem_regions[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ath10k_mem_region wcn399x_hw10_mem_regions[] = {
|
||||
{
|
||||
/* MSA region start is not fixed, hence it is assigned at runtime */
|
||||
.type = ATH10K_MEM_REGION_TYPE_MSA,
|
||||
.len = 0x100000,
|
||||
.name = "DRAM",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = QCA6174_HW_1_0_VERSION,
|
||||
@ -1048,6 +1061,14 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
.size = ARRAY_SIZE(qca4019_hw10_mem_regions),
|
||||
},
|
||||
},
|
||||
{
|
||||
.hw_id = WCN3990_HW_1_0_DEV_VERSION,
|
||||
.hw_rev = ATH10K_HW_WCN3990,
|
||||
.region_table = {
|
||||
.regions = wcn399x_hw10_mem_regions,
|
||||
.size = ARRAY_SIZE(wcn399x_hw10_mem_regions),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar)
|
||||
@ -1208,9 +1229,11 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar)
|
||||
dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
|
||||
dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_RAM_DATA);
|
||||
dump_tlv->tlv_len = cpu_to_le32(crash_data->ramdump_buf_len);
|
||||
memcpy(dump_tlv->tlv_data, crash_data->ramdump_buf,
|
||||
crash_data->ramdump_buf_len);
|
||||
sofar += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;
|
||||
if (crash_data->ramdump_buf_len) {
|
||||
memcpy(dump_tlv->tlv_data, crash_data->ramdump_buf,
|
||||
crash_data->ramdump_buf_len);
|
||||
sofar += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&ar->dump_mutex);
|
||||
@ -1257,6 +1280,9 @@ int ath10k_coredump_register(struct ath10k *ar)
|
||||
if (test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask)) {
|
||||
crash_data->ramdump_buf_len = ath10k_coredump_get_ramdump_size(ar);
|
||||
|
||||
if (!crash_data->ramdump_buf_len)
|
||||
return 0;
|
||||
|
||||
crash_data->ramdump_buf = vzalloc(crash_data->ramdump_buf_len);
|
||||
if (!crash_data->ramdump_buf)
|
||||
return -ENOMEM;
|
||||
|
@ -115,6 +115,7 @@ enum ath10k_mem_region_type {
|
||||
ATH10K_MEM_REGION_TYPE_IRAM2 = 5,
|
||||
ATH10K_MEM_REGION_TYPE_IOSRAM = 6,
|
||||
ATH10K_MEM_REGION_TYPE_IOREG = 7,
|
||||
ATH10K_MEM_REGION_TYPE_MSA = 8,
|
||||
};
|
||||
|
||||
/* Define a section of the region which should be copied. As not all parts
|
||||
|
@ -430,7 +430,7 @@ ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
|
||||
}
|
||||
|
||||
ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_DEBUG, peer_debug_trigger);
|
||||
ar->wmi.peer_param->debug, peer_debug_trigger);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n",
|
||||
ret);
|
||||
|
@ -2726,7 +2726,7 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
peer = ath10k_peer_find_by_id(ar, peer_id);
|
||||
if (!peer) {
|
||||
if (!peer || !peer->sta) {
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
rcu_read_unlock();
|
||||
continue;
|
||||
|
@ -155,6 +155,9 @@ const struct ath10k_hw_values qca6174_values = {
|
||||
.num_target_ce_config_wlan = 7,
|
||||
.ce_desc_meta_data_mask = 0xFFFC,
|
||||
.ce_desc_meta_data_lsb = 2,
|
||||
.rfkill_pin = 16,
|
||||
.rfkill_cfg = 0,
|
||||
.rfkill_on_level = 1,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_values qca99x0_values = {
|
||||
|
@ -379,6 +379,9 @@ struct ath10k_hw_values {
|
||||
u8 num_target_ce_config_wlan;
|
||||
u16 ce_desc_meta_data_mask;
|
||||
u8 ce_desc_meta_data_lsb;
|
||||
u32 rfkill_pin;
|
||||
u32 rfkill_cfg;
|
||||
bool rfkill_on_level;
|
||||
};
|
||||
|
||||
extern const struct ath10k_hw_values qca988x_values;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/bitfield.h>
|
||||
|
||||
#include "hif.h"
|
||||
#include "core.h"
|
||||
@ -2773,7 +2774,7 @@ static int ath10k_setup_peer_smps(struct ath10k *ar, struct ath10k_vif *arvif,
|
||||
return -EINVAL;
|
||||
|
||||
return ath10k_wmi_peer_set_param(ar, arvif->vdev_id, addr,
|
||||
WMI_PEER_SMPS_STATE,
|
||||
ar->wmi.peer_param->smps_state,
|
||||
ath10k_smps_map[smps]);
|
||||
}
|
||||
|
||||
@ -2930,7 +2931,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
|
||||
* poked with peer param command.
|
||||
*/
|
||||
ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, arvif->bssid,
|
||||
WMI_PEER_DUMMY_VAR, 1);
|
||||
ar->wmi.peer_param->dummy_var, 1);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to poke peer %pM param for ps workaround on vdev %i: %d\n",
|
||||
arvif->bssid, arvif->vdev_id, ret);
|
||||
@ -3708,7 +3709,7 @@ static int ath10k_mac_tx(struct ath10k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ath10k_hw_txrx_mode txmode,
|
||||
enum ath10k_mac_tx_path txpath,
|
||||
struct sk_buff *skb)
|
||||
struct sk_buff *skb, bool noque_offchan)
|
||||
{
|
||||
struct ieee80211_hw *hw = ar->hw;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
@ -3738,10 +3739,10 @@ static int ath10k_mac_tx(struct ath10k *ar,
|
||||
}
|
||||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
||||
if (!noque_offchan && info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
||||
if (!ath10k_mac_tx_frm_has_freq(ar)) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %pK\n",
|
||||
skb);
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac queued offchannel skb %pK len %d\n",
|
||||
skb, skb->len);
|
||||
|
||||
skb_queue_tail(&ar->offchan_tx_queue, skb);
|
||||
ieee80211_queue_work(hw, &ar->offchan_tx_work);
|
||||
@ -3803,8 +3804,8 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK\n",
|
||||
skb);
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK len %d\n",
|
||||
skb, skb->len);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
peer_addr = ieee80211_get_DA(hdr);
|
||||
@ -3850,7 +3851,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
||||
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
|
||||
txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode);
|
||||
|
||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
|
||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, true);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to transmit offchannel frame: %d\n",
|
||||
ret);
|
||||
@ -3860,8 +3861,8 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
||||
time_left =
|
||||
wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ);
|
||||
if (time_left == 0)
|
||||
ath10k_warn(ar, "timed out waiting for offchannel skb %pK\n",
|
||||
skb);
|
||||
ath10k_warn(ar, "timed out waiting for offchannel skb %pK, len: %d\n",
|
||||
skb, skb->len);
|
||||
|
||||
if (!peer && tmp_peer_created) {
|
||||
ret = ath10k_peer_delete(ar, vdev_id, peer_addr);
|
||||
@ -4065,7 +4066,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
skb = ieee80211_tx_dequeue(hw, txq);
|
||||
skb = ieee80211_tx_dequeue_ni(hw, txq);
|
||||
if (!skb) {
|
||||
spin_lock_bh(&ar->htt.tx_lock);
|
||||
ath10k_htt_tx_dec_pending(htt);
|
||||
@ -4097,7 +4098,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
|
||||
spin_unlock_bh(&ar->htt.tx_lock);
|
||||
}
|
||||
|
||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
|
||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, false);
|
||||
if (unlikely(ret)) {
|
||||
ath10k_warn(ar, "failed to push frame: %d\n", ret);
|
||||
|
||||
@ -4378,7 +4379,7 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
|
||||
spin_unlock_bh(&ar->htt.tx_lock);
|
||||
}
|
||||
|
||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
|
||||
ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, false);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to transmit frame: %d\n", ret);
|
||||
if (is_htt) {
|
||||
@ -4754,6 +4755,63 @@ static int __ath10k_fetch_bb_timing_dt(struct ath10k *ar,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_mac_rfkill_config(struct ath10k *ar)
|
||||
{
|
||||
u32 param;
|
||||
int ret;
|
||||
|
||||
if (ar->hw_values->rfkill_pin == 0) {
|
||||
ath10k_warn(ar, "ath10k does not support hardware rfkill with this device\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac rfkill_pin %d rfkill_cfg %d rfkill_on_level %d",
|
||||
ar->hw_values->rfkill_pin, ar->hw_values->rfkill_cfg,
|
||||
ar->hw_values->rfkill_on_level);
|
||||
|
||||
param = FIELD_PREP(WMI_TLV_RFKILL_CFG_RADIO_LEVEL,
|
||||
ar->hw_values->rfkill_on_level) |
|
||||
FIELD_PREP(WMI_TLV_RFKILL_CFG_GPIO_PIN_NUM,
|
||||
ar->hw_values->rfkill_pin) |
|
||||
FIELD_PREP(WMI_TLV_RFKILL_CFG_PIN_AS_GPIO,
|
||||
ar->hw_values->rfkill_cfg);
|
||||
|
||||
ret = ath10k_wmi_pdev_set_param(ar,
|
||||
ar->wmi.pdev_param->rfkill_config,
|
||||
param);
|
||||
if (ret) {
|
||||
ath10k_warn(ar,
|
||||
"failed to set rfkill config 0x%x: %d\n",
|
||||
param, ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_mac_rfkill_enable_radio(struct ath10k *ar, bool enable)
|
||||
{
|
||||
enum wmi_tlv_rfkill_enable_radio param;
|
||||
int ret;
|
||||
|
||||
if (enable)
|
||||
param = WMI_TLV_RFKILL_ENABLE_RADIO_ON;
|
||||
else
|
||||
param = WMI_TLV_RFKILL_ENABLE_RADIO_OFF;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac rfkill enable %d", param);
|
||||
|
||||
ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->rfkill_enable,
|
||||
param);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set rfkill enable param %d: %d\n",
|
||||
param, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
@ -4788,6 +4846,16 @@ static int ath10k_start(struct ieee80211_hw *hw)
|
||||
goto err;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
if (ar->hw_rfkill_on) {
|
||||
ar->hw_rfkill_on = false;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
goto err;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_NORMAL);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "Could not init hif: %d\n", ret);
|
||||
@ -4801,6 +4869,14 @@ static int ath10k_start(struct ieee80211_hw *hw)
|
||||
goto err_power_down;
|
||||
}
|
||||
|
||||
if (ar->sys_cap_info & WMI_TLV_SYS_CAP_INFO_RFKILL) {
|
||||
ret = ath10k_mac_rfkill_config(ar);
|
||||
if (ret && ret != -EOPNOTSUPP) {
|
||||
ath10k_warn(ar, "failed to configure rfkill: %d", ret);
|
||||
goto err_core_stop;
|
||||
}
|
||||
}
|
||||
|
||||
param = ar->wmi.pdev_param->pmf_qos;
|
||||
ret = ath10k_wmi_pdev_set_param(ar, param, 1);
|
||||
if (ret) {
|
||||
@ -4960,7 +5036,8 @@ static void ath10k_stop(struct ieee80211_hw *hw)
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
if (ar->state != ATH10K_STATE_OFF) {
|
||||
ath10k_halt(ar);
|
||||
if (!ar->hw_rfkill_on)
|
||||
ath10k_halt(ar);
|
||||
ar->state = ATH10K_STATE_OFF;
|
||||
}
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
@ -5635,6 +5712,37 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
static void ath10k_recalculate_mgmt_rate(struct ath10k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_chan_def *def)
|
||||
{
|
||||
struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
const struct ieee80211_supported_band *sband;
|
||||
u8 basic_rate_idx;
|
||||
int hw_rate_code;
|
||||
u32 vdev_param;
|
||||
u16 bitrate;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
sband = ar->hw->wiphy->bands[def->chan->band];
|
||||
basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
|
||||
bitrate = sband->bitrates[basic_rate_idx].bitrate;
|
||||
|
||||
hw_rate_code = ath10k_mac_get_rate_hw_value(bitrate);
|
||||
if (hw_rate_code < 0) {
|
||||
ath10k_warn(ar, "bitrate not supported %d\n", bitrate);
|
||||
return;
|
||||
}
|
||||
|
||||
vdev_param = ar->wmi.vdev_param->mgmt_rate;
|
||||
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
|
||||
hw_rate_code);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to set mgmt tx rate %d\n", ret);
|
||||
}
|
||||
|
||||
static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *info,
|
||||
@ -5645,10 +5753,9 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct cfg80211_chan_def def;
|
||||
u32 vdev_param, pdev_param, slottime, preamble;
|
||||
u16 bitrate, hw_value;
|
||||
u8 rate, basic_rate_idx, rateidx;
|
||||
int ret = 0, hw_rate_code, mcast_rate;
|
||||
u8 rate, rateidx;
|
||||
int ret = 0, mcast_rate;
|
||||
enum nl80211_band band;
|
||||
const struct ieee80211_supported_band *sband;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
@ -5872,29 +5979,9 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
arvif->vdev_id, ret);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BASIC_RATES) {
|
||||
if (ath10k_mac_vif_chan(vif, &def)) {
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
sband = ar->hw->wiphy->bands[def.chan->band];
|
||||
basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
|
||||
bitrate = sband->bitrates[basic_rate_idx].bitrate;
|
||||
|
||||
hw_rate_code = ath10k_mac_get_rate_hw_value(bitrate);
|
||||
if (hw_rate_code < 0) {
|
||||
ath10k_warn(ar, "bitrate not supported %d\n", bitrate);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
vdev_param = ar->wmi.vdev_param->mgmt_rate;
|
||||
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
|
||||
hw_rate_code);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to set mgmt tx rate %d\n", ret);
|
||||
}
|
||||
if (changed & BSS_CHANGED_BASIC_RATES &&
|
||||
!ath10k_mac_vif_chan(arvif->vif, &def))
|
||||
ath10k_recalculate_mgmt_rate(ar, vif, &def);
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
@ -6239,7 +6326,7 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
|
||||
if (sta && sta->tdls)
|
||||
ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_AUTHORIZE, 1);
|
||||
ar->wmi.peer_param->authorize, 1);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
@ -6330,7 +6417,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
|
||||
sta->addr, bw, mode);
|
||||
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_PHYMODE, mode);
|
||||
ar->wmi.peer_param->phymode, mode);
|
||||
if (err) {
|
||||
ath10k_warn(ar, "failed to update STA %pM peer phymode %d: %d\n",
|
||||
sta->addr, mode, err);
|
||||
@ -6338,7 +6425,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
|
||||
}
|
||||
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_CHAN_WIDTH, bw);
|
||||
ar->wmi.peer_param->chan_width, bw);
|
||||
if (err)
|
||||
ath10k_warn(ar, "failed to update STA %pM peer bw %d: %d\n",
|
||||
sta->addr, bw, err);
|
||||
@ -6349,7 +6436,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
|
||||
sta->addr, nss);
|
||||
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_NSS, nss);
|
||||
ar->wmi.peer_param->nss, nss);
|
||||
if (err)
|
||||
ath10k_warn(ar, "failed to update STA %pM nss %d: %d\n",
|
||||
sta->addr, nss, err);
|
||||
@ -6360,7 +6447,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
|
||||
sta->addr, smps);
|
||||
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_SMPS_STATE, smps);
|
||||
ar->wmi.peer_param->smps_state, smps);
|
||||
if (err)
|
||||
ath10k_warn(ar, "failed to update STA %pM smps %d: %d\n",
|
||||
sta->addr, smps, err);
|
||||
@ -6434,7 +6521,7 @@ static int ath10k_sta_set_txpwr(struct ieee80211_hw *hw,
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_USE_FIXED_PWR, txpwr);
|
||||
ar->wmi.peer_param->use_fixed_power, txpwr);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set tx power for station ret: %d\n",
|
||||
ret);
|
||||
@ -6549,8 +6636,12 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
if (!sta->tdls)
|
||||
if (!sta->tdls) {
|
||||
ath10k_peer_delete(ar, arvif->vdev_id, sta->addr);
|
||||
ath10k_mac_dec_num_stations(arvif, sta);
|
||||
kfree(arsta->tx_stats);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = ath10k_wmi_update_fw_tdls_state(ar, arvif->vdev_id,
|
||||
WMI_TDLS_ENABLE_ACTIVE);
|
||||
@ -7419,7 +7510,7 @@ static bool ath10k_mac_set_vht_bitrate_mask_fixup(struct ath10k *ar,
|
||||
err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_PARAM_FIXED_RATE, rate);
|
||||
if (err)
|
||||
ath10k_warn(ar, "failed to eanble STA %pM peer fixed rate: %d\n",
|
||||
ath10k_warn(ar, "failed to enable STA %pM peer fixed rate: %d\n",
|
||||
sta->addr, err);
|
||||
|
||||
return true;
|
||||
|
@ -72,6 +72,7 @@ struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar,
|
||||
u8 tid);
|
||||
int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val);
|
||||
void ath10k_mac_wait_tx_complete(struct ath10k *ar);
|
||||
int ath10k_mac_rfkill_enable_radio(struct ath10k *ar, bool enable);
|
||||
|
||||
static inline void ath10k_tx_h_seq_no(struct ieee80211_vif *vif,
|
||||
struct sk_buff *skb)
|
||||
|
@ -2567,35 +2567,31 @@ static void ath10k_pci_warm_reset_cpu(struct ath10k *ar)
|
||||
|
||||
ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, 0);
|
||||
|
||||
val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
|
||||
SOC_RESET_CONTROL_ADDRESS);
|
||||
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
|
||||
val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
|
||||
val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
|
||||
ath10k_pci_soc_write32(ar, SOC_RESET_CONTROL_ADDRESS,
|
||||
val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
|
||||
}
|
||||
|
||||
static void ath10k_pci_warm_reset_ce(struct ath10k *ar)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
|
||||
SOC_RESET_CONTROL_ADDRESS);
|
||||
val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
|
||||
|
||||
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
|
||||
val | SOC_RESET_CONTROL_CE_RST_MASK);
|
||||
ath10k_pci_soc_write32(ar, SOC_RESET_CONTROL_ADDRESS,
|
||||
val | SOC_RESET_CONTROL_CE_RST_MASK);
|
||||
msleep(10);
|
||||
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
|
||||
val & ~SOC_RESET_CONTROL_CE_RST_MASK);
|
||||
ath10k_pci_soc_write32(ar, SOC_RESET_CONTROL_ADDRESS,
|
||||
val & ~SOC_RESET_CONTROL_CE_RST_MASK);
|
||||
}
|
||||
|
||||
static void ath10k_pci_warm_reset_clear_lf(struct ath10k *ar)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
|
||||
SOC_LF_TIMER_CONTROL0_ADDRESS);
|
||||
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS +
|
||||
SOC_LF_TIMER_CONTROL0_ADDRESS,
|
||||
val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK);
|
||||
val = ath10k_pci_soc_read32(ar, SOC_LF_TIMER_CONTROL0_ADDRESS);
|
||||
ath10k_pci_soc_write32(ar, SOC_LF_TIMER_CONTROL0_ADDRESS,
|
||||
val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK);
|
||||
}
|
||||
|
||||
static int ath10k_pci_warm_reset(struct ath10k *ar)
|
||||
@ -3490,7 +3486,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
struct ath10k_pci *ar_pci;
|
||||
enum ath10k_hw_rev hw_rev;
|
||||
struct ath10k_bus_params bus_params = {};
|
||||
bool pci_ps;
|
||||
bool pci_ps, is_qca988x = false;
|
||||
int (*pci_soft_reset)(struct ath10k *ar);
|
||||
int (*pci_hard_reset)(struct ath10k *ar);
|
||||
u32 (*targ_cpu_to_ce_addr)(struct ath10k *ar, u32 addr);
|
||||
@ -3500,6 +3496,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
case QCA988X_2_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA988X;
|
||||
pci_ps = false;
|
||||
is_qca988x = true;
|
||||
pci_soft_reset = ath10k_pci_warm_reset;
|
||||
pci_hard_reset = ath10k_pci_qca988x_chip_reset;
|
||||
targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
|
||||
@ -3619,25 +3616,34 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
goto err_deinit_irq;
|
||||
}
|
||||
|
||||
bus_params.dev_type = ATH10K_DEV_TYPE_LL;
|
||||
bus_params.link_can_suspend = true;
|
||||
/* Read CHIP_ID before reset to catch QCA9880-AR1A v1 devices that
|
||||
* fall off the bus during chip_reset. These chips have the same pci
|
||||
* device id as the QCA9880 BR4A or 2R4E. So that's why the check.
|
||||
*/
|
||||
if (is_qca988x) {
|
||||
bus_params.chip_id =
|
||||
ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
|
||||
if (bus_params.chip_id != 0xffffffff) {
|
||||
if (!ath10k_pci_chip_is_supported(pdev->device,
|
||||
bus_params.chip_id))
|
||||
goto err_unsupported;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath10k_pci_chip_reset(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to reset chip: %d\n", ret);
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
bus_params.dev_type = ATH10K_DEV_TYPE_LL;
|
||||
bus_params.link_can_suspend = true;
|
||||
bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
|
||||
if (bus_params.chip_id == 0xffffffff) {
|
||||
ath10k_err(ar, "failed to get chip id\n");
|
||||
goto err_free_irq;
|
||||
}
|
||||
if (bus_params.chip_id == 0xffffffff)
|
||||
goto err_unsupported;
|
||||
|
||||
if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id)) {
|
||||
ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n",
|
||||
pdev->device, bus_params.chip_id);
|
||||
if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id))
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
ret = ath10k_core_register(ar, &bus_params);
|
||||
if (ret) {
|
||||
@ -3647,6 +3653,10 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
return 0;
|
||||
|
||||
err_unsupported:
|
||||
ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n",
|
||||
pdev->device, bus_params.chip_id);
|
||||
|
||||
err_free_irq:
|
||||
ath10k_pci_free_irq(ar);
|
||||
ath10k_pci_rx_retry_sync(ar);
|
||||
|
@ -111,6 +111,7 @@ static int ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
|
||||
struct wlfw_msa_info_resp_msg_v01 resp = {};
|
||||
struct wlfw_msa_info_req_msg_v01 req = {};
|
||||
struct ath10k *ar = qmi->ar;
|
||||
phys_addr_t max_mapped_addr;
|
||||
struct qmi_txn txn;
|
||||
int ret;
|
||||
int i;
|
||||
@ -150,8 +151,20 @@ static int ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
|
||||
goto out;
|
||||
}
|
||||
|
||||
max_mapped_addr = qmi->msa_pa + qmi->msa_mem_size;
|
||||
qmi->nr_mem_region = resp.mem_region_info_len;
|
||||
for (i = 0; i < resp.mem_region_info_len; i++) {
|
||||
if (resp.mem_region_info[i].size > qmi->msa_mem_size ||
|
||||
resp.mem_region_info[i].region_addr > max_mapped_addr ||
|
||||
resp.mem_region_info[i].region_addr < qmi->msa_pa ||
|
||||
resp.mem_region_info[i].size +
|
||||
resp.mem_region_info[i].region_addr > max_mapped_addr) {
|
||||
ath10k_err(ar, "received out of range memory region address 0x%llx with size 0x%x, aborting\n",
|
||||
resp.mem_region_info[i].region_addr,
|
||||
resp.mem_region_info[i].size);
|
||||
ret = -EINVAL;
|
||||
goto fail_unwind;
|
||||
}
|
||||
qmi->mem_region[i].addr = resp.mem_region_info[i].region_addr;
|
||||
qmi->mem_region[i].size = resp.mem_region_info[i].size;
|
||||
qmi->mem_region[i].secure = resp.mem_region_info[i].secure_flag;
|
||||
@ -165,6 +178,8 @@ static int ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
|
||||
ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi msa mem info request completed\n");
|
||||
return 0;
|
||||
|
||||
fail_unwind:
|
||||
memset(&qmi->mem_region[0], 0, sizeof(qmi->mem_region[0]) * i);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@ -291,10 +306,16 @@ static int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi)
|
||||
struct wlfw_cal_report_resp_msg_v01 resp = {};
|
||||
struct wlfw_cal_report_req_msg_v01 req = {};
|
||||
struct ath10k *ar = qmi->ar;
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct qmi_txn txn;
|
||||
int i, j = 0;
|
||||
int ret;
|
||||
|
||||
if (ar_snoc->xo_cal_supported) {
|
||||
req.xo_cal_data_valid = 1;
|
||||
req.xo_cal_data = ar_snoc->xo_cal_data;
|
||||
}
|
||||
|
||||
ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_cal_report_resp_msg_v01_ei,
|
||||
&resp);
|
||||
if (ret < 0)
|
||||
@ -581,22 +602,29 @@ static int ath10k_qmi_host_cap_send_sync(struct ath10k_qmi *qmi)
|
||||
{
|
||||
struct wlfw_host_cap_resp_msg_v01 resp = {};
|
||||
struct wlfw_host_cap_req_msg_v01 req = {};
|
||||
struct qmi_elem_info *req_ei;
|
||||
struct ath10k *ar = qmi->ar;
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct qmi_txn txn;
|
||||
int ret;
|
||||
|
||||
req.daemon_support_valid = 1;
|
||||
req.daemon_support = 0;
|
||||
|
||||
ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
|
||||
wlfw_host_cap_resp_msg_v01_ei, &resp);
|
||||
ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_host_cap_resp_msg_v01_ei,
|
||||
&resp);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (test_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags))
|
||||
req_ei = wlfw_host_cap_8bit_req_msg_v01_ei;
|
||||
else
|
||||
req_ei = wlfw_host_cap_req_msg_v01_ei;
|
||||
|
||||
ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
|
||||
QMI_WLFW_HOST_CAP_REQ_V01,
|
||||
WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN,
|
||||
wlfw_host_cap_req_msg_v01_ei, &req);
|
||||
req_ei, &req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath10k_err(ar, "failed to send host capability request: %d\n", ret);
|
||||
@ -643,7 +671,7 @@ int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode)
|
||||
wlfw_ini_req_msg_v01_ei, &req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath10k_err(ar, "fail to send fw log reqest: %d\n", ret);
|
||||
ath10k_err(ar, "failed to send fw log request: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -652,7 +680,7 @@ int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode)
|
||||
goto out;
|
||||
|
||||
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
||||
ath10k_err(ar, "fw log request rejectedr: %d\n",
|
||||
ath10k_err(ar, "fw log request rejected: %d\n",
|
||||
resp.resp.error);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
@ -671,6 +699,7 @@ ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
|
||||
struct wlfw_ind_register_resp_msg_v01 resp = {};
|
||||
struct wlfw_ind_register_req_msg_v01 req = {};
|
||||
struct ath10k *ar = qmi->ar;
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct qmi_txn txn;
|
||||
int ret;
|
||||
|
||||
@ -681,6 +710,11 @@ ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
|
||||
req.msa_ready_enable_valid = 1;
|
||||
req.msa_ready_enable = 1;
|
||||
|
||||
if (ar_snoc->xo_cal_supported) {
|
||||
req.xo_cal_enable_valid = 1;
|
||||
req.xo_cal_enable = 1;
|
||||
}
|
||||
|
||||
ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
|
||||
wlfw_ind_register_resp_msg_v01_ei, &resp);
|
||||
if (ret < 0)
|
||||
@ -795,9 +829,13 @@ ath10k_qmi_driver_event_post(struct ath10k_qmi *qmi,
|
||||
static void ath10k_qmi_event_server_exit(struct ath10k_qmi *qmi)
|
||||
{
|
||||
struct ath10k *ar = qmi->ar;
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
|
||||
ath10k_qmi_remove_msa_permission(qmi);
|
||||
ath10k_core_free_board_files(ar);
|
||||
if (!test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags))
|
||||
ath10k_snoc_fw_crashed_dump(ar);
|
||||
|
||||
ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_DOWN_IND);
|
||||
ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw qmi service disconnected\n");
|
||||
}
|
||||
|
@ -1988,6 +1988,28 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
struct qmi_elem_info wlfw_host_cap_8bit_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct wlfw_host_cap_req_msg_v01,
|
||||
daemon_support_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct wlfw_host_cap_req_msg_v01,
|
||||
daemon_support),
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
|
@ -575,6 +575,7 @@ struct wlfw_host_cap_req_msg_v01 {
|
||||
|
||||
#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 189
|
||||
extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[];
|
||||
extern struct qmi_elem_info wlfw_host_cap_8bit_req_msg_v01_ei[];
|
||||
|
||||
struct wlfw_host_cap_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
|
@ -2086,9 +2086,6 @@ static int ath10k_sdio_probe(struct sdio_func *func,
|
||||
goto err_free_wq;
|
||||
}
|
||||
|
||||
/* TODO: remove this once SDIO support is fully implemented */
|
||||
ath10k_warn(ar, "WARNING: ath10k SDIO support is work-in-progress, problems may arise!\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_wq:
|
||||
|
@ -9,9 +9,11 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "ce.h"
|
||||
#include "coredump.h"
|
||||
#include "debug.h"
|
||||
#include "hif.h"
|
||||
#include "htc.h"
|
||||
@ -36,15 +38,15 @@ static char *const ce_name[] = {
|
||||
"WLAN_CE_11",
|
||||
};
|
||||
|
||||
static struct ath10k_vreg_info vreg_cfg[] = {
|
||||
{NULL, "vdd-0.8-cx-mx", 800000, 850000, 0, 0, false},
|
||||
{NULL, "vdd-1.8-xo", 1800000, 1850000, 0, 0, false},
|
||||
{NULL, "vdd-1.3-rfa", 1300000, 1350000, 0, 0, false},
|
||||
{NULL, "vdd-3.3-ch0", 3300000, 3350000, 0, 0, false},
|
||||
static const char * const ath10k_regulators[] = {
|
||||
"vdd-0.8-cx-mx",
|
||||
"vdd-1.8-xo",
|
||||
"vdd-1.3-rfa",
|
||||
"vdd-3.3-ch0",
|
||||
};
|
||||
|
||||
static struct ath10k_clk_info clk_cfg[] = {
|
||||
{NULL, "cxo_ref_clk_pin", 0, false},
|
||||
static const char * const ath10k_clocks[] = {
|
||||
"cxo_ref_clk_pin",
|
||||
};
|
||||
|
||||
static void ath10k_snoc_htc_tx_cb(struct ath10k_ce_pipe *ce_state);
|
||||
@ -976,8 +978,7 @@ static int ath10k_snoc_wlan_enable(struct ath10k *ar,
|
||||
sizeof(struct ath10k_svc_pipe_cfg);
|
||||
cfg.ce_svc_cfg = (struct ath10k_svc_pipe_cfg *)
|
||||
&target_service_to_ce_map_wlan;
|
||||
cfg.num_shadow_reg_cfg = sizeof(target_shadow_reg_cfg_map) /
|
||||
sizeof(struct ath10k_shadow_reg_cfg);
|
||||
cfg.num_shadow_reg_cfg = ARRAY_SIZE(target_shadow_reg_cfg_map);
|
||||
cfg.shadow_reg_cfg = (struct ath10k_shadow_reg_cfg *)
|
||||
&target_shadow_reg_cfg_map;
|
||||
|
||||
@ -1257,10 +1258,29 @@ static int ath10k_snoc_resource_init(struct ath10k *ar)
|
||||
ar_snoc->ce_irqs[i].irq_line = res->start;
|
||||
}
|
||||
|
||||
ret = device_property_read_u32(&pdev->dev, "qcom,xo-cal-data",
|
||||
&ar_snoc->xo_cal_data);
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc xo-cal-data return %d\n", ret);
|
||||
if (ret == 0) {
|
||||
ar_snoc->xo_cal_supported = true;
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "xo cal data %x\n",
|
||||
ar_snoc->xo_cal_data);
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath10k_snoc_quirks_init(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct device *dev = &ar_snoc->dev->dev;
|
||||
|
||||
if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-8bit-quirk"))
|
||||
set_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags);
|
||||
}
|
||||
|
||||
int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
@ -1337,296 +1357,102 @@ static void ath10k_snoc_release_resource(struct ath10k *ar)
|
||||
ath10k_ce_free_pipe(ar, i);
|
||||
}
|
||||
|
||||
static int ath10k_get_vreg_info(struct ath10k *ar, struct device *dev,
|
||||
struct ath10k_vreg_info *vreg_info)
|
||||
{
|
||||
struct regulator *reg;
|
||||
int ret = 0;
|
||||
|
||||
reg = devm_regulator_get_optional(dev, vreg_info->name);
|
||||
|
||||
if (IS_ERR(reg)) {
|
||||
ret = PTR_ERR(reg);
|
||||
|
||||
if (ret == -EPROBE_DEFER) {
|
||||
ath10k_err(ar, "EPROBE_DEFER for regulator: %s\n",
|
||||
vreg_info->name);
|
||||
return ret;
|
||||
}
|
||||
if (vreg_info->required) {
|
||||
ath10k_err(ar, "Regulator %s doesn't exist: %d\n",
|
||||
vreg_info->name, ret);
|
||||
return ret;
|
||||
}
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC,
|
||||
"Optional regulator %s doesn't exist: %d\n",
|
||||
vreg_info->name, ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
vreg_info->reg = reg;
|
||||
|
||||
done:
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC,
|
||||
"snog vreg %s min_v %u max_v %u load_ua %u settle_delay %lu\n",
|
||||
vreg_info->name, vreg_info->min_v, vreg_info->max_v,
|
||||
vreg_info->load_ua, vreg_info->settle_delay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_get_clk_info(struct ath10k *ar, struct device *dev,
|
||||
struct ath10k_clk_info *clk_info)
|
||||
{
|
||||
struct clk *handle;
|
||||
int ret = 0;
|
||||
|
||||
handle = devm_clk_get(dev, clk_info->name);
|
||||
if (IS_ERR(handle)) {
|
||||
ret = PTR_ERR(handle);
|
||||
if (clk_info->required) {
|
||||
ath10k_err(ar, "snoc clock %s isn't available: %d\n",
|
||||
clk_info->name, ret);
|
||||
return ret;
|
||||
}
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc ignoring clock %s: %d\n",
|
||||
clk_info->name,
|
||||
ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc clock %s freq %u\n",
|
||||
clk_info->name, clk_info->freq);
|
||||
|
||||
clk_info->handle = handle;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __ath10k_snoc_vreg_on(struct ath10k *ar,
|
||||
struct ath10k_vreg_info *vreg_info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc regulator %s being enabled\n",
|
||||
vreg_info->name);
|
||||
|
||||
ret = regulator_set_voltage(vreg_info->reg, vreg_info->min_v,
|
||||
vreg_info->max_v);
|
||||
if (ret) {
|
||||
ath10k_err(ar,
|
||||
"failed to set regulator %s voltage-min: %d voltage-max: %d\n",
|
||||
vreg_info->name, vreg_info->min_v, vreg_info->max_v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (vreg_info->load_ua) {
|
||||
ret = regulator_set_load(vreg_info->reg, vreg_info->load_ua);
|
||||
if (ret < 0) {
|
||||
ath10k_err(ar, "failed to set regulator %s load: %d\n",
|
||||
vreg_info->name, vreg_info->load_ua);
|
||||
goto err_set_load;
|
||||
}
|
||||
}
|
||||
|
||||
ret = regulator_enable(vreg_info->reg);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to enable regulator %s\n",
|
||||
vreg_info->name);
|
||||
goto err_enable;
|
||||
}
|
||||
|
||||
if (vreg_info->settle_delay)
|
||||
udelay(vreg_info->settle_delay);
|
||||
|
||||
return 0;
|
||||
|
||||
err_enable:
|
||||
regulator_set_load(vreg_info->reg, 0);
|
||||
err_set_load:
|
||||
regulator_set_voltage(vreg_info->reg, 0, vreg_info->max_v);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __ath10k_snoc_vreg_off(struct ath10k *ar,
|
||||
struct ath10k_vreg_info *vreg_info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc regulator %s being disabled\n",
|
||||
vreg_info->name);
|
||||
|
||||
ret = regulator_disable(vreg_info->reg);
|
||||
if (ret)
|
||||
ath10k_err(ar, "failed to disable regulator %s\n",
|
||||
vreg_info->name);
|
||||
|
||||
ret = regulator_set_load(vreg_info->reg, 0);
|
||||
if (ret < 0)
|
||||
ath10k_err(ar, "failed to set load %s\n", vreg_info->name);
|
||||
|
||||
ret = regulator_set_voltage(vreg_info->reg, 0, vreg_info->max_v);
|
||||
if (ret)
|
||||
ath10k_err(ar, "failed to set voltage %s\n", vreg_info->name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_snoc_vreg_on(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct ath10k_vreg_info *vreg_info;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vreg_cfg); i++) {
|
||||
vreg_info = &ar_snoc->vreg[i];
|
||||
|
||||
if (!vreg_info->reg)
|
||||
continue;
|
||||
|
||||
ret = __ath10k_snoc_vreg_on(ar, vreg_info);
|
||||
if (ret)
|
||||
goto err_reg_config;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_reg_config:
|
||||
for (i = i - 1; i >= 0; i--) {
|
||||
vreg_info = &ar_snoc->vreg[i];
|
||||
|
||||
if (!vreg_info->reg)
|
||||
continue;
|
||||
|
||||
__ath10k_snoc_vreg_off(ar, vreg_info);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_snoc_vreg_off(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct ath10k_vreg_info *vreg_info;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = ARRAY_SIZE(vreg_cfg) - 1; i >= 0; i--) {
|
||||
vreg_info = &ar_snoc->vreg[i];
|
||||
|
||||
if (!vreg_info->reg)
|
||||
continue;
|
||||
|
||||
ret = __ath10k_snoc_vreg_off(ar, vreg_info);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_snoc_clk_init(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct ath10k_clk_info *clk_info;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clk_cfg); i++) {
|
||||
clk_info = &ar_snoc->clk[i];
|
||||
|
||||
if (!clk_info->handle)
|
||||
continue;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc clock %s being enabled\n",
|
||||
clk_info->name);
|
||||
|
||||
if (clk_info->freq) {
|
||||
ret = clk_set_rate(clk_info->handle, clk_info->freq);
|
||||
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to set clock %s freq %u\n",
|
||||
clk_info->name, clk_info->freq);
|
||||
goto err_clock_config;
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(clk_info->handle);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to enable clock %s\n",
|
||||
clk_info->name);
|
||||
goto err_clock_config;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_clock_config:
|
||||
for (i = i - 1; i >= 0; i--) {
|
||||
clk_info = &ar_snoc->clk[i];
|
||||
|
||||
if (!clk_info->handle)
|
||||
continue;
|
||||
|
||||
clk_disable_unprepare(clk_info->handle);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_snoc_clk_deinit(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
struct ath10k_clk_info *clk_info;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clk_cfg); i++) {
|
||||
clk_info = &ar_snoc->clk[i];
|
||||
|
||||
if (!clk_info->handle)
|
||||
continue;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc clock %s being disabled\n",
|
||||
clk_info->name);
|
||||
|
||||
clk_disable_unprepare(clk_info->handle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_hw_power_on(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power on\n");
|
||||
|
||||
ret = ath10k_snoc_vreg_on(ar);
|
||||
ret = regulator_bulk_enable(ar_snoc->num_vregs, ar_snoc->vregs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ath10k_snoc_clk_init(ar);
|
||||
ret = clk_bulk_prepare_enable(ar_snoc->num_clks, ar_snoc->clks);
|
||||
if (ret)
|
||||
goto vreg_off;
|
||||
|
||||
return ret;
|
||||
|
||||
vreg_off:
|
||||
ath10k_snoc_vreg_off(ar);
|
||||
regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_hw_power_off(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power off\n");
|
||||
|
||||
ath10k_snoc_clk_deinit(ar);
|
||||
clk_bulk_disable_unprepare(ar_snoc->num_clks, ar_snoc->clks);
|
||||
|
||||
ret = ath10k_snoc_vreg_off(ar);
|
||||
return regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
|
||||
}
|
||||
|
||||
return ret;
|
||||
static void ath10k_msa_dump_memory(struct ath10k *ar,
|
||||
struct ath10k_fw_crash_data *crash_data)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
const struct ath10k_hw_mem_layout *mem_layout;
|
||||
const struct ath10k_mem_region *current_region;
|
||||
struct ath10k_dump_ram_data_hdr *hdr;
|
||||
size_t buf_len;
|
||||
u8 *buf;
|
||||
|
||||
if (!crash_data && !crash_data->ramdump_buf)
|
||||
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);
|
||||
|
||||
/* Reserve space for the header. */
|
||||
hdr = (void *)buf;
|
||||
buf += sizeof(*hdr);
|
||||
buf_len -= sizeof(*hdr);
|
||||
|
||||
hdr->region_type = cpu_to_le32(current_region->type);
|
||||
hdr->start = cpu_to_le32((unsigned long)ar_snoc->qmi->msa_va);
|
||||
hdr->length = cpu_to_le32(ar_snoc->qmi->msa_mem_size);
|
||||
|
||||
if (current_region->len < ar_snoc->qmi->msa_mem_size) {
|
||||
memcpy(buf, ar_snoc->qmi->msa_va, current_region->len);
|
||||
ath10k_warn(ar, "msa dump length is less than msa size %x, %x\n",
|
||||
current_region->len, ar_snoc->qmi->msa_mem_size);
|
||||
} else {
|
||||
memcpy(buf, ar_snoc->qmi->msa_va, ar_snoc->qmi->msa_mem_size);
|
||||
}
|
||||
}
|
||||
|
||||
void ath10k_snoc_fw_crashed_dump(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_fw_crash_data *crash_data;
|
||||
char guid[UUID_STRING_LEN + 1];
|
||||
|
||||
mutex_lock(&ar->dump_mutex);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->stats.fw_crash_counter++;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
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_msa_dump_memory(ar, crash_data);
|
||||
mutex_unlock(&ar->dump_mutex);
|
||||
}
|
||||
|
||||
static const struct of_device_id ath10k_snoc_dt_match[] = {
|
||||
@ -1678,6 +1504,8 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
|
||||
ar->ce_priv = &ar_snoc->ce;
|
||||
msa_size = drv_data->msa_size;
|
||||
|
||||
ath10k_snoc_quirks_init(ar);
|
||||
|
||||
ret = ath10k_snoc_resource_init(ar);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to initialize resource: %d\n", ret);
|
||||
@ -1695,19 +1523,36 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
|
||||
goto err_release_resource;
|
||||
}
|
||||
|
||||
ar_snoc->vreg = vreg_cfg;
|
||||
for (i = 0; i < ARRAY_SIZE(vreg_cfg); i++) {
|
||||
ret = ath10k_get_vreg_info(ar, dev, &ar_snoc->vreg[i]);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
ar_snoc->num_vregs = ARRAY_SIZE(ath10k_regulators);
|
||||
ar_snoc->vregs = devm_kcalloc(&pdev->dev, ar_snoc->num_vregs,
|
||||
sizeof(*ar_snoc->vregs), GFP_KERNEL);
|
||||
if (!ar_snoc->vregs) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_irq;
|
||||
}
|
||||
for (i = 0; i < ar_snoc->num_vregs; i++)
|
||||
ar_snoc->vregs[i].supply = ath10k_regulators[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(&pdev->dev, ar_snoc->num_vregs,
|
||||
ar_snoc->vregs);
|
||||
if (ret < 0)
|
||||
goto err_free_irq;
|
||||
|
||||
ar_snoc->num_clks = ARRAY_SIZE(ath10k_clocks);
|
||||
ar_snoc->clks = devm_kcalloc(&pdev->dev, ar_snoc->num_clks,
|
||||
sizeof(*ar_snoc->clks), GFP_KERNEL);
|
||||
if (!ar_snoc->clks) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
ar_snoc->clk = clk_cfg;
|
||||
for (i = 0; i < ARRAY_SIZE(clk_cfg); i++) {
|
||||
ret = ath10k_get_clk_info(ar, dev, &ar_snoc->clk[i]);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
}
|
||||
for (i = 0; i < ar_snoc->num_clks; i++)
|
||||
ar_snoc->clks[i].id = ath10k_clocks[i];
|
||||
|
||||
ret = devm_clk_bulk_get_optional(&pdev->dev, ar_snoc->num_clks,
|
||||
ar_snoc->clks);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
|
||||
ret = ath10k_hw_power_on(ar);
|
||||
if (ret) {
|
||||
|
@ -42,29 +42,16 @@ struct ath10k_snoc_ce_irq {
|
||||
u32 irq_line;
|
||||
};
|
||||
|
||||
struct ath10k_vreg_info {
|
||||
struct regulator *reg;
|
||||
const char *name;
|
||||
u32 min_v;
|
||||
u32 max_v;
|
||||
u32 load_ua;
|
||||
unsigned long settle_delay;
|
||||
bool required;
|
||||
};
|
||||
|
||||
struct ath10k_clk_info {
|
||||
struct clk *handle;
|
||||
const char *name;
|
||||
u32 freq;
|
||||
bool required;
|
||||
};
|
||||
|
||||
enum ath10k_snoc_flags {
|
||||
ATH10K_SNOC_FLAG_REGISTERED,
|
||||
ATH10K_SNOC_FLAG_UNREGISTERING,
|
||||
ATH10K_SNOC_FLAG_RECOVERY,
|
||||
ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK,
|
||||
};
|
||||
|
||||
struct clk_bulk_data;
|
||||
struct regulator_bulk_data;
|
||||
|
||||
struct ath10k_snoc {
|
||||
struct platform_device *dev;
|
||||
struct ath10k *ar;
|
||||
@ -76,10 +63,14 @@ struct ath10k_snoc {
|
||||
struct ath10k_snoc_ce_irq ce_irqs[CE_COUNT_MAX];
|
||||
struct ath10k_ce ce;
|
||||
struct timer_list rx_post_retry;
|
||||
struct ath10k_vreg_info *vreg;
|
||||
struct ath10k_clk_info *clk;
|
||||
struct regulator_bulk_data *vregs;
|
||||
size_t num_vregs;
|
||||
struct clk_bulk_data *clks;
|
||||
size_t num_clks;
|
||||
struct ath10k_qmi *qmi;
|
||||
unsigned long flags;
|
||||
bool xo_cal_supported;
|
||||
u32 xo_cal_data;
|
||||
};
|
||||
|
||||
static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
|
||||
@ -88,5 +79,6 @@ static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
|
||||
}
|
||||
|
||||
int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type);
|
||||
void ath10k_snoc_fw_crashed_dump(struct ath10k *ar);
|
||||
|
||||
#endif /* _SNOC_H_ */
|
||||
|
@ -435,6 +435,7 @@ static int ath10k_usb_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
|
||||
ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
|
||||
"usb bulk transmit failed: %d\n", ret);
|
||||
usb_unanchor_urb(urb);
|
||||
usb_free_urb(urb);
|
||||
ret = -EINVAL;
|
||||
goto err_free_urb_to_pipe;
|
||||
}
|
||||
|
@ -409,6 +409,49 @@ static int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_wmi_tlv_event_rfkill_state_change(struct ath10k *ar,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const struct wmi_tlv_rfkill_state_change_ev *ev;
|
||||
const void **tb;
|
||||
bool radio;
|
||||
int ret;
|
||||
|
||||
tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath10k_warn(ar,
|
||||
"failed to parse rfkill state change event: %d\n",
|
||||
ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TLV_TAG_STRUCT_RFKILL_EVENT];
|
||||
if (!ev) {
|
||||
kfree(tb);
|
||||
return;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"wmi tlv rfkill state change gpio %d type %d radio_state %d\n",
|
||||
__le32_to_cpu(ev->gpio_pin_num),
|
||||
__le32_to_cpu(ev->int_type),
|
||||
__le32_to_cpu(ev->radio_state));
|
||||
|
||||
radio = (__le32_to_cpu(ev->radio_state) == WMI_TLV_RFKILL_RADIO_STATE_ON);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
if (!radio)
|
||||
ar->hw_rfkill_on = true;
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
/* notify cfg80211 radio state change */
|
||||
ath10k_mac_rfkill_enable_radio(ar, radio);
|
||||
wiphy_rfkill_set_hw_state(ar->hw->wiphy, !radio);
|
||||
}
|
||||
|
||||
static int ath10k_wmi_tlv_event_temperature(struct ath10k *ar,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -629,6 +672,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
case WMI_TLV_TX_PAUSE_EVENTID:
|
||||
ath10k_wmi_tlv_event_tx_pause(ar, skb);
|
||||
break;
|
||||
case WMI_TLV_RFKILL_STATE_CHANGE_EVENTID:
|
||||
ath10k_wmi_tlv_event_rfkill_state_change(ar, skb);
|
||||
break;
|
||||
case WMI_TLV_PDEV_TEMPERATURE_EVENTID:
|
||||
ath10k_wmi_tlv_event_temperature(ar, skb);
|
||||
break;
|
||||
@ -1201,17 +1247,21 @@ static int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar,
|
||||
arg->max_tx_power = ev->hw_max_tx_power;
|
||||
arg->ht_cap = ev->ht_cap_info;
|
||||
arg->vht_cap = ev->vht_cap_info;
|
||||
arg->vht_supp_mcs = ev->vht_supp_mcs;
|
||||
arg->sw_ver0 = ev->abi.abi_ver0;
|
||||
arg->sw_ver1 = ev->abi.abi_ver1;
|
||||
arg->fw_build = ev->fw_build_vers;
|
||||
arg->phy_capab = ev->phy_capability;
|
||||
arg->num_rf_chains = ev->num_rf_chains;
|
||||
arg->eeprom_rd = reg->eeprom_rd;
|
||||
arg->low_2ghz_chan = reg->low_2ghz_chan;
|
||||
arg->high_2ghz_chan = reg->high_2ghz_chan;
|
||||
arg->low_5ghz_chan = reg->low_5ghz_chan;
|
||||
arg->high_5ghz_chan = reg->high_5ghz_chan;
|
||||
arg->num_mem_reqs = ev->num_mem_reqs;
|
||||
arg->service_map = svc_bmap;
|
||||
arg->service_map_len = ath10k_wmi_tlv_len(svc_bmap);
|
||||
arg->sys_cap_info = ev->sys_cap_info;
|
||||
|
||||
ret = ath10k_wmi_tlv_iter(ar, mem_reqs, ath10k_wmi_tlv_len(mem_reqs),
|
||||
ath10k_wmi_tlv_parse_mem_reqs, arg);
|
||||
@ -1649,8 +1699,9 @@ ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id,
|
||||
static void
|
||||
ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks)
|
||||
{
|
||||
struct host_memory_chunk *chunk;
|
||||
struct host_memory_chunk_tlv *chunk;
|
||||
struct wmi_tlv *tlv;
|
||||
dma_addr_t paddr;
|
||||
int i;
|
||||
__le16 tlv_len, tlv_tag;
|
||||
|
||||
@ -1666,6 +1717,12 @@ ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks)
|
||||
chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
|
||||
chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
|
||||
|
||||
if (test_bit(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
|
||||
ar->wmi.svc_map)) {
|
||||
paddr = ar->wmi.mem_chunks[i].paddr;
|
||||
chunk->ptr_high = __cpu_to_le32(upper_32_bits(paddr));
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi-tlv chunk %d len %d, addr 0x%llx, id 0x%x\n",
|
||||
i,
|
||||
@ -1689,7 +1746,7 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
|
||||
void *ptr;
|
||||
|
||||
chunks_len = ar->wmi.num_mem_chunks *
|
||||
(sizeof(struct host_memory_chunk) + sizeof(*tlv));
|
||||
(sizeof(struct host_memory_chunk_tlv) + sizeof(*tlv));
|
||||
len = (sizeof(*tlv) + sizeof(*cmd)) +
|
||||
(sizeof(*tlv) + sizeof(*cfg)) +
|
||||
(sizeof(*tlv) + chunks_len);
|
||||
@ -4204,6 +4261,26 @@ static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = {
|
||||
.wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
|
||||
.rfkill_config = WMI_TLV_PDEV_PARAM_HW_RFKILL_CONFIG,
|
||||
.rfkill_enable = WMI_TLV_PDEV_PARAM_RFKILL_ENABLE,
|
||||
};
|
||||
|
||||
static struct wmi_peer_param_map wmi_tlv_peer_param_map = {
|
||||
.smps_state = WMI_TLV_PEER_SMPS_STATE,
|
||||
.ampdu = WMI_TLV_PEER_AMPDU,
|
||||
.authorize = WMI_TLV_PEER_AUTHORIZE,
|
||||
.chan_width = WMI_TLV_PEER_CHAN_WIDTH,
|
||||
.nss = WMI_TLV_PEER_NSS,
|
||||
.use_4addr = WMI_TLV_PEER_USE_4ADDR,
|
||||
.membership = WMI_TLV_PEER_MEMBERSHIP,
|
||||
.user_pos = WMI_TLV_PEER_USERPOS,
|
||||
.crit_proto_hint_enabled = WMI_TLV_PEER_CRIT_PROTO_HINT_ENABLED,
|
||||
.tx_fail_cnt_thr = WMI_TLV_PEER_TX_FAIL_CNT_THR,
|
||||
.set_hw_retry_cts2s = WMI_TLV_PEER_SET_HW_RETRY_CTS2S,
|
||||
.ibss_atim_win_len = WMI_TLV_PEER_IBSS_ATIM_WINDOW_LENGTH,
|
||||
.phymode = WMI_TLV_PEER_PHYMODE,
|
||||
.use_fixed_power = WMI_TLV_PEER_USE_FIXED_PWR,
|
||||
.dummy_var = WMI_TLV_PEER_DUMMY_VAR,
|
||||
};
|
||||
|
||||
static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
|
||||
@ -4394,6 +4471,7 @@ void ath10k_wmi_tlv_attach(struct ath10k *ar)
|
||||
ar->wmi.cmd = &wmi_tlv_cmd_map;
|
||||
ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
|
||||
ar->wmi.peer_param = &wmi_tlv_peer_param_map;
|
||||
ar->wmi.ops = &wmi_tlv_ops;
|
||||
ar->wmi.peer_flags = &wmi_tlv_peer_flags_map;
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef _WMI_TLV_H
|
||||
#define _WMI_TLV_H
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#define WMI_TLV_CMD(grp_id) (((grp_id) << 12) | 0x1)
|
||||
#define WMI_TLV_EV(grp_id) (((grp_id) << 12) | 0x1)
|
||||
#define WMI_TLV_CMD_UNSUPPORTED 0
|
||||
@ -528,6 +530,24 @@ enum wmi_tlv_vdev_param {
|
||||
WMI_TLV_VDEV_PARAM_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE,
|
||||
};
|
||||
|
||||
enum wmi_tlv_peer_param {
|
||||
WMI_TLV_PEER_SMPS_STATE = 0x1, /* see %wmi_peer_smps_state */
|
||||
WMI_TLV_PEER_AMPDU = 0x2,
|
||||
WMI_TLV_PEER_AUTHORIZE = 0x3,
|
||||
WMI_TLV_PEER_CHAN_WIDTH = 0x4,
|
||||
WMI_TLV_PEER_NSS = 0x5,
|
||||
WMI_TLV_PEER_USE_4ADDR = 0x6,
|
||||
WMI_TLV_PEER_MEMBERSHIP = 0x7,
|
||||
WMI_TLV_PEER_USERPOS = 0x8,
|
||||
WMI_TLV_PEER_CRIT_PROTO_HINT_ENABLED = 0x9,
|
||||
WMI_TLV_PEER_TX_FAIL_CNT_THR = 0xa,
|
||||
WMI_TLV_PEER_SET_HW_RETRY_CTS2S = 0xb,
|
||||
WMI_TLV_PEER_IBSS_ATIM_WINDOW_LENGTH = 0xc,
|
||||
WMI_TLV_PEER_PHYMODE = 0xd,
|
||||
WMI_TLV_PEER_USE_FIXED_PWR = 0xe,
|
||||
WMI_TLV_PEER_DUMMY_VAR = 0xff,
|
||||
};
|
||||
|
||||
enum wmi_tlv_peer_flags {
|
||||
WMI_TLV_PEER_AUTH = 0x00000001,
|
||||
WMI_TLV_PEER_QOS = 0x00000002,
|
||||
@ -1409,6 +1429,11 @@ enum wmi_tlv_service {
|
||||
WMI_TLV_SERVICE_WLAN_HPCS_PULSE = 172,
|
||||
WMI_TLV_SERVICE_PER_VDEV_CHAINMASK_CONFIG_SUPPORT = 173,
|
||||
WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI = 174,
|
||||
WMI_TLV_SERVICE_NAN_DISABLE_SUPPORT = 175,
|
||||
WMI_TLV_SERVICE_HTT_H2T_NO_HTC_HDR_LEN_IN_MSG_LEN = 176,
|
||||
WMI_TLV_SERVICE_COEX_SUPPORT_UNEQUAL_ISOLATION = 177,
|
||||
WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT = 178,
|
||||
WMI_TLV_SERVICE_SUPPORT_EXTEND_ADDRESS = 179,
|
||||
|
||||
WMI_TLV_MAX_EXT_SERVICE = 256,
|
||||
};
|
||||
@ -1588,6 +1613,9 @@ wmi_tlv_svc_map_ext(const __le32 *in, unsigned long *out, size_t len)
|
||||
WMI_TLV_MAX_SERVICE);
|
||||
SVCMAP(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
|
||||
WMI_SERVICE_TX_DATA_ACK_RSSI, WMI_TLV_MAX_SERVICE);
|
||||
SVCMAP(WMI_TLV_SERVICE_SUPPORT_EXTEND_ADDRESS,
|
||||
WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
|
||||
WMI_TLV_MAX_SERVICE);
|
||||
}
|
||||
|
||||
#undef SVCMAP
|
||||
@ -1743,6 +1771,21 @@ struct wmi_tlv_resource_config {
|
||||
__le32 host_capab;
|
||||
} __packed;
|
||||
|
||||
/* structure describing host memory chunk. */
|
||||
struct host_memory_chunk_tlv {
|
||||
/* id of the request that is passed up in service ready */
|
||||
__le32 req_id;
|
||||
|
||||
/* the physical address the memory chunk */
|
||||
__le32 ptr;
|
||||
|
||||
/* size of the chunk */
|
||||
__le32 size;
|
||||
|
||||
/* the upper 32 bit address valid only for more than 32 bit target */
|
||||
__le32 ptr_high;
|
||||
} __packed;
|
||||
|
||||
struct wmi_tlv_init_cmd {
|
||||
struct wmi_tlv_abi_version abi;
|
||||
__le32 num_host_mem_chunks;
|
||||
@ -2235,6 +2278,31 @@ struct wmi_tlv_tdls_peer_event {
|
||||
__le32 vdev_id;
|
||||
} __packed;
|
||||
|
||||
enum wmi_tlv_sys_cap_info_flags {
|
||||
WMI_TLV_SYS_CAP_INFO_RXTX_LED = BIT(0),
|
||||
WMI_TLV_SYS_CAP_INFO_RFKILL = BIT(1),
|
||||
};
|
||||
|
||||
#define WMI_TLV_RFKILL_CFG_GPIO_PIN_NUM GENMASK(5, 0)
|
||||
#define WMI_TLV_RFKILL_CFG_RADIO_LEVEL BIT(6)
|
||||
#define WMI_TLV_RFKILL_CFG_PIN_AS_GPIO GENMASK(10, 7)
|
||||
|
||||
enum wmi_tlv_rfkill_enable_radio {
|
||||
WMI_TLV_RFKILL_ENABLE_RADIO_ON = 0,
|
||||
WMI_TLV_RFKILL_ENABLE_RADIO_OFF = 1,
|
||||
};
|
||||
|
||||
enum wmi_tlv_rfkill_radio_state {
|
||||
WMI_TLV_RFKILL_RADIO_STATE_OFF = 1,
|
||||
WMI_TLV_RFKILL_RADIO_STATE_ON = 2,
|
||||
};
|
||||
|
||||
struct wmi_tlv_rfkill_state_change_ev {
|
||||
__le32 gpio_pin_num;
|
||||
__le32 int_type;
|
||||
__le32 radio_state;
|
||||
};
|
||||
|
||||
void ath10k_wmi_tlv_attach(struct ath10k *ar);
|
||||
|
||||
enum wmi_nlo_auth_algorithm {
|
||||
|
@ -742,6 +742,19 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = {
|
||||
.radar_found_cmdid = WMI_10_4_RADAR_FOUND_CMDID,
|
||||
};
|
||||
|
||||
static struct wmi_peer_param_map wmi_peer_param_map = {
|
||||
.smps_state = WMI_PEER_SMPS_STATE,
|
||||
.ampdu = WMI_PEER_AMPDU,
|
||||
.authorize = WMI_PEER_AUTHORIZE,
|
||||
.chan_width = WMI_PEER_CHAN_WIDTH,
|
||||
.nss = WMI_PEER_NSS,
|
||||
.use_4addr = WMI_PEER_USE_4ADDR,
|
||||
.use_fixed_power = WMI_PEER_USE_FIXED_PWR,
|
||||
.debug = WMI_PEER_DEBUG,
|
||||
.phymode = WMI_PEER_PHYMODE,
|
||||
.dummy_var = WMI_PEER_DUMMY_VAR,
|
||||
};
|
||||
|
||||
/* MAIN WMI VDEV param map */
|
||||
static struct wmi_vdev_param_map wmi_vdev_param_map = {
|
||||
.rts_threshold = WMI_VDEV_PARAM_RTS_THRESHOLD,
|
||||
@ -5344,11 +5357,14 @@ ath10k_wmi_main_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
|
||||
arg->max_tx_power = ev->hw_max_tx_power;
|
||||
arg->ht_cap = ev->ht_cap_info;
|
||||
arg->vht_cap = ev->vht_cap_info;
|
||||
arg->vht_supp_mcs = ev->vht_supp_mcs;
|
||||
arg->sw_ver0 = ev->sw_version;
|
||||
arg->sw_ver1 = ev->sw_version_1;
|
||||
arg->phy_capab = ev->phy_capability;
|
||||
arg->num_rf_chains = ev->num_rf_chains;
|
||||
arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
|
||||
arg->low_2ghz_chan = ev->hal_reg_capabilities.low_2ghz_chan;
|
||||
arg->high_2ghz_chan = ev->hal_reg_capabilities.high_2ghz_chan;
|
||||
arg->low_5ghz_chan = ev->hal_reg_capabilities.low_5ghz_chan;
|
||||
arg->high_5ghz_chan = ev->hal_reg_capabilities.high_5ghz_chan;
|
||||
arg->num_mem_reqs = ev->num_mem_reqs;
|
||||
@ -5383,16 +5399,25 @@ ath10k_wmi_10x_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
|
||||
arg->max_tx_power = ev->hw_max_tx_power;
|
||||
arg->ht_cap = ev->ht_cap_info;
|
||||
arg->vht_cap = ev->vht_cap_info;
|
||||
arg->vht_supp_mcs = ev->vht_supp_mcs;
|
||||
arg->sw_ver0 = ev->sw_version;
|
||||
arg->phy_capab = ev->phy_capability;
|
||||
arg->num_rf_chains = ev->num_rf_chains;
|
||||
arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
|
||||
arg->low_2ghz_chan = ev->hal_reg_capabilities.low_2ghz_chan;
|
||||
arg->high_2ghz_chan = ev->hal_reg_capabilities.high_2ghz_chan;
|
||||
arg->low_5ghz_chan = ev->hal_reg_capabilities.low_5ghz_chan;
|
||||
arg->high_5ghz_chan = ev->hal_reg_capabilities.high_5ghz_chan;
|
||||
arg->num_mem_reqs = ev->num_mem_reqs;
|
||||
arg->service_map = ev->wmi_service_bitmap;
|
||||
arg->service_map_len = sizeof(ev->wmi_service_bitmap);
|
||||
|
||||
/* Deliberately skipping ev->sys_cap_info as WMI and WMI-TLV have
|
||||
* different values. We would need a translation to handle that,
|
||||
* but as we don't currently need anything from sys_cap_info from
|
||||
* WMI interface (only from WMI-TLV) safest it to skip it.
|
||||
*/
|
||||
|
||||
n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
|
||||
ARRAY_SIZE(arg->mem_reqs));
|
||||
for (i = 0; i < n; i++)
|
||||
@ -5432,6 +5457,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
|
||||
ar->hw_max_tx_power = __le32_to_cpu(arg.max_tx_power);
|
||||
ar->ht_cap_info = __le32_to_cpu(arg.ht_cap);
|
||||
ar->vht_cap_info = __le32_to_cpu(arg.vht_cap);
|
||||
ar->vht_supp_mcs = __le32_to_cpu(arg.vht_supp_mcs);
|
||||
ar->fw_version_major =
|
||||
(__le32_to_cpu(arg.sw_ver0) & 0xff000000) >> 24;
|
||||
ar->fw_version_minor = (__le32_to_cpu(arg.sw_ver0) & 0x00ffffff);
|
||||
@ -5441,11 +5467,16 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
|
||||
ar->phy_capability = __le32_to_cpu(arg.phy_capab);
|
||||
ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
|
||||
ar->hw_eeprom_rd = __le32_to_cpu(arg.eeprom_rd);
|
||||
ar->low_2ghz_chan = __le32_to_cpu(arg.low_2ghz_chan);
|
||||
ar->high_2ghz_chan = __le32_to_cpu(arg.high_2ghz_chan);
|
||||
ar->low_5ghz_chan = __le32_to_cpu(arg.low_5ghz_chan);
|
||||
ar->high_5ghz_chan = __le32_to_cpu(arg.high_5ghz_chan);
|
||||
ar->sys_cap_info = __le32_to_cpu(arg.sys_cap_info);
|
||||
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
|
||||
arg.service_map, arg.service_map_len);
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sys_cap_info 0x%x\n",
|
||||
ar->sys_cap_info);
|
||||
|
||||
if (ar->num_rf_chains > ar->max_spatial_stream) {
|
||||
ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n",
|
||||
@ -5544,17 +5575,22 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
|
||||
|
||||
skip_mem_alloc:
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x fw_build 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n",
|
||||
"wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_mcs 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x fw_build 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x low_2ghz_chan %d high_2ghz_chan %d low_5ghz_chan %d high_5ghz_chan %d num_mem_reqs 0x%08x\n",
|
||||
__le32_to_cpu(arg.min_tx_power),
|
||||
__le32_to_cpu(arg.max_tx_power),
|
||||
__le32_to_cpu(arg.ht_cap),
|
||||
__le32_to_cpu(arg.vht_cap),
|
||||
__le32_to_cpu(arg.vht_supp_mcs),
|
||||
__le32_to_cpu(arg.sw_ver0),
|
||||
__le32_to_cpu(arg.sw_ver1),
|
||||
__le32_to_cpu(arg.fw_build),
|
||||
__le32_to_cpu(arg.phy_capab),
|
||||
__le32_to_cpu(arg.num_rf_chains),
|
||||
__le32_to_cpu(arg.eeprom_rd),
|
||||
__le32_to_cpu(arg.low_2ghz_chan),
|
||||
__le32_to_cpu(arg.high_2ghz_chan),
|
||||
__le32_to_cpu(arg.low_5ghz_chan),
|
||||
__le32_to_cpu(arg.high_5ghz_chan),
|
||||
__le32_to_cpu(arg.num_mem_reqs));
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
@ -5623,7 +5659,7 @@ int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi event ready sw_version %u abi_version %u mac_addr %pM status %d\n",
|
||||
"wmi event ready sw_version 0x%08x abi_version %u mac_addr %pM status %d\n",
|
||||
__le32_to_cpu(arg.sw_version),
|
||||
__le32_to_cpu(arg.abi_version),
|
||||
arg.mac_addr,
|
||||
@ -9332,6 +9368,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
||||
ar->wmi.cmd = &wmi_10_4_cmd_map;
|
||||
ar->wmi.vdev_param = &wmi_10_4_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_10_4_pdev_param_map;
|
||||
ar->wmi.peer_param = &wmi_peer_param_map;
|
||||
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
|
||||
ar->wmi_key_cipher = wmi_key_cipher_suites;
|
||||
break;
|
||||
@ -9340,6 +9377,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
||||
ar->wmi.ops = &wmi_10_2_4_ops;
|
||||
ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map;
|
||||
ar->wmi.peer_param = &wmi_peer_param_map;
|
||||
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
|
||||
ar->wmi_key_cipher = wmi_key_cipher_suites;
|
||||
break;
|
||||
@ -9348,6 +9386,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
||||
ar->wmi.ops = &wmi_10_2_ops;
|
||||
ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
|
||||
ar->wmi.peer_param = &wmi_peer_param_map;
|
||||
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
|
||||
ar->wmi_key_cipher = wmi_key_cipher_suites;
|
||||
break;
|
||||
@ -9356,6 +9395,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
||||
ar->wmi.ops = &wmi_10_1_ops;
|
||||
ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
|
||||
ar->wmi.peer_param = &wmi_peer_param_map;
|
||||
ar->wmi.peer_flags = &wmi_10x_peer_flags_map;
|
||||
ar->wmi_key_cipher = wmi_key_cipher_suites;
|
||||
break;
|
||||
@ -9364,6 +9404,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
||||
ar->wmi.ops = &wmi_ops;
|
||||
ar->wmi.vdev_param = &wmi_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_pdev_param_map;
|
||||
ar->wmi.peer_param = &wmi_peer_param_map;
|
||||
ar->wmi.peer_flags = &wmi_peer_flags_map;
|
||||
ar->wmi_key_cipher = wmi_key_cipher_suites;
|
||||
break;
|
||||
|
@ -202,6 +202,7 @@ enum wmi_service {
|
||||
WMI_SERVICE_REPORT_AIRTIME,
|
||||
WMI_SERVICE_SYNC_DELETE_CMDS,
|
||||
WMI_SERVICE_TX_PWR_PER_PEER,
|
||||
WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
|
||||
|
||||
/* Remember to add the new value to wmi_service_name()! */
|
||||
|
||||
@ -496,6 +497,7 @@ static inline char *wmi_service_name(enum wmi_service service_id)
|
||||
SVCSTR(WMI_SERVICE_REPORT_AIRTIME);
|
||||
SVCSTR(WMI_SERVICE_SYNC_DELETE_CMDS);
|
||||
SVCSTR(WMI_SERVICE_TX_PWR_PER_PEER);
|
||||
SVCSTR(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS);
|
||||
|
||||
case WMI_SERVICE_MAX:
|
||||
return NULL;
|
||||
@ -3786,6 +3788,8 @@ struct wmi_pdev_param_map {
|
||||
u32 arp_srcaddr;
|
||||
u32 arp_dstaddr;
|
||||
u32 enable_btcoex;
|
||||
u32 rfkill_config;
|
||||
u32 rfkill_enable;
|
||||
};
|
||||
|
||||
#define WMI_PDEV_PARAM_UNSUPPORTED 0
|
||||
@ -5071,6 +5075,25 @@ enum wmi_rate_preamble {
|
||||
/* Value to disable fixed rate setting */
|
||||
#define WMI_FIXED_RATE_NONE (0xff)
|
||||
|
||||
struct wmi_peer_param_map {
|
||||
u32 smps_state;
|
||||
u32 ampdu;
|
||||
u32 authorize;
|
||||
u32 chan_width;
|
||||
u32 nss;
|
||||
u32 use_4addr;
|
||||
u32 membership;
|
||||
u32 use_fixed_power;
|
||||
u32 user_pos;
|
||||
u32 crit_proto_hint_enabled;
|
||||
u32 tx_fail_cnt_thr;
|
||||
u32 set_hw_retry_cts2s;
|
||||
u32 ibss_atim_win_len;
|
||||
u32 debug;
|
||||
u32 phymode;
|
||||
u32 dummy_var;
|
||||
};
|
||||
|
||||
struct wmi_vdev_param_map {
|
||||
u32 rts_threshold;
|
||||
u32 fragmentation_threshold;
|
||||
@ -6842,6 +6865,7 @@ struct wmi_svc_rdy_ev_arg {
|
||||
__le32 max_tx_power;
|
||||
__le32 ht_cap;
|
||||
__le32 vht_cap;
|
||||
__le32 vht_supp_mcs;
|
||||
__le32 sw_ver0;
|
||||
__le32 sw_ver1;
|
||||
__le32 fw_build;
|
||||
@ -6849,8 +6873,11 @@ struct wmi_svc_rdy_ev_arg {
|
||||
__le32 num_rf_chains;
|
||||
__le32 eeprom_rd;
|
||||
__le32 num_mem_reqs;
|
||||
__le32 low_2ghz_chan;
|
||||
__le32 high_2ghz_chan;
|
||||
__le32 low_5ghz_chan;
|
||||
__le32 high_5ghz_chan;
|
||||
__le32 sys_cap_info;
|
||||
const __le32 *service_map;
|
||||
size_t service_map_len;
|
||||
const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
|
||||
|
@ -300,8 +300,7 @@ ath5k_pci_remove(struct pci_dev *pdev)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int ath5k_pci_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct ieee80211_hw *hw = dev_get_drvdata(dev);
|
||||
struct ath5k_hw *ah = hw->priv;
|
||||
|
||||
ath5k_led_off(ah);
|
||||
|
@ -4183,7 +4183,7 @@ static void ar9003_hw_thermometer_apply(struct ath_hw *ah)
|
||||
|
||||
static void ar9003_hw_thermo_cal_apply(struct ath_hw *ah)
|
||||
{
|
||||
u32 data, ko, kg;
|
||||
u32 data = 0, ko, kg;
|
||||
|
||||
if (!AR_SREV_9462_20_OR_LATER(ah))
|
||||
return;
|
||||
|
@ -12,7 +12,6 @@
|
||||
* initialize the chip when the user-space is ready to extract the init code.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/firmware.h>
|
||||
|
@ -973,6 +973,8 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
struct ath_htc_rx_status *rxstatus;
|
||||
struct ath_rx_status rx_stats;
|
||||
bool decrypt_error = false;
|
||||
__be16 rs_datalen;
|
||||
bool is_phyerr;
|
||||
|
||||
if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
|
||||
ath_err(common, "Corrupted RX frame, dropping (len: %d)\n",
|
||||
@ -982,11 +984,24 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
|
||||
rxstatus = (struct ath_htc_rx_status *)skb->data;
|
||||
|
||||
if (be16_to_cpu(rxstatus->rs_datalen) -
|
||||
(skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) {
|
||||
rs_datalen = be16_to_cpu(rxstatus->rs_datalen);
|
||||
if (unlikely(rs_datalen -
|
||||
(skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0)) {
|
||||
ath_err(common,
|
||||
"Corrupted RX data len, dropping (dlen: %d, skblen: %d)\n",
|
||||
rxstatus->rs_datalen, skb->len);
|
||||
rs_datalen, skb->len);
|
||||
goto rx_next;
|
||||
}
|
||||
|
||||
is_phyerr = rxstatus->rs_status & ATH9K_RXERR_PHY;
|
||||
/*
|
||||
* Discard zero-length packets and packets smaller than an ACK
|
||||
* which are not PHY_ERROR (short radar pulses have a length of 3)
|
||||
*/
|
||||
if (unlikely(!rs_datalen || (rs_datalen < 10 && !is_phyerr))) {
|
||||
ath_warn(common,
|
||||
"Short RX data len, dropping (dlen: %d)\n",
|
||||
rs_datalen);
|
||||
goto rx_next;
|
||||
}
|
||||
|
||||
@ -1011,7 +1026,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
* Process PHY errors and return so that the packet
|
||||
* can be dropped.
|
||||
*/
|
||||
if (rx_stats.rs_status & ATH9K_RXERR_PHY) {
|
||||
if (unlikely(is_phyerr)) {
|
||||
/* TODO: Not using DFS processing now. */
|
||||
if (ath_cmn_process_fft(&priv->spec_priv, hdr,
|
||||
&rx_stats, rx_status->mactime)) {
|
||||
|
@ -1021,13 +1021,12 @@ static void ath_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
static int ath_pci_suspend(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct ieee80211_hw *hw = dev_get_drvdata(device);
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
|
||||
if (test_bit(ATH_OP_WOW_ENABLED, &common->op_flags)) {
|
||||
dev_info(&pdev->dev, "WOW is enabled, bypassing PCI suspend\n");
|
||||
dev_info(device, "WOW is enabled, bypassing PCI suspend\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -629,8 +629,7 @@ static int __maybe_unused wil6210_pm_resume(struct device *dev)
|
||||
|
||||
static int __maybe_unused wil6210_pm_runtime_idle(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct wil6210_priv *wil = pci_get_drvdata(pdev);
|
||||
struct wil6210_priv *wil = dev_get_drvdata(dev);
|
||||
|
||||
wil_dbg_pm(wil, "Runtime idle\n");
|
||||
|
||||
@ -644,8 +643,7 @@ static int __maybe_unused wil6210_pm_runtime_resume(struct device *dev)
|
||||
|
||||
static int __maybe_unused wil6210_pm_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct wil6210_priv *wil = pci_get_drvdata(pdev);
|
||||
struct wil6210_priv *wil = dev_get_drvdata(dev);
|
||||
|
||||
if (test_bit(wil_status_suspended, wil->status)) {
|
||||
wil_dbg_pm(wil, "trying to suspend while suspended\n");
|
||||
|
@ -2505,7 +2505,8 @@ int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie)
|
||||
cmd->mgmt_frm_type = type;
|
||||
/* BUG: FW API define ieLen as u8. Will fix FW */
|
||||
cmd->ie_len = cpu_to_le16(ie_len);
|
||||
memcpy(cmd->ie_info, ie, ie_len);
|
||||
if (ie_len)
|
||||
memcpy(cmd->ie_info, ie, ie_len);
|
||||
rc = wmi_send(wil, WMI_SET_APPIE_CMDID, vif->mid, cmd, len);
|
||||
kfree(cmd);
|
||||
out:
|
||||
@ -2541,7 +2542,8 @@ int wmi_update_ft_ies(struct wil6210_vif *vif, u16 ie_len, const void *ie)
|
||||
}
|
||||
|
||||
cmd->ie_len = cpu_to_le16(ie_len);
|
||||
memcpy(cmd->ie_info, ie, ie_len);
|
||||
if (ie_len)
|
||||
memcpy(cmd->ie_info, ie, ie_len);
|
||||
rc = wmi_send(wil, WMI_UPDATE_FT_IES_CMDID, vif->mid, cmd, len);
|
||||
kfree(cmd);
|
||||
|
||||
@ -2715,7 +2717,7 @@ int wmi_get_all_temperatures(struct wil6210_priv *wil,
|
||||
return rc;
|
||||
|
||||
if (reply.evt.status == WMI_FW_STATUS_FAILURE) {
|
||||
wil_err(wil, "Failed geting TEMP_SENSE_ALL\n");
|
||||
wil_err(wil, "Failed getting TEMP_SENSE_ALL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user