Merge remote-tracking branch 'remotes/origin/tmp-896bb812' into HEAD
Current ATH10k driver snapshot is very old, up merge ATH10k project to enable WCN3990 chipset in msm4.4 tree. * remotes/origin/tmp-896bb812: ath10k: cache calibration data when the core is stopped ath10k: Ignore SWBA event for a vif if its marked for no beacon ath10k: fix error return code in ahb ath10k: support up to 64 vdevs ath10k: document cycle count related counters ath10k: fix typo in logging message ath10k: fix rfc1042 header retrieval in QCA4019 with eth decap mode ath10k: do not check if reset is NULL ath10k: use devm_reset_control_get() instead of reset_control_get() ath10k: use devm_clk_get() instead of clk_get() ath10k: spelling and miscellaneous neatening ath10k: remove 4-addr padding related hw_param configuration ath10k: properly remove padding from the start of rx payload ath10k: add provision for Rx descriptor abstraction ath10k: move ath10k_hw_params definition to hw.h ath10k: improve logging message ath10k: enable peer stats by default ath10k: remove unused variable ar_pci ath10k: fix memory leak on caldata on error exit path ath10k: fix reporting channel survey data ath10k: remove unnecessary error code assignment ath10k: fix throughput regression in multi client mode ath10k: implement NAPI support ath10k: fix spelling mistake "montior" -> "monitor" ath10k: Fix broken NULL func data frame status for 10.4 ath10k: replace config_enabled() with IS_REACHABLE() ath10k: Added support for extended dbglog module id for 10.4 ath10k: use complete() instead complete_all() ath10k: fix sending frame in management path in push txq logic ath10k: improve wake_tx_queue ops performance ath10k: suppress warnings when getting wmi WDS peer event id ath10k: fix group privacy action frame decryption for qca4019 ath10k: hide kernel addresses from logs using %pK format specifier ath10k: Add WMI_SERVICE_PERIODIC_CHAN_STAT_SUPPORT wmi service ath10k: fix spurious tx/rx during boot ath10k: add wmi command barrier utility ath10k: implement wmi echo event ath10k: implement wmi echo command ath10k: add testmode support for 10.4 firmware ath10k: handle testmode events for 10.2 and 10.4 based firmware ath10k: move firmware_swap_code_seg_info to ath10k_fw_file ath10k: Remove driver log suggesting QCA9887 support is experimental ath10k: fix get rx_status from htt context tree-wide: replace config_enabled() with IS_ENABLED() ath10k: disable wake_tx_queue for older devices ath10k: fix possible wrong rx_busy time reporting in QCA4019 ath10k: replace warning with an error message if HTT op version is unset ath10k: enable support for QCA9888 ath10k: remove unused member in ath10k_hw_regs ath10k: Clean up peer when sta goes away. ath10k: Add WARN_ON if we over-write peer-map pointer. ath10k: remove extra space on ath10k_update_channel_list ath10k: simplify pktlog htt event processing ath10k: remove unused <linux/semaphore.h> ath10k: ensure peer_map references are cleaned up ath10k: ensure txrx-compl-task is stopped when cleaning htt-tx ath10k: remove debugfs support for Per STA total rx duration ath10k: add support for ath10k_sta_statistics support ath10k: fix 10.4 extended peer stats update mac80211: Add support for beacon report radio measurement ath10k: fix some typo in spectral code commments ath10k: disable TX_STBC for tx chainmask of 1 ath10k: enable beacon loss detection support for 10.4 ath10k: fix potential null dereference bugs ath10k: remove unneccessary WARN_ON_ONCE in rx during ACS ath10k: fix crash during card removal ath10k: fix deadlock while processing rx_in_ord_ind ath10k: fix cycle counter wraparound handling for QCA4019 ath10k: define an enum to enable cycle counter wraparound logic ath10k: fix CCK h/w rates for QCA99X0 and newer chipsets ath10k: remove duplicate and unused rx rate flags ath10k: fix some of the macro definitions of HTT_RX_IND message ath10k: fix crash related to printing features ath10k: add board data download from target ath10k: add QCA9887 chipset support ath10k: fix deadlock when peer cannot be created ath10k: enable ipq4019 device probe in ahb module ath10k: add pdev param support to enable/disable btcoex ath10k: add new ATH10K_FW_FEATURE_BTCOEX_PARAM ath10k: update module description ath10k: remove unused phy_mode_to_band ath10k: fix operating irq mode for ahb device ath10k: fix error while writing 'simulate_fw_crash' debugfs ath10k: fix diag_read to collect data for larger memory ath10k: fix legacy rate packet debug messages ath10k: reduce warning messages during rx without proper channel context ath10k: improve tx scheduling ath10k: enable support for QCA9984 ath10k: define rx_ppdu_end for QCA9984 ath10k: clean up growing hw checks during safe and full reset ath10k: move rx_location_info out of struct rx_pkt_end ath10k: Fix survey reporting with QCA4019 ath10k: suppress warnings when getting wmi peer_rate_code_list event ath10k: release pre_cal_file while unloading driver ath10k: update bss channel survey information ath10k: handle pdev_chan_info wmi event ath10k: implement wmi_pdev_bss_chan_info_request ath10k: add pdev bss channel info wmi definitions ath10k: move spectral related structures under ath10k debugfs ath10k: remove VHT capabilities from 2.4GHz ath10k: fix a typo in ath10k_start() ath10k: add max_tx_power for QCA6174 WLAN.RM.2.0 firmware ath10k: remove enum ath10k_swap_code_seg_bin_type ath10k: switch testmode to use ath10k_core_fetch_firmware_api_n() ath10k: move htt_op_version to struct ath10k_fw_file ath10k: move wmi_op_version to struct ath10k_fw_file ath10k: move fw_features to struct ath10k_fw_file ath10k: move fw_version inside struct ath10k_fw_file ath10k: refactor firmware images to struct ath10k_fw_components ath10k: remove deprecated firmware API 1 support ath10k: add dynamic tx mode switch config support for qca4019 ath10k: add some sanity checks to peer_map_event() functions ath10k: fix return value for btcoex and peer stats debugfs ath10k: fix parenthesis alignment ath10k: prefer ether_addr_copy() over memcpy() ath10k: prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp() ath10k: prefer kernel type 'u64' over 'u_int64_t' ath10k: fix checkpatch warnings related to spaces ath10k: remove MSI range support ath10k: enable set_tsf vdev command to WMI 10.4 ath10k: update 10.4 WMI vdev parameters ath10k: add a support of set_tsf on vdev interface ath10k: Document alloc_frag_desc_for_data_pkt config option. cfg80211: remove enum ieee80211_band ath10k: fix unconditional num_mpdus_ready subtraction ath10k: remove unnecessary warning for probe response drops ath10k: fix calibration init sequence of qca99x0 mac80211: allow not sending MIC up from driver for HW crypto ath10k: parse Rx MAC timestamp in mgmt frame for FW 10.4 ath10k: combine txrx and replenish task ath10k: reuse copy engine 5 (htt rx) descriptors ath10k: cleanup copy engine receive next completion ath10k: register ath10k_htt_htc_t2h_msg_handler ath10k: speedup htt rx descriptor processing for rx_ind ath10k: cleanup amsdu processing for rx indication ath10k: remove unused fw_desc processing ath10k: copy tx fetch indication message ath10k: speedup htt rx descriptor processing for tx completion ath10k: enable parsing per station rx duration for 10.4 ath10k: introduce Extended Resource Config support for 10.4 ath10k: enable debugfs provision to enable Peer Stats feature ath10k: incorporate qca4019 cal data download sequence ath10k: move cal data len to hw_params ath10k: pass cal data location as an argument to ath10k_download_cal_{file|dt} ath10k: fix null deref if device crashes early ath10k: fix pull-push tx threshold handling ath10k: fix tx hang ath10k: advertise force AP scan feature ath10k: free cached fw bin contents when get board id fails ath10k: move mgmt descriptor limit handle under mgmt_tx ath10k: handle channel change htt event ath10k: set MAC timestamp in management Rx frame ath10k: deliver mgmt frames from htt to monitor vifs only ath10k: change htt tx desc/qcache peer limit config ath10k: fix HTT Tx CE ring size ath10k: implement push-pull tx ath10k: keep track of queue depth per txq ath10k: store txq in skb_cb ath10k: implement updating shared htt txq state ath10k: implement wake_tx_queue ath10k: add new htt message generation/parsing logic ath10k: add fast peer_map lookup ath10k: maintain peer_id for each sta and vif ath10k: refactor tx pending management ath10k: unify txpath decision ath10k: refactor tx code ath10k: fix sanity check on enabling btcoex via debugfs ath10k: reduce number of peers to support peer stats feature ath10k: process htt rx indication as batch mode ath10k: reduce rx_lock contention for htt rx indication ath10k: fix erroneous return value ath10k: add hw_rev to trace events to support pktlog ath10k: fix pktlog in QCA99X0 ath10k: fix pointless update of peer stats list ath10k: fix updating peer stats rx duration ath10k: remove impossible code ath10k: populate qca4019 fw specific wmi init params ath10k: add qca4019 hw params ath10k: add abstraction layer for vdev subtype ath10k: use vif->type and vif->p2p for P2P_GO check ath10k: update 10.4 WMI service map ath10k: rename Mesh related service names ath10k: expose hif ops for ahb ath10k: add resource init and deinit in ahb ath10k: include irq related functions in ahb ath10k: add chip and bus halt logic in ahb ath10k: add reset ctrl related functions in ahb ath10k: add clock ctrl related functions in ahb ath10k: add helper functions in ahb.c for reg rd/wr ath10k: include qca4019 register map table ath10k: add basic skeleton to support ahb ath10k: pull reusable code from pci probe and remove for ahb ath10k: make ath10k_pci_read32/write32() ops more generic ath10k: make some of ath10k_pci_* func reusable ath10k: implement basic support for new tx path firmware ath10k: clean up cont frag desc init code ath10k: add new FW_FEATURE_PEER_FLOW_CONTROL ath10k: add new htt definitions ath10k: rename some HTT events ath10k: remove the p2p notice of absence info from 10.2.4 FW beacon info ath10k: add debugfs support for Per STA total rx duration ath10k: enable periodic peer stats update ath10k: provision to support periodic peer stats update ath10k: rename few function names of firmware stats ath10k: cleanup setting pdev paramaters ath10k: fix naming Peer stats rssi_changed field in 10.2.4 ath10k: add support for parsing per STA rx_duration for 10.2.4 ath10k: prevent txrx running for too long mac80211: pass block ack session timeout to to driver ath10k: set SM power save disabled to default value ath10k: reduce indentation by moving powersave check within function ath10k: wake up device before accessing registers ath10k: allow Mesh Point to install peer security key ath10k: do not use coherent memory for allocated device memory chunks ath10k: remove unnecessary amsdu/ampdu assignment in debugfs ath10k: implement fw_checksums debugfs file ath10k: print crc32 checksums for firmware and board files ath10k: split driver info messages during device initialisation ath10k: always show bmi chip ids and subdevice ids ath10k: reorganise hardware and firmware info messages ath10k: fix otp board id error message ath10k: apply Mesh subtype when Mesh interface created. ath10k: introduce new subtypes for proxy STA and Mesh ath10k: update WMI 10.x service map ath10k: Fix write permission on few debugfs files ath10k: stop abusing GFP_DMA ath10k: Enable AP + STA interface combination support for 10.x ath10k: fix board data fetch error message ath10k: Fix build with CONFIG_THERMAL=m ath10k: store msdu_id instead of txbuf pointers ath10k: replace vdev_id and tid in skb cb ath10k: fix tx header parsing ath10k: pack up flags in skb_cb ath10k: remove freq from skb_cb ath10k: remove is_offchan ath10k: remove txmode from skb_cb ath10k: rename function to adhere to naming convention ath10k: merge is_protected with nohwcrypt ath10k: adjust the RX packet pad offset at QCA99X0 4addr mode ath10k: fix the wrong RX rate idx report at 11G mode ath10k: fix peerid configuration in htt tx desc for htt version < 3.4 ath10k: rename the helper which is used for off-channel tx ath10k: fix peer assoc complete WMI command for 10.4 ath10k: add support for pktlog in QCA99X0 ath10k: debugfs file to enable Bluetooth coexistence feature ath10k: add new pdev params defines to 10.4 ath10k: add new WMI cmd/event defines for 10.4 ath10k: add new service defines for 10.4 ath10k: add thermal throttling support for 10.4 firmware ath10k: set peer MFP flag in peer assoc command ath10k: add abstraction layer for peer flags ath10k: consolidate if statements in ath10k_wmi_event_mgmt_rx Change-Id: I22c4c7c5791079b17545ef7457c54bb60fcfca80 Signed-off-by: Govind Singh <govinds@codeaurora.org>
This commit is contained in:
commit
63900f4bf1
42 changed files with 6713 additions and 1927 deletions
|
@ -2,6 +2,7 @@ config ATH10K
|
|||
tristate "Atheros 802.11ac wireless cards support"
|
||||
depends on MAC80211 && HAS_DMA
|
||||
select ATH_COMMON
|
||||
select CRC32
|
||||
---help---
|
||||
This module adds support for wireless adapters based on
|
||||
Atheros IEEE 802.11ac family of chipsets.
|
||||
|
@ -14,6 +15,12 @@ config ATH10K_PCI
|
|||
---help---
|
||||
This module adds support for PCIE bus
|
||||
|
||||
config ATH10K_AHB
|
||||
bool "Atheros ath10k AHB support"
|
||||
depends on ATH10K_PCI && OF && RESET_CONTROLLER
|
||||
---help---
|
||||
This module adds support for AHB bus
|
||||
|
||||
config ATH10K_DEBUG
|
||||
bool "Atheros ath10k debugging"
|
||||
depends on ATH10K
|
||||
|
|
|
@ -25,5 +25,7 @@ obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o
|
|||
ath10k_pci-y += pci.o \
|
||||
ce.o
|
||||
|
||||
ath10k_pci-$(CONFIG_ATH10K_AHB) += ahb.o
|
||||
|
||||
# for tracing framework to find trace.h
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
|
|
875
drivers/net/wireless/ath/ath10k/ahb.c
Normal file
875
drivers/net/wireless/ath/ath10k/ahb.c
Normal file
|
@ -0,0 +1,875 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Qualcomm Atheros, Inc. All rights reserved.
|
||||
* Copyright (c) 2015 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.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/reset.h>
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
#include "pci.h"
|
||||
#include "ahb.h"
|
||||
|
||||
static const struct of_device_id ath10k_ahb_of_match[] = {
|
||||
{ .compatible = "qcom,ipq4019-wifi",
|
||||
.data = (void *)ATH10K_HW_QCA4019
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match);
|
||||
|
||||
static inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar)
|
||||
{
|
||||
return &((struct ath10k_pci *)ar->drv_priv)->ahb[0];
|
||||
}
|
||||
|
||||
static void ath10k_ahb_write32(struct ath10k *ar, u32 offset, u32 value)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
|
||||
iowrite32(value, ar_ahb->mem + offset);
|
||||
}
|
||||
|
||||
static u32 ath10k_ahb_read32(struct ath10k *ar, u32 offset)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
|
||||
return ioread32(ar_ahb->mem + offset);
|
||||
}
|
||||
|
||||
static u32 ath10k_ahb_gcc_read32(struct ath10k *ar, u32 offset)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
|
||||
return ioread32(ar_ahb->gcc_mem + offset);
|
||||
}
|
||||
|
||||
static void ath10k_ahb_tcsr_write32(struct ath10k *ar, u32 offset, u32 value)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
|
||||
iowrite32(value, ar_ahb->tcsr_mem + offset);
|
||||
}
|
||||
|
||||
static u32 ath10k_ahb_tcsr_read32(struct ath10k *ar, u32 offset)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
|
||||
return ioread32(ar_ahb->tcsr_mem + offset);
|
||||
}
|
||||
|
||||
static u32 ath10k_ahb_soc_read32(struct ath10k *ar, u32 addr)
|
||||
{
|
||||
return ath10k_ahb_read32(ar, RTC_SOC_BASE_ADDRESS + addr);
|
||||
}
|
||||
|
||||
static int ath10k_ahb_get_num_banks(struct ath10k *ar)
|
||||
{
|
||||
if (ar->hw_rev == ATH10K_HW_QCA4019)
|
||||
return 1;
|
||||
|
||||
ath10k_warn(ar, "unknown number of banks, assuming 1\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ath10k_ahb_clock_init(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
struct device *dev;
|
||||
|
||||
dev = &ar_ahb->pdev->dev;
|
||||
|
||||
ar_ahb->cmd_clk = devm_clk_get(dev, "wifi_wcss_cmd");
|
||||
if (IS_ERR_OR_NULL(ar_ahb->cmd_clk)) {
|
||||
ath10k_err(ar, "failed to get cmd clk: %ld\n",
|
||||
PTR_ERR(ar_ahb->cmd_clk));
|
||||
return ar_ahb->cmd_clk ? PTR_ERR(ar_ahb->cmd_clk) : -ENODEV;
|
||||
}
|
||||
|
||||
ar_ahb->ref_clk = devm_clk_get(dev, "wifi_wcss_ref");
|
||||
if (IS_ERR_OR_NULL(ar_ahb->ref_clk)) {
|
||||
ath10k_err(ar, "failed to get ref clk: %ld\n",
|
||||
PTR_ERR(ar_ahb->ref_clk));
|
||||
return ar_ahb->ref_clk ? PTR_ERR(ar_ahb->ref_clk) : -ENODEV;
|
||||
}
|
||||
|
||||
ar_ahb->rtc_clk = devm_clk_get(dev, "wifi_wcss_rtc");
|
||||
if (IS_ERR_OR_NULL(ar_ahb->rtc_clk)) {
|
||||
ath10k_err(ar, "failed to get rtc clk: %ld\n",
|
||||
PTR_ERR(ar_ahb->rtc_clk));
|
||||
return ar_ahb->rtc_clk ? PTR_ERR(ar_ahb->rtc_clk) : -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_ahb_clock_deinit(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
|
||||
ar_ahb->cmd_clk = NULL;
|
||||
ar_ahb->ref_clk = NULL;
|
||||
ar_ahb->rtc_clk = NULL;
|
||||
}
|
||||
|
||||
static int ath10k_ahb_clock_enable(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
struct device *dev;
|
||||
int ret;
|
||||
|
||||
dev = &ar_ahb->pdev->dev;
|
||||
|
||||
if (IS_ERR_OR_NULL(ar_ahb->cmd_clk) ||
|
||||
IS_ERR_OR_NULL(ar_ahb->ref_clk) ||
|
||||
IS_ERR_OR_NULL(ar_ahb->rtc_clk)) {
|
||||
ath10k_err(ar, "clock(s) is/are not initialized\n");
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(ar_ahb->cmd_clk);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to enable cmd clk: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(ar_ahb->ref_clk);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to enable ref clk: %d\n", ret);
|
||||
goto err_cmd_clk_disable;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(ar_ahb->rtc_clk);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to enable rtc clk: %d\n", ret);
|
||||
goto err_ref_clk_disable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_ref_clk_disable:
|
||||
clk_disable_unprepare(ar_ahb->ref_clk);
|
||||
|
||||
err_cmd_clk_disable:
|
||||
clk_disable_unprepare(ar_ahb->cmd_clk);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath10k_ahb_clock_disable(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
|
||||
if (!IS_ERR_OR_NULL(ar_ahb->cmd_clk))
|
||||
clk_disable_unprepare(ar_ahb->cmd_clk);
|
||||
|
||||
if (!IS_ERR_OR_NULL(ar_ahb->ref_clk))
|
||||
clk_disable_unprepare(ar_ahb->ref_clk);
|
||||
|
||||
if (!IS_ERR_OR_NULL(ar_ahb->rtc_clk))
|
||||
clk_disable_unprepare(ar_ahb->rtc_clk);
|
||||
}
|
||||
|
||||
static int ath10k_ahb_rst_ctrl_init(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
struct device *dev;
|
||||
|
||||
dev = &ar_ahb->pdev->dev;
|
||||
|
||||
ar_ahb->core_cold_rst = devm_reset_control_get(dev, "wifi_core_cold");
|
||||
if (IS_ERR(ar_ahb->core_cold_rst)) {
|
||||
ath10k_err(ar, "failed to get core cold rst ctrl: %ld\n",
|
||||
PTR_ERR(ar_ahb->core_cold_rst));
|
||||
return PTR_ERR(ar_ahb->core_cold_rst);
|
||||
}
|
||||
|
||||
ar_ahb->radio_cold_rst = devm_reset_control_get(dev, "wifi_radio_cold");
|
||||
if (IS_ERR(ar_ahb->radio_cold_rst)) {
|
||||
ath10k_err(ar, "failed to get radio cold rst ctrl: %ld\n",
|
||||
PTR_ERR(ar_ahb->radio_cold_rst));
|
||||
return PTR_ERR(ar_ahb->radio_cold_rst);
|
||||
}
|
||||
|
||||
ar_ahb->radio_warm_rst = devm_reset_control_get(dev, "wifi_radio_warm");
|
||||
if (IS_ERR(ar_ahb->radio_warm_rst)) {
|
||||
ath10k_err(ar, "failed to get radio warm rst ctrl: %ld\n",
|
||||
PTR_ERR(ar_ahb->radio_warm_rst));
|
||||
return PTR_ERR(ar_ahb->radio_warm_rst);
|
||||
}
|
||||
|
||||
ar_ahb->radio_srif_rst = devm_reset_control_get(dev, "wifi_radio_srif");
|
||||
if (IS_ERR(ar_ahb->radio_srif_rst)) {
|
||||
ath10k_err(ar, "failed to get radio srif rst ctrl: %ld\n",
|
||||
PTR_ERR(ar_ahb->radio_srif_rst));
|
||||
return PTR_ERR(ar_ahb->radio_srif_rst);
|
||||
}
|
||||
|
||||
ar_ahb->cpu_init_rst = devm_reset_control_get(dev, "wifi_cpu_init");
|
||||
if (IS_ERR(ar_ahb->cpu_init_rst)) {
|
||||
ath10k_err(ar, "failed to get cpu init rst ctrl: %ld\n",
|
||||
PTR_ERR(ar_ahb->cpu_init_rst));
|
||||
return PTR_ERR(ar_ahb->cpu_init_rst);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_ahb_rst_ctrl_deinit(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
|
||||
ar_ahb->core_cold_rst = NULL;
|
||||
ar_ahb->radio_cold_rst = NULL;
|
||||
ar_ahb->radio_warm_rst = NULL;
|
||||
ar_ahb->radio_srif_rst = NULL;
|
||||
ar_ahb->cpu_init_rst = NULL;
|
||||
}
|
||||
|
||||
static int ath10k_ahb_release_reset(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
int ret;
|
||||
|
||||
if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) ||
|
||||
IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) ||
|
||||
IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) ||
|
||||
IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) {
|
||||
ath10k_err(ar, "rst ctrl(s) is/are not initialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(ar_ahb->radio_cold_rst);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to deassert radio cold rst: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(ar_ahb->radio_warm_rst);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to deassert radio warm rst: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(ar_ahb->radio_srif_rst);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to deassert radio srif rst: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(ar_ahb->cpu_init_rst);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to deassert cpu init rst: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_ahb_halt_axi_bus(struct ath10k *ar, u32 haltreq_reg,
|
||||
u32 haltack_reg)
|
||||
{
|
||||
unsigned long timeout;
|
||||
u32 val;
|
||||
|
||||
/* Issue halt axi bus request */
|
||||
val = ath10k_ahb_tcsr_read32(ar, haltreq_reg);
|
||||
val |= AHB_AXI_BUS_HALT_REQ;
|
||||
ath10k_ahb_tcsr_write32(ar, haltreq_reg, val);
|
||||
|
||||
/* Wait for axi bus halted ack */
|
||||
timeout = jiffies + msecs_to_jiffies(ATH10K_AHB_AXI_BUS_HALT_TIMEOUT);
|
||||
do {
|
||||
val = ath10k_ahb_tcsr_read32(ar, haltack_reg);
|
||||
if (val & AHB_AXI_BUS_HALT_ACK)
|
||||
break;
|
||||
|
||||
mdelay(1);
|
||||
} while (time_before(jiffies, timeout));
|
||||
|
||||
if (!(val & AHB_AXI_BUS_HALT_ACK)) {
|
||||
ath10k_err(ar, "failed to halt axi bus: %d\n", val);
|
||||
return;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_AHB, "axi bus halted\n");
|
||||
}
|
||||
|
||||
static void ath10k_ahb_halt_chip(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
u32 core_id, glb_cfg_reg, haltreq_reg, haltack_reg;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst) ||
|
||||
IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) ||
|
||||
IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) ||
|
||||
IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) ||
|
||||
IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) {
|
||||
ath10k_err(ar, "rst ctrl(s) is/are not initialized\n");
|
||||
return;
|
||||
}
|
||||
|
||||
core_id = ath10k_ahb_read32(ar, ATH10K_AHB_WLAN_CORE_ID_REG);
|
||||
|
||||
switch (core_id) {
|
||||
case 0:
|
||||
glb_cfg_reg = ATH10K_AHB_TCSR_WIFI0_GLB_CFG;
|
||||
haltreq_reg = ATH10K_AHB_TCSR_WCSS0_HALTREQ;
|
||||
haltack_reg = ATH10K_AHB_TCSR_WCSS0_HALTACK;
|
||||
break;
|
||||
case 1:
|
||||
glb_cfg_reg = ATH10K_AHB_TCSR_WIFI1_GLB_CFG;
|
||||
haltreq_reg = ATH10K_AHB_TCSR_WCSS1_HALTREQ;
|
||||
haltack_reg = ATH10K_AHB_TCSR_WCSS1_HALTACK;
|
||||
break;
|
||||
default:
|
||||
ath10k_err(ar, "invalid core id %d found, skipping reset sequence\n",
|
||||
core_id);
|
||||
return;
|
||||
}
|
||||
|
||||
ath10k_ahb_halt_axi_bus(ar, haltreq_reg, haltack_reg);
|
||||
|
||||
val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg);
|
||||
val |= TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK;
|
||||
ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val);
|
||||
|
||||
ret = reset_control_assert(ar_ahb->core_cold_rst);
|
||||
if (ret)
|
||||
ath10k_err(ar, "failed to assert core cold rst: %d\n", ret);
|
||||
msleep(1);
|
||||
|
||||
ret = reset_control_assert(ar_ahb->radio_cold_rst);
|
||||
if (ret)
|
||||
ath10k_err(ar, "failed to assert radio cold rst: %d\n", ret);
|
||||
msleep(1);
|
||||
|
||||
ret = reset_control_assert(ar_ahb->radio_warm_rst);
|
||||
if (ret)
|
||||
ath10k_err(ar, "failed to assert radio warm rst: %d\n", ret);
|
||||
msleep(1);
|
||||
|
||||
ret = reset_control_assert(ar_ahb->radio_srif_rst);
|
||||
if (ret)
|
||||
ath10k_err(ar, "failed to assert radio srif rst: %d\n", ret);
|
||||
msleep(1);
|
||||
|
||||
ret = reset_control_assert(ar_ahb->cpu_init_rst);
|
||||
if (ret)
|
||||
ath10k_err(ar, "failed to assert cpu init rst: %d\n", ret);
|
||||
msleep(10);
|
||||
|
||||
/* Clear halt req and core clock disable req before
|
||||
* deasserting wifi core reset.
|
||||
*/
|
||||
val = ath10k_ahb_tcsr_read32(ar, haltreq_reg);
|
||||
val &= ~AHB_AXI_BUS_HALT_REQ;
|
||||
ath10k_ahb_tcsr_write32(ar, haltreq_reg, val);
|
||||
|
||||
val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg);
|
||||
val &= ~TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK;
|
||||
ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val);
|
||||
|
||||
ret = reset_control_deassert(ar_ahb->core_cold_rst);
|
||||
if (ret)
|
||||
ath10k_err(ar, "failed to deassert core cold rst: %d\n", ret);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_AHB, "core %d reset done\n", core_id);
|
||||
}
|
||||
|
||||
static irqreturn_t ath10k_ahb_interrupt_handler(int irq, void *arg)
|
||||
{
|
||||
struct ath10k *ar = arg;
|
||||
|
||||
if (!ath10k_pci_irq_pending(ar))
|
||||
return IRQ_NONE;
|
||||
|
||||
ath10k_pci_disable_and_clear_legacy_irq(ar);
|
||||
ath10k_pci_irq_msi_fw_mask(ar);
|
||||
napi_schedule(&ar->napi);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int ath10k_ahb_request_irq_legacy(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
int ret;
|
||||
|
||||
ret = request_irq(ar_ahb->irq,
|
||||
ath10k_ahb_interrupt_handler,
|
||||
IRQF_SHARED, "ath10k_ahb", ar);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to request legacy irq %d: %d\n",
|
||||
ar_ahb->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
ar_pci->oper_irq_mode = ATH10K_PCI_IRQ_LEGACY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_ahb_release_irq_legacy(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
|
||||
free_irq(ar_ahb->irq, ar);
|
||||
}
|
||||
|
||||
static void ath10k_ahb_irq_disable(struct ath10k *ar)
|
||||
{
|
||||
ath10k_ce_disable_interrupts(ar);
|
||||
ath10k_pci_disable_and_clear_legacy_irq(ar);
|
||||
}
|
||||
|
||||
static int ath10k_ahb_resource_init(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
struct platform_device *pdev;
|
||||
struct device *dev;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
pdev = ar_ahb->pdev;
|
||||
dev = &pdev->dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
ath10k_err(ar, "failed to get memory resource\n");
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ar_ahb->mem = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(ar_ahb->mem)) {
|
||||
ath10k_err(ar, "mem ioremap error\n");
|
||||
ret = PTR_ERR(ar_ahb->mem);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ar_ahb->mem_len = resource_size(res);
|
||||
|
||||
ar_ahb->gcc_mem = ioremap_nocache(ATH10K_GCC_REG_BASE,
|
||||
ATH10K_GCC_REG_SIZE);
|
||||
if (!ar_ahb->gcc_mem) {
|
||||
ath10k_err(ar, "gcc mem ioremap error\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_mem_unmap;
|
||||
}
|
||||
|
||||
ar_ahb->tcsr_mem = ioremap_nocache(ATH10K_TCSR_REG_BASE,
|
||||
ATH10K_TCSR_REG_SIZE);
|
||||
if (!ar_ahb->tcsr_mem) {
|
||||
ath10k_err(ar, "tcsr mem ioremap error\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_gcc_mem_unmap;
|
||||
}
|
||||
|
||||
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to set 32-bit dma mask: %d\n", ret);
|
||||
goto err_tcsr_mem_unmap;
|
||||
}
|
||||
|
||||
ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to set 32-bit consistent dma: %d\n",
|
||||
ret);
|
||||
goto err_tcsr_mem_unmap;
|
||||
}
|
||||
|
||||
ret = ath10k_ahb_clock_init(ar);
|
||||
if (ret)
|
||||
goto err_tcsr_mem_unmap;
|
||||
|
||||
ret = ath10k_ahb_rst_ctrl_init(ar);
|
||||
if (ret)
|
||||
goto err_clock_deinit;
|
||||
|
||||
ar_ahb->irq = platform_get_irq_byname(pdev, "legacy");
|
||||
if (ar_ahb->irq < 0) {
|
||||
ath10k_err(ar, "failed to get irq number: %d\n", ar_ahb->irq);
|
||||
ret = ar_ahb->irq;
|
||||
goto err_clock_deinit;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "irq: %d\n", ar_ahb->irq);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "mem: 0x%pK mem_len: %lu gcc mem: 0x%pK tcsr_mem: 0x%pK\n",
|
||||
ar_ahb->mem, ar_ahb->mem_len,
|
||||
ar_ahb->gcc_mem, ar_ahb->tcsr_mem);
|
||||
return 0;
|
||||
|
||||
err_clock_deinit:
|
||||
ath10k_ahb_clock_deinit(ar);
|
||||
|
||||
err_tcsr_mem_unmap:
|
||||
iounmap(ar_ahb->tcsr_mem);
|
||||
|
||||
err_gcc_mem_unmap:
|
||||
ar_ahb->tcsr_mem = NULL;
|
||||
iounmap(ar_ahb->gcc_mem);
|
||||
|
||||
err_mem_unmap:
|
||||
ar_ahb->gcc_mem = NULL;
|
||||
devm_iounmap(&pdev->dev, ar_ahb->mem);
|
||||
|
||||
out:
|
||||
ar_ahb->mem = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath10k_ahb_resource_deinit(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
struct device *dev;
|
||||
|
||||
dev = &ar_ahb->pdev->dev;
|
||||
|
||||
if (ar_ahb->mem)
|
||||
devm_iounmap(dev, ar_ahb->mem);
|
||||
|
||||
if (ar_ahb->gcc_mem)
|
||||
iounmap(ar_ahb->gcc_mem);
|
||||
|
||||
if (ar_ahb->tcsr_mem)
|
||||
iounmap(ar_ahb->tcsr_mem);
|
||||
|
||||
ar_ahb->mem = NULL;
|
||||
ar_ahb->gcc_mem = NULL;
|
||||
ar_ahb->tcsr_mem = NULL;
|
||||
|
||||
ath10k_ahb_clock_deinit(ar);
|
||||
ath10k_ahb_rst_ctrl_deinit(ar);
|
||||
}
|
||||
|
||||
static int ath10k_ahb_prepare_device(struct ath10k *ar)
|
||||
{
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = ath10k_ahb_clock_enable(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to enable clocks\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Clock for the target is supplied from outside of target (ie,
|
||||
* external clock module controlled by the host). Target needs
|
||||
* to know what frequency target cpu is configured which is needed
|
||||
* for target internal use. Read target cpu frequency info from
|
||||
* gcc register and write into target's scratch register where
|
||||
* target expects this information.
|
||||
*/
|
||||
val = ath10k_ahb_gcc_read32(ar, ATH10K_AHB_GCC_FEPLL_PLL_DIV);
|
||||
ath10k_ahb_write32(ar, ATH10K_AHB_WIFI_SCRATCH_5_REG, val);
|
||||
|
||||
ret = ath10k_ahb_release_reset(ar);
|
||||
if (ret)
|
||||
goto err_clk_disable;
|
||||
|
||||
ath10k_ahb_irq_disable(ar);
|
||||
|
||||
ath10k_ahb_write32(ar, FW_INDICATOR_ADDRESS, FW_IND_HOST_READY);
|
||||
|
||||
ret = ath10k_pci_wait_for_target_init(ar);
|
||||
if (ret)
|
||||
goto err_halt_chip;
|
||||
|
||||
return 0;
|
||||
|
||||
err_halt_chip:
|
||||
ath10k_ahb_halt_chip(ar);
|
||||
|
||||
err_clk_disable:
|
||||
ath10k_ahb_clock_disable(ar);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_ahb_chip_reset(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ath10k_ahb_halt_chip(ar);
|
||||
ath10k_ahb_clock_disable(ar);
|
||||
|
||||
ret = ath10k_ahb_prepare_device(ar);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_ahb_wake_target_cpu(struct ath10k *ar)
|
||||
{
|
||||
u32 addr, val;
|
||||
|
||||
addr = SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS;
|
||||
val = ath10k_ahb_read32(ar, addr);
|
||||
val |= ATH10K_AHB_CORE_CTRL_CPU_INTR_MASK;
|
||||
ath10k_ahb_write32(ar, addr, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_ahb_hif_start(struct ath10k *ar)
|
||||
{
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif start\n");
|
||||
|
||||
ath10k_ce_enable_interrupts(ar);
|
||||
ath10k_pci_enable_legacy_irq(ar);
|
||||
|
||||
ath10k_pci_rx_post(ar);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_ahb_hif_stop(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif stop\n");
|
||||
|
||||
ath10k_ahb_irq_disable(ar);
|
||||
synchronize_irq(ar_ahb->irq);
|
||||
|
||||
ath10k_pci_flush(ar);
|
||||
|
||||
napi_synchronize(&ar->napi);
|
||||
napi_disable(&ar->napi);
|
||||
}
|
||||
|
||||
static int ath10k_ahb_hif_power_up(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif power up\n");
|
||||
|
||||
ret = ath10k_ahb_chip_reset(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to reset chip: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ath10k_pci_init_pipes(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to initialize CE: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ath10k_pci_init_config(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to setup init config: %d\n", ret);
|
||||
goto err_ce_deinit;
|
||||
}
|
||||
|
||||
ret = ath10k_ahb_wake_target_cpu(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "could not wake up target CPU: %d\n", ret);
|
||||
goto err_ce_deinit;
|
||||
}
|
||||
napi_enable(&ar->napi);
|
||||
|
||||
return 0;
|
||||
|
||||
err_ce_deinit:
|
||||
ath10k_pci_ce_deinit(ar);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct ath10k_hif_ops ath10k_ahb_hif_ops = {
|
||||
.tx_sg = ath10k_pci_hif_tx_sg,
|
||||
.diag_read = ath10k_pci_hif_diag_read,
|
||||
.diag_write = ath10k_pci_diag_write_mem,
|
||||
.exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg,
|
||||
.start = ath10k_ahb_hif_start,
|
||||
.stop = ath10k_ahb_hif_stop,
|
||||
.map_service_to_pipe = ath10k_pci_hif_map_service_to_pipe,
|
||||
.get_default_pipe = ath10k_pci_hif_get_default_pipe,
|
||||
.send_complete_check = ath10k_pci_hif_send_complete_check,
|
||||
.get_free_queue_number = ath10k_pci_hif_get_free_queue_number,
|
||||
.power_up = ath10k_ahb_hif_power_up,
|
||||
.power_down = ath10k_pci_hif_power_down,
|
||||
.read32 = ath10k_ahb_read32,
|
||||
.write32 = ath10k_ahb_write32,
|
||||
};
|
||||
|
||||
static const struct ath10k_bus_ops ath10k_ahb_bus_ops = {
|
||||
.read32 = ath10k_ahb_read32,
|
||||
.write32 = ath10k_ahb_write32,
|
||||
.get_num_banks = ath10k_ahb_get_num_banks,
|
||||
};
|
||||
|
||||
static int ath10k_ahb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ath10k *ar;
|
||||
struct ath10k_ahb *ar_ahb;
|
||||
struct ath10k_pci *ar_pci;
|
||||
const struct of_device_id *of_id;
|
||||
enum ath10k_hw_rev hw_rev;
|
||||
size_t size;
|
||||
int ret;
|
||||
u32 chip_id;
|
||||
|
||||
of_id = of_match_device(ath10k_ahb_of_match, &pdev->dev);
|
||||
if (!of_id) {
|
||||
dev_err(&pdev->dev, "failed to find matching device tree id\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hw_rev = (enum ath10k_hw_rev)of_id->data;
|
||||
|
||||
size = sizeof(*ar_pci) + sizeof(*ar_ahb);
|
||||
ar = ath10k_core_create(size, &pdev->dev, ATH10K_BUS_AHB,
|
||||
hw_rev, &ath10k_ahb_hif_ops);
|
||||
if (!ar) {
|
||||
dev_err(&pdev->dev, "failed to allocate core\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "ahb probe\n");
|
||||
|
||||
ar_pci = ath10k_pci_priv(ar);
|
||||
ar_ahb = ath10k_ahb_priv(ar);
|
||||
|
||||
ar_ahb->pdev = pdev;
|
||||
platform_set_drvdata(pdev, ar);
|
||||
|
||||
ret = ath10k_ahb_resource_init(ar);
|
||||
if (ret)
|
||||
goto err_core_destroy;
|
||||
|
||||
ar->dev_id = 0;
|
||||
ar_pci->mem = ar_ahb->mem;
|
||||
ar_pci->mem_len = ar_ahb->mem_len;
|
||||
ar_pci->ar = ar;
|
||||
ar_pci->bus_ops = &ath10k_ahb_bus_ops;
|
||||
|
||||
ret = ath10k_pci_setup_resource(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to setup resource: %d\n", ret);
|
||||
goto err_resource_deinit;
|
||||
}
|
||||
|
||||
ath10k_pci_init_napi(ar);
|
||||
|
||||
ret = ath10k_ahb_request_irq_legacy(ar);
|
||||
if (ret)
|
||||
goto err_free_pipes;
|
||||
|
||||
ret = ath10k_ahb_prepare_device(ar);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
|
||||
ath10k_pci_ce_deinit(ar);
|
||||
|
||||
chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
|
||||
if (chip_id == 0xffffffff) {
|
||||
ath10k_err(ar, "failed to get chip id\n");
|
||||
ret = -ENODEV;
|
||||
goto err_halt_device;
|
||||
}
|
||||
|
||||
ret = ath10k_core_register(ar, chip_id);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to register driver core: %d\n", ret);
|
||||
goto err_halt_device;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_halt_device:
|
||||
ath10k_ahb_halt_chip(ar);
|
||||
ath10k_ahb_clock_disable(ar);
|
||||
|
||||
err_free_irq:
|
||||
ath10k_ahb_release_irq_legacy(ar);
|
||||
|
||||
err_free_pipes:
|
||||
ath10k_pci_free_pipes(ar);
|
||||
|
||||
err_resource_deinit:
|
||||
ath10k_ahb_resource_deinit(ar);
|
||||
|
||||
err_core_destroy:
|
||||
ath10k_core_destroy(ar);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_ahb_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ath10k *ar = platform_get_drvdata(pdev);
|
||||
struct ath10k_ahb *ar_ahb;
|
||||
|
||||
if (!ar)
|
||||
return -EINVAL;
|
||||
|
||||
ar_ahb = ath10k_ahb_priv(ar);
|
||||
|
||||
if (!ar_ahb)
|
||||
return -EINVAL;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_AHB, "ahb remove\n");
|
||||
|
||||
ath10k_core_unregister(ar);
|
||||
ath10k_ahb_irq_disable(ar);
|
||||
ath10k_ahb_release_irq_legacy(ar);
|
||||
ath10k_pci_release_resource(ar);
|
||||
ath10k_ahb_halt_chip(ar);
|
||||
ath10k_ahb_clock_disable(ar);
|
||||
ath10k_ahb_resource_deinit(ar);
|
||||
ath10k_core_destroy(ar);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ath10k_ahb_driver = {
|
||||
.driver = {
|
||||
.name = "ath10k_ahb",
|
||||
.of_match_table = ath10k_ahb_of_match,
|
||||
},
|
||||
.probe = ath10k_ahb_probe,
|
||||
.remove = ath10k_ahb_remove,
|
||||
};
|
||||
|
||||
int ath10k_ahb_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&ath10k_ahb_driver);
|
||||
if (ret)
|
||||
printk(KERN_ERR "failed to register ath10k ahb driver: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ath10k_ahb_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ath10k_ahb_driver);
|
||||
}
|
87
drivers/net/wireless/ath/ath10k/ahb.h
Normal file
87
drivers/net/wireless/ath/ath10k/ahb.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Qualcomm Atheros, Inc. All rights reserved.
|
||||
* Copyright (c) 2015 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 _AHB_H_
|
||||
#define _AHB_H_
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
struct ath10k_ahb {
|
||||
struct platform_device *pdev;
|
||||
void __iomem *mem;
|
||||
unsigned long mem_len;
|
||||
void __iomem *gcc_mem;
|
||||
void __iomem *tcsr_mem;
|
||||
|
||||
int irq;
|
||||
|
||||
struct clk *cmd_clk;
|
||||
struct clk *ref_clk;
|
||||
struct clk *rtc_clk;
|
||||
|
||||
struct reset_control *core_cold_rst;
|
||||
struct reset_control *radio_cold_rst;
|
||||
struct reset_control *radio_warm_rst;
|
||||
struct reset_control *radio_srif_rst;
|
||||
struct reset_control *cpu_init_rst;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ATH10K_AHB
|
||||
|
||||
#define ATH10K_GCC_REG_BASE 0x1800000
|
||||
#define ATH10K_GCC_REG_SIZE 0x60000
|
||||
|
||||
#define ATH10K_TCSR_REG_BASE 0x1900000
|
||||
#define ATH10K_TCSR_REG_SIZE 0x80000
|
||||
|
||||
#define ATH10K_AHB_GCC_FEPLL_PLL_DIV 0x2f020
|
||||
#define ATH10K_AHB_WIFI_SCRATCH_5_REG 0x4f014
|
||||
|
||||
#define ATH10K_AHB_WLAN_CORE_ID_REG 0x82030
|
||||
|
||||
#define ATH10K_AHB_TCSR_WIFI0_GLB_CFG 0x49000
|
||||
#define ATH10K_AHB_TCSR_WIFI1_GLB_CFG 0x49004
|
||||
#define TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK BIT(25)
|
||||
|
||||
#define ATH10K_AHB_TCSR_WCSS0_HALTREQ 0x52000
|
||||
#define ATH10K_AHB_TCSR_WCSS1_HALTREQ 0x52010
|
||||
#define ATH10K_AHB_TCSR_WCSS0_HALTACK 0x52004
|
||||
#define ATH10K_AHB_TCSR_WCSS1_HALTACK 0x52014
|
||||
|
||||
#define ATH10K_AHB_AXI_BUS_HALT_TIMEOUT 10 /* msec */
|
||||
#define AHB_AXI_BUS_HALT_REQ 1
|
||||
#define AHB_AXI_BUS_HALT_ACK 1
|
||||
|
||||
#define ATH10K_AHB_CORE_CTRL_CPU_INTR_MASK 1
|
||||
|
||||
int ath10k_ahb_init(void);
|
||||
void ath10k_ahb_exit(void);
|
||||
|
||||
#else /* CONFIG_ATH10K_AHB */
|
||||
|
||||
static inline int ath10k_ahb_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath10k_ahb_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ATH10K_AHB */
|
||||
|
||||
#endif /* _AHB_H_ */
|
|
@ -221,7 +221,7 @@ int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length)
|
|||
u32 txlen;
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi lz data buffer 0x%p length %d\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi lz data buffer 0x%pK length %d\n",
|
||||
buffer, length);
|
||||
|
||||
if (ar->bmi.done_sent) {
|
||||
|
@ -287,7 +287,7 @@ int ath10k_bmi_fast_download(struct ath10k *ar,
|
|||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI,
|
||||
"bmi fast download address 0x%x buffer 0x%p length %d\n",
|
||||
"bmi fast download address 0x%x buffer 0x%pK length %d\n",
|
||||
address, buffer, length);
|
||||
|
||||
ret = ath10k_bmi_lz_stream_start(ar, address);
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
* chooses what to send (buffer address, length). The destination
|
||||
* side keeps a supply of "anonymous receive buffers" available and
|
||||
* it handles incoming data as it arrives (when the destination
|
||||
* recieves an interrupt).
|
||||
* receives an interrupt).
|
||||
*
|
||||
* The sender may send a simple buffer (address/length) or it may
|
||||
* send a small list of buffers. When a small list is sent, hardware
|
||||
|
@ -411,7 +411,8 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
|
|||
|
||||
lockdep_assert_held(&ar_pci->ce_lock);
|
||||
|
||||
if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0)
|
||||
if ((pipe->id != 5) &&
|
||||
CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0)
|
||||
return -ENOSPC;
|
||||
|
||||
desc->addr = __cpu_to_le32(paddr);
|
||||
|
@ -425,6 +426,19 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries)
|
||||
{
|
||||
struct ath10k *ar = pipe->ar;
|
||||
struct ath10k_ce_ring *dest_ring = pipe->dest_ring;
|
||||
unsigned int nentries_mask = dest_ring->nentries_mask;
|
||||
unsigned int write_index = dest_ring->write_index;
|
||||
u32 ctrl_addr = pipe->ctrl_addr;
|
||||
|
||||
write_index = CE_RING_IDX_ADD(nentries_mask, write_index, nentries);
|
||||
ath10k_ce_dest_ring_write_index_set(ar, ctrl_addr, write_index);
|
||||
dest_ring->write_index = write_index;
|
||||
}
|
||||
|
||||
int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
|
||||
{
|
||||
struct ath10k *ar = pipe->ar;
|
||||
|
@ -444,14 +458,10 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
|
|||
*/
|
||||
int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp,
|
||||
unsigned int *flagsp)
|
||||
unsigned int *nbytesp)
|
||||
{
|
||||
struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
|
||||
unsigned int nentries_mask = dest_ring->nentries_mask;
|
||||
struct ath10k *ar = ce_state->ar;
|
||||
unsigned int sw_index = dest_ring->sw_index;
|
||||
|
||||
struct ce_desc *base = dest_ring->base_addr_owner_space;
|
||||
|
@ -476,21 +486,17 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
|
|||
desc->nbytes = 0;
|
||||
|
||||
/* Return data from completed destination descriptor */
|
||||
*bufferp = __le32_to_cpu(sdesc.addr);
|
||||
*nbytesp = nbytes;
|
||||
*transfer_idp = MS(__le16_to_cpu(sdesc.flags), CE_DESC_FLAGS_META_DATA);
|
||||
|
||||
if (__le16_to_cpu(sdesc.flags) & CE_DESC_FLAGS_BYTE_SWAP)
|
||||
*flagsp = CE_RECV_FLAG_SWAPPED;
|
||||
else
|
||||
*flagsp = 0;
|
||||
|
||||
if (per_transfer_contextp)
|
||||
*per_transfer_contextp =
|
||||
dest_ring->per_transfer_context[sw_index];
|
||||
|
||||
/* sanity */
|
||||
dest_ring->per_transfer_context[sw_index] = NULL;
|
||||
/* Copy engine 5 (HTT Rx) will reuse the same transfer context.
|
||||
* So update transfer context all CEs except CE5.
|
||||
*/
|
||||
if (ce_state->id != 5)
|
||||
dest_ring->per_transfer_context[sw_index] = NULL;
|
||||
|
||||
/* Update sw_index */
|
||||
sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
|
||||
|
@ -501,10 +507,7 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
|
|||
|
||||
int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp,
|
||||
unsigned int *flagsp)
|
||||
unsigned int *nbytesp)
|
||||
{
|
||||
struct ath10k *ar = ce_state->ar;
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
@ -513,8 +516,7 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
|
|||
spin_lock_bh(&ar_pci->ce_lock);
|
||||
ret = ath10k_ce_completed_recv_next_nolock(ce_state,
|
||||
per_transfer_contextp,
|
||||
bufferp, nbytesp,
|
||||
transfer_idp, flagsp);
|
||||
nbytesp);
|
||||
spin_unlock_bh(&ar_pci->ce_lock);
|
||||
|
||||
return ret;
|
||||
|
@ -838,7 +840,7 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,
|
|||
ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, nentries);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"boot init ce src ring id %d entries %d base_addr %p\n",
|
||||
"boot init ce src ring id %d entries %d base_addr %pK\n",
|
||||
ce_id, nentries, src_ring->base_addr_owner_space);
|
||||
|
||||
return 0;
|
||||
|
@ -872,7 +874,7 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar,
|
|||
ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, nentries);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"boot ce dest ring id %d entries %d base_addr %p\n",
|
||||
"boot ce dest ring id %d entries %d base_addr %pK\n",
|
||||
ce_id, nentries, dest_ring->base_addr_owner_space);
|
||||
|
||||
return 0;
|
||||
|
@ -1048,11 +1050,11 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
|
|||
*
|
||||
* For the lack of a better place do the check here.
|
||||
*/
|
||||
BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC >
|
||||
BUILD_BUG_ON(2 * TARGET_NUM_MSDU_DESC >
|
||||
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
|
||||
BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
|
||||
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 >
|
||||
BUILD_BUG_ON(2 * TARGET_TLV_NUM_MSDU_DESC >
|
||||
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
|
||||
|
||||
ce_state->ar = ar;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
/* Maximum number of Copy Engine's supported */
|
||||
#define CE_COUNT_MAX 12
|
||||
#define CE_HTT_H2T_MSG_SRC_NENTRIES 4096
|
||||
#define CE_HTT_H2T_MSG_SRC_NENTRIES 8192
|
||||
|
||||
/* Descriptor rings must be aligned to this boundary */
|
||||
#define CE_DESC_RING_ALIGN 8
|
||||
|
@ -166,6 +166,7 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe);
|
|||
int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe);
|
||||
int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
|
||||
int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
|
||||
void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries);
|
||||
|
||||
/* recv flags */
|
||||
/* Data is byte-swapped */
|
||||
|
@ -177,10 +178,7 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
|
|||
*/
|
||||
int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp,
|
||||
unsigned int *flagsp);
|
||||
unsigned int *nbytesp);
|
||||
/*
|
||||
* Supply data for the next completed unprocessed send descriptor.
|
||||
* Pops 1 completed send buffer from Source ring.
|
||||
|
@ -212,10 +210,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
|
|||
|
||||
int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp,
|
||||
unsigned int *flagsp);
|
||||
unsigned int *nbytesp);
|
||||
|
||||
/*
|
||||
* Support clean shutdown by allowing the caller to cancel
|
||||
|
@ -413,9 +408,11 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
|
|||
|
||||
/* Ring arithmetic (modulus number of entries in ring, which is a pwr of 2). */
|
||||
#define CE_RING_DELTA(nentries_mask, fromidx, toidx) \
|
||||
(((int)(toidx)-(int)(fromidx)) & (nentries_mask))
|
||||
(((int)(toidx) - (int)(fromidx)) & (nentries_mask))
|
||||
|
||||
#define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask))
|
||||
#define CE_RING_IDX_ADD(nentries_mask, idx, num) \
|
||||
(((idx) + (num)) & (nentries_mask))
|
||||
|
||||
#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB \
|
||||
ar->regs->ce_wrap_intr_sum_host_msi_lsb
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -44,8 +44,8 @@
|
|||
|
||||
#define ATH10K_SCAN_ID 0
|
||||
#define WMI_READY_TIMEOUT (5 * HZ)
|
||||
#define ATH10K_FLUSH_TIMEOUT_HZ (5*HZ)
|
||||
#define ATH10K_CONNECTION_LOSS_HZ (3*HZ)
|
||||
#define ATH10K_FLUSH_TIMEOUT_HZ (5 * HZ)
|
||||
#define ATH10K_CONNECTION_LOSS_HZ (3 * HZ)
|
||||
#define ATH10K_NUM_CHANS 39
|
||||
|
||||
/* Antenna noise floor */
|
||||
|
@ -65,10 +65,15 @@
|
|||
#define ATH10K_KEEPALIVE_MAX_IDLE 3895
|
||||
#define ATH10K_KEEPALIVE_MAX_UNRESPONSIVE 3900
|
||||
|
||||
/* NAPI poll budget */
|
||||
#define ATH10K_NAPI_BUDGET 64
|
||||
#define ATH10K_NAPI_QUOTA_LIMIT 60
|
||||
|
||||
struct ath10k;
|
||||
|
||||
enum ath10k_bus {
|
||||
ATH10K_BUS_PCI,
|
||||
ATH10K_BUS_AHB,
|
||||
};
|
||||
|
||||
static inline const char *ath10k_bus_str(enum ath10k_bus bus)
|
||||
|
@ -76,31 +81,28 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus)
|
|||
switch (bus) {
|
||||
case ATH10K_BUS_PCI:
|
||||
return "pci";
|
||||
case ATH10K_BUS_AHB:
|
||||
return "ahb";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
enum ath10k_skb_flags {
|
||||
ATH10K_SKB_F_NO_HWCRYPT = BIT(0),
|
||||
ATH10K_SKB_F_DTIM_ZERO = BIT(1),
|
||||
ATH10K_SKB_F_DELIVER_CAB = BIT(2),
|
||||
ATH10K_SKB_F_MGMT = BIT(3),
|
||||
ATH10K_SKB_F_QOS = BIT(4),
|
||||
};
|
||||
|
||||
struct ath10k_skb_cb {
|
||||
dma_addr_t paddr;
|
||||
u8 flags;
|
||||
u8 eid;
|
||||
u8 vdev_id;
|
||||
enum ath10k_hw_txrx_mode txmode;
|
||||
bool is_protected;
|
||||
|
||||
struct {
|
||||
u8 tid;
|
||||
u16 freq;
|
||||
bool is_offchan;
|
||||
bool nohwcrypt;
|
||||
struct ath10k_htt_txbuf *txbuf;
|
||||
u32 txbuf_paddr;
|
||||
} __packed htt;
|
||||
|
||||
struct {
|
||||
bool dtim_zero;
|
||||
bool deliver_cab;
|
||||
} bcn;
|
||||
u16 msdu_id;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ieee80211_txq *txq;
|
||||
} __packed;
|
||||
|
||||
struct ath10k_skb_rxcb {
|
||||
|
@ -141,16 +143,17 @@ 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;
|
||||
struct completion barrier;
|
||||
wait_queue_head_t tx_credits_wq;
|
||||
DECLARE_BITMAP(svc_map, WMI_SERVICE_MAX);
|
||||
struct wmi_cmd_map *cmd;
|
||||
struct wmi_vdev_param_map *vdev_param;
|
||||
struct wmi_pdev_param_map *pdev_param;
|
||||
const struct wmi_ops *ops;
|
||||
const struct wmi_peer_flags_map *peer_flags;
|
||||
|
||||
u32 num_mem_chunks;
|
||||
u32 rx_decap_mode;
|
||||
|
@ -164,6 +167,14 @@ struct ath10k_fw_stats_peer {
|
|||
u32 peer_rssi;
|
||||
u32 peer_tx_rate;
|
||||
u32 peer_rx_rate; /* 10x only */
|
||||
u32 rx_duration;
|
||||
};
|
||||
|
||||
struct ath10k_fw_extd_stats_peer {
|
||||
struct list_head list;
|
||||
|
||||
u8 peer_macaddr[ETH_ALEN];
|
||||
u32 rx_duration;
|
||||
};
|
||||
|
||||
struct ath10k_fw_stats_vdev {
|
||||
|
@ -190,10 +201,10 @@ struct ath10k_fw_stats_pdev {
|
|||
|
||||
/* PDEV stats */
|
||||
s32 ch_noise_floor;
|
||||
u32 tx_frame_count;
|
||||
u32 rx_frame_count;
|
||||
u32 rx_clear_count;
|
||||
u32 cycle_count;
|
||||
u32 tx_frame_count; /* Cycles spent transmitting frames */
|
||||
u32 rx_frame_count; /* Cycles spent receiving frames */
|
||||
u32 rx_clear_count; /* Total channel busy time, evidently */
|
||||
u32 cycle_count; /* Total on-channel time */
|
||||
u32 phy_err_count;
|
||||
u32 chan_tx_power;
|
||||
u32 ack_rx_bad;
|
||||
|
@ -257,9 +268,11 @@ struct ath10k_fw_stats_pdev {
|
|||
};
|
||||
|
||||
struct ath10k_fw_stats {
|
||||
bool extended;
|
||||
struct list_head pdevs;
|
||||
struct list_head vdevs;
|
||||
struct list_head peers;
|
||||
struct list_head peers_extd;
|
||||
};
|
||||
|
||||
#define ATH10K_TPC_TABLE_TYPE_FLAG 1
|
||||
|
@ -298,6 +311,9 @@ struct ath10k_dfs_stats {
|
|||
|
||||
struct ath10k_peer {
|
||||
struct list_head list;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ieee80211_sta *sta;
|
||||
|
||||
int vdev_id;
|
||||
u8 addr[ETH_ALEN];
|
||||
DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS);
|
||||
|
@ -306,6 +322,12 @@ struct ath10k_peer {
|
|||
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
|
||||
};
|
||||
|
||||
struct ath10k_txq {
|
||||
struct list_head list;
|
||||
unsigned long num_fw_queued;
|
||||
unsigned long num_push_allowed;
|
||||
};
|
||||
|
||||
struct ath10k_sta {
|
||||
struct ath10k_vif *arvif;
|
||||
|
||||
|
@ -314,16 +336,18 @@ struct ath10k_sta {
|
|||
u32 bw;
|
||||
u32 nss;
|
||||
u32 smps;
|
||||
u16 peer_id;
|
||||
|
||||
struct work_struct update_wk;
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
/* protected by conf_mutex */
|
||||
bool aggr_mode;
|
||||
u64 rx_duration;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ)
|
||||
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ)
|
||||
|
||||
enum ath10k_beacon_state {
|
||||
ATH10K_BEACON_SCHEDULED = 0,
|
||||
|
@ -335,6 +359,7 @@ struct ath10k_vif {
|
|||
struct list_head list;
|
||||
|
||||
u32 vdev_id;
|
||||
u16 peer_id;
|
||||
enum wmi_vdev_type vdev_type;
|
||||
enum wmi_vdev_subtype vdev_subtype;
|
||||
u32 beacon_interval;
|
||||
|
@ -420,11 +445,12 @@ struct ath10k_debug {
|
|||
struct completion tpc_complete;
|
||||
|
||||
/* protected by conf_mutex */
|
||||
u32 fw_dbglog_mask;
|
||||
u64 fw_dbglog_mask;
|
||||
u32 fw_dbglog_level;
|
||||
u32 pktlog_filter;
|
||||
u32 reg_addr;
|
||||
u32 nf_cal_period;
|
||||
void *cal_data;
|
||||
|
||||
struct ath10k_fw_crash_data *fw_crash_data;
|
||||
};
|
||||
|
@ -512,6 +538,32 @@ enum ath10k_fw_features {
|
|||
/* Firmware Supports Adaptive CCA*/
|
||||
ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11,
|
||||
|
||||
/* Firmware supports management frame protection */
|
||||
ATH10K_FW_FEATURE_MFP_SUPPORT = 12,
|
||||
|
||||
/* Firmware supports pull-push model where host shares it's software
|
||||
* queue state with firmware and firmware generates fetch requests
|
||||
* telling host which queues to dequeue tx from.
|
||||
*
|
||||
* Primary function of this is improved MU-MIMO performance with
|
||||
* multiple clients.
|
||||
*/
|
||||
ATH10K_FW_FEATURE_PEER_FLOW_CONTROL = 13,
|
||||
|
||||
/* Firmware supports BT-Coex without reloading firmware via pdev param.
|
||||
* To support Bluetooth coexistence pdev param, WMI_COEX_GPIO_SUPPORT of
|
||||
* extended resource config should be enabled always. This firmware IE
|
||||
* is used to configure WMI_COEX_GPIO_SUPPORT.
|
||||
*/
|
||||
ATH10K_FW_FEATURE_BTCOEX_PARAM = 14,
|
||||
|
||||
/* Older firmware with HTT delivers incorrect tx status for null func
|
||||
* frames to driver, but this fixed in 10.2 and 10.4 firmware versions.
|
||||
* Also this workaround results in reporting of incorrect null func
|
||||
* status for 10.4. This flag is used to skip the workaround.
|
||||
*/
|
||||
ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR = 15,
|
||||
|
||||
/* keep last */
|
||||
ATH10K_FW_FEATURE_COUNT,
|
||||
};
|
||||
|
@ -534,12 +586,21 @@ enum ath10k_dev_flags {
|
|||
|
||||
/* Disable HW crypto engine */
|
||||
ATH10K_FLAG_HW_CRYPTO_DISABLED,
|
||||
|
||||
/* Bluetooth coexistance enabled */
|
||||
ATH10K_FLAG_BTCOEX,
|
||||
|
||||
/* Per Station statistics service */
|
||||
ATH10K_FLAG_PEER_STATS,
|
||||
};
|
||||
|
||||
enum ath10k_cal_mode {
|
||||
ATH10K_CAL_MODE_FILE,
|
||||
ATH10K_CAL_MODE_OTP,
|
||||
ATH10K_CAL_MODE_DT,
|
||||
ATH10K_PRE_CAL_MODE_FILE,
|
||||
ATH10K_PRE_CAL_MODE_DT,
|
||||
ATH10K_CAL_MODE_EEPROM,
|
||||
};
|
||||
|
||||
enum ath10k_crypt_mode {
|
||||
|
@ -558,6 +619,12 @@ static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
|
|||
return "otp";
|
||||
case ATH10K_CAL_MODE_DT:
|
||||
return "dt";
|
||||
case ATH10K_PRE_CAL_MODE_FILE:
|
||||
return "pre-cal-file";
|
||||
case ATH10K_PRE_CAL_MODE_DT:
|
||||
return "pre-cal-dt";
|
||||
case ATH10K_CAL_MODE_EEPROM:
|
||||
return "eeprom";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
|
@ -591,9 +658,47 @@ enum ath10k_tx_pause_reason {
|
|||
ATH10K_TX_PAUSE_MAX,
|
||||
};
|
||||
|
||||
struct ath10k_fw_file {
|
||||
const struct firmware *firmware;
|
||||
|
||||
char fw_version[ETHTOOL_FWVERS_LEN];
|
||||
|
||||
DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT);
|
||||
|
||||
enum ath10k_fw_wmi_op_version wmi_op_version;
|
||||
enum ath10k_fw_htt_op_version htt_op_version;
|
||||
|
||||
const void *firmware_data;
|
||||
size_t firmware_len;
|
||||
|
||||
const void *otp_data;
|
||||
size_t otp_len;
|
||||
|
||||
const void *codeswap_data;
|
||||
size_t codeswap_len;
|
||||
|
||||
/* The original idea of struct ath10k_fw_file was that it only
|
||||
* contains struct firmware and pointers to various parts (actual
|
||||
* firmware binary, otp, metadata etc) of the file. This seg_info
|
||||
* is actually created separate but as this is used similarly as
|
||||
* the other firmware components it's more convenient to have it
|
||||
* here.
|
||||
*/
|
||||
struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info;
|
||||
};
|
||||
|
||||
struct ath10k_fw_components {
|
||||
const struct firmware *board;
|
||||
const void *board_data;
|
||||
size_t board_len;
|
||||
|
||||
struct ath10k_fw_file fw_file;
|
||||
};
|
||||
|
||||
struct ath10k {
|
||||
struct ath_common ath_common;
|
||||
struct ieee80211_hw *hw;
|
||||
struct ieee80211_ops *ops;
|
||||
struct device *dev;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
|
||||
|
@ -616,8 +721,6 @@ struct ath10k {
|
|||
/* protected by conf_mutex */
|
||||
bool ani_enabled;
|
||||
|
||||
DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT);
|
||||
|
||||
bool p2p;
|
||||
|
||||
struct {
|
||||
|
@ -634,64 +737,19 @@ struct ath10k {
|
|||
struct ath10k_htc htc;
|
||||
struct ath10k_htt htt;
|
||||
|
||||
struct ath10k_hw_params {
|
||||
u32 id;
|
||||
u16 dev_id;
|
||||
const char *name;
|
||||
u32 patch_load_addr;
|
||||
int uart_pin;
|
||||
u32 otp_exe_param;
|
||||
struct ath10k_hw_params hw_params;
|
||||
|
||||
/* This is true if given HW chip has a quirky Cycle Counter
|
||||
* wraparound which resets to 0x7fffffff instead of 0. All
|
||||
* other CC related counters (e.g. Rx Clear Count) are divided
|
||||
* by 2 so they never wraparound themselves.
|
||||
*/
|
||||
bool has_shifted_cc_wraparound;
|
||||
/* contains the firmware images used with ATH10K_FIRMWARE_MODE_NORMAL */
|
||||
struct ath10k_fw_components normal_mode_fw;
|
||||
|
||||
/* Some of chip expects fragment descriptor to be continuous
|
||||
* memory for any TX operation. Set continuous_frag_desc flag
|
||||
* for the hardware which have such requirement.
|
||||
*/
|
||||
bool continuous_frag_desc;
|
||||
|
||||
u32 channel_counters_freq_hz;
|
||||
|
||||
/* Mgmt tx descriptors threshold for limiting probe response
|
||||
* frames.
|
||||
*/
|
||||
u32 max_probe_resp_desc_thres;
|
||||
|
||||
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;
|
||||
|
||||
const struct firmware *board;
|
||||
const void *board_data;
|
||||
size_t board_len;
|
||||
|
||||
const struct firmware *otp;
|
||||
const void *otp_data;
|
||||
size_t otp_len;
|
||||
|
||||
const struct firmware *firmware;
|
||||
const void *firmware_data;
|
||||
size_t firmware_len;
|
||||
/* READ-ONLY images of the running firmware, which can be either
|
||||
* normal or UTF. Do not modify, release etc!
|
||||
*/
|
||||
const struct ath10k_fw_components *running_fw;
|
||||
|
||||
const struct firmware *pre_cal_file;
|
||||
const struct firmware *cal_file;
|
||||
|
||||
struct {
|
||||
const void *firmware_codeswap_data;
|
||||
size_t firmware_codeswap_len;
|
||||
struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info;
|
||||
} swap;
|
||||
|
||||
struct {
|
||||
u32 vendor;
|
||||
u32 device;
|
||||
|
@ -720,7 +778,7 @@ struct ath10k {
|
|||
} scan;
|
||||
|
||||
struct {
|
||||
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
|
||||
struct ieee80211_supported_band sbands[NUM_NL80211_BANDS];
|
||||
} mac;
|
||||
|
||||
/* should never be NULL; needed for regular htt rx */
|
||||
|
@ -732,6 +790,9 @@ struct ath10k {
|
|||
/* current operating channel definition */
|
||||
struct cfg80211_chan_def chandef;
|
||||
|
||||
/* currently configured operating channel in firmware */
|
||||
struct ieee80211_channel *tgt_oper_chan;
|
||||
|
||||
unsigned long long free_vdev_map;
|
||||
struct ath10k_vif *monitor_arvif;
|
||||
bool monitor;
|
||||
|
@ -762,9 +823,13 @@ struct ath10k {
|
|||
|
||||
/* protects shared structure data */
|
||||
spinlock_t data_lock;
|
||||
/* protects: ar->txqs, artxq->list */
|
||||
spinlock_t txqs_lock;
|
||||
|
||||
struct list_head txqs;
|
||||
struct list_head arvifs;
|
||||
struct list_head peers;
|
||||
struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS];
|
||||
wait_queue_head_t peer_mapping_wq;
|
||||
|
||||
/* protected by conf_mutex */
|
||||
|
@ -807,6 +872,7 @@ struct ath10k {
|
|||
* avoid reporting garbage data.
|
||||
*/
|
||||
bool ch_info_can_report_survey;
|
||||
struct completion bss_survey_done;
|
||||
|
||||
struct dfs_pattern_detector *dfs_detector;
|
||||
|
||||
|
@ -814,8 +880,6 @@ struct ath10k {
|
|||
|
||||
#ifdef CONFIG_ATH10K_DEBUGFS
|
||||
struct ath10k_debug debug;
|
||||
#endif
|
||||
|
||||
struct {
|
||||
/* relay(fs) channel for spectral scan */
|
||||
struct rchan *rfs_chan_spec_scan;
|
||||
|
@ -824,16 +888,12 @@ struct ath10k {
|
|||
enum ath10k_spectral_mode mode;
|
||||
struct ath10k_spec_scan config;
|
||||
} spectral;
|
||||
#endif
|
||||
|
||||
struct {
|
||||
/* protected by conf_mutex */
|
||||
const struct firmware *utf;
|
||||
char utf_version[32];
|
||||
const void *utf_firmware_data;
|
||||
size_t utf_firmware_len;
|
||||
DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
|
||||
enum ath10k_fw_wmi_op_version orig_wmi_op_version;
|
||||
enum ath10k_fw_wmi_op_version op_version;
|
||||
struct ath10k_fw_components utf_mode_fw;
|
||||
|
||||
/* protected by data_lock */
|
||||
bool utf_monitor;
|
||||
} testmode;
|
||||
|
@ -848,10 +908,23 @@ struct ath10k {
|
|||
struct ath10k_thermal thermal;
|
||||
struct ath10k_wow wow;
|
||||
|
||||
/* NAPI */
|
||||
struct net_device napi_dev;
|
||||
struct napi_struct napi;
|
||||
|
||||
/* must be last */
|
||||
u8 drv_priv[0] __aligned(sizeof(void *));
|
||||
};
|
||||
|
||||
static inline bool ath10k_peer_stats_enabled(struct ath10k *ar)
|
||||
{
|
||||
if (test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) &&
|
||||
test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
||||
enum ath10k_bus bus,
|
||||
enum ath10k_hw_rev hw_rev,
|
||||
|
@ -860,8 +933,11 @@ void ath10k_core_destroy(struct ath10k *ar);
|
|||
void ath10k_core_get_fw_features_str(struct ath10k *ar,
|
||||
char *buf,
|
||||
size_t max_len);
|
||||
int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
|
||||
struct ath10k_fw_file *fw_file);
|
||||
|
||||
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode);
|
||||
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
const struct ath10k_fw_components *fw_components);
|
||||
int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
|
||||
void ath10k_core_stop(struct ath10k *ar);
|
||||
int ath10k_core_register(struct ath10k *ar, u32 chip_id);
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <linux/debugfs.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
|
@ -28,6 +30,8 @@
|
|||
/* ms */
|
||||
#define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
|
||||
|
||||
#define ATH10K_DEBUG_CAL_DATA_LEN 12064
|
||||
|
||||
#define ATH10K_FW_CRASH_DUMP_VERSION 1
|
||||
|
||||
/**
|
||||
|
@ -122,43 +126,73 @@ void ath10k_info(struct ath10k *ar, const char *fmt, ...)
|
|||
}
|
||||
EXPORT_SYMBOL(ath10k_info);
|
||||
|
||||
void ath10k_print_driver_info(struct ath10k *ar)
|
||||
void ath10k_debug_print_hwfw_info(struct ath10k *ar)
|
||||
{
|
||||
const struct firmware *firmware;
|
||||
char fw_features[128] = {};
|
||||
char boardinfo[100];
|
||||
u32 crc = 0;
|
||||
|
||||
ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
|
||||
|
||||
if (ar->id.bmi_ids_valid)
|
||||
scnprintf(boardinfo, sizeof(boardinfo), "bmi %d:%d",
|
||||
ar->id.bmi_chip_id, ar->id.bmi_board_id);
|
||||
else
|
||||
scnprintf(boardinfo, sizeof(boardinfo), "sub %04x:%04x",
|
||||
ar->id.subsystem_vendor, ar->id.subsystem_device);
|
||||
|
||||
ath10k_info(ar, "%s (0x%08x, 0x%08x %s) fw %s fwapi %d bdapi %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n",
|
||||
ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x",
|
||||
ar->hw_params.name,
|
||||
ar->target_version,
|
||||
ar->chip_id,
|
||||
boardinfo,
|
||||
ar->id.subsystem_vendor, ar->id.subsystem_device);
|
||||
|
||||
ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n",
|
||||
IS_ENABLED(CONFIG_ATH10K_DEBUG),
|
||||
IS_ENABLED(CONFIG_ATH10K_DEBUGFS),
|
||||
IS_ENABLED(CONFIG_ATH10K_TRACING),
|
||||
IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED),
|
||||
IS_ENABLED(CONFIG_NL80211_TESTMODE));
|
||||
|
||||
firmware = ar->normal_mode_fw.fw_file.firmware;
|
||||
if (firmware)
|
||||
crc = crc32_le(0, firmware->data, firmware->size);
|
||||
|
||||
ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",
|
||||
ar->hw->wiphy->fw_version,
|
||||
ar->fw_api,
|
||||
fw_features,
|
||||
crc);
|
||||
}
|
||||
|
||||
void ath10k_debug_print_board_info(struct ath10k *ar)
|
||||
{
|
||||
char boardinfo[100];
|
||||
|
||||
if (ar->id.bmi_ids_valid)
|
||||
scnprintf(boardinfo, sizeof(boardinfo), "%d:%d",
|
||||
ar->id.bmi_chip_id, ar->id.bmi_board_id);
|
||||
else
|
||||
scnprintf(boardinfo, sizeof(boardinfo), "N/A");
|
||||
|
||||
ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x",
|
||||
ar->bd_api,
|
||||
boardinfo,
|
||||
crc32_le(0, ar->normal_mode_fw.board->data,
|
||||
ar->normal_mode_fw.board->size));
|
||||
}
|
||||
|
||||
void ath10k_debug_print_boot_info(struct ath10k *ar)
|
||||
{
|
||||
ath10k_info(ar, "htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d\n",
|
||||
ar->htt.target_version_major,
|
||||
ar->htt.target_version_minor,
|
||||
ar->wmi.op_version,
|
||||
ar->htt.op_version,
|
||||
ar->normal_mode_fw.fw_file.wmi_op_version,
|
||||
ar->normal_mode_fw.fw_file.htt_op_version,
|
||||
ath10k_cal_mode_str(ar->cal_mode),
|
||||
ar->max_num_stations,
|
||||
test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
|
||||
!test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags),
|
||||
fw_features);
|
||||
ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
|
||||
config_enabled(CONFIG_ATH10K_DEBUG),
|
||||
config_enabled(CONFIG_ATH10K_DEBUGFS),
|
||||
config_enabled(CONFIG_ATH10K_TRACING),
|
||||
config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
|
||||
config_enabled(CONFIG_NL80211_TESTMODE));
|
||||
!test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags));
|
||||
}
|
||||
|
||||
void ath10k_print_driver_info(struct ath10k *ar)
|
||||
{
|
||||
ath10k_debug_print_hwfw_info(ar);
|
||||
ath10k_debug_print_board_info(ar);
|
||||
ath10k_debug_print_boot_info(ar);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_print_driver_info);
|
||||
|
||||
|
@ -251,7 +285,7 @@ static const struct file_operations fops_wmi_services = {
|
|||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
|
||||
static void ath10k_fw_stats_pdevs_free(struct list_head *head)
|
||||
{
|
||||
struct ath10k_fw_stats_pdev *i, *tmp;
|
||||
|
||||
|
@ -261,7 +295,7 @@ static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
|
|||
}
|
||||
}
|
||||
|
||||
static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head)
|
||||
static void ath10k_fw_stats_vdevs_free(struct list_head *head)
|
||||
{
|
||||
struct ath10k_fw_stats_vdev *i, *tmp;
|
||||
|
||||
|
@ -271,7 +305,7 @@ static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head)
|
|||
}
|
||||
}
|
||||
|
||||
static void ath10k_debug_fw_stats_peers_free(struct list_head *head)
|
||||
static void ath10k_fw_stats_peers_free(struct list_head *head)
|
||||
{
|
||||
struct ath10k_fw_stats_peer *i, *tmp;
|
||||
|
||||
|
@ -281,13 +315,25 @@ static void ath10k_debug_fw_stats_peers_free(struct list_head *head)
|
|||
}
|
||||
}
|
||||
|
||||
static void ath10k_fw_extd_stats_peers_free(struct list_head *head)
|
||||
{
|
||||
struct ath10k_fw_extd_stats_peer *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
|
||||
{
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->debug.fw_stats_done = false;
|
||||
ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
|
||||
ath10k_debug_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
|
||||
ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers);
|
||||
ar->debug.fw_stats.extended = false;
|
||||
ath10k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
|
||||
ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
|
||||
ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
|
||||
ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
|
@ -302,6 +348,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
|
|||
INIT_LIST_HEAD(&stats.pdevs);
|
||||
INIT_LIST_HEAD(&stats.vdevs);
|
||||
INIT_LIST_HEAD(&stats.peers);
|
||||
INIT_LIST_HEAD(&stats.peers_extd);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
|
||||
|
@ -321,9 +368,13 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
|
|||
* b) consume stat update events until another one with pdev stats is
|
||||
* delivered which is treated as end-of-data and is itself discarded
|
||||
*/
|
||||
if (ath10k_peer_stats_enabled(ar))
|
||||
ath10k_sta_update_rx_duration(ar, &stats);
|
||||
|
||||
if (ar->debug.fw_stats_done) {
|
||||
ath10k_warn(ar, "received unsolicited stats update event\n");
|
||||
if (!ath10k_peer_stats_enabled(ar))
|
||||
ath10k_warn(ar, "received unsolicited stats update event\n");
|
||||
|
||||
goto free;
|
||||
}
|
||||
|
||||
|
@ -347,17 +398,21 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
|
|||
/* Although this is unlikely impose a sane limit to
|
||||
* prevent firmware from DoS-ing the host.
|
||||
*/
|
||||
ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
|
||||
ath10k_warn(ar, "dropping fw peer stats\n");
|
||||
goto free;
|
||||
}
|
||||
|
||||
if (num_vdevs >= BITS_PER_LONG) {
|
||||
ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
|
||||
ath10k_warn(ar, "dropping fw vdev stats\n");
|
||||
goto free;
|
||||
}
|
||||
|
||||
list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
|
||||
list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
|
||||
list_splice_tail_init(&stats.peers_extd,
|
||||
&ar->debug.fw_stats.peers_extd);
|
||||
}
|
||||
|
||||
complete(&ar->debug.fw_stats_complete);
|
||||
|
@ -366,9 +421,10 @@ free:
|
|||
/* In some cases lists have been spliced and cleared. Free up
|
||||
* resources if that is not the case.
|
||||
*/
|
||||
ath10k_debug_fw_stats_pdevs_free(&stats.pdevs);
|
||||
ath10k_debug_fw_stats_vdevs_free(&stats.vdevs);
|
||||
ath10k_debug_fw_stats_peers_free(&stats.peers);
|
||||
ath10k_fw_stats_pdevs_free(&stats.pdevs);
|
||||
ath10k_fw_stats_vdevs_free(&stats.vdevs);
|
||||
ath10k_fw_stats_peers_free(&stats.peers);
|
||||
ath10k_fw_extd_stats_peers_free(&stats.peers_extd);
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
@ -571,25 +627,23 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
|
|||
char buf[32];
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
|
||||
|
||||
/* make sure that buf is null terminated */
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
|
||||
/* drop the possible '\n' from the end */
|
||||
if (buf[count - 1] == '\n')
|
||||
buf[count - 1] = 0;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON &&
|
||||
ar->state != ATH10K_STATE_RESTARTED) {
|
||||
ret = -ENETDOWN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* drop the possible '\n' from the end */
|
||||
if (buf[count - 1] == '\n') {
|
||||
buf[count - 1] = 0;
|
||||
count--;
|
||||
}
|
||||
|
||||
if (!strcmp(buf, "soft")) {
|
||||
ath10k_info(ar, "simulating soft firmware crash\n");
|
||||
ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
|
||||
|
@ -1114,7 +1168,7 @@ static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
|
|||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
char buf[64];
|
||||
u8 amsdu = 3, ampdu = 64;
|
||||
u8 amsdu, ampdu;
|
||||
unsigned int len;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
@ -1176,9 +1230,9 @@ static ssize_t ath10k_read_fw_dbglog(struct file *file,
|
|||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
unsigned int len;
|
||||
char buf[64];
|
||||
char buf[96];
|
||||
|
||||
len = scnprintf(buf, sizeof(buf), "0x%08x %u\n",
|
||||
len = scnprintf(buf, sizeof(buf), "0x%16llx %u\n",
|
||||
ar->debug.fw_dbglog_mask, ar->debug.fw_dbglog_level);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
|
@ -1190,15 +1244,16 @@ static ssize_t ath10k_write_fw_dbglog(struct file *file,
|
|||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
int ret;
|
||||
char buf[64];
|
||||
unsigned int log_level, mask;
|
||||
char buf[96];
|
||||
unsigned int log_level;
|
||||
u64 mask;
|
||||
|
||||
simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
|
||||
|
||||
/* make sure that buf is null terminated */
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
|
||||
ret = sscanf(buf, "%x %u", &mask, &log_level);
|
||||
ret = sscanf(buf, "%llx %u", &mask, &log_level);
|
||||
|
||||
if (!ret)
|
||||
return -EINVAL;
|
||||
|
@ -1398,74 +1453,68 @@ static const struct file_operations fops_fw_dbglog = {
|
|||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
|
||||
static int ath10k_debug_cal_data_fetch(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k *ar = inode->i_private;
|
||||
void *buf;
|
||||
u32 hi_addr;
|
||||
__le32 addr;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON &&
|
||||
ar->state != ATH10K_STATE_UTF) {
|
||||
ret = -ENETDOWN;
|
||||
goto err;
|
||||
}
|
||||
|
||||
buf = vmalloc(QCA988X_CAL_DATA_LEN);
|
||||
if (!buf) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
if (WARN_ON(ar->hw_params.cal_data_len > ATH10K_DEBUG_CAL_DATA_LEN))
|
||||
return -EINVAL;
|
||||
|
||||
hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
|
||||
|
||||
ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret);
|
||||
goto err_vfree;
|
||||
ath10k_warn(ar, "failed to read hi_board_data address: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
|
||||
QCA988X_CAL_DATA_LEN);
|
||||
ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), ar->debug.cal_data,
|
||||
ar->hw_params.cal_data_len);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
|
||||
goto err_vfree;
|
||||
return ret;
|
||||
}
|
||||
|
||||
file->private_data = buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct ath10k *ar = inode->i_private;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state == ATH10K_STATE_ON ||
|
||||
ar->state == ATH10K_STATE_UTF) {
|
||||
ath10k_debug_cal_data_fetch(ar);
|
||||
}
|
||||
|
||||
file->private_data = ar;
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
err_vfree:
|
||||
vfree(buf);
|
||||
|
||||
err:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ath10k_debug_cal_data_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
void *buf = file->private_data;
|
||||
struct ath10k *ar = file->private_data;
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos,
|
||||
buf, QCA988X_CAL_DATA_LEN);
|
||||
}
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
static int ath10k_debug_cal_data_release(struct inode *inode,
|
||||
struct file *file)
|
||||
{
|
||||
vfree(file->private_data);
|
||||
count = simple_read_from_buffer(user_buf, count, ppos,
|
||||
ar->debug.cal_data,
|
||||
ar->hw_params.cal_data_len);
|
||||
|
||||
return 0;
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ath10k_write_ani_enable(struct file *file,
|
||||
|
@ -1526,7 +1575,6 @@ static const struct file_operations fops_ani_enable = {
|
|||
static const struct file_operations fops_cal_data = {
|
||||
.open = ath10k_debug_cal_data_open,
|
||||
.read = ath10k_debug_cal_data_read,
|
||||
.release = ath10k_debug_cal_data_release,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
@ -1878,6 +1926,8 @@ void ath10k_debug_stop(struct ath10k *ar)
|
|||
{
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
ath10k_debug_cal_data_fetch(ar);
|
||||
|
||||
/* Must not use _sync to avoid deadlock, we do that in
|
||||
* ath10k_debug_destroy(). The check for htt_stats_mask is to avoid
|
||||
* warning from del_timer(). */
|
||||
|
@ -2079,15 +2129,225 @@ static const struct file_operations fops_quiet_period = {
|
|||
.open = simple_open
|
||||
};
|
||||
|
||||
static ssize_t ath10k_write_btcoex(struct file *file,
|
||||
const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
char buf[32];
|
||||
size_t buf_size;
|
||||
int ret;
|
||||
bool val;
|
||||
u32 pdev_param;
|
||||
|
||||
buf_size = min(count, (sizeof(buf) - 1));
|
||||
if (copy_from_user(buf, ubuf, buf_size))
|
||||
return -EFAULT;
|
||||
|
||||
buf[buf_size] = '\0';
|
||||
|
||||
if (strtobool(buf, &val) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON &&
|
||||
ar->state != ATH10K_STATE_RESTARTED) {
|
||||
ret = -ENETDOWN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) {
|
||||
ret = count;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pdev_param = ar->wmi.pdev_param->enable_btcoex;
|
||||
if (test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM,
|
||||
ar->running_fw->fw_file.fw_features)) {
|
||||
ret = ath10k_wmi_pdev_set_param(ar, pdev_param, val);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to enable btcoex: %d\n", ret);
|
||||
ret = count;
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
ath10k_info(ar, "restarting firmware due to btcoex change");
|
||||
queue_work(ar->workqueue, &ar->restart_work);
|
||||
}
|
||||
|
||||
if (val)
|
||||
set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
|
||||
else
|
||||
clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
|
||||
|
||||
ret = count;
|
||||
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char buf[32];
|
||||
struct ath10k *ar = file->private_data;
|
||||
int len = 0;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
len = scnprintf(buf, sizeof(buf) - len, "%d\n",
|
||||
test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_btcoex = {
|
||||
.read = ath10k_read_btcoex,
|
||||
.write = ath10k_write_btcoex,
|
||||
.open = simple_open
|
||||
};
|
||||
|
||||
static ssize_t ath10k_write_peer_stats(struct file *file,
|
||||
const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
char buf[32];
|
||||
size_t buf_size;
|
||||
int ret;
|
||||
bool val;
|
||||
|
||||
buf_size = min(count, (sizeof(buf) - 1));
|
||||
if (copy_from_user(buf, ubuf, buf_size))
|
||||
return -EFAULT;
|
||||
|
||||
buf[buf_size] = '\0';
|
||||
|
||||
if (strtobool(buf, &val) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON &&
|
||||
ar->state != ATH10K_STATE_RESTARTED) {
|
||||
ret = -ENETDOWN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val)) {
|
||||
ret = count;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (val)
|
||||
set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
|
||||
else
|
||||
clear_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
|
||||
|
||||
ath10k_info(ar, "restarting firmware due to Peer stats change");
|
||||
|
||||
queue_work(ar->workqueue, &ar->restart_work);
|
||||
ret = count;
|
||||
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ath10k_read_peer_stats(struct file *file, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
||||
{
|
||||
char buf[32];
|
||||
struct ath10k *ar = file->private_data;
|
||||
int len = 0;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
len = scnprintf(buf, sizeof(buf) - len, "%d\n",
|
||||
test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags));
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_peer_stats = {
|
||||
.read = ath10k_read_peer_stats,
|
||||
.write = ath10k_write_peer_stats,
|
||||
.open = simple_open
|
||||
};
|
||||
|
||||
static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
unsigned int len = 0, buf_len = 4096;
|
||||
ssize_t ret_cnt;
|
||||
char *buf;
|
||||
|
||||
buf = kzalloc(buf_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"firmware-N.bin\t\t%08x\n",
|
||||
crc32_le(0, ar->normal_mode_fw.fw_file.firmware->data,
|
||||
ar->normal_mode_fw.fw_file.firmware->size));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"athwlan\t\t\t%08x\n",
|
||||
crc32_le(0, ar->normal_mode_fw.fw_file.firmware_data,
|
||||
ar->normal_mode_fw.fw_file.firmware_len));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"otp\t\t\t%08x\n",
|
||||
crc32_le(0, ar->normal_mode_fw.fw_file.otp_data,
|
||||
ar->normal_mode_fw.fw_file.otp_len));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"codeswap\t\t%08x\n",
|
||||
crc32_le(0, ar->normal_mode_fw.fw_file.codeswap_data,
|
||||
ar->normal_mode_fw.fw_file.codeswap_len));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"board-N.bin\t\t%08x\n",
|
||||
crc32_le(0, ar->normal_mode_fw.board->data,
|
||||
ar->normal_mode_fw.board->size));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"board\t\t\t%08x\n",
|
||||
crc32_le(0, ar->normal_mode_fw.board_data,
|
||||
ar->normal_mode_fw.board_len));
|
||||
|
||||
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
kfree(buf);
|
||||
return ret_cnt;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_fw_checksums = {
|
||||
.read = ath10k_debug_fw_checksums_read,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
int ath10k_debug_create(struct ath10k *ar)
|
||||
{
|
||||
ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
|
||||
if (!ar->debug.fw_crash_data)
|
||||
return -ENOMEM;
|
||||
|
||||
ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
|
||||
if (!ar->debug.cal_data)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
|
||||
INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
|
||||
INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
|
||||
INIT_LIST_HEAD(&ar->debug.fw_stats.peers_extd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2097,6 +2357,9 @@ void ath10k_debug_destroy(struct ath10k *ar)
|
|||
vfree(ar->debug.fw_crash_data);
|
||||
ar->debug.fw_crash_data = NULL;
|
||||
|
||||
vfree(ar->debug.cal_data);
|
||||
ar->debug.cal_data = NULL;
|
||||
|
||||
ath10k_debug_fw_stats_reset(ar);
|
||||
|
||||
kfree(ar->debug.tpc_stats);
|
||||
|
@ -2128,8 +2391,8 @@ int ath10k_debug_register(struct ath10k *ar)
|
|||
debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
|
||||
&fops_wmi_services);
|
||||
|
||||
debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_simulate_fw_crash);
|
||||
debugfs_create_file("simulate_fw_crash", S_IRUSR | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_simulate_fw_crash);
|
||||
|
||||
debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_fw_crash_dump);
|
||||
|
@ -2146,15 +2409,15 @@ int ath10k_debug_register(struct ath10k *ar)
|
|||
debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_chip_id);
|
||||
|
||||
debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_htt_stats_mask);
|
||||
debugfs_create_file("htt_stats_mask", S_IRUSR | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_htt_stats_mask);
|
||||
|
||||
debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar,
|
||||
&fops_htt_max_amsdu_ampdu);
|
||||
|
||||
debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_fw_dbglog);
|
||||
debugfs_create_file("fw_dbglog", S_IRUSR | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_fw_dbglog);
|
||||
|
||||
debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_cal_data);
|
||||
|
@ -2165,7 +2428,7 @@ int ath10k_debug_register(struct ath10k *ar)
|
|||
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)) {
|
||||
if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {
|
||||
debugfs_create_file("dfs_simulate_radar", S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar,
|
||||
&fops_simulate_radar);
|
||||
|
@ -2188,6 +2451,18 @@ int ath10k_debug_register(struct ath10k *ar)
|
|||
debugfs_create_file("tpc_stats", S_IRUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_tpc_stats);
|
||||
|
||||
if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
|
||||
debugfs_create_file("btcoex", S_IRUGO | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_btcoex);
|
||||
|
||||
if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
|
||||
debugfs_create_file("peer_stats", S_IRUGO | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar,
|
||||
&fops_peer_stats);
|
||||
|
||||
debugfs_create_file("fw_checksums", S_IRUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_fw_checksums);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ enum ath10k_debug_mask {
|
|||
ATH10K_DBG_TESTMODE = 0x00001000,
|
||||
ATH10K_DBG_WMI_PRINT = 0x00002000,
|
||||
ATH10K_DBG_PCI_PS = 0x00004000,
|
||||
ATH10K_DBG_AHB = 0x00008000,
|
||||
ATH10K_DBG_ANY = 0xffffffff,
|
||||
};
|
||||
|
||||
|
@ -56,13 +57,17 @@ enum ath10k_dbg_aggr_mode {
|
|||
};
|
||||
|
||||
/* FIXME: How to calculate the buffer size sanely? */
|
||||
#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
|
||||
#define ATH10K_FW_STATS_BUF_SIZE (1024 * 1024)
|
||||
|
||||
extern unsigned int ath10k_debug_mask;
|
||||
|
||||
__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
|
||||
__printf(2, 3) void ath10k_err(struct ath10k *ar, const char *fmt, ...);
|
||||
__printf(2, 3) void ath10k_warn(struct ath10k *ar, const char *fmt, ...);
|
||||
|
||||
void ath10k_debug_print_hwfw_info(struct ath10k *ar);
|
||||
void ath10k_debug_print_board_info(struct ath10k *ar);
|
||||
void ath10k_debug_print_boot_info(struct ath10k *ar);
|
||||
void ath10k_print_driver_info(struct ath10k *ar);
|
||||
|
||||
#ifdef CONFIG_ATH10K_DEBUGFS
|
||||
|
@ -149,6 +154,17 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
|
|||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct dentry *dir);
|
||||
void ath10k_sta_update_rx_duration(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *stats);
|
||||
void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct station_info *sinfo);
|
||||
#else
|
||||
static inline
|
||||
void ath10k_sta_update_rx_duration(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *stats)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_MAC80211_DEBUGFS */
|
||||
|
||||
#ifdef CONFIG_ATH10K_DEBUG
|
||||
|
|
|
@ -18,6 +18,67 @@
|
|||
#include "wmi-ops.h"
|
||||
#include "debug.h"
|
||||
|
||||
static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *stats)
|
||||
{
|
||||
struct ath10k_fw_extd_stats_peer *peer;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ath10k_sta *arsta;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry(peer, &stats->peers_extd, list) {
|
||||
sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
|
||||
NULL);
|
||||
if (!sta)
|
||||
continue;
|
||||
arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||
arsta->rx_duration += (u64)peer->rx_duration;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void ath10k_sta_update_stats_rx_duration(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *stats)
|
||||
{
|
||||
struct ath10k_fw_stats_peer *peer;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ath10k_sta *arsta;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry(peer, &stats->peers, list) {
|
||||
sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
|
||||
NULL);
|
||||
if (!sta)
|
||||
continue;
|
||||
arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||
arsta->rx_duration += (u64)peer->rx_duration;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void ath10k_sta_update_rx_duration(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *stats)
|
||||
{
|
||||
if (stats->extended)
|
||||
ath10k_sta_update_extd_stats_rx_duration(ar, stats);
|
||||
else
|
||||
ath10k_sta_update_stats_rx_duration(ar, stats);
|
||||
}
|
||||
|
||||
void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct station_info *sinfo)
|
||||
{
|
||||
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||
struct ath10k *ar = arsta->arvif->ar;
|
||||
|
||||
if (!ath10k_peer_stats_enabled(ar))
|
||||
return;
|
||||
|
||||
sinfo->rx_duration = arsta->rx_duration;
|
||||
sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION;
|
||||
}
|
||||
|
||||
static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
|
|
@ -87,6 +87,10 @@ struct ath10k_hif_ops {
|
|||
|
||||
int (*suspend)(struct ath10k *ar);
|
||||
int (*resume)(struct ath10k *ar);
|
||||
|
||||
/* fetch calibration data from target eeprom */
|
||||
int (*fetch_cal_eeprom)(struct ath10k *ar, void **data,
|
||||
size_t *data_len);
|
||||
};
|
||||
|
||||
static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
|
||||
|
@ -202,4 +206,14 @@ static inline void ath10k_hif_write32(struct ath10k *ar,
|
|||
ar->hif.ops->write32(ar, address, data);
|
||||
}
|
||||
|
||||
static inline int ath10k_hif_fetch_cal_eeprom(struct ath10k *ar,
|
||||
void **data,
|
||||
size_t *data_len)
|
||||
{
|
||||
if (!ar->hif.ops->fetch_cal_eeprom)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar->hif.ops->fetch_cal_eeprom(ar, data, data_len);
|
||||
}
|
||||
|
||||
#endif /* _HIF_H_ */
|
||||
|
|
|
@ -44,7 +44,7 @@ static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar)
|
|||
skb_cb = ATH10K_SKB_CB(skb);
|
||||
memset(skb_cb, 0, sizeof(*skb_cb));
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: skb %p\n", __func__, skb);
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: skb %pK\n", __func__, skb);
|
||||
return skb;
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
|
|||
{
|
||||
struct ath10k *ar = ep->htc->ar;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %p\n", __func__,
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %pK\n", __func__,
|
||||
ep->eid, skb);
|
||||
|
||||
ath10k_htc_restore_tx_skb(ep->htc, skb);
|
||||
|
@ -404,7 +404,7 @@ void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
|
|||
goto out;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %p\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %pK\n",
|
||||
eid, skb);
|
||||
ep->ep_ops.ep_rx_complete(ar, skb);
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <linux/list.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
struct ath10k;
|
||||
|
@ -297,10 +296,10 @@ struct ath10k_htc_svc_conn_resp {
|
|||
#define ATH10K_NUM_CONTROL_TX_BUFFERS 2
|
||||
#define ATH10K_HTC_MAX_LEN 4096
|
||||
#define ATH10K_HTC_MAX_CTRL_MSG_LEN 256
|
||||
#define ATH10K_HTC_WAIT_TIMEOUT_HZ (1*HZ)
|
||||
#define ATH10K_HTC_WAIT_TIMEOUT_HZ (1 * HZ)
|
||||
#define ATH10K_HTC_CONTROL_BUFFER_SIZE (ATH10K_HTC_MAX_CTRL_MSG_LEN + \
|
||||
sizeof(struct ath10k_htc_hdr))
|
||||
#define ATH10K_HTC_CONN_SVC_TIMEOUT_HZ (1*HZ)
|
||||
#define ATH10K_HTC_CONN_SVC_TIMEOUT_HZ (1 * HZ)
|
||||
|
||||
struct ath10k_htc_ep {
|
||||
struct ath10k_htc *htc;
|
||||
|
|
|
@ -131,12 +131,12 @@ static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] = {
|
|||
[HTT_10_4_T2H_MSG_TYPE_AGGR_CONF] = HTT_T2H_MSG_TYPE_AGGR_CONF,
|
||||
[HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND] =
|
||||
HTT_T2H_MSG_TYPE_TX_FETCH_IND,
|
||||
[HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONF] =
|
||||
HTT_T2H_MSG_TYPE_TX_FETCH_CONF,
|
||||
[HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONFIRM] =
|
||||
HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM,
|
||||
[HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD] =
|
||||
HTT_T2H_MSG_TYPE_STATS_NOUPLOAD,
|
||||
[HTT_10_4_T2H_MSG_TYPE_TX_LOW_LATENCY_IND] =
|
||||
HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND,
|
||||
[HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND] =
|
||||
HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND,
|
||||
};
|
||||
|
||||
int ath10k_htt_connect(struct ath10k_htt *htt)
|
||||
|
@ -149,7 +149,7 @@ int ath10k_htt_connect(struct ath10k_htt *htt)
|
|||
memset(&conn_resp, 0, sizeof(conn_resp));
|
||||
|
||||
conn_req.ep_ops.ep_tx_complete = ath10k_htt_htc_tx_complete;
|
||||
conn_req.ep_ops.ep_rx_complete = ath10k_htt_t2h_msg_handler;
|
||||
conn_req.ep_ops.ep_rx_complete = ath10k_htt_htc_t2h_msg_handler;
|
||||
|
||||
/* connect to control service */
|
||||
conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_DATA_MSG;
|
||||
|
@ -183,7 +183,7 @@ int ath10k_htt_init(struct ath10k *ar)
|
|||
8 + /* llc snap */
|
||||
2; /* ip4 dscp or ip6 priority */
|
||||
|
||||
switch (ar->htt.op_version) {
|
||||
switch (ar->running_fw->fw_file.htt_op_version) {
|
||||
case ATH10K_FW_HTT_OP_VERSION_10_4:
|
||||
ar->htt.t2h_msg_types = htt_10_4_t2h_msg_types;
|
||||
ar->htt.t2h_msg_types_max = HTT_10_4_T2H_NUM_MSGS;
|
||||
|
@ -208,7 +208,7 @@ int ath10k_htt_init(struct ath10k *ar)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define HTT_TARGET_VERSION_TIMEOUT_HZ (3*HZ)
|
||||
#define HTT_TARGET_VERSION_TIMEOUT_HZ (3 * HZ)
|
||||
|
||||
static int ath10k_htt_verify_version(struct ath10k_htt *htt)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/dmapool.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "htc.h"
|
||||
|
@ -52,6 +53,7 @@ enum htt_h2t_msg_type { /* host-to-target */
|
|||
/* This command is used for sending management frames in HTT < 3.0.
|
||||
* HTT >= 3.0 uses TX_FRM for everything. */
|
||||
HTT_H2T_MSG_TYPE_MGMT_TX = 7,
|
||||
HTT_H2T_MSG_TYPE_TX_FETCH_RESP = 11,
|
||||
|
||||
HTT_H2T_NUM_MSGS /* keep this last */
|
||||
};
|
||||
|
@ -166,8 +168,13 @@ struct htt_data_tx_desc {
|
|||
__le16 len;
|
||||
__le16 id;
|
||||
__le32 frags_paddr;
|
||||
__le16 peerid;
|
||||
__le16 freq;
|
||||
union {
|
||||
__le32 peerid;
|
||||
struct {
|
||||
__le16 peerid;
|
||||
__le16 freq;
|
||||
} __packed offchan_tx;
|
||||
} __packed;
|
||||
u8 prefetch[0]; /* start of frame, for FW classification engine */
|
||||
} __packed;
|
||||
|
||||
|
@ -408,10 +415,10 @@ enum htt_10_4_t2h_msg_type {
|
|||
HTT_10_4_T2H_MSG_TYPE_EN_STATS = 0x14,
|
||||
HTT_10_4_T2H_MSG_TYPE_AGGR_CONF = 0x15,
|
||||
HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND = 0x16,
|
||||
HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONF = 0x17,
|
||||
HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONFIRM = 0x17,
|
||||
HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD = 0x18,
|
||||
/* 0x19 to 0x2f are reserved */
|
||||
HTT_10_4_T2H_MSG_TYPE_TX_LOW_LATENCY_IND = 0x30,
|
||||
HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND = 0x30,
|
||||
/* keep this last */
|
||||
HTT_10_4_T2H_NUM_MSGS
|
||||
};
|
||||
|
@ -444,8 +451,8 @@ enum htt_t2h_msg_type {
|
|||
HTT_T2H_MSG_TYPE_TEST,
|
||||
HTT_T2H_MSG_TYPE_EN_STATS,
|
||||
HTT_T2H_MSG_TYPE_TX_FETCH_IND,
|
||||
HTT_T2H_MSG_TYPE_TX_FETCH_CONF,
|
||||
HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND,
|
||||
HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM,
|
||||
HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND,
|
||||
/* keep this last */
|
||||
HTT_T2H_NUM_MSGS
|
||||
};
|
||||
|
@ -478,10 +485,10 @@ struct htt_mgmt_tx_completion {
|
|||
__le32 status;
|
||||
} __packed;
|
||||
|
||||
#define HTT_RX_INDICATION_INFO0_EXT_TID_MASK (0x3F)
|
||||
#define HTT_RX_INDICATION_INFO0_EXT_TID_MASK (0x1F)
|
||||
#define HTT_RX_INDICATION_INFO0_EXT_TID_LSB (0)
|
||||
#define HTT_RX_INDICATION_INFO0_FLUSH_VALID (1 << 6)
|
||||
#define HTT_RX_INDICATION_INFO0_RELEASE_VALID (1 << 7)
|
||||
#define HTT_RX_INDICATION_INFO0_FLUSH_VALID (1 << 5)
|
||||
#define HTT_RX_INDICATION_INFO0_RELEASE_VALID (1 << 6)
|
||||
|
||||
#define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_MASK 0x0000003F
|
||||
#define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_LSB 0
|
||||
|
@ -588,7 +595,7 @@ enum htt_rx_mpdu_status {
|
|||
/* only accept EAPOL frames */
|
||||
HTT_RX_IND_MPDU_STATUS_UNAUTH_PEER,
|
||||
HTT_RX_IND_MPDU_STATUS_OUT_OF_SYNC,
|
||||
/* Non-data in promiscous mode */
|
||||
/* Non-data in promiscuous mode */
|
||||
HTT_RX_IND_MPDU_STATUS_MGMT_CTRL,
|
||||
HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR,
|
||||
HTT_RX_IND_MPDU_STATUS_DECRYPT_ERR,
|
||||
|
@ -893,7 +900,7 @@ struct htt_rx_in_ord_ind {
|
|||
* Purpose: indicate how many 32-bit integers follow the message header
|
||||
* - NUM_CHARS
|
||||
* Bits 31:16
|
||||
* Purpose: indicate how many 8-bit charaters follow the series of integers
|
||||
* Purpose: indicate how many 8-bit characters follow the series of integers
|
||||
*/
|
||||
struct htt_rx_test {
|
||||
u8 num_ints;
|
||||
|
@ -1035,10 +1042,10 @@ struct htt_dbg_stats_wal_tx_stats {
|
|||
/* illegal rate phy errors */
|
||||
__le32 illgl_rate_phy_err;
|
||||
|
||||
/* wal pdev continous xretry */
|
||||
/* wal pdev continuous xretry */
|
||||
__le32 pdev_cont_xretry;
|
||||
|
||||
/* wal pdev continous xretry */
|
||||
/* wal pdev continuous xretry */
|
||||
__le32 pdev_tx_timeout;
|
||||
|
||||
/* wal pdev resets */
|
||||
|
@ -1301,9 +1308,43 @@ struct htt_frag_desc_bank_id {
|
|||
* so we use a conservatively safe value for now */
|
||||
#define HTT_FRAG_DESC_BANK_MAX 4
|
||||
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_MASK 0x03
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_LSB 0
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_SWAP (1 << 2)
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_MASK 0x03
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_LSB 0
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_SWAP BIT(2)
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_VALID BIT(3)
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE_MASK BIT(4)
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE_LSB 4
|
||||
|
||||
enum htt_q_depth_type {
|
||||
HTT_Q_DEPTH_TYPE_BYTES = 0,
|
||||
HTT_Q_DEPTH_TYPE_MSDUS = 1,
|
||||
};
|
||||
|
||||
#define HTT_TX_Q_STATE_NUM_PEERS (TARGET_10_4_NUM_QCACHE_PEERS_MAX + \
|
||||
TARGET_10_4_NUM_VDEVS)
|
||||
#define HTT_TX_Q_STATE_NUM_TIDS 8
|
||||
#define HTT_TX_Q_STATE_ENTRY_SIZE 1
|
||||
#define HTT_TX_Q_STATE_ENTRY_MULTIPLIER 0
|
||||
|
||||
/**
|
||||
* htt_q_state_conf - part of htt_frag_desc_bank_cfg for host q state config
|
||||
*
|
||||
* Defines host q state format and behavior. See htt_q_state.
|
||||
*
|
||||
* @record_size: Defines the size of each host q entry in bytes. In practice
|
||||
* however firmware (at least 10.4.3-00191) ignores this host
|
||||
* configuration value and uses hardcoded value of 1.
|
||||
* @record_multiplier: This is valid only when q depth type is MSDUs. It
|
||||
* defines the exponent for the power of 2 multiplication.
|
||||
*/
|
||||
struct htt_q_state_conf {
|
||||
__le32 paddr;
|
||||
__le16 num_peers;
|
||||
__le16 num_tids;
|
||||
u8 record_size;
|
||||
u8 record_multiplier;
|
||||
u8 pad[2];
|
||||
} __packed;
|
||||
|
||||
struct htt_frag_desc_bank_cfg {
|
||||
u8 info; /* HTT_FRAG_DESC_BANK_CFG_INFO_ */
|
||||
|
@ -1311,6 +1352,122 @@ struct htt_frag_desc_bank_cfg {
|
|||
u8 desc_size;
|
||||
__le32 bank_base_addrs[HTT_FRAG_DESC_BANK_MAX];
|
||||
struct htt_frag_desc_bank_id bank_id[HTT_FRAG_DESC_BANK_MAX];
|
||||
struct htt_q_state_conf q_state;
|
||||
} __packed;
|
||||
|
||||
#define HTT_TX_Q_STATE_ENTRY_COEFFICIENT 128
|
||||
#define HTT_TX_Q_STATE_ENTRY_FACTOR_MASK 0x3f
|
||||
#define HTT_TX_Q_STATE_ENTRY_FACTOR_LSB 0
|
||||
#define HTT_TX_Q_STATE_ENTRY_EXP_MASK 0xc0
|
||||
#define HTT_TX_Q_STATE_ENTRY_EXP_LSB 6
|
||||
|
||||
/**
|
||||
* htt_q_state - shared between host and firmware via DMA
|
||||
*
|
||||
* This structure is used for the host to expose it's software queue state to
|
||||
* firmware so that its rate control can schedule fetch requests for optimized
|
||||
* performance. This is most notably used for MU-MIMO aggregation when multiple
|
||||
* MU clients are connected.
|
||||
*
|
||||
* @count: Each element defines the host queue depth. When q depth type was
|
||||
* configured as HTT_Q_DEPTH_TYPE_BYTES then each entry is defined as:
|
||||
* FACTOR * 128 * 8^EXP (see HTT_TX_Q_STATE_ENTRY_FACTOR_MASK and
|
||||
* HTT_TX_Q_STATE_ENTRY_EXP_MASK). When q depth type was configured as
|
||||
* HTT_Q_DEPTH_TYPE_MSDUS the number of packets is scaled by 2 **
|
||||
* record_multiplier (see htt_q_state_conf).
|
||||
* @map: Used by firmware to quickly check which host queues are not empty. It
|
||||
* is a bitmap simply saying.
|
||||
* @seq: Used by firmware to quickly check if the host queues were updated
|
||||
* since it last checked.
|
||||
*
|
||||
* FIXME: Is the q_state map[] size calculation really correct?
|
||||
*/
|
||||
struct htt_q_state {
|
||||
u8 count[HTT_TX_Q_STATE_NUM_TIDS][HTT_TX_Q_STATE_NUM_PEERS];
|
||||
u32 map[HTT_TX_Q_STATE_NUM_TIDS][(HTT_TX_Q_STATE_NUM_PEERS + 31) / 32];
|
||||
__le32 seq;
|
||||
} __packed;
|
||||
|
||||
#define HTT_TX_FETCH_RECORD_INFO_PEER_ID_MASK 0x0fff
|
||||
#define HTT_TX_FETCH_RECORD_INFO_PEER_ID_LSB 0
|
||||
#define HTT_TX_FETCH_RECORD_INFO_TID_MASK 0xf000
|
||||
#define HTT_TX_FETCH_RECORD_INFO_TID_LSB 12
|
||||
|
||||
struct htt_tx_fetch_record {
|
||||
__le16 info; /* HTT_TX_FETCH_IND_RECORD_INFO_ */
|
||||
__le16 num_msdus;
|
||||
__le32 num_bytes;
|
||||
} __packed;
|
||||
|
||||
struct htt_tx_fetch_ind {
|
||||
u8 pad0;
|
||||
__le16 fetch_seq_num;
|
||||
__le32 token;
|
||||
__le16 num_resp_ids;
|
||||
__le16 num_records;
|
||||
struct htt_tx_fetch_record records[0];
|
||||
__le32 resp_ids[0]; /* ath10k_htt_get_tx_fetch_ind_resp_ids() */
|
||||
} __packed;
|
||||
|
||||
static inline void *
|
||||
ath10k_htt_get_tx_fetch_ind_resp_ids(struct htt_tx_fetch_ind *ind)
|
||||
{
|
||||
return (void *)&ind->records[le16_to_cpu(ind->num_records)];
|
||||
}
|
||||
|
||||
struct htt_tx_fetch_resp {
|
||||
u8 pad0;
|
||||
__le16 resp_id;
|
||||
__le16 fetch_seq_num;
|
||||
__le16 num_records;
|
||||
__le32 token;
|
||||
struct htt_tx_fetch_record records[0];
|
||||
} __packed;
|
||||
|
||||
struct htt_tx_fetch_confirm {
|
||||
u8 pad0;
|
||||
__le16 num_resp_ids;
|
||||
__le32 resp_ids[0];
|
||||
} __packed;
|
||||
|
||||
enum htt_tx_mode_switch_mode {
|
||||
HTT_TX_MODE_SWITCH_PUSH = 0,
|
||||
HTT_TX_MODE_SWITCH_PUSH_PULL = 1,
|
||||
};
|
||||
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO0_ENABLE BIT(0)
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO0_NUM_RECORDS_MASK 0xfffe
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO0_NUM_RECORDS_LSB 1
|
||||
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO1_MODE_MASK 0x0003
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO1_MODE_LSB 0
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD_MASK 0xfffc
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD_LSB 2
|
||||
|
||||
#define HTT_TX_MODE_SWITCH_RECORD_INFO0_PEER_ID_MASK 0x0fff
|
||||
#define HTT_TX_MODE_SWITCH_RECORD_INFO0_PEER_ID_LSB 0
|
||||
#define HTT_TX_MODE_SWITCH_RECORD_INFO0_TID_MASK 0xf000
|
||||
#define HTT_TX_MODE_SWITCH_RECORD_INFO0_TID_LSB 12
|
||||
|
||||
struct htt_tx_mode_switch_record {
|
||||
__le16 info0; /* HTT_TX_MODE_SWITCH_RECORD_INFO0_ */
|
||||
__le16 num_max_msdus;
|
||||
} __packed;
|
||||
|
||||
struct htt_tx_mode_switch_ind {
|
||||
u8 pad0;
|
||||
__le16 info0; /* HTT_TX_MODE_SWITCH_IND_INFO0_ */
|
||||
__le16 info1; /* HTT_TX_MODE_SWITCH_IND_INFO1_ */
|
||||
u8 pad1[2];
|
||||
struct htt_tx_mode_switch_record records[0];
|
||||
} __packed;
|
||||
|
||||
struct htt_channel_change {
|
||||
u8 pad[3];
|
||||
__le32 freq;
|
||||
__le32 center_freq1;
|
||||
__le32 center_freq2;
|
||||
__le32 phymode;
|
||||
} __packed;
|
||||
|
||||
union htt_rx_pn_t {
|
||||
|
@ -1318,10 +1475,10 @@ union htt_rx_pn_t {
|
|||
u32 pn24;
|
||||
|
||||
/* TKIP or CCMP: 48-bit PN */
|
||||
u_int64_t pn48;
|
||||
u64 pn48;
|
||||
|
||||
/* WAPI: 128-bit PN */
|
||||
u_int64_t pn128[2];
|
||||
u64 pn128[2];
|
||||
};
|
||||
|
||||
struct htt_cmd {
|
||||
|
@ -1335,6 +1492,7 @@ struct htt_cmd {
|
|||
struct htt_oob_sync_req oob_sync_req;
|
||||
struct htt_aggr_conf aggr_conf;
|
||||
struct htt_frag_desc_bank_cfg frag_desc_bank_cfg;
|
||||
struct htt_tx_fetch_resp tx_fetch_resp;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
|
@ -1359,16 +1517,25 @@ struct htt_resp {
|
|||
struct htt_rx_pn_ind rx_pn_ind;
|
||||
struct htt_rx_offload_ind rx_offload_ind;
|
||||
struct htt_rx_in_ord_ind rx_in_ord_ind;
|
||||
struct htt_tx_fetch_ind tx_fetch_ind;
|
||||
struct htt_tx_fetch_confirm tx_fetch_confirm;
|
||||
struct htt_tx_mode_switch_ind tx_mode_switch_ind;
|
||||
struct htt_channel_change chan_change;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
/*** host side structures follow ***/
|
||||
|
||||
struct htt_tx_done {
|
||||
u32 msdu_id;
|
||||
bool discard;
|
||||
bool no_ack;
|
||||
bool success;
|
||||
u16 msdu_id;
|
||||
u16 status;
|
||||
};
|
||||
|
||||
enum htt_tx_compl_state {
|
||||
HTT_TX_COMPL_STATE_NONE,
|
||||
HTT_TX_COMPL_STATE_ACK,
|
||||
HTT_TX_COMPL_STATE_NOACK,
|
||||
HTT_TX_COMPL_STATE_DISCARD,
|
||||
};
|
||||
|
||||
struct htt_peer_map_event {
|
||||
|
@ -1395,7 +1562,6 @@ struct ath10k_htt {
|
|||
u8 target_version_major;
|
||||
u8 target_version_minor;
|
||||
struct completion target_version_received;
|
||||
enum ath10k_fw_htt_op_version op_version;
|
||||
u8 max_num_amsdu;
|
||||
u8 max_num_ampdu;
|
||||
|
||||
|
@ -1489,17 +1655,19 @@ struct ath10k_htt {
|
|||
struct idr pending_tx;
|
||||
wait_queue_head_t empty_tx_wq;
|
||||
|
||||
/* FIFO for storing tx done status {ack, no-ack, discard} and msdu id */
|
||||
DECLARE_KFIFO_PTR(txdone_fifo, struct htt_tx_done);
|
||||
|
||||
/* set if host-fw communication goes haywire
|
||||
* used to avoid further failures */
|
||||
bool rx_confused;
|
||||
struct tasklet_struct rx_replenish_task;
|
||||
atomic_t num_mpdus_ready;
|
||||
|
||||
/* This is used to group tx/rx completions separately and process them
|
||||
* in batches to reduce cache stalls */
|
||||
struct tasklet_struct txrx_compl_task;
|
||||
struct sk_buff_head tx_compl_q;
|
||||
struct sk_buff_head rx_compl_q;
|
||||
struct sk_buff_head rx_in_ord_compl_q;
|
||||
struct sk_buff_head tx_fetch_ind_q;
|
||||
|
||||
/* rx_status template */
|
||||
struct ieee80211_rx_status rx_status;
|
||||
|
@ -1513,6 +1681,17 @@ struct ath10k_htt {
|
|||
dma_addr_t paddr;
|
||||
struct ath10k_htt_txbuf *vaddr;
|
||||
} txbuf;
|
||||
|
||||
struct {
|
||||
bool enabled;
|
||||
struct htt_q_state *vaddr;
|
||||
dma_addr_t paddr;
|
||||
u16 num_push_allowed;
|
||||
u16 num_peers;
|
||||
u16 num_tids;
|
||||
enum htt_tx_mode_switch_mode mode;
|
||||
enum htt_q_depth_type type;
|
||||
} tx_q_state;
|
||||
};
|
||||
|
||||
#define RX_HTT_HDR_STATUS_LEN 64
|
||||
|
@ -1555,7 +1734,7 @@ struct htt_rx_desc {
|
|||
|
||||
/* Refill a bunch of RX buffers for each refill round so that FW/HW can handle
|
||||
* aggregated traffic more nicely. */
|
||||
#define ATH10K_HTT_MAX_NUM_REFILL 16
|
||||
#define ATH10K_HTT_MAX_NUM_REFILL 100
|
||||
|
||||
/*
|
||||
* DMA_MAP expects the buffer to be an integral number of cache lines.
|
||||
|
@ -1583,7 +1762,8 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar);
|
|||
void ath10k_htt_rx_free(struct ath10k_htt *htt);
|
||||
|
||||
void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb);
|
||||
void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
|
||||
void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
|
||||
bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
|
||||
int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt);
|
||||
int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie);
|
||||
int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt);
|
||||
|
@ -1592,11 +1772,31 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
|
|||
u8 max_subfrms_ampdu,
|
||||
u8 max_subfrms_amsdu);
|
||||
void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb);
|
||||
int ath10k_htt_tx_fetch_resp(struct ath10k *ar,
|
||||
__le32 token,
|
||||
__le16 fetch_seq_num,
|
||||
struct htt_tx_fetch_record *records,
|
||||
size_t num_records);
|
||||
|
||||
void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw,
|
||||
struct ieee80211_txq *txq);
|
||||
void ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw,
|
||||
struct ieee80211_txq *txq);
|
||||
void ath10k_htt_tx_txq_sync(struct ath10k *ar);
|
||||
void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt);
|
||||
int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt);
|
||||
void ath10k_htt_tx_mgmt_dec_pending(struct ath10k_htt *htt);
|
||||
int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt,
|
||||
bool is_presp);
|
||||
|
||||
void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc);
|
||||
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb);
|
||||
void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id);
|
||||
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *);
|
||||
int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *);
|
||||
int ath10k_htt_tx(struct ath10k_htt *htt,
|
||||
enum ath10k_hw_txrx_mode txmode,
|
||||
struct sk_buff *msdu);
|
||||
void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
|
||||
struct sk_buff *skb);
|
||||
int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget);
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -22,53 +22,185 @@
|
|||
#include "txrx.h"
|
||||
#include "debug.h"
|
||||
|
||||
void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc)
|
||||
static u8 ath10k_htt_tx_txq_calc_size(size_t count)
|
||||
{
|
||||
if (limit_mgmt_desc)
|
||||
htt->num_pending_mgmt_tx--;
|
||||
int exp;
|
||||
int factor;
|
||||
|
||||
exp = 0;
|
||||
factor = count >> 7;
|
||||
|
||||
while (factor >= 64 && exp < 4) {
|
||||
factor >>= 3;
|
||||
exp++;
|
||||
}
|
||||
|
||||
if (exp == 4)
|
||||
return 0xff;
|
||||
|
||||
if (count > 0)
|
||||
factor = max(1, factor);
|
||||
|
||||
return SM(exp, HTT_TX_Q_STATE_ENTRY_EXP) |
|
||||
SM(factor, HTT_TX_Q_STATE_ENTRY_FACTOR);
|
||||
}
|
||||
|
||||
static void __ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw,
|
||||
struct ieee80211_txq *txq)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
struct ath10k_sta *arsta;
|
||||
struct ath10k_vif *arvif = (void *)txq->vif->drv_priv;
|
||||
unsigned long frame_cnt;
|
||||
unsigned long byte_cnt;
|
||||
int idx;
|
||||
u32 bit;
|
||||
u16 peer_id;
|
||||
u8 tid;
|
||||
u8 count;
|
||||
|
||||
lockdep_assert_held(&ar->htt.tx_lock);
|
||||
|
||||
if (!ar->htt.tx_q_state.enabled)
|
||||
return;
|
||||
|
||||
if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH_PULL)
|
||||
return;
|
||||
|
||||
if (txq->sta) {
|
||||
arsta = (void *)txq->sta->drv_priv;
|
||||
peer_id = arsta->peer_id;
|
||||
} else {
|
||||
peer_id = arvif->peer_id;
|
||||
}
|
||||
|
||||
tid = txq->tid;
|
||||
bit = BIT(peer_id % 32);
|
||||
idx = peer_id / 32;
|
||||
|
||||
ieee80211_txq_get_depth(txq, &frame_cnt, &byte_cnt);
|
||||
count = ath10k_htt_tx_txq_calc_size(byte_cnt);
|
||||
|
||||
if (unlikely(peer_id >= ar->htt.tx_q_state.num_peers) ||
|
||||
unlikely(tid >= ar->htt.tx_q_state.num_tids)) {
|
||||
ath10k_warn(ar, "refusing to update txq for peer_id %hu tid %hhu due to out of bounds\n",
|
||||
peer_id, tid);
|
||||
return;
|
||||
}
|
||||
|
||||
ar->htt.tx_q_state.vaddr->count[tid][peer_id] = count;
|
||||
ar->htt.tx_q_state.vaddr->map[tid][idx] &= ~bit;
|
||||
ar->htt.tx_q_state.vaddr->map[tid][idx] |= count ? bit : 0;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx txq state update peer_id %hu tid %hhu count %hhu\n",
|
||||
peer_id, tid, count);
|
||||
}
|
||||
|
||||
static void __ath10k_htt_tx_txq_sync(struct ath10k *ar)
|
||||
{
|
||||
u32 seq;
|
||||
size_t size;
|
||||
|
||||
lockdep_assert_held(&ar->htt.tx_lock);
|
||||
|
||||
if (!ar->htt.tx_q_state.enabled)
|
||||
return;
|
||||
|
||||
if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH_PULL)
|
||||
return;
|
||||
|
||||
seq = le32_to_cpu(ar->htt.tx_q_state.vaddr->seq);
|
||||
seq++;
|
||||
ar->htt.tx_q_state.vaddr->seq = cpu_to_le32(seq);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx txq state update commit seq %u\n",
|
||||
seq);
|
||||
|
||||
size = sizeof(*ar->htt.tx_q_state.vaddr);
|
||||
dma_sync_single_for_device(ar->dev,
|
||||
ar->htt.tx_q_state.paddr,
|
||||
size,
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
void ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw,
|
||||
struct ieee80211_txq *txq)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
|
||||
spin_lock_bh(&ar->htt.tx_lock);
|
||||
__ath10k_htt_tx_txq_recalc(hw, txq);
|
||||
spin_unlock_bh(&ar->htt.tx_lock);
|
||||
}
|
||||
|
||||
void ath10k_htt_tx_txq_sync(struct ath10k *ar)
|
||||
{
|
||||
spin_lock_bh(&ar->htt.tx_lock);
|
||||
__ath10k_htt_tx_txq_sync(ar);
|
||||
spin_unlock_bh(&ar->htt.tx_lock);
|
||||
}
|
||||
|
||||
void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw,
|
||||
struct ieee80211_txq *txq)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
|
||||
spin_lock_bh(&ar->htt.tx_lock);
|
||||
__ath10k_htt_tx_txq_recalc(hw, txq);
|
||||
__ath10k_htt_tx_txq_sync(ar);
|
||||
spin_unlock_bh(&ar->htt.tx_lock);
|
||||
}
|
||||
|
||||
void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt)
|
||||
{
|
||||
lockdep_assert_held(&htt->tx_lock);
|
||||
|
||||
htt->num_pending_tx--;
|
||||
if (htt->num_pending_tx == htt->max_num_pending_tx - 1)
|
||||
ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
|
||||
}
|
||||
|
||||
static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt,
|
||||
bool limit_mgmt_desc)
|
||||
int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt)
|
||||
{
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
__ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
}
|
||||
lockdep_assert_held(&htt->tx_lock);
|
||||
|
||||
static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt,
|
||||
bool limit_mgmt_desc, bool is_probe_resp)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
|
||||
if (htt->num_pending_tx >= htt->max_num_pending_tx) {
|
||||
ret = -EBUSY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (limit_mgmt_desc) {
|
||||
if (is_probe_resp && (htt->num_pending_mgmt_tx >
|
||||
ar->hw_params.max_probe_resp_desc_thres)) {
|
||||
ret = -EBUSY;
|
||||
goto exit;
|
||||
}
|
||||
htt->num_pending_mgmt_tx++;
|
||||
}
|
||||
if (htt->num_pending_tx >= htt->max_num_pending_tx)
|
||||
return -EBUSY;
|
||||
|
||||
htt->num_pending_tx++;
|
||||
if (htt->num_pending_tx == htt->max_num_pending_tx)
|
||||
ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
|
||||
|
||||
exit:
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt,
|
||||
bool is_presp)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
|
||||
lockdep_assert_held(&htt->tx_lock);
|
||||
|
||||
if (!is_mgmt || !ar->hw_params.max_probe_resp_desc_thres)
|
||||
return 0;
|
||||
|
||||
if (is_presp &&
|
||||
ar->hw_params.max_probe_resp_desc_thres < htt->num_pending_mgmt_tx)
|
||||
return -EBUSY;
|
||||
|
||||
htt->num_pending_mgmt_tx++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath10k_htt_tx_mgmt_dec_pending(struct ath10k_htt *htt)
|
||||
{
|
||||
lockdep_assert_held(&htt->tx_lock);
|
||||
|
||||
if (!htt->ar->hw_params.max_probe_resp_desc_thres)
|
||||
return;
|
||||
|
||||
htt->num_pending_mgmt_tx--;
|
||||
}
|
||||
|
||||
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb)
|
||||
|
@ -97,6 +229,87 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id)
|
|||
idr_remove(&htt->pending_tx, msdu_id);
|
||||
}
|
||||
|
||||
static void ath10k_htt_tx_free_cont_frag_desc(struct ath10k_htt *htt)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
if (!htt->frag_desc.vaddr)
|
||||
return;
|
||||
|
||||
size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc);
|
||||
|
||||
dma_free_coherent(htt->ar->dev,
|
||||
size,
|
||||
htt->frag_desc.vaddr,
|
||||
htt->frag_desc.paddr);
|
||||
}
|
||||
|
||||
static int ath10k_htt_tx_alloc_cont_frag_desc(struct ath10k_htt *htt)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
size_t size;
|
||||
|
||||
if (!ar->hw_params.continuous_frag_desc)
|
||||
return 0;
|
||||
|
||||
size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc);
|
||||
htt->frag_desc.vaddr = dma_alloc_coherent(ar->dev, size,
|
||||
&htt->frag_desc.paddr,
|
||||
GFP_KERNEL);
|
||||
if (!htt->frag_desc.vaddr) {
|
||||
ath10k_err(ar, "failed to alloc fragment desc memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_htt_tx_free_txq(struct ath10k_htt *htt)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
size_t size;
|
||||
|
||||
if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
return;
|
||||
|
||||
size = sizeof(*htt->tx_q_state.vaddr);
|
||||
|
||||
dma_unmap_single(ar->dev, htt->tx_q_state.paddr, size, DMA_TO_DEVICE);
|
||||
kfree(htt->tx_q_state.vaddr);
|
||||
}
|
||||
|
||||
static int ath10k_htt_tx_alloc_txq(struct ath10k_htt *htt)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
return 0;
|
||||
|
||||
htt->tx_q_state.num_peers = HTT_TX_Q_STATE_NUM_PEERS;
|
||||
htt->tx_q_state.num_tids = HTT_TX_Q_STATE_NUM_TIDS;
|
||||
htt->tx_q_state.type = HTT_Q_DEPTH_TYPE_BYTES;
|
||||
|
||||
size = sizeof(*htt->tx_q_state.vaddr);
|
||||
htt->tx_q_state.vaddr = kzalloc(size, GFP_KERNEL);
|
||||
if (!htt->tx_q_state.vaddr)
|
||||
return -ENOMEM;
|
||||
|
||||
htt->tx_q_state.paddr = dma_map_single(ar->dev, htt->tx_q_state.vaddr,
|
||||
size, DMA_TO_DEVICE);
|
||||
ret = dma_mapping_error(ar->dev, htt->tx_q_state.paddr);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to dma map tx_q_state: %d\n", ret);
|
||||
kfree(htt->tx_q_state.vaddr);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
|
@ -111,36 +324,49 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
|
|||
size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf);
|
||||
htt->txbuf.vaddr = dma_alloc_coherent(ar->dev, size,
|
||||
&htt->txbuf.paddr,
|
||||
GFP_DMA);
|
||||
GFP_KERNEL);
|
||||
if (!htt->txbuf.vaddr) {
|
||||
ath10k_err(ar, "failed to alloc tx buffer\n");
|
||||
ret = -ENOMEM;
|
||||
goto free_idr_pending_tx;
|
||||
}
|
||||
|
||||
if (!ar->hw_params.continuous_frag_desc)
|
||||
goto skip_frag_desc_alloc;
|
||||
|
||||
size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc);
|
||||
htt->frag_desc.vaddr = dma_alloc_coherent(ar->dev, size,
|
||||
&htt->frag_desc.paddr,
|
||||
GFP_DMA);
|
||||
if (!htt->frag_desc.vaddr) {
|
||||
ath10k_warn(ar, "failed to alloc fragment desc memory\n");
|
||||
ret = -ENOMEM;
|
||||
ret = ath10k_htt_tx_alloc_cont_frag_desc(htt);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to alloc cont frag desc: %d\n", ret);
|
||||
goto free_txbuf;
|
||||
}
|
||||
|
||||
skip_frag_desc_alloc:
|
||||
ret = ath10k_htt_tx_alloc_txq(htt);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to alloc txq: %d\n", ret);
|
||||
goto free_frag_desc;
|
||||
}
|
||||
|
||||
size = roundup_pow_of_two(htt->max_num_pending_tx);
|
||||
ret = kfifo_alloc(&htt->txdone_fifo, size, GFP_KERNEL);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to alloc txdone fifo: %d\n", ret);
|
||||
goto free_txq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_txq:
|
||||
ath10k_htt_tx_free_txq(htt);
|
||||
|
||||
free_frag_desc:
|
||||
ath10k_htt_tx_free_cont_frag_desc(htt);
|
||||
|
||||
free_txbuf:
|
||||
size = htt->max_num_pending_tx *
|
||||
sizeof(struct ath10k_htt_txbuf);
|
||||
dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr,
|
||||
htt->txbuf.paddr);
|
||||
|
||||
free_idr_pending_tx:
|
||||
idr_destroy(&htt->pending_tx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -152,8 +378,8 @@ static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx)
|
|||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n", msdu_id);
|
||||
|
||||
tx_done.discard = 1;
|
||||
tx_done.msdu_id = msdu_id;
|
||||
tx_done.status = HTT_TX_COMPL_STATE_DISCARD;
|
||||
|
||||
ath10k_txrx_tx_unref(htt, &tx_done);
|
||||
|
||||
|
@ -174,12 +400,10 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
|
|||
htt->txbuf.paddr);
|
||||
}
|
||||
|
||||
if (htt->frag_desc.vaddr) {
|
||||
size = htt->max_num_pending_tx *
|
||||
sizeof(struct htt_msdu_ext_desc);
|
||||
dma_free_coherent(htt->ar->dev, size, htt->frag_desc.vaddr,
|
||||
htt->frag_desc.paddr);
|
||||
}
|
||||
ath10k_htt_tx_free_txq(htt);
|
||||
ath10k_htt_tx_free_cont_frag_desc(htt);
|
||||
WARN_ON(!kfifo_is_empty(&htt->txdone_fifo));
|
||||
kfifo_free(&htt->txdone_fifo);
|
||||
}
|
||||
|
||||
void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
|
||||
|
@ -268,7 +492,9 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt)
|
|||
struct ath10k *ar = htt->ar;
|
||||
struct sk_buff *skb;
|
||||
struct htt_cmd *cmd;
|
||||
struct htt_frag_desc_bank_cfg *cfg;
|
||||
int ret, size;
|
||||
u8 info;
|
||||
|
||||
if (!ar->hw_params.continuous_frag_desc)
|
||||
return 0;
|
||||
|
@ -286,14 +512,31 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt)
|
|||
skb_put(skb, size);
|
||||
cmd = (struct htt_cmd *)skb->data;
|
||||
cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG;
|
||||
cmd->frag_desc_bank_cfg.info = 0;
|
||||
cmd->frag_desc_bank_cfg.num_banks = 1;
|
||||
cmd->frag_desc_bank_cfg.desc_size = sizeof(struct htt_msdu_ext_desc);
|
||||
cmd->frag_desc_bank_cfg.bank_base_addrs[0] =
|
||||
__cpu_to_le32(htt->frag_desc.paddr);
|
||||
cmd->frag_desc_bank_cfg.bank_id[0].bank_min_id = 0;
|
||||
cmd->frag_desc_bank_cfg.bank_id[0].bank_max_id =
|
||||
__cpu_to_le16(htt->max_num_pending_tx - 1);
|
||||
|
||||
info = 0;
|
||||
info |= SM(htt->tx_q_state.type,
|
||||
HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE);
|
||||
|
||||
if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
info |= HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_VALID;
|
||||
|
||||
cfg = &cmd->frag_desc_bank_cfg;
|
||||
cfg->info = info;
|
||||
cfg->num_banks = 1;
|
||||
cfg->desc_size = sizeof(struct htt_msdu_ext_desc);
|
||||
cfg->bank_base_addrs[0] = __cpu_to_le32(htt->frag_desc.paddr);
|
||||
cfg->bank_id[0].bank_min_id = 0;
|
||||
cfg->bank_id[0].bank_max_id = __cpu_to_le16(htt->max_num_pending_tx -
|
||||
1);
|
||||
|
||||
cfg->q_state.paddr = cpu_to_le32(htt->tx_q_state.paddr);
|
||||
cfg->q_state.num_peers = cpu_to_le16(htt->tx_q_state.num_peers);
|
||||
cfg->q_state.num_tids = cpu_to_le16(htt->tx_q_state.num_tids);
|
||||
cfg->q_state.record_size = HTT_TX_Q_STATE_ENTRY_SIZE;
|
||||
cfg->q_state.record_multiplier = HTT_TX_Q_STATE_ENTRY_MULTIPLIER;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt frag desc bank cmd\n");
|
||||
|
||||
ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
|
||||
if (ret) {
|
||||
|
@ -439,6 +682,86 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_htt_tx_fetch_resp(struct ath10k *ar,
|
||||
__le32 token,
|
||||
__le16 fetch_seq_num,
|
||||
struct htt_tx_fetch_record *records,
|
||||
size_t num_records)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct htt_cmd *cmd;
|
||||
const u16 resp_id = 0;
|
||||
int len = 0;
|
||||
int ret;
|
||||
|
||||
/* Response IDs are echo-ed back only for host driver convienence
|
||||
* purposes. They aren't used for anything in the driver yet so use 0.
|
||||
*/
|
||||
|
||||
len += sizeof(cmd->hdr);
|
||||
len += sizeof(cmd->tx_fetch_resp);
|
||||
len += sizeof(cmd->tx_fetch_resp.records[0]) * num_records;
|
||||
|
||||
skb = ath10k_htc_alloc_skb(ar, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
skb_put(skb, len);
|
||||
cmd = (struct htt_cmd *)skb->data;
|
||||
cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FETCH_RESP;
|
||||
cmd->tx_fetch_resp.resp_id = cpu_to_le16(resp_id);
|
||||
cmd->tx_fetch_resp.fetch_seq_num = fetch_seq_num;
|
||||
cmd->tx_fetch_resp.num_records = cpu_to_le16(num_records);
|
||||
cmd->tx_fetch_resp.token = token;
|
||||
|
||||
memcpy(cmd->tx_fetch_resp.records, records,
|
||||
sizeof(records[0]) * num_records);
|
||||
|
||||
ret = ath10k_htc_send(&ar->htc, ar->htt.eid, skb);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to submit htc command: %d\n", ret);
|
||||
goto err_free_skb;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_skb:
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8 ath10k_htt_tx_get_vdev_id(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
|
||||
struct ath10k_vif *arvif;
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
||||
return ar->scan.vdev_id;
|
||||
} else if (cb->vif) {
|
||||
arvif = (void *)cb->vif->drv_priv;
|
||||
return arvif->vdev_id;
|
||||
} else if (ar->monitor_started) {
|
||||
return ar->monitor_vdev_id;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
|
||||
|
||||
if (!is_eth && ieee80211_is_mgmt(hdr->frame_control))
|
||||
return HTT_DATA_TX_EXT_TID_MGMT;
|
||||
else if (cb->flags & ATH10K_SKB_F_QOS)
|
||||
return skb->priority % IEEE80211_QOS_CTL_TID_MASK;
|
||||
else
|
||||
return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
|
||||
}
|
||||
|
||||
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
|
@ -446,25 +769,11 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
struct sk_buff *txdesc = NULL;
|
||||
struct htt_cmd *cmd;
|
||||
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
|
||||
u8 vdev_id = skb_cb->vdev_id;
|
||||
u8 vdev_id = ath10k_htt_tx_get_vdev_id(ar, msdu);
|
||||
int len = 0;
|
||||
int msdu_id = -1;
|
||||
int res;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
bool limit_mgmt_desc = false;
|
||||
bool is_probe_resp = false;
|
||||
|
||||
if (ar->hw_params.max_probe_resp_desc_thres) {
|
||||
limit_mgmt_desc = true;
|
||||
|
||||
if (ieee80211_is_probe_resp(hdr->frame_control))
|
||||
is_probe_resp = true;
|
||||
}
|
||||
|
||||
res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp);
|
||||
|
||||
if (res)
|
||||
goto err;
|
||||
|
||||
len += sizeof(cmd->hdr);
|
||||
len += sizeof(cmd->mgmt_tx);
|
||||
|
@ -473,10 +782,17 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
if (res < 0)
|
||||
goto err_tx_dec;
|
||||
goto err;
|
||||
|
||||
msdu_id = res;
|
||||
|
||||
if ((ieee80211_is_action(hdr->frame_control) ||
|
||||
ieee80211_is_deauth(hdr->frame_control) ||
|
||||
ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
ieee80211_has_protected(hdr->frame_control)) {
|
||||
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
}
|
||||
|
||||
txdesc = ath10k_htc_alloc_skb(ar, len);
|
||||
if (!txdesc) {
|
||||
res = -ENOMEM;
|
||||
|
@ -503,8 +819,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
memcpy(cmd->mgmt_tx.hdr, msdu->data,
|
||||
min_t(int, msdu->len, HTT_MGMT_FRM_HDR_DOWNLOAD_LEN));
|
||||
|
||||
skb_cb->htt.txbuf = NULL;
|
||||
|
||||
res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc);
|
||||
if (res)
|
||||
goto err_unmap_msdu;
|
||||
|
@ -519,65 +833,55 @@ err_free_msdu_id:
|
|||
spin_lock_bh(&htt->tx_lock);
|
||||
ath10k_htt_tx_free_msdu_id(htt, msdu_id);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
err_tx_dec:
|
||||
ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
|
||||
err:
|
||||
return res;
|
||||
}
|
||||
|
||||
int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
||||
int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
|
||||
struct sk_buff *msdu)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct device *dev = ar->dev;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
|
||||
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
|
||||
struct ath10k_hif_sg_item sg_items[2];
|
||||
struct ath10k_htt_txbuf *txbuf;
|
||||
struct htt_data_tx_desc_frag *frags;
|
||||
u8 vdev_id = skb_cb->vdev_id;
|
||||
u8 tid = skb_cb->htt.tid;
|
||||
bool is_eth = (txmode == ATH10K_HW_TXRX_ETHERNET);
|
||||
u8 vdev_id = ath10k_htt_tx_get_vdev_id(ar, msdu);
|
||||
u8 tid = ath10k_htt_tx_get_tid(msdu, is_eth);
|
||||
int prefetch_len;
|
||||
int res;
|
||||
u8 flags0 = 0;
|
||||
u16 msdu_id, flags1 = 0;
|
||||
u16 freq = 0;
|
||||
u32 frags_paddr = 0;
|
||||
u32 txbuf_paddr;
|
||||
struct htt_msdu_ext_desc *ext_desc = NULL;
|
||||
bool limit_mgmt_desc = false;
|
||||
bool is_probe_resp = false;
|
||||
|
||||
if (unlikely(ieee80211_is_mgmt(hdr->frame_control)) &&
|
||||
ar->hw_params.max_probe_resp_desc_thres) {
|
||||
limit_mgmt_desc = true;
|
||||
|
||||
if (ieee80211_is_probe_resp(hdr->frame_control))
|
||||
is_probe_resp = true;
|
||||
}
|
||||
|
||||
res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp);
|
||||
if (res)
|
||||
goto err;
|
||||
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
if (res < 0)
|
||||
goto err_tx_dec;
|
||||
goto err;
|
||||
|
||||
msdu_id = res;
|
||||
|
||||
prefetch_len = min(htt->prefetch_len, msdu->len);
|
||||
prefetch_len = roundup(prefetch_len, 4);
|
||||
|
||||
skb_cb->htt.txbuf = &htt->txbuf.vaddr[msdu_id];
|
||||
skb_cb->htt.txbuf_paddr = htt->txbuf.paddr +
|
||||
(sizeof(struct ath10k_htt_txbuf) * msdu_id);
|
||||
txbuf = &htt->txbuf.vaddr[msdu_id];
|
||||
txbuf_paddr = htt->txbuf.paddr +
|
||||
(sizeof(struct ath10k_htt_txbuf) * msdu_id);
|
||||
|
||||
if ((ieee80211_is_action(hdr->frame_control) ||
|
||||
ieee80211_is_deauth(hdr->frame_control) ||
|
||||
ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
ieee80211_has_protected(hdr->frame_control)) {
|
||||
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
} else if (!skb_cb->htt.nohwcrypt &&
|
||||
skb_cb->txmode == ATH10K_HW_TXRX_RAW &&
|
||||
} else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
|
||||
txmode == ATH10K_HW_TXRX_RAW &&
|
||||
ieee80211_has_protected(hdr->frame_control)) {
|
||||
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
}
|
||||
|
@ -590,7 +894,10 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
goto err_free_msdu_id;
|
||||
}
|
||||
|
||||
switch (skb_cb->txmode) {
|
||||
if (unlikely(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN))
|
||||
freq = ar->scan.roc_freq;
|
||||
|
||||
switch (txmode) {
|
||||
case ATH10K_HW_TXRX_RAW:
|
||||
case ATH10K_HW_TXRX_NATIVE_WIFI:
|
||||
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
|
||||
|
@ -610,16 +917,16 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
frags_paddr = htt->frag_desc.paddr +
|
||||
(sizeof(struct htt_msdu_ext_desc) * msdu_id);
|
||||
} else {
|
||||
frags = skb_cb->htt.txbuf->frags;
|
||||
frags = txbuf->frags;
|
||||
frags[0].dword_addr.paddr =
|
||||
__cpu_to_le32(skb_cb->paddr);
|
||||
frags[0].dword_addr.len = __cpu_to_le32(msdu->len);
|
||||
frags[1].dword_addr.paddr = 0;
|
||||
frags[1].dword_addr.len = 0;
|
||||
|
||||
frags_paddr = skb_cb->htt.txbuf_paddr;
|
||||
frags_paddr = txbuf_paddr;
|
||||
}
|
||||
flags0 |= SM(skb_cb->txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
|
||||
flags0 |= SM(txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
|
||||
break;
|
||||
case ATH10K_HW_TXRX_MGMT:
|
||||
flags0 |= SM(ATH10K_HW_TXRX_MGMT,
|
||||
|
@ -646,17 +953,13 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
* avoid extra memory allocations, compress data structures and thus
|
||||
* improve performance. */
|
||||
|
||||
skb_cb->htt.txbuf->htc_hdr.eid = htt->eid;
|
||||
skb_cb->htt.txbuf->htc_hdr.len = __cpu_to_le16(
|
||||
sizeof(skb_cb->htt.txbuf->cmd_hdr) +
|
||||
sizeof(skb_cb->htt.txbuf->cmd_tx) +
|
||||
prefetch_len);
|
||||
skb_cb->htt.txbuf->htc_hdr.flags = 0;
|
||||
txbuf->htc_hdr.eid = htt->eid;
|
||||
txbuf->htc_hdr.len = __cpu_to_le16(sizeof(txbuf->cmd_hdr) +
|
||||
sizeof(txbuf->cmd_tx) +
|
||||
prefetch_len);
|
||||
txbuf->htc_hdr.flags = 0;
|
||||
|
||||
if (skb_cb->htt.nohwcrypt)
|
||||
flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
|
||||
|
||||
if (!skb_cb->is_protected)
|
||||
if (skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)
|
||||
flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
|
||||
|
||||
flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID);
|
||||
|
@ -675,20 +978,27 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
*/
|
||||
flags1 |= HTT_DATA_TX_DESC_FLAGS1_POSTPONED;
|
||||
|
||||
skb_cb->htt.txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
|
||||
skb_cb->htt.txbuf->cmd_tx.flags0 = flags0;
|
||||
skb_cb->htt.txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1);
|
||||
skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len);
|
||||
skb_cb->htt.txbuf->cmd_tx.id = __cpu_to_le16(msdu_id);
|
||||
skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
|
||||
skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le16(HTT_INVALID_PEERID);
|
||||
skb_cb->htt.txbuf->cmd_tx.freq = __cpu_to_le16(skb_cb->htt.freq);
|
||||
txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
|
||||
txbuf->cmd_tx.flags0 = flags0;
|
||||
txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1);
|
||||
txbuf->cmd_tx.len = __cpu_to_le16(msdu->len);
|
||||
txbuf->cmd_tx.id = __cpu_to_le16(msdu_id);
|
||||
txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
|
||||
if (ath10k_mac_tx_frm_has_freq(ar)) {
|
||||
txbuf->cmd_tx.offchan_tx.peerid =
|
||||
__cpu_to_le16(HTT_INVALID_PEERID);
|
||||
txbuf->cmd_tx.offchan_tx.freq =
|
||||
__cpu_to_le16(freq);
|
||||
} else {
|
||||
txbuf->cmd_tx.peerid =
|
||||
__cpu_to_le32(HTT_INVALID_PEERID);
|
||||
}
|
||||
|
||||
trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid);
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT,
|
||||
"htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu freq %hu\n",
|
||||
flags0, flags1, msdu->len, msdu_id, frags_paddr,
|
||||
(u32)skb_cb->paddr, vdev_id, tid, skb_cb->htt.freq);
|
||||
(u32)skb_cb->paddr, vdev_id, tid, freq);
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ",
|
||||
msdu->data, msdu->len);
|
||||
trace_ath10k_tx_hdr(ar, msdu->data, msdu->len);
|
||||
|
@ -696,12 +1006,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
|
||||
sg_items[0].transfer_id = 0;
|
||||
sg_items[0].transfer_context = NULL;
|
||||
sg_items[0].vaddr = &skb_cb->htt.txbuf->htc_hdr;
|
||||
sg_items[0].paddr = skb_cb->htt.txbuf_paddr +
|
||||
sizeof(skb_cb->htt.txbuf->frags);
|
||||
sg_items[0].len = sizeof(skb_cb->htt.txbuf->htc_hdr) +
|
||||
sizeof(skb_cb->htt.txbuf->cmd_hdr) +
|
||||
sizeof(skb_cb->htt.txbuf->cmd_tx);
|
||||
sg_items[0].vaddr = &txbuf->htc_hdr;
|
||||
sg_items[0].paddr = txbuf_paddr +
|
||||
sizeof(txbuf->frags);
|
||||
sg_items[0].len = sizeof(txbuf->htc_hdr) +
|
||||
sizeof(txbuf->cmd_hdr) +
|
||||
sizeof(txbuf->cmd_tx);
|
||||
|
||||
sg_items[1].transfer_id = 0;
|
||||
sg_items[1].transfer_context = NULL;
|
||||
|
@ -720,11 +1030,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
err_unmap_msdu:
|
||||
dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
err_free_msdu_id:
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
ath10k_htt_tx_free_msdu_id(htt, msdu_id);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
err_tx_dec:
|
||||
ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
|
||||
err:
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "hw.h"
|
||||
|
||||
const struct ath10k_hw_regs qca988x_regs = {
|
||||
.rtc_state_cold_reset_mask = 0x00000400,
|
||||
.rtc_soc_base_address = 0x00004000,
|
||||
.rtc_wmac_base_address = 0x00005000,
|
||||
.soc_core_base_address = 0x00009000,
|
||||
|
@ -46,7 +45,6 @@ const struct ath10k_hw_regs qca988x_regs = {
|
|||
};
|
||||
|
||||
const struct ath10k_hw_regs qca6174_regs = {
|
||||
.rtc_state_cold_reset_mask = 0x00002000,
|
||||
.rtc_soc_base_address = 0x00000800,
|
||||
.rtc_wmac_base_address = 0x00001000,
|
||||
.soc_core_base_address = 0x0003a000,
|
||||
|
@ -73,7 +71,6 @@ const struct ath10k_hw_regs qca6174_regs = {
|
|||
};
|
||||
|
||||
const struct ath10k_hw_regs qca99x0_regs = {
|
||||
.rtc_state_cold_reset_mask = 0x00000400,
|
||||
.rtc_soc_base_address = 0x00080000,
|
||||
.rtc_wmac_base_address = 0x00000000,
|
||||
.soc_core_base_address = 0x00082000,
|
||||
|
@ -88,7 +85,7 @@ const struct ath10k_hw_regs qca99x0_regs = {
|
|||
.ce7_base_address = 0x0004bc00,
|
||||
/* Note: qca99x0 supports upto 12 Copy Engines. Other than address of
|
||||
* CE0 and CE1 no other copy engine is directly referred in the code.
|
||||
* It is not really neccessary to assign address for newly supported
|
||||
* It is not really necessary to assign address for newly supported
|
||||
* CEs in this address table.
|
||||
* Copy Engine Address
|
||||
* CE8 0x0004c000
|
||||
|
@ -109,6 +106,38 @@ const struct ath10k_hw_regs qca99x0_regs = {
|
|||
.pcie_intr_clr_address = 0x00000010,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_regs qca4019_regs = {
|
||||
.rtc_soc_base_address = 0x00080000,
|
||||
.soc_core_base_address = 0x00082000,
|
||||
.ce_wrapper_base_address = 0x0004d000,
|
||||
.ce0_base_address = 0x0004a000,
|
||||
.ce1_base_address = 0x0004a400,
|
||||
.ce2_base_address = 0x0004a800,
|
||||
.ce3_base_address = 0x0004ac00,
|
||||
.ce4_base_address = 0x0004b000,
|
||||
.ce5_base_address = 0x0004b400,
|
||||
.ce6_base_address = 0x0004b800,
|
||||
.ce7_base_address = 0x0004bc00,
|
||||
/* qca4019 supports upto 12 copy engines. Since base address
|
||||
* of ce8 to ce11 are not directly referred in the code,
|
||||
* no need have them in separate members in this table.
|
||||
* Copy Engine Address
|
||||
* CE8 0x0004c000
|
||||
* CE9 0x0004c400
|
||||
* CE10 0x0004c800
|
||||
* CE11 0x0004cc00
|
||||
*/
|
||||
.soc_reset_control_si0_rst_mask = 0x00000001,
|
||||
.soc_reset_control_ce_rst_mask = 0x00000100,
|
||||
.soc_chip_id_address = 0x000000ec,
|
||||
.fw_indicator_address = 0x0004f00c,
|
||||
.ce_wrap_intr_sum_host_msi_lsb = 0x0000000c,
|
||||
.ce_wrap_intr_sum_host_msi_mask = 0x00fff000,
|
||||
.pcie_intr_fw_mask = 0x00100000,
|
||||
.pcie_intr_ce_mask_all = 0x000fff00,
|
||||
.pcie_intr_clr_address = 0x00000010,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_values qca988x_values = {
|
||||
.rtc_state_val_on = 3,
|
||||
.ce_count = 8,
|
||||
|
@ -136,22 +165,70 @@ const struct ath10k_hw_values qca99x0_values = {
|
|||
.ce_desc_meta_data_lsb = 4,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_values qca9888_values = {
|
||||
.rtc_state_val_on = 3,
|
||||
.ce_count = 12,
|
||||
.msi_assign_ce_max = 12,
|
||||
.num_target_ce_config_wlan = 10,
|
||||
.ce_desc_meta_data_mask = 0xFFF0,
|
||||
.ce_desc_meta_data_lsb = 4,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_values qca4019_values = {
|
||||
.ce_count = 12,
|
||||
.num_target_ce_config_wlan = 10,
|
||||
.ce_desc_meta_data_mask = 0xFFF0,
|
||||
.ce_desc_meta_data_lsb = 4,
|
||||
};
|
||||
|
||||
void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev)
|
||||
{
|
||||
u32 cc_fix = 0;
|
||||
u32 rcc_fix = 0;
|
||||
enum ath10k_hw_cc_wraparound_type wraparound_type;
|
||||
|
||||
survey->filled |= SURVEY_INFO_TIME |
|
||||
SURVEY_INFO_TIME_BUSY;
|
||||
|
||||
if (ar->hw_params.has_shifted_cc_wraparound && cc < cc_prev) {
|
||||
cc_fix = 0x7fffffff;
|
||||
survey->filled &= ~SURVEY_INFO_TIME_BUSY;
|
||||
wraparound_type = ar->hw_params.cc_wraparound_type;
|
||||
|
||||
if (cc < cc_prev || rcc < rcc_prev) {
|
||||
switch (wraparound_type) {
|
||||
case ATH10K_HW_CC_WRAP_SHIFTED_ALL:
|
||||
if (cc < cc_prev) {
|
||||
cc_fix = 0x7fffffff;
|
||||
survey->filled &= ~SURVEY_INFO_TIME_BUSY;
|
||||
}
|
||||
break;
|
||||
case ATH10K_HW_CC_WRAP_SHIFTED_EACH:
|
||||
if (cc < cc_prev)
|
||||
cc_fix = 0x7fffffff;
|
||||
|
||||
if (rcc < rcc_prev)
|
||||
rcc_fix = 0x7fffffff;
|
||||
break;
|
||||
case ATH10K_HW_CC_WRAP_DISABLED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cc -= cc_prev - cc_fix;
|
||||
rcc -= rcc_prev;
|
||||
rcc -= rcc_prev - rcc_fix;
|
||||
|
||||
survey->time = CCNT_TO_MSEC(ar, cc);
|
||||
survey->time_busy = CCNT_TO_MSEC(ar, rcc);
|
||||
}
|
||||
|
||||
const struct ath10k_hw_ops qca988x_ops = {
|
||||
};
|
||||
|
||||
static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd)
|
||||
{
|
||||
return MS(__le32_to_cpu(rxd->msdu_end.qca99x0.info1),
|
||||
RX_MSDU_END_INFO1_L3_HDR_PAD);
|
||||
}
|
||||
|
||||
const struct ath10k_hw_ops qca99x0_ops = {
|
||||
.rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes,
|
||||
};
|
||||
|
|
|
@ -26,7 +26,10 @@
|
|||
#define QCA6164_2_1_DEVICE_ID (0x0041)
|
||||
#define QCA6174_2_1_DEVICE_ID (0x003e)
|
||||
#define QCA99X0_2_0_DEVICE_ID (0x0040)
|
||||
#define QCA9888_2_0_DEVICE_ID (0x0056)
|
||||
#define QCA9984_1_0_DEVICE_ID (0x0046)
|
||||
#define QCA9377_1_0_DEVICE_ID (0x0042)
|
||||
#define QCA9887_1_0_DEVICE_ID (0x0050)
|
||||
|
||||
/* QCA988X 1.0 definitions (unsupported) */
|
||||
#define QCA988X_HW_1_0_CHIP_ID_REV 0x0
|
||||
|
@ -35,11 +38,16 @@
|
|||
#define QCA988X_HW_2_0_VERSION 0x4100016c
|
||||
#define QCA988X_HW_2_0_CHIP_ID_REV 0x2
|
||||
#define QCA988X_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA988X/hw2.0"
|
||||
#define QCA988X_HW_2_0_FW_FILE "firmware.bin"
|
||||
#define QCA988X_HW_2_0_OTP_FILE "otp.bin"
|
||||
#define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9887 1.0 definitions */
|
||||
#define QCA9887_HW_1_0_VERSION 0x4100016d
|
||||
#define QCA9887_HW_1_0_CHIP_ID_REV 0
|
||||
#define QCA9887_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9887/hw1.0"
|
||||
#define QCA9887_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9887_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA6174 target BMI version signatures */
|
||||
#define QCA6174_HW_1_0_VERSION 0x05000000
|
||||
#define QCA6174_HW_1_1_VERSION 0x05000001
|
||||
|
@ -76,14 +84,10 @@ enum qca9377_chip_id_rev {
|
|||
};
|
||||
|
||||
#define QCA6174_HW_2_1_FW_DIR "ath10k/QCA6174/hw2.1"
|
||||
#define QCA6174_HW_2_1_FW_FILE "firmware.bin"
|
||||
#define QCA6174_HW_2_1_OTP_FILE "otp.bin"
|
||||
#define QCA6174_HW_2_1_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA6174_HW_2_1_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
#define QCA6174_HW_3_0_FW_DIR "ath10k/QCA6174/hw3.0"
|
||||
#define QCA6174_HW_3_0_FW_FILE "firmware.bin"
|
||||
#define QCA6174_HW_3_0_OTP_FILE "otp.bin"
|
||||
#define QCA6174_HW_3_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA6174_HW_3_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
|
@ -94,18 +98,36 @@ enum qca9377_chip_id_rev {
|
|||
#define QCA99X0_HW_2_0_DEV_VERSION 0x01000000
|
||||
#define QCA99X0_HW_2_0_CHIP_ID_REV 0x1
|
||||
#define QCA99X0_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA99X0/hw2.0"
|
||||
#define QCA99X0_HW_2_0_FW_FILE "firmware.bin"
|
||||
#define QCA99X0_HW_2_0_OTP_FILE "otp.bin"
|
||||
#define QCA99X0_HW_2_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9984 1.0 defines */
|
||||
#define QCA9984_HW_1_0_DEV_VERSION 0x1000000
|
||||
#define QCA9984_HW_DEV_TYPE 0xa
|
||||
#define QCA9984_HW_1_0_CHIP_ID_REV 0x0
|
||||
#define QCA9984_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9984/hw1.0"
|
||||
#define QCA9984_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9984_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9888 2.0 defines */
|
||||
#define QCA9888_HW_2_0_DEV_VERSION 0x1000000
|
||||
#define QCA9888_HW_DEV_TYPE 0xc
|
||||
#define QCA9888_HW_2_0_CHIP_ID_REV 0x0
|
||||
#define QCA9888_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA9888/hw2.0"
|
||||
#define QCA9888_HW_2_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9888_HW_2_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9377 1.0 definitions */
|
||||
#define QCA9377_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9377/hw1.0"
|
||||
#define QCA9377_HW_1_0_FW_FILE "firmware.bin"
|
||||
#define QCA9377_HW_1_0_OTP_FILE "otp.bin"
|
||||
#define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9377_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA4019 1.0 definitions */
|
||||
#define QCA4019_HW_1_0_DEV_VERSION 0x01000000
|
||||
#define QCA4019_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA4019/hw1.0"
|
||||
#define QCA4019_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA4019_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
#define ATH10K_FW_API2_FILE "firmware-2.bin"
|
||||
#define ATH10K_FW_API3_FILE "firmware-3.bin"
|
||||
|
||||
|
@ -126,8 +148,6 @@ enum qca9377_chip_id_rev {
|
|||
|
||||
#define REG_DUMP_COUNT_QCA988X 60
|
||||
|
||||
#define QCA988X_CAL_DATA_LEN 2116
|
||||
|
||||
struct ath10k_fw_ie {
|
||||
__le32 id;
|
||||
__le32 len;
|
||||
|
@ -199,11 +219,14 @@ enum ath10k_hw_rev {
|
|||
ATH10K_HW_QCA988X,
|
||||
ATH10K_HW_QCA6174,
|
||||
ATH10K_HW_QCA99X0,
|
||||
ATH10K_HW_QCA9888,
|
||||
ATH10K_HW_QCA9984,
|
||||
ATH10K_HW_QCA9377,
|
||||
ATH10K_HW_QCA4019,
|
||||
ATH10K_HW_QCA9887,
|
||||
};
|
||||
|
||||
struct ath10k_hw_regs {
|
||||
u32 rtc_state_cold_reset_mask;
|
||||
u32 rtc_soc_base_address;
|
||||
u32 rtc_wmac_base_address;
|
||||
u32 soc_core_base_address;
|
||||
|
@ -232,6 +255,7 @@ struct ath10k_hw_regs {
|
|||
extern const struct ath10k_hw_regs qca988x_regs;
|
||||
extern const struct ath10k_hw_regs qca6174_regs;
|
||||
extern const struct ath10k_hw_regs qca99x0_regs;
|
||||
extern const struct ath10k_hw_regs qca4019_regs;
|
||||
|
||||
struct ath10k_hw_values {
|
||||
u32 rtc_state_val_on;
|
||||
|
@ -245,16 +269,22 @@ struct ath10k_hw_values {
|
|||
extern const struct ath10k_hw_values qca988x_values;
|
||||
extern const struct ath10k_hw_values qca6174_values;
|
||||
extern const struct ath10k_hw_values qca99x0_values;
|
||||
extern const struct ath10k_hw_values qca9888_values;
|
||||
extern const struct ath10k_hw_values qca4019_values;
|
||||
|
||||
void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev);
|
||||
|
||||
#define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X)
|
||||
#define QCA_REV_9887(ar) ((ar)->hw_rev == ATH10K_HW_QCA9887)
|
||||
#define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174)
|
||||
#define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0)
|
||||
#define QCA_REV_9888(ar) ((ar)->hw_rev == ATH10K_HW_QCA9888)
|
||||
#define QCA_REV_9984(ar) ((ar)->hw_rev == ATH10K_HW_QCA9984)
|
||||
#define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377)
|
||||
#define QCA_REV_40XX(ar) ((ar)->hw_rev == ATH10K_HW_QCA4019)
|
||||
|
||||
/* Known pecularities:
|
||||
/* Known peculiarities:
|
||||
* - raw appears in nwifi decap, raw and nwifi appear in ethernet decap
|
||||
* - raw have FCS, nwifi doesn't
|
||||
* - ethernet frames have 802.11 header decapped and parts (base hdr, cipher
|
||||
|
@ -277,15 +307,6 @@ enum ath10k_mcast2ucast_mode {
|
|||
ATH10K_MCAST2UCAST_ENABLED = 1,
|
||||
};
|
||||
|
||||
struct ath10k_pktlog_hdr {
|
||||
__le16 flags;
|
||||
__le16 missed_cnt;
|
||||
__le16 log_type;
|
||||
__le16 size;
|
||||
__le32 timestamp;
|
||||
u8 payload[0];
|
||||
} __packed;
|
||||
|
||||
enum ath10k_hw_rate_ofdm {
|
||||
ATH10K_HW_RATE_OFDM_48M = 0,
|
||||
ATH10K_HW_RATE_OFDM_24M,
|
||||
|
@ -307,6 +328,110 @@ enum ath10k_hw_rate_cck {
|
|||
ATH10K_HW_RATE_CCK_SP_2M,
|
||||
};
|
||||
|
||||
enum ath10k_hw_rate_rev2_cck {
|
||||
ATH10K_HW_RATE_REV2_CCK_LP_1M = 1,
|
||||
ATH10K_HW_RATE_REV2_CCK_LP_2M,
|
||||
ATH10K_HW_RATE_REV2_CCK_LP_5_5M,
|
||||
ATH10K_HW_RATE_REV2_CCK_LP_11M,
|
||||
ATH10K_HW_RATE_REV2_CCK_SP_2M,
|
||||
ATH10K_HW_RATE_REV2_CCK_SP_5_5M,
|
||||
ATH10K_HW_RATE_REV2_CCK_SP_11M,
|
||||
};
|
||||
|
||||
enum ath10k_hw_cc_wraparound_type {
|
||||
ATH10K_HW_CC_WRAP_DISABLED = 0,
|
||||
|
||||
/* This type is when the HW chip has a quirky Cycle Counter
|
||||
* wraparound which resets to 0x7fffffff instead of 0. All
|
||||
* other CC related counters (e.g. Rx Clear Count) are divided
|
||||
* by 2 so they never wraparound themselves.
|
||||
*/
|
||||
ATH10K_HW_CC_WRAP_SHIFTED_ALL = 1,
|
||||
|
||||
/* Each hw counter wrapsaround independently. When the
|
||||
* counter overflows the repestive counter is right shifted
|
||||
* by 1, i.e reset to 0x7fffffff, and other counters will be
|
||||
* running unaffected. In this type of wraparound, it should
|
||||
* be possible to report accurate Rx busy time unlike the
|
||||
* first type.
|
||||
*/
|
||||
ATH10K_HW_CC_WRAP_SHIFTED_EACH = 2,
|
||||
};
|
||||
|
||||
struct ath10k_hw_params {
|
||||
u32 id;
|
||||
u16 dev_id;
|
||||
const char *name;
|
||||
u32 patch_load_addr;
|
||||
int uart_pin;
|
||||
u32 otp_exe_param;
|
||||
|
||||
/* Type of hw cycle counter wraparound logic, for more info
|
||||
* refer enum ath10k_hw_cc_wraparound_type.
|
||||
*/
|
||||
enum ath10k_hw_cc_wraparound_type cc_wraparound_type;
|
||||
|
||||
/* Some of chip expects fragment descriptor to be continuous
|
||||
* memory for any TX operation. Set continuous_frag_desc flag
|
||||
* for the hardware which have such requirement.
|
||||
*/
|
||||
bool continuous_frag_desc;
|
||||
|
||||
/* CCK hardware rate table mapping for the newer chipsets
|
||||
* like QCA99X0, QCA4019 got revised. The CCK h/w rate values
|
||||
* are in a proper order with respect to the rate/preamble
|
||||
*/
|
||||
bool cck_rate_map_rev2;
|
||||
|
||||
u32 channel_counters_freq_hz;
|
||||
|
||||
/* Mgmt tx descriptors threshold for limiting probe response
|
||||
* frames.
|
||||
*/
|
||||
u32 max_probe_resp_desc_thres;
|
||||
|
||||
u32 tx_chain_mask;
|
||||
u32 rx_chain_mask;
|
||||
u32 max_spatial_stream;
|
||||
u32 cal_data_len;
|
||||
|
||||
struct ath10k_hw_params_fw {
|
||||
const char *dir;
|
||||
const char *board;
|
||||
size_t board_size;
|
||||
size_t board_ext_size;
|
||||
} fw;
|
||||
|
||||
/* qca99x0 family chips deliver broadcast/multicast management
|
||||
* frames encrypted and expect software do decryption.
|
||||
*/
|
||||
bool sw_decrypt_mcast_mgmt;
|
||||
|
||||
const struct ath10k_hw_ops *hw_ops;
|
||||
|
||||
/* Number of bytes used for alignment in rx_hdr_status of rx desc. */
|
||||
int decap_align_bytes;
|
||||
};
|
||||
|
||||
struct htt_rx_desc;
|
||||
|
||||
/* Defines needed for Rx descriptor abstraction */
|
||||
struct ath10k_hw_ops {
|
||||
int (*rx_desc_get_l3_pad_bytes)(struct htt_rx_desc *rxd);
|
||||
};
|
||||
|
||||
extern const struct ath10k_hw_ops qca988x_ops;
|
||||
extern const struct ath10k_hw_ops qca99x0_ops;
|
||||
|
||||
static inline int
|
||||
ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
|
||||
struct htt_rx_desc *rxd)
|
||||
{
|
||||
if (hw->hw_ops->rx_desc_get_l3_pad_bytes)
|
||||
return hw->hw_ops->rx_desc_get_l3_pad_bytes(rxd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Target specific defines for MAIN firmware */
|
||||
#define TARGET_NUM_VDEVS 8
|
||||
#define TARGET_NUM_PEER_AST 2
|
||||
|
@ -348,14 +473,19 @@ enum ath10k_hw_rate_cck {
|
|||
#define TARGET_10X_MAC_AGGR_DELIM 0
|
||||
#define TARGET_10X_AST_SKID_LIMIT 128
|
||||
#define TARGET_10X_NUM_STATIONS 128
|
||||
#define TARGET_10X_TX_STATS_NUM_STATIONS 118
|
||||
#define TARGET_10X_NUM_PEERS ((TARGET_10X_NUM_STATIONS) + \
|
||||
(TARGET_10X_NUM_VDEVS))
|
||||
#define TARGET_10X_TX_STATS_NUM_PEERS ((TARGET_10X_TX_STATS_NUM_STATIONS) + \
|
||||
(TARGET_10X_NUM_VDEVS))
|
||||
#define TARGET_10X_NUM_OFFLOAD_PEERS 0
|
||||
#define TARGET_10X_NUM_OFFLOAD_REORDER_BUFS 0
|
||||
#define TARGET_10X_NUM_PEER_KEYS 2
|
||||
#define TARGET_10X_NUM_TIDS_MAX 256
|
||||
#define TARGET_10X_NUM_TIDS min((TARGET_10X_NUM_TIDS_MAX), \
|
||||
(TARGET_10X_NUM_PEERS) * 2)
|
||||
#define TARGET_10X_TX_STATS_NUM_TIDS min((TARGET_10X_NUM_TIDS_MAX), \
|
||||
(TARGET_10X_TX_STATS_NUM_PEERS) * 2)
|
||||
#define TARGET_10X_TX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2))
|
||||
#define TARGET_10X_RX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2))
|
||||
#define TARGET_10X_RX_TIMEOUT_LO_PRI 100
|
||||
|
@ -400,15 +530,14 @@ enum ath10k_hw_rate_cck {
|
|||
|
||||
#define TARGET_10_4_NUM_QCACHE_PEERS_MAX 512
|
||||
#define TARGET_10_4_QCACHE_ACTIVE_PEERS 50
|
||||
#define TARGET_10_4_QCACHE_ACTIVE_PEERS_PFC 35
|
||||
#define TARGET_10_4_NUM_OFFLOAD_PEERS 0
|
||||
#define TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS 0
|
||||
#define TARGET_10_4_NUM_PEER_KEYS 2
|
||||
#define TARGET_10_4_TGT_NUM_TIDS ((TARGET_10_4_NUM_PEERS) * 2)
|
||||
#define TARGET_10_4_NUM_MSDU_DESC (1024 + 400)
|
||||
#define TARGET_10_4_NUM_MSDU_DESC_PFC 2500
|
||||
#define TARGET_10_4_AST_SKID_LIMIT 32
|
||||
#define TARGET_10_4_TX_CHAIN_MASK (BIT(0) | BIT(1) | \
|
||||
BIT(2) | BIT(3))
|
||||
#define TARGET_10_4_RX_CHAIN_MASK (BIT(0) | BIT(1) | \
|
||||
BIT(2) | BIT(3))
|
||||
|
||||
/* 100 ms for video, best-effort, and background */
|
||||
#define TARGET_10_4_RX_TIMEOUT_LO_PRI 100
|
||||
|
@ -434,7 +563,6 @@ enum ath10k_hw_rate_cck {
|
|||
#define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1
|
||||
#define TARGET_10_4_VOW_CONFIG 0
|
||||
#define TARGET_10_4_GTK_OFFLOAD_MAX_VDEV 3
|
||||
#define TARGET_10_4_NUM_MSDU_DESC (1024 + 400)
|
||||
#define TARGET_10_4_11AC_TX_MAX_FRAGS 2
|
||||
#define TARGET_10_4_MAX_PEER_EXT_STATS 16
|
||||
#define TARGET_10_4_SMART_ANT_CAP 0
|
||||
|
@ -468,7 +596,6 @@ enum ath10k_hw_rate_cck {
|
|||
/* as of IP3.7.1 */
|
||||
#define RTC_STATE_V_ON ar->hw_values->rtc_state_val_on
|
||||
|
||||
#define RTC_STATE_COLD_RESET_MASK ar->regs->rtc_state_cold_reset_mask
|
||||
#define RTC_STATE_V_LSB 0
|
||||
#define RTC_STATE_V_MASK 0x00000007
|
||||
#define RTC_STATE_ADDRESS 0x0000
|
||||
|
@ -531,7 +658,10 @@ enum ath10k_hw_rate_cck {
|
|||
#define WLAN_SYSTEM_SLEEP_DISABLE_MASK 0x00000001
|
||||
|
||||
#define WLAN_GPIO_PIN0_ADDRESS 0x00000028
|
||||
#define WLAN_GPIO_PIN0_CONFIG_LSB 11
|
||||
#define WLAN_GPIO_PIN0_CONFIG_MASK 0x00007800
|
||||
#define WLAN_GPIO_PIN0_PAD_PULL_LSB 5
|
||||
#define WLAN_GPIO_PIN0_PAD_PULL_MASK 0x00000060
|
||||
#define WLAN_GPIO_PIN1_ADDRESS 0x0000002c
|
||||
#define WLAN_GPIO_PIN1_CONFIG_MASK 0x00007800
|
||||
#define WLAN_GPIO_PIN10_ADDRESS 0x00000050
|
||||
|
@ -544,6 +674,8 @@ enum ath10k_hw_rate_cck {
|
|||
#define CLOCK_GPIO_BT_CLK_OUT_EN_MASK 0
|
||||
|
||||
#define SI_CONFIG_OFFSET 0x00000000
|
||||
#define SI_CONFIG_ERR_INT_LSB 19
|
||||
#define SI_CONFIG_ERR_INT_MASK 0x00080000
|
||||
#define SI_CONFIG_BIDIR_OD_DATA_LSB 18
|
||||
#define SI_CONFIG_BIDIR_OD_DATA_MASK 0x00040000
|
||||
#define SI_CONFIG_I2C_LSB 16
|
||||
|
@ -557,7 +689,9 @@ enum ath10k_hw_rate_cck {
|
|||
#define SI_CONFIG_DIVIDER_LSB 0
|
||||
#define SI_CONFIG_DIVIDER_MASK 0x0000000f
|
||||
#define SI_CS_OFFSET 0x00000004
|
||||
#define SI_CS_DONE_ERR_LSB 10
|
||||
#define SI_CS_DONE_ERR_MASK 0x00000400
|
||||
#define SI_CS_DONE_INT_LSB 9
|
||||
#define SI_CS_DONE_INT_MASK 0x00000200
|
||||
#define SI_CS_START_LSB 8
|
||||
#define SI_CS_START_MASK 0x00000100
|
||||
|
@ -586,6 +720,7 @@ enum ath10k_hw_rate_cck {
|
|||
#define FW_INDICATOR_ADDRESS ar->regs->fw_indicator_address
|
||||
#define FW_IND_EVENT_PENDING 1
|
||||
#define FW_IND_INITIALIZED 2
|
||||
#define FW_IND_HOST_READY 0x80000000
|
||||
|
||||
/* HOST_REG interrupt from firmware */
|
||||
#define PCIE_INTR_FIRMWARE_MASK ar->regs->pcie_intr_fw_mask
|
||||
|
@ -607,7 +742,10 @@ enum ath10k_hw_rate_cck {
|
|||
#define GPIO_BASE_ADDRESS WLAN_GPIO_BASE_ADDRESS
|
||||
#define GPIO_PIN0_OFFSET WLAN_GPIO_PIN0_ADDRESS
|
||||
#define GPIO_PIN1_OFFSET WLAN_GPIO_PIN1_ADDRESS
|
||||
#define GPIO_PIN0_CONFIG_LSB WLAN_GPIO_PIN0_CONFIG_LSB
|
||||
#define GPIO_PIN0_CONFIG_MASK WLAN_GPIO_PIN0_CONFIG_MASK
|
||||
#define GPIO_PIN0_PAD_PULL_LSB WLAN_GPIO_PIN0_PAD_PULL_LSB
|
||||
#define GPIO_PIN0_PAD_PULL_MASK WLAN_GPIO_PIN0_PAD_PULL_MASK
|
||||
#define GPIO_PIN1_CONFIG_MASK WLAN_GPIO_PIN1_CONFIG_MASK
|
||||
#define SI_BASE_ADDRESS WLAN_SI_BASE_ADDRESS
|
||||
#define SCRATCH_BASE_ADDRESS SOC_CORE_BASE_ADDRESS
|
||||
|
@ -662,6 +800,18 @@ enum ath10k_hw_rate_cck {
|
|||
#define WINDOW_READ_ADDR_ADDRESS MISSING
|
||||
#define WINDOW_WRITE_ADDR_ADDRESS MISSING
|
||||
|
||||
#define QCA9887_1_0_I2C_SDA_GPIO_PIN 5
|
||||
#define QCA9887_1_0_I2C_SDA_PIN_CONFIG 3
|
||||
#define QCA9887_1_0_SI_CLK_GPIO_PIN 17
|
||||
#define QCA9887_1_0_SI_CLK_PIN_CONFIG 3
|
||||
#define QCA9887_1_0_GPIO_ENABLE_W1TS_LOW_ADDRESS 0x00000010
|
||||
|
||||
#define QCA9887_EEPROM_SELECT_READ 0xa10000a0
|
||||
#define QCA9887_EEPROM_ADDR_HI_MASK 0x0000ff00
|
||||
#define QCA9887_EEPROM_ADDR_HI_LSB 8
|
||||
#define QCA9887_EEPROM_ADDR_LO_MASK 0x00ff0000
|
||||
#define QCA9887_EEPROM_ADDR_LO_LSB 16
|
||||
|
||||
#define RTC_STATE_V_GET(x) (((x) & RTC_STATE_V_MASK) >> RTC_STATE_V_LSB)
|
||||
|
||||
#endif /* _HW_H_ */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -66,7 +66,7 @@ void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
|
|||
enum wmi_tlv_tx_pause_action action);
|
||||
|
||||
u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
|
||||
u8 hw_rate);
|
||||
u8 hw_rate, bool cck);
|
||||
u8 ath10k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
|
||||
u32 bitrate);
|
||||
|
||||
|
@ -74,6 +74,14 @@ void ath10k_mac_tx_lock(struct ath10k *ar, int reason);
|
|||
void ath10k_mac_tx_unlock(struct ath10k *ar, int reason);
|
||||
void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason);
|
||||
void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, int reason);
|
||||
bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar);
|
||||
void ath10k_mac_tx_push_pending(struct ath10k *ar);
|
||||
int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
|
||||
struct ieee80211_txq *txq);
|
||||
struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar,
|
||||
u16 peer_id,
|
||||
u8 tid);
|
||||
int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val);
|
||||
|
||||
static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "hw.h"
|
||||
#include "ce.h"
|
||||
#include "ahb.h"
|
||||
|
||||
/*
|
||||
* maximum number of bytes that can be handled atomically by DiagRead/DiagWrite
|
||||
|
@ -147,9 +148,6 @@ struct ath10k_pci_pipe {
|
|||
|
||||
/* protects compl_free and num_send_allowed */
|
||||
spinlock_t pipe_lock;
|
||||
|
||||
struct ath10k_pci *ar_pci;
|
||||
struct tasklet_struct intr;
|
||||
};
|
||||
|
||||
struct ath10k_pci_supp_chip {
|
||||
|
@ -157,6 +155,18 @@ struct ath10k_pci_supp_chip {
|
|||
u32 rev_id;
|
||||
};
|
||||
|
||||
struct ath10k_bus_ops {
|
||||
u32 (*read32)(struct ath10k *ar, u32 offset);
|
||||
void (*write32)(struct ath10k *ar, u32 offset, u32 value);
|
||||
int (*get_num_banks)(struct ath10k *ar);
|
||||
};
|
||||
|
||||
enum ath10k_pci_irq_mode {
|
||||
ATH10K_PCI_IRQ_AUTO = 0,
|
||||
ATH10K_PCI_IRQ_LEGACY = 1,
|
||||
ATH10K_PCI_IRQ_MSI = 2,
|
||||
};
|
||||
|
||||
struct ath10k_pci {
|
||||
struct pci_dev *pdev;
|
||||
struct device *dev;
|
||||
|
@ -164,14 +174,8 @@ struct ath10k_pci {
|
|||
void __iomem *mem;
|
||||
size_t mem_len;
|
||||
|
||||
/*
|
||||
* Number of MSI interrupts granted, 0 --> using legacy PCI line
|
||||
* interrupts.
|
||||
*/
|
||||
int num_msi_intrs;
|
||||
|
||||
struct tasklet_struct intr_tq;
|
||||
struct tasklet_struct msi_fw_err;
|
||||
/* Operating interrupt mode */
|
||||
enum ath10k_pci_irq_mode oper_irq_mode;
|
||||
|
||||
struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX];
|
||||
|
||||
|
@ -225,6 +229,20 @@ struct ath10k_pci {
|
|||
* on MMIO read/write.
|
||||
*/
|
||||
bool pci_ps;
|
||||
|
||||
const struct ath10k_bus_ops *bus_ops;
|
||||
|
||||
/* Chip specific pci reset routine used to do a safe reset */
|
||||
int (*pci_soft_reset)(struct ath10k *ar);
|
||||
|
||||
/* Chip specific pci full reset function */
|
||||
int (*pci_hard_reset)(struct ath10k *ar);
|
||||
|
||||
/* Keep this entry in the last, memory for struct ath10k_ahb is
|
||||
* allocated (ahb support enabled case) in the continuation of
|
||||
* this struct.
|
||||
*/
|
||||
struct ath10k_ahb ahb[0];
|
||||
};
|
||||
|
||||
static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar)
|
||||
|
@ -253,6 +271,40 @@ u32 ath10k_pci_read32(struct ath10k *ar, u32 offset);
|
|||
u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr);
|
||||
u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr);
|
||||
|
||||
int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
|
||||
struct ath10k_hif_sg_item *items, int n_items);
|
||||
int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
|
||||
size_t buf_len);
|
||||
int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
|
||||
const void *data, int nbytes);
|
||||
int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, void *req, u32 req_len,
|
||||
void *resp, u32 *resp_len);
|
||||
int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id,
|
||||
u8 *ul_pipe, u8 *dl_pipe);
|
||||
void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, u8 *ul_pipe,
|
||||
u8 *dl_pipe);
|
||||
void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe,
|
||||
int force);
|
||||
u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe);
|
||||
void ath10k_pci_hif_power_down(struct ath10k *ar);
|
||||
int ath10k_pci_alloc_pipes(struct ath10k *ar);
|
||||
void ath10k_pci_free_pipes(struct ath10k *ar);
|
||||
void ath10k_pci_free_pipes(struct ath10k *ar);
|
||||
void ath10k_pci_rx_replenish_retry(unsigned long ptr);
|
||||
void ath10k_pci_ce_deinit(struct ath10k *ar);
|
||||
void ath10k_pci_init_napi(struct ath10k *ar);
|
||||
int ath10k_pci_init_pipes(struct ath10k *ar);
|
||||
int ath10k_pci_init_config(struct ath10k *ar);
|
||||
void ath10k_pci_rx_post(struct ath10k *ar);
|
||||
void ath10k_pci_flush(struct ath10k *ar);
|
||||
void ath10k_pci_enable_legacy_irq(struct ath10k *ar);
|
||||
bool ath10k_pci_irq_pending(struct ath10k *ar);
|
||||
void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar);
|
||||
void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar);
|
||||
int ath10k_pci_wait_for_target_init(struct ath10k *ar);
|
||||
int ath10k_pci_setup_resource(struct ath10k *ar);
|
||||
void ath10k_pci_release_resource(struct ath10k *ar);
|
||||
|
||||
/* QCA6174 is known to have Tx/Rx issues when SOC_WAKE register is poked too
|
||||
* frequently. To avoid this put SoC to sleep after a very conservative grace
|
||||
* period. Adjust with great care.
|
||||
|
|
|
@ -656,26 +656,6 @@ struct rx_msdu_end {
|
|||
* Reserved: HW should fill with zero. FW should ignore.
|
||||
*/
|
||||
|
||||
#define RX_PPDU_START_SIG_RATE_SELECT_OFDM 0
|
||||
#define RX_PPDU_START_SIG_RATE_SELECT_CCK 1
|
||||
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_48 0
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_24 1
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_12 2
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_6 3
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_54 4
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_36 5
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_18 6
|
||||
#define RX_PPDU_START_SIG_RATE_OFDM_9 7
|
||||
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_LP_11 0
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_LP_5_5 1
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_LP_2 2
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_LP_1 3
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_SP_11 4
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_SP_5_5 5
|
||||
#define RX_PPDU_START_SIG_RATE_CCK_SP_2 6
|
||||
|
||||
#define HTT_RX_PPDU_START_PREAMBLE_LEGACY 0x04
|
||||
#define HTT_RX_PPDU_START_PREAMBLE_HT 0x08
|
||||
#define HTT_RX_PPDU_START_PREAMBLE_HT_WITH_TXBF 0x09
|
||||
|
@ -711,25 +691,6 @@ struct rx_msdu_end {
|
|||
/* No idea what this flag means. It seems to be always set in rate. */
|
||||
#define RX_PPDU_START_RATE_FLAG BIT(3)
|
||||
|
||||
enum rx_ppdu_start_rate {
|
||||
RX_PPDU_START_RATE_OFDM_48M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_48M,
|
||||
RX_PPDU_START_RATE_OFDM_24M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_24M,
|
||||
RX_PPDU_START_RATE_OFDM_12M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_12M,
|
||||
RX_PPDU_START_RATE_OFDM_6M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_6M,
|
||||
RX_PPDU_START_RATE_OFDM_54M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_54M,
|
||||
RX_PPDU_START_RATE_OFDM_36M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_36M,
|
||||
RX_PPDU_START_RATE_OFDM_18M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_18M,
|
||||
RX_PPDU_START_RATE_OFDM_9M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_9M,
|
||||
|
||||
RX_PPDU_START_RATE_CCK_LP_11M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_11M,
|
||||
RX_PPDU_START_RATE_CCK_LP_5_5M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_5_5M,
|
||||
RX_PPDU_START_RATE_CCK_LP_2M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_2M,
|
||||
RX_PPDU_START_RATE_CCK_LP_1M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_1M,
|
||||
RX_PPDU_START_RATE_CCK_SP_11M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_SP_11M,
|
||||
RX_PPDU_START_RATE_CCK_SP_5_5M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_SP_5_5M,
|
||||
RX_PPDU_START_RATE_CCK_SP_2M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_SP_2M,
|
||||
};
|
||||
|
||||
struct rx_ppdu_start {
|
||||
struct {
|
||||
u8 pri20_mhz;
|
||||
|
@ -994,7 +955,41 @@ struct rx_pkt_end {
|
|||
__le32 info0; /* %RX_PKT_END_INFO0_ */
|
||||
__le32 phy_timestamp_1;
|
||||
__le32 phy_timestamp_2;
|
||||
__le32 rx_location_info; /* %RX_LOCATION_INFO_ */
|
||||
} __packed;
|
||||
|
||||
#define RX_LOCATION_INFO0_RTT_FAC_LEGACY_MASK 0x00003fff
|
||||
#define RX_LOCATION_INFO0_RTT_FAC_LEGACY_LSB 0
|
||||
#define RX_LOCATION_INFO0_RTT_FAC_VHT_MASK 0x1fff8000
|
||||
#define RX_LOCATION_INFO0_RTT_FAC_VHT_LSB 15
|
||||
#define RX_LOCATION_INFO0_RTT_STRONGEST_CHAIN_MASK 0xc0000000
|
||||
#define RX_LOCATION_INFO0_RTT_STRONGEST_CHAIN_LSB 30
|
||||
#define RX_LOCATION_INFO0_RTT_FAC_LEGACY_STATUS BIT(14)
|
||||
#define RX_LOCATION_INFO0_RTT_FAC_VHT_STATUS BIT(29)
|
||||
|
||||
#define RX_LOCATION_INFO1_RTT_PREAMBLE_TYPE_MASK 0x0000000c
|
||||
#define RX_LOCATION_INFO1_RTT_PREAMBLE_TYPE_LSB 2
|
||||
#define RX_LOCATION_INFO1_PKT_BW_MASK 0x00000030
|
||||
#define RX_LOCATION_INFO1_PKT_BW_LSB 4
|
||||
#define RX_LOCATION_INFO1_SKIP_P_SKIP_BTCF_MASK 0x0000ff00
|
||||
#define RX_LOCATION_INFO1_SKIP_P_SKIP_BTCF_LSB 8
|
||||
#define RX_LOCATION_INFO1_RTT_MSC_RATE_MASK 0x000f0000
|
||||
#define RX_LOCATION_INFO1_RTT_MSC_RATE_LSB 16
|
||||
#define RX_LOCATION_INFO1_RTT_PBD_LEG_BW_MASK 0x00300000
|
||||
#define RX_LOCATION_INFO1_RTT_PBD_LEG_BW_LSB 20
|
||||
#define RX_LOCATION_INFO1_TIMING_BACKOFF_MASK 0x07c00000
|
||||
#define RX_LOCATION_INFO1_TIMING_BACKOFF_LSB 22
|
||||
#define RX_LOCATION_INFO1_RTT_TX_FRAME_PHASE_MASK 0x18000000
|
||||
#define RX_LOCATION_INFO1_RTT_TX_FRAME_PHASE_LSB 27
|
||||
#define RX_LOCATION_INFO1_RTT_CFR_STATUS BIT(0)
|
||||
#define RX_LOCATION_INFO1_RTT_CIR_STATUS BIT(1)
|
||||
#define RX_LOCATION_INFO1_RTT_GI_TYPE BIT(7)
|
||||
#define RX_LOCATION_INFO1_RTT_MAC_PHY_PHASE BIT(29)
|
||||
#define RX_LOCATION_INFO1_RTT_TX_DATA_START_X_PHASE BIT(30)
|
||||
#define RX_LOCATION_INFO1_RX_LOCATION_VALID BIT(31)
|
||||
|
||||
struct rx_location_info {
|
||||
__le32 rx_location_info0; /* %RX_LOCATION_INFO0_ */
|
||||
__le32 rx_location_info1; /* %RX_LOCATION_INFO1_ */
|
||||
} __packed;
|
||||
|
||||
enum rx_phy_ppdu_end_info0 {
|
||||
|
@ -1067,6 +1062,17 @@ struct rx_phy_ppdu_end {
|
|||
|
||||
struct rx_ppdu_end_qca99x0 {
|
||||
struct rx_pkt_end rx_pkt_end;
|
||||
__le32 rx_location_info; /* %RX_LOCATION_INFO_ */
|
||||
struct rx_phy_ppdu_end rx_phy_ppdu_end;
|
||||
__le32 rx_timing_offset; /* %RX_PPDU_END_RX_TIMING_OFFSET_ */
|
||||
__le32 rx_info; /* %RX_PPDU_END_RX_INFO_ */
|
||||
__le16 bb_length;
|
||||
__le16 info1; /* %RX_PPDU_END_INFO1_ */
|
||||
} __packed;
|
||||
|
||||
struct rx_ppdu_end_qca9984 {
|
||||
struct rx_pkt_end rx_pkt_end;
|
||||
struct rx_location_info rx_location_info;
|
||||
struct rx_phy_ppdu_end rx_phy_ppdu_end;
|
||||
__le32 rx_timing_offset; /* %RX_PPDU_END_RX_TIMING_OFFSET_ */
|
||||
__le32 rx_info; /* %RX_PPDU_END_RX_INFO_ */
|
||||
|
@ -1080,6 +1086,7 @@ struct rx_ppdu_end {
|
|||
struct rx_ppdu_end_qca988x qca988x;
|
||||
struct rx_ppdu_end_qca6174 qca6174;
|
||||
struct rx_ppdu_end_qca99x0 qca99x0;
|
||||
struct rx_ppdu_end_qca9984 qca9984;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
|
|
|
@ -101,9 +101,9 @@ int ath10k_spectral_process_fft(struct ath10k *ar,
|
|||
break;
|
||||
case 80:
|
||||
/* TODO: As experiments with an analogue sender and various
|
||||
* configuaritions (fft-sizes of 64/128/256 and 20/40/80 Mhz)
|
||||
* configurations (fft-sizes of 64/128/256 and 20/40/80 Mhz)
|
||||
* show, the particular configuration of 80 MHz/64 bins does
|
||||
* not match with the other smaples at all. Until the reason
|
||||
* not match with the other samples at all. Until the reason
|
||||
* for that is found, don't report these samples.
|
||||
*/
|
||||
if (bin_len == 64)
|
||||
|
|
|
@ -135,26 +135,17 @@ ath10k_swap_code_seg_alloc(struct ath10k *ar, size_t swap_bin_len)
|
|||
}
|
||||
|
||||
int ath10k_swap_code_seg_configure(struct ath10k *ar,
|
||||
enum ath10k_swap_code_seg_bin_type type)
|
||||
const struct ath10k_fw_file *fw_file)
|
||||
{
|
||||
int ret;
|
||||
struct ath10k_swap_code_seg_info *seg_info = NULL;
|
||||
|
||||
switch (type) {
|
||||
case ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW:
|
||||
if (!ar->swap.firmware_swap_code_seg_info)
|
||||
return 0;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot found firmware code swap binary\n");
|
||||
seg_info = ar->swap.firmware_swap_code_seg_info;
|
||||
break;
|
||||
default:
|
||||
case ATH10K_SWAP_CODE_SEG_BIN_TYPE_OTP:
|
||||
case ATH10K_SWAP_CODE_SEG_BIN_TYPE_UTF:
|
||||
ath10k_warn(ar, "ignoring unknown code swap binary type %d\n",
|
||||
type);
|
||||
if (!fw_file->firmware_swap_code_seg_info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot found firmware code swap binary\n");
|
||||
|
||||
seg_info = fw_file->firmware_swap_code_seg_info;
|
||||
|
||||
ret = ath10k_bmi_write_memory(ar, seg_info->target_addr,
|
||||
&seg_info->seg_hw_info,
|
||||
|
@ -168,32 +159,41 @@ int ath10k_swap_code_seg_configure(struct ath10k *ar,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ath10k_swap_code_seg_release(struct ath10k *ar)
|
||||
void ath10k_swap_code_seg_release(struct ath10k *ar,
|
||||
struct ath10k_fw_file *fw_file)
|
||||
{
|
||||
ath10k_swap_code_seg_free(ar, ar->swap.firmware_swap_code_seg_info);
|
||||
ar->swap.firmware_codeswap_data = NULL;
|
||||
ar->swap.firmware_codeswap_len = 0;
|
||||
ar->swap.firmware_swap_code_seg_info = NULL;
|
||||
ath10k_swap_code_seg_free(ar, fw_file->firmware_swap_code_seg_info);
|
||||
|
||||
/* FIXME: these two assignments look to bein wrong place! Shouldn't
|
||||
* they be in ath10k_core_free_firmware_files() like the rest?
|
||||
*/
|
||||
fw_file->codeswap_data = NULL;
|
||||
fw_file->codeswap_len = 0;
|
||||
|
||||
fw_file->firmware_swap_code_seg_info = NULL;
|
||||
}
|
||||
|
||||
int ath10k_swap_code_seg_init(struct ath10k *ar)
|
||||
int ath10k_swap_code_seg_init(struct ath10k *ar, struct ath10k_fw_file *fw_file)
|
||||
{
|
||||
int ret;
|
||||
struct ath10k_swap_code_seg_info *seg_info;
|
||||
const void *codeswap_data;
|
||||
size_t codeswap_len;
|
||||
|
||||
if (!ar->swap.firmware_codeswap_len || !ar->swap.firmware_codeswap_data)
|
||||
codeswap_data = fw_file->codeswap_data;
|
||||
codeswap_len = fw_file->codeswap_len;
|
||||
|
||||
if (!codeswap_len || !codeswap_data)
|
||||
return 0;
|
||||
|
||||
seg_info = ath10k_swap_code_seg_alloc(ar,
|
||||
ar->swap.firmware_codeswap_len);
|
||||
seg_info = ath10k_swap_code_seg_alloc(ar, codeswap_len);
|
||||
if (!seg_info) {
|
||||
ath10k_err(ar, "failed to allocate fw code swap segment\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = ath10k_swap_code_seg_fill(ar, seg_info,
|
||||
ar->swap.firmware_codeswap_data,
|
||||
ar->swap.firmware_codeswap_len);
|
||||
codeswap_data, codeswap_len);
|
||||
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to initialize fw code swap segment: %d\n",
|
||||
|
@ -202,7 +202,7 @@ int ath10k_swap_code_seg_init(struct ath10k *ar)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ar->swap.firmware_swap_code_seg_info = seg_info;
|
||||
fw_file->firmware_swap_code_seg_info = seg_info;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
/* Currently only one swap segment is supported */
|
||||
#define ATH10K_SWAP_CODE_SEG_NUM_SUPPORTED 1
|
||||
|
||||
struct ath10k_fw_file;
|
||||
|
||||
struct ath10k_swap_code_seg_tlv {
|
||||
__le32 address;
|
||||
__le32 length;
|
||||
|
@ -39,12 +41,6 @@ union ath10k_swap_code_seg_item {
|
|||
struct ath10k_swap_code_seg_tail tail;
|
||||
} __packed;
|
||||
|
||||
enum ath10k_swap_code_seg_bin_type {
|
||||
ATH10K_SWAP_CODE_SEG_BIN_TYPE_OTP,
|
||||
ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW,
|
||||
ATH10K_SWAP_CODE_SEG_BIN_TYPE_UTF,
|
||||
};
|
||||
|
||||
struct ath10k_swap_code_seg_hw_info {
|
||||
/* Swap binary image size */
|
||||
__le32 swap_size;
|
||||
|
@ -65,8 +61,10 @@ struct ath10k_swap_code_seg_info {
|
|||
};
|
||||
|
||||
int ath10k_swap_code_seg_configure(struct ath10k *ar,
|
||||
enum ath10k_swap_code_seg_bin_type type);
|
||||
void ath10k_swap_code_seg_release(struct ath10k *ar);
|
||||
int ath10k_swap_code_seg_init(struct ath10k *ar);
|
||||
const struct ath10k_fw_file *fw_file);
|
||||
void ath10k_swap_code_seg_release(struct ath10k *ar,
|
||||
struct ath10k_fw_file *fw_file);
|
||||
int ath10k_swap_code_seg_init(struct ath10k *ar,
|
||||
struct ath10k_fw_file *fw_file);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -405,7 +405,7 @@ Fw Mode/SubMode Mask
|
|||
* 1. target firmware would check magic number and if it's a match, firmware
|
||||
* would consider the bits[0:15] are valid and base on that to calculate
|
||||
* the end of DRAM. Early allocation would be located at that area and
|
||||
* may be reclaimed when necesary
|
||||
* may be reclaimed when necessary
|
||||
* 2. if no magic number is found, early allocation would happen at "_end"
|
||||
* symbol of ROM which is located before the app-data and might NOT be
|
||||
* re-claimable. If this is adopted, link script should keep this in
|
||||
|
@ -438,7 +438,7 @@ Fw Mode/SubMode Mask
|
|||
((HOST_INTEREST->hi_pwr_save_flags & HI_PWR_SAVE_LPL_ENABLED))
|
||||
#define HI_DEV_LPL_TYPE_GET(_devix) \
|
||||
(HOST_INTEREST->hi_pwr_save_flags & ((HI_PWR_SAVE_LPL_DEV_MASK) << \
|
||||
(HI_PWR_SAVE_LPL_DEV0_LSB + (_devix)*2)))
|
||||
(HI_PWR_SAVE_LPL_DEV0_LSB + (_devix) * 2)))
|
||||
|
||||
#define HOST_INTEREST_SMPS_IS_ALLOWED() \
|
||||
((HOST_INTEREST->hi_smps_options & HI_SMPS_ALLOW_MASK))
|
||||
|
@ -447,6 +447,9 @@ Fw Mode/SubMode Mask
|
|||
#define QCA988X_BOARD_DATA_SZ 7168
|
||||
#define QCA988X_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
#define QCA9887_BOARD_DATA_SZ 7168
|
||||
#define QCA9887_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
#define QCA6174_BOARD_DATA_SZ 8192
|
||||
#define QCA6174_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
|
@ -456,4 +459,7 @@ Fw Mode/SubMode Mask
|
|||
#define QCA99X0_BOARD_DATA_SZ 12288
|
||||
#define QCA99X0_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
#define QCA4019_BOARD_DATA_SZ 12064
|
||||
#define QCA4019_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
#endif /* __TARGADDRS_H__ */
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "wmi.h"
|
||||
#include "hif.h"
|
||||
#include "hw.h"
|
||||
#include "core.h"
|
||||
|
||||
#include "testmode_i.h"
|
||||
|
||||
|
@ -45,7 +46,7 @@ bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
|
|||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||
"testmode event wmi cmd_id %d skb %p skb->len %d\n",
|
||||
"testmode event wmi cmd_id %d skb %pK skb->len %d\n",
|
||||
cmd_id, skb, skb->len);
|
||||
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
|
||||
|
@ -139,127 +140,8 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
|
|||
return cfg80211_testmode_reply(skb);
|
||||
}
|
||||
|
||||
static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar)
|
||||
{
|
||||
size_t len, magic_len, ie_len;
|
||||
struct ath10k_fw_ie *hdr;
|
||||
char filename[100];
|
||||
__le32 *version;
|
||||
const u8 *data;
|
||||
int ie_id, ret;
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s/%s",
|
||||
ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE);
|
||||
|
||||
/* load utf firmware image */
|
||||
ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
|
||||
filename, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
data = ar->testmode.utf->data;
|
||||
len = ar->testmode.utf->size;
|
||||
|
||||
/* FIXME: call release_firmware() in error cases */
|
||||
|
||||
/* magic also includes the null byte, check that as well */
|
||||
magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;
|
||||
|
||||
if (len < magic_len) {
|
||||
ath10k_err(ar, "utf firmware file is too small to contain magic\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) {
|
||||
ath10k_err(ar, "invalid firmware magic\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* jump over the padding */
|
||||
magic_len = ALIGN(magic_len, 4);
|
||||
|
||||
len -= magic_len;
|
||||
data += magic_len;
|
||||
|
||||
/* loop elements */
|
||||
while (len > sizeof(struct ath10k_fw_ie)) {
|
||||
hdr = (struct ath10k_fw_ie *)data;
|
||||
|
||||
ie_id = le32_to_cpu(hdr->id);
|
||||
ie_len = le32_to_cpu(hdr->len);
|
||||
|
||||
len -= sizeof(*hdr);
|
||||
data += sizeof(*hdr);
|
||||
|
||||
if (len < ie_len) {
|
||||
ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n",
|
||||
ie_id, len, ie_len);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (ie_id) {
|
||||
case ATH10K_FW_IE_FW_VERSION:
|
||||
if (ie_len > sizeof(ar->testmode.utf_version) - 1)
|
||||
break;
|
||||
|
||||
memcpy(ar->testmode.utf_version, data, ie_len);
|
||||
ar->testmode.utf_version[ie_len] = '\0';
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||
"testmode found fw utf version %s\n",
|
||||
ar->testmode.utf_version);
|
||||
break;
|
||||
case ATH10K_FW_IE_TIMESTAMP:
|
||||
/* ignore timestamp, but don't warn about it either */
|
||||
break;
|
||||
case ATH10K_FW_IE_FW_IMAGE:
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||
"testmode found fw image ie (%zd B)\n",
|
||||
ie_len);
|
||||
|
||||
ar->testmode.utf_firmware_data = data;
|
||||
ar->testmode.utf_firmware_len = ie_len;
|
||||
break;
|
||||
case ATH10K_FW_IE_WMI_OP_VERSION:
|
||||
if (ie_len != sizeof(u32))
|
||||
break;
|
||||
version = (__le32 *)data;
|
||||
ar->testmode.op_version = le32_to_cpup(version);
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n",
|
||||
ar->testmode.op_version);
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "Unknown testmode FW IE: %u\n",
|
||||
le32_to_cpu(hdr->id));
|
||||
break;
|
||||
}
|
||||
/* jump over the padding */
|
||||
ie_len = ALIGN(ie_len, 4);
|
||||
|
||||
len -= ie_len;
|
||||
data += ie_len;
|
||||
}
|
||||
|
||||
if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) {
|
||||
ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
release_firmware(ar->testmode.utf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar)
|
||||
static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar,
|
||||
struct ath10k_fw_file *fw_file)
|
||||
{
|
||||
char filename[100];
|
||||
int ret;
|
||||
|
@ -268,7 +150,7 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar)
|
|||
ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
|
||||
|
||||
/* load utf firmware image */
|
||||
ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
|
||||
ret = request_firmware(&fw_file->firmware, filename, ar->dev);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
|
||||
filename, ret);
|
||||
|
@ -281,24 +163,27 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar)
|
|||
* correct WMI interface.
|
||||
*/
|
||||
|
||||
ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
|
||||
ar->testmode.utf_firmware_data = ar->testmode.utf->data;
|
||||
ar->testmode.utf_firmware_len = ar->testmode.utf->size;
|
||||
fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
|
||||
fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_10_1;
|
||||
fw_file->firmware_data = fw_file->firmware->data;
|
||||
fw_file->firmware_len = fw_file->firmware->size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_tm_fetch_firmware(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_fw_components *utf_mode_fw;
|
||||
int ret;
|
||||
|
||||
ret = ath10k_tm_fetch_utf_firmware_api_2(ar);
|
||||
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_UTF_API2_FILE,
|
||||
&ar->testmode.utf_mode_fw.fw_file);
|
||||
if (ret == 0) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2");
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ath10k_tm_fetch_utf_firmware_api_1(ar);
|
||||
ret = ath10k_tm_fetch_utf_firmware_api_1(ar, &ar->testmode.utf_mode_fw.fw_file);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret);
|
||||
return ret;
|
||||
|
@ -306,6 +191,21 @@ static int ath10k_tm_fetch_firmware(struct ath10k *ar)
|
|||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1");
|
||||
|
||||
out:
|
||||
utf_mode_fw = &ar->testmode.utf_mode_fw;
|
||||
|
||||
/* Use the same board data file as the normal firmware uses (but
|
||||
* it's still "owned" by normal_mode_fw so we shouldn't free it.
|
||||
*/
|
||||
utf_mode_fw->board_data = ar->normal_mode_fw.board_data;
|
||||
utf_mode_fw->board_len = ar->normal_mode_fw.board_len;
|
||||
|
||||
if (!utf_mode_fw->fw_file.otp_data) {
|
||||
ath10k_info(ar, "utf.bin didn't contain otp binary, taking it from the normal mode firmware");
|
||||
utf_mode_fw->fw_file.otp_data = ar->normal_mode_fw.fw_file.otp_data;
|
||||
utf_mode_fw->fw_file.otp_len = ar->normal_mode_fw.fw_file.otp_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -329,7 +229,7 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (WARN_ON(ar->testmode.utf != NULL)) {
|
||||
if (WARN_ON(ar->testmode.utf_mode_fw.fw_file.firmware != NULL)) {
|
||||
/* utf image is already downloaded, it shouldn't be */
|
||||
ret = -EEXIST;
|
||||
goto err;
|
||||
|
@ -341,30 +241,34 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (ar->testmode.utf_mode_fw.fw_file.codeswap_data &&
|
||||
ar->testmode.utf_mode_fw.fw_file.codeswap_len) {
|
||||
ret = ath10k_swap_code_seg_init(ar,
|
||||
&ar->testmode.utf_mode_fw.fw_file);
|
||||
if (ret) {
|
||||
ath10k_warn(ar,
|
||||
"failed to init utf code swap segment: %d\n",
|
||||
ret);
|
||||
goto err_release_utf_mode_fw;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->testmode.utf_monitor = true;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
BUILD_BUG_ON(sizeof(ar->fw_features) !=
|
||||
sizeof(ar->testmode.orig_fw_features));
|
||||
|
||||
memcpy(ar->testmode.orig_fw_features, ar->fw_features,
|
||||
sizeof(ar->fw_features));
|
||||
ar->testmode.orig_wmi_op_version = ar->wmi.op_version;
|
||||
memset(ar->fw_features, 0, sizeof(ar->fw_features));
|
||||
|
||||
ar->wmi.op_version = ar->testmode.op_version;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n",
|
||||
ar->wmi.op_version);
|
||||
ar->testmode.utf_mode_fw.fw_file.wmi_op_version);
|
||||
|
||||
ret = ath10k_hif_power_up(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret);
|
||||
ar->state = ATH10K_STATE_OFF;
|
||||
goto err_fw_features;
|
||||
goto err_release_utf_mode_fw;
|
||||
}
|
||||
|
||||
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF);
|
||||
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF,
|
||||
&ar->testmode.utf_mode_fw);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to start core (testmode): %d\n", ret);
|
||||
ar->state = ATH10K_STATE_OFF;
|
||||
|
@ -373,8 +277,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
|||
|
||||
ar->state = ATH10K_STATE_UTF;
|
||||
|
||||
if (strlen(ar->testmode.utf_version) > 0)
|
||||
ver = ar->testmode.utf_version;
|
||||
if (strlen(ar->testmode.utf_mode_fw.fw_file.fw_version) > 0)
|
||||
ver = ar->testmode.utf_mode_fw.fw_file.fw_version;
|
||||
else
|
||||
ver = "API 1";
|
||||
|
||||
|
@ -387,14 +291,14 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
|||
err_power_down:
|
||||
ath10k_hif_power_down(ar);
|
||||
|
||||
err_fw_features:
|
||||
/* 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;
|
||||
err_release_utf_mode_fw:
|
||||
if (ar->testmode.utf_mode_fw.fw_file.codeswap_data &&
|
||||
ar->testmode.utf_mode_fw.fw_file.codeswap_len)
|
||||
ath10k_swap_code_seg_release(ar,
|
||||
&ar->testmode.utf_mode_fw.fw_file);
|
||||
|
||||
release_firmware(ar->testmode.utf);
|
||||
ar->testmode.utf = NULL;
|
||||
release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware);
|
||||
ar->testmode.utf_mode_fw.fw_file.firmware = NULL;
|
||||
|
||||
err:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
@ -415,13 +319,13 @@ static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar)
|
|||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
/* 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;
|
||||
if (ar->testmode.utf_mode_fw.fw_file.codeswap_data &&
|
||||
ar->testmode.utf_mode_fw.fw_file.codeswap_len)
|
||||
ath10k_swap_code_seg_release(ar,
|
||||
&ar->testmode.utf_mode_fw.fw_file);
|
||||
|
||||
release_firmware(ar->testmode.utf);
|
||||
ar->testmode.utf = NULL;
|
||||
release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware);
|
||||
ar->testmode.utf_mode_fw.fw_file.firmware = NULL;
|
||||
|
||||
ar->state = ATH10K_STATE_OFF;
|
||||
}
|
||||
|
@ -479,7 +383,7 @@ static int ath10k_tm_cmd_wmi(struct ath10k *ar, struct nlattr *tb[])
|
|||
cmd_id = nla_get_u32(tb[ATH10K_TM_ATTR_WMI_CMDID]);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||
"testmode cmd wmi cmd_id %d buf %p buf_len %d\n",
|
||||
"testmode cmd wmi cmd_id %d buf %pK buf_len %d\n",
|
||||
cmd_id, buf, buf_len);
|
||||
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", buf, buf_len);
|
||||
|
|
|
@ -187,12 +187,12 @@ int ath10k_thermal_register(struct ath10k *ar)
|
|||
/* 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)
|
||||
if (!(ar->wmi.ops->gen_pdev_get_temperature))
|
||||
return 0;
|
||||
|
||||
/* Avoid linking error on devm_hwmon_device_register_with_groups, I
|
||||
* guess linux/hwmon.h is missing proper stubs. */
|
||||
if (!config_enabled(CONFIG_HWMON))
|
||||
if (!IS_REACHABLE(CONFIG_HWMON))
|
||||
return 0;
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_groups(ar->dev,
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#define ATH10K_QUIET_PERIOD_MIN 25
|
||||
#define ATH10K_QUIET_START_OFFSET 10
|
||||
#define ATH10K_HWMON_NAME_LEN 15
|
||||
#define ATH10K_THERMAL_SYNC_TIMEOUT_HZ (5*HZ)
|
||||
#define ATH10K_THERMAL_SYNC_TIMEOUT_HZ (5 * HZ)
|
||||
#define ATH10K_THERMAL_THROTTLE_MAX 100
|
||||
|
||||
struct ath10k_thermal {
|
||||
|
@ -36,7 +36,7 @@ struct ath10k_thermal {
|
|||
int temperature;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_THERMAL
|
||||
#if IS_REACHABLE(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);
|
||||
|
|
|
@ -250,6 +250,7 @@ TRACE_EVENT(ath10k_wmi_dbglog,
|
|||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(ar->dev))
|
||||
__string(driver, dev_driver_string(ar->dev))
|
||||
__field(u8, hw_type);
|
||||
__field(size_t, buf_len)
|
||||
__dynamic_array(u8, buf, buf_len)
|
||||
),
|
||||
|
@ -257,14 +258,16 @@ TRACE_EVENT(ath10k_wmi_dbglog,
|
|||
TP_fast_assign(
|
||||
__assign_str(device, dev_name(ar->dev));
|
||||
__assign_str(driver, dev_driver_string(ar->dev));
|
||||
__entry->hw_type = ar->hw_rev;
|
||||
__entry->buf_len = buf_len;
|
||||
memcpy(__get_dynamic_array(buf), buf, buf_len);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s %s len %zu",
|
||||
"%s %s %d len %zu",
|
||||
__get_str(driver),
|
||||
__get_str(device),
|
||||
__entry->hw_type,
|
||||
__entry->buf_len
|
||||
)
|
||||
);
|
||||
|
@ -277,6 +280,7 @@ TRACE_EVENT(ath10k_htt_pktlog,
|
|||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(ar->dev))
|
||||
__string(driver, dev_driver_string(ar->dev))
|
||||
__field(u8, hw_type);
|
||||
__field(u16, buf_len)
|
||||
__dynamic_array(u8, pktlog, buf_len)
|
||||
),
|
||||
|
@ -284,14 +288,16 @@ TRACE_EVENT(ath10k_htt_pktlog,
|
|||
TP_fast_assign(
|
||||
__assign_str(device, dev_name(ar->dev));
|
||||
__assign_str(driver, dev_driver_string(ar->dev));
|
||||
__entry->hw_type = ar->hw_rev;
|
||||
__entry->buf_len = buf_len;
|
||||
memcpy(__get_dynamic_array(pktlog), buf, buf_len);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s %s size %hu",
|
||||
"%s %s %d size %hu",
|
||||
__get_str(driver),
|
||||
__get_str(device),
|
||||
__entry->hw_type,
|
||||
__entry->buf_len
|
||||
)
|
||||
);
|
||||
|
@ -440,6 +446,7 @@ TRACE_EVENT(ath10k_htt_rx_desc,
|
|||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(ar->dev))
|
||||
__string(driver, dev_driver_string(ar->dev))
|
||||
__field(u8, hw_type);
|
||||
__field(u16, len)
|
||||
__dynamic_array(u8, rxdesc, len)
|
||||
),
|
||||
|
@ -447,14 +454,16 @@ TRACE_EVENT(ath10k_htt_rx_desc,
|
|||
TP_fast_assign(
|
||||
__assign_str(device, dev_name(ar->dev));
|
||||
__assign_str(driver, dev_driver_string(ar->dev));
|
||||
__entry->hw_type = ar->hw_rev;
|
||||
__entry->len = len;
|
||||
memcpy(__get_dynamic_array(rxdesc), data, len);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s %s rxdesc len %d",
|
||||
"%s %s %d rxdesc len %d",
|
||||
__get_str(driver),
|
||||
__get_str(device),
|
||||
__entry->hw_type,
|
||||
__entry->len
|
||||
)
|
||||
);
|
||||
|
|
|
@ -23,7 +23,12 @@
|
|||
|
||||
static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
if (!ATH10K_SKB_CB(skb)->htt.is_offchan)
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
if (likely(!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)))
|
||||
return;
|
||||
|
||||
if (ath10k_mac_tx_frm_has_freq(ar))
|
||||
return;
|
||||
|
||||
/* If the original wait_for_completion() timed out before
|
||||
|
@ -39,32 +44,30 @@ static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb)
|
|||
complete(&ar->offchan_tx_completed);
|
||||
ar->offchan_tx_skb = NULL; /* just for sanity */
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "completed offchannel skb %p\n", skb);
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "completed offchannel skb %pK\n", skb);
|
||||
out:
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
const struct htt_tx_done *tx_done)
|
||||
int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
const struct htt_tx_done *tx_done)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct device *dev = ar->dev;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ieee80211_txq *txq;
|
||||
struct ath10k_skb_cb *skb_cb;
|
||||
struct ath10k_txq *artxq;
|
||||
struct sk_buff *msdu;
|
||||
struct ieee80211_hdr *hdr;
|
||||
__le16 fc;
|
||||
bool limit_mgmt_desc = false;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT,
|
||||
"htt tx completion msdu_id %u discard %d no_ack %d success %d\n",
|
||||
tx_done->msdu_id, !!tx_done->discard,
|
||||
!!tx_done->no_ack, !!tx_done->success);
|
||||
"htt tx completion msdu_id %u status %d\n",
|
||||
tx_done->msdu_id, tx_done->status);
|
||||
|
||||
if (tx_done->msdu_id >= htt->max_num_pending_tx) {
|
||||
ath10k_warn(ar, "warning: msdu_id %d too big, ignoring\n",
|
||||
tx_done->msdu_id);
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
|
@ -73,23 +76,23 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
|||
ath10k_warn(ar, "received tx completion for invalid msdu_id: %d\n",
|
||||
tx_done->msdu_id);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
return;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
fc = hdr->frame_control;
|
||||
skb_cb = ATH10K_SKB_CB(msdu);
|
||||
txq = skb_cb->txq;
|
||||
|
||||
if (unlikely(ieee80211_is_mgmt(fc)) &&
|
||||
ar->hw_params.max_probe_resp_desc_thres)
|
||||
limit_mgmt_desc = true;
|
||||
if (txq) {
|
||||
artxq = (void *)txq->drv_priv;
|
||||
artxq->num_fw_queued--;
|
||||
}
|
||||
|
||||
ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
|
||||
__ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
|
||||
ath10k_htt_tx_dec_pending(htt);
|
||||
if (htt->num_pending_tx == 0)
|
||||
wake_up(&htt->empty_tx_wq);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
|
||||
skb_cb = ATH10K_SKB_CB(msdu);
|
||||
dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
|
||||
ath10k_report_offchan_tx(htt->ar, msdu);
|
||||
|
@ -98,22 +101,25 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
|||
memset(&info->status, 0, sizeof(info->status));
|
||||
trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id);
|
||||
|
||||
if (tx_done->discard) {
|
||||
if (tx_done->status == HTT_TX_COMPL_STATE_DISCARD) {
|
||||
ieee80211_free_txskb(htt->ar->hw, msdu);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
if (tx_done->no_ack)
|
||||
if (tx_done->status == HTT_TX_COMPL_STATE_NOACK)
|
||||
info->flags &= ~IEEE80211_TX_STAT_ACK;
|
||||
|
||||
if (tx_done->success && (info->flags & IEEE80211_TX_CTL_NO_ACK))
|
||||
if ((tx_done->status == HTT_TX_COMPL_STATE_ACK) &&
|
||||
(info->flags & IEEE80211_TX_CTL_NO_ACK))
|
||||
info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
|
||||
|
||||
ieee80211_tx_status(htt->ar->hw, msdu);
|
||||
/* we do not own the msdu anymore */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
|
||||
|
@ -126,7 +132,7 @@ struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
|
|||
list_for_each_entry(peer, &ar->peers, list) {
|
||||
if (peer->vdev_id != vdev_id)
|
||||
continue;
|
||||
if (memcmp(peer->addr, addr, ETH_ALEN))
|
||||
if (!ether_addr_equal(peer->addr, addr))
|
||||
continue;
|
||||
|
||||
return peer;
|
||||
|
@ -162,7 +168,7 @@ static int ath10k_wait_for_peer_common(struct ath10k *ar, int vdev_id,
|
|||
|
||||
(mapped == expect_mapped ||
|
||||
test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags));
|
||||
}), 3*HZ);
|
||||
}), 3 * HZ);
|
||||
|
||||
if (time_left == 0)
|
||||
return -ETIMEDOUT;
|
||||
|
@ -186,6 +192,13 @@ void ath10k_peer_map_event(struct ath10k_htt *htt,
|
|||
struct ath10k *ar = htt->ar;
|
||||
struct ath10k_peer *peer;
|
||||
|
||||
if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) {
|
||||
ath10k_warn(ar,
|
||||
"received htt peer map event with idx out of bounds: %hu\n",
|
||||
ev->peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
peer = ath10k_peer_find(ar, ev->vdev_id, ev->addr);
|
||||
if (!peer) {
|
||||
|
@ -202,6 +215,8 @@ void ath10k_peer_map_event(struct ath10k_htt *htt,
|
|||
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer map vdev %d peer %pM id %d\n",
|
||||
ev->vdev_id, ev->addr, ev->peer_id);
|
||||
|
||||
WARN_ON(ar->peer_map[ev->peer_id] && (ar->peer_map[ev->peer_id] != peer));
|
||||
ar->peer_map[ev->peer_id] = peer;
|
||||
set_bit(ev->peer_id, peer->peer_ids);
|
||||
exit:
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
@ -213,6 +228,13 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt,
|
|||
struct ath10k *ar = htt->ar;
|
||||
struct ath10k_peer *peer;
|
||||
|
||||
if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) {
|
||||
ath10k_warn(ar,
|
||||
"received htt peer unmap event with idx out of bounds: %hu\n",
|
||||
ev->peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
peer = ath10k_peer_find_by_id(ar, ev->peer_id);
|
||||
if (!peer) {
|
||||
|
@ -224,6 +246,7 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt,
|
|||
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer unmap vdev %d peer %pM id %d\n",
|
||||
peer->vdev_id, peer->addr, ev->peer_id);
|
||||
|
||||
ar->peer_map[ev->peer_id] = NULL;
|
||||
clear_bit(ev->peer_id, peer->peer_ids);
|
||||
|
||||
if (bitmap_empty(peer->peer_ids, ATH10K_MAX_NUM_PEER_IDS)) {
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
#include "htt.h"
|
||||
|
||||
void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
const struct htt_tx_done *tx_done);
|
||||
int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
const struct htt_tx_done *tx_done);
|
||||
|
||||
struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
|
||||
const u8 *addr);
|
||||
|
|
|
@ -51,6 +51,8 @@ struct wmi_ops {
|
|||
struct wmi_roam_ev_arg *arg);
|
||||
int (*pull_wow_event)(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_wow_ev_arg *arg);
|
||||
int (*pull_echo_ev)(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_echo_ev_arg *arg);
|
||||
enum wmi_txbf_conf (*get_txbf_conf_scheme)(struct ath10k *ar);
|
||||
|
||||
struct sk_buff *(*gen_pdev_suspend)(struct ath10k *ar, u32 suspend_opt);
|
||||
|
@ -123,7 +125,7 @@ struct wmi_ops {
|
|||
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_dbglog_cfg)(struct ath10k *ar, u64 module_enable,
|
||||
u32 log_level);
|
||||
struct sk_buff *(*gen_pktlog_enable)(struct ath10k *ar, u32 filter);
|
||||
struct sk_buff *(*gen_pktlog_disable)(struct ath10k *ar);
|
||||
|
@ -186,6 +188,15 @@ struct wmi_ops {
|
|||
u8 enable,
|
||||
u32 detect_level,
|
||||
u32 detect_margin);
|
||||
struct sk_buff *(*ext_resource_config)(struct ath10k *ar,
|
||||
enum wmi_host_platform_type type,
|
||||
u32 fw_feature_bitmap);
|
||||
int (*get_vdev_subtype)(struct ath10k *ar,
|
||||
enum wmi_vdev_subtype subtype);
|
||||
struct sk_buff *(*gen_pdev_bss_chan_info_req)
|
||||
(struct ath10k *ar,
|
||||
enum wmi_bss_survey_req_type type);
|
||||
struct sk_buff *(*gen_echo)(struct ath10k *ar, u32 value);
|
||||
};
|
||||
|
||||
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
|
||||
|
@ -341,6 +352,16 @@ ath10k_wmi_pull_wow_event(struct ath10k *ar, struct sk_buff *skb,
|
|||
return ar->wmi.ops->pull_wow_event(ar, skb, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_pull_echo_ev(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_echo_ev_arg *arg)
|
||||
{
|
||||
if (!ar->wmi.ops->pull_echo_ev)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar->wmi.ops->pull_echo_ev(ar, skb, arg);
|
||||
}
|
||||
|
||||
static inline enum wmi_txbf_conf
|
||||
ath10k_wmi_get_txbf_conf_scheme(struct ath10k *ar)
|
||||
{
|
||||
|
@ -924,7 +945,7 @@ ath10k_wmi_force_fw_hang(struct ath10k *ar,
|
|||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable, u32 log_level)
|
||||
ath10k_wmi_dbglog_cfg(struct ath10k *ar, u64 module_enable, u32 log_level)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
|
@ -1327,4 +1348,67 @@ ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable,
|
|||
ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_ext_resource_config(struct ath10k *ar,
|
||||
enum wmi_host_platform_type type,
|
||||
u32 fw_feature_bitmap)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!ar->wmi.ops->ext_resource_config)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
skb = ar->wmi.ops->ext_resource_config(ar, type,
|
||||
fw_feature_bitmap);
|
||||
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
return ath10k_wmi_cmd_send(ar, skb,
|
||||
ar->wmi.cmd->ext_resource_cfg_cmdid);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_get_vdev_subtype(struct ath10k *ar, enum wmi_vdev_subtype subtype)
|
||||
{
|
||||
if (!ar->wmi.ops->get_vdev_subtype)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar->wmi.ops->get_vdev_subtype(ar, subtype);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_pdev_bss_chan_info_request(struct ath10k *ar,
|
||||
enum wmi_bss_survey_req_type type)
|
||||
{
|
||||
struct ath10k_wmi *wmi = &ar->wmi;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!wmi->ops->gen_pdev_bss_chan_info_req)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
skb = wmi->ops->gen_pdev_bss_chan_info_req(ar, type);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
return ath10k_wmi_cmd_send(ar, skb,
|
||||
wmi->cmd->pdev_bss_chan_info_request_cmdid);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_echo(struct ath10k *ar, u32 value)
|
||||
{
|
||||
struct ath10k_wmi *wmi = &ar->wmi;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!wmi->ops->gen_echo)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
skb = wmi->ops->gen_echo(ar, value);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
return ath10k_wmi_cmd_send(ar, skb, wmi->cmd->echo_cmdid);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1223,6 +1223,33 @@ ath10k_wmi_tlv_op_pull_wow_ev(struct ath10k *ar, struct sk_buff *skb,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_wmi_tlv_op_pull_echo_ev(struct ath10k *ar,
|
||||
struct sk_buff *skb,
|
||||
struct wmi_echo_ev_arg *arg)
|
||||
{
|
||||
const void **tb;
|
||||
const struct wmi_echo_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TLV_TAG_STRUCT_ECHO_EVENT];
|
||||
if (!ev) {
|
||||
kfree(tb);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
arg->value = ev->value;
|
||||
|
||||
kfree(tb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_tlv_op_gen_pdev_suspend(struct ath10k *ar, u32 opt)
|
||||
{
|
||||
|
@ -2441,7 +2468,7 @@ ath10k_wmi_tlv_op_gen_force_fw_hang(struct ath10k *ar,
|
|||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k *ar, u32 module_enable,
|
||||
ath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k *ar, u64 module_enable,
|
||||
u32 log_level) {
|
||||
struct wmi_tlv_dbglog_cmd *cmd;
|
||||
struct wmi_tlv *tlv;
|
||||
|
@ -3081,6 +3108,34 @@ ath10k_wmi_tlv_op_gen_adaptive_qcs(struct ath10k *ar, bool enable)
|
|||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_tlv_op_gen_echo(struct ath10k *ar, u32 value)
|
||||
{
|
||||
struct wmi_echo_cmd *cmd;
|
||||
struct wmi_tlv *tlv;
|
||||
struct sk_buff *skb;
|
||||
void *ptr;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*tlv) + sizeof(*cmd);
|
||||
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_ECHO_CMD);
|
||||
tlv->len = __cpu_to_le16(sizeof(*cmd));
|
||||
cmd = (void *)tlv->value;
|
||||
cmd->value = cpu_to_le32(value);
|
||||
|
||||
ptr += sizeof(*tlv);
|
||||
ptr += sizeof(*cmd);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv echo value 0x%08x\n", value);
|
||||
return skb;
|
||||
}
|
||||
|
||||
/****************/
|
||||
/* TLV mappings */
|
||||
/****************/
|
||||
|
@ -3409,6 +3464,7 @@ static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
|
|||
.meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
.set_tsf = WMI_VDEV_PARAM_UNSUPPORTED,
|
||||
};
|
||||
|
||||
static const struct wmi_ops wmi_tlv_ops = {
|
||||
|
@ -3428,6 +3484,7 @@ static const struct wmi_ops wmi_tlv_ops = {
|
|||
.pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,
|
||||
.pull_roam_ev = ath10k_wmi_tlv_op_pull_roam_ev,
|
||||
.pull_wow_event = ath10k_wmi_tlv_op_pull_wow_ev,
|
||||
.pull_echo_ev = ath10k_wmi_tlv_op_pull_echo_ev,
|
||||
.get_txbf_conf_scheme = ath10k_wmi_tlv_txbf_conf_scheme,
|
||||
|
||||
.gen_pdev_suspend = ath10k_wmi_tlv_op_gen_pdev_suspend,
|
||||
|
@ -3483,6 +3540,26 @@ static const struct wmi_ops wmi_tlv_ops = {
|
|||
.gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update,
|
||||
.gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs,
|
||||
.fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
|
||||
.get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
|
||||
.gen_echo = ath10k_wmi_tlv_op_gen_echo,
|
||||
};
|
||||
|
||||
static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
|
||||
.auth = WMI_TLV_PEER_AUTH,
|
||||
.qos = WMI_TLV_PEER_QOS,
|
||||
.need_ptk_4_way = WMI_TLV_PEER_NEED_PTK_4_WAY,
|
||||
.need_gtk_2_way = WMI_TLV_PEER_NEED_GTK_2_WAY,
|
||||
.apsd = WMI_TLV_PEER_APSD,
|
||||
.ht = WMI_TLV_PEER_HT,
|
||||
.bw40 = WMI_TLV_PEER_40MHZ,
|
||||
.stbc = WMI_TLV_PEER_STBC,
|
||||
.ldbc = WMI_TLV_PEER_LDPC,
|
||||
.dyn_mimops = WMI_TLV_PEER_DYN_MIMOPS,
|
||||
.static_mimops = WMI_TLV_PEER_STATIC_MIMOPS,
|
||||
.spatial_mux = WMI_TLV_PEER_SPATIAL_MUX,
|
||||
.vht = WMI_TLV_PEER_VHT,
|
||||
.bw80 = WMI_TLV_PEER_80MHZ,
|
||||
.pmf = WMI_TLV_PEER_PMF,
|
||||
};
|
||||
|
||||
/************/
|
||||
|
@ -3495,4 +3572,5 @@ void ath10k_wmi_tlv_attach(struct ath10k *ar)
|
|||
ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
|
||||
ar->wmi.ops = &wmi_tlv_ops;
|
||||
ar->wmi.peer_flags = &wmi_tlv_peer_flags_map;
|
||||
}
|
||||
|
|
|
@ -527,6 +527,24 @@ enum wmi_tlv_vdev_param {
|
|||
WMI_TLV_VDEV_PARAM_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE,
|
||||
};
|
||||
|
||||
enum wmi_tlv_peer_flags {
|
||||
WMI_TLV_PEER_AUTH = 0x00000001,
|
||||
WMI_TLV_PEER_QOS = 0x00000002,
|
||||
WMI_TLV_PEER_NEED_PTK_4_WAY = 0x00000004,
|
||||
WMI_TLV_PEER_NEED_GTK_2_WAY = 0x00000010,
|
||||
WMI_TLV_PEER_APSD = 0x00000800,
|
||||
WMI_TLV_PEER_HT = 0x00001000,
|
||||
WMI_TLV_PEER_40MHZ = 0x00002000,
|
||||
WMI_TLV_PEER_STBC = 0x00008000,
|
||||
WMI_TLV_PEER_LDPC = 0x00010000,
|
||||
WMI_TLV_PEER_DYN_MIMOPS = 0x00020000,
|
||||
WMI_TLV_PEER_STATIC_MIMOPS = 0x00040000,
|
||||
WMI_TLV_PEER_SPATIAL_MUX = 0x00200000,
|
||||
WMI_TLV_PEER_VHT = 0x02000000,
|
||||
WMI_TLV_PEER_80MHZ = 0x04000000,
|
||||
WMI_TLV_PEER_PMF = 0x08000000,
|
||||
};
|
||||
|
||||
enum wmi_tlv_tag {
|
||||
WMI_TLV_TAG_LAST_RESERVED = 15,
|
||||
|
||||
|
@ -950,8 +968,8 @@ enum wmi_tlv_service {
|
|||
|
||||
#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \
|
||||
((svc_id) < (len) && \
|
||||
__le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
|
||||
BIT((svc_id)%(sizeof(u32))))
|
||||
__le32_to_cpu((wmi_svc_bmap)[(svc_id) / (sizeof(u32))]) & \
|
||||
BIT((svc_id) % (sizeof(u32))))
|
||||
|
||||
#define SVCMAP(x, y, len) \
|
||||
do { \
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -55,7 +55,7 @@
|
|||
* type.
|
||||
*
|
||||
* 6. Comment each parameter part of the WMI command/event structure by
|
||||
* using the 2 stars at the begining of C comment instead of one star to
|
||||
* using the 2 stars at the beginning of C comment instead of one star to
|
||||
* enable HTML document generation using Doxygen.
|
||||
*
|
||||
*/
|
||||
|
@ -175,6 +175,15 @@ enum wmi_service {
|
|||
WMI_SERVICE_AUX_SPECTRAL_INTF,
|
||||
WMI_SERVICE_AUX_CHAN_LOAD_INTF,
|
||||
WMI_SERVICE_BSS_CHANNEL_INFO_64,
|
||||
WMI_SERVICE_EXT_RES_CFG_SUPPORT,
|
||||
WMI_SERVICE_MESH_11S,
|
||||
WMI_SERVICE_MESH_NON_11S,
|
||||
WMI_SERVICE_PEER_STATS,
|
||||
WMI_SERVICE_RESTRT_CHNL_SUPPORT,
|
||||
WMI_SERVICE_PERIODIC_CHAN_STAT_SUPPORT,
|
||||
WMI_SERVICE_TX_MODE_PUSH_ONLY,
|
||||
WMI_SERVICE_TX_MODE_PUSH_PULL,
|
||||
WMI_SERVICE_TX_MODE_DYNAMIC,
|
||||
|
||||
/* keep last */
|
||||
WMI_SERVICE_MAX,
|
||||
|
@ -206,6 +215,12 @@ enum wmi_10x_service {
|
|||
WMI_10X_SERVICE_SMART_ANTENNA_HW_SUPPORT,
|
||||
WMI_10X_SERVICE_ATF,
|
||||
WMI_10X_SERVICE_COEX_GPIO,
|
||||
WMI_10X_SERVICE_AUX_SPECTRAL_INTF,
|
||||
WMI_10X_SERVICE_AUX_CHAN_LOAD_INTF,
|
||||
WMI_10X_SERVICE_BSS_CHANNEL_INFO_64,
|
||||
WMI_10X_SERVICE_MESH,
|
||||
WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT,
|
||||
WMI_10X_SERVICE_PEER_STATS,
|
||||
};
|
||||
|
||||
enum wmi_main_service {
|
||||
|
@ -286,6 +301,15 @@ enum wmi_10_4_service {
|
|||
WMI_10_4_SERVICE_AUX_SPECTRAL_INTF,
|
||||
WMI_10_4_SERVICE_AUX_CHAN_LOAD_INTF,
|
||||
WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64,
|
||||
WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT,
|
||||
WMI_10_4_SERVICE_MESH_NON_11S,
|
||||
WMI_10_4_SERVICE_RESTRT_CHNL_SUPPORT,
|
||||
WMI_10_4_SERVICE_PEER_STATS,
|
||||
WMI_10_4_SERVICE_MESH_11S,
|
||||
WMI_10_4_SERVICE_PERIODIC_CHAN_STAT_SUPPORT,
|
||||
WMI_10_4_SERVICE_TX_MODE_PUSH_ONLY,
|
||||
WMI_10_4_SERVICE_TX_MODE_PUSH_PULL,
|
||||
WMI_10_4_SERVICE_TX_MODE_DYNAMIC,
|
||||
};
|
||||
|
||||
static inline char *wmi_service_name(int service_id)
|
||||
|
@ -375,6 +399,15 @@ static inline char *wmi_service_name(int service_id)
|
|||
SVCSTR(WMI_SERVICE_AUX_SPECTRAL_INTF);
|
||||
SVCSTR(WMI_SERVICE_AUX_CHAN_LOAD_INTF);
|
||||
SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64);
|
||||
SVCSTR(WMI_SERVICE_EXT_RES_CFG_SUPPORT);
|
||||
SVCSTR(WMI_SERVICE_MESH_11S);
|
||||
SVCSTR(WMI_SERVICE_MESH_NON_11S);
|
||||
SVCSTR(WMI_SERVICE_PEER_STATS);
|
||||
SVCSTR(WMI_SERVICE_RESTRT_CHNL_SUPPORT);
|
||||
SVCSTR(WMI_SERVICE_PERIODIC_CHAN_STAT_SUPPORT);
|
||||
SVCSTR(WMI_SERVICE_TX_MODE_PUSH_ONLY);
|
||||
SVCSTR(WMI_SERVICE_TX_MODE_PUSH_PULL);
|
||||
SVCSTR(WMI_SERVICE_TX_MODE_DYNAMIC);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -384,8 +417,8 @@ static inline char *wmi_service_name(int service_id)
|
|||
|
||||
#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \
|
||||
((svc_id) < (len) && \
|
||||
__le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
|
||||
BIT((svc_id)%(sizeof(u32))))
|
||||
__le32_to_cpu((wmi_svc_bmap)[(svc_id) / (sizeof(u32))]) & \
|
||||
BIT((svc_id) % (sizeof(u32))))
|
||||
|
||||
#define SVCMAP(x, y, len) \
|
||||
do { \
|
||||
|
@ -442,6 +475,18 @@ static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out,
|
|||
WMI_SERVICE_ATF, len);
|
||||
SVCMAP(WMI_10X_SERVICE_COEX_GPIO,
|
||||
WMI_SERVICE_COEX_GPIO, len);
|
||||
SVCMAP(WMI_10X_SERVICE_AUX_SPECTRAL_INTF,
|
||||
WMI_SERVICE_AUX_SPECTRAL_INTF, len);
|
||||
SVCMAP(WMI_10X_SERVICE_AUX_CHAN_LOAD_INTF,
|
||||
WMI_SERVICE_AUX_CHAN_LOAD_INTF, len);
|
||||
SVCMAP(WMI_10X_SERVICE_BSS_CHANNEL_INFO_64,
|
||||
WMI_SERVICE_BSS_CHANNEL_INFO_64, len);
|
||||
SVCMAP(WMI_10X_SERVICE_MESH,
|
||||
WMI_SERVICE_MESH_11S, len);
|
||||
SVCMAP(WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT,
|
||||
WMI_SERVICE_EXT_RES_CFG_SUPPORT, len);
|
||||
SVCMAP(WMI_10X_SERVICE_PEER_STATS,
|
||||
WMI_SERVICE_PEER_STATS, len);
|
||||
}
|
||||
|
||||
static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out,
|
||||
|
@ -600,6 +645,24 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
|
|||
WMI_SERVICE_AUX_CHAN_LOAD_INTF, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64,
|
||||
WMI_SERVICE_BSS_CHANNEL_INFO_64, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT,
|
||||
WMI_SERVICE_EXT_RES_CFG_SUPPORT, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_MESH_NON_11S,
|
||||
WMI_SERVICE_MESH_NON_11S, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_RESTRT_CHNL_SUPPORT,
|
||||
WMI_SERVICE_RESTRT_CHNL_SUPPORT, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_PEER_STATS,
|
||||
WMI_SERVICE_PEER_STATS, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_MESH_11S,
|
||||
WMI_SERVICE_MESH_11S, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_PERIODIC_CHAN_STAT_SUPPORT,
|
||||
WMI_SERVICE_PERIODIC_CHAN_STAT_SUPPORT, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_TX_MODE_PUSH_ONLY,
|
||||
WMI_SERVICE_TX_MODE_PUSH_ONLY, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_TX_MODE_PUSH_PULL,
|
||||
WMI_SERVICE_TX_MODE_PUSH_PULL, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_TX_MODE_DYNAMIC,
|
||||
WMI_SERVICE_TX_MODE_DYNAMIC, len);
|
||||
}
|
||||
|
||||
#undef SVCMAP
|
||||
|
@ -773,6 +836,7 @@ struct wmi_cmd_map {
|
|||
u32 set_cca_params_cmdid;
|
||||
u32 pdev_bss_chan_info_request_cmdid;
|
||||
u32 pdev_enable_adaptive_cca_cmdid;
|
||||
u32 ext_resource_cfg_cmdid;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1265,7 +1329,7 @@ enum wmi_10x_event_id {
|
|||
WMI_10X_PDEV_TPC_CONFIG_EVENTID,
|
||||
|
||||
WMI_10X_GPIO_INPUT_EVENTID,
|
||||
WMI_10X_PDEV_UTF_EVENTID = WMI_10X_END_EVENTID-1,
|
||||
WMI_10X_PDEV_UTF_EVENTID = WMI_10X_END_EVENTID - 1,
|
||||
};
|
||||
|
||||
enum wmi_10_2_cmd_id {
|
||||
|
@ -1385,6 +1449,7 @@ enum wmi_10_2_cmd_id {
|
|||
WMI_10_2_MU_CAL_START_CMDID,
|
||||
WMI_10_2_SET_LTEU_CONFIG_CMDID,
|
||||
WMI_10_2_SET_CCA_PARAMS,
|
||||
WMI_10_2_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
|
||||
WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1,
|
||||
};
|
||||
|
||||
|
@ -1428,6 +1493,8 @@ enum wmi_10_2_event_id {
|
|||
WMI_10_2_WDS_PEER_EVENTID,
|
||||
WMI_10_2_PEER_STA_PS_STATECHG_EVENTID,
|
||||
WMI_10_2_PDEV_TEMPERATURE_EVENTID,
|
||||
WMI_10_2_MU_REPORT_EVENTID,
|
||||
WMI_10_2_PDEV_BSS_CHAN_INFO_EVENTID,
|
||||
WMI_10_2_PDEV_UTF_EVENTID = WMI_10_2_END_EVENTID - 1,
|
||||
};
|
||||
|
||||
|
@ -1576,6 +1643,9 @@ enum wmi_10_4_cmd_id {
|
|||
WMI_10_4_MU_CAL_START_CMDID,
|
||||
WMI_10_4_SET_CCA_PARAMS_CMDID,
|
||||
WMI_10_4_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
|
||||
WMI_10_4_EXT_RESOURCE_CFG_CMDID,
|
||||
WMI_10_4_VDEV_SET_IE_CMDID,
|
||||
WMI_10_4_SET_LTEU_CONFIG_CMDID,
|
||||
WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1,
|
||||
};
|
||||
|
||||
|
@ -1638,6 +1708,7 @@ enum wmi_10_4_event_id {
|
|||
WMI_10_4_PDEV_TEMPERATURE_EVENTID,
|
||||
WMI_10_4_PDEV_NFCAL_POWER_ALL_CHANNELS_EVENTID,
|
||||
WMI_10_4_PDEV_BSS_CHAN_INFO_EVENTID,
|
||||
WMI_10_4_MU_REPORT_EVENTID,
|
||||
WMI_10_4_PDEV_UTF_EVENTID = WMI_10_4_END_EVENTID - 1,
|
||||
};
|
||||
|
||||
|
@ -1732,6 +1803,7 @@ struct wmi_channel {
|
|||
__le32 reginfo1;
|
||||
struct {
|
||||
u8 antenna_max;
|
||||
u8 max_tx_power;
|
||||
} __packed;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
@ -1771,7 +1843,6 @@ enum wmi_channel_change_cause {
|
|||
#define WMI_CHANNEL_CHANGE_CAUSE_CSA (1 << 13)
|
||||
|
||||
#define WMI_MAX_SPATIAL_STREAM 3 /* default max ss */
|
||||
#define WMI_10_4_MAX_SPATIAL_STREAM 4
|
||||
|
||||
/* HT Capabilities*/
|
||||
#define WMI_HT_CAP_ENABLED 0x0001 /* HT Enabled/ disabled */
|
||||
|
@ -1995,8 +2066,8 @@ struct wmi_10x_service_ready_event {
|
|||
struct wlan_host_mem_req mem_reqs[0];
|
||||
} __packed;
|
||||
|
||||
#define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ)
|
||||
#define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ)
|
||||
#define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ)
|
||||
#define WMI_UNIFIED_READY_TIMEOUT_HZ (5 * HZ)
|
||||
|
||||
struct wmi_ready_event {
|
||||
__le32 sw_version;
|
||||
|
@ -2016,7 +2087,7 @@ struct wmi_resource_config {
|
|||
* In offload mode target supports features like WOW, chatter and
|
||||
* other protocol offloads. In order to support them some
|
||||
* functionalities like reorder buffering, PN checking need to be
|
||||
* done in target. This determines maximum number of peers suported
|
||||
* done in target. This determines maximum number of peers supported
|
||||
* by target in offload mode
|
||||
*/
|
||||
__le32 num_offload_peers;
|
||||
|
@ -2197,7 +2268,7 @@ struct wmi_resource_config {
|
|||
* Max. number of Tx fragments per MSDU
|
||||
* This parameter controls the max number of Tx fragments per MSDU.
|
||||
* This is sent by the target as part of the WMI_SERVICE_READY event
|
||||
* and is overriden by the OS shim as required.
|
||||
* and is overridden by the OS shim as required.
|
||||
*/
|
||||
__le32 max_frag_entries;
|
||||
} __packed;
|
||||
|
@ -2379,7 +2450,7 @@ struct wmi_resource_config_10x {
|
|||
* Max. number of Tx fragments per MSDU
|
||||
* This parameter controls the max number of Tx fragments per MSDU.
|
||||
* This is sent by the target as part of the WMI_SERVICE_READY event
|
||||
* and is overriden by the OS shim as required.
|
||||
* and is overridden by the OS shim as required.
|
||||
*/
|
||||
__le32 max_frag_entries;
|
||||
} __packed;
|
||||
|
@ -2388,6 +2459,8 @@ enum wmi_10_2_feature_mask {
|
|||
WMI_10_2_RX_BATCH_MODE = BIT(0),
|
||||
WMI_10_2_ATF_CONFIG = BIT(1),
|
||||
WMI_10_2_COEX_GPIO = BIT(3),
|
||||
WMI_10_2_BSS_CHAN_INFO = BIT(6),
|
||||
WMI_10_2_PEER_STATS = BIT(7),
|
||||
};
|
||||
|
||||
struct wmi_resource_config_10_2 {
|
||||
|
@ -2613,13 +2686,43 @@ struct wmi_resource_config_10_4 {
|
|||
*/
|
||||
__le32 iphdr_pad_config;
|
||||
|
||||
/* qwrap configuration
|
||||
/* qwrap configuration (bits 15-0)
|
||||
* 1 - This is qwrap configuration
|
||||
* 0 - This is not qwrap
|
||||
*
|
||||
* Bits 31-16 is alloc_frag_desc_for_data_pkt (1 enables, 0 disables)
|
||||
* In order to get ack-RSSI reporting and to specify the tx-rate for
|
||||
* individual frames, this option must be enabled. This uses an extra
|
||||
* 4 bytes per tx-msdu descriptor, so don't enable it unless you need it.
|
||||
*/
|
||||
__le32 qwrap_config;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* enum wmi_10_4_feature_mask - WMI 10.4 feature enable/disable flags
|
||||
* @WMI_10_4_LTEU_SUPPORT: LTEU config
|
||||
* @WMI_10_4_COEX_GPIO_SUPPORT: COEX GPIO config
|
||||
* @WMI_10_4_AUX_RADIO_SPECTRAL_INTF: AUX Radio Enhancement for spectral scan
|
||||
* @WMI_10_4_AUX_RADIO_CHAN_LOAD_INTF: AUX Radio Enhancement for chan load scan
|
||||
* @WMI_10_4_BSS_CHANNEL_INFO_64: BSS channel info stats
|
||||
* @WMI_10_4_PEER_STATS: Per station stats
|
||||
*/
|
||||
enum wmi_10_4_feature_mask {
|
||||
WMI_10_4_LTEU_SUPPORT = BIT(0),
|
||||
WMI_10_4_COEX_GPIO_SUPPORT = BIT(1),
|
||||
WMI_10_4_AUX_RADIO_SPECTRAL_INTF = BIT(2),
|
||||
WMI_10_4_AUX_RADIO_CHAN_LOAD_INTF = BIT(3),
|
||||
WMI_10_4_BSS_CHANNEL_INFO_64 = BIT(4),
|
||||
WMI_10_4_PEER_STATS = BIT(5),
|
||||
};
|
||||
|
||||
struct wmi_ext_resource_config_10_4_cmd {
|
||||
/* contains enum wmi_host_platform_type */
|
||||
__le32 host_platform_config;
|
||||
/* see enum wmi_10_4_feature_mask */
|
||||
__le32 fw_feature_bitmap;
|
||||
};
|
||||
|
||||
/* strucutre describing host memory chunk. */
|
||||
struct host_memory_chunk {
|
||||
/* id of the request that is passed up in service ready */
|
||||
|
@ -2641,7 +2744,7 @@ struct wmi_init_cmd {
|
|||
struct wmi_host_mem_chunks mem_chunks;
|
||||
} __packed;
|
||||
|
||||
/* _10x stucture is from 10.X FW API */
|
||||
/* _10x structure is from 10.X FW API */
|
||||
struct wmi_init_cmd_10x {
|
||||
struct wmi_resource_config_10x resource_config;
|
||||
struct wmi_host_mem_chunks mem_chunks;
|
||||
|
@ -2990,11 +3093,17 @@ struct wmi_10_4_mgmt_rx_event {
|
|||
u8 buf[0];
|
||||
} __packed;
|
||||
|
||||
struct wmi_mgmt_rx_ext_info {
|
||||
__le64 rx_mac_timestamp;
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define WMI_RX_STATUS_OK 0x00
|
||||
#define WMI_RX_STATUS_ERR_CRC 0x01
|
||||
#define WMI_RX_STATUS_ERR_DECRYPT 0x08
|
||||
#define WMI_RX_STATUS_ERR_MIC 0x10
|
||||
#define WMI_RX_STATUS_ERR_KEY_CACHE_MISS 0x20
|
||||
/* Extension data at the end of mgmt frame */
|
||||
#define WMI_RX_STATUS_EXT_INFO 0x40
|
||||
|
||||
#define PHY_ERROR_GEN_SPECTRAL_SCAN 0x26
|
||||
#define PHY_ERROR_GEN_FALSE_RADAR_EXT 0x24
|
||||
|
@ -3343,6 +3452,7 @@ struct wmi_pdev_param_map {
|
|||
u32 wapi_mbssid_offset;
|
||||
u32 arp_srcaddr;
|
||||
u32 arp_dstaddr;
|
||||
u32 enable_btcoex;
|
||||
};
|
||||
|
||||
#define WMI_PDEV_PARAM_UNSUPPORTED 0
|
||||
|
@ -3650,6 +3760,15 @@ enum wmi_10_4_pdev_param {
|
|||
WMI_10_4_PDEV_PARAM_WAPI_MBSSID_OFFSET,
|
||||
WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
|
||||
WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
|
||||
WMI_10_4_PDEV_PARAM_TXPOWER_DECR_DB,
|
||||
WMI_10_4_PDEV_PARAM_RX_BATCHMODE,
|
||||
WMI_10_4_PDEV_PARAM_PACKET_AGGR_DELAY,
|
||||
WMI_10_4_PDEV_PARAM_ATF_OBSS_NOISE_SCH,
|
||||
WMI_10_4_PDEV_PARAM_ATF_OBSS_NOISE_SCALING_FACTOR,
|
||||
WMI_10_4_PDEV_PARAM_CUST_TXPOWER_SCALE,
|
||||
WMI_10_4_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
|
||||
WMI_10_4_PDEV_PARAM_ATF_SSID_GROUP_POLICY,
|
||||
WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
|
||||
};
|
||||
|
||||
struct wmi_pdev_set_param_cmd {
|
||||
|
@ -3848,7 +3967,7 @@ struct wmi_pdev_stats_tx {
|
|||
/* illegal rate phy errors */
|
||||
__le32 illgl_rate_phy_err;
|
||||
|
||||
/* wal pdev continous xretry */
|
||||
/* wal pdev continuous xretry */
|
||||
__le32 pdev_cont_xretry;
|
||||
|
||||
/* wal pdev continous xretry */
|
||||
|
@ -4019,6 +4138,13 @@ enum wmi_stats_id {
|
|||
WMI_STAT_VDEV_RATE = BIT(5),
|
||||
};
|
||||
|
||||
enum wmi_10_4_stats_id {
|
||||
WMI_10_4_STAT_PEER = BIT(0),
|
||||
WMI_10_4_STAT_AP = BIT(1),
|
||||
WMI_10_4_STAT_INST = BIT(2),
|
||||
WMI_10_4_STAT_PEER_EXTD = BIT(3),
|
||||
};
|
||||
|
||||
struct wlan_inst_rssi_args {
|
||||
__le16 cfg_retry_count;
|
||||
__le16 retry_count;
|
||||
|
@ -4096,10 +4222,10 @@ struct wmi_10_2_stats_event {
|
|||
*/
|
||||
struct wmi_pdev_stats_base {
|
||||
__le32 chan_nf;
|
||||
__le32 tx_frame_count;
|
||||
__le32 rx_frame_count;
|
||||
__le32 rx_clear_count;
|
||||
__le32 cycle_count;
|
||||
__le32 tx_frame_count; /* Cycles spent transmitting frames */
|
||||
__le32 rx_frame_count; /* Cycles spent receiving frames */
|
||||
__le32 rx_clear_count; /* Total channel busy time, evidently */
|
||||
__le32 cycle_count; /* Total on-channel time */
|
||||
__le32 phy_err_count;
|
||||
__le32 chan_tx_pwr;
|
||||
} __packed;
|
||||
|
@ -4192,7 +4318,13 @@ struct wmi_10_2_peer_stats {
|
|||
|
||||
struct wmi_10_2_4_peer_stats {
|
||||
struct wmi_10_2_peer_stats common;
|
||||
__le32 unknown_value; /* FIXME: what is this word? */
|
||||
__le32 peer_rssi_changed;
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_2_4_ext_peer_stats {
|
||||
struct wmi_10_2_peer_stats common;
|
||||
__le32 peer_rssi_changed;
|
||||
__le32 rx_duration;
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_peer_stats {
|
||||
|
@ -4212,6 +4344,27 @@ struct wmi_10_4_peer_stats {
|
|||
__le32 peer_rssi_changed;
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_peer_extd_stats {
|
||||
struct wmi_mac_addr peer_macaddr;
|
||||
__le32 inactive_time;
|
||||
__le32 peer_chain_rssi;
|
||||
__le32 rx_duration;
|
||||
__le32 reserved[10];
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_bss_bcn_stats {
|
||||
__le32 vdev_id;
|
||||
__le32 bss_bcns_dropped;
|
||||
__le32 bss_bcn_delivered;
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_bss_bcn_filter_stats {
|
||||
__le32 bcns_dropped;
|
||||
__le32 bcns_delivered;
|
||||
__le32 active_filters;
|
||||
struct wmi_10_4_bss_bcn_stats bss_stats;
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_2_pdev_ext_stats {
|
||||
__le32 rx_rssi_comb;
|
||||
__le32 rx_rssi[4];
|
||||
|
@ -4235,10 +4388,40 @@ enum wmi_vdev_type {
|
|||
};
|
||||
|
||||
enum wmi_vdev_subtype {
|
||||
WMI_VDEV_SUBTYPE_NONE = 0,
|
||||
WMI_VDEV_SUBTYPE_P2P_DEVICE = 1,
|
||||
WMI_VDEV_SUBTYPE_P2P_CLIENT = 2,
|
||||
WMI_VDEV_SUBTYPE_P2P_GO = 3,
|
||||
WMI_VDEV_SUBTYPE_NONE,
|
||||
WMI_VDEV_SUBTYPE_P2P_DEVICE,
|
||||
WMI_VDEV_SUBTYPE_P2P_CLIENT,
|
||||
WMI_VDEV_SUBTYPE_P2P_GO,
|
||||
WMI_VDEV_SUBTYPE_PROXY_STA,
|
||||
WMI_VDEV_SUBTYPE_MESH_11S,
|
||||
WMI_VDEV_SUBTYPE_MESH_NON_11S,
|
||||
};
|
||||
|
||||
enum wmi_vdev_subtype_legacy {
|
||||
WMI_VDEV_SUBTYPE_LEGACY_NONE = 0,
|
||||
WMI_VDEV_SUBTYPE_LEGACY_P2P_DEV = 1,
|
||||
WMI_VDEV_SUBTYPE_LEGACY_P2P_CLI = 2,
|
||||
WMI_VDEV_SUBTYPE_LEGACY_P2P_GO = 3,
|
||||
WMI_VDEV_SUBTYPE_LEGACY_PROXY_STA = 4,
|
||||
};
|
||||
|
||||
enum wmi_vdev_subtype_10_2_4 {
|
||||
WMI_VDEV_SUBTYPE_10_2_4_NONE = 0,
|
||||
WMI_VDEV_SUBTYPE_10_2_4_P2P_DEV = 1,
|
||||
WMI_VDEV_SUBTYPE_10_2_4_P2P_CLI = 2,
|
||||
WMI_VDEV_SUBTYPE_10_2_4_P2P_GO = 3,
|
||||
WMI_VDEV_SUBTYPE_10_2_4_PROXY_STA = 4,
|
||||
WMI_VDEV_SUBTYPE_10_2_4_MESH_11S = 5,
|
||||
};
|
||||
|
||||
enum wmi_vdev_subtype_10_4 {
|
||||
WMI_VDEV_SUBTYPE_10_4_NONE = 0,
|
||||
WMI_VDEV_SUBTYPE_10_4_P2P_DEV = 1,
|
||||
WMI_VDEV_SUBTYPE_10_4_P2P_CLI = 2,
|
||||
WMI_VDEV_SUBTYPE_10_4_P2P_GO = 3,
|
||||
WMI_VDEV_SUBTYPE_10_4_PROXY_STA = 4,
|
||||
WMI_VDEV_SUBTYPE_10_4_MESH_NON_11S = 5,
|
||||
WMI_VDEV_SUBTYPE_10_4_MESH_11S = 6,
|
||||
};
|
||||
|
||||
/* values for vdev_subtype */
|
||||
|
@ -4247,14 +4430,14 @@ enum wmi_vdev_subtype {
|
|||
/*
|
||||
* Indicates that AP VDEV uses hidden ssid. only valid for
|
||||
* AP/GO */
|
||||
#define WMI_VDEV_START_HIDDEN_SSID (1<<0)
|
||||
#define WMI_VDEV_START_HIDDEN_SSID (1 << 0)
|
||||
/*
|
||||
* Indicates if robust management frame/management frame
|
||||
* protection is enabled. For GO/AP vdevs, it indicates that
|
||||
* it may support station/client associations with RMF enabled.
|
||||
* For STA/client vdevs, it indicates that sta will
|
||||
* associate with AP with RMF enabled. */
|
||||
#define WMI_VDEV_START_PMF_ENABLED (1<<1)
|
||||
#define WMI_VDEV_START_PMF_ENABLED (1 << 1)
|
||||
|
||||
struct wmi_p2p_noa_descriptor {
|
||||
__le32 type_count; /* 255: continuous schedule, 0: reserved */
|
||||
|
@ -4278,9 +4461,9 @@ struct wmi_vdev_start_request_cmd {
|
|||
__le32 flags;
|
||||
/* ssid field. Only valid for AP/GO/IBSS/BTAmp VDEV type. */
|
||||
struct wmi_ssid ssid;
|
||||
/* beacon/probe reponse xmit rate. Applicable for SoftAP. */
|
||||
/* beacon/probe response xmit rate. Applicable for SoftAP. */
|
||||
__le32 bcn_tx_rate;
|
||||
/* beacon/probe reponse xmit power. Applicable for SoftAP. */
|
||||
/* beacon/probe response xmit power. Applicable for SoftAP. */
|
||||
__le32 bcn_tx_power;
|
||||
/* number of p2p NOA descriptor(s) from scan entry */
|
||||
__le32 num_noa_descriptors;
|
||||
|
@ -4493,6 +4676,7 @@ struct wmi_vdev_param_map {
|
|||
u32 meru_vc;
|
||||
u32 rx_decap_type;
|
||||
u32 bw_nss_ratemask;
|
||||
u32 set_tsf;
|
||||
};
|
||||
|
||||
#define WMI_VDEV_PARAM_UNSUPPORTED 0
|
||||
|
@ -4507,7 +4691,7 @@ enum wmi_vdev_param {
|
|||
WMI_VDEV_PARAM_BEACON_INTERVAL,
|
||||
/* Listen interval in TUs */
|
||||
WMI_VDEV_PARAM_LISTEN_INTERVAL,
|
||||
/* muticast rate in Mbps */
|
||||
/* multicast rate in Mbps */
|
||||
WMI_VDEV_PARAM_MULTICAST_RATE,
|
||||
/* management frame rate in Mbps */
|
||||
WMI_VDEV_PARAM_MGMT_TX_RATE,
|
||||
|
@ -4638,7 +4822,7 @@ enum wmi_10x_vdev_param {
|
|||
WMI_10X_VDEV_PARAM_BEACON_INTERVAL,
|
||||
/* Listen interval in TUs */
|
||||
WMI_10X_VDEV_PARAM_LISTEN_INTERVAL,
|
||||
/* muticast rate in Mbps */
|
||||
/* multicast rate in Mbps */
|
||||
WMI_10X_VDEV_PARAM_MULTICAST_RATE,
|
||||
/* management frame rate in Mbps */
|
||||
WMI_10X_VDEV_PARAM_MGMT_TX_RATE,
|
||||
|
@ -4749,6 +4933,7 @@ enum wmi_10x_vdev_param {
|
|||
WMI_10X_VDEV_PARAM_RTS_FIXED_RATE,
|
||||
WMI_10X_VDEV_PARAM_VHT_SGIMASK,
|
||||
WMI_10X_VDEV_PARAM_VHT80_RATEMASK,
|
||||
WMI_10X_VDEV_PARAM_TSF_INCREMENT,
|
||||
};
|
||||
|
||||
enum wmi_10_4_vdev_param {
|
||||
|
@ -4818,6 +5003,12 @@ enum wmi_10_4_vdev_param {
|
|||
WMI_10_4_VDEV_PARAM_MERU_VC,
|
||||
WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE,
|
||||
WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK,
|
||||
WMI_10_4_VDEV_PARAM_SENSOR_AP,
|
||||
WMI_10_4_VDEV_PARAM_BEACON_RATE,
|
||||
WMI_10_4_VDEV_PARAM_DTIM_ENABLE_CTS,
|
||||
WMI_10_4_VDEV_PARAM_STA_KICKOUT,
|
||||
WMI_10_4_VDEV_PARAM_CAPABILITIES,
|
||||
WMI_10_4_VDEV_PARAM_TSF_INCREMENT,
|
||||
};
|
||||
|
||||
#define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0)
|
||||
|
@ -4876,7 +5067,7 @@ struct wmi_vdev_simple_event {
|
|||
} __packed;
|
||||
|
||||
/* VDEV start response status codes */
|
||||
/* VDEV succesfully started */
|
||||
/* VDEV successfully started */
|
||||
#define WMI_INIFIED_VDEV_START_RESPONSE_STATUS_SUCCESS 0x0
|
||||
|
||||
/* requested VDEV not found */
|
||||
|
@ -5192,7 +5383,7 @@ enum wmi_sta_ps_param_pspoll_count {
|
|||
#define WMI_UAPSD_AC_TYPE_TRIG 1
|
||||
|
||||
#define WMI_UAPSD_AC_BIT_MASK(ac, type) \
|
||||
((type == WMI_UAPSD_AC_TYPE_DELI) ? (1<<(ac<<1)) : (1<<((ac<<1)+1)))
|
||||
(type == WMI_UAPSD_AC_TYPE_DELI ? 1 << (ac << 1) : 1 << ((ac << 1) + 1))
|
||||
|
||||
enum wmi_sta_ps_param_uapsd {
|
||||
WMI_STA_PS_UAPSD_AC0_DELIVERY_EN = (1 << 0),
|
||||
|
@ -5405,6 +5596,16 @@ struct wmi_host_swba_event {
|
|||
struct wmi_bcn_info bcn_info[0];
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_2_4_bcn_info {
|
||||
struct wmi_tim_info tim_info;
|
||||
/* The 10.2.4 FW doesn't have p2p NOA info */
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_2_4_host_swba_event {
|
||||
__le32 vdev_map;
|
||||
struct wmi_10_2_4_bcn_info bcn_info[0];
|
||||
} __packed;
|
||||
|
||||
/* 16 words = 512 client + 1 word = for guard */
|
||||
#define WMI_10_4_TIM_BITMAP_ARRAY_SIZE 17
|
||||
|
||||
|
@ -5597,7 +5798,7 @@ struct wmi_rate_set {
|
|||
* the rates are filled from least significant byte to most
|
||||
* significant byte.
|
||||
*/
|
||||
__le32 rates[(MAX_SUPPORTED_RATES/4)+1];
|
||||
__le32 rates[(MAX_SUPPORTED_RATES / 4) + 1];
|
||||
} __packed;
|
||||
|
||||
struct wmi_rate_set_arg {
|
||||
|
@ -5641,21 +5842,79 @@ struct wmi_peer_set_q_empty_callback_cmd {
|
|||
__le32 callback_enable;
|
||||
} __packed;
|
||||
|
||||
#define WMI_PEER_AUTH 0x00000001
|
||||
#define WMI_PEER_QOS 0x00000002
|
||||
#define WMI_PEER_NEED_PTK_4_WAY 0x00000004
|
||||
#define WMI_PEER_NEED_GTK_2_WAY 0x00000010
|
||||
#define WMI_PEER_APSD 0x00000800
|
||||
#define WMI_PEER_HT 0x00001000
|
||||
#define WMI_PEER_40MHZ 0x00002000
|
||||
#define WMI_PEER_STBC 0x00008000
|
||||
#define WMI_PEER_LDPC 0x00010000
|
||||
#define WMI_PEER_DYN_MIMOPS 0x00020000
|
||||
#define WMI_PEER_STATIC_MIMOPS 0x00040000
|
||||
#define WMI_PEER_SPATIAL_MUX 0x00200000
|
||||
#define WMI_PEER_VHT 0x02000000
|
||||
#define WMI_PEER_80MHZ 0x04000000
|
||||
#define WMI_PEER_VHT_2G 0x08000000
|
||||
struct wmi_peer_flags_map {
|
||||
u32 auth;
|
||||
u32 qos;
|
||||
u32 need_ptk_4_way;
|
||||
u32 need_gtk_2_way;
|
||||
u32 apsd;
|
||||
u32 ht;
|
||||
u32 bw40;
|
||||
u32 stbc;
|
||||
u32 ldbc;
|
||||
u32 dyn_mimops;
|
||||
u32 static_mimops;
|
||||
u32 spatial_mux;
|
||||
u32 vht;
|
||||
u32 bw80;
|
||||
u32 vht_2g;
|
||||
u32 pmf;
|
||||
};
|
||||
|
||||
enum wmi_peer_flags {
|
||||
WMI_PEER_AUTH = 0x00000001,
|
||||
WMI_PEER_QOS = 0x00000002,
|
||||
WMI_PEER_NEED_PTK_4_WAY = 0x00000004,
|
||||
WMI_PEER_NEED_GTK_2_WAY = 0x00000010,
|
||||
WMI_PEER_APSD = 0x00000800,
|
||||
WMI_PEER_HT = 0x00001000,
|
||||
WMI_PEER_40MHZ = 0x00002000,
|
||||
WMI_PEER_STBC = 0x00008000,
|
||||
WMI_PEER_LDPC = 0x00010000,
|
||||
WMI_PEER_DYN_MIMOPS = 0x00020000,
|
||||
WMI_PEER_STATIC_MIMOPS = 0x00040000,
|
||||
WMI_PEER_SPATIAL_MUX = 0x00200000,
|
||||
WMI_PEER_VHT = 0x02000000,
|
||||
WMI_PEER_80MHZ = 0x04000000,
|
||||
WMI_PEER_VHT_2G = 0x08000000,
|
||||
WMI_PEER_PMF = 0x10000000,
|
||||
};
|
||||
|
||||
enum wmi_10x_peer_flags {
|
||||
WMI_10X_PEER_AUTH = 0x00000001,
|
||||
WMI_10X_PEER_QOS = 0x00000002,
|
||||
WMI_10X_PEER_NEED_PTK_4_WAY = 0x00000004,
|
||||
WMI_10X_PEER_NEED_GTK_2_WAY = 0x00000010,
|
||||
WMI_10X_PEER_APSD = 0x00000800,
|
||||
WMI_10X_PEER_HT = 0x00001000,
|
||||
WMI_10X_PEER_40MHZ = 0x00002000,
|
||||
WMI_10X_PEER_STBC = 0x00008000,
|
||||
WMI_10X_PEER_LDPC = 0x00010000,
|
||||
WMI_10X_PEER_DYN_MIMOPS = 0x00020000,
|
||||
WMI_10X_PEER_STATIC_MIMOPS = 0x00040000,
|
||||
WMI_10X_PEER_SPATIAL_MUX = 0x00200000,
|
||||
WMI_10X_PEER_VHT = 0x02000000,
|
||||
WMI_10X_PEER_80MHZ = 0x04000000,
|
||||
};
|
||||
|
||||
enum wmi_10_2_peer_flags {
|
||||
WMI_10_2_PEER_AUTH = 0x00000001,
|
||||
WMI_10_2_PEER_QOS = 0x00000002,
|
||||
WMI_10_2_PEER_NEED_PTK_4_WAY = 0x00000004,
|
||||
WMI_10_2_PEER_NEED_GTK_2_WAY = 0x00000010,
|
||||
WMI_10_2_PEER_APSD = 0x00000800,
|
||||
WMI_10_2_PEER_HT = 0x00001000,
|
||||
WMI_10_2_PEER_40MHZ = 0x00002000,
|
||||
WMI_10_2_PEER_STBC = 0x00008000,
|
||||
WMI_10_2_PEER_LDPC = 0x00010000,
|
||||
WMI_10_2_PEER_DYN_MIMOPS = 0x00020000,
|
||||
WMI_10_2_PEER_STATIC_MIMOPS = 0x00040000,
|
||||
WMI_10_2_PEER_SPATIAL_MUX = 0x00200000,
|
||||
WMI_10_2_PEER_VHT = 0x02000000,
|
||||
WMI_10_2_PEER_80MHZ = 0x04000000,
|
||||
WMI_10_2_PEER_VHT_2G = 0x08000000,
|
||||
WMI_10_2_PEER_PMF = 0x10000000,
|
||||
};
|
||||
|
||||
/*
|
||||
* Peer rate capabilities.
|
||||
|
@ -5721,6 +5980,11 @@ struct wmi_10_2_peer_assoc_complete_cmd {
|
|||
__le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_peer_assoc_complete_cmd {
|
||||
struct wmi_10_2_peer_assoc_complete_cmd cmd;
|
||||
__le32 peer_bw_rxnss_override;
|
||||
} __packed;
|
||||
|
||||
struct wmi_peer_assoc_complete_arg {
|
||||
u8 addr[ETH_ALEN];
|
||||
u32 vdev_id;
|
||||
|
@ -5910,6 +6174,20 @@ struct wmi_dbglog_cfg_cmd {
|
|||
__le32 config_valid;
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_dbglog_cfg_cmd {
|
||||
/* bitmask to hold mod id config*/
|
||||
__le64 module_enable;
|
||||
|
||||
/* see ATH10K_DBGLOG_CFG_ */
|
||||
__le32 config_enable;
|
||||
|
||||
/* mask of module id bits to be changed */
|
||||
__le64 module_valid;
|
||||
|
||||
/* mask of config bits to be changed, see ATH10K_DBGLOG_CFG_ */
|
||||
__le32 config_valid;
|
||||
} __packed;
|
||||
|
||||
enum wmi_roam_reason {
|
||||
WMI_ROAM_REASON_BETTER_AP = 1,
|
||||
WMI_ROAM_REASON_BEACON_MISS = 2,
|
||||
|
@ -5954,6 +6232,7 @@ struct wmi_mgmt_rx_ev_arg {
|
|||
__le32 phy_mode;
|
||||
__le32 buf_len;
|
||||
__le32 status; /* %WMI_RX_STATUS_ */
|
||||
struct wmi_mgmt_rx_ext_info ext_info;
|
||||
};
|
||||
|
||||
struct wmi_ch_info_ev_arg {
|
||||
|
@ -6036,11 +6315,26 @@ struct wmi_roam_ev_arg {
|
|||
__le32 rssi;
|
||||
};
|
||||
|
||||
struct wmi_echo_ev_arg {
|
||||
__le32 value;
|
||||
};
|
||||
|
||||
struct wmi_pdev_temperature_event {
|
||||
/* temperature value in Celcius degree */
|
||||
__le32 temperature;
|
||||
} __packed;
|
||||
|
||||
struct wmi_pdev_bss_chan_info_event {
|
||||
__le32 freq;
|
||||
__le32 noise_floor;
|
||||
__le64 cycle_busy;
|
||||
__le64 cycle_total;
|
||||
__le64 cycle_tx;
|
||||
__le64 cycle_rx;
|
||||
__le64 cycle_rx_bss;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/* WOW structures */
|
||||
enum wmi_wow_wakeup_event {
|
||||
WOW_BMISS_EVENT = 0,
|
||||
|
@ -6239,6 +6533,21 @@ struct wmi_pdev_set_adaptive_cca_params {
|
|||
__le32 cca_detect_margin;
|
||||
} __packed;
|
||||
|
||||
enum wmi_host_platform_type {
|
||||
WMI_HOST_PLATFORM_HIGH_PERF,
|
||||
WMI_HOST_PLATFORM_LOW_PERF,
|
||||
};
|
||||
|
||||
enum wmi_bss_survey_req_type {
|
||||
WMI_BSS_SURVEY_REQ_TYPE_READ = 1,
|
||||
WMI_BSS_SURVEY_REQ_TYPE_READ_CLEAR,
|
||||
};
|
||||
|
||||
struct wmi_pdev_chan_info_req_cmd {
|
||||
__le32 type;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
struct ath10k;
|
||||
struct ath10k_vif;
|
||||
struct ath10k_fw_stats_pdev;
|
||||
|
@ -6336,5 +6645,8 @@ size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head);
|
|||
void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *fw_stats,
|
||||
char *buf);
|
||||
int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar,
|
||||
enum wmi_vdev_subtype subtype);
|
||||
int ath10k_wmi_barrier(struct ath10k *ar);
|
||||
|
||||
#endif /* _WMI_H_ */
|
||||
|
|
|
@ -233,7 +233,7 @@ int ath10k_wow_op_suspend(struct ieee80211_hw *hw,
|
|||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
|
||||
ar->fw_features))) {
|
||||
ar->running_fw->fw_file.fw_features))) {
|
||||
ret = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ int ath10k_wow_op_resume(struct ieee80211_hw *hw)
|
|||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
|
||||
ar->fw_features))) {
|
||||
ar->running_fw->fw_file.fw_features))) {
|
||||
ret = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -325,7 +325,8 @@ exit:
|
|||
|
||||
int ath10k_wow_init(struct ath10k *ar)
|
||||
{
|
||||
if (!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, ar->fw_features))
|
||||
if (!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
return 0;
|
||||
|
||||
if (WARN_ON(!test_bit(WMI_SERVICE_WOW, ar->wmi.svc_map)))
|
||||
|
|
Loading…
Add table
Reference in a new issue