Merge ath-next from ath.git

Major changes in ath10k:

* Device tree support

* Major restructuring how to handle different WMI interface versions

* Add WMI TLV interface in preparation for new firmware interface support

* Support new firmware branch 10.2.4

* Add thermal cooling interface

* Add hwmon interface to read temparture from the device

And of course lots of small fixes and cleanups.
This commit is contained in:
Kalle Valo 2015-01-09 18:38:46 +02:00
commit 350b193ebd
20 changed files with 6734 additions and 732 deletions

View File

@ -0,0 +1,30 @@
* Qualcomm Atheros ath10k wireless devices
For ath10k devices the calibration data can be provided through Device
Tree. The node is a child node of the PCI controller.
Required properties:
-compatible : Should be "qcom,ath10k"
Optional properties:
- qcom,ath10k-calibration-data : calibration data as an array, the
length can vary between hw versions
Example:
pci {
pcie@0 {
reg = <0 0 0 0 0>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
ath10k@0,0 {
reg = <0 0 0 0 0>;
device_type = "pci";
qcom,ath10k-calibration-data = [ 01 02 03 ... ];
};
};
};

View File

@ -8,11 +8,13 @@ ath10k_core-y += mac.o \
htt_tx.o \
txrx.o \
wmi.o \
wmi-tlv.o \
bmi.o
ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o
ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o
ath10k_core-$(CONFIG_THERMAL) += thermal.o
obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o
ath10k_pci-y += pci.o \

View File

@ -1093,6 +1093,8 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
BUILD_BUG_ON(2*TARGET_TLV_NUM_MSDU_DESC >
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
ce_state->ar = ar;
ce_state->id = ce_id;

View File

@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/of.h>
#include "core.h"
#include "mac.h"
@ -27,20 +28,18 @@
#include "debug.h"
#include "htt.h"
#include "testmode.h"
#include "wmi-ops.h"
unsigned int ath10k_debug_mask;
static bool uart_print;
static unsigned int ath10k_p2p;
static bool skip_otp;
module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
module_param(uart_print, bool, 0644);
module_param_named(p2p, ath10k_p2p, uint, 0644);
module_param(skip_otp, bool, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(uart_print, "Uart target debugging");
MODULE_PARM_DESC(p2p, "Enable ath10k P2P support");
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
static const struct ath10k_hw_params ath10k_hw_params_list[] = {
@ -48,11 +47,14 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.id = QCA988X_HW_2_0_VERSION,
.name = "qca988x hw2.0",
.patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
.fw = {
.dir = QCA988X_HW_2_0_FW_DIR,
.fw = QCA988X_HW_2_0_FW_FILE,
.otp = QCA988X_HW_2_0_OTP_FILE,
.board = QCA988X_HW_2_0_BOARD_DATA_FILE,
.board_size = QCA988X_BOARD_DATA_SZ,
.board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,
},
},
};
@ -146,8 +148,8 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar,
static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data,
size_t data_len)
{
u32 board_data_size = QCA988X_BOARD_DATA_SZ;
u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ;
u32 board_data_size = ar->hw_params.fw.board_size;
u32 board_ext_data_size = ar->hw_params.fw.board_ext_size;
u32 board_ext_data_addr;
int ret;
@ -193,7 +195,7 @@ static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data,
static int ath10k_download_board_data(struct ath10k *ar, const void *data,
size_t data_len)
{
u32 board_data_size = QCA988X_BOARD_DATA_SZ;
u32 board_data_size = ar->hw_params.fw.board_size;
u32 address;
int ret;
@ -249,6 +251,63 @@ static int ath10k_download_cal_file(struct ath10k *ar)
return 0;
}
static int ath10k_download_cal_dt(struct ath10k *ar)
{
struct device_node *node;
int data_len;
void *data;
int ret;
node = ar->dev->of_node;
if (!node)
/* Device Tree is optional, don't print any warnings if
* there's no node for ath10k.
*/
return -ENOENT;
if (!of_get_property(node, "qcom,ath10k-calibration-data",
&data_len)) {
/* The calibration data node is optional */
return -ENOENT;
}
if (data_len != QCA988X_CAL_DATA_LEN) {
ath10k_warn(ar, "invalid calibration data length in DT: %d\n",
data_len);
ret = -EMSGSIZE;
goto out;
}
data = kmalloc(data_len, GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
goto out;
}
ret = of_property_read_u8_array(node, "qcom,ath10k-calibration-data",
data, data_len);
if (ret) {
ath10k_warn(ar, "failed to read calibration data from DT: %d\n",
ret);
goto out_free;
}
ret = ath10k_download_board_data(ar, data, data_len);
if (ret) {
ath10k_warn(ar, "failed to download calibration data from Device Tree: %d\n",
ret);
goto out_free;
}
ret = 0;
out_free:
kfree(data);
out:
return ret;
}
static int ath10k_download_and_run_otp(struct ath10k *ar)
{
u32 result, address = ar->hw_params.patch_load_addr;
@ -447,7 +506,7 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
int ie_id, i, index, bit, ret;
struct ath10k_fw_ie *hdr;
const u8 *data;
__le32 *timestamp;
__le32 *timestamp, *version;
/* first fetch the firmware file (firmware-*.bin) */
ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name);
@ -562,6 +621,17 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
ar->otp_len = ie_len;
break;
case ATH10K_FW_IE_WMI_OP_VERSION:
if (ie_len != sizeof(u32))
break;
version = (__le32 *)data;
ar->wmi.op_version = le32_to_cpup(version);
ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie wmi op version %d\n",
ar->wmi.op_version);
break;
default:
ath10k_warn(ar, "Unknown FW IE: %u\n",
le32_to_cpu(hdr->id));
@ -582,13 +652,6 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
goto err;
}
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features) &&
!test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");
ret = -EINVAL;
goto err;
}
/* now fetch the board file */
if (ar->hw_params.fw.board == NULL) {
ath10k_err(ar, "board data file not defined");
@ -624,6 +687,13 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
/* calibration file is optional, don't check for any errors */
ath10k_fetch_cal_file(ar);
ar->fw_api = 4;
ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE);
if (ret == 0)
goto success;
ar->fw_api = 3;
ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
@ -662,7 +732,17 @@ static int ath10k_download_cal_data(struct ath10k *ar)
}
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot did not find a calibration file, try OTP next: %d\n",
"boot did not find a calibration file, try DT next: %d\n",
ret);
ret = ath10k_download_cal_dt(ar);
if (ret == 0) {
ar->cal_mode = ATH10K_CAL_MODE_DT;
goto done;
}
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot did not find DT entry, try OTP next: %d\n",
ret);
ret = ath10k_download_and_run_otp(ar);
@ -696,7 +776,7 @@ static int ath10k_init_uart(struct ath10k *ar)
if (!uart_print)
return 0;
ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, 7);
ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, ar->hw_params.uart_pin);
if (ret) {
ath10k_warn(ar, "could not enable UART prints (%d)\n", ret);
return ret;
@ -764,6 +844,7 @@ static void ath10k_core_restart(struct work_struct *work)
complete_all(&ar->offchan_tx_completed);
complete_all(&ar->install_key_done);
complete_all(&ar->vdev_setup_done);
complete_all(&ar->thermal.wmi_sync);
wake_up(&ar->htt.empty_tx_wq);
wake_up(&ar->wmi.tx_credits_wq);
wake_up(&ar->peer_mapping_wq);
@ -799,15 +880,62 @@ static void ath10k_core_restart(struct work_struct *work)
mutex_unlock(&ar->conf_mutex);
}
static void ath10k_core_init_max_sta_count(struct ath10k *ar)
static int ath10k_core_init_firmware_features(struct ath10k *ar)
{
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
ar->max_num_peers = TARGET_10X_NUM_PEERS;
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
} else {
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features) &&
!test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");
return -EINVAL;
}
if (ar->wmi.op_version >= ATH10K_FW_WMI_OP_VERSION_MAX) {
ath10k_err(ar, "unsupported WMI OP version (max %d): %d\n",
ATH10K_FW_WMI_OP_VERSION_MAX, ar->wmi.op_version);
return -EINVAL;
}
/* Backwards compatibility for firmwares without
* ATH10K_FW_IE_WMI_OP_VERSION.
*/
if (ar->wmi.op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) {
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2,
ar->fw_features))
ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_2;
else
ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
} else {
ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_MAIN;
}
}
switch (ar->wmi.op_version) {
case ATH10K_FW_WMI_OP_VERSION_MAIN:
ar->max_num_peers = TARGET_NUM_PEERS;
ar->max_num_stations = TARGET_NUM_STATIONS;
ar->max_num_vdevs = TARGET_NUM_VDEVS;
ar->htt.max_num_pending_tx = TARGET_NUM_MSDU_DESC;
break;
case ATH10K_FW_WMI_OP_VERSION_10_1:
case ATH10K_FW_WMI_OP_VERSION_10_2:
case ATH10K_FW_WMI_OP_VERSION_10_2_4:
ar->max_num_peers = TARGET_10X_NUM_PEERS;
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
ar->htt.max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
ar->max_num_peers = TARGET_TLV_NUM_PEERS;
ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC;
break;
case ATH10K_FW_WMI_OP_VERSION_UNSET:
case ATH10K_FW_WMI_OP_VERSION_MAX:
WARN_ON(1);
return -EINVAL;
}
return 0;
}
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
@ -945,10 +1073,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
if (status)
goto err_hif_stop;
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1;
else
ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1;
ar->free_vdev_map = (1LL << ar->max_num_vdevs) - 1;
INIT_LIST_HEAD(&ar->arvifs);
@ -1025,8 +1150,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
ret = ath10k_bmi_get_target_info(ar, &target_info);
if (ret) {
ath10k_err(ar, "could not get target info (%d)\n", ret);
ath10k_hif_power_down(ar);
return ret;
goto err_power_down;
}
ar->target_version = target_info.version;
@ -1035,28 +1159,28 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
ret = ath10k_init_hw_params(ar);
if (ret) {
ath10k_err(ar, "could not get hw params (%d)\n", ret);
ath10k_hif_power_down(ar);
return ret;
goto err_power_down;
}
ret = ath10k_core_fetch_firmware_files(ar);
if (ret) {
ath10k_err(ar, "could not fetch firmware files (%d)\n", ret);
ath10k_hif_power_down(ar);
return ret;
goto err_power_down;
}
ath10k_core_init_max_sta_count(ar);
ret = ath10k_core_init_firmware_features(ar);
if (ret) {
ath10k_err(ar, "fatal problem with firmware features: %d\n",
ret);
goto err_free_firmware_files;
}
mutex_lock(&ar->conf_mutex);
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
if (ret) {
ath10k_err(ar, "could not init core (%d)\n", ret);
ath10k_core_free_firmware_files(ar);
ath10k_hif_power_down(ar);
mutex_unlock(&ar->conf_mutex);
return ret;
goto err_unlock;
}
ath10k_print_driver_info(ar);
@ -1066,34 +1190,17 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
ath10k_hif_power_down(ar);
return 0;
}
static int ath10k_core_check_chip_id(struct ath10k *ar)
{
u32 hw_revision = MS(ar->chip_id, SOC_CHIP_ID_REV);
err_unlock:
mutex_unlock(&ar->conf_mutex);
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip_id 0x%08x hw_revision 0x%x\n",
ar->chip_id, hw_revision);
err_free_firmware_files:
ath10k_core_free_firmware_files(ar);
/* Check that we are not using hw1.0 (some of them have same pci id
* as hw2.0) before doing anything else as ath10k crashes horribly
* due to missing hw1.0 workarounds. */
switch (hw_revision) {
case QCA988X_HW_1_0_CHIP_ID_REV:
ath10k_err(ar, "ERROR: qca988x hw1.0 is not supported\n");
return -EOPNOTSUPP;
err_power_down:
ath10k_hif_power_down(ar);
case QCA988X_HW_2_0_CHIP_ID_REV:
/* known hardware revision, continue normally */
return 0;
default:
ath10k_warn(ar, "Warning: hardware revision unknown (0x%x), expect problems\n",
ar->chip_id);
return 0;
}
return 0;
return ret;
}
static void ath10k_core_register_work(struct work_struct *work)
@ -1125,9 +1232,18 @@ static void ath10k_core_register_work(struct work_struct *work)
goto err_debug_destroy;
}
status = ath10k_thermal_register(ar);
if (status) {
ath10k_err(ar, "could not register thermal device: %d\n",
status);
goto err_spectral_destroy;
}
set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags);
return;
err_spectral_destroy:
ath10k_spectral_destroy(ar);
err_debug_destroy:
ath10k_debug_destroy(ar);
err_unregister_mac:
@ -1143,16 +1259,7 @@ static void ath10k_core_register_work(struct work_struct *work)
int ath10k_core_register(struct ath10k *ar, u32 chip_id)
{
int status;
ar->chip_id = chip_id;
status = ath10k_core_check_chip_id(ar);
if (status) {
ath10k_err(ar, "Unsupported chip id 0x%08x\n", ar->chip_id);
return status;
}
queue_work(ar->workqueue, &ar->register_work);
return 0;
@ -1166,6 +1273,7 @@ void ath10k_core_unregister(struct ath10k *ar)
if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
return;
ath10k_thermal_unregister(ar);
/* Stop spectral before unregistering from mac80211 to remove the
* relayfs debugfs file cleanly. Otherwise the parent debugfs tree
* would be already be free'd recursively, leading to a double free.
@ -1198,10 +1306,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
ar->ath_common.priv = ar;
ar->ath_common.hw = ar->hw;
ar->p2p = !!ath10k_p2p;
ar->dev = dev;
ar->hif.ops = hif_ops;
ar->hif.bus = bus;
@ -1212,6 +1317,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
init_completion(&ar->install_key_done);
init_completion(&ar->vdev_setup_done);
init_completion(&ar->thermal.wmi_sync);
INIT_DELAYED_WORK(&ar->scan.timeout, ath10k_scan_timeout_work);

View File

@ -34,6 +34,7 @@
#include "../regd.h"
#include "../dfs_pattern_detector.h"
#include "spectral.h"
#include "thermal.h"
#define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@ -120,6 +121,7 @@ struct ath10k_mem_chunk {
};
struct ath10k_wmi {
enum ath10k_fw_wmi_op_version op_version;
enum ath10k_htc_ep_id eid;
struct completion service_ready;
struct completion unified_ready;
@ -128,6 +130,7 @@ struct ath10k_wmi {
struct wmi_cmd_map *cmd;
struct wmi_vdev_param_map *vdev_param;
struct wmi_pdev_param_map *pdev_param;
const struct wmi_ops *ops;
u32 num_mem_chunks;
struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS];
@ -325,6 +328,7 @@ struct ath10k_debug {
u32 fw_dbglog_mask;
u32 pktlog_filter;
u32 reg_addr;
u32 nf_cal_period;
u8 htt_max_amsdu;
u8 htt_max_ampdu;
@ -369,7 +373,7 @@ enum ath10k_fw_features {
/* wmi_mgmt_rx_hdr contains extra RSSI information */
ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX = 0,
/* firmware from 10X branch */
/* Firmware from 10X branch. Deprecated, don't use in new code. */
ATH10K_FW_FEATURE_WMI_10X = 1,
/* firmware support tx frame management over WMI, otherwise it's HTT */
@ -378,8 +382,9 @@ enum ath10k_fw_features {
/* Firmware does not support P2P */
ATH10K_FW_FEATURE_NO_P2P = 3,
/* Firmware 10.2 feature bit. The ATH10K_FW_FEATURE_WMI_10X feature bit
* is required to be set as well.
/* Firmware 10.2 feature bit. The ATH10K_FW_FEATURE_WMI_10X feature
* bit is required to be set as well. Deprecated, don't use in new
* code.
*/
ATH10K_FW_FEATURE_WMI_10_2 = 4,
@ -401,6 +406,7 @@ enum ath10k_dev_flags {
enum ath10k_cal_mode {
ATH10K_CAL_MODE_FILE,
ATH10K_CAL_MODE_OTP,
ATH10K_CAL_MODE_DT,
};
static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
@ -410,6 +416,8 @@ static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
return "file";
case ATH10K_CAL_MODE_OTP:
return "otp";
case ATH10K_CAL_MODE_DT:
return "dt";
}
return "unknown";
@ -480,12 +488,15 @@ struct ath10k {
u32 id;
const char *name;
u32 patch_load_addr;
int uart_pin;
struct ath10k_hw_params_fw {
const char *dir;
const char *fw;
const char *otp;
const char *board;
size_t board_size;
size_t board_ext_size;
} fw;
} hw_params;
@ -571,6 +582,7 @@ struct ath10k {
int max_num_peers;
int max_num_stations;
int max_num_vdevs;
struct work_struct offchan_tx_work;
struct sk_buff_head offchan_tx_queue;
@ -610,6 +622,7 @@ struct ath10k {
/* protected by conf_mutex */
const struct firmware *utf;
DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
enum ath10k_fw_wmi_op_version orig_wmi_op_version;
/* protected by data_lock */
bool utf_monitor;
@ -622,6 +635,8 @@ struct ath10k {
u32 fw_cold_reset_counter;
} stats;
struct ath10k_thermal thermal;
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};

View File

@ -23,6 +23,7 @@
#include "core.h"
#include "debug.h"
#include "hif.h"
#include "wmi-ops.h"
/* ms */
#define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
@ -123,7 +124,7 @@ EXPORT_SYMBOL(ath10k_info);
void ath10k_print_driver_info(struct ath10k *ar)
{
ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d.%d.%d.%d cal %s max_sta %d\n",
ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d cal %s max_sta %d\n",
ar->hw_params.name,
ar->target_version,
ar->chip_id,
@ -131,10 +132,7 @@ void ath10k_print_driver_info(struct ath10k *ar)
ar->fw_api,
ar->htt.target_version_major,
ar->htt.target_version_minor,
ar->fw_version_major,
ar->fw_version_minor,
ar->fw_version_release,
ar->fw_version_build,
ar->wmi.op_version,
ath10k_cal_mode_str(ar->cal_mode),
ar->max_num_stations);
ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
@ -1607,6 +1605,73 @@ static const struct file_operations fops_cal_data = {
.llseek = default_llseek,
};
static ssize_t ath10k_read_nf_cal_period(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
unsigned int len;
char buf[32];
len = scnprintf(buf, sizeof(buf), "%d\n",
ar->debug.nf_cal_period);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t ath10k_write_nf_cal_period(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
unsigned long period;
int ret;
ret = kstrtoul_from_user(user_buf, count, 0, &period);
if (ret)
return ret;
if (period > WMI_PDEV_PARAM_CAL_PERIOD_MAX)
return -EINVAL;
/* there's no way to switch back to the firmware default */
if (period == 0)
return -EINVAL;
mutex_lock(&ar->conf_mutex);
ar->debug.nf_cal_period = period;
if (ar->state != ATH10K_STATE_ON) {
/* firmware is not running, nothing else to do */
ret = count;
goto exit;
}
ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->cal_period,
ar->debug.nf_cal_period);
if (ret) {
ath10k_warn(ar, "cal period cfg failed from debugfs: %d\n",
ret);
goto exit;
}
ret = count;
exit:
mutex_unlock(&ar->conf_mutex);
return ret;
}
static const struct file_operations fops_nf_cal_period = {
.read = ath10k_read_nf_cal_period,
.write = ath10k_write_nf_cal_period,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
int ath10k_debug_start(struct ath10k *ar)
{
int ret;
@ -1642,6 +1707,16 @@ int ath10k_debug_start(struct ath10k *ar)
ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
}
if (ar->debug.nf_cal_period) {
ret = ath10k_wmi_pdev_set_param(ar,
ar->wmi.pdev_param->cal_period,
ar->debug.nf_cal_period);
if (ret)
/* not serious */
ath10k_warn(ar, "cal period cfg failed from debug start: %d\n",
ret);
}
return ret;
}
@ -1880,6 +1955,9 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_cal_data);
debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar, &fops_nf_cal_period);
if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
debugfs_create_file("dfs_simulate_radar", S_IWUSR,
ar->debug.debugfs_phy, ar,

View File

@ -93,11 +93,6 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
spin_lock_init(&htt->tx_lock);
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features))
htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
else
htt->max_num_pending_tx = TARGET_NUM_MSDU_DESC;
ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n",
htt->max_num_pending_tx);

View File

@ -37,6 +37,9 @@
#define ATH10K_FW_API2_FILE "firmware-2.bin"
#define ATH10K_FW_API3_FILE "firmware-3.bin"
/* added support for ATH10K_FW_IE_WMI_OP_VERSION */
#define ATH10K_FW_API4_FILE "firmware-4.bin"
#define ATH10K_FW_UTF_FILE "utf.bin"
/* includes also the null byte */
@ -58,6 +61,24 @@ enum ath10k_fw_ie_type {
ATH10K_FW_IE_FEATURES = 2,
ATH10K_FW_IE_FW_IMAGE = 3,
ATH10K_FW_IE_OTP_IMAGE = 4,
/* WMI "operations" interface version, 32 bit value. Supported from
* FW API 4 and above.
*/
ATH10K_FW_IE_WMI_OP_VERSION = 5,
};
enum ath10k_fw_wmi_op_version {
ATH10K_FW_WMI_OP_VERSION_UNSET = 0,
ATH10K_FW_WMI_OP_VERSION_MAIN = 1,
ATH10K_FW_WMI_OP_VERSION_10_1 = 2,
ATH10K_FW_WMI_OP_VERSION_10_2 = 3,
ATH10K_FW_WMI_OP_VERSION_TLV = 4,
ATH10K_FW_WMI_OP_VERSION_10_2_4 = 5,
/* keep last */
ATH10K_FW_WMI_OP_VERSION_MAX,
};
/* Known pecularities:
@ -162,6 +183,15 @@ struct ath10k_pktlog_hdr {
#define TARGET_10X_NUM_MSDU_DESC (1024 + 400)
#define TARGET_10X_MAX_FRAG_ENTRIES 0
/* Target specific defines for WMI-TLV firmware */
#define TARGET_TLV_NUM_VDEVS 3
#define TARGET_TLV_NUM_STATIONS 32
#define TARGET_TLV_NUM_PEERS ((TARGET_TLV_NUM_STATIONS) + \
(TARGET_TLV_NUM_VDEVS) + \
2)
#define TARGET_TLV_NUM_TIDS ((TARGET_TLV_NUM_PEERS) * 2)
#define TARGET_TLV_NUM_MSDU_DESC (1024 + 32)
/* Number of Copy Engines supported */
#define CE_COUNT 8

View File

@ -27,6 +27,8 @@
#include "htt.h"
#include "txrx.h"
#include "testmode.h"
#include "wmi.h"
#include "wmi-ops.h"
/**********/
/* Crypto */
@ -267,7 +269,10 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef)
case IEEE80211_BAND_2GHZ:
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20_NOHT:
phymode = MODE_11G;
if (chandef->chan->flags & IEEE80211_CHAN_NO_OFDM)
phymode = MODE_11B;
else
phymode = MODE_11G;
break;
case NL80211_CHAN_WIDTH_20:
phymode = MODE_11NG_HT20;
@ -1046,28 +1051,85 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif,
arvif->vdev_id, ret);
}
/*
* Review this when mac80211 gains per-interface powersave support.
*/
static int ath10k_mac_vif_recalc_ps_wake_threshold(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
u32 param;
u32 value;
int ret;
lockdep_assert_held(&arvif->ar->conf_mutex);
if (arvif->u.sta.uapsd)
value = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER;
else
value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, value);
if (ret) {
ath10k_warn(ar, "failed to submit ps wake threshold %u on vdev %i: %d\n",
value, arvif->vdev_id, ret);
return ret;
}
return 0;
}
static int ath10k_mac_vif_recalc_ps_poll_count(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
u32 param;
u32 value;
int ret;
lockdep_assert_held(&arvif->ar->conf_mutex);
if (arvif->u.sta.uapsd)
value = WMI_STA_PS_PSPOLL_COUNT_UAPSD;
else
value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
param = WMI_STA_PS_PARAM_PSPOLL_COUNT;
ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
param, value);
if (ret) {
ath10k_warn(ar, "failed to submit ps poll count %u on vdev %i: %d\n",
value, arvif->vdev_id, ret);
return ret;
}
return 0;
}
static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
struct ieee80211_vif *vif = arvif->vif;
struct ieee80211_conf *conf = &ar->hw->conf;
enum wmi_sta_powersave_param param;
enum wmi_sta_ps_mode psmode;
int ret;
int ps_timeout;
lockdep_assert_held(&arvif->ar->conf_mutex);
if (arvif->vif->type != NL80211_IFTYPE_STATION)
return 0;
if (conf->flags & IEEE80211_CONF_PS) {
if (vif->bss_conf.ps) {
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
ps_timeout = conf->dynamic_ps_timeout;
if (ps_timeout == 0) {
/* Firmware doesn't like 0 */
ps_timeout = ieee80211_tu_to_usec(
vif->bss_conf.beacon_int) / 1000;
}
ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param,
conf->dynamic_ps_timeout);
ps_timeout);
if (ret) {
ath10k_warn(ar, "failed to set inactivity time for vdev %d: %i\n",
arvif->vdev_id, ret);
@ -1409,9 +1471,22 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
if (vif->bss_conf.qos)
arg->peer_flags |= WMI_PEER_QOS;
break;
case WMI_VDEV_TYPE_IBSS:
if (sta->wme)
arg->peer_flags |= WMI_PEER_QOS;
break;
default:
break;
}
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac peer %pM qos %d\n",
sta->addr, !!(arg->peer_flags & WMI_PEER_QOS));
}
static bool ath10k_mac_sta_has_11g_rates(struct ieee80211_sta *sta)
{
/* First 4 rates in ath10k_rates are CCK (11b) rates. */
return sta->supp_rates[IEEE80211_BAND_2GHZ] >> 4;
}
static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
@ -1428,8 +1503,10 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
phymode = MODE_11NG_HT40;
else
phymode = MODE_11NG_HT20;
} else {
} else if (ath10k_mac_sta_has_11g_rates(sta)) {
phymode = MODE_11G;
} else {
phymode = MODE_11B;
}
break;
@ -2894,10 +2971,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
arvif->vdev_id = bit;
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
if (ar->p2p)
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
switch (vif->type) {
case NL80211_IFTYPE_P2P_DEVICE:
arvif->vdev_type = WMI_VDEV_TYPE_STA;
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
break;
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_STATION:
arvif->vdev_type = WMI_VDEV_TYPE_STA;
@ -3026,22 +3104,16 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
goto err_peer_delete;
}
param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
param, value);
ret = ath10k_mac_vif_recalc_ps_wake_threshold(arvif);
if (ret) {
ath10k_warn(ar, "failed to set vdev %i TX wake thresh: %d\n",
ath10k_warn(ar, "failed to recalc ps wake threshold on vdev %i: %d\n",
arvif->vdev_id, ret);
goto err_peer_delete;
}
param = WMI_STA_PS_PARAM_PSPOLL_COUNT;
value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
param, value);
ret = ath10k_mac_vif_recalc_ps_poll_count(arvif);
if (ret) {
ath10k_warn(ar, "failed to set vdev %i PSPOLL count: %d\n",
ath10k_warn(ar, "failed to recalc ps poll count on vdev %i: %d\n",
arvif->vdev_id, ret);
goto err_peer_delete;
}
@ -3314,6 +3386,13 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
}
if (changed & BSS_CHANGED_PS) {
ret = ath10k_mac_vif_setup_ps(arvif);
if (ret)
ath10k_warn(ar, "failed to setup ps on vdev %i: %d\n",
arvif->vdev_id, ret);
}
mutex_unlock(&ar->conf_mutex);
}
@ -3583,8 +3662,9 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
sta->addr, smps, err);
}
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n",
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED ||
changed & IEEE80211_RC_NSS_CHANGED) {
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates/nss\n",
sta->addr);
err = ath10k_station_assoc(ar, arvif->vif, sta, true);
@ -3808,6 +3888,20 @@ static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif,
if (ret)
ath10k_warn(ar, "failed to set rx wake param: %d\n", ret);
ret = ath10k_mac_vif_recalc_ps_wake_threshold(arvif);
if (ret) {
ath10k_warn(ar, "failed to recalc ps wake threshold on vdev %i: %d\n",
arvif->vdev_id, ret);
return ret;
}
ret = ath10k_mac_vif_recalc_ps_poll_count(arvif);
if (ret) {
ath10k_warn(ar, "failed to recalc ps poll count on vdev %i: %d\n",
arvif->vdev_id, ret);
return ret;
}
exit:
return ret;
}
@ -3989,29 +4083,6 @@ static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
return ret;
}
static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
{
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif;
int ret = 0;
mutex_lock(&ar->conf_mutex);
list_for_each_entry(arvif, &ar->arvifs, list) {
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n",
arvif->vdev_id, value);
ret = ath10k_mac_set_frag(arvif, value);
if (ret) {
ath10k_warn(ar, "failed to set fragmentation threshold for vdev %d: %d\n",
arvif->vdev_id, ret);
break;
}
}
mutex_unlock(&ar->conf_mutex);
return ret;
}
static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
@ -4655,7 +4726,6 @@ static const struct ieee80211_ops ath10k_ops = {
.remain_on_channel = ath10k_remain_on_channel,
.cancel_remain_on_channel = ath10k_cancel_remain_on_channel,
.set_rts_threshold = ath10k_set_rts_threshold,
.set_frag_threshold = ath10k_set_frag_threshold,
.flush = ath10k_flush,
.tx_last_beacon = ath10k_tx_last_beacon,
.set_antenna = ath10k_set_antenna,
@ -4746,6 +4816,9 @@ static const struct ieee80211_channel ath10k_5ghz_channels[] = {
CHAN5G(165, 5825, 0),
};
/* Note: Be careful if you re-order these. There is code which depends on this
* ordering.
*/
static struct ieee80211_rate ath10k_rates[] = {
/* CCK */
RATETAB_ENT(10, 0x82, 0),
@ -4799,6 +4872,10 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = {
.types = BIT(NL80211_IFTYPE_P2P_GO)
},
{
.max = 1,
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
},
{
.max = 7,
.types = BIT(NL80211_IFTYPE_AP)
},
@ -5018,6 +5095,7 @@ int ath10k_mac_register(struct ath10k *ar)
if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features))
ar->hw->wiphy->interface_modes |=
BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO);
@ -5062,16 +5140,26 @@ int ath10k_mac_register(struct ath10k *ar)
*/
ar->hw->queues = 4;
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb;
ar->hw->wiphy->n_iface_combinations =
ARRAY_SIZE(ath10k_10x_if_comb);
} else {
switch (ar->wmi.op_version) {
case ATH10K_FW_WMI_OP_VERSION_MAIN:
case ATH10K_FW_WMI_OP_VERSION_TLV:
ar->hw->wiphy->iface_combinations = ath10k_if_comb;
ar->hw->wiphy->n_iface_combinations =
ARRAY_SIZE(ath10k_if_comb);
ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
break;
case ATH10K_FW_WMI_OP_VERSION_10_1:
case ATH10K_FW_WMI_OP_VERSION_10_2:
case ATH10K_FW_WMI_OP_VERSION_10_2_4:
ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb;
ar->hw->wiphy->n_iface_combinations =
ARRAY_SIZE(ath10k_10x_if_comb);
break;
case ATH10K_FW_WMI_OP_VERSION_UNSET:
case ATH10K_FW_WMI_OP_VERSION_MAX:
WARN_ON(1);
ret = -EINVAL;
goto err_free;
}
ar->hw->netdev_features = NETIF_F_HW_CSUM;

View File

@ -64,6 +64,14 @@ static const struct pci_device_id ath10k_pci_id_table[] = {
{0}
};
static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = {
/* QCA988X pre 2.0 chips are not supported because they need some nasty
* hacks. ath10k doesn't have them and these devices crash horribly
* because of that.
*/
{ QCA988X_2_0_DEVICE_ID, QCA988X_HW_2_0_CHIP_ID_REV },
};
static void ath10k_pci_buffer_cleanup(struct ath10k *ar);
static int ath10k_pci_cold_reset(struct ath10k *ar);
static int ath10k_pci_warm_reset(struct ath10k *ar);
@ -2476,6 +2484,23 @@ static void ath10k_pci_release(struct ath10k *ar)
pci_disable_device(pdev);
}
static bool ath10k_pci_chip_is_supported(u32 dev_id, u32 chip_id)
{
const struct ath10k_pci_supp_chip *supp_chip;
int i;
u32 rev_id = MS(chip_id, SOC_CHIP_ID_REV);
for (i = 0; i < ARRAY_SIZE(ath10k_pci_supp_chips); i++) {
supp_chip = &ath10k_pci_supp_chips[i];
if (supp_chip->dev_id == dev_id &&
supp_chip->rev_id == rev_id)
return true;
}
return false;
}
static int ath10k_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_dev)
{
@ -2521,6 +2546,12 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
goto err_sleep;
}
if (!ath10k_pci_chip_is_supported(pdev->device, chip_id)) {
ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n",
pdev->device, chip_id);
goto err_sleep;
}
ret = ath10k_pci_alloc_pipes(ar);
if (ret) {
ath10k_err(ar, "failed to allocate copy engine pipes: %d\n",

View File

@ -152,6 +152,11 @@ struct ath10k_pci_pipe {
struct tasklet_struct intr;
};
struct ath10k_pci_supp_chip {
u32 dev_id;
u32 rev_id;
};
struct ath10k_pci {
struct pci_dev *pdev;
struct device *dev;

View File

@ -17,6 +17,7 @@
#include <linux/relay.h>
#include "core.h"
#include "debug.h"
#include "wmi-ops.h"
static void send_fft_sample(struct ath10k *ar,
const struct fft_sample_tlv *fft_sample_tlv)

View File

@ -187,13 +187,14 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
memcpy(ar->testmode.orig_fw_features, ar->fw_features,
sizeof(ar->fw_features));
ar->testmode.orig_wmi_op_version = ar->wmi.op_version;
/* utf.bin firmware image does not advertise firmware features. Do
* an ugly hack where we force the firmware features so that wmi.c
* will use the correct WMI interface.
*/
memset(ar->fw_features, 0, sizeof(ar->fw_features));
__set_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features);
ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
ret = ath10k_hif_power_up(ar);
if (ret) {
@ -224,6 +225,7 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
/* return the original firmware features */
memcpy(ar->fw_features, ar->testmode.orig_fw_features,
sizeof(ar->fw_features));
ar->wmi.op_version = ar->testmode.orig_wmi_op_version;
release_firmware(ar->testmode.utf);
ar->testmode.utf = NULL;
@ -250,6 +252,7 @@ static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar)
/* return the original firmware features */
memcpy(ar->fw_features, ar->testmode.orig_fw_features,
sizeof(ar->fw_features));
ar->wmi.op_version = ar->testmode.orig_wmi_op_version;
release_firmware(ar->testmode.utf);
ar->testmode.utf = NULL;

View File

@ -0,0 +1,243 @@
/*
* Copyright (c) 2014 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* 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.
*/
#include <linux/device.h>
#include <linux/sysfs.h>
#include <linux/thermal.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include "core.h"
#include "debug.h"
#include "wmi-ops.h"
static int ath10k_thermal_get_active_vifs(struct ath10k *ar,
enum wmi_vdev_type type)
{
struct ath10k_vif *arvif;
int count = 0;
lockdep_assert_held(&ar->conf_mutex);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (!arvif->is_started)
continue;
if (!arvif->is_up)
continue;
if (arvif->vdev_type != type)
continue;
count++;
}
return count;
}
static int ath10k_thermal_get_max_dutycycle(struct thermal_cooling_device *cdev,
unsigned long *state)
{
*state = ATH10K_QUIET_DUTY_CYCLE_MAX;
return 0;
}
static int ath10k_thermal_get_cur_dutycycle(struct thermal_cooling_device *cdev,
unsigned long *state)
{
struct ath10k *ar = cdev->devdata;
mutex_lock(&ar->conf_mutex);
*state = ar->thermal.duty_cycle;
mutex_unlock(&ar->conf_mutex);
return 0;
}
static int ath10k_thermal_set_cur_dutycycle(struct thermal_cooling_device *cdev,
unsigned long duty_cycle)
{
struct ath10k *ar = cdev->devdata;
u32 period, duration, enabled;
int num_bss, ret = 0;
mutex_lock(&ar->conf_mutex);
if (ar->state != ATH10K_STATE_ON) {
ret = -ENETDOWN;
goto out;
}
if (duty_cycle > ATH10K_QUIET_DUTY_CYCLE_MAX) {
ath10k_warn(ar, "duty cycle %ld is exceeding the limit %d\n",
duty_cycle, ATH10K_QUIET_DUTY_CYCLE_MAX);
ret = -EINVAL;
goto out;
}
/* TODO: Right now, thermal mitigation is handled only for single/multi
* vif AP mode. Since quiet param is not validated in STA mode, it needs
* to be investigated further to handle multi STA and multi-vif (AP+STA)
* mode properly.
*/
num_bss = ath10k_thermal_get_active_vifs(ar, WMI_VDEV_TYPE_AP);
if (!num_bss) {
ath10k_warn(ar, "no active AP interfaces\n");
ret = -ENETDOWN;
goto out;
}
period = max(ATH10K_QUIET_PERIOD_MIN,
(ATH10K_QUIET_PERIOD_DEFAULT / num_bss));
duration = period * (duty_cycle / 100);
enabled = duration ? 1 : 0;
ret = ath10k_wmi_pdev_set_quiet_mode(ar, period, duration,
ATH10K_QUIET_START_OFFSET,
enabled);
if (ret) {
ath10k_warn(ar, "failed to set quiet mode period %u duarion %u enabled %u ret %d\n",
period, duration, enabled, ret);
goto out;
}
ar->thermal.duty_cycle = duty_cycle;
out:
mutex_unlock(&ar->conf_mutex);
return ret;
}
static struct thermal_cooling_device_ops ath10k_thermal_ops = {
.get_max_state = ath10k_thermal_get_max_dutycycle,
.get_cur_state = ath10k_thermal_get_cur_dutycycle,
.set_cur_state = ath10k_thermal_set_cur_dutycycle,
};
static ssize_t ath10k_thermal_show_temp(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ath10k *ar = dev_get_drvdata(dev);
int ret, temperature;
mutex_lock(&ar->conf_mutex);
/* Can't get temperature when the card is off */
if (ar->state != ATH10K_STATE_ON) {
ret = -ENETDOWN;
goto out;
}
reinit_completion(&ar->thermal.wmi_sync);
ret = ath10k_wmi_pdev_get_temperature(ar);
if (ret) {
ath10k_warn(ar, "failed to read temperature %d\n", ret);
goto out;
}
if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) {
ret = -ESHUTDOWN;
goto out;
}
ret = wait_for_completion_timeout(&ar->thermal.wmi_sync,
ATH10K_THERMAL_SYNC_TIMEOUT_HZ);
if (ret == 0) {
ath10k_warn(ar, "failed to synchronize thermal read\n");
ret = -ETIMEDOUT;
goto out;
}
spin_lock_bh(&ar->data_lock);
temperature = ar->thermal.temperature;
spin_unlock_bh(&ar->data_lock);
ret = snprintf(buf, PAGE_SIZE, "%d", temperature);
out:
mutex_unlock(&ar->conf_mutex);
return ret;
}
void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature)
{
spin_lock_bh(&ar->data_lock);
ar->thermal.temperature = temperature;
spin_unlock_bh(&ar->data_lock);
complete(&ar->thermal.wmi_sync);
}
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ath10k_thermal_show_temp,
NULL, 0);
static struct attribute *ath10k_hwmon_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(ath10k_hwmon);
int ath10k_thermal_register(struct ath10k *ar)
{
struct thermal_cooling_device *cdev;
struct device *hwmon_dev;
int ret;
cdev = thermal_cooling_device_register("ath10k_thermal", ar,
&ath10k_thermal_ops);
if (IS_ERR(cdev)) {
ath10k_err(ar, "failed to setup thermal device result: %ld\n",
PTR_ERR(cdev));
return -EINVAL;
}
ret = sysfs_create_link(&ar->dev->kobj, &cdev->device.kobj,
"cooling_device");
if (ret) {
ath10k_err(ar, "failed to create thermal symlink\n");
goto err_cooling_destroy;
}
ar->thermal.cdev = cdev;
/* Do not register hwmon device when temperature reading is not
* supported by firmware
*/
if (ar->wmi.op_version != ATH10K_FW_WMI_OP_VERSION_10_2_4)
return 0;
/* Avoid linking error on devm_hwmon_device_register_with_groups, I
* guess linux/hwmon.h is missing proper stubs. */
if (!config_enabled(HWMON))
return 0;
hwmon_dev = devm_hwmon_device_register_with_groups(ar->dev,
"ath10k_hwmon", ar,
ath10k_hwmon_groups);
if (IS_ERR(hwmon_dev)) {
ath10k_err(ar, "failed to register hwmon device: %ld\n",
PTR_ERR(hwmon_dev));
ret = -EINVAL;
goto err_remove_link;
}
return 0;
err_remove_link:
sysfs_remove_link(&ar->dev->kobj, "thermal_sensor");
err_cooling_destroy:
thermal_cooling_device_unregister(cdev);
return ret;
}
void ath10k_thermal_unregister(struct ath10k *ar)
{
thermal_cooling_device_unregister(ar->thermal.cdev);
sysfs_remove_link(&ar->dev->kobj, "cooling_device");
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2014 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* 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 _THERMAL_
#define _THERMAL_
#define ATH10K_QUIET_PERIOD_DEFAULT 100
#define ATH10K_QUIET_PERIOD_MIN 25
#define ATH10K_QUIET_START_OFFSET 10
#define ATH10K_QUIET_DUTY_CYCLE_MAX 70
#define ATH10K_HWMON_NAME_LEN 15
#define ATH10K_THERMAL_SYNC_TIMEOUT_HZ (5*HZ)
struct ath10k_thermal {
struct thermal_cooling_device *cdev;
struct completion wmi_sync;
/* protected by conf_mutex */
u32 duty_cycle;
/* temperature value in Celcius degree
* protected by data_lock
*/
int temperature;
};
#ifdef CONFIG_THERMAL
int ath10k_thermal_register(struct ath10k *ar);
void ath10k_thermal_unregister(struct ath10k *ar);
void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature);
#else
static inline int ath10k_thermal_register(struct ath10k *ar)
{
return 0;
}
static inline void ath10k_thermal_unregister(struct ath10k *ar)
{
}
static inline void ath10k_thermal_event_temperature(struct ath10k *ar,
int temperature)
{
}
#endif
#endif /* _THERMAL_ */

View File

@ -0,0 +1,860 @@
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2014 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* 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 _WMI_OPS_H_
#define _WMI_OPS_H_
struct ath10k;
struct sk_buff;
struct wmi_ops {
void (*rx)(struct ath10k *ar, struct sk_buff *skb);
void (*map_svc)(const __le32 *in, unsigned long *out, size_t len);
int (*pull_scan)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_scan_ev_arg *arg);
int (*pull_mgmt_rx)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_mgmt_rx_ev_arg *arg);
int (*pull_ch_info)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_ch_info_ev_arg *arg);
int (*pull_vdev_start)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_vdev_start_ev_arg *arg);
int (*pull_peer_kick)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_peer_kick_ev_arg *arg);
int (*pull_swba)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_swba_ev_arg *arg);
int (*pull_phyerr)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_ev_arg *arg);
int (*pull_svc_rdy)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_svc_rdy_ev_arg *arg);
int (*pull_rdy)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_rdy_ev_arg *arg);
int (*pull_fw_stats)(struct ath10k *ar, struct sk_buff *skb,
struct ath10k_fw_stats *stats);
struct sk_buff *(*gen_pdev_suspend)(struct ath10k *ar, u32 suspend_opt);
struct sk_buff *(*gen_pdev_resume)(struct ath10k *ar);
struct sk_buff *(*gen_pdev_set_rd)(struct ath10k *ar, u16 rd, u16 rd2g,
u16 rd5g, u16 ctl2g, u16 ctl5g,
enum wmi_dfs_region dfs_reg);
struct sk_buff *(*gen_pdev_set_param)(struct ath10k *ar, u32 id,
u32 value);
struct sk_buff *(*gen_init)(struct ath10k *ar);
struct sk_buff *(*gen_start_scan)(struct ath10k *ar,
const struct wmi_start_scan_arg *arg);
struct sk_buff *(*gen_stop_scan)(struct ath10k *ar,
const struct wmi_stop_scan_arg *arg);
struct sk_buff *(*gen_vdev_create)(struct ath10k *ar, u32 vdev_id,
enum wmi_vdev_type type,
enum wmi_vdev_subtype subtype,
const u8 macaddr[ETH_ALEN]);
struct sk_buff *(*gen_vdev_delete)(struct ath10k *ar, u32 vdev_id);
struct sk_buff *(*gen_vdev_start)(struct ath10k *ar,
const struct wmi_vdev_start_request_arg *arg,
bool restart);
struct sk_buff *(*gen_vdev_stop)(struct ath10k *ar, u32 vdev_id);
struct sk_buff *(*gen_vdev_up)(struct ath10k *ar, u32 vdev_id, u32 aid,
const u8 *bssid);
struct sk_buff *(*gen_vdev_down)(struct ath10k *ar, u32 vdev_id);
struct sk_buff *(*gen_vdev_set_param)(struct ath10k *ar, u32 vdev_id,
u32 param_id, u32 param_value);
struct sk_buff *(*gen_vdev_install_key)(struct ath10k *ar,
const struct wmi_vdev_install_key_arg *arg);
struct sk_buff *(*gen_vdev_spectral_conf)(struct ath10k *ar,
const struct wmi_vdev_spectral_conf_arg *arg);
struct sk_buff *(*gen_vdev_spectral_enable)(struct ath10k *ar, u32 vdev_id,
u32 trigger, u32 enable);
struct sk_buff *(*gen_peer_create)(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN]);
struct sk_buff *(*gen_peer_delete)(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN]);
struct sk_buff *(*gen_peer_flush)(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN],
u32 tid_bitmap);
struct sk_buff *(*gen_peer_set_param)(struct ath10k *ar, u32 vdev_id,
const u8 *peer_addr,
enum wmi_peer_param param_id,
u32 param_value);
struct sk_buff *(*gen_peer_assoc)(struct ath10k *ar,
const struct wmi_peer_assoc_complete_arg *arg);
struct sk_buff *(*gen_set_psmode)(struct ath10k *ar, u32 vdev_id,
enum wmi_sta_ps_mode psmode);
struct sk_buff *(*gen_set_sta_ps)(struct ath10k *ar, u32 vdev_id,
enum wmi_sta_powersave_param param_id,
u32 value);
struct sk_buff *(*gen_set_ap_ps)(struct ath10k *ar, u32 vdev_id,
const u8 *mac,
enum wmi_ap_ps_peer_param param_id,
u32 value);
struct sk_buff *(*gen_scan_chan_list)(struct ath10k *ar,
const struct wmi_scan_chan_list_arg *arg);
struct sk_buff *(*gen_beacon_dma)(struct ath10k_vif *arvif);
struct sk_buff *(*gen_pdev_set_wmm)(struct ath10k *ar,
const struct wmi_pdev_set_wmm_params_arg *arg);
struct sk_buff *(*gen_request_stats)(struct ath10k *ar,
enum wmi_stats_id stats_id);
struct sk_buff *(*gen_force_fw_hang)(struct ath10k *ar,
enum wmi_force_fw_hang_type type,
u32 delay_ms);
struct sk_buff *(*gen_mgmt_tx)(struct ath10k *ar, struct sk_buff *skb);
struct sk_buff *(*gen_dbglog_cfg)(struct ath10k *ar, u32 module_enable);
struct sk_buff *(*gen_pktlog_enable)(struct ath10k *ar, u32 filter);
struct sk_buff *(*gen_pktlog_disable)(struct ath10k *ar);
struct sk_buff *(*gen_pdev_set_quiet_mode)(struct ath10k *ar,
u32 period, u32 duration,
u32 next_offset,
u32 enabled);
struct sk_buff *(*gen_pdev_get_temperature)(struct ath10k *ar);
};
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
static inline int
ath10k_wmi_rx(struct ath10k *ar, struct sk_buff *skb)
{
if (WARN_ON_ONCE(!ar->wmi.ops->rx))
return -EOPNOTSUPP;
ar->wmi.ops->rx(ar, skb);
return 0;
}
static inline int
ath10k_wmi_map_svc(struct ath10k *ar, const __le32 *in, unsigned long *out,
size_t len)
{
if (!ar->wmi.ops->map_svc)
return -EOPNOTSUPP;
ar->wmi.ops->map_svc(in, out, len);
return 0;
}
static inline int
ath10k_wmi_pull_scan(struct ath10k *ar, struct sk_buff *skb,
struct wmi_scan_ev_arg *arg)
{
if (!ar->wmi.ops->pull_scan)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_scan(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_mgmt_rx(struct ath10k *ar, struct sk_buff *skb,
struct wmi_mgmt_rx_ev_arg *arg)
{
if (!ar->wmi.ops->pull_mgmt_rx)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_mgmt_rx(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_ch_info(struct ath10k *ar, struct sk_buff *skb,
struct wmi_ch_info_ev_arg *arg)
{
if (!ar->wmi.ops->pull_ch_info)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_ch_info(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_vdev_start(struct ath10k *ar, struct sk_buff *skb,
struct wmi_vdev_start_ev_arg *arg)
{
if (!ar->wmi.ops->pull_vdev_start)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_vdev_start(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_peer_kick(struct ath10k *ar, struct sk_buff *skb,
struct wmi_peer_kick_ev_arg *arg)
{
if (!ar->wmi.ops->pull_peer_kick)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_peer_kick(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_swba(struct ath10k *ar, struct sk_buff *skb,
struct wmi_swba_ev_arg *arg)
{
if (!ar->wmi.ops->pull_swba)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_swba(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_phyerr(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_ev_arg *arg)
{
if (!ar->wmi.ops->pull_phyerr)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_phyerr(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_svc_rdy(struct ath10k *ar, struct sk_buff *skb,
struct wmi_svc_rdy_ev_arg *arg)
{
if (!ar->wmi.ops->pull_svc_rdy)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_svc_rdy(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_rdy(struct ath10k *ar, struct sk_buff *skb,
struct wmi_rdy_ev_arg *arg)
{
if (!ar->wmi.ops->pull_rdy)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_rdy(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
struct ath10k_fw_stats *stats)
{
if (!ar->wmi.ops->pull_fw_stats)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_fw_stats(ar, skb, stats);
}
static inline int
ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
struct sk_buff *skb;
int ret;
if (!ar->wmi.ops->gen_mgmt_tx)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_mgmt_tx(ar, msdu);
if (IS_ERR(skb))
return PTR_ERR(skb);
ret = ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->mgmt_tx_cmdid);
if (ret)
return ret;
/* FIXME There's no ACK event for Management Tx. This probably
* shouldn't be called here either. */
info->flags |= IEEE80211_TX_STAT_ACK;
ieee80211_tx_status_irqsafe(ar->hw, msdu);
return 0;
}
static inline int
ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g,
u16 ctl2g, u16 ctl5g,
enum wmi_dfs_region dfs_reg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_set_rd)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_set_rd(ar, rd, rd2g, rd5g, ctl2g, ctl5g,
dfs_reg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->pdev_set_regdomain_cmdid);
}
static inline int
ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_suspend)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_suspend(ar, suspend_opt);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_suspend_cmdid);
}
static inline int
ath10k_wmi_pdev_resume_target(struct ath10k *ar)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_resume)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_resume(ar);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_resume_cmdid);
}
static inline int
ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_set_param)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_set_param(ar, id, value);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid);
}
static inline int
ath10k_wmi_cmd_init(struct ath10k *ar)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_init)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_init(ar);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->init_cmdid);
}
static inline int
ath10k_wmi_start_scan(struct ath10k *ar,
const struct wmi_start_scan_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_start_scan)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_start_scan(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->start_scan_cmdid);
}
static inline int
ath10k_wmi_stop_scan(struct ath10k *ar, const struct wmi_stop_scan_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_stop_scan)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_stop_scan(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->stop_scan_cmdid);
}
static inline int
ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id,
enum wmi_vdev_type type,
enum wmi_vdev_subtype subtype,
const u8 macaddr[ETH_ALEN])
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_create)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_create(ar, vdev_id, type, subtype, macaddr);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_create_cmdid);
}
static inline int
ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_delete)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_delete(ar, vdev_id);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_delete_cmdid);
}
static inline int
ath10k_wmi_vdev_start(struct ath10k *ar,
const struct wmi_vdev_start_request_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_start)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_start(ar, arg, false);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->vdev_start_request_cmdid);
}
static inline int
ath10k_wmi_vdev_restart(struct ath10k *ar,
const struct wmi_vdev_start_request_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_start)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_start(ar, arg, true);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->vdev_restart_request_cmdid);
}
static inline int
ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_stop)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_stop(ar, vdev_id);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_stop_cmdid);
}
static inline int
ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_up)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_up(ar, vdev_id, aid, bssid);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_up_cmdid);
}
static inline int
ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_down)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_down(ar, vdev_id);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_down_cmdid);
}
static inline int
ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, u32 param_id,
u32 param_value)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_set_param)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_set_param(ar, vdev_id, param_id,
param_value);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_set_param_cmdid);
}
static inline int
ath10k_wmi_vdev_install_key(struct ath10k *ar,
const struct wmi_vdev_install_key_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_install_key)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_install_key(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->vdev_install_key_cmdid);
}
static inline int
ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
const struct wmi_vdev_spectral_conf_arg *arg)
{
struct sk_buff *skb;
u32 cmd_id;
skb = ar->wmi.ops->gen_vdev_spectral_conf(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
cmd_id = ar->wmi.cmd->vdev_spectral_scan_configure_cmdid;
return ath10k_wmi_cmd_send(ar, skb, cmd_id);
}
static inline int
ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
u32 enable)
{
struct sk_buff *skb;
u32 cmd_id;
skb = ar->wmi.ops->gen_vdev_spectral_enable(ar, vdev_id, trigger,
enable);
if (IS_ERR(skb))
return PTR_ERR(skb);
cmd_id = ar->wmi.cmd->vdev_spectral_scan_enable_cmdid;
return ath10k_wmi_cmd_send(ar, skb, cmd_id);
}
static inline int
ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN])
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_peer_create)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_peer_create(ar, vdev_id, peer_addr);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_create_cmdid);
}
static inline int
ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN])
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_peer_delete)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_peer_delete(ar, vdev_id, peer_addr);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_delete_cmdid);
}
static inline int
ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN], u32 tid_bitmap)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_peer_flush)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_peer_flush(ar, vdev_id, peer_addr, tid_bitmap);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_flush_tids_cmdid);
}
static inline int
ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, const u8 *peer_addr,
enum wmi_peer_param param_id, u32 param_value)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_peer_set_param)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_peer_set_param(ar, vdev_id, peer_addr, param_id,
param_value);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_set_param_cmdid);
}
static inline int
ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id,
enum wmi_sta_ps_mode psmode)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_set_psmode)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_set_psmode(ar, vdev_id, psmode);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->sta_powersave_mode_cmdid);
}
static inline int
ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id,
enum wmi_sta_powersave_param param_id, u32 value)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_set_sta_ps)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_set_sta_ps(ar, vdev_id, param_id, value);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->sta_powersave_param_cmdid);
}
static inline int
ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac,
enum wmi_ap_ps_peer_param param_id, u32 value)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_set_ap_ps)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_set_ap_ps(ar, vdev_id, mac, param_id, value);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->ap_ps_peer_param_cmdid);
}
static inline int
ath10k_wmi_scan_chan_list(struct ath10k *ar,
const struct wmi_scan_chan_list_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_scan_chan_list)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_scan_chan_list(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid);
}
static inline int
ath10k_wmi_peer_assoc(struct ath10k *ar,
const struct wmi_peer_assoc_complete_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_peer_assoc)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_peer_assoc(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid);
}
static inline int
ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
struct sk_buff *skb;
int ret;
if (!ar->wmi.ops->gen_beacon_dma)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_beacon_dma(arvif);
if (IS_ERR(skb))
return PTR_ERR(skb);
ret = ath10k_wmi_cmd_send_nowait(ar, skb,
ar->wmi.cmd->pdev_send_bcn_cmdid);
if (ret) {
dev_kfree_skb(skb);
return ret;
}
return 0;
}
static inline int
ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
const struct wmi_pdev_set_wmm_params_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_set_wmm)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_set_wmm(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->pdev_set_wmm_params_cmdid);
}
static inline int
ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_request_stats)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_request_stats(ar, stats_id);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->request_stats_cmdid);
}
static inline int
ath10k_wmi_force_fw_hang(struct ath10k *ar,
enum wmi_force_fw_hang_type type, u32 delay_ms)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_force_fw_hang)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_force_fw_hang(ar, type, delay_ms);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid);
}
static inline int
ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_dbglog_cfg)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_dbglog_cfg(ar, module_enable);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid);
}
static inline int
ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 filter)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pktlog_enable)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pktlog_enable(ar, filter);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_pktlog_enable_cmdid);
}
static inline int
ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pktlog_disable)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pktlog_disable(ar);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->pdev_pktlog_disable_cmdid);
}
static inline int
ath10k_wmi_pdev_set_quiet_mode(struct ath10k *ar, u32 period, u32 duration,
u32 next_offset, u32 enabled)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_set_quiet_mode)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_set_quiet_mode(ar, period, duration,
next_offset, enabled);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->pdev_set_quiet_mode_cmdid);
}
static inline int
ath10k_wmi_pdev_get_temperature(struct ath10k *ar)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_get_temperature)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_get_temperature(ar);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->pdev_get_temperature_cmdid);
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -109,6 +109,45 @@ enum wmi_service {
WMI_SERVICE_BURST,
WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT,
WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT,
WMI_SERVICE_ROAM_SCAN_OFFLOAD,
WMI_SERVICE_AP_PS_DETECT_OUT_OF_SYNC,
WMI_SERVICE_EARLY_RX,
WMI_SERVICE_STA_SMPS,
WMI_SERVICE_FWTEST,
WMI_SERVICE_STA_WMMAC,
WMI_SERVICE_TDLS,
WMI_SERVICE_MCC_BCN_INTERVAL_CHANGE,
WMI_SERVICE_ADAPTIVE_OCS,
WMI_SERVICE_BA_SSN_SUPPORT,
WMI_SERVICE_FILTER_IPSEC_NATKEEPALIVE,
WMI_SERVICE_WLAN_HB,
WMI_SERVICE_LTE_ANT_SHARE_SUPPORT,
WMI_SERVICE_BATCH_SCAN,
WMI_SERVICE_QPOWER,
WMI_SERVICE_PLMREQ,
WMI_SERVICE_THERMAL_MGMT,
WMI_SERVICE_RMC,
WMI_SERVICE_MHF_OFFLOAD,
WMI_SERVICE_COEX_SAR,
WMI_SERVICE_BCN_TXRATE_OVERRIDE,
WMI_SERVICE_NAN,
WMI_SERVICE_L1SS_STAT,
WMI_SERVICE_ESTIMATE_LINKSPEED,
WMI_SERVICE_OBSS_SCAN,
WMI_SERVICE_TDLS_OFFCHAN,
WMI_SERVICE_TDLS_UAPSD_BUFFER_STA,
WMI_SERVICE_TDLS_UAPSD_SLEEP_STA,
WMI_SERVICE_IBSS_PWRSAVE,
WMI_SERVICE_LPASS,
WMI_SERVICE_EXTSCAN,
WMI_SERVICE_D0WOW,
WMI_SERVICE_HSOFFLOAD,
WMI_SERVICE_ROAM_HO_OFFLOAD,
WMI_SERVICE_RX_FULL_REORDER,
WMI_SERVICE_DHCP_OFFLOAD,
WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT,
WMI_SERVICE_MDNS_OFFLOAD,
WMI_SERVICE_SAP_AUTH_OFFLOAD,
/* keep last */
WMI_SERVICE_MAX,
@ -215,6 +254,45 @@ static inline char *wmi_service_name(int service_id)
SVCSTR(WMI_SERVICE_BURST);
SVCSTR(WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT);
SVCSTR(WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT);
SVCSTR(WMI_SERVICE_ROAM_SCAN_OFFLOAD);
SVCSTR(WMI_SERVICE_AP_PS_DETECT_OUT_OF_SYNC);
SVCSTR(WMI_SERVICE_EARLY_RX);
SVCSTR(WMI_SERVICE_STA_SMPS);
SVCSTR(WMI_SERVICE_FWTEST);
SVCSTR(WMI_SERVICE_STA_WMMAC);
SVCSTR(WMI_SERVICE_TDLS);
SVCSTR(WMI_SERVICE_MCC_BCN_INTERVAL_CHANGE);
SVCSTR(WMI_SERVICE_ADAPTIVE_OCS);
SVCSTR(WMI_SERVICE_BA_SSN_SUPPORT);
SVCSTR(WMI_SERVICE_FILTER_IPSEC_NATKEEPALIVE);
SVCSTR(WMI_SERVICE_WLAN_HB);
SVCSTR(WMI_SERVICE_LTE_ANT_SHARE_SUPPORT);
SVCSTR(WMI_SERVICE_BATCH_SCAN);
SVCSTR(WMI_SERVICE_QPOWER);
SVCSTR(WMI_SERVICE_PLMREQ);
SVCSTR(WMI_SERVICE_THERMAL_MGMT);
SVCSTR(WMI_SERVICE_RMC);
SVCSTR(WMI_SERVICE_MHF_OFFLOAD);
SVCSTR(WMI_SERVICE_COEX_SAR);
SVCSTR(WMI_SERVICE_BCN_TXRATE_OVERRIDE);
SVCSTR(WMI_SERVICE_NAN);
SVCSTR(WMI_SERVICE_L1SS_STAT);
SVCSTR(WMI_SERVICE_ESTIMATE_LINKSPEED);
SVCSTR(WMI_SERVICE_OBSS_SCAN);
SVCSTR(WMI_SERVICE_TDLS_OFFCHAN);
SVCSTR(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA);
SVCSTR(WMI_SERVICE_TDLS_UAPSD_SLEEP_STA);
SVCSTR(WMI_SERVICE_IBSS_PWRSAVE);
SVCSTR(WMI_SERVICE_LPASS);
SVCSTR(WMI_SERVICE_EXTSCAN);
SVCSTR(WMI_SERVICE_D0WOW);
SVCSTR(WMI_SERVICE_HSOFFLOAD);
SVCSTR(WMI_SERVICE_ROAM_HO_OFFLOAD);
SVCSTR(WMI_SERVICE_RX_FULL_REORDER);
SVCSTR(WMI_SERVICE_DHCP_OFFLOAD);
SVCSTR(WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT);
SVCSTR(WMI_SERVICE_MDNS_OFFLOAD);
SVCSTR(WMI_SERVICE_SAP_AUTH_OFFLOAD);
default:
return NULL;
}
@ -472,6 +550,7 @@ struct wmi_cmd_map {
u32 force_fw_hang_cmdid;
u32 gpio_config_cmdid;
u32 gpio_output_cmdid;
u32 pdev_get_temperature_cmdid;
};
/*
@ -1076,6 +1155,11 @@ enum wmi_10_2_cmd_id {
WMI_10_2_PDEV_SET_MIMOGAIN_TABLE_CMDID,
WMI_10_2_PDEV_RATEPWR_TABLE_CMDID,
WMI_10_2_PDEV_RATEPWR_CHAINMSK_TABLE_CMDID,
WMI_10_2_PDEV_GET_INFO,
WMI_10_2_VDEV_GET_INFO,
WMI_10_2_VDEV_ATF_REQUEST_CMDID,
WMI_10_2_PEER_ATF_REQUEST_CMDID,
WMI_10_2_PDEV_GET_TEMPERATURE_CMDID,
WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1,
};
@ -1117,6 +1201,8 @@ enum wmi_10_2_event_id {
WMI_10_2_MCAST_BUF_RELEASE_EVENTID,
WMI_10_2_MCAST_LIST_AGEOUT_EVENTID,
WMI_10_2_WDS_PEER_EVENTID,
WMI_10_2_PEER_STA_PS_STATECHG_EVENTID,
WMI_10_2_PDEV_TEMPERATURE_EVENTID,
WMI_10_2_PDEV_UTF_EVENTID = WMI_10_2_END_EVENTID - 1,
};
@ -1862,6 +1948,11 @@ struct wmi_resource_config_10x {
__le32 max_frag_entries;
} __packed;
enum wmi_10_2_feature_mask {
WMI_10_2_RX_BATCH_MODE = BIT(0),
WMI_10_2_ATF_CONFIG = BIT(1),
};
struct wmi_resource_config_10_2 {
struct wmi_resource_config_10x common;
__le32 max_peer_ext_stats;
@ -1870,7 +1961,7 @@ struct wmi_resource_config_10_2 {
__le32 be_min_free;
__le32 vi_min_free;
__le32 vo_min_free;
__le32 rx_batchmode; /* 0-disable, 1-enable */
__le32 feature_mask;
} __packed;
#define NUM_UNITS_IS_NUM_VDEVS 0x1
@ -2505,6 +2596,7 @@ struct wmi_pdev_param_map {
u32 fast_channel_reset;
u32 burst_dur;
u32 burst_enable;
u32 cal_period;
};
#define WMI_PDEV_PARAM_UNSUPPORTED 0
@ -2715,6 +2807,9 @@ enum wmi_10x_pdev_param {
WMI_10X_PDEV_PARAM_SET_MCAST2UCAST_MODE,
WMI_10X_PDEV_PARAM_SET_MCAST2UCAST_BUFFER,
WMI_10X_PDEV_PARAM_REMOVE_MCAST2UCAST_BUFFER,
WMI_10X_PDEV_PARAM_PEER_STA_PS_STATECHG_ENABLE,
WMI_10X_PDEV_PARAM_RTS_FIXED_RATE,
WMI_10X_PDEV_PARAM_CAL_PERIOD
};
struct wmi_pdev_set_param_cmd {
@ -2722,6 +2817,9 @@ struct wmi_pdev_set_param_cmd {
__le32 param_value;
} __packed;
/* valid period is 1 ~ 60000ms, unit in millisecond */
#define WMI_PDEV_PARAM_CAL_PERIOD_MAX 60000
struct wmi_pdev_get_tpc_config_cmd {
/* parameter */
__le32 param;
@ -3930,6 +4028,13 @@ enum wmi_sta_ps_param_pspoll_count {
* Values greater than 0 indicate the maximum numer of PS-Poll frames
* FW will send before waking up.
*/
/* When u-APSD is enabled the firmware will be very reluctant to exit
* STA PS. This could result in very poor Rx performance with STA doing
* PS-Poll for each and every buffered frame. This value is a bit
* arbitrary.
*/
WMI_STA_PS_PSPOLL_COUNT_UAPSD = 3,
};
/*
@ -4120,7 +4225,7 @@ struct wmi_bcn_info {
struct wmi_host_swba_event {
__le32 vdev_map;
struct wmi_bcn_info bcn_info[1];
struct wmi_bcn_info bcn_info[0];
} __packed;
#define WMI_MAX_AP_VDEV 16
@ -4567,6 +4672,58 @@ struct wmi_dbglog_cfg_cmd {
#define WMI_MAX_MEM_REQS 16
struct wmi_scan_ev_arg {
__le32 event_type; /* %WMI_SCAN_EVENT_ */
__le32 reason; /* %WMI_SCAN_REASON_ */
__le32 channel_freq; /* only valid for WMI_SCAN_EVENT_FOREIGN_CHANNEL */
__le32 scan_req_id;
__le32 scan_id;
__le32 vdev_id;
};
struct wmi_mgmt_rx_ev_arg {
__le32 channel;
__le32 snr;
__le32 rate;
__le32 phy_mode;
__le32 buf_len;
__le32 status; /* %WMI_RX_STATUS_ */
};
struct wmi_ch_info_ev_arg {
__le32 err_code;
__le32 freq;
__le32 cmd_flags;
__le32 noise_floor;
__le32 rx_clear_count;
__le32 cycle_count;
};
struct wmi_vdev_start_ev_arg {
__le32 vdev_id;
__le32 req_id;
__le32 resp_type; /* %WMI_VDEV_RESP_ */
__le32 status;
};
struct wmi_peer_kick_ev_arg {
const u8 *mac_addr;
};
struct wmi_swba_ev_arg {
__le32 vdev_map;
const struct wmi_tim_info *tim_info[WMI_MAX_AP_VDEV];
const struct wmi_p2p_noa_info *noa_info[WMI_MAX_AP_VDEV];
};
struct wmi_phyerr_ev_arg {
__le32 num_phyerrs;
__le32 tsf_l32;
__le32 tsf_u32;
__le32 buf_len;
const struct wmi_phyerr *phyerrs;
};
struct wmi_svc_rdy_ev_arg {
__le32 min_tx_power;
__le32 max_tx_power;
@ -4574,6 +4731,7 @@ struct wmi_svc_rdy_ev_arg {
__le32 vht_cap;
__le32 sw_ver0;
__le32 sw_ver1;
__le32 fw_build;
__le32 phy_capab;
__le32 num_rf_chains;
__le32 eeprom_rd;
@ -4583,83 +4741,93 @@ struct wmi_svc_rdy_ev_arg {
const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
};
struct wmi_rdy_ev_arg {
__le32 sw_version;
__le32 abi_version;
__le32 status;
const u8 *mac_addr;
};
struct wmi_pdev_temperature_event {
/* temperature value in Celcius degree */
__le32 temperature;
} __packed;
struct ath10k;
struct ath10k_vif;
struct ath10k_fw_stats;
struct ath10k_fw_stats_pdev;
struct ath10k_fw_stats_peer;
int ath10k_wmi_attach(struct ath10k *ar);
void ath10k_wmi_detach(struct ath10k *ar);
int ath10k_wmi_wait_for_service_ready(struct ath10k *ar);
int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
int ath10k_wmi_connect(struct ath10k *ar);
struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);
int ath10k_wmi_pdev_resume_target(struct ath10k *ar);
int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g,
u16 rd5g, u16 ctl2g, u16 ctl5g,
enum wmi_dfs_region dfs_reg);
int ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value);
int ath10k_wmi_cmd_init(struct ath10k *ar);
int ath10k_wmi_start_scan(struct ath10k *ar, const struct wmi_start_scan_arg *);
int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
u32 cmd_id);
void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *);
int ath10k_wmi_stop_scan(struct ath10k *ar,
const struct wmi_stop_scan_arg *arg);
int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id,
enum wmi_vdev_type type,
enum wmi_vdev_subtype subtype,
const u8 macaddr[ETH_ALEN]);
int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id);
int ath10k_wmi_vdev_start(struct ath10k *ar,
const struct wmi_vdev_start_request_arg *);
int ath10k_wmi_vdev_restart(struct ath10k *ar,
const struct wmi_vdev_start_request_arg *);
int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id);
int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid,
const u8 *bssid);
int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id);
int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id,
u32 param_id, u32 param_value);
int ath10k_wmi_vdev_install_key(struct ath10k *ar,
const struct wmi_vdev_install_key_arg *arg);
int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
const struct wmi_vdev_spectral_conf_arg *arg);
int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
u32 enable);
int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN]);
int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN]);
int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN], u32 tid_bitmap);
int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id,
const u8 *peer_addr,
enum wmi_peer_param param_id, u32 param_value);
int ath10k_wmi_peer_assoc(struct ath10k *ar,
const struct wmi_peer_assoc_complete_arg *arg);
int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id,
enum wmi_sta_ps_mode psmode);
int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id,
enum wmi_sta_powersave_param param_id,
u32 value);
int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac,
enum wmi_ap_ps_peer_param param_id, u32 value);
int ath10k_wmi_scan_chan_list(struct ath10k *ar,
const struct wmi_scan_chan_list_arg *arg);
int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif);
int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
const struct wmi_pdev_set_wmm_params_arg *arg);
int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id);
int ath10k_wmi_force_fw_hang(struct ath10k *ar,
enum wmi_force_fw_hang_type type, u32 delay_ms);
int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable);
int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
struct ath10k_fw_stats *stats);
int ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 ev_list);
int ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar);
void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src,
struct ath10k_fw_stats_pdev *dst);
void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src,
struct ath10k_fw_stats_peer *dst);
void ath10k_wmi_put_host_mem_chunks(struct ath10k *ar,
struct wmi_host_mem_chunks *chunks);
void ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn,
const struct wmi_start_scan_arg *arg);
void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params,
const struct wmi_wmm_params_arg *arg);
void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
const struct wmi_channel_arg *arg);
int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg);
int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_vdev_stopped(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_dfs(struct ath10k *ar,
const struct wmi_phyerr *phyerr, u64 tsf);
void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
u64 tsf);
void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_profile_match(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_debug_print(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_wlan_profile_data(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_rtt_measurement_report(struct ath10k *ar,
struct sk_buff *skb);
void ath10k_wmi_event_tsf_measurement_report(struct ath10k *ar,
struct sk_buff *skb);
void ath10k_wmi_event_rtt_error_report(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_wow_wakeup_host(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_dcs_interference(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_gtk_offload_status(struct ath10k *ar,
struct sk_buff *skb);
void ath10k_wmi_event_gtk_rekey_fail(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_delba_complete(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_addba_complete(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar,
struct sk_buff *skb);
void ath10k_wmi_event_inst_rssi_stats(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_vdev_standby_req(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb);
#endif /* _WMI_H_ */