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:
Kalle Valo 2019-10-03 16:39:51 +03:00
commit 97ef12263f
31 changed files with 733 additions and 434 deletions

View File

@ -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):

View File

@ -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;

View File

@ -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, &param);
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, &param);
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, &param);
ret = ath10k_bmi_read32(ar, hi_option_flag, &param);
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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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 = {

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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");
}

View File

@ -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,

View File

@ -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;

View File

@ -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:

View File

@ -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) {

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;

View File

@ -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];

View File

@ -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);

View File

@ -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;

View File

@ -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>

View File

@ -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)) {

View File

@ -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;
}

View File

@ -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");

View File

@ -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;
}