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

ath.git patches for 4.20. Major changes:

ath10k

* support NET_DETECT WoWLAN feature

* wcn3990 basic functionality now working after we got QMI support
This commit is contained in:
Kalle Valo 2018-10-14 12:21:43 +03:00
commit f95cd52476
30 changed files with 4997 additions and 109 deletions

View File

@ -56,6 +56,11 @@ Optional properties:
the length can vary between hw versions. the length can vary between hw versions.
- <supply-name>-supply: handle to the regulator device tree node - <supply-name>-supply: handle to the regulator device tree node
optional "supply-name" is "vdd-0.8-cx-mx". optional "supply-name" is "vdd-0.8-cx-mx".
- memory-region:
Usage: optional
Value type: <phandle>
Definition: reference to the reserved-memory for the msa region
used by the wifi firmware running in Q6.
Example (to supply the calibration data alone): Example (to supply the calibration data alone):
@ -149,4 +154,5 @@ wifi@18000000 {
<0 140 0 /* CE10 */ >, <0 140 0 /* CE10 */ >,
<0 141 0 /* CE11 */ >; <0 141 0 /* CE11 */ >;
vdd-0.8-cx-mx-supply = <&pm8998_l5>; vdd-0.8-cx-mx-supply = <&pm8998_l5>;
memory-region = <&wifi_msa_mem>;
}; };

View File

@ -44,6 +44,7 @@ config ATH10K_SNOC
tristate "Qualcomm ath10k SNOC support (EXPERIMENTAL)" tristate "Qualcomm ath10k SNOC support (EXPERIMENTAL)"
depends on ATH10K depends on ATH10K
depends on ARCH_QCOM || COMPILE_TEST depends on ARCH_QCOM || COMPILE_TEST
select QCOM_QMI_HELPERS
---help--- ---help---
This module adds support for integrated WCN3990 chip connected This module adds support for integrated WCN3990 chip connected
to system NOC(SNOC). Currently work in progress and will not to system NOC(SNOC). Currently work in progress and will not

View File

@ -36,7 +36,9 @@ obj-$(CONFIG_ATH10K_USB) += ath10k_usb.o
ath10k_usb-y += usb.o ath10k_usb-y += usb.o
obj-$(CONFIG_ATH10K_SNOC) += ath10k_snoc.o obj-$(CONFIG_ATH10K_SNOC) += ath10k_snoc.o
ath10k_snoc-y += snoc.o ath10k_snoc-y += qmi.o \
qmi_wlfw_v01.o \
snoc.o
# for tracing framework to find trace.h # for tracing framework to find trace.h
CFLAGS_trace.o := -I$(src) CFLAGS_trace.o := -I$(src)

View File

@ -989,7 +989,7 @@ static int ath10k_download_fw(struct ath10k *ar)
data, data_len); data, data_len);
} }
static void ath10k_core_free_board_files(struct ath10k *ar) void ath10k_core_free_board_files(struct ath10k *ar)
{ {
if (!IS_ERR(ar->normal_mode_fw.board)) if (!IS_ERR(ar->normal_mode_fw.board))
release_firmware(ar->normal_mode_fw.board); release_firmware(ar->normal_mode_fw.board);
@ -1004,6 +1004,7 @@ static void ath10k_core_free_board_files(struct ath10k *ar)
ar->normal_mode_fw.ext_board_data = NULL; ar->normal_mode_fw.ext_board_data = NULL;
ar->normal_mode_fw.ext_board_len = 0; ar->normal_mode_fw.ext_board_len = 0;
} }
EXPORT_SYMBOL(ath10k_core_free_board_files);
static void ath10k_core_free_firmware_files(struct ath10k *ar) static void ath10k_core_free_firmware_files(struct ath10k *ar)
{ {
@ -1331,6 +1332,14 @@ static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
goto out; goto out;
} }
if (ar->id.qmi_ids_valid) {
scnprintf(name, name_len,
"bus=%s,qmi-board-id=%x",
ath10k_bus_str(ar->hif.bus),
ar->id.qmi_board_id);
goto out;
}
scnprintf(name, name_len, scnprintf(name, name_len,
"bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s", "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s",
ath10k_bus_str(ar->hif.bus), ath10k_bus_str(ar->hif.bus),
@ -1359,7 +1368,7 @@ static int ath10k_core_create_eboard_name(struct ath10k *ar, char *name,
return -1; return -1;
} }
static int ath10k_core_fetch_board_file(struct ath10k *ar, int bd_ie_type) int ath10k_core_fetch_board_file(struct ath10k *ar, int bd_ie_type)
{ {
char boardname[100], fallback_boardname[100]; char boardname[100], fallback_boardname[100];
int ret; int ret;
@ -1407,6 +1416,7 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar, int bd_ie_type)
ath10k_dbg(ar, ATH10K_DBG_BOOT, "using board api %d\n", ar->bd_api); ath10k_dbg(ar, ATH10K_DBG_BOOT, "using board api %d\n", ar->bd_api);
return 0; return 0;
} }
EXPORT_SYMBOL(ath10k_core_fetch_board_file);
static int ath10k_core_get_ext_board_id_from_otp(struct ath10k *ar) static int ath10k_core_get_ext_board_id_from_otp(struct ath10k *ar)
{ {

View File

@ -951,6 +951,7 @@ struct ath10k {
/* protected by conf_mutex */ /* protected by conf_mutex */
u8 ps_state_enable; u8 ps_state_enable;
bool nlo_enabled;
bool p2p; bool p2p;
struct { struct {
@ -988,6 +989,8 @@ struct ath10k {
u32 subsystem_device; u32 subsystem_device;
bool bmi_ids_valid; bool bmi_ids_valid;
bool qmi_ids_valid;
u32 qmi_board_id;
u8 bmi_board_id; u8 bmi_board_id;
u8 bmi_eboard_id; u8 bmi_eboard_id;
u8 bmi_chip_id; u8 bmi_chip_id;
@ -1215,5 +1218,7 @@ void ath10k_core_stop(struct ath10k *ar);
int ath10k_core_register(struct ath10k *ar, int ath10k_core_register(struct ath10k *ar,
const struct ath10k_bus_params *bus_params); const struct ath10k_bus_params *bus_params);
void ath10k_core_unregister(struct ath10k *ar); void ath10k_core_unregister(struct ath10k *ar);
int ath10k_core_fetch_board_file(struct ath10k *ar, int bd_ie_type);
void ath10k_core_free_board_files(struct ath10k *ar);
#endif /* _CORE_H_ */ #endif /* _CORE_H_ */

View File

@ -2421,7 +2421,7 @@ static ssize_t ath10k_write_ps_state_enable(struct file *file,
if (kstrtou8_from_user(user_buf, count, 0, &ps_state_enable)) if (kstrtou8_from_user(user_buf, count, 0, &ps_state_enable))
return -EINVAL; return -EINVAL;
if (ps_state_enable > 1 || ps_state_enable < 0) if (ps_state_enable > 1)
return -EINVAL; return -EINVAL;
mutex_lock(&ar->conf_mutex); mutex_lock(&ar->conf_mutex);

View File

@ -44,6 +44,7 @@ enum ath10k_debug_mask {
ATH10K_DBG_USB = 0x00040000, ATH10K_DBG_USB = 0x00040000,
ATH10K_DBG_USB_BULK = 0x00080000, ATH10K_DBG_USB_BULK = 0x00080000,
ATH10K_DBG_SNOC = 0x00100000, ATH10K_DBG_SNOC = 0x00100000,
ATH10K_DBG_QMI = 0x00200000,
ATH10K_DBG_ANY = 0xffffffff, ATH10K_DBG_ANY = 0xffffffff,
}; };

View File

@ -2680,8 +2680,6 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar,
STATS_OP_FMT(RETRY).ht[1][ht_idx] += pstats->retry_pkts; STATS_OP_FMT(RETRY).ht[1][ht_idx] += pstats->retry_pkts;
} else { } else {
mcs = legacy_rate_idx; mcs = legacy_rate_idx;
if (mcs < 0)
return;
STATS_OP_FMT(SUCC).legacy[0][mcs] += pstats->succ_bytes; STATS_OP_FMT(SUCC).legacy[0][mcs] += pstats->succ_bytes;
STATS_OP_FMT(SUCC).legacy[1][mcs] += pstats->succ_pkts; STATS_OP_FMT(SUCC).legacy[1][mcs] += pstats->succ_pkts;
@ -2753,7 +2751,8 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
struct ath10k_per_peer_tx_stats *peer_stats) struct ath10k_per_peer_tx_stats *peer_stats)
{ {
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
u8 rate = 0, rate_idx = 0, sgi; u8 rate = 0, sgi;
s8 rate_idx = 0;
struct rate_info txrate; struct rate_info txrate;
lockdep_assert_held(&ar->data_lock); lockdep_assert_held(&ar->data_lock);

View File

@ -164,7 +164,7 @@ static int ath10k_mac_get_rate_hw_value(int bitrate)
if (ath10k_mac_bitrate_is_cck(bitrate)) if (ath10k_mac_bitrate_is_cck(bitrate))
hw_value_prefix = WMI_RATE_PREAMBLE_CCK << 6; hw_value_prefix = WMI_RATE_PREAMBLE_CCK << 6;
for (i = 0; i < sizeof(ath10k_rates); i++) { for (i = 0; i < ARRAY_SIZE(ath10k_rates); i++) {
if (ath10k_rates[i].bitrate == bitrate) if (ath10k_rates[i].bitrate == bitrate)
return hw_value_prefix | ath10k_rates[i].hw_value; return hw_value_prefix | ath10k_rates[i].hw_value;
} }
@ -4697,6 +4697,14 @@ static int ath10k_start(struct ieee80211_hw *hw)
goto err_core_stop; goto err_core_stop;
} }
if (test_bit(WMI_SERVICE_SPOOF_MAC_SUPPORT, ar->wmi.svc_map)) {
ret = ath10k_wmi_scan_prob_req_oui(ar, ar->mac_addr);
if (ret) {
ath10k_err(ar, "failed to set prob req oui: %i\n", ret);
goto err_core_stop;
}
}
if (test_bit(WMI_SERVICE_ADAPTIVE_OCS, ar->wmi.svc_map)) { if (test_bit(WMI_SERVICE_ADAPTIVE_OCS, ar->wmi.svc_map)) {
ret = ath10k_wmi_adaptive_qcs(ar, true); ret = ath10k_wmi_adaptive_qcs(ar, true);
if (ret) { if (ret) {
@ -5682,22 +5690,22 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
return; return;
} }
sband = ar->hw->wiphy->bands[def.chan->band]; sband = ar->hw->wiphy->bands[def.chan->band];
basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1; basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
bitrate = sband->bitrates[basic_rate_idx].bitrate; bitrate = sband->bitrates[basic_rate_idx].bitrate;
hw_rate_code = ath10k_mac_get_rate_hw_value(bitrate); hw_rate_code = ath10k_mac_get_rate_hw_value(bitrate);
if (hw_rate_code < 0) { if (hw_rate_code < 0) {
ath10k_warn(ar, "bitrate not supported %d\n", bitrate); ath10k_warn(ar, "bitrate not supported %d\n", bitrate);
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);
return; return;
} }
vdev_param = ar->wmi.vdev_param->mgmt_rate; vdev_param = ar->wmi.vdev_param->mgmt_rate;
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
hw_rate_code); hw_rate_code);
if (ret) if (ret)
ath10k_warn(ar, "failed to set mgmt tx rate %d\n", ret); ath10k_warn(ar, "failed to set mgmt tx rate %d\n", ret);
} }
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);
@ -6855,9 +6863,20 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop) u32 queues, bool drop)
{ {
struct ath10k *ar = hw->priv; struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif;
u32 bitmap;
if (drop) if (drop) {
if (vif->type == NL80211_IFTYPE_STATION) {
bitmap = ~(1 << WMI_MGMT_TID);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
ath10k_wmi_peer_flush(ar, arvif->vdev_id,
arvif->bssid, bitmap);
}
}
return; return;
}
mutex_lock(&ar->conf_mutex); mutex_lock(&ar->conf_mutex);
ath10k_mac_wait_tx_complete(ar); ath10k_mac_wait_tx_complete(ar);
@ -8493,6 +8512,18 @@ int ath10k_mac_register(struct ath10k *ar)
ar->hw->wiphy->max_scan_ssids = WLAN_SCAN_PARAMS_MAX_SSID; ar->hw->wiphy->max_scan_ssids = WLAN_SCAN_PARAMS_MAX_SSID;
ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN; ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN;
if (test_bit(WMI_SERVICE_NLO, ar->wmi.svc_map)) {
ar->hw->wiphy->max_sched_scan_reqs = 1;
ar->hw->wiphy->max_sched_scan_ssids = WMI_PNO_MAX_SUPP_NETWORKS;
ar->hw->wiphy->max_match_sets = WMI_PNO_MAX_SUPP_NETWORKS;
ar->hw->wiphy->max_sched_scan_ie_len = WMI_PNO_MAX_IE_LENGTH;
ar->hw->wiphy->max_sched_scan_plans = WMI_PNO_MAX_SCHED_SCAN_PLANS;
ar->hw->wiphy->max_sched_scan_plan_interval =
WMI_PNO_MAX_SCHED_SCAN_PLAN_INT;
ar->hw->wiphy->max_sched_scan_plan_iterations =
WMI_PNO_MAX_SCHED_SCAN_PLAN_ITRNS;
}
ar->hw->vif_data_size = sizeof(struct ath10k_vif); ar->hw->vif_data_size = sizeof(struct ath10k_vif);
ar->hw->sta_data_size = sizeof(struct ath10k_sta); ar->hw->sta_data_size = sizeof(struct ath10k_sta);
ar->hw->txq_data_size = sizeof(struct ath10k_txq); ar->hw->txq_data_size = sizeof(struct ath10k_txq);
@ -8542,9 +8573,10 @@ int ath10k_mac_register(struct ath10k *ar)
wiphy_ext_feature_set(ar->hw->wiphy, wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_SET_SCAN_DWELL); NL80211_EXT_FEATURE_SET_SCAN_DWELL);
if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map) ||
test_bit(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, ar->wmi.svc_map))
wiphy_ext_feature_set(ar->hw->wiphy, wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT); NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
/* /*
* on LL hardware queues are managed entirely by the FW * on LL hardware queues are managed entirely by the FW
@ -8635,12 +8667,6 @@ int ath10k_mac_register(struct ath10k *ar)
} }
if (test_bit(WMI_SERVICE_SPOOF_MAC_SUPPORT, ar->wmi.svc_map)) { if (test_bit(WMI_SERVICE_SPOOF_MAC_SUPPORT, ar->wmi.svc_map)) {
ret = ath10k_wmi_scan_prob_req_oui(ar, ar->mac_addr);
if (ret) {
ath10k_err(ar, "failed to set prob req oui: %i\n", ret);
goto err_dfs_detector_exit;
}
ar->hw->wiphy->features |= ar->hw->wiphy->features |=
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
} }

View File

@ -1071,10 +1071,9 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
struct ath10k_ce *ce = ath10k_ce_priv(ar); struct ath10k_ce *ce = ath10k_ce_priv(ar);
int ret = 0; int ret = 0;
u32 *buf; u32 *buf;
unsigned int completed_nbytes, orig_nbytes, remaining_bytes; unsigned int completed_nbytes, alloc_nbytes, remaining_bytes;
struct ath10k_ce_pipe *ce_diag; struct ath10k_ce_pipe *ce_diag;
void *data_buf = NULL; void *data_buf = NULL;
u32 ce_data; /* Host buffer address in CE space */
dma_addr_t ce_data_base = 0; dma_addr_t ce_data_base = 0;
int i; int i;
@ -1088,9 +1087,10 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
* 1) 4-byte alignment * 1) 4-byte alignment
* 2) Buffer in DMA-able space * 2) Buffer in DMA-able space
*/ */
orig_nbytes = nbytes; alloc_nbytes = min_t(unsigned int, nbytes, DIAG_TRANSFER_LIMIT);
data_buf = (unsigned char *)dma_alloc_coherent(ar->dev, data_buf = (unsigned char *)dma_alloc_coherent(ar->dev,
orig_nbytes, alloc_nbytes,
&ce_data_base, &ce_data_base,
GFP_ATOMIC); GFP_ATOMIC);
if (!data_buf) { if (!data_buf) {
@ -1098,9 +1098,6 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
goto done; goto done;
} }
/* Copy caller's data to allocated DMA buf */
memcpy(data_buf, data, orig_nbytes);
/* /*
* The address supplied by the caller is in the * The address supplied by the caller is in the
* Target CPU virtual address space. * Target CPU virtual address space.
@ -1113,12 +1110,14 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
*/ */
address = ath10k_pci_targ_cpu_to_ce_addr(ar, address); address = ath10k_pci_targ_cpu_to_ce_addr(ar, address);
remaining_bytes = orig_nbytes; remaining_bytes = nbytes;
ce_data = ce_data_base;
while (remaining_bytes) { while (remaining_bytes) {
/* FIXME: check cast */ /* FIXME: check cast */
nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT); nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT);
/* Copy caller's data to allocated DMA buf */
memcpy(data_buf, data, nbytes);
/* Set up to receive directly into Target(!) address */ /* Set up to receive directly into Target(!) address */
ret = ce_diag->ops->ce_rx_post_buf(ce_diag, &address, address); ret = ce_diag->ops->ce_rx_post_buf(ce_diag, &address, address);
if (ret != 0) if (ret != 0)
@ -1128,7 +1127,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
* Request CE to send caller-supplied data that * Request CE to send caller-supplied data that
* was copied to bounce buffer to Target(!) address. * was copied to bounce buffer to Target(!) address.
*/ */
ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)ce_data, ret = ath10k_ce_send_nolock(ce_diag, NULL, ce_data_base,
nbytes, 0, 0); nbytes, 0, 0);
if (ret != 0) if (ret != 0)
goto done; goto done;
@ -1171,12 +1170,12 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
remaining_bytes -= nbytes; remaining_bytes -= nbytes;
address += nbytes; address += nbytes;
ce_data += nbytes; data += nbytes;
} }
done: done:
if (data_buf) { if (data_buf) {
dma_free_coherent(ar->dev, orig_nbytes, data_buf, dma_free_coherent(ar->dev, alloc_nbytes, data_buf,
ce_data_base); ce_data_base);
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,129 @@
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _ATH10K_QMI_H_
#define _ATH10K_QMI_H_
#include <linux/soc/qcom/qmi.h>
#include <linux/qrtr.h>
#include "qmi_wlfw_v01.h"
#define MAX_NUM_MEMORY_REGIONS 2
#define MAX_TIMESTAMP_LEN 32
#define MAX_BUILD_ID_LEN 128
#define MAX_NUM_CAL_V01 5
enum ath10k_qmi_driver_event_type {
ATH10K_QMI_EVENT_SERVER_ARRIVE,
ATH10K_QMI_EVENT_SERVER_EXIT,
ATH10K_QMI_EVENT_FW_READY_IND,
ATH10K_QMI_EVENT_FW_DOWN_IND,
ATH10K_QMI_EVENT_MSA_READY_IND,
ATH10K_QMI_EVENT_MAX,
};
struct ath10k_msa_mem_info {
phys_addr_t addr;
u32 size;
bool secure;
};
struct ath10k_qmi_chip_info {
u32 chip_id;
u32 chip_family;
};
struct ath10k_qmi_board_info {
u32 board_id;
};
struct ath10k_qmi_soc_info {
u32 soc_id;
};
struct ath10k_qmi_cal_data {
u32 cal_id;
u32 total_size;
u8 *data;
};
struct ath10k_tgt_pipe_cfg {
__le32 pipe_num;
__le32 pipe_dir;
__le32 nentries;
__le32 nbytes_max;
__le32 flags;
__le32 reserved;
};
struct ath10k_svc_pipe_cfg {
__le32 service_id;
__le32 pipe_dir;
__le32 pipe_num;
};
struct ath10k_shadow_reg_cfg {
__le16 ce_id;
__le16 reg_offset;
};
struct ath10k_qmi_wlan_enable_cfg {
u32 num_ce_tgt_cfg;
struct ath10k_tgt_pipe_cfg *ce_tgt_cfg;
u32 num_ce_svc_pipe_cfg;
struct ath10k_svc_pipe_cfg *ce_svc_cfg;
u32 num_shadow_reg_cfg;
struct ath10k_shadow_reg_cfg *shadow_reg_cfg;
};
struct ath10k_qmi_driver_event {
struct list_head list;
enum ath10k_qmi_driver_event_type type;
void *data;
};
struct ath10k_qmi {
struct ath10k *ar;
struct qmi_handle qmi_hdl;
struct sockaddr_qrtr sq;
struct work_struct event_work;
struct workqueue_struct *event_wq;
struct list_head event_list;
spinlock_t event_lock; /* spinlock for qmi event list */
u32 nr_mem_region;
struct ath10k_msa_mem_info mem_region[MAX_NUM_MEMORY_REGIONS];
dma_addr_t msa_pa;
u32 msa_mem_size;
void *msa_va;
struct ath10k_qmi_chip_info chip_info;
struct ath10k_qmi_board_info board_info;
struct ath10k_qmi_soc_info soc_info;
char fw_build_id[MAX_BUILD_ID_LEN + 1];
u32 fw_version;
bool fw_ready;
char fw_build_timestamp[MAX_TIMESTAMP_LEN + 1];
struct ath10k_qmi_cal_data cal_data[MAX_NUM_CAL_V01];
};
int ath10k_qmi_wlan_enable(struct ath10k *ar,
struct ath10k_qmi_wlan_enable_cfg *config,
enum wlfw_driver_mode_enum_v01 mode,
const char *version);
int ath10k_qmi_wlan_disable(struct ath10k *ar);
int ath10k_qmi_register_service_notifier(struct notifier_block *nb);
int ath10k_qmi_init(struct ath10k *ar, u32 msa_size);
int ath10k_qmi_deinit(struct ath10k *ar);
#endif /* ATH10K_QMI_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,677 @@
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef WCN3990_QMI_SVC_V01_H
#define WCN3990_QMI_SVC_V01_H
#define WLFW_SERVICE_ID_V01 0x45
#define WLFW_SERVICE_VERS_V01 0x01
#define QMI_WLFW_BDF_DOWNLOAD_REQ_V01 0x0025
#define QMI_WLFW_MEM_READY_IND_V01 0x0037
#define QMI_WLFW_DYNAMIC_FEATURE_MASK_RESP_V01 0x003B
#define QMI_WLFW_INITIATE_CAL_UPDATE_IND_V01 0x002A
#define QMI_WLFW_HOST_CAP_REQ_V01 0x0034
#define QMI_WLFW_M3_INFO_REQ_V01 0x003C
#define QMI_WLFW_CAP_REQ_V01 0x0024
#define QMI_WLFW_FW_INIT_DONE_IND_V01 0x0038
#define QMI_WLFW_CAL_REPORT_REQ_V01 0x0026
#define QMI_WLFW_M3_INFO_RESP_V01 0x003C
#define QMI_WLFW_CAL_UPDATE_RESP_V01 0x0029
#define QMI_WLFW_CAL_DOWNLOAD_RESP_V01 0x0027
#define QMI_WLFW_XO_CAL_IND_V01 0x003D
#define QMI_WLFW_INI_RESP_V01 0x002F
#define QMI_WLFW_CAL_REPORT_RESP_V01 0x0026
#define QMI_WLFW_MAC_ADDR_RESP_V01 0x0033
#define QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01 0x0028
#define QMI_WLFW_HOST_CAP_RESP_V01 0x0034
#define QMI_WLFW_MSA_READY_IND_V01 0x002B
#define QMI_WLFW_ATHDIAG_WRITE_RESP_V01 0x0031
#define QMI_WLFW_WLAN_MODE_REQ_V01 0x0022
#define QMI_WLFW_IND_REGISTER_REQ_V01 0x0020
#define QMI_WLFW_WLAN_CFG_RESP_V01 0x0023
#define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035
#define QMI_WLFW_REJUVENATE_IND_V01 0x0039
#define QMI_WLFW_DYNAMIC_FEATURE_MASK_REQ_V01 0x003B
#define QMI_WLFW_ATHDIAG_WRITE_REQ_V01 0x0031
#define QMI_WLFW_WLAN_MODE_RESP_V01 0x0022
#define QMI_WLFW_RESPOND_MEM_REQ_V01 0x0036
#define QMI_WLFW_PIN_CONNECT_RESULT_IND_V01 0x002C
#define QMI_WLFW_FW_READY_IND_V01 0x0021
#define QMI_WLFW_MSA_READY_RESP_V01 0x002E
#define QMI_WLFW_CAL_UPDATE_REQ_V01 0x0029
#define QMI_WLFW_INI_REQ_V01 0x002F
#define QMI_WLFW_BDF_DOWNLOAD_RESP_V01 0x0025
#define QMI_WLFW_REJUVENATE_ACK_RESP_V01 0x003A
#define QMI_WLFW_MSA_INFO_RESP_V01 0x002D
#define QMI_WLFW_MSA_READY_REQ_V01 0x002E
#define QMI_WLFW_CAP_RESP_V01 0x0024
#define QMI_WLFW_REJUVENATE_ACK_REQ_V01 0x003A
#define QMI_WLFW_ATHDIAG_READ_RESP_V01 0x0030
#define QMI_WLFW_VBATT_REQ_V01 0x0032
#define QMI_WLFW_MAC_ADDR_REQ_V01 0x0033
#define QMI_WLFW_RESPOND_MEM_RESP_V01 0x0036
#define QMI_WLFW_VBATT_RESP_V01 0x0032
#define QMI_WLFW_MSA_INFO_REQ_V01 0x002D
#define QMI_WLFW_CAL_DOWNLOAD_REQ_V01 0x0027
#define QMI_WLFW_ATHDIAG_READ_REQ_V01 0x0030
#define QMI_WLFW_WLAN_CFG_REQ_V01 0x0023
#define QMI_WLFW_IND_REGISTER_RESP_V01 0x0020
#define QMI_WLFW_MAX_MEM_REG_V01 2
#define QMI_WLFW_MAX_NUM_MEM_SEG_V01 16
#define QMI_WLFW_MAX_NUM_CAL_V01 5
#define QMI_WLFW_MAX_DATA_SIZE_V01 6144
#define QMI_WLFW_FUNCTION_NAME_LEN_V01 128
#define QMI_WLFW_MAX_NUM_CE_V01 12
#define QMI_WLFW_MAX_TIMESTAMP_LEN_V01 32
#define QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01 6144
#define QMI_WLFW_MAX_NUM_GPIO_V01 32
#define QMI_WLFW_MAX_BUILD_ID_LEN_V01 128
#define QMI_WLFW_MAX_NUM_MEM_CFG_V01 2
#define QMI_WLFW_MAX_STR_LEN_V01 16
#define QMI_WLFW_MAX_NUM_SHADOW_REG_V01 24
#define QMI_WLFW_MAC_ADDR_SIZE_V01 6
#define QMI_WLFW_MAX_SHADOW_REG_V2 36
#define QMI_WLFW_MAX_NUM_SVC_V01 24
enum wlfw_driver_mode_enum_v01 {
QMI_WLFW_MISSION_V01 = 0,
QMI_WLFW_FTM_V01 = 1,
QMI_WLFW_EPPING_V01 = 2,
QMI_WLFW_WALTEST_V01 = 3,
QMI_WLFW_OFF_V01 = 4,
QMI_WLFW_CCPM_V01 = 5,
QMI_WLFW_QVIT_V01 = 6,
QMI_WLFW_CALIBRATION_V01 = 7,
};
enum wlfw_cal_temp_id_enum_v01 {
QMI_WLFW_CAL_TEMP_IDX_0_V01 = 0,
QMI_WLFW_CAL_TEMP_IDX_1_V01 = 1,
QMI_WLFW_CAL_TEMP_IDX_2_V01 = 2,
QMI_WLFW_CAL_TEMP_IDX_3_V01 = 3,
QMI_WLFW_CAL_TEMP_IDX_4_V01 = 4,
};
enum wlfw_pipedir_enum_v01 {
QMI_WLFW_PIPEDIR_NONE_V01 = 0,
QMI_WLFW_PIPEDIR_IN_V01 = 1,
QMI_WLFW_PIPEDIR_OUT_V01 = 2,
QMI_WLFW_PIPEDIR_INOUT_V01 = 3,
};
enum wlfw_mem_type_enum_v01 {
QMI_WLFW_MEM_TYPE_MSA_V01 = 0,
QMI_WLFW_MEM_TYPE_DDR_V01 = 1,
};
#define QMI_WLFW_CE_ATTR_FLAGS_V01 ((u32)0x00)
#define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01)
#define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((u32)0x02)
#define QMI_WLFW_CE_ATTR_SWIZZLE_DESCRIPTORS_V01 ((u32)0x04)
#define QMI_WLFW_CE_ATTR_DISABLE_INTR_V01 ((u32)0x08)
#define QMI_WLFW_CE_ATTR_ENABLE_POLL_V01 ((u32)0x10)
#define QMI_WLFW_ALREADY_REGISTERED_V01 ((u64)0x01ULL)
#define QMI_WLFW_FW_READY_V01 ((u64)0x02ULL)
#define QMI_WLFW_MSA_READY_V01 ((u64)0x04ULL)
#define QMI_WLFW_MEM_READY_V01 ((u64)0x08ULL)
#define QMI_WLFW_FW_INIT_DONE_V01 ((u64)0x10ULL)
#define QMI_WLFW_FW_REJUVENATE_V01 ((u64)0x01ULL)
struct wlfw_ce_tgt_pipe_cfg_s_v01 {
__le32 pipe_num;
__le32 pipe_dir;
__le32 nentries;
__le32 nbytes_max;
__le32 flags;
};
struct wlfw_ce_svc_pipe_cfg_s_v01 {
__le32 service_id;
__le32 pipe_dir;
__le32 pipe_num;
};
struct wlfw_shadow_reg_cfg_s_v01 {
u16 id;
u16 offset;
};
struct wlfw_shadow_reg_v2_cfg_s_v01 {
u32 addr;
};
struct wlfw_memory_region_info_s_v01 {
u64 region_addr;
u32 size;
u8 secure_flag;
};
struct wlfw_mem_cfg_s_v01 {
u64 offset;
u32 size;
u8 secure_flag;
};
struct wlfw_mem_seg_s_v01 {
u32 size;
enum wlfw_mem_type_enum_v01 type;
u32 mem_cfg_len;
struct wlfw_mem_cfg_s_v01 mem_cfg[QMI_WLFW_MAX_NUM_MEM_CFG_V01];
};
struct wlfw_mem_seg_resp_s_v01 {
u64 addr;
u32 size;
enum wlfw_mem_type_enum_v01 type;
};
struct wlfw_rf_chip_info_s_v01 {
u32 chip_id;
u32 chip_family;
};
struct wlfw_rf_board_info_s_v01 {
u32 board_id;
};
struct wlfw_soc_info_s_v01 {
u32 soc_id;
};
struct wlfw_fw_version_info_s_v01 {
u32 fw_version;
char fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN_V01 + 1];
};
struct wlfw_ind_register_req_msg_v01 {
u8 fw_ready_enable_valid;
u8 fw_ready_enable;
u8 initiate_cal_download_enable_valid;
u8 initiate_cal_download_enable;
u8 initiate_cal_update_enable_valid;
u8 initiate_cal_update_enable;
u8 msa_ready_enable_valid;
u8 msa_ready_enable;
u8 pin_connect_result_enable_valid;
u8 pin_connect_result_enable;
u8 client_id_valid;
u32 client_id;
u8 request_mem_enable_valid;
u8 request_mem_enable;
u8 mem_ready_enable_valid;
u8 mem_ready_enable;
u8 fw_init_done_enable_valid;
u8 fw_init_done_enable;
u8 rejuvenate_enable_valid;
u32 rejuvenate_enable;
u8 xo_cal_enable_valid;
u8 xo_cal_enable;
};
#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 50
extern struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[];
struct wlfw_ind_register_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u8 fw_status_valid;
u64 fw_status;
};
#define WLFW_IND_REGISTER_RESP_MSG_V01_MAX_MSG_LEN 18
extern struct qmi_elem_info wlfw_ind_register_resp_msg_v01_ei[];
struct wlfw_fw_ready_ind_msg_v01 {
char placeholder;
};
#define WLFW_FW_READY_IND_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_fw_ready_ind_msg_v01_ei[];
struct wlfw_msa_ready_ind_msg_v01 {
char placeholder;
};
#define WLFW_MSA_READY_IND_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[];
struct wlfw_pin_connect_result_ind_msg_v01 {
u8 pwr_pin_result_valid;
u32 pwr_pin_result;
u8 phy_io_pin_result_valid;
u32 phy_io_pin_result;
u8 rf_pin_result_valid;
u32 rf_pin_result;
};
#define WLFW_PIN_CONNECT_RESULT_IND_MSG_V01_MAX_MSG_LEN 21
extern struct qmi_elem_info wlfw_pin_connect_result_ind_msg_v01_ei[];
struct wlfw_wlan_mode_req_msg_v01 {
enum wlfw_driver_mode_enum_v01 mode;
u8 hw_debug_valid;
u8 hw_debug;
};
#define WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN 11
extern struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[];
struct wlfw_wlan_mode_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_WLAN_MODE_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_wlan_mode_resp_msg_v01_ei[];
struct wlfw_wlan_cfg_req_msg_v01 {
u8 host_version_valid;
char host_version[QMI_WLFW_MAX_STR_LEN_V01 + 1];
u8 tgt_cfg_valid;
u32 tgt_cfg_len;
struct wlfw_ce_tgt_pipe_cfg_s_v01 tgt_cfg[QMI_WLFW_MAX_NUM_CE_V01];
u8 svc_cfg_valid;
u32 svc_cfg_len;
struct wlfw_ce_svc_pipe_cfg_s_v01 svc_cfg[QMI_WLFW_MAX_NUM_SVC_V01];
u8 shadow_reg_valid;
u32 shadow_reg_len;
struct wlfw_shadow_reg_cfg_s_v01 shadow_reg[QMI_WLFW_MAX_NUM_SHADOW_REG_V01];
u8 shadow_reg_v2_valid;
u32 shadow_reg_v2_len;
struct wlfw_shadow_reg_v2_cfg_s_v01 shadow_reg_v2[QMI_WLFW_MAX_SHADOW_REG_V2];
};
#define WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN 803
extern struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[];
struct wlfw_wlan_cfg_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_WLAN_CFG_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_wlan_cfg_resp_msg_v01_ei[];
struct wlfw_cap_req_msg_v01 {
char placeholder;
};
#define WLFW_CAP_REQ_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_cap_req_msg_v01_ei[];
struct wlfw_cap_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u8 chip_info_valid;
struct wlfw_rf_chip_info_s_v01 chip_info;
u8 board_info_valid;
struct wlfw_rf_board_info_s_v01 board_info;
u8 soc_info_valid;
struct wlfw_soc_info_s_v01 soc_info;
u8 fw_version_info_valid;
struct wlfw_fw_version_info_s_v01 fw_version_info;
u8 fw_build_id_valid;
char fw_build_id[QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1];
u8 num_macs_valid;
u8 num_macs;
};
#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 207
extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[];
struct wlfw_bdf_download_req_msg_v01 {
u8 valid;
u8 file_id_valid;
enum wlfw_cal_temp_id_enum_v01 file_id;
u8 total_size_valid;
u32 total_size;
u8 seg_id_valid;
u32 seg_id;
u8 data_valid;
u32 data_len;
u8 data[QMI_WLFW_MAX_DATA_SIZE_V01];
u8 end_valid;
u8 end;
u8 bdf_type_valid;
u8 bdf_type;
};
#define WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6182
extern struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[];
struct wlfw_bdf_download_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_BDF_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_bdf_download_resp_msg_v01_ei[];
struct wlfw_cal_report_req_msg_v01 {
u32 meta_data_len;
enum wlfw_cal_temp_id_enum_v01 meta_data[QMI_WLFW_MAX_NUM_CAL_V01];
u8 xo_cal_data_valid;
u8 xo_cal_data;
};
#define WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN 28
extern struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[];
struct wlfw_cal_report_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_CAL_REPORT_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_cal_report_resp_msg_v01_ei[];
struct wlfw_initiate_cal_download_ind_msg_v01 {
enum wlfw_cal_temp_id_enum_v01 cal_id;
};
#define WLFW_INITIATE_CAL_DOWNLOAD_IND_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[];
struct wlfw_cal_download_req_msg_v01 {
u8 valid;
u8 file_id_valid;
enum wlfw_cal_temp_id_enum_v01 file_id;
u8 total_size_valid;
u32 total_size;
u8 seg_id_valid;
u32 seg_id;
u8 data_valid;
u32 data_len;
u8 data[QMI_WLFW_MAX_DATA_SIZE_V01];
u8 end_valid;
u8 end;
};
#define WLFW_CAL_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6178
extern struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[];
struct wlfw_cal_download_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_CAL_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_cal_download_resp_msg_v01_ei[];
struct wlfw_initiate_cal_update_ind_msg_v01 {
enum wlfw_cal_temp_id_enum_v01 cal_id;
u32 total_size;
};
#define WLFW_INITIATE_CAL_UPDATE_IND_MSG_V01_MAX_MSG_LEN 14
extern struct qmi_elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[];
struct wlfw_cal_update_req_msg_v01 {
enum wlfw_cal_temp_id_enum_v01 cal_id;
u32 seg_id;
};
#define WLFW_CAL_UPDATE_REQ_MSG_V01_MAX_MSG_LEN 14
extern struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[];
struct wlfw_cal_update_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u8 file_id_valid;
enum wlfw_cal_temp_id_enum_v01 file_id;
u8 total_size_valid;
u32 total_size;
u8 seg_id_valid;
u32 seg_id;
u8 data_valid;
u32 data_len;
u8 data[QMI_WLFW_MAX_DATA_SIZE_V01];
u8 end_valid;
u8 end;
};
#define WLFW_CAL_UPDATE_RESP_MSG_V01_MAX_MSG_LEN 6181
extern struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[];
struct wlfw_msa_info_req_msg_v01 {
u64 msa_addr;
u32 size;
};
#define WLFW_MSA_INFO_REQ_MSG_V01_MAX_MSG_LEN 18
extern struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[];
struct wlfw_msa_info_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u32 mem_region_info_len;
struct wlfw_memory_region_info_s_v01 mem_region_info[QMI_WLFW_MAX_MEM_REG_V01];
};
#define WLFW_MSA_INFO_RESP_MSG_V01_MAX_MSG_LEN 37
extern struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[];
struct wlfw_msa_ready_req_msg_v01 {
char placeholder;
};
#define WLFW_MSA_READY_REQ_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_msa_ready_req_msg_v01_ei[];
struct wlfw_msa_ready_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_MSA_READY_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_msa_ready_resp_msg_v01_ei[];
struct wlfw_ini_req_msg_v01 {
u8 enablefwlog_valid;
u8 enablefwlog;
};
#define WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN 4
extern struct qmi_elem_info wlfw_ini_req_msg_v01_ei[];
struct wlfw_ini_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_INI_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_ini_resp_msg_v01_ei[];
struct wlfw_athdiag_read_req_msg_v01 {
u32 offset;
u32 mem_type;
u32 data_len;
};
#define WLFW_ATHDIAG_READ_REQ_MSG_V01_MAX_MSG_LEN 21
extern struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[];
struct wlfw_athdiag_read_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u8 data_valid;
u32 data_len;
u8 data[QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01];
};
#define WLFW_ATHDIAG_READ_RESP_MSG_V01_MAX_MSG_LEN 6156
extern struct qmi_elem_info wlfw_athdiag_read_resp_msg_v01_ei[];
struct wlfw_athdiag_write_req_msg_v01 {
u32 offset;
u32 mem_type;
u32 data_len;
u8 data[QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01];
};
#define WLFW_ATHDIAG_WRITE_REQ_MSG_V01_MAX_MSG_LEN 6163
extern struct qmi_elem_info wlfw_athdiag_write_req_msg_v01_ei[];
struct wlfw_athdiag_write_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_ATHDIAG_WRITE_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_athdiag_write_resp_msg_v01_ei[];
struct wlfw_vbatt_req_msg_v01 {
u64 voltage_uv;
};
#define WLFW_VBATT_REQ_MSG_V01_MAX_MSG_LEN 11
extern struct qmi_elem_info wlfw_vbatt_req_msg_v01_ei[];
struct wlfw_vbatt_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_VBATT_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_vbatt_resp_msg_v01_ei[];
struct wlfw_mac_addr_req_msg_v01 {
u8 mac_addr_valid;
u8 mac_addr[QMI_WLFW_MAC_ADDR_SIZE_V01];
};
#define WLFW_MAC_ADDR_REQ_MSG_V01_MAX_MSG_LEN 9
extern struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[];
struct wlfw_mac_addr_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_MAC_ADDR_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[];
struct wlfw_host_cap_req_msg_v01 {
u8 daemon_support_valid;
u8 daemon_support;
};
#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 4
extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[];
struct wlfw_host_cap_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_HOST_CAP_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[];
struct wlfw_request_mem_ind_msg_v01 {
u32 mem_seg_len;
struct wlfw_mem_seg_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
};
#define WLFW_REQUEST_MEM_IND_MSG_V01_MAX_MSG_LEN 564
extern struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[];
struct wlfw_respond_mem_req_msg_v01 {
u32 mem_seg_len;
struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
};
#define WLFW_RESPOND_MEM_REQ_MSG_V01_MAX_MSG_LEN 260
extern struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[];
struct wlfw_respond_mem_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_RESPOND_MEM_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[];
struct wlfw_mem_ready_ind_msg_v01 {
char placeholder;
};
#define WLFW_MEM_READY_IND_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_mem_ready_ind_msg_v01_ei[];
struct wlfw_fw_init_done_ind_msg_v01 {
char placeholder;
};
#define WLFW_FW_INIT_DONE_IND_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[];
struct wlfw_rejuvenate_ind_msg_v01 {
u8 cause_for_rejuvenation_valid;
u8 cause_for_rejuvenation;
u8 requesting_sub_system_valid;
u8 requesting_sub_system;
u8 line_number_valid;
u16 line_number;
u8 function_name_valid;
char function_name[QMI_WLFW_FUNCTION_NAME_LEN_V01 + 1];
};
#define WLFW_REJUVENATE_IND_MSG_V01_MAX_MSG_LEN 144
extern struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[];
struct wlfw_rejuvenate_ack_req_msg_v01 {
char placeholder;
};
#define WLFW_REJUVENATE_ACK_REQ_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_rejuvenate_ack_req_msg_v01_ei[];
struct wlfw_rejuvenate_ack_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_REJUVENATE_ACK_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_rejuvenate_ack_resp_msg_v01_ei[];
struct wlfw_dynamic_feature_mask_req_msg_v01 {
u8 mask_valid;
u64 mask;
};
#define WLFW_DYNAMIC_FEATURE_MASK_REQ_MSG_V01_MAX_MSG_LEN 11
extern struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[];
struct wlfw_dynamic_feature_mask_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u8 prev_mask_valid;
u64 prev_mask;
u8 curr_mask_valid;
u64 curr_mask;
};
#define WLFW_DYNAMIC_FEATURE_MASK_RESP_MSG_V01_MAX_MSG_LEN 29
extern struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[];
struct wlfw_m3_info_req_msg_v01 {
u64 addr;
u32 size;
};
#define WLFW_M3_INFO_REQ_MSG_V01_MAX_MSG_LEN 18
extern struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[];
struct wlfw_m3_info_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_M3_INFO_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_m3_info_resp_msg_v01_ei[];
struct wlfw_xo_cal_ind_msg_v01 {
u8 xo_cal_data;
};
#define WLFW_XO_CAL_IND_MSG_V01_MAX_MSG_LEN 4
extern struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[];
#endif

View File

@ -67,6 +67,72 @@ static void ath10k_snoc_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state);
static const struct ath10k_snoc_drv_priv drv_priv = { static const struct ath10k_snoc_drv_priv drv_priv = {
.hw_rev = ATH10K_HW_WCN3990, .hw_rev = ATH10K_HW_WCN3990,
.dma_mask = DMA_BIT_MASK(37), .dma_mask = DMA_BIT_MASK(37),
.msa_size = 0x100000,
};
#define WCN3990_SRC_WR_IDX_OFFSET 0x3C
#define WCN3990_DST_WR_IDX_OFFSET 0x40
static struct ath10k_shadow_reg_cfg target_shadow_reg_cfg_map[] = {
{
.ce_id = __cpu_to_le16(0),
.reg_offset = __cpu_to_le16(WCN3990_SRC_WR_IDX_OFFSET),
},
{
.ce_id = __cpu_to_le16(3),
.reg_offset = __cpu_to_le16(WCN3990_SRC_WR_IDX_OFFSET),
},
{
.ce_id = __cpu_to_le16(4),
.reg_offset = __cpu_to_le16(WCN3990_SRC_WR_IDX_OFFSET),
},
{
.ce_id = __cpu_to_le16(5),
.reg_offset = __cpu_to_le16(WCN3990_SRC_WR_IDX_OFFSET),
},
{
.ce_id = __cpu_to_le16(7),
.reg_offset = __cpu_to_le16(WCN3990_SRC_WR_IDX_OFFSET),
},
{
.ce_id = __cpu_to_le16(1),
.reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),
},
{
.ce_id = __cpu_to_le16(2),
.reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),
},
{
.ce_id = __cpu_to_le16(7),
.reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),
},
{
.ce_id = __cpu_to_le16(8),
.reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),
},
{
.ce_id = __cpu_to_le16(9),
.reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),
},
{
.ce_id = __cpu_to_le16(10),
.reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),
},
{
.ce_id = __cpu_to_le16(11),
.reg_offset = __cpu_to_le16(WCN3990_DST_WR_IDX_OFFSET),
},
}; };
static struct ce_attr host_ce_config_wlan[] = { static struct ce_attr host_ce_config_wlan[] = {
@ -176,6 +242,128 @@ static struct ce_attr host_ce_config_wlan[] = {
}, },
}; };
static struct ce_pipe_config target_ce_config_wlan[] = {
/* CE0: host->target HTC control and raw streams */
{
.pipenum = __cpu_to_le32(0),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE1: target->host HTT + HTC control */
{
.pipenum = __cpu_to_le32(1),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE2: target->host WMI */
{
.pipenum = __cpu_to_le32(2),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(64),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE3: host->target WMI */
{
.pipenum = __cpu_to_le32(3),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE4: host->target HTT */
{
.pipenum = __cpu_to_le32(4),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(256),
.nbytes_max = __cpu_to_le32(256),
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
.reserved = __cpu_to_le32(0),
},
/* CE5: target->host HTT (HIF->HTT) */
{
.pipenum = __cpu_to_le32(5),
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
.nentries = __cpu_to_le32(1024),
.nbytes_max = __cpu_to_le32(64),
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
.reserved = __cpu_to_le32(0),
},
/* CE6: Reserved for target autonomous hif_memcpy */
{
.pipenum = __cpu_to_le32(6),
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(16384),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE7 used only by Host */
{
.pipenum = __cpu_to_le32(7),
.pipedir = __cpu_to_le32(4),
.nentries = __cpu_to_le32(0),
.nbytes_max = __cpu_to_le32(0),
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
.reserved = __cpu_to_le32(0),
},
/* CE8 Target to uMC */
{
.pipenum = __cpu_to_le32(8),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(0),
.reserved = __cpu_to_le32(0),
},
/* CE9 target->host HTT */
{
.pipenum = __cpu_to_le32(9),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE10 target->host HTT */
{
.pipenum = __cpu_to_le32(10),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
/* CE11 target autonomous qcache memcpy */
{
.pipenum = __cpu_to_le32(11),
.pipedir = __cpu_to_le32(PIPEDIR_IN),
.nentries = __cpu_to_le32(32),
.nbytes_max = __cpu_to_le32(2048),
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
.reserved = __cpu_to_le32(0),
},
};
static struct service_to_pipe target_service_to_ce_map_wlan[] = { static struct service_to_pipe target_service_to_ce_map_wlan[] = {
{ {
__cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VO), __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VO),
@ -766,11 +954,47 @@ static int ath10k_snoc_init_pipes(struct ath10k *ar)
static int ath10k_snoc_wlan_enable(struct ath10k *ar) static int ath10k_snoc_wlan_enable(struct ath10k *ar)
{ {
return 0; struct ath10k_tgt_pipe_cfg tgt_cfg[CE_COUNT_MAX];
struct ath10k_qmi_wlan_enable_cfg cfg;
enum wlfw_driver_mode_enum_v01 mode;
int pipe_num;
for (pipe_num = 0; pipe_num < CE_COUNT_MAX; pipe_num++) {
tgt_cfg[pipe_num].pipe_num =
target_ce_config_wlan[pipe_num].pipenum;
tgt_cfg[pipe_num].pipe_dir =
target_ce_config_wlan[pipe_num].pipedir;
tgt_cfg[pipe_num].nentries =
target_ce_config_wlan[pipe_num].nentries;
tgt_cfg[pipe_num].nbytes_max =
target_ce_config_wlan[pipe_num].nbytes_max;
tgt_cfg[pipe_num].flags =
target_ce_config_wlan[pipe_num].flags;
tgt_cfg[pipe_num].reserved = 0;
}
cfg.num_ce_tgt_cfg = sizeof(target_ce_config_wlan) /
sizeof(struct ath10k_tgt_pipe_cfg);
cfg.ce_tgt_cfg = (struct ath10k_tgt_pipe_cfg *)
&tgt_cfg;
cfg.num_ce_svc_pipe_cfg = sizeof(target_service_to_ce_map_wlan) /
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.shadow_reg_cfg = (struct ath10k_shadow_reg_cfg *)
&target_shadow_reg_cfg_map;
mode = QMI_WLFW_MISSION_V01;
return ath10k_qmi_wlan_enable(ar, &cfg, mode,
NULL);
} }
static void ath10k_snoc_wlan_disable(struct ath10k *ar) static void ath10k_snoc_wlan_disable(struct ath10k *ar)
{ {
ath10k_qmi_wlan_disable(ar);
} }
static void ath10k_snoc_hif_power_down(struct ath10k *ar) static void ath10k_snoc_hif_power_down(struct ath10k *ar)
@ -957,6 +1181,32 @@ static int ath10k_snoc_resource_init(struct ath10k *ar)
return ret; return ret;
} }
int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type)
{
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
struct ath10k_bus_params bus_params;
int ret;
switch (type) {
case ATH10K_QMI_EVENT_FW_READY_IND:
bus_params.dev_type = ATH10K_DEV_TYPE_LL;
bus_params.chip_id = ar_snoc->target_info.soc_version;
ret = ath10k_core_register(ar, &bus_params);
if (ret) {
ath10k_err(ar, "failed to register driver core: %d\n",
ret);
}
break;
case ATH10K_QMI_EVENT_FW_DOWN_IND:
break;
default:
ath10k_err(ar, "invalid fw indication: %llx\n", type);
return -EINVAL;
}
return 0;
}
static int ath10k_snoc_setup_resource(struct ath10k *ar) static int ath10k_snoc_setup_resource(struct ath10k *ar)
{ {
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
@ -1281,9 +1531,9 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
struct ath10k_snoc *ar_snoc; struct ath10k_snoc *ar_snoc;
struct device *dev; struct device *dev;
struct ath10k *ar; struct ath10k *ar;
u32 msa_size;
int ret; int ret;
u32 i; u32 i;
struct ath10k_bus_params bus_params;
of_id = of_match_device(ath10k_snoc_dt_match, &pdev->dev); of_id = of_match_device(ath10k_snoc_dt_match, &pdev->dev);
if (!of_id) { if (!of_id) {
@ -1313,6 +1563,7 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
ar_snoc->ar = ar; ar_snoc->ar = ar;
ar_snoc->ce.bus_ops = &ath10k_snoc_bus_ops; ar_snoc->ce.bus_ops = &ath10k_snoc_bus_ops;
ar->ce_priv = &ar_snoc->ce; ar->ce_priv = &ar_snoc->ce;
msa_size = drv_data->msa_size;
ret = ath10k_snoc_resource_init(ar); ret = ath10k_snoc_resource_init(ar);
if (ret) { if (ret) {
@ -1351,12 +1602,10 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
goto err_free_irq; goto err_free_irq;
} }
bus_params.dev_type = ATH10K_DEV_TYPE_LL; ret = ath10k_qmi_init(ar, msa_size);
bus_params.chip_id = drv_data->hw_rev;
ret = ath10k_core_register(ar, &bus_params);
if (ret) { if (ret) {
ath10k_err(ar, "failed to register driver core: %d\n", ret); ath10k_warn(ar, "failed to register wlfw qmi client: %d\n", ret);
goto err_hw_power_off; goto err_core_destroy;
} }
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc probe\n"); ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc probe\n");
@ -1364,9 +1613,6 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
return 0; return 0;
err_hw_power_off:
ath10k_hw_power_off(ar);
err_free_irq: err_free_irq:
ath10k_snoc_free_irq(ar); ath10k_snoc_free_irq(ar);
@ -1388,6 +1634,7 @@ static int ath10k_snoc_remove(struct platform_device *pdev)
ath10k_hw_power_off(ar); ath10k_hw_power_off(ar);
ath10k_snoc_free_irq(ar); ath10k_snoc_free_irq(ar);
ath10k_snoc_release_resource(ar); ath10k_snoc_release_resource(ar);
ath10k_qmi_deinit(ar);
ath10k_core_destroy(ar); ath10k_core_destroy(ar);
return 0; return 0;

View File

@ -19,10 +19,12 @@
#include "hw.h" #include "hw.h"
#include "ce.h" #include "ce.h"
#include "qmi.h"
struct ath10k_snoc_drv_priv { struct ath10k_snoc_drv_priv {
enum ath10k_hw_rev hw_rev; enum ath10k_hw_rev hw_rev;
u64 dma_mask; u64 dma_mask;
u32 msa_size;
}; };
struct snoc_state { struct snoc_state {
@ -81,6 +83,7 @@ struct ath10k_snoc {
struct timer_list rx_post_retry; struct timer_list rx_post_retry;
struct ath10k_wcn3990_vreg_info *vreg; struct ath10k_wcn3990_vreg_info *vreg;
struct ath10k_wcn3990_clk_info *clk; struct ath10k_wcn3990_clk_info *clk;
struct ath10k_qmi *qmi;
}; };
static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar) static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
@ -90,5 +93,6 @@ static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
void ath10k_snoc_write32(struct ath10k *ar, u32 offset, u32 value); void ath10k_snoc_write32(struct ath10k *ar, u32 offset, u32 value);
u32 ath10k_snoc_read32(struct ath10k *ar, u32 offset); u32 ath10k_snoc_read32(struct ath10k *ar, u32 offset);
int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type);
#endif /* _SNOC_H_ */ #endif /* _SNOC_H_ */

View File

@ -210,6 +210,9 @@ struct wmi_ops {
u32 fw_feature_bitmap); u32 fw_feature_bitmap);
int (*get_vdev_subtype)(struct ath10k *ar, int (*get_vdev_subtype)(struct ath10k *ar,
enum wmi_vdev_subtype subtype); enum wmi_vdev_subtype subtype);
struct sk_buff *(*gen_wow_config_pno)(struct ath10k *ar,
u32 vdev_id,
struct wmi_pno_scan_req *pno_scan);
struct sk_buff *(*gen_pdev_bss_chan_info_req) struct sk_buff *(*gen_pdev_bss_chan_info_req)
(struct ath10k *ar, (struct ath10k *ar,
enum wmi_bss_survey_req_type type); enum wmi_bss_survey_req_type type);
@ -1360,6 +1363,24 @@ ath10k_wmi_wow_del_pattern(struct ath10k *ar, u32 vdev_id, u32 pattern_id)
return ath10k_wmi_cmd_send(ar, skb, cmd_id); return ath10k_wmi_cmd_send(ar, skb, cmd_id);
} }
static inline int
ath10k_wmi_wow_config_pno(struct ath10k *ar, u32 vdev_id,
struct wmi_pno_scan_req *pno_scan)
{
struct sk_buff *skb;
u32 cmd_id;
if (!ar->wmi.ops->gen_wow_config_pno)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_wow_config_pno(ar, vdev_id, pno_scan);
if (IS_ERR(skb))
return PTR_ERR(skb);
cmd_id = ar->wmi.cmd->network_list_offload_config_cmdid;
return ath10k_wmi_cmd_send(ar, skb, cmd_id);
}
static inline int static inline int
ath10k_wmi_update_fw_tdls_state(struct ath10k *ar, u32 vdev_id, ath10k_wmi_update_fw_tdls_state(struct ath10k *ar, u32 vdev_id,
enum wmi_tdls_state state) enum wmi_tdls_state state)

View File

@ -3441,6 +3441,192 @@ ath10k_wmi_tlv_op_gen_wow_del_pattern(struct ath10k *ar, u32 vdev_id,
return skb; return skb;
} }
/* Request FW to start PNO operation */
static struct sk_buff *
ath10k_wmi_tlv_op_gen_config_pno_start(struct ath10k *ar,
u32 vdev_id,
struct wmi_pno_scan_req *pno)
{
struct nlo_configured_parameters *nlo_list;
struct wmi_tlv_wow_nlo_config_cmd *cmd;
struct wmi_tlv *tlv;
struct sk_buff *skb;
__le32 *channel_list;
u16 tlv_len;
size_t len;
void *ptr;
u32 i;
len = sizeof(*tlv) + sizeof(*cmd) +
sizeof(*tlv) +
/* TLV place holder for array of structures
* nlo_configured_parameters(nlo_list)
*/
sizeof(*tlv);
/* TLV place holder for array of uint32 channel_list */
len += sizeof(u32) * min_t(u8, pno->a_networks[0].channel_count,
WMI_NLO_MAX_CHAN);
len += sizeof(struct nlo_configured_parameters) *
min_t(u8, pno->uc_networks_count, WMI_NLO_MAX_SSIDS);
skb = ath10k_wmi_alloc_skb(ar, len);
if (!skb)
return ERR_PTR(-ENOMEM);
ptr = (void *)skb->data;
tlv = ptr;
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD);
tlv->len = __cpu_to_le16(sizeof(*cmd));
cmd = (void *)tlv->value;
/* wmi_tlv_wow_nlo_config_cmd parameters*/
cmd->vdev_id = __cpu_to_le32(pno->vdev_id);
cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_START | WMI_NLO_CONFIG_SSID_HIDE_EN);
/* current FW does not support min-max range for dwell time */
cmd->active_dwell_time = __cpu_to_le32(pno->active_max_time);
cmd->passive_dwell_time = __cpu_to_le32(pno->passive_max_time);
if (pno->do_passive_scan)
cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SCAN_PASSIVE);
/* copy scan interval */
cmd->fast_scan_period = __cpu_to_le32(pno->fast_scan_period);
cmd->slow_scan_period = __cpu_to_le32(pno->slow_scan_period);
cmd->fast_scan_max_cycles = __cpu_to_le32(pno->fast_scan_max_cycles);
cmd->delay_start_time = __cpu_to_le32(pno->delay_start_time);
if (pno->enable_pno_scan_randomization) {
cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ |
WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ);
ether_addr_copy(cmd->mac_addr.addr, pno->mac_addr);
ether_addr_copy(cmd->mac_mask.addr, pno->mac_addr_mask);
}
ptr += sizeof(*tlv);
ptr += sizeof(*cmd);
/* nlo_configured_parameters(nlo_list) */
cmd->no_of_ssids = __cpu_to_le32(min_t(u8, pno->uc_networks_count,
WMI_NLO_MAX_SSIDS));
tlv_len = __le32_to_cpu(cmd->no_of_ssids) *
sizeof(struct nlo_configured_parameters);
tlv = ptr;
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
tlv->len = __cpu_to_le16(len);
ptr += sizeof(*tlv);
nlo_list = ptr;
for (i = 0; i < __le32_to_cpu(cmd->no_of_ssids); i++) {
tlv = (struct wmi_tlv *)(&nlo_list[i].tlv_header);
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
tlv->len = __cpu_to_le16(sizeof(struct nlo_configured_parameters) -
sizeof(*tlv));
/* copy ssid and it's length */
nlo_list[i].ssid.valid = __cpu_to_le32(true);
nlo_list[i].ssid.ssid.ssid_len = pno->a_networks[i].ssid.ssid_len;
memcpy(nlo_list[i].ssid.ssid.ssid,
pno->a_networks[i].ssid.ssid,
__le32_to_cpu(nlo_list[i].ssid.ssid.ssid_len));
/* copy rssi threshold */
if (pno->a_networks[i].rssi_threshold &&
pno->a_networks[i].rssi_threshold > -300) {
nlo_list[i].rssi_cond.valid = __cpu_to_le32(true);
nlo_list[i].rssi_cond.rssi =
__cpu_to_le32(pno->a_networks[i].rssi_threshold);
}
nlo_list[i].bcast_nw_type.valid = __cpu_to_le32(true);
nlo_list[i].bcast_nw_type.bcast_nw_type =
__cpu_to_le32(pno->a_networks[i].bcast_nw_type);
}
ptr += __le32_to_cpu(cmd->no_of_ssids) * sizeof(struct nlo_configured_parameters);
/* copy channel info */
cmd->num_of_channels = __cpu_to_le32(min_t(u8,
pno->a_networks[0].channel_count,
WMI_NLO_MAX_CHAN));
tlv = ptr;
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
tlv->len = __cpu_to_le16(__le32_to_cpu(cmd->num_of_channels) *
sizeof(u_int32_t));
ptr += sizeof(*tlv);
channel_list = (__le32 *)ptr;
for (i = 0; i < __le32_to_cpu(cmd->num_of_channels); i++)
channel_list[i] = __cpu_to_le32(pno->a_networks[0].channels[i]);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start pno config vdev_id %d\n",
vdev_id);
return skb;
}
/* Request FW to stop ongoing PNO operation */
static struct sk_buff *ath10k_wmi_tlv_op_gen_config_pno_stop(struct ath10k *ar,
u32 vdev_id)
{
struct wmi_tlv_wow_nlo_config_cmd *cmd;
struct wmi_tlv *tlv;
struct sk_buff *skb;
void *ptr;
size_t len;
len = sizeof(*tlv) + sizeof(*cmd) +
sizeof(*tlv) +
/* TLV place holder for array of structures
* nlo_configured_parameters(nlo_list)
*/
sizeof(*tlv);
/* TLV place holder for array of uint32 channel_list */
skb = ath10k_wmi_alloc_skb(ar, len);
if (!skb)
return ERR_PTR(-ENOMEM);
ptr = (void *)skb->data;
tlv = ptr;
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD);
tlv->len = __cpu_to_le16(sizeof(*cmd));
cmd = (void *)tlv->value;
cmd->vdev_id = __cpu_to_le32(vdev_id);
cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_STOP);
ptr += sizeof(*tlv);
ptr += sizeof(*cmd);
/* nlo_configured_parameters(nlo_list) */
tlv = ptr;
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
tlv->len = __cpu_to_le16(0);
ptr += sizeof(*tlv);
/* channel list */
tlv = ptr;
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
tlv->len = __cpu_to_le16(0);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop pno config vdev_id %d\n", vdev_id);
return skb;
}
static struct sk_buff *
ath10k_wmi_tlv_op_gen_config_pno(struct ath10k *ar, u32 vdev_id,
struct wmi_pno_scan_req *pno_scan)
{
if (pno_scan->enable)
return ath10k_wmi_tlv_op_gen_config_pno_start(ar, vdev_id, pno_scan);
else
return ath10k_wmi_tlv_op_gen_config_pno_stop(ar, vdev_id);
}
static struct sk_buff * static struct sk_buff *
ath10k_wmi_tlv_op_gen_adaptive_qcs(struct ath10k *ar, bool enable) ath10k_wmi_tlv_op_gen_adaptive_qcs(struct ath10k *ar, bool enable)
{ {
@ -3973,6 +4159,7 @@ static const struct wmi_ops wmi_tlv_ops = {
.gen_wow_host_wakeup_ind = ath10k_wmi_tlv_gen_wow_host_wakeup_ind, .gen_wow_host_wakeup_ind = ath10k_wmi_tlv_gen_wow_host_wakeup_ind,
.gen_wow_add_pattern = ath10k_wmi_tlv_op_gen_wow_add_pattern, .gen_wow_add_pattern = ath10k_wmi_tlv_op_gen_wow_add_pattern,
.gen_wow_del_pattern = ath10k_wmi_tlv_op_gen_wow_del_pattern, .gen_wow_del_pattern = ath10k_wmi_tlv_op_gen_wow_del_pattern,
.gen_wow_config_pno = ath10k_wmi_tlv_op_gen_config_pno,
.gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state, .gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state,
.gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update, .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update,
.gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs, .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs,

View File

@ -2146,6 +2146,260 @@ struct wmi_tlv_tdls_peer_event {
void ath10k_wmi_tlv_attach(struct ath10k *ar); void ath10k_wmi_tlv_attach(struct ath10k *ar);
enum wmi_nlo_auth_algorithm {
WMI_NLO_AUTH_ALGO_80211_OPEN = 1,
WMI_NLO_AUTH_ALGO_80211_SHARED_KEY = 2,
WMI_NLO_AUTH_ALGO_WPA = 3,
WMI_NLO_AUTH_ALGO_WPA_PSK = 4,
WMI_NLO_AUTH_ALGO_WPA_NONE = 5,
WMI_NLO_AUTH_ALGO_RSNA = 6,
WMI_NLO_AUTH_ALGO_RSNA_PSK = 7,
};
enum wmi_nlo_cipher_algorithm {
WMI_NLO_CIPHER_ALGO_NONE = 0x00,
WMI_NLO_CIPHER_ALGO_WEP40 = 0x01,
WMI_NLO_CIPHER_ALGO_TKIP = 0x02,
WMI_NLO_CIPHER_ALGO_CCMP = 0x04,
WMI_NLO_CIPHER_ALGO_WEP104 = 0x05,
WMI_NLO_CIPHER_ALGO_BIP = 0x06,
WMI_NLO_CIPHER_ALGO_RSN_USE_GROUP = 0x100,
WMI_NLO_CIPHER_ALGO_WEP = 0x101,
};
/* SSID broadcast type passed in NLO params */
enum wmi_nlo_ssid_bcastnwtype {
WMI_NLO_BCAST_UNKNOWN = 0,
WMI_NLO_BCAST_NORMAL = 1,
WMI_NLO_BCAST_HIDDEN = 2,
};
#define WMI_NLO_MAX_SSIDS 16
#define WMI_NLO_MAX_CHAN 48
#define WMI_NLO_CONFIG_STOP (0x1 << 0)
#define WMI_NLO_CONFIG_START (0x1 << 1)
#define WMI_NLO_CONFIG_RESET (0x1 << 2)
#define WMI_NLO_CONFIG_SLOW_SCAN (0x1 << 4)
#define WMI_NLO_CONFIG_FAST_SCAN (0x1 << 5)
#define WMI_NLO_CONFIG_SSID_HIDE_EN (0x1 << 6)
/* This bit is used to indicate if EPNO or supplicant PNO is enabled.
* Only one of them can be enabled at a given time
*/
#define WMI_NLO_CONFIG_ENLO (0x1 << 7)
#define WMI_NLO_CONFIG_SCAN_PASSIVE (0x1 << 8)
#define WMI_NLO_CONFIG_ENLO_RESET (0x1 << 9)
#define WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ (0x1 << 10)
#define WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ (0x1 << 11)
#define WMI_NLO_CONFIG_ENABLE_IE_WHITELIST_IN_PROBE_REQ (0x1 << 12)
#define WMI_NLO_CONFIG_ENABLE_CNLO_RSSI_CONFIG (0x1 << 13)
/* Whether directed scan needs to be performed (for hidden SSIDs) */
#define WMI_ENLO_FLAG_DIRECTED_SCAN 1
/* Whether PNO event shall be triggered if the network is found on A band */
#define WMI_ENLO_FLAG_A_BAND 2
/* Whether PNO event shall be triggered if the network is found on G band */
#define WMI_ENLO_FLAG_G_BAND 4
/* Whether strict matching is required (i.e. firmware shall not
* match on the entire SSID)
*/
#define WMI_ENLO_FLAG_STRICT_MATCH 8
/* Code for matching the beacon AUTH IE - additional codes TBD */
/* open */
#define WMI_ENLO_AUTH_CODE_OPEN 1
/* WPA_PSK or WPA2PSK */
#define WMI_ENLO_AUTH_CODE_PSK 2
/* any EAPOL */
#define WMI_ENLO_AUTH_CODE_EAPOL 4
struct wmi_nlo_ssid_param {
__le32 valid;
struct wmi_ssid ssid;
} __packed;
struct wmi_nlo_enc_param {
__le32 valid;
__le32 enc_type;
} __packed;
struct wmi_nlo_auth_param {
__le32 valid;
__le32 auth_type;
} __packed;
struct wmi_nlo_bcast_nw_param {
__le32 valid;
/* If WMI_NLO_CONFIG_EPNO is not set. Supplicant PNO is enabled.
* The value should be true/false. Otherwise EPNO is enabled.
* bcast_nw_type would be used as a bit flag contains WMI_ENLO_FLAG_XXX
*/
__le32 bcast_nw_type;
} __packed;
struct wmi_nlo_rssi_param {
__le32 valid;
__le32 rssi;
} __packed;
struct nlo_configured_parameters {
/* TLV tag and len;*/
__le32 tlv_header;
struct wmi_nlo_ssid_param ssid;
struct wmi_nlo_enc_param enc_type;
struct wmi_nlo_auth_param auth_type;
struct wmi_nlo_rssi_param rssi_cond;
/* indicates if the SSID is hidden or not */
struct wmi_nlo_bcast_nw_param bcast_nw_type;
} __packed;
/* Support channel prediction for PNO scan after scanning top_k_num channels
* if stationary_threshold is met.
*/
struct nlo_channel_prediction_cfg {
__le32 tlv_header;
/* Enable or disable this feature. */
__le32 enable;
/* Top K channels will be scanned before deciding whether to further scan
* or stop. Minimum value is 3 and maximum is 5.
*/
__le32 top_k_num;
/* Preconfigured stationary threshold.
* Lesser value means more conservative. Bigger value means more aggressive.
* Maximum is 100 and mininum is 0.
*/
__le32 stationary_threshold;
/* Periodic full channel scan in milliseconds unit.
* After full_scan_period_ms since last full scan, channel prediction
* scan is suppressed and will do full scan.
* This is to help detecting sudden AP power-on or -off. Value 0 means no
* full scan at all (not recommended).
*/
__le32 full_scan_period_ms;
} __packed;
struct enlo_candidate_score_params_t {
__le32 tlv_header; /* TLV tag and len; */
/* minimum 5GHz RSSI for a BSSID to be considered (units = dBm) */
__le32 min_5ghz_rssi;
/* minimum 2.4GHz RSSI for a BSSID to be considered (units = dBm) */
__le32 min_24ghz_rssi;
/* the maximum score that a network can have before bonuses */
__le32 initial_score_max;
/* current_connection_bonus:
* only report when there is a network's score this much higher
* than the current connection
*/
__le32 current_connection_bonus;
/* score bonus for all networks with the same network flag */
__le32 same_network_bonus;
/* score bonus for networks that are not open */
__le32 secure_bonus;
/* 5GHz RSSI score bonus (applied to all 5GHz networks) */
__le32 band_5ghz_bonus;
} __packed;
struct connected_nlo_bss_band_rssi_pref_t {
__le32 tlv_header; /* TLV tag and len;*/
/* band which needs to get preference over other band
* - see wmi_set_vdev_ie_band enum
*/
__le32 band;
/* Amount of RSSI preference (in dB) that can be given to a band */
__le32 rssi_pref;
} __packed;
struct connected_nlo_rssi_params_t {
__le32 tlv_header; /* TLV tag and len;*/
/* Relative rssi threshold (in dB) by which new BSS should have
* better rssi than the current connected BSS.
*/
__le32 relative_rssi;
/* The amount of rssi preference (in dB) that can be given
* to a 5G BSS over 2.4G BSS.
*/
__le32 relative_rssi_5g_pref;
} __packed;
struct wmi_tlv_wow_nlo_config_cmd {
__le32 flags;
__le32 vdev_id;
__le32 fast_scan_max_cycles;
__le32 active_dwell_time;
__le32 passive_dwell_time; /* PDT in msecs */
__le32 probe_bundle_size;
/* ART = IRT */
__le32 rest_time;
/* Max value that can be reached after SBM */
__le32 max_rest_time;
/* SBM */
__le32 scan_backoff_multiplier;
/* SCBM */
__le32 fast_scan_period;
/* specific to windows */
__le32 slow_scan_period;
__le32 no_of_ssids;
__le32 num_of_channels;
/* NLO scan start delay time in milliseconds */
__le32 delay_start_time;
/** MAC Address to use in Probe Req as SA **/
struct wmi_mac_addr mac_addr;
/** Mask on which MAC has to be randomized **/
struct wmi_mac_addr mac_mask;
/** IE bitmap to use in Probe Req **/
__le32 ie_bitmap[8];
/** Number of vendor OUIs. In the TLV vendor_oui[] **/
__le32 num_vendor_oui;
/** Number of connected NLO band preferences **/
__le32 num_cnlo_band_pref;
/* The TLVs will follow.
* nlo_configured_parameters nlo_list[];
* A_UINT32 channel_list[num_of_channels];
* nlo_channel_prediction_cfg ch_prediction_cfg;
* enlo_candidate_score_params candidate_score_params;
* wmi_vendor_oui vendor_oui[num_vendor_oui];
* connected_nlo_rssi_params cnlo_rssi_params;
* connected_nlo_bss_band_rssi_pref cnlo_bss_band_rssi_pref[num_cnlo_band_pref];
*/
} __packed;
struct wmi_tlv_mgmt_tx_cmd { struct wmi_tlv_mgmt_tx_cmd {
__le32 vdev_id; __le32 vdev_id;
__le32 desc_id; __le32 desc_id;

View File

@ -7068,6 +7068,63 @@ struct wmi_pdev_set_adaptive_cca_params {
__le32 cca_detect_margin; __le32 cca_detect_margin;
} __packed; } __packed;
#define WMI_PNO_MAX_SCHED_SCAN_PLANS 2
#define WMI_PNO_MAX_SCHED_SCAN_PLAN_INT 7200
#define WMI_PNO_MAX_SCHED_SCAN_PLAN_ITRNS 100
#define WMI_PNO_MAX_NETW_CHANNELS 26
#define WMI_PNO_MAX_NETW_CHANNELS_EX 60
#define WMI_PNO_MAX_SUPP_NETWORKS WLAN_SCAN_PARAMS_MAX_SSID
#define WMI_PNO_MAX_IE_LENGTH WLAN_SCAN_PARAMS_MAX_IE_LEN
/*size based of dot11 declaration without extra IEs as we will not carry those for PNO*/
#define WMI_PNO_MAX_PB_REQ_SIZE 450
#define WMI_PNO_24G_DEFAULT_CH 1
#define WMI_PNO_5G_DEFAULT_CH 36
#define WMI_ACTIVE_MAX_CHANNEL_TIME 40
#define WMI_PASSIVE_MAX_CHANNEL_TIME 110
/* SSID broadcast type */
enum wmi_SSID_bcast_type {
BCAST_UNKNOWN = 0,
BCAST_NORMAL = 1,
BCAST_HIDDEN = 2,
};
struct wmi_network_type {
struct wmi_ssid ssid;
u32 authentication;
u32 encryption;
u32 bcast_nw_type;
u8 channel_count;
u16 channels[WMI_PNO_MAX_NETW_CHANNELS_EX];
s32 rssi_threshold;
} __packed;
struct wmi_pno_scan_req {
u8 enable;
u8 vdev_id;
u8 uc_networks_count;
struct wmi_network_type a_networks[WMI_PNO_MAX_SUPP_NETWORKS];
u32 fast_scan_period;
u32 slow_scan_period;
u8 fast_scan_max_cycles;
bool do_passive_scan;
u32 delay_start_time;
u32 active_min_time;
u32 active_max_time;
u32 passive_min_time;
u32 passive_max_time;
/* mac address randomization attributes */
u32 enable_pno_scan_randomization;
u8 mac_addr[ETH_ALEN];
u8 mac_addr_mask[ETH_ALEN];
} __packed;
enum wmi_host_platform_type { enum wmi_host_platform_type {
WMI_HOST_PLATFORM_HIGH_PERF, WMI_HOST_PLATFORM_HIGH_PERF,
WMI_HOST_PLATFORM_LOW_PERF, WMI_HOST_PLATFORM_LOW_PERF,

View File

@ -180,6 +180,100 @@ static void ath10k_wow_convert_8023_to_80211
} }
} }
static int ath10k_wmi_pno_check(struct ath10k *ar, u32 vdev_id,
struct cfg80211_sched_scan_request *nd_config,
struct wmi_pno_scan_req *pno)
{
int i, j, ret = 0;
u8 ssid_len;
pno->enable = 1;
pno->vdev_id = vdev_id;
pno->uc_networks_count = nd_config->n_match_sets;
if (!pno->uc_networks_count ||
pno->uc_networks_count > WMI_PNO_MAX_SUPP_NETWORKS)
return -EINVAL;
if (nd_config->n_channels > WMI_PNO_MAX_NETW_CHANNELS_EX)
return -EINVAL;
/* Filling per profile params */
for (i = 0; i < pno->uc_networks_count; i++) {
ssid_len = nd_config->match_sets[i].ssid.ssid_len;
if (ssid_len == 0 || ssid_len > 32)
return -EINVAL;
pno->a_networks[i].ssid.ssid_len = __cpu_to_le32(ssid_len);
memcpy(pno->a_networks[i].ssid.ssid,
nd_config->match_sets[i].ssid.ssid,
nd_config->match_sets[i].ssid.ssid_len);
pno->a_networks[i].authentication = 0;
pno->a_networks[i].encryption = 0;
pno->a_networks[i].bcast_nw_type = 0;
/*Copying list of valid channel into request */
pno->a_networks[i].channel_count = nd_config->n_channels;
pno->a_networks[i].rssi_threshold = nd_config->match_sets[i].rssi_thold;
for (j = 0; j < nd_config->n_channels; j++) {
pno->a_networks[i].channels[j] =
nd_config->channels[j]->center_freq;
}
}
/* set scan to passive if no SSIDs are specified in the request */
if (nd_config->n_ssids == 0)
pno->do_passive_scan = true;
else
pno->do_passive_scan = false;
for (i = 0; i < nd_config->n_ssids; i++) {
j = 0;
while (j < pno->uc_networks_count) {
if (__le32_to_cpu(pno->a_networks[j].ssid.ssid_len) ==
nd_config->ssids[i].ssid_len &&
(memcmp(pno->a_networks[j].ssid.ssid,
nd_config->ssids[i].ssid,
__le32_to_cpu(pno->a_networks[j].ssid.ssid_len)) == 0)) {
pno->a_networks[j].bcast_nw_type = BCAST_HIDDEN;
break;
}
j++;
}
}
if (nd_config->n_scan_plans == 2) {
pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC;
pno->fast_scan_max_cycles = nd_config->scan_plans[0].iterations;
pno->slow_scan_period =
nd_config->scan_plans[1].interval * MSEC_PER_SEC;
} else if (nd_config->n_scan_plans == 1) {
pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC;
pno->fast_scan_max_cycles = 1;
pno->slow_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC;
} else {
ath10k_warn(ar, "Invalid number of scan plans %d !!",
nd_config->n_scan_plans);
}
if (nd_config->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
/* enable mac randomization */
pno->enable_pno_scan_randomization = 1;
memcpy(pno->mac_addr, nd_config->mac_addr, ETH_ALEN);
memcpy(pno->mac_addr_mask, nd_config->mac_addr_mask, ETH_ALEN);
}
pno->delay_start_time = nd_config->delay;
/* Current FW does not support min-max range for dwell time */
pno->active_max_time = WMI_ACTIVE_MAX_CHANNEL_TIME;
pno->passive_max_time = WMI_PASSIVE_MAX_CHANNEL_TIME;
return ret;
}
static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif, static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,
struct cfg80211_wowlan *wowlan) struct cfg80211_wowlan *wowlan)
{ {
@ -213,6 +307,26 @@ static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,
if (wowlan->magic_pkt) if (wowlan->magic_pkt)
__set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask); __set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask);
if (wowlan->nd_config) {
struct wmi_pno_scan_req *pno;
int ret;
pno = kzalloc(sizeof(*pno), GFP_KERNEL);
if (!pno)
return -ENOMEM;
ar->nlo_enabled = true;
ret = ath10k_wmi_pno_check(ar, arvif->vdev_id,
wowlan->nd_config, pno);
if (!ret) {
ath10k_wmi_wow_config_pno(ar, arvif->vdev_id, pno);
__set_bit(WOW_NLO_DETECTED_EVENT, &wow_mask);
}
kfree(pno);
}
break; break;
default: default:
break; break;
@ -299,6 +413,51 @@ static int ath10k_wow_set_wakeups(struct ath10k *ar,
return 0; return 0;
} }
static int ath10k_vif_wow_clean_nlo(struct ath10k_vif *arvif)
{
int ret = 0;
struct ath10k *ar = arvif->ar;
switch (arvif->vdev_type) {
case WMI_VDEV_TYPE_STA:
if (ar->nlo_enabled) {
struct wmi_pno_scan_req *pno;
pno = kzalloc(sizeof(*pno), GFP_KERNEL);
if (!pno)
return -ENOMEM;
pno->enable = 0;
ar->nlo_enabled = false;
ret = ath10k_wmi_wow_config_pno(ar, arvif->vdev_id, pno);
kfree(pno);
}
break;
default:
break;
}
return ret;
}
static int ath10k_wow_nlo_cleanup(struct ath10k *ar)
{
struct ath10k_vif *arvif;
int ret = 0;
lockdep_assert_held(&ar->conf_mutex);
list_for_each_entry(arvif, &ar->arvifs, list) {
ret = ath10k_vif_wow_clean_nlo(arvif);
if (ret) {
ath10k_warn(ar, "failed to clean nlo settings on vdev %i: %d\n",
arvif->vdev_id, ret);
return ret;
}
}
return 0;
}
static int ath10k_wow_enable(struct ath10k *ar) static int ath10k_wow_enable(struct ath10k *ar)
{ {
int ret; int ret;
@ -436,6 +595,10 @@ int ath10k_wow_op_resume(struct ieee80211_hw *hw)
if (ret) if (ret)
ath10k_warn(ar, "failed to wakeup from wow: %d\n", ret); ath10k_warn(ar, "failed to wakeup from wow: %d\n", ret);
ret = ath10k_wow_nlo_cleanup(ar);
if (ret)
ath10k_warn(ar, "failed to cleanup nlo: %d\n", ret);
exit: exit:
if (ret) { if (ret) {
switch (ar->state) { switch (ar->state) {
@ -475,6 +638,11 @@ int ath10k_wow_init(struct ath10k *ar)
ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE; ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE;
} }
if (test_bit(WMI_SERVICE_NLO, ar->wmi.svc_map)) {
ar->wow.wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT;
ar->wow.wowlan_support.max_nd_match_sets = WMI_PNO_MAX_SUPP_NETWORKS;
}
ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns; ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns;
ar->hw->wiphy->wowlan = &ar->wow.wowlan_support; ar->hw->wiphy->wowlan = &ar->wow.wowlan_support;

View File

@ -755,11 +755,11 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
} }
if (main_ant_conf == rx_ant_conf) { if (main_ant_conf == rx_ant_conf) {
ANT_STAT_INC(ANT_MAIN, recv_cnt); ANT_STAT_INC(sc, ANT_MAIN, recv_cnt);
ANT_LNA_INC(ANT_MAIN, rx_ant_conf); ANT_LNA_INC(sc, ANT_MAIN, rx_ant_conf);
} else { } else {
ANT_STAT_INC(ANT_ALT, recv_cnt); ANT_STAT_INC(sc, ANT_ALT, recv_cnt);
ANT_LNA_INC(ANT_ALT, rx_ant_conf); ANT_LNA_INC(sc, ANT_ALT, rx_ant_conf);
} }
/* Short scan check */ /* Short scan check */

View File

@ -624,9 +624,9 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h
tsf, freq, chan_type); tsf, freq, chan_type);
if (ret == 0) if (ret == 0)
RX_STAT_INC(rx_spectral_sample_good); RX_STAT_INC(sc, rx_spectral_sample_good);
else else
RX_STAT_INC(rx_spectral_sample_err); RX_STAT_INC(sc, rx_spectral_sample_err);
memset(sample_buf, 0, SPECTRAL_SAMPLE_MAX_LEN); memset(sample_buf, 0, SPECTRAL_SAMPLE_MAX_LEN);
@ -642,9 +642,9 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h
tsf, freq, chan_type); tsf, freq, chan_type);
if (ret == 0) if (ret == 0)
RX_STAT_INC(rx_spectral_sample_good); RX_STAT_INC(sc, rx_spectral_sample_good);
else else
RX_STAT_INC(rx_spectral_sample_err); RX_STAT_INC(sc, rx_spectral_sample_err);
/* Mix the received bins to the /dev/random /* Mix the received bins to the /dev/random
* pool * pool

View File

@ -785,35 +785,35 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
{ {
int qnum = txq->axq_qnum; int qnum = txq->axq_qnum;
TX_STAT_INC(qnum, tx_pkts_all); TX_STAT_INC(sc, qnum, tx_pkts_all);
sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len; sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
if (bf_isampdu(bf)) { if (bf_isampdu(bf)) {
if (flags & ATH_TX_ERROR) if (flags & ATH_TX_ERROR)
TX_STAT_INC(qnum, a_xretries); TX_STAT_INC(sc, qnum, a_xretries);
else else
TX_STAT_INC(qnum, a_completed); TX_STAT_INC(sc, qnum, a_completed);
} else { } else {
if (ts->ts_status & ATH9K_TXERR_XRETRY) if (ts->ts_status & ATH9K_TXERR_XRETRY)
TX_STAT_INC(qnum, xretries); TX_STAT_INC(sc, qnum, xretries);
else else
TX_STAT_INC(qnum, completed); TX_STAT_INC(sc, qnum, completed);
} }
if (ts->ts_status & ATH9K_TXERR_FILT) if (ts->ts_status & ATH9K_TXERR_FILT)
TX_STAT_INC(qnum, txerr_filtered); TX_STAT_INC(sc, qnum, txerr_filtered);
if (ts->ts_status & ATH9K_TXERR_FIFO) if (ts->ts_status & ATH9K_TXERR_FIFO)
TX_STAT_INC(qnum, fifo_underrun); TX_STAT_INC(sc, qnum, fifo_underrun);
if (ts->ts_status & ATH9K_TXERR_XTXOP) if (ts->ts_status & ATH9K_TXERR_XTXOP)
TX_STAT_INC(qnum, xtxop); TX_STAT_INC(sc, qnum, xtxop);
if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED) if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED)
TX_STAT_INC(qnum, timer_exp); TX_STAT_INC(sc, qnum, timer_exp);
if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR) if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR)
TX_STAT_INC(qnum, desc_cfg_err); TX_STAT_INC(sc, qnum, desc_cfg_err);
if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN) if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN)
TX_STAT_INC(qnum, data_underrun); TX_STAT_INC(sc, qnum, data_underrun);
if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
TX_STAT_INC(qnum, delim_underrun); TX_STAT_INC(sc, qnum, delim_underrun);
} }
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)

View File

@ -25,17 +25,17 @@ struct ath_buf;
struct fft_sample_tlv; struct fft_sample_tlv;
#ifdef CONFIG_ATH9K_DEBUGFS #ifdef CONFIG_ATH9K_DEBUGFS
#define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++ #define TX_STAT_INC(sc, q, c) do { (sc)->debug.stats.txstats[q].c++; } while (0)
#define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++) #define RX_STAT_INC(sc, c) do { (sc)->debug.stats.rxstats.c++; } while (0)
#define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++ #define RESET_STAT_INC(sc, type) do { (sc)->debug.stats.reset[type]++; } while (0)
#define ANT_STAT_INC(i, c) sc->debug.stats.ant_stats[i].c++ #define ANT_STAT_INC(sc, i, c) do { (sc)->debug.stats.ant_stats[i].c++; } while (0)
#define ANT_LNA_INC(i, c) sc->debug.stats.ant_stats[i].lna_recv_cnt[c]++; #define ANT_LNA_INC(sc, i, c) do { (sc)->debug.stats.ant_stats[i].lna_recv_cnt[c]++; } while (0)
#else #else
#define TX_STAT_INC(q, c) do { } while (0) #define TX_STAT_INC(sc, q, c) do { (void)(sc); } while (0)
#define RX_STAT_INC(c) #define RX_STAT_INC(sc, c) do { (void)(sc); } while (0)
#define RESET_STAT_INC(sc, type) do { } while (0) #define RESET_STAT_INC(sc, type) do { (void)(sc); } while (0)
#define ANT_STAT_INC(i, c) do { } while (0) #define ANT_STAT_INC(sc, i, c) do { (void)(sc); } while (0)
#define ANT_LNA_INC(i, c) do { } while (0) #define ANT_LNA_INC(sc, i, c) do { (void)(sc); } while (0)
#endif #endif
enum ath_reset_type { enum ath_reset_type {

View File

@ -809,7 +809,7 @@ static void ath9k_tx(struct ieee80211_hw *hw,
if (ath_tx_start(hw, skb, &txctl) != 0) { if (ath_tx_start(hw, skb, &txctl) != 0) {
ath_dbg(common, XMIT, "TX failed\n"); ath_dbg(common, XMIT, "TX failed\n");
TX_STAT_INC(txctl.txq->axq_qnum, txfailed); TX_STAT_INC(sc, txctl.txq->axq_qnum, txfailed);
goto exit; goto exit;
} }

View File

@ -829,7 +829,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
* Discard zero-length packets and packets smaller than an ACK * Discard zero-length packets and packets smaller than an ACK
*/ */
if (rx_stats->rs_datalen < 10) { if (rx_stats->rs_datalen < 10) {
RX_STAT_INC(rx_len_err); RX_STAT_INC(sc, rx_len_err);
goto corrupt; goto corrupt;
} }
@ -839,7 +839,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
* those frames. * those frames.
*/ */
if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) { if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) {
RX_STAT_INC(rx_len_err); RX_STAT_INC(sc, rx_len_err);
goto corrupt; goto corrupt;
} }
@ -880,7 +880,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
} else if (sc->spec_priv.spectral_mode != SPECTRAL_DISABLED && } else if (sc->spec_priv.spectral_mode != SPECTRAL_DISABLED &&
ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats, ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats,
rx_status->mactime)) { rx_status->mactime)) {
RX_STAT_INC(rx_spectral); RX_STAT_INC(sc, rx_spectral);
} }
return -EINVAL; return -EINVAL;
} }
@ -898,7 +898,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
spin_unlock_bh(&sc->chan_lock); spin_unlock_bh(&sc->chan_lock);
if (ath_is_mybeacon(common, hdr)) { if (ath_is_mybeacon(common, hdr)) {
RX_STAT_INC(rx_beacons); RX_STAT_INC(sc, rx_beacons);
rx_stats->is_mybeacon = true; rx_stats->is_mybeacon = true;
} }
@ -915,7 +915,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
*/ */
ath_dbg(common, ANY, "unsupported hw bitrate detected 0x%02x using 1 Mbit\n", ath_dbg(common, ANY, "unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
rx_stats->rs_rate); rx_stats->rs_rate);
RX_STAT_INC(rx_rate_err); RX_STAT_INC(sc, rx_rate_err);
return -EINVAL; return -EINVAL;
} }
@ -1136,7 +1136,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
* skb and put it at the tail of the sc->rx.rxbuf list for * skb and put it at the tail of the sc->rx.rxbuf list for
* processing. */ * processing. */
if (!requeue_skb) { if (!requeue_skb) {
RX_STAT_INC(rx_oom_err); RX_STAT_INC(sc, rx_oom_err);
goto requeue_drop_frag; goto requeue_drop_frag;
} }
@ -1164,7 +1164,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
rxs, decrypt_error); rxs, decrypt_error);
if (rs.rs_more) { if (rs.rs_more) {
RX_STAT_INC(rx_frags); RX_STAT_INC(sc, rx_frags);
/* /*
* rs_more indicates chained descriptors which can be * rs_more indicates chained descriptors which can be
* used to link buffers together for a sort of * used to link buffers together for a sort of
@ -1174,7 +1174,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
/* too many fragments - cannot handle frame */ /* too many fragments - cannot handle frame */
dev_kfree_skb_any(sc->rx.frag); dev_kfree_skb_any(sc->rx.frag);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
RX_STAT_INC(rx_too_many_frags_err); RX_STAT_INC(sc, rx_too_many_frags_err);
skb = NULL; skb = NULL;
} }
sc->rx.frag = skb; sc->rx.frag = skb;
@ -1186,7 +1186,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) { if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
RX_STAT_INC(rx_oom_err); RX_STAT_INC(sc, rx_oom_err);
goto requeue_drop_frag; goto requeue_drop_frag;
} }

View File

@ -391,7 +391,7 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
int prev = fi->retries; int prev = fi->retries;
TX_STAT_INC(txq->axq_qnum, a_retries); TX_STAT_INC(sc, txq->axq_qnum, a_retries);
fi->retries += count; fi->retries += count;
if (prev > 0) if (prev > 0)
@ -1105,7 +1105,7 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
al = get_frame_info(bf->bf_mpdu)->framelen; al = get_frame_info(bf->bf_mpdu)->framelen;
bf->bf_state.bf_type = BUF_AMPDU; bf->bf_state.bf_type = BUF_AMPDU;
} else { } else {
TX_STAT_INC(txq->axq_qnum, a_aggr); TX_STAT_INC(sc, txq->axq_qnum, a_aggr);
} }
return al; return al;
@ -1727,7 +1727,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
bf_tail = bf; bf_tail = bf;
nframes--; nframes--;
sent++; sent++;
TX_STAT_INC(txq->axq_qnum, a_queued_hw); TX_STAT_INC(sc, txq->axq_qnum, a_queued_hw);
if (an->sta && skb_queue_empty(&tid->retry_q)) if (an->sta && skb_queue_empty(&tid->retry_q))
ieee80211_sta_set_buffered(an->sta, i, false); ieee80211_sta_set_buffered(an->sta, i, false);
@ -2110,14 +2110,14 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
} }
if (puttxbuf) { if (puttxbuf) {
TX_STAT_INC(txq->axq_qnum, puttxbuf); TX_STAT_INC(sc, txq->axq_qnum, puttxbuf);
ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
ath_dbg(common, XMIT, "TXDP[%u] = %llx (%p)\n", ath_dbg(common, XMIT, "TXDP[%u] = %llx (%p)\n",
txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
} }
if (!edma || sc->tx99_state) { if (!edma || sc->tx99_state) {
TX_STAT_INC(txq->axq_qnum, txstart); TX_STAT_INC(sc, txq->axq_qnum, txstart);
ath9k_hw_txstart(ah, txq->axq_qnum); ath9k_hw_txstart(ah, txq->axq_qnum);
} }
@ -2154,7 +2154,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_lastbf = bf; bf->bf_lastbf = bf;
ath_tx_fill_desc(sc, bf, txq, fi->framelen); ath_tx_fill_desc(sc, bf, txq, fi->framelen);
ath_tx_txqaddbuf(sc, txq, &bf_head, false); ath_tx_txqaddbuf(sc, txq, &bf_head, false);
TX_STAT_INC(txq->axq_qnum, queued); TX_STAT_INC(sc, txq->axq_qnum, queued);
} }
static void setup_frame_info(struct ieee80211_hw *hw, static void setup_frame_info(struct ieee80211_hw *hw,
@ -2486,7 +2486,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
ath_txq_lock(sc, txctl.txq); ath_txq_lock(sc, txctl.txq);
ath_tx_fill_desc(sc, bf, txctl.txq, 0); ath_tx_fill_desc(sc, bf, txctl.txq, 0);
ath_tx_txqaddbuf(sc, txctl.txq, &bf_q, false); ath_tx_txqaddbuf(sc, txctl.txq, &bf_q, false);
TX_STAT_INC(txctl.txq->axq_qnum, queued); TX_STAT_INC(sc, txctl.txq->axq_qnum, queued);
ath_txq_unlock(sc, txctl.txq); ath_txq_unlock(sc, txctl.txq);
} }
@ -2699,7 +2699,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
if (status == -EINPROGRESS) if (status == -EINPROGRESS)
break; break;
TX_STAT_INC(txq->axq_qnum, txprocdesc); TX_STAT_INC(sc, txq->axq_qnum, txprocdesc);
/* /*
* Remove ath_buf's of the same transmit unit from txq, * Remove ath_buf's of the same transmit unit from txq,
@ -2778,7 +2778,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
ath_txq_lock(sc, txq); ath_txq_lock(sc, txq);
TX_STAT_INC(txq->axq_qnum, txprocdesc); TX_STAT_INC(sc, txq->axq_qnum, txprocdesc);
fifo_list = &txq->txq_fifo[txq->txq_tailidx]; fifo_list = &txq->txq_fifo[txq->txq_tailidx];
if (list_empty(fifo_list)) { if (list_empty(fifo_list)) {

View File

@ -416,8 +416,8 @@ static int wil_debugfs_iomem_x32_get(void *data, u64 *val)
return 0; return 0;
} }
DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get, DEFINE_DEBUGFS_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get,
wil_debugfs_iomem_x32_set, "0x%08llx\n"); wil_debugfs_iomem_x32_set, "0x%08llx\n");
static struct dentry *wil_debugfs_create_iomem_x32(const char *name, static struct dentry *wil_debugfs_create_iomem_x32(const char *name,
umode_t mode, umode_t mode,
@ -432,7 +432,8 @@ static struct dentry *wil_debugfs_create_iomem_x32(const char *name,
data->wil = wil; data->wil = wil;
data->offset = value; data->offset = value;
file = debugfs_create_file(name, mode, parent, data, &fops_iomem_x32); file = debugfs_create_file_unsafe(name, mode, parent, data,
&fops_iomem_x32);
if (!IS_ERR_OR_NULL(file)) if (!IS_ERR_OR_NULL(file))
wil->dbg_data.iomem_data_count++; wil->dbg_data.iomem_data_count++;
@ -451,14 +452,15 @@ static int wil_debugfs_ulong_get(void *data, u64 *val)
return 0; return 0;
} }
DEFINE_SIMPLE_ATTRIBUTE(wil_fops_ulong, wil_debugfs_ulong_get, DEFINE_DEBUGFS_ATTRIBUTE(wil_fops_ulong, wil_debugfs_ulong_get,
wil_debugfs_ulong_set, "0x%llx\n"); wil_debugfs_ulong_set, "0x%llx\n");
static struct dentry *wil_debugfs_create_ulong(const char *name, umode_t mode, static struct dentry *wil_debugfs_create_ulong(const char *name, umode_t mode,
struct dentry *parent, struct dentry *parent,
ulong *value) ulong *value)
{ {
return debugfs_create_file(name, mode, parent, value, &wil_fops_ulong); return debugfs_create_file_unsafe(name, mode, parent, value,
&wil_fops_ulong);
} }
/** /**

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2015, 2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2015 Linaro Ltd. * Copyright (C) 2015 Linaro Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -33,6 +33,8 @@ struct qcom_scm_vmperm {
#define QCOM_SCM_VMID_HLOS 0x3 #define QCOM_SCM_VMID_HLOS 0x3
#define QCOM_SCM_VMID_MSS_MSA 0xF #define QCOM_SCM_VMID_MSS_MSA 0xF
#define QCOM_SCM_VMID_WLAN 0x18
#define QCOM_SCM_VMID_WLAN_CE 0x19
#define QCOM_SCM_PERM_READ 0x4 #define QCOM_SCM_PERM_READ 0x4
#define QCOM_SCM_PERM_WRITE 0x2 #define QCOM_SCM_PERM_WRITE 0x2
#define QCOM_SCM_PERM_EXEC 0x1 #define QCOM_SCM_PERM_EXEC 0x1