forked from Minki/linux
wireless-next patches for v6.1
Few stack changes and lots of driver changes in this round. brcmfmac has more activity as usual and it gets new hardware support. ath11k improves WCN6750 support and also other smaller features. And of course changes all over. Note: in early September wireless tree was merged to wireless-next to avoid some conflicts with mac80211 patches, this shouldn't cause any problems but wanted to mention anyway. Major changes: mac80211 * refactoring and preparation for Wi-Fi 7 Multi-Link Operation (MLO) feature continues brcmfmac * support CYW43439 SDIO chipset * support BCM4378 on Apple platforms * support CYW89459 PCIe chipset rtw89 * more work to get rtw8852c supported * P2P support * support for enabling and disabling MSDU aggregation via nl80211 mt76 * tx status reporting improvements ath11k * cold boot calibration support on WCN6750 * Target Wake Time (TWT) debugfs support for STA interface * support to connect to a non-transmit MBSSID AP profile * enable remain-on-channel support on WCN6750 * implement SRAM dump debugfs interface * enable threaded NAPI on all hardware * WoW support for WCN6750 * support to provide transmit power from firmware via nl80211 * support to get power save duration for each client * spectral scan support for 160 MHz wcn36xx * add SNR from a received frame as a source of system entropy -----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEiBjanGPFTz4PRfLobhckVSbrbZsFAmM3BGYRHGt2YWxvQGtl cm5lbC5vcmcACgkQbhckVSbrbZuR3Af/XiuMlnDB6flq+M/kQHLWWvHybLw5aCJ7 l3yXhNFWxpBl2hQXtj17JSjVCYQmxbfrgRqhbNhyACO25bpymCb5QctB9X+Y7TwL 250JmuKvQfFx5oJNRfJ67dKTf3raloQYbdEMJNqySgebL+eSfrDskc9vaCLVDmCK I994fl0Q1wUbJ6fbuIFd07ti8ay6UlSS/iakv4+nEeimabtZWJWlXBWYRpKpikdP h9z2kPtss6yz6seaQuw6ny+qysYLi11Tp+Cued9XR3dWOOhB2X1tLHH0H02xPw76 9OJZEJHycP2juxjMfAaktHY+VX36GPLsMLUTVusH0h/Fdy3VG8YSAw== =emmG -----END PGP SIGNATURE----- Merge tag 'wireless-next-2022-09-30' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next Kalle Valo says: ==================== wireless-next patches for v6.1 Few stack changes and lots of driver changes in this round. brcmfmac has more activity as usual and it gets new hardware support. ath11k improves WCN6750 support and also other smaller features. And of course changes all over. Note: in early September wireless tree was merged to wireless-next to avoid some conflicts with mac80211 patches, this shouldn't cause any problems but wanted to mention anyway. Major changes: mac80211 - refactoring and preparation for Wi-Fi 7 Multi-Link Operation (MLO) feature continues brcmfmac - support CYW43439 SDIO chipset - support BCM4378 on Apple platforms - support CYW89459 PCIe chipset rtw89 - more work to get rtw8852c supported - P2P support - support for enabling and disabling MSDU aggregation via nl80211 mt76 - tx status reporting improvements ath11k - cold boot calibration support on WCN6750 - Target Wake Time (TWT) debugfs support for STA interface - support to connect to a non-transmit MBSSID AP profile - enable remain-on-channel support on WCN6750 - implement SRAM dump debugfs interface - enable threaded NAPI on all hardware - WoW support for WCN6750 - support to provide transmit power from firmware via nl80211 - support to get power save duration for each client - spectral scan support for 160 MHz wcn36xx - add SNR from a received frame as a source of system entropy * tag 'wireless-next-2022-09-30' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (231 commits) wifi: rtl8xxxu: Improve rtl8xxxu_queue_select wifi: rtl8xxxu: Fix AIFS written to REG_EDCA_*_PARAM wifi: rtl8xxxu: gen2: Enable 40 MHz channel width wifi: rtw89: 8852b: configure DLE mem wifi: rtw89: check DLE FIFO size with reserved size wifi: rtw89: mac: correct register of report IMR wifi: rtw89: pci: set power cut closed for 8852be wifi: rtw89: pci: add to do PCI auto calibration wifi: rtw89: 8852b: implement chip_ops::{enable,disable}_bb_rf wifi: rtw89: add DMA busy checking bits to chip info wifi: rtw89: mac: define DMA channel mask to avoid unsupported channels wifi: rtw89: pci: mask out unsupported TX channels iwlegacy: Replace zero-length arrays with DECLARE_FLEX_ARRAY() helper ipw2x00: Replace zero-length array with DECLARE_FLEX_ARRAY() helper wifi: iwlwifi: Track scan_cmd allocation size explicitly brcmfmac: Remove the call to "dtim_assoc" IOVAR brcmfmac: increase dcmd maximum buffer size brcmfmac: Support 89459 pcie brcmfmac: increase default max WOWL patterns to 16 cw1200: fix incorrect check to determine if no element is found in list ... ==================== Link: https://lore.kernel.org/r/20220930150413.A7984C433D6@smtp.kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
915b96c527
@ -4,7 +4,7 @@
|
||||
$id: http://devicetree.org/schemas/net/wireless/brcm,bcm4329-fmac.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom BCM4329 family fullmac wireless SDIO devices
|
||||
title: Broadcom BCM4329 family fullmac wireless SDIO/PCIE devices
|
||||
|
||||
maintainers:
|
||||
- Arend van Spriel <arend@broadcom.com>
|
||||
@ -41,11 +41,17 @@ properties:
|
||||
- cypress,cyw4373-fmac
|
||||
- cypress,cyw43012-fmac
|
||||
- const: brcm,bcm4329-fmac
|
||||
- const: brcm,bcm4329-fmac
|
||||
- enum:
|
||||
- brcm,bcm4329-fmac
|
||||
- pci14e4,43dc # BCM4355
|
||||
- pci14e4,4464 # BCM4364
|
||||
- pci14e4,4488 # BCM4377
|
||||
- pci14e4,4425 # BCM4378
|
||||
- pci14e4,4433 # BCM4387
|
||||
|
||||
reg:
|
||||
description: SDIO function number for the device, for most cases
|
||||
this will be 1.
|
||||
description: SDIO function number for the device (for most cases
|
||||
this will be 1) or PCI device identifier.
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
@ -85,6 +91,31 @@ properties:
|
||||
takes precedence.
|
||||
type: boolean
|
||||
|
||||
brcm,cal-blob:
|
||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||
description: A per-device calibration blob for the Wi-Fi radio. This
|
||||
should be filled in by the bootloader from platform configuration
|
||||
data, if necessary, and will be uploaded to the device if present.
|
||||
|
||||
brcm,board-type:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description: Overrides the board type, which is normally the compatible of
|
||||
the root node. This can be used to decouple the overall system board or
|
||||
device name from the board type for WiFi purposes, which is used to
|
||||
construct firmware and NVRAM configuration filenames, allowing for
|
||||
multiple devices that share the same module or characteristics for the
|
||||
WiFi subsystem to share the same firmware/NVRAM files. On Apple platforms,
|
||||
this should be the Apple module-instance codename prefixed by "apple,",
|
||||
e.g. "apple,honshu".
|
||||
|
||||
apple,antenna-sku:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description: Antenna SKU used to identify a specific antenna configuration
|
||||
on Apple platforms. This is use to build firmware filenames, to allow
|
||||
platforms with different antenna configs to have different firmware and/or
|
||||
NVRAM. This would normally be filled in by the bootloader from platform
|
||||
configuration data.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -66,6 +66,18 @@ properties:
|
||||
required:
|
||||
- iommus
|
||||
|
||||
qcom,smem-states:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description: State bits used by the AP to signal the WLAN Q6.
|
||||
items:
|
||||
- description: Signal bits used to enable/disable low power mode
|
||||
on WCN6750 in the case of WoW (Wake on Wireless).
|
||||
|
||||
qcom,smem-state-names:
|
||||
description: The names of the state bits used for SMP2P output.
|
||||
items:
|
||||
- const: wlan-smp2p-out
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@ -448,6 +460,8 @@ examples:
|
||||
<GIC_SPI 799 IRQ_TYPE_EDGE_RISING>;
|
||||
qcom,rproc = <&remoteproc_wpss>;
|
||||
memory-region = <&wlan_fw_mem>, <&wlan_ce_mem>;
|
||||
qcom,smem-states = <&wlan_smp2p_out 0>;
|
||||
qcom,smem-state-names = "wlan-smp2p-out";
|
||||
wifi-firmware {
|
||||
iommus = <&apps_smmu 0x1c02 0x1>;
|
||||
};
|
||||
|
@ -21,6 +21,10 @@
|
||||
};
|
||||
};
|
||||
|
||||
&wifi0 {
|
||||
brcm,board-type = "apple,atlantisb";
|
||||
};
|
||||
|
||||
/*
|
||||
* Force the bus number assignments so that we can declare some of the
|
||||
* on-board devices and properties that are populated by the bootloader
|
||||
|
@ -17,6 +17,10 @@
|
||||
model = "Apple MacBook Pro (13-inch, M1, 2020)";
|
||||
};
|
||||
|
||||
&wifi0 {
|
||||
brcm,board-type = "apple,honshu";
|
||||
};
|
||||
|
||||
/*
|
||||
* Remove unused PCIe ports and disable the associated DARTs.
|
||||
*/
|
||||
|
@ -17,6 +17,10 @@
|
||||
model = "Apple MacBook Air (M1, 2020)";
|
||||
};
|
||||
|
||||
&wifi0 {
|
||||
brcm,board-type = "apple,shikoku";
|
||||
};
|
||||
|
||||
/*
|
||||
* Remove unused PCIe ports and disable the associated DARTs.
|
||||
*/
|
||||
|
@ -21,6 +21,10 @@
|
||||
};
|
||||
};
|
||||
|
||||
&wifi0 {
|
||||
brcm,board-type = "apple,capri";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
hpm2: usb-pd@3b {
|
||||
compatible = "apple,cd321x";
|
||||
|
@ -21,6 +21,10 @@
|
||||
};
|
||||
};
|
||||
|
||||
&wifi0 {
|
||||
brcm,board-type = "apple,santorini";
|
||||
};
|
||||
|
||||
/*
|
||||
* Force the bus number assignments so that we can declare some of the
|
||||
* on-board devices and properties that are populated by the bootloader
|
||||
|
@ -71,8 +71,10 @@
|
||||
&port00 {
|
||||
bus-range = <1 1>;
|
||||
wifi0: network@0,0 {
|
||||
compatible = "pci14e4,4425";
|
||||
reg = <0x10000 0x0 0x0 0x0 0x0>;
|
||||
/* To be filled by the loader */
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
apple,antenna-sku = "XX";
|
||||
};
|
||||
};
|
||||
|
@ -30,7 +30,7 @@ enum bcma_boot_dev {
|
||||
BCMA_BOOT_DEV_NAND,
|
||||
};
|
||||
|
||||
/* The 47162a0 hangs when reading MIPS DMP registers registers */
|
||||
/* The 47162a0 hangs when reading MIPS DMP registers */
|
||||
static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
|
||||
{
|
||||
return dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM47162 &&
|
||||
|
@ -101,7 +101,7 @@ int ath10k_bmi_get_target_info_sdio(struct ath10k *ar,
|
||||
cmd.id = __cpu_to_le32(BMI_GET_TARGET_INFO);
|
||||
|
||||
/* Step 1: Read 4 bytes of the target info and check if it is
|
||||
* the special sentinal version word or the first word in the
|
||||
* the special sentinel version word or the first word in the
|
||||
* version response.
|
||||
*/
|
||||
resplen = sizeof(u32);
|
||||
@ -111,7 +111,7 @@ int ath10k_bmi_get_target_info_sdio(struct ath10k *ar,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Some SDIO boards have a special sentinal byte before the real
|
||||
/* Some SDIO boards have a special sentinel byte before the real
|
||||
* version response.
|
||||
*/
|
||||
if (__le32_to_cpu(tmp) == TARGET_VERSION_SENTINAL) {
|
||||
|
@ -1323,7 +1323,7 @@ EXPORT_SYMBOL(ath10k_ce_per_engine_service);
|
||||
/*
|
||||
* Handler for per-engine interrupts on ALL active CEs.
|
||||
* This is used in cases where the system is sharing a
|
||||
* single interrput for all CEs
|
||||
* single interrupt for all CEs
|
||||
*/
|
||||
|
||||
void ath10k_ce_per_engine_service_any(struct ath10k *ar)
|
||||
|
@ -3096,7 +3096,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
* enabled always.
|
||||
*
|
||||
* We can still enable BTCOEX if firmware has the support
|
||||
* eventhough btceox_support value is
|
||||
* even though btceox_support value is
|
||||
* ATH10K_DT_BTCOEX_NOT_FOUND
|
||||
*/
|
||||
|
||||
|
@ -76,7 +76,7 @@
|
||||
/* The magic used by QCA spec */
|
||||
#define ATH10K_SMBIOS_BDF_EXT_MAGIC "BDF_"
|
||||
|
||||
/* Default Airtime weight multipler (Tuned for multiclient performance) */
|
||||
/* Default Airtime weight multiplier (Tuned for multiclient performance) */
|
||||
#define ATH10K_AIRTIME_WEIGHT_MULTIPLIER 4
|
||||
|
||||
#define ATH10K_MAX_RETRY_COUNT 30
|
||||
@ -857,7 +857,7 @@ enum ath10k_dev_flags {
|
||||
/* Disable HW crypto engine */
|
||||
ATH10K_FLAG_HW_CRYPTO_DISABLED,
|
||||
|
||||
/* Bluetooth coexistance enabled */
|
||||
/* Bluetooth coexistence enabled */
|
||||
ATH10K_FLAG_BTCOEX,
|
||||
|
||||
/* Per Station statistics service */
|
||||
|
@ -531,7 +531,7 @@ static const struct ath10k_mem_section qca6174_hw30_sdio_register_sections[] = {
|
||||
|
||||
{0x40000, 0x400A4},
|
||||
|
||||
/* SI register is skiped here.
|
||||
/* SI register is skipped here.
|
||||
* Because it will cause bus hang
|
||||
*
|
||||
* {0x50000, 0x50018},
|
||||
|
@ -125,7 +125,7 @@ enum ath10k_mem_region_type {
|
||||
* To minimize the size of the array, the list must obey the format:
|
||||
* '{start0,stop0},{start1,stop1},{start2,stop2}....' The values below must
|
||||
* also obey to 'start0 < stop0 < start1 < stop1 < start2 < ...', otherwise
|
||||
* we may encouter error in the dump processing.
|
||||
* we may encounter error in the dump processing.
|
||||
*/
|
||||
struct ath10k_mem_section {
|
||||
u32 start;
|
||||
|
@ -1081,7 +1081,7 @@ exit:
|
||||
* struct available..
|
||||
*/
|
||||
|
||||
/* This generally cooresponds to the debugfs fw_stats file */
|
||||
/* This generally corresponds to the debugfs fw_stats file */
|
||||
static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
|
||||
"tx_pkts_nic",
|
||||
"tx_bytes_nic",
|
||||
|
@ -498,7 +498,7 @@ static char *get_num_ampdu_subfrm_str(enum ath10k_ampdu_subfrm_num i)
|
||||
{
|
||||
switch (i) {
|
||||
case ATH10K_AMPDU_SUBFRM_NUM_10:
|
||||
return "upto 10";
|
||||
return "up to 10";
|
||||
case ATH10K_AMPDU_SUBFRM_NUM_20:
|
||||
return "11-20";
|
||||
case ATH10K_AMPDU_SUBFRM_NUM_30:
|
||||
|
@ -301,12 +301,16 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt)
|
||||
ath10k_htt_get_vaddr_ring(htt),
|
||||
htt->rx_ring.base_paddr);
|
||||
|
||||
ath10k_htt_config_paddrs_ring(htt, NULL);
|
||||
|
||||
dma_free_coherent(htt->ar->dev,
|
||||
sizeof(*htt->rx_ring.alloc_idx.vaddr),
|
||||
htt->rx_ring.alloc_idx.vaddr,
|
||||
htt->rx_ring.alloc_idx.paddr);
|
||||
htt->rx_ring.alloc_idx.vaddr = NULL;
|
||||
|
||||
kfree(htt->rx_ring.netbufs_ring);
|
||||
htt->rx_ring.netbufs_ring = NULL;
|
||||
}
|
||||
|
||||
static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
|
||||
@ -846,8 +850,10 @@ err_dma_idx:
|
||||
ath10k_htt_get_rx_ring_size(htt),
|
||||
vaddr_ring,
|
||||
htt->rx_ring.base_paddr);
|
||||
ath10k_htt_config_paddrs_ring(htt, NULL);
|
||||
err_dma_ring:
|
||||
kfree(htt->rx_ring.netbufs_ring);
|
||||
htt->rx_ring.netbufs_ring = NULL;
|
||||
err_netbuf:
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -2496,7 +2502,7 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
|
||||
|
||||
/* I have not yet seen any case where num_mpdu_ranges > 1.
|
||||
* qcacld does not seem handle that case either, so we introduce the
|
||||
* same limitiation here as well.
|
||||
* same limitation here as well.
|
||||
*/
|
||||
if (num_mpdu_ranges > 1)
|
||||
ath10k_warn(ar,
|
||||
|
@ -1112,7 +1112,7 @@ int ath10k_htt_tx_fetch_resp(struct ath10k *ar,
|
||||
int len = 0;
|
||||
int ret;
|
||||
|
||||
/* Response IDs are echo-ed back only for host driver convienence
|
||||
/* Response IDs are echo-ed back only for host driver convenience
|
||||
* purposes. They aren't used for anything in the driver yet so use 0.
|
||||
*/
|
||||
|
||||
|
@ -84,7 +84,7 @@ const struct ath10k_hw_regs qca99x0_regs = {
|
||||
.ce5_base_address = 0x0004b400,
|
||||
.ce6_base_address = 0x0004b800,
|
||||
.ce7_base_address = 0x0004bc00,
|
||||
/* Note: qca99x0 supports upto 12 Copy Engines. Other than address of
|
||||
/* Note: qca99x0 supports up to 12 Copy Engines. Other than address of
|
||||
* CE0 and CE1 no other copy engine is directly referred in the code.
|
||||
* It is not really necessary to assign address for newly supported
|
||||
* CEs in this address table.
|
||||
@ -120,7 +120,7 @@ const struct ath10k_hw_regs qca4019_regs = {
|
||||
.ce5_base_address = 0x0004b400,
|
||||
.ce6_base_address = 0x0004b800,
|
||||
.ce7_base_address = 0x0004bc00,
|
||||
/* qca4019 supports upto 12 copy engines. Since base address
|
||||
/* qca4019 supports up to 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
|
||||
@ -924,7 +924,7 @@ static void ath10k_hw_map_target_mem(struct ath10k *ar, u32 msb)
|
||||
ath10k_hif_write32(ar, address, msb);
|
||||
}
|
||||
|
||||
/* 1. Write to memory region of target, such as IRAM adn DRAM.
|
||||
/* 1. Write to memory region of target, such as IRAM and DRAM.
|
||||
* 2. Target address( 0 ~ 00100000 & 0x00400000~0x00500000)
|
||||
* can be written directly. See ath10k_pci_targ_cpu_to_ce_addr() too.
|
||||
* 3. In order to access the region other than the above,
|
||||
|
@ -4051,7 +4051,7 @@ static int ath10k_mac_tx(struct ath10k *ar,
|
||||
ath10k_tx_h_seq_no(vif, skb);
|
||||
break;
|
||||
case ATH10K_HW_TXRX_ETHERNET:
|
||||
/* Convert 802.11->802.3 header only if the frame was erlier
|
||||
/* Convert 802.11->802.3 header only if the frame was earlier
|
||||
* encapsulated to 802.11 by mac80211. Otherwise pass it as is.
|
||||
*/
|
||||
if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
|
||||
@ -8097,7 +8097,7 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
/* TODO: Implement this function properly
|
||||
* For now it is needed to reply to Probe Requests in IBSS mode.
|
||||
* Propably we need this information from FW.
|
||||
* Probably we need this information from FW.
|
||||
*/
|
||||
static int ath10k_tx_last_beacon(struct ieee80211_hw *hw)
|
||||
{
|
||||
@ -8520,7 +8520,7 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
|
||||
"mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
|
||||
sta->addr, changed, sta->deflink.bandwidth,
|
||||
sta->deflink.rx_nss,
|
||||
sta->smps_mode);
|
||||
sta->deflink.smps_mode);
|
||||
|
||||
if (changed & IEEE80211_RC_BW_CHANGED) {
|
||||
bw = WMI_PEER_CHWIDTH_20MHZ;
|
||||
@ -8554,7 +8554,7 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
|
||||
if (changed & IEEE80211_RC_SMPS_CHANGED) {
|
||||
smps = WMI_PEER_SMPS_PS_NONE;
|
||||
|
||||
switch (sta->smps_mode) {
|
||||
switch (sta->deflink.smps_mode) {
|
||||
case IEEE80211_SMPS_AUTOMATIC:
|
||||
case IEEE80211_SMPS_OFF:
|
||||
smps = WMI_PEER_SMPS_PS_NONE;
|
||||
@ -8567,7 +8567,7 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
|
||||
break;
|
||||
case IEEE80211_SMPS_NUM_MODES:
|
||||
ath10k_warn(ar, "Invalid smps %d in sta rc update for %pM\n",
|
||||
sta->smps_mode, sta->addr);
|
||||
sta->deflink.smps_mode, sta->addr);
|
||||
smps = WMI_PEER_SMPS_PS_NONE;
|
||||
break;
|
||||
}
|
||||
@ -9686,7 +9686,7 @@ static const struct ieee80211_iface_limit ath10k_tlv_if_limit_ibss[] = {
|
||||
},
|
||||
};
|
||||
|
||||
/* FIXME: This is not thouroughly tested. These combinations may over- or
|
||||
/* FIXME: This is not thoroughly tested. These combinations may over- or
|
||||
* underestimate hw/fw capabilities.
|
||||
*/
|
||||
static struct ieee80211_iface_combination ath10k_tlv_if_comb[] = {
|
||||
@ -9926,7 +9926,7 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
WLAN_CIPHER_SUITE_BIP_GMAC_128,
|
||||
WLAN_CIPHER_SUITE_BIP_GMAC_256,
|
||||
|
||||
/* Only QCA99x0 and QCA4019 varients support GCMP-128, GCMP-256
|
||||
/* Only QCA99x0 and QCA4019 variants support GCMP-128, GCMP-256
|
||||
* and CCMP-256 in hardware.
|
||||
*/
|
||||
WLAN_CIPHER_SUITE_GCMP,
|
||||
|
@ -1244,7 +1244,7 @@ static void ath10k_pci_process_htt_rx_cb(struct ath10k_ce_pipe *ce_state,
|
||||
unsigned int nbytes, max_nbytes, nentries;
|
||||
int orig_len;
|
||||
|
||||
/* No need to aquire ce_lock for CE5, since this is the only place CE5
|
||||
/* No need to acquire ce_lock for CE5, since this is the only place CE5
|
||||
* is processed other than init and deinit. Before releasing CE5
|
||||
* buffers, interrupts are disabled. Thus CE5 access is serialized.
|
||||
*/
|
||||
|
@ -81,7 +81,7 @@ struct ath10k_pci_pipe {
|
||||
/* Handle of underlying Copy Engine */
|
||||
struct ath10k_ce_pipe *ce_hdl;
|
||||
|
||||
/* Our pipe number; facilitiates use of pipe_info ptrs. */
|
||||
/* Our pipe number; facilitates use of pipe_info ptrs. */
|
||||
u8 pipe_num;
|
||||
|
||||
/* Convenience back pointer to hif_ce_state. */
|
||||
|
@ -792,7 +792,7 @@ static void ath10k_qmi_event_server_arrive(struct ath10k_qmi *qmi)
|
||||
return;
|
||||
|
||||
/*
|
||||
* HACK: sleep for a while inbetween receiving the msa info response
|
||||
* HACK: sleep for a while between receiving the msa info response
|
||||
* and the XPU update to prevent SDM845 from crashing due to a security
|
||||
* violation, when running MPSS.AT.4.0.c2-01184-SDM845_GEN_PACK-1.
|
||||
*/
|
||||
|
@ -448,7 +448,7 @@ struct rx_mpdu_end {
|
||||
* - 4 bytes for WEP
|
||||
* - 8 bytes for TKIP, AES
|
||||
* [padding to 4 bytes]
|
||||
* c) A-MSDU subframe header (14 bytes) if appliable
|
||||
* c) A-MSDU subframe header (14 bytes) if applicable
|
||||
* d) LLC/SNAP (RFC1042, 8 bytes)
|
||||
*
|
||||
* In case of A-MSDU only first frame in sequence contains (a) and (b).
|
||||
|
@ -1057,7 +1057,7 @@ static int ath10k_sdio_mbox_proc_pending_irqs(struct ath10k *ar,
|
||||
|
||||
out:
|
||||
/* An optimization to bypass reading the IRQ status registers
|
||||
* unecessarily which can re-wake the target, if upper layers
|
||||
* unnecessarily which can re-wake the target, if upper layers
|
||||
* determine that we are in a low-throughput mode, we can rely on
|
||||
* taking another interrupt rather than re-checking the status
|
||||
* registers which can re-wake the target.
|
||||
|
@ -98,7 +98,7 @@ static ssize_t ath10k_thermal_show_temp(struct device *dev,
|
||||
temperature = ar->thermal.temperature;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
/* display in millidegree celcius */
|
||||
/* display in millidegree celsius */
|
||||
ret = snprintf(buf, PAGE_SIZE, "%d\n", temperature * 1000);
|
||||
out:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
@ -19,7 +19,7 @@ struct ath10k_thermal {
|
||||
/* protected by conf_mutex */
|
||||
u32 throttle_state;
|
||||
u32 quiet_period;
|
||||
/* temperature value in Celcius degree
|
||||
/* temperature value in Celsius degree
|
||||
* protected by data_lock
|
||||
*/
|
||||
int temperature;
|
||||
|
@ -26,7 +26,7 @@
|
||||
#define ATH10K_USB_EP_ADDR_APP_DATA_MP_OUT 0x03
|
||||
#define ATH10K_USB_EP_ADDR_APP_DATA_HP_OUT 0x04
|
||||
|
||||
/* diagnostic command defnitions */
|
||||
/* diagnostic command definitions */
|
||||
#define ATH10K_USB_CONTROL_REQ_SEND_BMI_CMD 1
|
||||
#define ATH10K_USB_CONTROL_REQ_RECV_BMI_RESP 2
|
||||
#define ATH10K_USB_CONTROL_REQ_DIAG_CMD 3
|
||||
|
@ -1813,7 +1813,7 @@ struct wmi_tlv_pdev_get_temp_cmd {
|
||||
|
||||
struct wmi_tlv_pdev_temperature_event {
|
||||
__le32 tlv_hdr;
|
||||
/* temperature value in Celcius degree */
|
||||
/* temperature value in Celsius degree */
|
||||
__le32 temperature;
|
||||
__le32 pdev_id;
|
||||
} __packed;
|
||||
@ -2548,7 +2548,7 @@ struct nlo_channel_prediction_cfg {
|
||||
|
||||
/* Preconfigured stationary threshold.
|
||||
* Lesser value means more conservative. Bigger value means more aggressive.
|
||||
* Maximum is 100 and mininum is 0.
|
||||
* Maximum is 100 and minimum is 0.
|
||||
*/
|
||||
__le32 stationary_threshold;
|
||||
|
||||
|
@ -3555,7 +3555,7 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
|
||||
__le32 t;
|
||||
u32 v, tim_len;
|
||||
|
||||
/* When FW reports 0 in tim_len, ensure atleast first byte
|
||||
/* When FW reports 0 in tim_len, ensure at least first byte
|
||||
* in tim_bitmap is considered for pvm calculation.
|
||||
*/
|
||||
tim_len = tim_info->tim_len ? __le32_to_cpu(tim_info->tim_len) : 1;
|
||||
|
@ -3170,7 +3170,7 @@ struct wmi_start_scan_common {
|
||||
/* dwell time in msec on passive channels */
|
||||
__le32 dwell_time_passive;
|
||||
/*
|
||||
* min time in msec on the BSS channel,only valid if atleast one
|
||||
* min time in msec on the BSS channel,only valid if at least one
|
||||
* VDEV is active
|
||||
*/
|
||||
__le32 min_rest_time;
|
||||
@ -3196,7 +3196,7 @@ struct wmi_start_scan_common {
|
||||
* and bssid_list
|
||||
*/
|
||||
__le32 repeat_probe_time;
|
||||
/* time in msec between 2 consequetive probe requests with in a set. */
|
||||
/* time in msec between 2 consecutive probe requests with in a set. */
|
||||
__le32 probe_spacing_time;
|
||||
/*
|
||||
* data inactivity time in msec on bss channel that will be used by
|
||||
@ -4397,7 +4397,7 @@ struct wmi_pdev_stats_tx {
|
||||
/* wal pdev continuous xretry */
|
||||
__le32 pdev_cont_xretry;
|
||||
|
||||
/* wal pdev continous xretry */
|
||||
/* wal pdev continuous xretry */
|
||||
__le32 pdev_tx_timeout;
|
||||
|
||||
/* wal pdev resets */
|
||||
@ -5240,7 +5240,7 @@ enum wmi_vdev_param {
|
||||
* scheduler.
|
||||
*/
|
||||
WMI_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
|
||||
/* enable/dsiable WDS for this VDEV */
|
||||
/* enable/disable WDS for this VDEV */
|
||||
WMI_VDEV_PARAM_WDS,
|
||||
/* ATIM Window */
|
||||
WMI_VDEV_PARAM_ATIM_WINDOW,
|
||||
@ -5372,7 +5372,7 @@ enum wmi_10x_vdev_param {
|
||||
* scheduler.
|
||||
*/
|
||||
WMI_10X_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
|
||||
/* enable/dsiable WDS for this VDEV */
|
||||
/* enable/disable WDS for this VDEV */
|
||||
WMI_10X_VDEV_PARAM_WDS,
|
||||
/* ATIM Window */
|
||||
WMI_10X_VDEV_PARAM_ATIM_WINDOW,
|
||||
@ -5904,7 +5904,7 @@ enum wmi_sta_ps_param_tx_wake_threshold {
|
||||
enum wmi_sta_ps_param_pspoll_count {
|
||||
WMI_STA_PS_PSPOLL_COUNT_NO_MAX = 0,
|
||||
/*
|
||||
* Values greater than 0 indicate the maximum numer of PS-Poll frames
|
||||
* Values greater than 0 indicate the maximum number of PS-Poll frames
|
||||
* FW will send before waking up.
|
||||
*/
|
||||
|
||||
@ -6947,7 +6947,7 @@ struct wmi_echo_ev_arg {
|
||||
};
|
||||
|
||||
struct wmi_pdev_temperature_event {
|
||||
/* temperature value in Celcius degree */
|
||||
/* temperature value in Celsius degree */
|
||||
__le32 temperature;
|
||||
} __packed;
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "hif.h"
|
||||
#include <linux/remoteproc.h>
|
||||
#include "pcic.h"
|
||||
#include <linux/soc/qcom/smem.h>
|
||||
#include <linux/soc/qcom/smem_state.h>
|
||||
|
||||
static const struct of_device_id ath11k_ahb_of_match[] = {
|
||||
/* TODO: Should we change the compatible string to something similar
|
||||
@ -359,6 +361,7 @@ static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab)
|
||||
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
|
||||
|
||||
if (!irq_grp->napi_enabled) {
|
||||
dev_set_threaded(&irq_grp->napi_ndev, true);
|
||||
napi_enable(&irq_grp->napi);
|
||||
irq_grp->napi_enabled = true;
|
||||
}
|
||||
@ -406,7 +409,8 @@ static int ath11k_ahb_fwreset_from_cold_boot(struct ath11k_base *ab)
|
||||
int timeout;
|
||||
|
||||
if (ath11k_cold_boot_cal == 0 || ab->qmi.cal_done ||
|
||||
ab->hw_params.cold_boot_calib == 0)
|
||||
ab->hw_params.cold_boot_calib == 0 ||
|
||||
ab->hw_params.cbcal_restart_fw == 0)
|
||||
return 0;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_AHB, "wait for cold boot done\n");
|
||||
@ -685,11 +689,90 @@ static int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_ahb_hif_suspend(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
|
||||
u32 wake_irq;
|
||||
u32 value = 0;
|
||||
int ret;
|
||||
|
||||
if (!device_may_wakeup(ab->dev))
|
||||
return -EPERM;
|
||||
|
||||
wake_irq = ab->irq_num[ATH11K_PCI_IRQ_CE0_OFFSET + ATH11K_PCI_CE_WAKE_IRQ];
|
||||
|
||||
ret = enable_irq_wake(wake_irq);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to enable wakeup irq :%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
value = u32_encode_bits(ab_ahb->smp2p_info.seq_no++,
|
||||
ATH11K_AHB_SMP2P_SMEM_SEQ_NO);
|
||||
value |= u32_encode_bits(ATH11K_AHB_POWER_SAVE_ENTER,
|
||||
ATH11K_AHB_SMP2P_SMEM_MSG);
|
||||
|
||||
ret = qcom_smem_state_update_bits(ab_ahb->smp2p_info.smem_state,
|
||||
ATH11K_AHB_SMP2P_SMEM_VALUE_MASK, value);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to send smp2p power save enter cmd :%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_AHB, "ahb device suspended\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_ahb_hif_resume(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
|
||||
u32 wake_irq;
|
||||
u32 value = 0;
|
||||
int ret;
|
||||
|
||||
if (!device_may_wakeup(ab->dev))
|
||||
return -EPERM;
|
||||
|
||||
wake_irq = ab->irq_num[ATH11K_PCI_IRQ_CE0_OFFSET + ATH11K_PCI_CE_WAKE_IRQ];
|
||||
|
||||
ret = disable_irq_wake(wake_irq);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to disable wakeup irq: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
reinit_completion(&ab->wow.wakeup_completed);
|
||||
|
||||
value = u32_encode_bits(ab_ahb->smp2p_info.seq_no++,
|
||||
ATH11K_AHB_SMP2P_SMEM_SEQ_NO);
|
||||
value |= u32_encode_bits(ATH11K_AHB_POWER_SAVE_EXIT,
|
||||
ATH11K_AHB_SMP2P_SMEM_MSG);
|
||||
|
||||
ret = qcom_smem_state_update_bits(ab_ahb->smp2p_info.smem_state,
|
||||
ATH11K_AHB_SMP2P_SMEM_VALUE_MASK, value);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to send smp2p power save enter cmd :%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_timeout(&ab->wow.wakeup_completed, 3 * HZ);
|
||||
if (ret == 0) {
|
||||
ath11k_warn(ab, "timed out while waiting for wow wakeup completion\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_AHB, "ahb device resumed\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ath11k_hif_ops ath11k_ahb_hif_ops_ipq8074 = {
|
||||
.start = ath11k_ahb_start,
|
||||
.stop = ath11k_ahb_stop,
|
||||
.read32 = ath11k_ahb_read32,
|
||||
.write32 = ath11k_ahb_write32,
|
||||
.read = NULL,
|
||||
.irq_enable = ath11k_ahb_ext_irq_enable,
|
||||
.irq_disable = ath11k_ahb_ext_irq_disable,
|
||||
.map_service_to_pipe = ath11k_ahb_map_service_to_pipe,
|
||||
@ -702,6 +785,7 @@ static const struct ath11k_hif_ops ath11k_ahb_hif_ops_wcn6750 = {
|
||||
.stop = ath11k_pcic_stop,
|
||||
.read32 = ath11k_pcic_read32,
|
||||
.write32 = ath11k_pcic_write32,
|
||||
.read = NULL,
|
||||
.irq_enable = ath11k_pcic_ext_irq_enable,
|
||||
.irq_disable = ath11k_pcic_ext_irq_disable,
|
||||
.get_msi_address = ath11k_pcic_get_msi_address,
|
||||
@ -709,6 +793,10 @@ static const struct ath11k_hif_ops ath11k_ahb_hif_ops_wcn6750 = {
|
||||
.map_service_to_pipe = ath11k_pcic_map_service_to_pipe,
|
||||
.power_down = ath11k_ahb_power_down,
|
||||
.power_up = ath11k_ahb_power_up,
|
||||
.suspend = ath11k_ahb_hif_suspend,
|
||||
.resume = ath11k_ahb_hif_resume,
|
||||
.ce_irq_enable = ath11k_pci_enable_ce_irqs_except_wake_irq,
|
||||
.ce_irq_disable = ath11k_pci_disable_ce_irqs_except_wake_irq,
|
||||
};
|
||||
|
||||
static int ath11k_core_get_rproc(struct ath11k_base *ab)
|
||||
@ -783,6 +871,34 @@ static int ath11k_ahb_setup_msi_resources(struct ath11k_base *ab)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_ahb_setup_smp2p_handle(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
|
||||
|
||||
if (!ab->hw_params.smp2p_wow_exit)
|
||||
return 0;
|
||||
|
||||
ab_ahb->smp2p_info.smem_state = qcom_smem_state_get(ab->dev, "wlan-smp2p-out",
|
||||
&ab_ahb->smp2p_info.smem_bit);
|
||||
if (IS_ERR(ab_ahb->smp2p_info.smem_state)) {
|
||||
ath11k_err(ab, "failed to fetch smem state: %ld\n",
|
||||
PTR_ERR(ab_ahb->smp2p_info.smem_state));
|
||||
return PTR_ERR(ab_ahb->smp2p_info.smem_state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_ahb_release_smp2p_handle(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
|
||||
|
||||
if (!ab->hw_params.smp2p_wow_exit)
|
||||
return;
|
||||
|
||||
qcom_smem_state_put(ab_ahb->smp2p_info.smem_state);
|
||||
}
|
||||
|
||||
static int ath11k_ahb_setup_resources(struct ath11k_base *ab)
|
||||
{
|
||||
struct platform_device *pdev = ab->pdev;
|
||||
@ -1038,10 +1154,14 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto err_core_free;
|
||||
|
||||
ret = ath11k_hal_srng_init(ab);
|
||||
ret = ath11k_ahb_setup_smp2p_handle(ab);
|
||||
if (ret)
|
||||
goto err_fw_deinit;
|
||||
|
||||
ret = ath11k_hal_srng_init(ab);
|
||||
if (ret)
|
||||
goto err_release_smp2p_handle;
|
||||
|
||||
ret = ath11k_ce_alloc_pipes(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
|
||||
@ -1078,6 +1198,9 @@ err_ce_free:
|
||||
err_hal_srng_deinit:
|
||||
ath11k_hal_srng_deinit(ab);
|
||||
|
||||
err_release_smp2p_handle:
|
||||
ath11k_ahb_release_smp2p_handle(ab);
|
||||
|
||||
err_fw_deinit:
|
||||
ath11k_ahb_fw_resource_deinit(ab);
|
||||
|
||||
@ -1088,20 +1211,10 @@ err_core_free:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_ahb_remove(struct platform_device *pdev)
|
||||
static void ath11k_ahb_remove_prepare(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_base *ab = platform_get_drvdata(pdev);
|
||||
unsigned long left;
|
||||
|
||||
if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
|
||||
ath11k_ahb_power_down(ab);
|
||||
ath11k_debugfs_soc_destroy(ab);
|
||||
ath11k_qmi_deinit_service(ab);
|
||||
goto qmi_fail;
|
||||
}
|
||||
|
||||
reinit_completion(&ab->driver_recovery);
|
||||
|
||||
if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags)) {
|
||||
left = wait_for_completion_timeout(&ab->driver_recovery,
|
||||
ATH11K_AHB_RECOVERY_TIMEOUT);
|
||||
@ -1111,19 +1224,61 @@ static int ath11k_ahb_remove(struct platform_device *pdev)
|
||||
|
||||
set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
|
||||
cancel_work_sync(&ab->restart_work);
|
||||
cancel_work_sync(&ab->qmi.event_work);
|
||||
}
|
||||
|
||||
static void ath11k_ahb_free_resources(struct ath11k_base *ab)
|
||||
{
|
||||
struct platform_device *pdev = ab->pdev;
|
||||
|
||||
ath11k_core_deinit(ab);
|
||||
qmi_fail:
|
||||
ath11k_ahb_free_irq(ab);
|
||||
ath11k_hal_srng_deinit(ab);
|
||||
ath11k_ahb_release_smp2p_handle(ab);
|
||||
ath11k_ahb_fw_resource_deinit(ab);
|
||||
ath11k_ce_free_pipes(ab);
|
||||
ath11k_core_free(ab);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static int ath11k_ahb_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ath11k_base *ab = platform_get_drvdata(pdev);
|
||||
|
||||
if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
|
||||
ath11k_ahb_power_down(ab);
|
||||
ath11k_debugfs_soc_destroy(ab);
|
||||
ath11k_qmi_deinit_service(ab);
|
||||
goto qmi_fail;
|
||||
}
|
||||
|
||||
ath11k_ahb_remove_prepare(ab);
|
||||
ath11k_core_deinit(ab);
|
||||
|
||||
qmi_fail:
|
||||
ath11k_ahb_free_resources(ab);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_ahb_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct ath11k_base *ab = platform_get_drvdata(pdev);
|
||||
|
||||
/* platform shutdown() & remove() are mutually exclusive.
|
||||
* remove() is invoked during rmmod & shutdown() during
|
||||
* system reboot/shutdown.
|
||||
*/
|
||||
ath11k_ahb_remove_prepare(ab);
|
||||
|
||||
if (!(test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)))
|
||||
goto free_resources;
|
||||
|
||||
ath11k_core_deinit(ab);
|
||||
|
||||
free_resources:
|
||||
ath11k_ahb_free_resources(ab);
|
||||
}
|
||||
|
||||
static struct platform_driver ath11k_ahb_driver = {
|
||||
.driver = {
|
||||
.name = "ath11k",
|
||||
@ -1131,6 +1286,7 @@ static struct platform_driver ath11k_ahb_driver = {
|
||||
},
|
||||
.probe = ath11k_ahb_probe,
|
||||
.remove = ath11k_ahb_remove,
|
||||
.shutdown = ath11k_ahb_shutdown,
|
||||
};
|
||||
|
||||
static int ath11k_ahb_init(void)
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef ATH11K_AHB_H
|
||||
#define ATH11K_AHB_H
|
||||
@ -8,6 +9,16 @@
|
||||
#include "core.h"
|
||||
|
||||
#define ATH11K_AHB_RECOVERY_TIMEOUT (3 * HZ)
|
||||
|
||||
#define ATH11K_AHB_SMP2P_SMEM_MSG GENMASK(15, 0)
|
||||
#define ATH11K_AHB_SMP2P_SMEM_SEQ_NO GENMASK(31, 16)
|
||||
#define ATH11K_AHB_SMP2P_SMEM_VALUE_MASK 0xFFFFFFFF
|
||||
|
||||
enum ath11k_ahb_smp2p_msg_id {
|
||||
ATH11K_AHB_POWER_SAVE_ENTER = 1,
|
||||
ATH11K_AHB_POWER_SAVE_EXIT,
|
||||
};
|
||||
|
||||
struct ath11k_base;
|
||||
|
||||
struct ath11k_ahb {
|
||||
@ -21,6 +32,11 @@ struct ath11k_ahb {
|
||||
u32 ce_size;
|
||||
bool use_tz;
|
||||
} fw;
|
||||
struct {
|
||||
unsigned short seq_no;
|
||||
unsigned int smem_bit;
|
||||
struct qcom_smem_state *smem_state;
|
||||
} smp2p_info;
|
||||
};
|
||||
|
||||
static inline struct ath11k_ahb *ath11k_ahb_priv(struct ath11k_base *ab)
|
||||
|
@ -250,7 +250,7 @@ const struct ce_attr ath11k_host_ce_config_qcn9074[] = {
|
||||
|
||||
static bool ath11k_ce_need_shadow_fix(int ce_id)
|
||||
{
|
||||
/* only ce4 needs shadow workaroud*/
|
||||
/* only ce4 needs shadow workaround */
|
||||
if (ce_id == 4)
|
||||
return true;
|
||||
return false;
|
||||
@ -1042,7 +1042,7 @@ int ath11k_ce_alloc_pipes(struct ath11k_base *ab)
|
||||
|
||||
ret = ath11k_ce_alloc_pipe(ab, i);
|
||||
if (ret) {
|
||||
/* Free any parial successful allocation */
|
||||
/* Free any partial successful allocation */
|
||||
ath11k_ce_free_pipes(ab);
|
||||
return ret;
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.summary_pad_sz = 0,
|
||||
.fft_hdr_len = 16,
|
||||
.max_fft_bins = 512,
|
||||
.fragment_160mhz = true,
|
||||
},
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
@ -81,6 +82,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.idle_ps = false,
|
||||
.supports_sta_ps = false,
|
||||
.cold_boot_calib = true,
|
||||
.cbcal_restart_fw = true,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_peers = 512,
|
||||
@ -106,6 +108,13 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.hybrid_bus_type = false,
|
||||
.fixed_fw_mem = false,
|
||||
.support_off_channel_tx = false,
|
||||
.supports_multi_bssid = false,
|
||||
|
||||
.sram_dump = {},
|
||||
|
||||
.tcl_ring_retry = true,
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
},
|
||||
{
|
||||
.hw_rev = ATH11K_HW_IPQ6018_HW10,
|
||||
@ -141,6 +150,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.summary_pad_sz = 0,
|
||||
.fft_hdr_len = 16,
|
||||
.max_fft_bins = 512,
|
||||
.fragment_160mhz = true,
|
||||
},
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
@ -152,6 +162,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.idle_ps = false,
|
||||
.supports_sta_ps = false,
|
||||
.cold_boot_calib = true,
|
||||
.cbcal_restart_fw = true,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_peers = 512,
|
||||
@ -177,6 +188,13 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.hybrid_bus_type = false,
|
||||
.fixed_fw_mem = false,
|
||||
.support_off_channel_tx = false,
|
||||
.supports_multi_bssid = false,
|
||||
|
||||
.sram_dump = {},
|
||||
|
||||
.tcl_ring_retry = true,
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
},
|
||||
{
|
||||
.name = "qca6390 hw2.0",
|
||||
@ -212,6 +230,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.summary_pad_sz = 0,
|
||||
.fft_hdr_len = 0,
|
||||
.max_fft_bins = 0,
|
||||
.fragment_160mhz = false,
|
||||
},
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
@ -222,6 +241,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.idle_ps = true,
|
||||
.supports_sta_ps = true,
|
||||
.cold_boot_calib = false,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_peers = 512,
|
||||
@ -247,6 +267,16 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.hybrid_bus_type = false,
|
||||
.fixed_fw_mem = false,
|
||||
.support_off_channel_tx = true,
|
||||
.supports_multi_bssid = true,
|
||||
|
||||
.sram_dump = {
|
||||
.start = 0x01400000,
|
||||
.end = 0x0171ffff,
|
||||
},
|
||||
|
||||
.tcl_ring_retry = true,
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
},
|
||||
{
|
||||
.name = "qcn9074 hw1.0",
|
||||
@ -281,6 +311,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.summary_pad_sz = 16,
|
||||
.fft_hdr_len = 24,
|
||||
.max_fft_bins = 1024,
|
||||
.fragment_160mhz = false,
|
||||
},
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
@ -292,6 +323,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.idle_ps = false,
|
||||
.supports_sta_ps = false,
|
||||
.cold_boot_calib = false,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 2,
|
||||
.num_vdevs = 8,
|
||||
.num_peers = 128,
|
||||
@ -317,6 +349,13 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.hybrid_bus_type = false,
|
||||
.fixed_fw_mem = false,
|
||||
.support_off_channel_tx = false,
|
||||
.supports_multi_bssid = false,
|
||||
|
||||
.sram_dump = {},
|
||||
|
||||
.tcl_ring_retry = true,
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
},
|
||||
{
|
||||
.name = "wcn6855 hw2.0",
|
||||
@ -352,6 +391,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.summary_pad_sz = 0,
|
||||
.fft_hdr_len = 0,
|
||||
.max_fft_bins = 0,
|
||||
.fragment_160mhz = false,
|
||||
},
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
@ -362,6 +402,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.idle_ps = true,
|
||||
.supports_sta_ps = true,
|
||||
.cold_boot_calib = false,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_peers = 512,
|
||||
@ -387,6 +428,16 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.hybrid_bus_type = false,
|
||||
.fixed_fw_mem = false,
|
||||
.support_off_channel_tx = true,
|
||||
.supports_multi_bssid = true,
|
||||
|
||||
.sram_dump = {
|
||||
.start = 0x01400000,
|
||||
.end = 0x0177ffff,
|
||||
},
|
||||
|
||||
.tcl_ring_retry = true,
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
},
|
||||
{
|
||||
.name = "wcn6855 hw2.1",
|
||||
@ -422,6 +473,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.summary_pad_sz = 0,
|
||||
.fft_hdr_len = 0,
|
||||
.max_fft_bins = 0,
|
||||
.fragment_160mhz = false,
|
||||
},
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
@ -431,6 +483,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.idle_ps = true,
|
||||
.supports_sta_ps = true,
|
||||
.cold_boot_calib = false,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_peers = 512,
|
||||
@ -456,6 +509,16 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.hybrid_bus_type = false,
|
||||
.fixed_fw_mem = false,
|
||||
.support_off_channel_tx = true,
|
||||
.supports_multi_bssid = true,
|
||||
|
||||
.sram_dump = {
|
||||
.start = 0x01400000,
|
||||
.end = 0x0177ffff,
|
||||
},
|
||||
|
||||
.tcl_ring_retry = true,
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
},
|
||||
{
|
||||
.name = "wcn6750 hw1.0",
|
||||
@ -468,7 +531,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.max_radios = 1,
|
||||
.bdf_addr = 0x4B0C0000,
|
||||
.hw_ops = &wcn6750_ops,
|
||||
.ring_mask = &ath11k_hw_ring_mask_qca6390,
|
||||
.ring_mask = &ath11k_hw_ring_mask_wcn6750,
|
||||
.internal_sleep_clock = false,
|
||||
.regs = &wcn6750_regs,
|
||||
.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_WCN6750,
|
||||
@ -491,6 +554,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.summary_pad_sz = 0,
|
||||
.fft_hdr_len = 0,
|
||||
.max_fft_bins = 0,
|
||||
.fragment_160mhz = false,
|
||||
},
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
@ -499,7 +563,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.supports_shadow_regs = true,
|
||||
.idle_ps = true,
|
||||
.supports_sta_ps = true,
|
||||
.cold_boot_calib = false,
|
||||
.cold_boot_calib = true,
|
||||
.cbcal_restart_fw = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_peers = 512,
|
||||
@ -508,8 +573,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.supports_regdb = true,
|
||||
.fix_l1ss = false,
|
||||
.credit_flow = true,
|
||||
.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
|
||||
.hal_params = &ath11k_hw_hal_params_qca6390,
|
||||
.max_tx_ring = DP_TCL_NUM_RING_MAX,
|
||||
.hal_params = &ath11k_hw_hal_params_wcn6750,
|
||||
.supports_dynamic_smps_6ghz = false,
|
||||
.alloc_cacheable_memory = false,
|
||||
.supports_rssi_stats = true,
|
||||
@ -524,7 +589,14 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.static_window_map = true,
|
||||
.hybrid_bus_type = true,
|
||||
.fixed_fw_mem = true,
|
||||
.support_off_channel_tx = false,
|
||||
.support_off_channel_tx = true,
|
||||
.supports_multi_bssid = true,
|
||||
|
||||
.sram_dump = {},
|
||||
|
||||
.tcl_ring_retry = false,
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE_WCN6750,
|
||||
.smp2p_wow_exit = true,
|
||||
},
|
||||
};
|
||||
|
||||
@ -535,6 +607,52 @@ static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base
|
||||
return &ab->pdevs[0];
|
||||
}
|
||||
|
||||
void ath11k_fw_stats_pdevs_free(struct list_head *head)
|
||||
{
|
||||
struct ath11k_fw_stats_pdev *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
void ath11k_fw_stats_vdevs_free(struct list_head *head)
|
||||
{
|
||||
struct ath11k_fw_stats_vdev *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
void ath11k_fw_stats_bcn_free(struct list_head *head)
|
||||
{
|
||||
struct ath11k_fw_stats_bcn *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
void ath11k_fw_stats_init(struct ath11k *ar)
|
||||
{
|
||||
INIT_LIST_HEAD(&ar->fw_stats.pdevs);
|
||||
INIT_LIST_HEAD(&ar->fw_stats.vdevs);
|
||||
INIT_LIST_HEAD(&ar->fw_stats.bcn);
|
||||
|
||||
init_completion(&ar->fw_stats_complete);
|
||||
}
|
||||
|
||||
void ath11k_fw_stats_free(struct ath11k_fw_stats *stats)
|
||||
{
|
||||
ath11k_fw_stats_pdevs_free(&stats->pdevs);
|
||||
ath11k_fw_stats_vdevs_free(&stats->vdevs);
|
||||
ath11k_fw_stats_bcn_free(&stats->bcn);
|
||||
}
|
||||
|
||||
int ath11k_core_suspend(struct ath11k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
@ -1544,7 +1662,7 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
|
||||
ar->state_11d = ATH11K_11D_IDLE;
|
||||
complete(&ar->completed_11d_scan);
|
||||
complete(&ar->scan.started);
|
||||
complete(&ar->scan.completed);
|
||||
complete_all(&ar->scan.completed);
|
||||
complete(&ar->scan.on_channel);
|
||||
complete(&ar->peer_assoc_done);
|
||||
complete(&ar->peer_delete_done);
|
||||
@ -1563,6 +1681,8 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
|
||||
|
||||
wake_up(&ab->wmi_ab.tx_credits_wq);
|
||||
wake_up(&ab->peer_mapping_wq);
|
||||
|
||||
reinit_completion(&ab->driver_recovery);
|
||||
}
|
||||
|
||||
static void ath11k_core_post_reconfigure_recovery(struct ath11k_base *ab)
|
||||
|
@ -498,6 +498,13 @@ struct ath11k_sta {
|
||||
|
||||
bool use_4addr_set;
|
||||
u16 tcl_metadata;
|
||||
|
||||
/* Protected with ar->data_lock */
|
||||
enum ath11k_wmi_peer_ps_state peer_ps_state;
|
||||
u64 ps_start_time;
|
||||
u64 ps_start_jiffies;
|
||||
u64 ps_total_duration;
|
||||
bool peer_current_ps_valid;
|
||||
};
|
||||
|
||||
#define ATH11K_MIN_5G_FREQ 4150
|
||||
@ -545,9 +552,6 @@ struct ath11k_debug {
|
||||
struct dentry *debugfs_pdev;
|
||||
struct ath11k_dbg_htt_stats htt_stats;
|
||||
u32 extd_tx_stats;
|
||||
struct ath11k_fw_stats fw_stats;
|
||||
struct completion fw_stats_complete;
|
||||
bool fw_stats_done;
|
||||
u32 extd_rx_stats;
|
||||
u32 pktlog_filter;
|
||||
u32 pktlog_mode;
|
||||
@ -710,6 +714,13 @@ struct ath11k {
|
||||
u8 twt_enabled;
|
||||
bool nlo_enabled;
|
||||
u8 alpha2[REG_ALPHA2_LEN + 1];
|
||||
struct ath11k_fw_stats fw_stats;
|
||||
struct completion fw_stats_complete;
|
||||
bool fw_stats_done;
|
||||
|
||||
/* protected by conf_mutex */
|
||||
bool ps_state_enable;
|
||||
bool ps_timekeeper_enable;
|
||||
};
|
||||
|
||||
struct ath11k_band_cap {
|
||||
@ -887,7 +898,7 @@ struct ath11k_base {
|
||||
|
||||
/* Below regd's are protected by ab->data_lock */
|
||||
/* This is the regd set for every radio
|
||||
* by the firmware during initializatin
|
||||
* by the firmware during initialization
|
||||
*/
|
||||
struct ieee80211_regdomain *default_regd[MAX_RADIOS];
|
||||
/* This regd is set during dynamic country setting
|
||||
@ -1112,6 +1123,12 @@ struct ath11k_fw_stats_bcn {
|
||||
u32 tx_bcn_outage_cnt;
|
||||
};
|
||||
|
||||
void ath11k_fw_stats_init(struct ath11k *ar);
|
||||
void ath11k_fw_stats_pdevs_free(struct list_head *head);
|
||||
void ath11k_fw_stats_vdevs_free(struct list_head *head);
|
||||
void ath11k_fw_stats_bcn_free(struct list_head *head);
|
||||
void ath11k_fw_stats_free(struct ath11k_fw_stats *stats);
|
||||
|
||||
extern const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq8074[];
|
||||
extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq8074[];
|
||||
extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq6018[];
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "dp_tx.h"
|
||||
#include "debugfs_htt_stats.h"
|
||||
#include "peer.h"
|
||||
#include "hif.h"
|
||||
|
||||
static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
|
||||
"REO2SW1_RING",
|
||||
@ -91,91 +92,35 @@ void ath11k_debugfs_add_dbring_entry(struct ath11k *ar,
|
||||
spin_unlock_bh(&dbr_data->lock);
|
||||
}
|
||||
|
||||
static void ath11k_fw_stats_pdevs_free(struct list_head *head)
|
||||
{
|
||||
struct ath11k_fw_stats_pdev *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_fw_stats_vdevs_free(struct list_head *head)
|
||||
{
|
||||
struct ath11k_fw_stats_vdev *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_fw_stats_bcn_free(struct list_head *head)
|
||||
{
|
||||
struct ath11k_fw_stats_bcn *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar)
|
||||
{
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->debug.fw_stats_done = false;
|
||||
ath11k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
|
||||
ath11k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
|
||||
ar->fw_stats_done = false;
|
||||
ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
|
||||
ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats)
|
||||
{
|
||||
struct ath11k_fw_stats stats = {};
|
||||
struct ath11k *ar;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_pdev *pdev;
|
||||
bool is_end;
|
||||
static unsigned int num_vdev, num_bcn;
|
||||
size_t total_vdevs_started = 0;
|
||||
int i, ret;
|
||||
int i;
|
||||
|
||||
INIT_LIST_HEAD(&stats.pdevs);
|
||||
INIT_LIST_HEAD(&stats.vdevs);
|
||||
INIT_LIST_HEAD(&stats.bcn);
|
||||
/* WMI_REQUEST_PDEV_STAT request has been already processed */
|
||||
|
||||
ret = ath11k_wmi_pull_fw_stats(ab, skb, &stats);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to pull fw stats: %d\n", ret);
|
||||
goto free;
|
||||
if (stats->stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
|
||||
ar->fw_stats_done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
ar = ath11k_mac_get_ar_by_pdev_id(ab, stats.pdev_id);
|
||||
if (!ar) {
|
||||
rcu_read_unlock();
|
||||
ath11k_warn(ab, "failed to get ar for pdev_id %d: %d\n",
|
||||
stats.pdev_id, ret);
|
||||
goto free;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
|
||||
list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
|
||||
ar->debug.fw_stats_done = true;
|
||||
goto complete;
|
||||
}
|
||||
|
||||
if (stats.stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
|
||||
ar->debug.fw_stats_done = true;
|
||||
goto complete;
|
||||
}
|
||||
|
||||
if (stats.stats_id == WMI_REQUEST_VDEV_STAT) {
|
||||
if (list_empty(&stats.vdevs)) {
|
||||
if (stats->stats_id == WMI_REQUEST_VDEV_STAT) {
|
||||
if (list_empty(&stats->vdevs)) {
|
||||
ath11k_warn(ab, "empty vdev stats");
|
||||
goto complete;
|
||||
return;
|
||||
}
|
||||
/* FW sends all the active VDEV stats irrespective of PDEV,
|
||||
* hence limit until the count of all VDEVs started
|
||||
@ -188,43 +133,34 @@ void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb
|
||||
|
||||
is_end = ((++num_vdev) == total_vdevs_started);
|
||||
|
||||
list_splice_tail_init(&stats.vdevs,
|
||||
&ar->debug.fw_stats.vdevs);
|
||||
list_splice_tail_init(&stats->vdevs,
|
||||
&ar->fw_stats.vdevs);
|
||||
|
||||
if (is_end) {
|
||||
ar->debug.fw_stats_done = true;
|
||||
ar->fw_stats_done = true;
|
||||
num_vdev = 0;
|
||||
}
|
||||
goto complete;
|
||||
return;
|
||||
}
|
||||
|
||||
if (stats.stats_id == WMI_REQUEST_BCN_STAT) {
|
||||
if (list_empty(&stats.bcn)) {
|
||||
if (stats->stats_id == WMI_REQUEST_BCN_STAT) {
|
||||
if (list_empty(&stats->bcn)) {
|
||||
ath11k_warn(ab, "empty bcn stats");
|
||||
goto complete;
|
||||
return;
|
||||
}
|
||||
/* Mark end until we reached the count of all started VDEVs
|
||||
* within the PDEV
|
||||
*/
|
||||
is_end = ((++num_bcn) == ar->num_started_vdevs);
|
||||
|
||||
list_splice_tail_init(&stats.bcn,
|
||||
&ar->debug.fw_stats.bcn);
|
||||
list_splice_tail_init(&stats->bcn,
|
||||
&ar->fw_stats.bcn);
|
||||
|
||||
if (is_end) {
|
||||
ar->debug.fw_stats_done = true;
|
||||
ar->fw_stats_done = true;
|
||||
num_bcn = 0;
|
||||
}
|
||||
}
|
||||
complete:
|
||||
complete(&ar->debug.fw_stats_complete);
|
||||
rcu_read_unlock();
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
free:
|
||||
ath11k_fw_stats_pdevs_free(&stats.pdevs);
|
||||
ath11k_fw_stats_vdevs_free(&stats.vdevs);
|
||||
ath11k_fw_stats_bcn_free(&stats.bcn);
|
||||
}
|
||||
|
||||
static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
|
||||
@ -245,7 +181,7 @@ static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
|
||||
|
||||
ath11k_debugfs_fw_stats_reset(ar);
|
||||
|
||||
reinit_completion(&ar->debug.fw_stats_complete);
|
||||
reinit_completion(&ar->fw_stats_complete);
|
||||
|
||||
ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
|
||||
|
||||
@ -255,9 +191,8 @@ static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
|
||||
return ret;
|
||||
}
|
||||
|
||||
time_left =
|
||||
wait_for_completion_timeout(&ar->debug.fw_stats_complete,
|
||||
1 * HZ);
|
||||
time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ);
|
||||
|
||||
if (!time_left)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
@ -266,7 +201,7 @@ static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
|
||||
break;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
if (ar->debug.fw_stats_done) {
|
||||
if (ar->fw_stats_done) {
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
break;
|
||||
}
|
||||
@ -338,8 +273,7 @@ static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
|
||||
buf);
|
||||
ath11k_wmi_fw_stats_fill(ar, &ar->fw_stats, req_param.stats_id, buf);
|
||||
|
||||
file->private_data = buf;
|
||||
|
||||
@ -410,8 +344,7 @@ static int ath11k_open_vdev_stats(struct inode *inode, struct file *file)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
|
||||
buf);
|
||||
ath11k_wmi_fw_stats_fill(ar, &ar->fw_stats, req_param.stats_id, buf);
|
||||
|
||||
file->private_data = buf;
|
||||
|
||||
@ -488,14 +421,13 @@ static int ath11k_open_bcn_stats(struct inode *inode, struct file *file)
|
||||
}
|
||||
}
|
||||
|
||||
ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
|
||||
buf);
|
||||
ath11k_wmi_fw_stats_fill(ar, &ar->fw_stats, req_param.stats_id, buf);
|
||||
|
||||
/* since beacon stats request is looped for all active VDEVs, saved fw
|
||||
* stats is not freed for each request until done for all active VDEVs
|
||||
*/
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ath11k_fw_stats_bcn_free(&ar->debug.fw_stats.bcn);
|
||||
ath11k_fw_stats_bcn_free(&ar->fw_stats.bcn);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
file->private_data = buf;
|
||||
@ -982,6 +914,63 @@ static const struct file_operations fops_fw_dbglog = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int ath11k_open_sram_dump(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct ath11k_base *ab = inode->i_private;
|
||||
u8 *buf;
|
||||
u32 start, end;
|
||||
int ret;
|
||||
|
||||
start = ab->hw_params.sram_dump.start;
|
||||
end = ab->hw_params.sram_dump.end;
|
||||
|
||||
buf = vmalloc(end - start + 1);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = ath11k_hif_read(ab, buf, start, end);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to dump sram: %d\n", ret);
|
||||
vfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
file->private_data = buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t ath11k_read_sram_dump(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath11k_base *ab = file->f_inode->i_private;
|
||||
const char *buf = file->private_data;
|
||||
int len;
|
||||
u32 start, end;
|
||||
|
||||
start = ab->hw_params.sram_dump.start;
|
||||
end = ab->hw_params.sram_dump.end;
|
||||
len = end - start + 1;
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static int ath11k_release_sram_dump(struct inode *inode, struct file *file)
|
||||
{
|
||||
vfree(file->private_data);
|
||||
file->private_data = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_sram_dump = {
|
||||
.open = ath11k_open_sram_dump,
|
||||
.read = ath11k_read_sram_dump,
|
||||
.release = ath11k_release_sram_dump,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
|
||||
{
|
||||
if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
|
||||
@ -997,6 +986,10 @@ int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
|
||||
debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
|
||||
&fops_soc_dp_stats);
|
||||
|
||||
if (ab->hw_params.sram_dump.start != 0)
|
||||
debugfs_create_file("sram", 0400, ab->debugfs_soc, ab,
|
||||
&fops_sram_dump);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1025,7 +1018,7 @@ void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
|
||||
struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
|
||||
ar->debug.debugfs_pdev);
|
||||
|
||||
ar->debug.fw_stats.debugfs_fwstats = fwstats_dir;
|
||||
ar->fw_stats.debugfs_fwstats = fwstats_dir;
|
||||
|
||||
/* all stats debugfs files created are under "fw_stats" directory
|
||||
* created per PDEV
|
||||
@ -1036,12 +1029,6 @@ void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
|
||||
&fops_vdev_stats);
|
||||
debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
|
||||
&fops_bcn_stats);
|
||||
|
||||
INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
|
||||
INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
|
||||
INIT_LIST_HEAD(&ar->debug.fw_stats.bcn);
|
||||
|
||||
init_completion(&ar->debug.fw_stats_complete);
|
||||
}
|
||||
|
||||
static ssize_t ath11k_write_pktlog_filter(struct file *file,
|
||||
@ -1382,6 +1369,193 @@ static const struct file_operations fops_dbr_debug = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath11k_write_ps_timekeeper_enable(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath11k *ar = file->private_data;
|
||||
ssize_t ret;
|
||||
u8 ps_timekeeper_enable;
|
||||
|
||||
if (kstrtou8_from_user(user_buf, count, 0, &ps_timekeeper_enable))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH11K_STATE_ON) {
|
||||
ret = -ENETDOWN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!ar->ps_state_enable) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ar->ps_timekeeper_enable = !!ps_timekeeper_enable;
|
||||
ret = count;
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ath11k_read_ps_timekeeper_enable(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath11k *ar = file->private_data;
|
||||
char buf[32];
|
||||
int len;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
len = scnprintf(buf, sizeof(buf), "%d\n", ar->ps_timekeeper_enable);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_ps_timekeeper_enable = {
|
||||
.read = ath11k_read_ps_timekeeper_enable,
|
||||
.write = ath11k_write_ps_timekeeper_enable,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static void ath11k_reset_peer_ps_duration(void *data,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath11k *ar = data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
arsta->ps_total_duration = 0;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
static ssize_t ath11k_write_reset_ps_duration(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath11k *ar = file->private_data;
|
||||
int ret;
|
||||
u8 reset_ps_duration;
|
||||
|
||||
if (kstrtou8_from_user(user_buf, count, 0, &reset_ps_duration))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH11K_STATE_ON) {
|
||||
ret = -ENETDOWN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!ar->ps_state_enable) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ieee80211_iterate_stations_atomic(ar->hw,
|
||||
ath11k_reset_peer_ps_duration,
|
||||
ar);
|
||||
|
||||
ret = count;
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_reset_ps_duration = {
|
||||
.write = ath11k_write_reset_ps_duration,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static void ath11k_peer_ps_state_disable(void *data,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath11k *ar = data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
|
||||
arsta->ps_start_time = 0;
|
||||
arsta->ps_total_duration = 0;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
static ssize_t ath11k_write_ps_state_enable(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath11k *ar = file->private_data;
|
||||
struct ath11k_pdev *pdev = ar->pdev;
|
||||
int ret;
|
||||
u32 param;
|
||||
u8 ps_state_enable;
|
||||
|
||||
if (kstrtou8_from_user(user_buf, count, 0, &ps_state_enable))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ps_state_enable = !!ps_state_enable;
|
||||
|
||||
if (ar->ps_state_enable == ps_state_enable) {
|
||||
ret = count;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
param = WMI_PDEV_PEER_STA_PS_STATECHG_ENABLE;
|
||||
ret = ath11k_wmi_pdev_set_param(ar, param, ps_state_enable, pdev->pdev_id);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to enable ps_state_enable: %d\n",
|
||||
ret);
|
||||
goto exit;
|
||||
}
|
||||
ar->ps_state_enable = ps_state_enable;
|
||||
|
||||
if (!ar->ps_state_enable) {
|
||||
ar->ps_timekeeper_enable = false;
|
||||
ieee80211_iterate_stations_atomic(ar->hw,
|
||||
ath11k_peer_ps_state_disable,
|
||||
ar);
|
||||
}
|
||||
|
||||
ret = count;
|
||||
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ath11k_read_ps_state_enable(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath11k *ar = file->private_data;
|
||||
char buf[32];
|
||||
int len;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
len = scnprintf(buf, sizeof(buf), "%d\n", ar->ps_state_enable);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_ps_state_enable = {
|
||||
.read = ath11k_read_ps_state_enable,
|
||||
.write = ath11k_write_ps_state_enable,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
int ath11k_debugfs_register(struct ath11k *ar)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
@ -1428,6 +1602,20 @@ int ath11k_debugfs_register(struct ath11k *ar)
|
||||
debugfs_create_file("enable_dbr_debug", 0200, ar->debug.debugfs_pdev,
|
||||
ar, &fops_dbr_debug);
|
||||
|
||||
debugfs_create_file("ps_state_enable", 0600, ar->debug.debugfs_pdev, ar,
|
||||
&fops_ps_state_enable);
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
|
||||
ar->ab->wmi_ab.svc_map)) {
|
||||
debugfs_create_file("ps_timekeeper_enable", 0600,
|
||||
ar->debug.debugfs_pdev, ar,
|
||||
&fops_ps_timekeeper_enable);
|
||||
|
||||
debugfs_create_file("reset_ps_duration", 0200,
|
||||
ar->debug.debugfs_pdev, ar,
|
||||
&fops_reset_ps_duration);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1456,11 +1644,13 @@ static ssize_t ath11k_write_twt_add_dialog(struct file *file,
|
||||
{
|
||||
struct ath11k_vif *arvif = file->private_data;
|
||||
struct wmi_twt_add_dialog_params params = { 0 };
|
||||
struct wmi_twt_enable_params twt_params = {0};
|
||||
struct ath11k *ar = arvif->ar;
|
||||
u8 buf[128] = {0};
|
||||
int ret;
|
||||
|
||||
if (arvif->ar->twt_enabled == 0) {
|
||||
ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
|
||||
if (ar->twt_enabled == 0) {
|
||||
ath11k_err(ar->ab, "twt support is not enabled\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
@ -1490,13 +1680,38 @@ static ssize_t ath11k_write_twt_add_dialog(struct file *file,
|
||||
if (ret != 16)
|
||||
return -EINVAL;
|
||||
|
||||
/* In the case of station vif, TWT is entirely handled by
|
||||
* the firmware based on the input parameters in the TWT enable
|
||||
* WMI command that is sent to the target during assoc.
|
||||
* For manually testing the TWT feature, we need to first disable
|
||||
* TWT and send enable command again with TWT input parameter
|
||||
* sta_cong_timer_ms set to 0.
|
||||
*/
|
||||
if (arvif->vif->type == NL80211_IFTYPE_STATION) {
|
||||
ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
|
||||
|
||||
ath11k_wmi_fill_default_twt_params(&twt_params);
|
||||
twt_params.sta_cong_timer_ms = 0;
|
||||
|
||||
ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id, &twt_params);
|
||||
}
|
||||
|
||||
params.vdev_id = arvif->vdev_id;
|
||||
|
||||
ret = ath11k_wmi_send_twt_add_dialog_cmd(arvif->ar, ¶ms);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_twt_add_dialog;
|
||||
|
||||
return count;
|
||||
|
||||
err_twt_add_dialog:
|
||||
if (arvif->vif->type == NL80211_IFTYPE_STATION) {
|
||||
ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
|
||||
ath11k_wmi_fill_default_twt_params(&twt_params);
|
||||
ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id, &twt_params);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ath11k_write_twt_del_dialog(struct file *file,
|
||||
@ -1505,11 +1720,13 @@ static ssize_t ath11k_write_twt_del_dialog(struct file *file,
|
||||
{
|
||||
struct ath11k_vif *arvif = file->private_data;
|
||||
struct wmi_twt_del_dialog_params params = { 0 };
|
||||
struct wmi_twt_enable_params twt_params = {0};
|
||||
struct ath11k *ar = arvif->ar;
|
||||
u8 buf[64] = {0};
|
||||
int ret;
|
||||
|
||||
if (arvif->ar->twt_enabled == 0) {
|
||||
ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
|
||||
if (ar->twt_enabled == 0) {
|
||||
ath11k_err(ar->ab, "twt support is not enabled\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
@ -1535,6 +1752,12 @@ static ssize_t ath11k_write_twt_del_dialog(struct file *file,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (arvif->vif->type == NL80211_IFTYPE_STATION) {
|
||||
ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
|
||||
ath11k_wmi_fill_default_twt_params(&twt_params);
|
||||
ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id, &twt_params);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -1638,36 +1861,35 @@ static const struct file_operations ath11k_fops_twt_resume_dialog = {
|
||||
.open = simple_open
|
||||
};
|
||||
|
||||
int ath11k_debugfs_add_interface(struct ath11k_vif *arvif)
|
||||
void ath11k_debugfs_add_interface(struct ath11k_vif *arvif)
|
||||
{
|
||||
if (arvif->vif->type == NL80211_IFTYPE_AP && !arvif->debugfs_twt) {
|
||||
arvif->debugfs_twt = debugfs_create_dir("twt",
|
||||
arvif->vif->debugfs_dir);
|
||||
if (!arvif->debugfs_twt || IS_ERR(arvif->debugfs_twt)) {
|
||||
ath11k_warn(arvif->ar->ab,
|
||||
"failed to create directory %p\n",
|
||||
arvif->debugfs_twt);
|
||||
arvif->debugfs_twt = NULL;
|
||||
return -1;
|
||||
}
|
||||
struct ath11k_base *ab = arvif->ar->ab;
|
||||
|
||||
debugfs_create_file("add_dialog", 0200, arvif->debugfs_twt,
|
||||
arvif, &ath11k_fops_twt_add_dialog);
|
||||
if (arvif->vif->type != NL80211_IFTYPE_AP &&
|
||||
!(arvif->vif->type == NL80211_IFTYPE_STATION &&
|
||||
test_bit(WMI_TLV_SERVICE_STA_TWT, ab->wmi_ab.svc_map)))
|
||||
return;
|
||||
|
||||
debugfs_create_file("del_dialog", 0200, arvif->debugfs_twt,
|
||||
arvif, &ath11k_fops_twt_del_dialog);
|
||||
arvif->debugfs_twt = debugfs_create_dir("twt",
|
||||
arvif->vif->debugfs_dir);
|
||||
debugfs_create_file("add_dialog", 0200, arvif->debugfs_twt,
|
||||
arvif, &ath11k_fops_twt_add_dialog);
|
||||
|
||||
debugfs_create_file("pause_dialog", 0200, arvif->debugfs_twt,
|
||||
arvif, &ath11k_fops_twt_pause_dialog);
|
||||
debugfs_create_file("del_dialog", 0200, arvif->debugfs_twt,
|
||||
arvif, &ath11k_fops_twt_del_dialog);
|
||||
|
||||
debugfs_create_file("resume_dialog", 0200, arvif->debugfs_twt,
|
||||
arvif, &ath11k_fops_twt_resume_dialog);
|
||||
}
|
||||
return 0;
|
||||
debugfs_create_file("pause_dialog", 0200, arvif->debugfs_twt,
|
||||
arvif, &ath11k_fops_twt_pause_dialog);
|
||||
|
||||
debugfs_create_file("resume_dialog", 0200, arvif->debugfs_twt,
|
||||
arvif, &ath11k_fops_twt_resume_dialog);
|
||||
}
|
||||
|
||||
void ath11k_debugfs_remove_interface(struct ath11k_vif *arvif)
|
||||
{
|
||||
if (!arvif->debugfs_twt)
|
||||
return;
|
||||
|
||||
debugfs_remove_recursive(arvif->debugfs_twt);
|
||||
arvif->debugfs_twt = NULL;
|
||||
}
|
||||
|
@ -269,7 +269,7 @@ int ath11k_debugfs_pdev_create(struct ath11k_base *ab);
|
||||
void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab);
|
||||
int ath11k_debugfs_register(struct ath11k *ar);
|
||||
void ath11k_debugfs_unregister(struct ath11k *ar);
|
||||
void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb);
|
||||
void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats);
|
||||
|
||||
void ath11k_debugfs_fw_stats_init(struct ath11k *ar);
|
||||
int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
|
||||
@ -306,7 +306,7 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar)
|
||||
return ar->debug.rx_filter;
|
||||
}
|
||||
|
||||
int ath11k_debugfs_add_interface(struct ath11k_vif *arvif);
|
||||
void ath11k_debugfs_add_interface(struct ath11k_vif *arvif);
|
||||
void ath11k_debugfs_remove_interface(struct ath11k_vif *arvif);
|
||||
void ath11k_debugfs_add_dbring_entry(struct ath11k *ar,
|
||||
enum wmi_direct_buffer_module id,
|
||||
@ -341,8 +341,8 @@ static inline void ath11k_debugfs_unregister(struct ath11k *ar)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
static inline void ath11k_debugfs_fw_stats_process(struct ath11k *ar,
|
||||
struct ath11k_fw_stats *stats)
|
||||
{
|
||||
}
|
||||
|
||||
@ -386,9 +386,8 @@ static inline int ath11k_debugfs_get_fw_stats(struct ath11k *ar,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ath11k_debugfs_add_interface(struct ath11k_vif *arvif)
|
||||
static inline void ath11k_debugfs_add_interface(struct ath11k_vif *arvif)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath11k_debugfs_remove_interface(struct ath11k_vif *arvif)
|
||||
|
@ -630,7 +630,7 @@ struct htt_tx_hwq_tried_mpdu_cnt_hist_tlv_v {
|
||||
* completing the burst, we identify the txop used in the burst and
|
||||
* incr the corresponding bin.
|
||||
* Each bin represents 1ms & we have 10 bins in this histogram.
|
||||
* they are deined in FW using the following macros
|
||||
* they are defined in FW using the following macros
|
||||
* #define WAL_MAX_TXOP_USED_CNT_HISTOGRAM 10
|
||||
* #define WAL_TXOP_USED_HISTOGRAM_INTERVAL 1000 ( 1 ms )
|
||||
*/
|
||||
@ -1897,7 +1897,7 @@ struct htt_phy_counters_tlv {
|
||||
u32 phytx_abort_cnt;
|
||||
/* number of times rx abort initiated by phy */
|
||||
u32 phyrx_abort_cnt;
|
||||
/* number of rx defered count initiated by phy */
|
||||
/* number of rx deferred count initiated by phy */
|
||||
u32 phyrx_defer_abort_cnt;
|
||||
/* number of sizing events generated at LSTF */
|
||||
u32 rx_gain_adj_lstf_event_cnt;
|
||||
|
@ -751,6 +751,102 @@ static const struct file_operations fops_htt_peer_stats_reset = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath11k_dbg_sta_read_peer_ps_state(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
char buf[20];
|
||||
int len;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
len = scnprintf(buf, sizeof(buf), "%d\n", arsta->peer_ps_state);
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_peer_ps_state = {
|
||||
.open = simple_open,
|
||||
.read = ath11k_dbg_sta_read_peer_ps_state,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath11k_dbg_sta_read_current_ps_duration(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
u64 time_since_station_in_power_save;
|
||||
char buf[20];
|
||||
int len;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON &&
|
||||
arsta->peer_current_ps_valid)
|
||||
time_since_station_in_power_save = jiffies_to_msecs(jiffies
|
||||
- arsta->ps_start_jiffies);
|
||||
else
|
||||
time_since_station_in_power_save = 0;
|
||||
|
||||
len = scnprintf(buf, sizeof(buf), "%llu\n",
|
||||
time_since_station_in_power_save);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_current_ps_duration = {
|
||||
.open = simple_open,
|
||||
.read = ath11k_dbg_sta_read_current_ps_duration,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath11k_dbg_sta_read_total_ps_duration(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
char buf[20];
|
||||
u64 power_save_duration;
|
||||
int len;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON &&
|
||||
arsta->peer_current_ps_valid)
|
||||
power_save_duration = jiffies_to_msecs(jiffies
|
||||
- arsta->ps_start_jiffies)
|
||||
+ arsta->ps_total_duration;
|
||||
else
|
||||
power_save_duration = arsta->ps_total_duration;
|
||||
|
||||
len = scnprintf(buf, sizeof(buf), "%llu\n", power_save_duration);
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_total_ps_duration = {
|
||||
.open = simple_open,
|
||||
.read = ath11k_dbg_sta_read_total_ps_duration,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct dentry *dir)
|
||||
{
|
||||
@ -778,4 +874,15 @@ void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vi
|
||||
ar->ab->wmi_ab.svc_map))
|
||||
debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta,
|
||||
&fops_htt_peer_stats_reset);
|
||||
|
||||
debugfs_create_file("peer_ps_state", 0400, dir, sta,
|
||||
&fops_peer_ps_state);
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
|
||||
ar->ab->wmi_ab.svc_map)) {
|
||||
debugfs_create_file("current_ps_duration", 0440, dir, sta,
|
||||
&fops_current_ps_duration);
|
||||
debugfs_create_file("total_ps_duration", 0440, dir, sta,
|
||||
&fops_total_ps_duration);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <crypto/hash.h>
|
||||
@ -131,13 +132,11 @@ static int ath11k_dp_srng_calculate_msi_group(struct ath11k_base *ab,
|
||||
|
||||
switch (type) {
|
||||
case HAL_WBM2SW_RELEASE:
|
||||
if (ring_num < 3) {
|
||||
grp_mask = &ab->hw_params.ring_mask->tx[0];
|
||||
} else if (ring_num == 3) {
|
||||
if (ring_num == DP_RX_RELEASE_RING_NUM) {
|
||||
grp_mask = &ab->hw_params.ring_mask->rx_wbm_rel[0];
|
||||
ring_num = 0;
|
||||
} else {
|
||||
return -ENOENT;
|
||||
grp_mask = &ab->hw_params.ring_mask->tx[0];
|
||||
}
|
||||
break;
|
||||
case HAL_REO_EXCEPTION:
|
||||
@ -371,6 +370,7 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab)
|
||||
struct ath11k_dp *dp = &ab->dp;
|
||||
struct hal_srng *srng;
|
||||
int i, ret;
|
||||
u8 tcl_num, wbm_num;
|
||||
|
||||
ret = ath11k_dp_srng_setup(ab, &dp->wbm_desc_rel_ring,
|
||||
HAL_SW2WBM_RELEASE, 0, 0,
|
||||
@ -396,9 +396,12 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab)
|
||||
}
|
||||
|
||||
for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
|
||||
tcl_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].tcl_ring_num;
|
||||
wbm_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num;
|
||||
|
||||
ret = ath11k_dp_srng_setup(ab, &dp->tx_ring[i].tcl_data_ring,
|
||||
HAL_TCL_DATA, i, 0,
|
||||
DP_TCL_DATA_RING_SIZE);
|
||||
HAL_TCL_DATA, tcl_num, 0,
|
||||
ab->hw_params.tx_ring_size);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set up tcl_data ring (%d) :%d\n",
|
||||
i, ret);
|
||||
@ -406,7 +409,7 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab)
|
||||
}
|
||||
|
||||
ret = ath11k_dp_srng_setup(ab, &dp->tx_ring[i].tcl_comp_ring,
|
||||
HAL_WBM2SW_RELEASE, i, 0,
|
||||
HAL_WBM2SW_RELEASE, wbm_num, 0,
|
||||
DP_TX_COMP_RING_SIZE);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set up tcl_comp ring (%d) :%d\n",
|
||||
@ -431,7 +434,7 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab)
|
||||
}
|
||||
|
||||
ret = ath11k_dp_srng_setup(ab, &dp->rx_rel_ring, HAL_WBM2SW_RELEASE,
|
||||
3, 0, DP_RX_RELEASE_RING_SIZE);
|
||||
DP_RX_RELEASE_RING_NUM, 0, DP_RX_RELEASE_RING_SIZE);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set up rx_rel ring :%d\n", ret);
|
||||
goto err;
|
||||
@ -774,9 +777,10 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
|
||||
int i, j;
|
||||
int tot_work_done = 0;
|
||||
|
||||
if (ab->hw_params.ring_mask->tx[grp_id]) {
|
||||
i = __fls(ab->hw_params.ring_mask->tx[grp_id]);
|
||||
ath11k_dp_tx_completion_handler(ab, i);
|
||||
for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
|
||||
if (BIT(ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num) &
|
||||
ab->hw_params.ring_mask->tx[grp_id])
|
||||
ath11k_dp_tx_completion_handler(ab, i);
|
||||
}
|
||||
|
||||
if (ab->hw_params.ring_mask->rx_err[grp_id]) {
|
||||
@ -963,7 +967,7 @@ static void ath11k_dp_update_vdev_search(struct ath11k_vif *arvif)
|
||||
{
|
||||
/* When v2_map_support is true:for STA mode, enable address
|
||||
* search index, tcl uses ast_hash value in the descriptor.
|
||||
* When v2_map_support is false: for STA mode, dont' enable
|
||||
* When v2_map_support is false: for STA mode, don't enable
|
||||
* address search index.
|
||||
*/
|
||||
switch (arvif->vdev_type) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH11K_DP_H
|
||||
@ -203,6 +204,7 @@ struct ath11k_pdev_dp {
|
||||
|
||||
#define DP_WBM_RELEASE_RING_SIZE 64
|
||||
#define DP_TCL_DATA_RING_SIZE 512
|
||||
#define DP_TCL_DATA_RING_SIZE_WCN6750 2048
|
||||
#define DP_TX_COMP_RING_SIZE 32768
|
||||
#define DP_TX_IDR_SIZE DP_TX_COMP_RING_SIZE
|
||||
#define DP_TCL_CMD_RING_SIZE 32
|
||||
@ -222,6 +224,8 @@ struct ath11k_pdev_dp {
|
||||
#define DP_RXDMA_MONITOR_DST_RING_SIZE 2048
|
||||
#define DP_RXDMA_MONITOR_DESC_RING_SIZE 4096
|
||||
|
||||
#define DP_RX_RELEASE_RING_NUM 3
|
||||
|
||||
#define DP_RX_BUFFER_SIZE 2048
|
||||
#define DP_RX_BUFFER_SIZE_LITE 1024
|
||||
#define DP_RX_BUFFER_ALIGN_SIZE 128
|
||||
@ -299,7 +303,7 @@ struct ath11k_dp {
|
||||
|
||||
#define HTT_TX_WBM_COMP_STATUS_OFFSET 8
|
||||
|
||||
/* HTT tx completion is overlayed in wbm_release_ring */
|
||||
/* HTT tx completion is overlaid in wbm_release_ring */
|
||||
#define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(12, 9)
|
||||
#define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13)
|
||||
#define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13)
|
||||
@ -466,7 +470,7 @@ enum htt_srng_ring_id {
|
||||
* 3'b010: 4 usec
|
||||
* 3'b011: 8 usec (default)
|
||||
* 3'b100: 16 usec
|
||||
* Others: Reserverd
|
||||
* Others: Reserved
|
||||
* b'19 - response_required:
|
||||
* Host needs HTT_T2H_MSG_TYPE_SRING_SETUP_DONE as response
|
||||
* b'20:31 - reserved: reserved for future use
|
||||
@ -993,8 +997,7 @@ struct htt_rx_ring_tlv_filter {
|
||||
#define HTT_RX_FULL_MON_MODE_CFG_CMD_CFG_NON_ZERO_MPDUS_END BIT(2)
|
||||
#define HTT_RX_FULL_MON_MODE_CFG_CMD_CFG_RELEASE_RING GENMASK(10, 3)
|
||||
|
||||
/**
|
||||
* Enumeration for full monitor mode destination ring select
|
||||
/* Enumeration for full monitor mode destination ring select
|
||||
* 0 - REO destination ring select
|
||||
* 1 - FW destination ring select
|
||||
* 2 - SW destination ring select
|
||||
@ -1391,8 +1394,7 @@ struct htt_ppdu_stats_info {
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief target -> host packet log message
|
||||
/* @brief target -> host packet log message
|
||||
*
|
||||
* @details
|
||||
* The following field definitions describe the format of the packet log
|
||||
@ -1430,8 +1432,7 @@ struct htt_pktlog_msg {
|
||||
u8 payload[];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief host -> target FW extended statistics retrieve
|
||||
/* @brief host -> target FW extended statistics retrieve
|
||||
*
|
||||
* @details
|
||||
* The following field definitions describe the format of the HTT host
|
||||
@ -1566,8 +1567,7 @@ struct htt_ext_stats_cfg_params {
|
||||
u32 cfg3;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief target -> host extended statistics upload
|
||||
/* @brief target -> host extended statistics upload
|
||||
*
|
||||
* @details
|
||||
* The following field definitions describe the format of the HTT target
|
||||
|
@ -2499,7 +2499,7 @@ static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *nap
|
||||
|
||||
/* PN for multicast packets are not validate in HW,
|
||||
* so skip 802.3 rx path
|
||||
* Also, fast_rx expectes the STA to be authorized, hence
|
||||
* Also, fast_rx expects the STA to be authorized, hence
|
||||
* eapol packets are sent in slow path.
|
||||
*/
|
||||
if (decap == DP_RX_DECAP_TYPE_ETHERNET2_DIX && !is_eapol &&
|
||||
@ -5197,7 +5197,8 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
|
||||
if (log_type != ATH11K_PKTLOG_TYPE_INVALID)
|
||||
trace_ath11k_htt_rxdesc(ar, skb->data, log_type, rx_buf_sz);
|
||||
|
||||
memset(ppdu_info, 0, sizeof(struct hal_rx_mon_ppdu_info));
|
||||
memset(ppdu_info, 0, sizeof(*ppdu_info));
|
||||
ppdu_info->peer_id = HAL_INVALID_PEERID;
|
||||
hal_status = ath11k_hal_rx_parse_mon_status(ab, ppdu_info, skb);
|
||||
|
||||
if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags) &&
|
||||
|
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
@ -93,7 +94,8 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
u8 pool_id;
|
||||
u8 hal_ring_id;
|
||||
int ret;
|
||||
u8 ring_selector = 0, ring_map = 0;
|
||||
u32 ring_selector = 0;
|
||||
u8 ring_map = 0;
|
||||
bool tcl_ring_retry;
|
||||
|
||||
if (unlikely(test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)))
|
||||
@ -105,19 +107,13 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
|
||||
pool_id = skb_get_queue_mapping(skb) & (ATH11K_HW_MAX_QUEUES - 1);
|
||||
|
||||
/* Let the default ring selection be based on current processor
|
||||
* number, where one of the 3 tcl rings are selected based on
|
||||
* the smp_processor_id(). In case that ring
|
||||
* is full/busy, we resort to other available rings.
|
||||
* If all rings are full, we drop the packet.
|
||||
* //TODO Add throttling logic when all rings are full
|
||||
*/
|
||||
ring_selector = smp_processor_id();
|
||||
ring_selector = ab->hw_params.hw_ops->get_ring_selector(skb);
|
||||
|
||||
tcl_ring_sel:
|
||||
tcl_ring_retry = false;
|
||||
|
||||
ti.ring_id = ring_selector % ab->hw_params.max_tx_ring;
|
||||
ti.rbm_id = ab->hw_params.hal_params->tcl2wbm_rbm_map[ti.ring_id].rbm_id;
|
||||
|
||||
ring_map |= BIT(ti.ring_id);
|
||||
|
||||
@ -129,7 +125,8 @@ tcl_ring_sel:
|
||||
spin_unlock_bh(&tx_ring->tx_idr_lock);
|
||||
|
||||
if (unlikely(ret < 0)) {
|
||||
if (ring_map == (BIT(ab->hw_params.max_tx_ring) - 1)) {
|
||||
if (ring_map == (BIT(ab->hw_params.max_tx_ring) - 1) ||
|
||||
!ab->hw_params.tcl_ring_retry) {
|
||||
atomic_inc(&ab->soc_stats.tx_err.misc_fail);
|
||||
return -ENOSPC;
|
||||
}
|
||||
@ -247,7 +244,7 @@ tcl_ring_sel:
|
||||
* Restart ring selection if some rings are not checked yet.
|
||||
*/
|
||||
if (unlikely(ring_map != (BIT(ab->hw_params.max_tx_ring)) - 1) &&
|
||||
ab->hw_params.max_tx_ring > 1) {
|
||||
ab->hw_params.tcl_ring_retry && ab->hw_params.max_tx_ring > 1) {
|
||||
tcl_ring_retry = true;
|
||||
ring_selector++;
|
||||
}
|
||||
@ -755,7 +752,7 @@ int ath11k_dp_tx_send_reo_cmd(struct ath11k_base *ab, struct dp_rx_tid *rx_tid,
|
||||
return 0;
|
||||
|
||||
/* Can this be optimized so that we keep the pending command list only
|
||||
* for tid delete command to free up the resoruce on the command status
|
||||
* for tid delete command to free up the resource on the command status
|
||||
* indication?
|
||||
*/
|
||||
dp_cmd = kzalloc(sizeof(*dp_cmd), GFP_ATOMIC);
|
||||
|
@ -126,7 +126,7 @@ static const struct hal_srng_config hw_srng_config_template[] = {
|
||||
},
|
||||
{ /* WBM2SW_RELEASE */
|
||||
.start_ring_id = HAL_SRNG_RING_ID_WBM2SW0_RELEASE,
|
||||
.max_rings = 4,
|
||||
.max_rings = 5,
|
||||
.entry_size = sizeof(struct hal_wbm_release_ring) >> 2,
|
||||
.lmac_ring = false,
|
||||
.ring_dir = HAL_SRNG_DIR_DST,
|
||||
@ -1164,7 +1164,7 @@ void ath11k_hal_srng_shadow_update_hp_tp(struct ath11k_base *ab,
|
||||
{
|
||||
lockdep_assert_held(&srng->lock);
|
||||
|
||||
/* check whether the ring is emptry. Update the shadow
|
||||
/* check whether the ring is empty. Update the shadow
|
||||
* HP only when then ring isn't empty.
|
||||
*/
|
||||
if (srng->ring_dir == HAL_SRNG_DIR_SRC &&
|
||||
|
@ -243,7 +243,7 @@ struct ath11k_base;
|
||||
#define HAL_WBM0_RELEASE_RING_HP 0x000030c0
|
||||
#define HAL_WBM1_RELEASE_RING_HP 0x000030c8
|
||||
|
||||
/* TCL ring feild mask and offset */
|
||||
/* TCL ring field mask and offset */
|
||||
#define HAL_TCL1_RING_BASE_MSB_RING_SIZE GENMASK(27, 8)
|
||||
#define HAL_TCL1_RING_BASE_MSB_RING_BASE_ADDR_MSB GENMASK(7, 0)
|
||||
#define HAL_TCL1_RING_ID_ENTRY_SIZE GENMASK(7, 0)
|
||||
@ -268,7 +268,7 @@ struct ath11k_base;
|
||||
#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP6 GENMASK(20, 18)
|
||||
#define HAL_TCL1_RING_FIELD_DSCP_TID_MAP7 GENMASK(23, 21)
|
||||
|
||||
/* REO ring feild mask and offset */
|
||||
/* REO ring field mask and offset */
|
||||
#define HAL_REO1_RING_BASE_MSB_RING_SIZE GENMASK(27, 8)
|
||||
#define HAL_REO1_RING_BASE_MSB_RING_BASE_ADDR_MSB GENMASK(7, 0)
|
||||
#define HAL_REO1_RING_ID_RING_ID GENMASK(15, 8)
|
||||
@ -389,6 +389,7 @@ enum hal_srng_ring_id {
|
||||
HAL_SRNG_RING_ID_WBM2SW1_RELEASE,
|
||||
HAL_SRNG_RING_ID_WBM2SW2_RELEASE,
|
||||
HAL_SRNG_RING_ID_WBM2SW3_RELEASE,
|
||||
HAL_SRNG_RING_ID_WBM2SW4_RELEASE,
|
||||
|
||||
HAL_SRNG_RING_ID_UMAC_ID_END = 127,
|
||||
HAL_SRNG_RING_ID_LMAC1_ID_START,
|
||||
@ -450,13 +451,13 @@ enum hal_ring_type {
|
||||
|
||||
/**
|
||||
* enum hal_reo_cmd_type: Enum for REO command type
|
||||
* @CMD_GET_QUEUE_STATS: Get REO queue status/stats
|
||||
* @CMD_FLUSH_QUEUE: Flush all frames in REO queue
|
||||
* @CMD_FLUSH_CACHE: Flush descriptor entries in the cache
|
||||
* @CMD_UNBLOCK_CACHE: Unblock a descriptor's address that was blocked
|
||||
* @HAL_REO_CMD_GET_QUEUE_STATS: Get REO queue status/stats
|
||||
* @HAL_REO_CMD_FLUSH_QUEUE: Flush all frames in REO queue
|
||||
* @HAL_REO_CMD_FLUSH_CACHE: Flush descriptor entries in the cache
|
||||
* @HAL_REO_CMD_UNBLOCK_CACHE: Unblock a descriptor's address that was blocked
|
||||
* earlier with a 'REO_FLUSH_CACHE' command
|
||||
* @CMD_FLUSH_TIMEOUT_LIST: Flush buffers/descriptors from timeout list
|
||||
* @CMD_UPDATE_RX_REO_QUEUE: Update REO queue settings
|
||||
* @HAL_REO_CMD_FLUSH_TIMEOUT_LIST: Flush buffers/descriptors from timeout list
|
||||
* @HAL_REO_CMD_UPDATE_RX_QUEUE: Update REO queue settings
|
||||
*/
|
||||
enum hal_reo_cmd_type {
|
||||
HAL_REO_CMD_GET_QUEUE_STATS = 0,
|
||||
@ -635,7 +636,7 @@ struct hal_srng {
|
||||
} u;
|
||||
};
|
||||
|
||||
/* Interrupt mitigation - Batch threshold in terms of numer of frames */
|
||||
/* Interrupt mitigation - Batch threshold in terms of number of frames */
|
||||
#define HAL_SRNG_INT_BATCH_THRESHOLD_TX 256
|
||||
#define HAL_SRNG_INT_BATCH_THRESHOLD_RX 128
|
||||
#define HAL_SRNG_INT_BATCH_THRESHOLD_OTHER 1
|
||||
@ -678,6 +679,7 @@ enum hal_rx_buf_return_buf_manager {
|
||||
HAL_RX_BUF_RBM_SW1_BM,
|
||||
HAL_RX_BUF_RBM_SW2_BM,
|
||||
HAL_RX_BUF_RBM_SW3_BM,
|
||||
HAL_RX_BUF_RBM_SW4_BM,
|
||||
};
|
||||
|
||||
#define HAL_SRNG_DESC_LOOP_CNT 0xf0000000
|
||||
@ -873,8 +875,7 @@ struct hal_reo_status {
|
||||
} u;
|
||||
};
|
||||
|
||||
/**
|
||||
* HAL context to be used to access SRNG APIs (currently used by data path
|
||||
/* HAL context to be used to access SRNG APIs (currently used by data path
|
||||
* and transport (CE) modules)
|
||||
*/
|
||||
struct ath11k_hal {
|
||||
|
@ -607,7 +607,7 @@ struct rx_msdu_desc {
|
||||
*
|
||||
* msdu_continuation
|
||||
* When set, this MSDU buffer was not able to hold the entire MSDU.
|
||||
* The next buffer will therefor contain additional information
|
||||
* The next buffer will therefore contain additional information
|
||||
* related to this MSDU.
|
||||
*
|
||||
* msdu_length
|
||||
@ -643,7 +643,7 @@ struct rx_msdu_desc {
|
||||
*
|
||||
* da_idx_timeout
|
||||
* Indicates, an unsuccessful MAC destination address search due
|
||||
* to the expiration of search timer fot this MSDU.
|
||||
* to the expiration of search timer for this MSDU.
|
||||
*/
|
||||
|
||||
enum hal_reo_dest_ring_buffer_type {
|
||||
@ -1678,7 +1678,7 @@ struct hal_wbm_release_ring {
|
||||
* Producer: SW/TQM/RXDMA/REO/SWITCH
|
||||
* Consumer: WBM/SW/FW
|
||||
*
|
||||
* HTT tx status is overlayed on wbm_release ring on 4-byte words 2, 3, 4 and 5
|
||||
* HTT tx status is overlaid on wbm_release ring on 4-byte words 2, 3, 4 and 5
|
||||
* for software based completions.
|
||||
*
|
||||
* buf_addr_info
|
||||
@ -2159,7 +2159,7 @@ struct hal_reo_status_hdr {
|
||||
* commands.
|
||||
*
|
||||
* execution_time (in us)
|
||||
* The amount of time REO took to excecute the command. Note that
|
||||
* The amount of time REO took to execute the command. Note that
|
||||
* this time does not include the duration of the command waiting
|
||||
* in the command ring, before the execution started.
|
||||
*
|
||||
|
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "hal_desc.h"
|
||||
@ -44,8 +45,7 @@ void ath11k_hal_tx_cmd_desc_setup(struct ath11k_base *ab, void *cmd,
|
||||
FIELD_PREP(BUFFER_ADDR_INFO1_ADDR,
|
||||
((uint64_t)ti->paddr >> HAL_ADDR_MSB_REG_SHIFT));
|
||||
tcl_cmd->buf_addr_info.info1 |=
|
||||
FIELD_PREP(BUFFER_ADDR_INFO1_RET_BUF_MGR,
|
||||
(ti->ring_id + HAL_RX_BUF_RBM_SW0_BM)) |
|
||||
FIELD_PREP(BUFFER_ADDR_INFO1_RET_BUF_MGR, ti->rbm_id) |
|
||||
FIELD_PREP(BUFFER_ADDR_INFO1_SW_COOKIE, ti->desc_id);
|
||||
|
||||
tcl_cmd->info0 =
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH11K_HAL_TX_H
|
||||
@ -35,6 +36,7 @@ struct hal_tx_info {
|
||||
u8 lmac_id;
|
||||
u8 dscp_tid_tbl_idx;
|
||||
bool enable_mesh;
|
||||
u8 rbm_id;
|
||||
};
|
||||
|
||||
/* TODO: Check if the actual desc macros can be used instead */
|
||||
|
@ -11,6 +11,7 @@
|
||||
struct ath11k_hif_ops {
|
||||
u32 (*read32)(struct ath11k_base *sc, u32 address);
|
||||
void (*write32)(struct ath11k_base *sc, u32 address, u32 data);
|
||||
int (*read)(struct ath11k_base *ab, void *buf, u32 start, u32 end);
|
||||
void (*irq_enable)(struct ath11k_base *sc);
|
||||
void (*irq_disable)(struct ath11k_base *sc);
|
||||
int (*start)(struct ath11k_base *sc);
|
||||
@ -99,6 +100,15 @@ static inline void ath11k_hif_write32(struct ath11k_base *sc, u32 address, u32 d
|
||||
sc->hif.ops->write32(sc, address, data);
|
||||
}
|
||||
|
||||
static inline int ath11k_hif_read(struct ath11k_base *ab, void *buf,
|
||||
u32 start, u32 end)
|
||||
{
|
||||
if (!ab->hif.ops->read)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ab->hif.ops->read(ab, buf, start, end);
|
||||
}
|
||||
|
||||
static inline int ath11k_hif_map_service_to_pipe(struct ath11k_base *sc, u16 service_id,
|
||||
u8 *ul_pipe, u8 *dl_pipe)
|
||||
{
|
||||
@ -134,4 +144,5 @@ static inline void ath11k_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id,
|
||||
else
|
||||
*msi_data_idx = ce_id;
|
||||
}
|
||||
|
||||
#endif /* _HIF_H_ */
|
||||
|
@ -820,6 +820,30 @@ static bool ath11k_hw_wcn6855_rx_desc_get_ldpc_support(struct hal_rx_desc *desc)
|
||||
__le32_to_cpu(desc->u.wcn6855.msdu_start.info2));
|
||||
}
|
||||
|
||||
static u32 ath11k_hw_ipq8074_get_tcl_ring_selector(struct sk_buff *skb)
|
||||
{
|
||||
/* Let the default ring selection be based on current processor
|
||||
* number, where one of the 3 tcl rings are selected based on
|
||||
* the smp_processor_id(). In case that ring
|
||||
* is full/busy, we resort to other available rings.
|
||||
* If all rings are full, we drop the packet.
|
||||
*
|
||||
* TODO: Add throttling logic when all rings are full
|
||||
*/
|
||||
return smp_processor_id();
|
||||
}
|
||||
|
||||
static u32 ath11k_hw_wcn6750_get_tcl_ring_selector(struct sk_buff *skb)
|
||||
{
|
||||
/* Select the TCL ring based on the flow hash of the SKB instead
|
||||
* of CPU ID. Since applications pumping the traffic can be scheduled
|
||||
* on multiple CPUs, there is a chance that packets of the same flow
|
||||
* could end on different TCL rings, this could sometimes results in
|
||||
* an out of order arrival of the packets at the receiver.
|
||||
*/
|
||||
return skb_get_hash(skb);
|
||||
}
|
||||
|
||||
const struct ath11k_hw_ops ipq8074_ops = {
|
||||
.get_hw_mac_from_pdev_id = ath11k_hw_ipq8074_mac_from_pdev_id,
|
||||
.wmi_init_config = ath11k_init_wmi_config_ipq8074,
|
||||
@ -857,6 +881,7 @@ const struct ath11k_hw_ops ipq8074_ops = {
|
||||
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
|
||||
.rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid,
|
||||
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2,
|
||||
.get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_ops ipq6018_ops = {
|
||||
@ -896,6 +921,7 @@ const struct ath11k_hw_ops ipq6018_ops = {
|
||||
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
|
||||
.rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid,
|
||||
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2,
|
||||
.get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_ops qca6390_ops = {
|
||||
@ -935,6 +961,7 @@ const struct ath11k_hw_ops qca6390_ops = {
|
||||
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
|
||||
.rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid,
|
||||
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2,
|
||||
.get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_ops qcn9074_ops = {
|
||||
@ -974,6 +1001,7 @@ const struct ath11k_hw_ops qcn9074_ops = {
|
||||
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
|
||||
.rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid,
|
||||
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2,
|
||||
.get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_ops wcn6855_ops = {
|
||||
@ -1013,6 +1041,7 @@ const struct ath11k_hw_ops wcn6855_ops = {
|
||||
.mpdu_info_get_peerid = ath11k_hw_wcn6855_mpdu_info_get_peerid,
|
||||
.rx_desc_mac_addr2_valid = ath11k_hw_wcn6855_rx_desc_mac_addr2_valid,
|
||||
.rx_desc_mpdu_start_addr2 = ath11k_hw_wcn6855_rx_desc_mpdu_start_addr2,
|
||||
.get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_ops wcn6750_ops = {
|
||||
@ -1052,11 +1081,14 @@ const struct ath11k_hw_ops wcn6750_ops = {
|
||||
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
|
||||
.rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid,
|
||||
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2,
|
||||
.get_ring_selector = ath11k_hw_wcn6750_get_tcl_ring_selector,
|
||||
};
|
||||
|
||||
#define ATH11K_TX_RING_MASK_0 0x1
|
||||
#define ATH11K_TX_RING_MASK_1 0x2
|
||||
#define ATH11K_TX_RING_MASK_2 0x4
|
||||
#define ATH11K_TX_RING_MASK_0 BIT(0)
|
||||
#define ATH11K_TX_RING_MASK_1 BIT(1)
|
||||
#define ATH11K_TX_RING_MASK_2 BIT(2)
|
||||
#define ATH11K_TX_RING_MASK_3 BIT(3)
|
||||
#define ATH11K_TX_RING_MASK_4 BIT(4)
|
||||
|
||||
#define ATH11K_RX_RING_MASK_0 0x1
|
||||
#define ATH11K_RX_RING_MASK_1 0x2
|
||||
@ -1903,6 +1935,43 @@ const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qcn9074 = {
|
||||
},
|
||||
};
|
||||
|
||||
const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_wcn6750 = {
|
||||
.tx = {
|
||||
ATH11K_TX_RING_MASK_0,
|
||||
0,
|
||||
ATH11K_TX_RING_MASK_2,
|
||||
0,
|
||||
ATH11K_TX_RING_MASK_4,
|
||||
},
|
||||
.rx_mon_status = {
|
||||
0, 0, 0, 0, 0, 0,
|
||||
ATH11K_RX_MON_STATUS_RING_MASK_0,
|
||||
},
|
||||
.rx = {
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
ATH11K_RX_RING_MASK_0,
|
||||
ATH11K_RX_RING_MASK_1,
|
||||
ATH11K_RX_RING_MASK_2,
|
||||
ATH11K_RX_RING_MASK_3,
|
||||
},
|
||||
.rx_err = {
|
||||
0, ATH11K_RX_ERR_RING_MASK_0,
|
||||
},
|
||||
.rx_wbm_rel = {
|
||||
0, ATH11K_RX_WBM_REL_RING_MASK_0,
|
||||
},
|
||||
.reo_status = {
|
||||
0, ATH11K_REO_STATUS_RING_MASK_0,
|
||||
},
|
||||
.rxdma2host = {
|
||||
ATH11K_RXDMA2HOST_RING_MASK_0,
|
||||
ATH11K_RXDMA2HOST_RING_MASK_1,
|
||||
ATH11K_RXDMA2HOST_RING_MASK_2,
|
||||
},
|
||||
.host2rxdma = {
|
||||
},
|
||||
};
|
||||
|
||||
const struct ath11k_hw_regs ipq8074_regs = {
|
||||
/* SW2TCL(x) R0 ring configuration address */
|
||||
.hal_tcl1_ring_base_lsb = 0x00000510,
|
||||
@ -2332,12 +2401,55 @@ const struct ath11k_hw_regs wcn6750_regs = {
|
||||
.hal_reo1_misc_ctl = 0x000005d8,
|
||||
};
|
||||
|
||||
static const struct ath11k_hw_tcl2wbm_rbm_map ath11k_hw_tcl2wbm_rbm_map_ipq8074[] = {
|
||||
{
|
||||
.tcl_ring_num = 0,
|
||||
.wbm_ring_num = 0,
|
||||
.rbm_id = HAL_RX_BUF_RBM_SW0_BM,
|
||||
},
|
||||
{
|
||||
.tcl_ring_num = 1,
|
||||
.wbm_ring_num = 1,
|
||||
.rbm_id = HAL_RX_BUF_RBM_SW1_BM,
|
||||
},
|
||||
{
|
||||
.tcl_ring_num = 2,
|
||||
.wbm_ring_num = 2,
|
||||
.rbm_id = HAL_RX_BUF_RBM_SW2_BM,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ath11k_hw_tcl2wbm_rbm_map ath11k_hw_tcl2wbm_rbm_map_wcn6750[] = {
|
||||
{
|
||||
.tcl_ring_num = 0,
|
||||
.wbm_ring_num = 0,
|
||||
.rbm_id = HAL_RX_BUF_RBM_SW0_BM,
|
||||
},
|
||||
{
|
||||
.tcl_ring_num = 1,
|
||||
.wbm_ring_num = 4,
|
||||
.rbm_id = HAL_RX_BUF_RBM_SW4_BM,
|
||||
},
|
||||
{
|
||||
.tcl_ring_num = 2,
|
||||
.wbm_ring_num = 2,
|
||||
.rbm_id = HAL_RX_BUF_RBM_SW2_BM,
|
||||
},
|
||||
};
|
||||
|
||||
const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074 = {
|
||||
.rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
|
||||
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq8074,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390 = {
|
||||
.rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM,
|
||||
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq8074,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_hal_params ath11k_hw_hal_params_wcn6750 = {
|
||||
.rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM,
|
||||
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_wcn6750,
|
||||
};
|
||||
|
||||
static const struct cfg80211_sar_freq_ranges ath11k_hw_sar_freq_ranges_wcn6855[] = {
|
||||
|
@ -122,8 +122,15 @@ struct ath11k_hw_ring_mask {
|
||||
u8 host2rxdma[ATH11K_EXT_IRQ_GRP_NUM_MAX];
|
||||
};
|
||||
|
||||
struct ath11k_hw_tcl2wbm_rbm_map {
|
||||
u8 tcl_ring_num;
|
||||
u8 wbm_ring_num;
|
||||
u8 rbm_id;
|
||||
};
|
||||
|
||||
struct ath11k_hw_hal_params {
|
||||
enum hal_rx_buf_return_buf_manager rx_buf_rbm;
|
||||
const struct ath11k_hw_tcl2wbm_rbm_map *tcl2wbm_rbm_map;
|
||||
};
|
||||
|
||||
struct ath11k_hw_params {
|
||||
@ -166,6 +173,7 @@ struct ath11k_hw_params {
|
||||
u8 summary_pad_sz;
|
||||
u8 fft_hdr_len;
|
||||
u16 max_fft_bins;
|
||||
bool fragment_160mhz;
|
||||
} spectral;
|
||||
|
||||
u16 interface_modes;
|
||||
@ -175,6 +183,7 @@ struct ath11k_hw_params {
|
||||
bool idle_ps;
|
||||
bool supports_sta_ps;
|
||||
bool cold_boot_calib;
|
||||
bool cbcal_restart_fw;
|
||||
int fw_mem_mode;
|
||||
u32 num_vdevs;
|
||||
u32 num_peers;
|
||||
@ -200,6 +209,16 @@ struct ath11k_hw_params {
|
||||
bool hybrid_bus_type;
|
||||
bool fixed_fw_mem;
|
||||
bool support_off_channel_tx;
|
||||
bool supports_multi_bssid;
|
||||
|
||||
struct {
|
||||
u32 start;
|
||||
u32 end;
|
||||
} sram_dump;
|
||||
|
||||
bool tcl_ring_retry;
|
||||
u32 tx_ring_size;
|
||||
bool smp2p_wow_exit;
|
||||
};
|
||||
|
||||
struct ath11k_hw_ops {
|
||||
@ -242,6 +261,7 @@ struct ath11k_hw_ops {
|
||||
u16 (*mpdu_info_get_peerid)(u8 *tlv_data);
|
||||
bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc);
|
||||
u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc);
|
||||
u32 (*get_ring_selector)(struct sk_buff *skb);
|
||||
};
|
||||
|
||||
extern const struct ath11k_hw_ops ipq8074_ops;
|
||||
@ -254,9 +274,11 @@ extern const struct ath11k_hw_ops wcn6750_ops;
|
||||
extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_ipq8074;
|
||||
extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qca6390;
|
||||
extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qcn9074;
|
||||
extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_wcn6750;
|
||||
|
||||
extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074;
|
||||
extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390;
|
||||
extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_wcn6750;
|
||||
|
||||
static inline
|
||||
int ath11k_hw_get_mac_from_pdev_id(struct ath11k_hw_params *hw,
|
||||
@ -397,4 +419,5 @@ static inline const char *ath11k_bd_ie_type_str(enum ath11k_bd_ie_type type)
|
||||
}
|
||||
|
||||
extern const struct cfg80211_sar_capa ath11k_hw_sar_capa_wcn6855;
|
||||
|
||||
#endif
|
||||
|
@ -3059,7 +3059,7 @@ static int ath11k_mac_config_obss_pd(struct ath11k *ar,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable all patial BSSID mask for SRG */
|
||||
/* Enable all partial BSSID mask for SRG */
|
||||
ret = ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(ar, bitmap);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab,
|
||||
@ -3077,7 +3077,7 @@ static int ath11k_mac_config_obss_pd(struct ath11k *ar,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable all patial BSSID mask for non-SRG */
|
||||
/* Enable all partial BSSID mask for non-SRG */
|
||||
ret = ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(ar, bitmap);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab,
|
||||
@ -3350,10 +3350,15 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
ath11k_recalculate_mgmt_rate(ar, vif, &def);
|
||||
|
||||
if (changed & BSS_CHANGED_TWT) {
|
||||
if (info->twt_requester || info->twt_responder)
|
||||
ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id);
|
||||
else
|
||||
struct wmi_twt_enable_params twt_params = {0};
|
||||
|
||||
if (info->twt_requester || info->twt_responder) {
|
||||
ath11k_wmi_fill_default_twt_params(&twt_params);
|
||||
ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id,
|
||||
&twt_params);
|
||||
} else {
|
||||
ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_HE_OBSS_PD)
|
||||
@ -3451,7 +3456,7 @@ void __ath11k_mac_scan_finish(struct ath11k *ar)
|
||||
ar->scan_channel = NULL;
|
||||
ar->scan.roc_freq = 0;
|
||||
cancel_delayed_work(&ar->scan.timeout);
|
||||
complete(&ar->scan.completed);
|
||||
complete_all(&ar->scan.completed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -4524,6 +4529,7 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
|
||||
new_state == IEEE80211_STA_NONE) {
|
||||
memset(arsta, 0, sizeof(*arsta));
|
||||
arsta->arvif = arvif;
|
||||
arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
|
||||
INIT_WORK(&arsta->update_wk, ath11k_sta_rc_update_wk);
|
||||
INIT_WORK(&arsta->set_4addr_wk, ath11k_sta_set_4addr_wk);
|
||||
|
||||
@ -4701,7 +4707,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
|
||||
"mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
|
||||
sta->addr, changed, sta->deflink.bandwidth,
|
||||
sta->deflink.rx_nss,
|
||||
sta->smps_mode);
|
||||
sta->deflink.smps_mode);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
@ -4737,7 +4743,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
|
||||
if (changed & IEEE80211_RC_SMPS_CHANGED) {
|
||||
smps = WMI_PEER_SMPS_PS_NONE;
|
||||
|
||||
switch (sta->smps_mode) {
|
||||
switch (sta->deflink.smps_mode) {
|
||||
case IEEE80211_SMPS_AUTOMATIC:
|
||||
case IEEE80211_SMPS_OFF:
|
||||
smps = WMI_PEER_SMPS_PS_NONE;
|
||||
@ -4750,7 +4756,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
|
||||
break;
|
||||
default:
|
||||
ath11k_warn(ar->ab, "Invalid smps %d in sta rc update for %pM\n",
|
||||
sta->smps_mode, sta->addr);
|
||||
sta->deflink.smps_mode, sta->addr);
|
||||
smps = WMI_PEER_SMPS_PS_NONE;
|
||||
break;
|
||||
}
|
||||
@ -4954,6 +4960,8 @@ static int ath11k_mac_set_txbf_conf(struct ath11k_vif *arvif)
|
||||
if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) {
|
||||
nsts = vht_cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
|
||||
nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
|
||||
if (nsts > (ar->num_rx_chains - 1))
|
||||
nsts = ar->num_rx_chains - 1;
|
||||
value |= SM(nsts, WMI_TXBF_STS_CAP_OFFSET);
|
||||
}
|
||||
|
||||
@ -4994,7 +5002,7 @@ static int ath11k_mac_set_txbf_conf(struct ath11k_vif *arvif)
|
||||
static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap)
|
||||
{
|
||||
bool subfer, subfee;
|
||||
int sound_dim = 0;
|
||||
int sound_dim = 0, nsts = 0;
|
||||
|
||||
subfer = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE));
|
||||
subfee = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE));
|
||||
@ -5004,6 +5012,11 @@ static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap)
|
||||
subfer = false;
|
||||
}
|
||||
|
||||
if (ar->num_rx_chains < 2) {
|
||||
*vht_cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
|
||||
subfee = false;
|
||||
}
|
||||
|
||||
/* If SU Beaformer is not set, then disable MU Beamformer Capability */
|
||||
if (!subfer)
|
||||
*vht_cap &= ~(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
|
||||
@ -5016,7 +5029,9 @@ static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap)
|
||||
sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
|
||||
*vht_cap &= ~IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
|
||||
|
||||
/* TODO: Need to check invalid STS and Sound_dim values set by FW? */
|
||||
nsts = (*vht_cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK);
|
||||
nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
|
||||
*vht_cap &= ~IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
|
||||
|
||||
/* Enable Sounding Dimension Field only if SU BF is enabled */
|
||||
if (subfer) {
|
||||
@ -5028,9 +5043,15 @@ static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap)
|
||||
*vht_cap |= sound_dim;
|
||||
}
|
||||
|
||||
/* Use the STS advertised by FW unless SU Beamformee is not supported*/
|
||||
if (!subfee)
|
||||
*vht_cap &= ~(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK);
|
||||
/* Enable Beamformee STS Field only if SU BF is enabled */
|
||||
if (subfee) {
|
||||
if (nsts > (ar->num_rx_chains - 1))
|
||||
nsts = ar->num_rx_chains - 1;
|
||||
|
||||
nsts <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
|
||||
nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
|
||||
*vht_cap |= nsts;
|
||||
}
|
||||
}
|
||||
|
||||
static struct ieee80211_sta_vht_cap
|
||||
@ -6173,6 +6194,13 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* In the case of hardware recovery, debugfs files are
|
||||
* not deleted since ieee80211_ops.remove_interface() is
|
||||
* not invoked. In such cases, try to delete the files.
|
||||
* These will be re-created later.
|
||||
*/
|
||||
ath11k_debugfs_remove_interface(arvif);
|
||||
|
||||
memset(arvif, 0, sizeof(*arvif));
|
||||
|
||||
arvif->ar = ar;
|
||||
@ -6354,9 +6382,7 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath11k_debugfs_add_interface(arvif);
|
||||
if (ret)
|
||||
goto err_peer_del;
|
||||
ath11k_debugfs_add_interface(arvif);
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
@ -8421,6 +8447,95 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_fw_stats_request(struct ath11k *ar,
|
||||
struct stats_request_params *req_param)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
unsigned long time_left;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->fw_stats_done = false;
|
||||
ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
reinit_completion(&ar->fw_stats_complete);
|
||||
|
||||
ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "could not request fw stats (%d)\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
time_left = wait_for_completion_timeout(&ar->fw_stats_complete,
|
||||
1 * HZ);
|
||||
|
||||
if (!time_left)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
int *dbm)
|
||||
{
|
||||
struct ath11k *ar = hw->priv;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct stats_request_params req_param = {0};
|
||||
struct ath11k_fw_stats_pdev *pdev;
|
||||
int ret;
|
||||
|
||||
/* Final Tx power is minimum of Target Power, CTL power, Regulatory
|
||||
* Power, PSD EIRP Power. We just know the Regulatory power from the
|
||||
* regulatory rules obtained. FW knows all these power and sets the min
|
||||
* of these. Hence, we request the FW pdev stats in which FW reports
|
||||
* the minimum of all vdev's channel Tx power.
|
||||
*/
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH11K_STATE_ON)
|
||||
goto err_fallback;
|
||||
|
||||
req_param.pdev_id = ar->pdev->pdev_id;
|
||||
req_param.stats_id = WMI_REQUEST_PDEV_STAT;
|
||||
|
||||
ret = ath11k_fw_stats_request(ar, &req_param);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
|
||||
goto err_fallback;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
pdev = list_first_entry_or_null(&ar->fw_stats.pdevs,
|
||||
struct ath11k_fw_stats_pdev, list);
|
||||
if (!pdev) {
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
goto err_fallback;
|
||||
}
|
||||
|
||||
/* tx power is set as 2 units per dBm in FW. */
|
||||
*dbm = pdev->chan_tx_power / 2;
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "txpower from firmware %d, reported %d dBm\n",
|
||||
pdev->chan_tx_power, *dbm);
|
||||
return 0;
|
||||
|
||||
err_fallback:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
/* We didn't get txpower from FW. Hence, relying on vif->bss_conf.txpower */
|
||||
*dbm = vif->bss_conf.txpower;
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "txpower from firmware NaN, reported %d dBm\n",
|
||||
*dbm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ieee80211_ops ath11k_ops = {
|
||||
.tx = ath11k_mac_op_tx,
|
||||
.start = ath11k_mac_op_start,
|
||||
@ -8471,6 +8586,7 @@ static const struct ieee80211_ops ath11k_ops = {
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
.ipv6_addr_change = ath11k_mac_op_ipv6_changed,
|
||||
#endif
|
||||
.get_txpower = ath11k_mac_op_get_txpower,
|
||||
|
||||
.set_sar_specs = ath11k_mac_op_set_bios_sar_specs,
|
||||
.remain_on_channel = ath11k_mac_op_remain_on_channel,
|
||||
@ -8777,6 +8893,11 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
||||
if (ab->hw_params.single_pdev_only && ar->supports_6ghz)
|
||||
ieee80211_hw_set(ar->hw, SINGLE_SCAN_ON_ALL_BANDS);
|
||||
|
||||
if (ab->hw_params.supports_multi_bssid) {
|
||||
ieee80211_hw_set(ar->hw, SUPPORTS_MULTI_BSSID);
|
||||
ieee80211_hw_set(ar->hw, SUPPORTS_ONLY_HE_MULTI_BSSID);
|
||||
}
|
||||
|
||||
ieee80211_hw_set(ar->hw, SIGNAL_DBM);
|
||||
ieee80211_hw_set(ar->hw, SUPPORTS_PS);
|
||||
ieee80211_hw_set(ar->hw, SUPPORTS_DYNAMIC_PS);
|
||||
@ -8967,6 +9088,7 @@ int ath11k_mac_register(struct ath11k_base *ab)
|
||||
struct ath11k_pdev *pdev;
|
||||
int i;
|
||||
int ret;
|
||||
u8 mac_addr[ETH_ALEN] = {0};
|
||||
|
||||
if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
|
||||
return 0;
|
||||
@ -8979,13 +9101,18 @@ int ath11k_mac_register(struct ath11k_base *ab)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
device_get_mac_address(ab->dev, mac_addr);
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
if (ab->pdevs_macaddr_valid) {
|
||||
ether_addr_copy(ar->mac_addr, pdev->mac_addr);
|
||||
} else {
|
||||
ether_addr_copy(ar->mac_addr, ab->mac_addr);
|
||||
if (is_zero_ether_addr(mac_addr))
|
||||
ether_addr_copy(ar->mac_addr, ab->mac_addr);
|
||||
else
|
||||
ether_addr_copy(ar->mac_addr, mac_addr);
|
||||
ar->mac_addr[4] += i;
|
||||
}
|
||||
|
||||
@ -9079,6 +9206,8 @@ int ath11k_mac_allocate(struct ath11k_base *ab)
|
||||
clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
|
||||
ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID;
|
||||
init_completion(&ar->completed_11d_scan);
|
||||
|
||||
ath11k_fw_stats_init(ar);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -402,8 +402,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
|
||||
ret = ath11k_mhi_get_msi(ab_pci);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to get msi for mhi\n");
|
||||
mhi_free_controller(mhi_ctrl);
|
||||
return ret;
|
||||
goto free_controller;
|
||||
}
|
||||
|
||||
if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))
|
||||
@ -412,7 +411,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
|
||||
if (test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) {
|
||||
ret = ath11k_mhi_read_addr_from_dt(mhi_ctrl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto free_controller;
|
||||
} else {
|
||||
mhi_ctrl->iova_start = 0;
|
||||
mhi_ctrl->iova_stop = 0xFFFFFFFF;
|
||||
@ -440,18 +439,22 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
|
||||
default:
|
||||
ath11k_err(ab, "failed assign mhi_config for unknown hw rev %d\n",
|
||||
ab->hw_rev);
|
||||
mhi_free_controller(mhi_ctrl);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto free_controller;
|
||||
}
|
||||
|
||||
ret = mhi_register_controller(mhi_ctrl, ath11k_mhi_config);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to register to mhi bus, err = %d\n", ret);
|
||||
mhi_free_controller(mhi_ctrl);
|
||||
return ret;
|
||||
goto free_controller;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_controller:
|
||||
mhi_free_controller(mhi_ctrl);
|
||||
ab_pci->mhi_ctrl = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ath11k_mhi_unregister(struct ath11k_pci *ab_pci)
|
||||
|
@ -685,6 +685,7 @@ static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
|
||||
.stop = ath11k_pcic_stop,
|
||||
.read32 = ath11k_pcic_read32,
|
||||
.write32 = ath11k_pcic_write32,
|
||||
.read = ath11k_pcic_read,
|
||||
.power_down = ath11k_pci_power_down,
|
||||
.power_up = ath11k_pci_power_up,
|
||||
.suspend = ath11k_pci_hif_suspend,
|
||||
|
@ -140,55 +140,100 @@ int ath11k_pcic_init_msi_config(struct ath11k_base *ab)
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_pcic_init_msi_config);
|
||||
|
||||
void ath11k_pcic_write32(struct ath11k_base *ab, u32 offset, u32 value)
|
||||
static void __ath11k_pcic_write32(struct ath11k_base *ab, u32 offset, u32 value)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* for offset beyond BAR + 4K - 32, may
|
||||
* need to wakeup the device to access.
|
||||
*/
|
||||
if (test_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags) &&
|
||||
offset >= ATH11K_PCI_ACCESS_ALWAYS_OFF && ab->pci.ops->wakeup)
|
||||
ret = ab->pci.ops->wakeup(ab);
|
||||
|
||||
if (offset < ATH11K_PCI_WINDOW_START)
|
||||
iowrite32(value, ab->mem + offset);
|
||||
else
|
||||
ab->pci.ops->window_write32(ab, offset, value);
|
||||
|
||||
if (test_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags) &&
|
||||
offset >= ATH11K_PCI_ACCESS_ALWAYS_OFF && ab->pci.ops->release &&
|
||||
!ret)
|
||||
ab->pci.ops->release(ab);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_pcic_write32);
|
||||
|
||||
u32 ath11k_pcic_read32(struct ath11k_base *ab, u32 offset)
|
||||
void ath11k_pcic_write32(struct ath11k_base *ab, u32 offset, u32 value)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 val;
|
||||
bool wakeup_required;
|
||||
|
||||
/* for offset beyond BAR + 4K - 32, may
|
||||
* need to wakeup the device to access.
|
||||
*/
|
||||
if (test_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags) &&
|
||||
offset >= ATH11K_PCI_ACCESS_ALWAYS_OFF && ab->pci.ops->wakeup)
|
||||
wakeup_required = test_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags) &&
|
||||
offset >= ATH11K_PCI_ACCESS_ALWAYS_OFF;
|
||||
if (wakeup_required && ab->pci.ops->wakeup)
|
||||
ret = ab->pci.ops->wakeup(ab);
|
||||
|
||||
__ath11k_pcic_write32(ab, offset, value);
|
||||
|
||||
if (wakeup_required && !ret && ab->pci.ops->release)
|
||||
ab->pci.ops->release(ab);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_pcic_write32);
|
||||
|
||||
static u32 __ath11k_pcic_read32(struct ath11k_base *ab, u32 offset)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (offset < ATH11K_PCI_WINDOW_START)
|
||||
val = ioread32(ab->mem + offset);
|
||||
else
|
||||
val = ab->pci.ops->window_read32(ab, offset);
|
||||
|
||||
if (test_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags) &&
|
||||
offset >= ATH11K_PCI_ACCESS_ALWAYS_OFF && ab->pci.ops->release &&
|
||||
!ret)
|
||||
return val;
|
||||
}
|
||||
|
||||
u32 ath11k_pcic_read32(struct ath11k_base *ab, u32 offset)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 val;
|
||||
bool wakeup_required;
|
||||
|
||||
/* for offset beyond BAR + 4K - 32, may
|
||||
* need to wakeup the device to access.
|
||||
*/
|
||||
wakeup_required = test_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags) &&
|
||||
offset >= ATH11K_PCI_ACCESS_ALWAYS_OFF;
|
||||
if (wakeup_required && ab->pci.ops->wakeup)
|
||||
ret = ab->pci.ops->wakeup(ab);
|
||||
|
||||
val = __ath11k_pcic_read32(ab, offset);
|
||||
|
||||
if (wakeup_required && !ret && ab->pci.ops->release)
|
||||
ab->pci.ops->release(ab);
|
||||
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_pcic_read32);
|
||||
|
||||
int ath11k_pcic_read(struct ath11k_base *ab, void *buf, u32 start, u32 end)
|
||||
{
|
||||
int ret = 0;
|
||||
bool wakeup_required;
|
||||
u32 *data = buf;
|
||||
u32 i;
|
||||
|
||||
/* for offset beyond BAR + 4K - 32, may
|
||||
* need to wakeup the device to access.
|
||||
*/
|
||||
wakeup_required = test_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags) &&
|
||||
end >= ATH11K_PCI_ACCESS_ALWAYS_OFF;
|
||||
if (wakeup_required && ab->pci.ops->wakeup) {
|
||||
ret = ab->pci.ops->wakeup(ab);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to wakeup for read from 0x%x: %d\n",
|
||||
start, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = start; i < end + 1; i += 4)
|
||||
*data++ = __ath11k_pcic_read32(ab, i);
|
||||
|
||||
if (wakeup_required && ab->pci.ops->release)
|
||||
ab->pci.ops->release(ab);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_pcic_read);
|
||||
|
||||
void ath11k_pcic_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo,
|
||||
u32 *msi_addr_hi)
|
||||
{
|
||||
@ -414,6 +459,7 @@ void ath11k_pcic_ext_irq_enable(struct ath11k_base *ab)
|
||||
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
|
||||
|
||||
if (!irq_grp->napi_enabled) {
|
||||
dev_set_threaded(&irq_grp->napi_ndev, true);
|
||||
napi_enable(&irq_grp->napi);
|
||||
irq_grp->napi_enabled = true;
|
||||
}
|
||||
@ -731,3 +777,37 @@ int ath11k_pcic_register_pci_ops(struct ath11k_base *ab,
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_pcic_register_pci_ops);
|
||||
|
||||
void ath11k_pci_enable_ce_irqs_except_wake_irq(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR ||
|
||||
i == ATH11K_PCI_CE_WAKE_IRQ)
|
||||
continue;
|
||||
ath11k_pcic_ce_irq_enable(ab, i);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_pci_enable_ce_irqs_except_wake_irq);
|
||||
|
||||
void ath11k_pci_disable_ce_irqs_except_wake_irq(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
int irq_idx;
|
||||
struct ath11k_ce_pipe *ce_pipe;
|
||||
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
ce_pipe = &ab->ce.ce_pipe[i];
|
||||
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
|
||||
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR ||
|
||||
i == ATH11K_PCI_CE_WAKE_IRQ)
|
||||
continue;
|
||||
|
||||
disable_irq_nosync(ab->irq_num[irq_idx]);
|
||||
synchronize_irq(ab->irq_num[irq_idx]);
|
||||
tasklet_kill(&ce_pipe->intr_tq);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_pci_disable_ce_irqs_except_wake_irq);
|
||||
|
@ -12,6 +12,8 @@
|
||||
#define ATH11K_PCI_IRQ_CE0_OFFSET 3
|
||||
#define ATH11K_PCI_IRQ_DP_OFFSET 14
|
||||
|
||||
#define ATH11K_PCI_CE_WAKE_IRQ 2
|
||||
|
||||
#define ATH11K_PCI_WINDOW_ENABLE_BIT 0x40000000
|
||||
#define ATH11K_PCI_WINDOW_REG_ADDRESS 0x310c
|
||||
#define ATH11K_PCI_WINDOW_VALUE_MASK GENMASK(24, 19)
|
||||
@ -45,4 +47,8 @@ void ath11k_pcic_ce_irq_disable_sync(struct ath11k_base *ab);
|
||||
int ath11k_pcic_init_msi_config(struct ath11k_base *ab);
|
||||
int ath11k_pcic_register_pci_ops(struct ath11k_base *ab,
|
||||
const struct ath11k_pci_ops *pci_ops);
|
||||
int ath11k_pcic_read(struct ath11k_base *ab, void *buf, u32 start, u32 end);
|
||||
void ath11k_pci_enable_ce_irqs_except_wake_irq(struct ath11k_base *ab);
|
||||
void ath11k_pci_disable_ce_irqs_except_wake_irq(struct ath11k_base *ab);
|
||||
|
||||
#endif
|
||||
|
@ -302,6 +302,21 @@ static int __ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, const u8 *addr)
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
|
||||
peer = ath11k_peer_find_by_addr(ab, addr);
|
||||
/* Check if the found peer is what we want to remove.
|
||||
* While the sta is transitioning to another band we may
|
||||
* have 2 peer with the same addr assigned to different
|
||||
* vdev_id. Make sure we are deleting the correct peer.
|
||||
*/
|
||||
if (peer && peer->vdev_id == vdev_id)
|
||||
ath11k_peer_rhash_delete(ab, peer);
|
||||
|
||||
/* Fallback to peer list search if the correct peer can't be found.
|
||||
* Skip the deletion of the peer from the rhash since it has already
|
||||
* been deleted in peer add.
|
||||
*/
|
||||
if (!peer)
|
||||
peer = ath11k_peer_find(ab, vdev_id, addr);
|
||||
|
||||
if (!peer) {
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
mutex_unlock(&ab->tbl_mtx_lock);
|
||||
@ -312,8 +327,6 @@ static int __ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, const u8 *addr)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ath11k_peer_rhash_delete(ab, peer);
|
||||
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
mutex_unlock(&ab->tbl_mtx_lock);
|
||||
|
||||
@ -372,8 +385,17 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
spin_lock_bh(&ar->ab->base_lock);
|
||||
peer = ath11k_peer_find_by_addr(ar->ab, param->peer_addr);
|
||||
if (peer) {
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
return -EINVAL;
|
||||
if (peer->vdev_id == param->vdev_id) {
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Assume sta is transitioning to another band.
|
||||
* Remove here the peer from rhash.
|
||||
*/
|
||||
mutex_lock(&ar->ab->tbl_mtx_lock);
|
||||
ath11k_peer_rhash_delete(ar->ab, peer);
|
||||
mutex_unlock(&ar->ab->tbl_mtx_lock);
|
||||
}
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
|
||||
|
@ -1696,6 +1696,13 @@ static struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info qmi_wlfw_fw_init_done_ind_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
},
|
||||
};
|
||||
|
||||
static int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
|
||||
{
|
||||
struct qmi_wlanfw_host_cap_req_msg_v01 req;
|
||||
@ -1872,7 +1879,7 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
|
||||
|
||||
/* For QCA6390 by default FW requests a block of ~4M contiguous
|
||||
* DMA memory, it's hard to allocate from OS. So host returns
|
||||
* failure to FW and FW will then request mulitple blocks of small
|
||||
* failure to FW and FW will then request multiple blocks of small
|
||||
* chunk size memory.
|
||||
*/
|
||||
if (!(ab->hw_params.fixed_mem_region ||
|
||||
@ -3006,6 +3013,12 @@ static void ath11k_qmi_msg_fw_ready_cb(struct qmi_handle *qmi_hdl,
|
||||
struct ath11k_base *ab = qmi->ab;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware ready\n");
|
||||
|
||||
if (!ab->qmi.cal_done) {
|
||||
ab->qmi.cal_done = 1;
|
||||
wake_up(&ab->qmi.cold_boot_waitq);
|
||||
}
|
||||
|
||||
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_READY, NULL);
|
||||
}
|
||||
|
||||
@ -3023,6 +3036,19 @@ static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi_hdl,
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cold boot calibration done\n");
|
||||
}
|
||||
|
||||
static void ath11k_qmi_msg_fw_init_done_cb(struct qmi_handle *qmi_hdl,
|
||||
struct sockaddr_qrtr *sq,
|
||||
struct qmi_txn *txn,
|
||||
const void *decoded)
|
||||
{
|
||||
struct ath11k_qmi *qmi = container_of(qmi_hdl,
|
||||
struct ath11k_qmi, handle);
|
||||
struct ath11k_base *ab = qmi->ab;
|
||||
|
||||
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_INIT_DONE, NULL);
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware init done\n");
|
||||
}
|
||||
|
||||
static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = {
|
||||
{
|
||||
.type = QMI_INDICATION,
|
||||
@ -3053,6 +3079,14 @@ static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = {
|
||||
sizeof(struct qmi_wlanfw_fw_cold_cal_done_ind_msg_v01),
|
||||
.fn = ath11k_qmi_msg_cold_boot_cal_done_cb,
|
||||
},
|
||||
{
|
||||
.type = QMI_INDICATION,
|
||||
.msg_id = QMI_WLFW_FW_INIT_DONE_IND_V01,
|
||||
.ei = qmi_wlfw_fw_init_done_ind_msg_v01_ei,
|
||||
.decoded_size =
|
||||
sizeof(struct qmi_wlfw_fw_init_done_ind_msg_v01),
|
||||
.fn = ath11k_qmi_msg_fw_init_done_cb,
|
||||
},
|
||||
};
|
||||
|
||||
static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl,
|
||||
@ -3145,7 +3179,7 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
break;
|
||||
case ATH11K_QMI_EVENT_FW_READY:
|
||||
case ATH11K_QMI_EVENT_FW_INIT_DONE:
|
||||
clear_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
|
||||
if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) {
|
||||
ath11k_hal_dump_srng_stats(ab);
|
||||
@ -3168,6 +3202,22 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)
|
||||
set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
|
||||
}
|
||||
|
||||
break;
|
||||
case ATH11K_QMI_EVENT_FW_READY:
|
||||
/* For targets requiring a FW restart upon cold
|
||||
* boot completion, there is no need to process
|
||||
* FW ready; such targets will receive FW init
|
||||
* done message after FW restart.
|
||||
*/
|
||||
if (ab->hw_params.cbcal_restart_fw)
|
||||
break;
|
||||
|
||||
clear_bit(ATH11K_FLAG_CRASH_FLUSH,
|
||||
&ab->dev_flags);
|
||||
clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
|
||||
ath11k_core_qmi_firmware_ready(ab);
|
||||
set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
|
||||
|
||||
break;
|
||||
case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE:
|
||||
break;
|
||||
|
@ -31,8 +31,9 @@
|
||||
|
||||
#define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035
|
||||
#define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037
|
||||
#define QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01 0x0021
|
||||
#define QMI_WLFW_FW_READY_IND_V01 0x0038
|
||||
#define QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01 0x003E
|
||||
#define QMI_WLFW_FW_READY_IND_V01 0x0021
|
||||
#define QMI_WLFW_FW_INIT_DONE_IND_V01 0x0038
|
||||
|
||||
#define QMI_WLANFW_MAX_DATA_SIZE_V01 6144
|
||||
#define ATH11K_FIRMWARE_MODE_OFF 4
|
||||
@ -69,6 +70,7 @@ enum ath11k_qmi_event_type {
|
||||
ATH11K_QMI_EVENT_FORCE_FW_ASSERT,
|
||||
ATH11K_QMI_EVENT_POWER_UP,
|
||||
ATH11K_QMI_EVENT_POWER_DOWN,
|
||||
ATH11K_QMI_EVENT_FW_INIT_DONE,
|
||||
ATH11K_QMI_EVENT_MAX,
|
||||
};
|
||||
|
||||
@ -291,6 +293,10 @@ struct qmi_wlanfw_fw_cold_cal_done_ind_msg_v01 {
|
||||
char placeholder;
|
||||
};
|
||||
|
||||
struct qmi_wlfw_fw_init_done_ind_msg_v01 {
|
||||
char placeholder;
|
||||
};
|
||||
|
||||
#define QMI_WLANFW_CAP_REQ_MSG_V01_MAX_LEN 0
|
||||
#define QMI_WLANFW_CAP_RESP_MSG_V01_MAX_LEN 235
|
||||
#define QMI_WLANFW_CAP_REQ_V01 0x0024
|
||||
|
@ -877,7 +877,7 @@ struct rx_msdu_start_wcn6855 {
|
||||
*
|
||||
* l4_offset
|
||||
* Depending upon mode bit, this field either indicates the
|
||||
* L4 offset nin bytes from the start of RX_HEADER (only valid
|
||||
* L4 offset in bytes from the start of RX_HEADER (only valid
|
||||
* if either ipv4_proto or ipv6_proto is set to 1) or indicates
|
||||
* the offset in bytes to the start of TCP or UDP header from
|
||||
* the start of the IP header after decapsulation (Only valid if
|
||||
|
@ -30,6 +30,7 @@
|
||||
#define ATH11K_SPECTRAL_20MHZ 20
|
||||
#define ATH11K_SPECTRAL_40MHZ 40
|
||||
#define ATH11K_SPECTRAL_80MHZ 80
|
||||
#define ATH11K_SPECTRAL_160MHZ 160
|
||||
|
||||
#define ATH11K_SPECTRAL_SIGNATURE 0xFA
|
||||
|
||||
@ -183,6 +184,8 @@ static int ath11k_spectral_scan_trigger(struct ath11k *ar)
|
||||
if (ar->spectral.mode == ATH11K_SPECTRAL_DISABLED)
|
||||
return 0;
|
||||
|
||||
ar->spectral.is_primary = true;
|
||||
|
||||
ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id,
|
||||
ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
|
||||
ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE);
|
||||
@ -585,6 +588,7 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
|
||||
u8 chan_width_mhz, bin_sz;
|
||||
int ret;
|
||||
u32 check_length;
|
||||
bool fragment_sample = false;
|
||||
|
||||
lockdep_assert_held(&ar->spectral.lock);
|
||||
|
||||
@ -639,6 +643,13 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
|
||||
case ATH11K_SPECTRAL_80MHZ:
|
||||
fft_sample->chan_width_mhz = chan_width_mhz;
|
||||
break;
|
||||
case ATH11K_SPECTRAL_160MHZ:
|
||||
if (ab->hw_params.spectral.fragment_160mhz) {
|
||||
chan_width_mhz /= 2;
|
||||
fragment_sample = true;
|
||||
}
|
||||
fft_sample->chan_width_mhz = chan_width_mhz;
|
||||
break;
|
||||
default:
|
||||
ath11k_warn(ab, "invalid channel width %d\n", chan_width_mhz);
|
||||
return -EINVAL;
|
||||
@ -663,6 +674,17 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
|
||||
freq = summary->meta.freq2;
|
||||
fft_sample->freq2 = __cpu_to_be16(freq);
|
||||
|
||||
/* If freq2 is available then the spectral scan results are fragmented
|
||||
* as primary and secondary
|
||||
*/
|
||||
if (fragment_sample && freq) {
|
||||
if (!ar->spectral.is_primary)
|
||||
fft_sample->freq1 = cpu_to_be16(freq);
|
||||
|
||||
/* We have to toggle the is_primary to handle the next report */
|
||||
ar->spectral.is_primary = !ar->spectral.is_primary;
|
||||
}
|
||||
|
||||
ath11k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins,
|
||||
ab->hw_params.spectral.fft_sz);
|
||||
|
||||
|
@ -35,6 +35,7 @@ struct ath11k_spectral {
|
||||
u16 count;
|
||||
u8 fft_size;
|
||||
bool enabled;
|
||||
bool is_primary;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ATH11K_SPECTRAL
|
||||
|
@ -99,7 +99,7 @@ static ssize_t ath11k_thermal_show_temp(struct device *dev,
|
||||
temperature = ar->thermal.temperature;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
/* display in millidegree celcius */
|
||||
/* display in millidegree Celsius */
|
||||
ret = snprintf(buf, PAGE_SIZE, "%d\n", temperature * 1000);
|
||||
out:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
@ -19,7 +19,7 @@ struct ath11k_thermal {
|
||||
|
||||
/* protected by conf_mutex */
|
||||
u32 throttle_state;
|
||||
/* temperature value in Celcius degree
|
||||
/* temperature value in Celsius degree
|
||||
* protected by data_lock
|
||||
*/
|
||||
int temperature;
|
||||
|
@ -305,6 +305,34 @@ TRACE_EVENT(ath11k_wmi_diag,
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(ath11k_ps_timekeeper,
|
||||
TP_PROTO(struct ath11k *ar, const void *peer_addr,
|
||||
u32 peer_ps_timestamp, u8 peer_ps_state),
|
||||
TP_ARGS(ar, peer_addr, peer_ps_timestamp, peer_ps_state),
|
||||
|
||||
TP_STRUCT__entry(__string(device, dev_name(ar->ab->dev))
|
||||
__string(driver, dev_driver_string(ar->ab->dev))
|
||||
__dynamic_array(u8, peer_addr, ETH_ALEN)
|
||||
__field(u8, peer_ps_state)
|
||||
__field(u32, peer_ps_timestamp)
|
||||
),
|
||||
|
||||
TP_fast_assign(__assign_str(device, dev_name(ar->ab->dev));
|
||||
__assign_str(driver, dev_driver_string(ar->ab->dev));
|
||||
memcpy(__get_dynamic_array(peer_addr), peer_addr,
|
||||
ETH_ALEN);
|
||||
__entry->peer_ps_state = peer_ps_state;
|
||||
__entry->peer_ps_timestamp = peer_ps_timestamp;
|
||||
),
|
||||
|
||||
TP_printk("%s %s %u %u",
|
||||
__get_str(driver),
|
||||
__get_str(device),
|
||||
__entry->peer_ps_state,
|
||||
__entry->peer_ps_timestamp
|
||||
)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/
|
||||
|
||||
/* we don't want to use include/trace/events */
|
||||
|
@ -416,7 +416,7 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(struct ath11k_pdev_wmi *wmi_handle,
|
||||
|
||||
/* tx/rx chainmask reported from fw depends on the actual hw chains used,
|
||||
* For example, for 4x4 capable macphys, first 4 chains can be used for first
|
||||
* mac and the remaing 4 chains can be used for the second mac or vice-versa.
|
||||
* mac and the remaining 4 chains can be used for the second mac or vice-versa.
|
||||
* In this case, tx/rx chainmask 0xf will be advertised for first mac and 0xf0
|
||||
* will be advertised for second mac or vice-versa. Compute the shift value
|
||||
* for tx/rx chainmask which will be used to advertise supported ht/vht rates to
|
||||
@ -991,9 +991,13 @@ int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
|
||||
{
|
||||
struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
struct wmi_vdev_up_cmd *cmd;
|
||||
struct ieee80211_bss_conf *bss_conf;
|
||||
struct ath11k_vif *arvif;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
arvif = ath11k_mac_get_arvif(ar, vdev_id);
|
||||
|
||||
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
@ -1007,6 +1011,17 @@ int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
|
||||
|
||||
ether_addr_copy(cmd->vdev_bssid.addr, bssid);
|
||||
|
||||
if (arvif && arvif->vif->type == NL80211_IFTYPE_STATION) {
|
||||
bss_conf = &arvif->vif->bss_conf;
|
||||
|
||||
if (bss_conf->nontransmitted) {
|
||||
ether_addr_copy(cmd->trans_bssid.addr,
|
||||
bss_conf->transmitter_bssid);
|
||||
cmd->profile_idx = bss_conf->bssid_index;
|
||||
cmd->profile_num = bss_conf->bssid_indicator;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_VDEV_UP_CMDID);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to submit WMI_VDEV_UP cmd\n");
|
||||
@ -3064,8 +3079,34 @@ int ath11k_wmi_pdev_pktlog_disable(struct ath11k *ar)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id)
|
||||
void ath11k_wmi_fill_default_twt_params(struct wmi_twt_enable_params *twt_params)
|
||||
{
|
||||
twt_params->sta_cong_timer_ms = ATH11K_TWT_DEF_STA_CONG_TIMER_MS;
|
||||
twt_params->default_slot_size = ATH11K_TWT_DEF_DEFAULT_SLOT_SIZE;
|
||||
twt_params->congestion_thresh_setup = ATH11K_TWT_DEF_CONGESTION_THRESH_SETUP;
|
||||
twt_params->congestion_thresh_teardown =
|
||||
ATH11K_TWT_DEF_CONGESTION_THRESH_TEARDOWN;
|
||||
twt_params->congestion_thresh_critical =
|
||||
ATH11K_TWT_DEF_CONGESTION_THRESH_CRITICAL;
|
||||
twt_params->interference_thresh_teardown =
|
||||
ATH11K_TWT_DEF_INTERFERENCE_THRESH_TEARDOWN;
|
||||
twt_params->interference_thresh_setup =
|
||||
ATH11K_TWT_DEF_INTERFERENCE_THRESH_SETUP;
|
||||
twt_params->min_no_sta_setup = ATH11K_TWT_DEF_MIN_NO_STA_SETUP;
|
||||
twt_params->min_no_sta_teardown = ATH11K_TWT_DEF_MIN_NO_STA_TEARDOWN;
|
||||
twt_params->no_of_bcast_mcast_slots = ATH11K_TWT_DEF_NO_OF_BCAST_MCAST_SLOTS;
|
||||
twt_params->min_no_twt_slots = ATH11K_TWT_DEF_MIN_NO_TWT_SLOTS;
|
||||
twt_params->max_no_sta_twt = ATH11K_TWT_DEF_MAX_NO_STA_TWT;
|
||||
twt_params->mode_check_interval = ATH11K_TWT_DEF_MODE_CHECK_INTERVAL;
|
||||
twt_params->add_sta_slot_interval = ATH11K_TWT_DEF_ADD_STA_SLOT_INTERVAL;
|
||||
twt_params->remove_sta_slot_interval =
|
||||
ATH11K_TWT_DEF_REMOVE_STA_SLOT_INTERVAL;
|
||||
/* TODO add MBSSID support */
|
||||
twt_params->mbss_support = 0;
|
||||
}
|
||||
|
||||
int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id,
|
||||
struct wmi_twt_enable_params *params)
|
||||
{
|
||||
struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
struct ath11k_base *ab = wmi->wmi_ab->ab;
|
||||
@ -3083,28 +3124,22 @@ ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id)
|
||||
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_TWT_ENABLE_CMD) |
|
||||
FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
|
||||
cmd->pdev_id = pdev_id;
|
||||
cmd->sta_cong_timer_ms = ATH11K_TWT_DEF_STA_CONG_TIMER_MS;
|
||||
cmd->default_slot_size = ATH11K_TWT_DEF_DEFAULT_SLOT_SIZE;
|
||||
cmd->congestion_thresh_setup = ATH11K_TWT_DEF_CONGESTION_THRESH_SETUP;
|
||||
cmd->congestion_thresh_teardown =
|
||||
ATH11K_TWT_DEF_CONGESTION_THRESH_TEARDOWN;
|
||||
cmd->congestion_thresh_critical =
|
||||
ATH11K_TWT_DEF_CONGESTION_THRESH_CRITICAL;
|
||||
cmd->interference_thresh_teardown =
|
||||
ATH11K_TWT_DEF_INTERFERENCE_THRESH_TEARDOWN;
|
||||
cmd->interference_thresh_setup =
|
||||
ATH11K_TWT_DEF_INTERFERENCE_THRESH_SETUP;
|
||||
cmd->min_no_sta_setup = ATH11K_TWT_DEF_MIN_NO_STA_SETUP;
|
||||
cmd->min_no_sta_teardown = ATH11K_TWT_DEF_MIN_NO_STA_TEARDOWN;
|
||||
cmd->no_of_bcast_mcast_slots = ATH11K_TWT_DEF_NO_OF_BCAST_MCAST_SLOTS;
|
||||
cmd->min_no_twt_slots = ATH11K_TWT_DEF_MIN_NO_TWT_SLOTS;
|
||||
cmd->max_no_sta_twt = ATH11K_TWT_DEF_MAX_NO_STA_TWT;
|
||||
cmd->mode_check_interval = ATH11K_TWT_DEF_MODE_CHECK_INTERVAL;
|
||||
cmd->add_sta_slot_interval = ATH11K_TWT_DEF_ADD_STA_SLOT_INTERVAL;
|
||||
cmd->remove_sta_slot_interval =
|
||||
ATH11K_TWT_DEF_REMOVE_STA_SLOT_INTERVAL;
|
||||
/* TODO add MBSSID support */
|
||||
cmd->mbss_support = 0;
|
||||
cmd->sta_cong_timer_ms = params->sta_cong_timer_ms;
|
||||
cmd->default_slot_size = params->default_slot_size;
|
||||
cmd->congestion_thresh_setup = params->congestion_thresh_setup;
|
||||
cmd->congestion_thresh_teardown = params->congestion_thresh_teardown;
|
||||
cmd->congestion_thresh_critical = params->congestion_thresh_critical;
|
||||
cmd->interference_thresh_teardown = params->interference_thresh_teardown;
|
||||
cmd->interference_thresh_setup = params->interference_thresh_setup;
|
||||
cmd->min_no_sta_setup = params->min_no_sta_setup;
|
||||
cmd->min_no_sta_teardown = params->min_no_sta_teardown;
|
||||
cmd->no_of_bcast_mcast_slots = params->no_of_bcast_mcast_slots;
|
||||
cmd->min_no_twt_slots = params->min_no_twt_slots;
|
||||
cmd->max_no_sta_twt = params->max_no_sta_twt;
|
||||
cmd->mode_check_interval = params->mode_check_interval;
|
||||
cmd->add_sta_slot_interval = params->add_sta_slot_interval;
|
||||
cmd->remove_sta_slot_interval = params->remove_sta_slot_interval;
|
||||
cmd->mbss_support = params->mbss_support;
|
||||
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_TWT_ENABLE_CMDID);
|
||||
if (ret) {
|
||||
@ -6767,6 +6802,107 @@ static void ath11k_bcn_tx_status_event(struct ath11k_base *ab, struct sk_buff *s
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void ath11k_wmi_event_peer_sta_ps_state_chg(struct ath11k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const struct wmi_peer_sta_ps_state_chg_event *ev;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ath11k_peer *peer;
|
||||
struct ath11k *ar;
|
||||
struct ath11k_sta *arsta;
|
||||
const void **tb;
|
||||
enum ath11k_wmi_peer_ps_state peer_previous_ps_state;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_PEER_STA_PS_STATECHANGE_EVENT];
|
||||
if (!ev) {
|
||||
ath11k_warn(ab, "failed to fetch sta ps change ev");
|
||||
kfree(tb);
|
||||
return;
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
"peer sta ps chnange ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n",
|
||||
ev->peer_macaddr.addr, ev->peer_ps_state,
|
||||
ev->ps_supported_bitmap, ev->peer_ps_valid,
|
||||
ev->peer_ps_timestamp);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
|
||||
peer = ath11k_peer_find_by_addr(ab, ev->peer_macaddr.addr);
|
||||
|
||||
if (!peer) {
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
ath11k_warn(ab, "peer not found %pM\n", ev->peer_macaddr.addr);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ar = ath11k_mac_get_ar_by_vdev_id(ab, peer->vdev_id);
|
||||
|
||||
if (!ar) {
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
ath11k_warn(ab, "invalid vdev id in peer sta ps state change ev %d",
|
||||
peer->vdev_id);
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
sta = peer->sta;
|
||||
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
if (!sta) {
|
||||
ath11k_warn(ab, "failed to find station entry %pM\n",
|
||||
ev->peer_macaddr.addr);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
peer_previous_ps_state = arsta->peer_ps_state;
|
||||
arsta->peer_ps_state = ev->peer_ps_state;
|
||||
arsta->peer_current_ps_valid = !!ev->peer_ps_valid;
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
|
||||
ar->ab->wmi_ab.svc_map)) {
|
||||
if (!(ev->ps_supported_bitmap & WMI_PEER_PS_VALID) ||
|
||||
!(ev->ps_supported_bitmap & WMI_PEER_PS_STATE_TIMESTAMP) ||
|
||||
!ev->peer_ps_valid)
|
||||
goto out;
|
||||
|
||||
if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON) {
|
||||
arsta->ps_start_time = ev->peer_ps_timestamp;
|
||||
arsta->ps_start_jiffies = jiffies;
|
||||
} else if (arsta->peer_ps_state == WMI_PEER_PS_STATE_OFF &&
|
||||
peer_previous_ps_state == WMI_PEER_PS_STATE_ON) {
|
||||
arsta->ps_total_duration = arsta->ps_total_duration +
|
||||
(ev->peer_ps_timestamp - arsta->ps_start_time);
|
||||
}
|
||||
|
||||
if (ar->ps_timekeeper_enable)
|
||||
trace_ath11k_ps_timekeeper(ar, ev->peer_macaddr.addr,
|
||||
ev->peer_ps_timestamp,
|
||||
arsta->peer_ps_state);
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
exit:
|
||||
rcu_read_unlock();
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
static void ath11k_vdev_stopped_event(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
struct ath11k *ar;
|
||||
@ -7409,7 +7545,53 @@ static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff
|
||||
|
||||
static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
ath11k_debugfs_fw_stats_process(ab, skb);
|
||||
struct ath11k_fw_stats stats = {};
|
||||
struct ath11k *ar;
|
||||
int ret;
|
||||
|
||||
INIT_LIST_HEAD(&stats.pdevs);
|
||||
INIT_LIST_HEAD(&stats.vdevs);
|
||||
INIT_LIST_HEAD(&stats.bcn);
|
||||
|
||||
ret = ath11k_wmi_pull_fw_stats(ab, skb, &stats);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to pull fw stats: %d\n", ret);
|
||||
goto free;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
ar = ath11k_mac_get_ar_by_pdev_id(ab, stats.pdev_id);
|
||||
if (!ar) {
|
||||
rcu_read_unlock();
|
||||
ath11k_warn(ab, "failed to get ar for pdev_id %d: %d\n",
|
||||
stats.pdev_id, ret);
|
||||
goto free;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
/* WMI_REQUEST_PDEV_STAT can be requested via .get_txpower mac ops or via
|
||||
* debugfs fw stats. Therefore, processing it separately.
|
||||
*/
|
||||
if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
|
||||
list_splice_tail_init(&stats.pdevs, &ar->fw_stats.pdevs);
|
||||
ar->fw_stats_done = true;
|
||||
goto complete;
|
||||
}
|
||||
|
||||
/* WMI_REQUEST_VDEV_STAT, WMI_REQUEST_BCN_STAT and WMI_REQUEST_RSSI_PER_CHAIN_STAT
|
||||
* are currently requested only via debugfs fw stats. Hence, processing these
|
||||
* in debugfs context
|
||||
*/
|
||||
ath11k_debugfs_fw_stats_process(ar, &stats);
|
||||
|
||||
complete:
|
||||
complete(&ar->fw_stats_complete);
|
||||
rcu_read_unlock();
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
free:
|
||||
ath11k_fw_stats_free(&stats);
|
||||
}
|
||||
|
||||
/* PDEV_CTL_FAILSAFE_CHECK_EVENT is received from FW when the frequency scanned
|
||||
@ -7960,6 +8142,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
case WMI_DIAG_EVENTID:
|
||||
ath11k_wmi_diag_event(ab, skb);
|
||||
break;
|
||||
case WMI_PEER_STA_PS_STATECHG_EVENTID:
|
||||
ath11k_wmi_event_peer_sta_ps_state_chg(ab, skb);
|
||||
break;
|
||||
case WMI_GTK_OFFLOAD_STATUS_EVENTID:
|
||||
ath11k_wmi_gtk_offload_status_event(ab, skb);
|
||||
break;
|
||||
@ -8962,12 +9147,13 @@ int ath11k_wmi_sta_keepalive(struct ath11k *ar,
|
||||
cmd->interval = arg->interval;
|
||||
cmd->method = arg->method;
|
||||
|
||||
arp = (struct wmi_sta_keepalive_arp_resp *)(cmd + 1);
|
||||
arp->tlv_header = FIELD_PREP(WMI_TLV_TAG,
|
||||
WMI_TAG_STA_KEEPALIVE_ARP_RESPONSE) |
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*arp) - TLV_HDR_SIZE);
|
||||
|
||||
if (arg->method == WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE ||
|
||||
arg->method == WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST) {
|
||||
arp = (struct wmi_sta_keepalive_arp_resp *)(cmd + 1);
|
||||
arp->tlv_header = FIELD_PREP(WMI_TLV_TAG,
|
||||
WMI_TAG_STA_KEEPALVE_ARP_RESPONSE) |
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*arp) - TLV_HDR_SIZE);
|
||||
arp->src_ip4_addr = arg->src_ip4_addr;
|
||||
arp->dest_ip4_addr = arg->dest_ip4_addr;
|
||||
ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr);
|
||||
|
@ -17,7 +17,7 @@ struct ath11k_vif;
|
||||
|
||||
#define PSOC_HOST_MAX_NUM_SS (8)
|
||||
|
||||
/* defines to set Packet extension values whic can be 0 us, 8 usec or 16 usec */
|
||||
/* defines to set Packet extension values which can be 0 us, 8 usec or 16 usec */
|
||||
#define MAX_HE_NSS 8
|
||||
#define MAX_HE_MODULATION 8
|
||||
#define MAX_HE_RU 4
|
||||
@ -1214,7 +1214,7 @@ enum wmi_tlv_tag {
|
||||
WMI_TAG_NS_OFFLOAD_TUPLE,
|
||||
WMI_TAG_FTM_INTG_CMD,
|
||||
WMI_TAG_STA_KEEPALIVE_CMD,
|
||||
WMI_TAG_STA_KEEPALVE_ARP_RESPONSE,
|
||||
WMI_TAG_STA_KEEPALIVE_ARP_RESPONSE,
|
||||
WMI_TAG_P2P_SET_VENDOR_IE_DATA_CMD,
|
||||
WMI_TAG_AP_PS_PEER_CMD,
|
||||
WMI_TAG_PEER_RATE_RETRY_SCHED_CMD,
|
||||
@ -2090,6 +2090,7 @@ enum wmi_tlv_service {
|
||||
WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET = 213,
|
||||
WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219,
|
||||
WMI_TLV_SERVICE_EXT2_MSG = 220,
|
||||
WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246,
|
||||
WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249,
|
||||
|
||||
/* The second 128 bits */
|
||||
@ -4482,7 +4483,7 @@ struct wmi_pdev_radar_ev {
|
||||
} __packed;
|
||||
|
||||
struct wmi_pdev_temperature_event {
|
||||
/* temperature value in Celcius degree */
|
||||
/* temperature value in Celsius degree */
|
||||
s32 temp;
|
||||
u32 pdev_id;
|
||||
} __packed;
|
||||
@ -4708,7 +4709,7 @@ enum wmi_sta_ps_param_tx_wake_threshold {
|
||||
*/
|
||||
enum wmi_sta_ps_param_pspoll_count {
|
||||
WMI_STA_PS_PSPOLL_COUNT_NO_MAX = 0,
|
||||
/* Values greater than 0 indicate the maximum numer of PS-Poll frames
|
||||
/* Values greater than 0 indicate the maximum number of PS-Poll frames
|
||||
* FW will send before waking up.
|
||||
*/
|
||||
};
|
||||
@ -4820,9 +4821,9 @@ enum wmi_rate_preamble {
|
||||
|
||||
/**
|
||||
* enum wmi_rtscts_prot_mode - Enable/Disable RTS/CTS and CTS2Self Protection.
|
||||
* @WMI_RTS_CTS_DISABLED : RTS/CTS protection is disabled.
|
||||
* @WMI_USE_RTS_CTS : RTS/CTS Enabled.
|
||||
* @WMI_USE_CTS2SELF : CTS to self protection Enabled.
|
||||
* @WMI_RTS_CTS_DISABLED: RTS/CTS protection is disabled.
|
||||
* @WMI_USE_RTS_CTS: RTS/CTS Enabled.
|
||||
* @WMI_USE_CTS2SELF: CTS to self protection Enabled.
|
||||
*/
|
||||
enum wmi_rtscts_prot_mode {
|
||||
WMI_RTS_CTS_DISABLED = 0,
|
||||
@ -4833,13 +4834,13 @@ enum wmi_rtscts_prot_mode {
|
||||
/**
|
||||
* enum wmi_rtscts_profile - Selection of RTS CTS profile along with enabling
|
||||
* protection mode.
|
||||
* @WMI_RTSCTS_FOR_NO_RATESERIES - Neither of rate-series should use RTS-CTS
|
||||
* @WMI_RTSCTS_FOR_SECOND_RATESERIES - Only second rate-series will use RTS-CTS
|
||||
* @WMI_RTSCTS_ACROSS_SW_RETRIES - Only the second rate-series will use RTS-CTS,
|
||||
* but if there's a sw retry, both the rate
|
||||
* series will use RTS-CTS.
|
||||
* @WMI_RTSCTS_ERP - RTS/CTS used for ERP protection for every PPDU.
|
||||
* @WMI_RTSCTS_FOR_ALL_RATESERIES - Enable RTS-CTS for all rate series.
|
||||
* @WMI_RTSCTS_FOR_NO_RATESERIES: Neither of rate-series should use RTS-CTS
|
||||
* @WMI_RTSCTS_FOR_SECOND_RATESERIES: Only second rate-series will use RTS-CTS
|
||||
* @WMI_RTSCTS_ACROSS_SW_RETRIES: Only the second rate-series will use RTS-CTS,
|
||||
* but if there's a sw retry, both the rate
|
||||
* series will use RTS-CTS.
|
||||
* @WMI_RTSCTS_ERP: RTS/CTS used for ERP protection for every PPDU.
|
||||
* @WMI_RTSCTS_FOR_ALL_RATESERIES: Enable RTS-CTS for all rate series.
|
||||
*/
|
||||
enum wmi_rtscts_profile {
|
||||
WMI_RTSCTS_FOR_NO_RATESERIES = 0,
|
||||
@ -4933,6 +4934,25 @@ struct wmi_wmm_params_all_arg {
|
||||
#define ATH11K_TWT_DEF_ADD_STA_SLOT_INTERVAL 1000
|
||||
#define ATH11K_TWT_DEF_REMOVE_STA_SLOT_INTERVAL 5000
|
||||
|
||||
struct wmi_twt_enable_params {
|
||||
u32 sta_cong_timer_ms;
|
||||
u32 mbss_support;
|
||||
u32 default_slot_size;
|
||||
u32 congestion_thresh_setup;
|
||||
u32 congestion_thresh_teardown;
|
||||
u32 congestion_thresh_critical;
|
||||
u32 interference_thresh_teardown;
|
||||
u32 interference_thresh_setup;
|
||||
u32 min_no_sta_setup;
|
||||
u32 min_no_sta_teardown;
|
||||
u32 no_of_bcast_mcast_slots;
|
||||
u32 min_no_twt_slots;
|
||||
u32 max_no_sta_twt;
|
||||
u32 mode_check_interval;
|
||||
u32 add_sta_slot_interval;
|
||||
u32 remove_sta_slot_interval;
|
||||
};
|
||||
|
||||
struct wmi_twt_enable_params_cmd {
|
||||
u32 tlv_header;
|
||||
u32 pdev_id;
|
||||
@ -5350,6 +5370,26 @@ struct wmi_debug_log_config_cmd_fixed_param {
|
||||
#define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ)
|
||||
#define WMI_SEND_TIMEOUT_HZ (3 * HZ)
|
||||
|
||||
enum ath11k_wmi_peer_ps_state {
|
||||
WMI_PEER_PS_STATE_OFF,
|
||||
WMI_PEER_PS_STATE_ON,
|
||||
WMI_PEER_PS_STATE_DISABLED,
|
||||
};
|
||||
|
||||
enum wmi_peer_ps_supported_bitmap {
|
||||
/* Used to indicate that power save state change is valid */
|
||||
WMI_PEER_PS_VALID = 0x1,
|
||||
WMI_PEER_PS_STATE_TIMESTAMP = 0x2,
|
||||
};
|
||||
|
||||
struct wmi_peer_sta_ps_state_chg_event {
|
||||
struct wmi_mac_addr peer_macaddr;
|
||||
u32 peer_ps_state;
|
||||
u32 ps_supported_bitmap;
|
||||
u32 peer_ps_valid;
|
||||
u32 peer_ps_timestamp;
|
||||
} __packed;
|
||||
|
||||
struct ath11k_wmi_base {
|
||||
struct ath11k_base *ab;
|
||||
struct ath11k_pdev_wmi wmi[MAX_RADIOS];
|
||||
@ -6039,7 +6079,9 @@ void ath11k_wmi_fw_stats_fill(struct ath11k *ar,
|
||||
struct ath11k_fw_stats *fw_stats, u32 stats_id,
|
||||
char *buf);
|
||||
int ath11k_wmi_simulate_radar(struct ath11k *ar);
|
||||
int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id);
|
||||
void ath11k_wmi_fill_default_twt_params(struct wmi_twt_enable_params *twt_params);
|
||||
int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id,
|
||||
struct wmi_twt_enable_params *params);
|
||||
int ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id);
|
||||
int ath11k_wmi_send_twt_add_dialog_cmd(struct ath11k *ar,
|
||||
struct wmi_twt_add_dialog_params *params);
|
||||
|
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
@ -67,6 +68,13 @@ int ath11k_wow_wakeup(struct ath11k_base *ab)
|
||||
struct ath11k *ar = ath11k_ab_to_ar(ab, 0);
|
||||
int ret;
|
||||
|
||||
/* In the case of WCN6750, WoW wakeup is done
|
||||
* by sending SMP2P power save exit message
|
||||
* to the target processor.
|
||||
*/
|
||||
if (ab->hw_params.smp2p_wow_exit)
|
||||
return 0;
|
||||
|
||||
reinit_completion(&ab->wow.wakeup_completed);
|
||||
|
||||
ret = ath11k_wmi_wow_host_wakeup_ind(ar);
|
||||
@ -664,6 +672,12 @@ int ath11k_wow_op_suspend(struct ieee80211_hw *hw,
|
||||
struct ath11k *ar = hw->priv;
|
||||
int ret;
|
||||
|
||||
ret = ath11k_mac_wait_tx_complete(ar);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to wait tx complete: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ret = ath11k_dp_rx_pktlog_stop(ar->ab, true);
|
||||
@ -695,13 +709,6 @@ int ath11k_wow_op_suspend(struct ieee80211_hw *hw,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ath11k_mac_drain_tx(ar);
|
||||
ret = ath11k_mac_wait_tx_complete(ar);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to wait tx complete: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = ath11k_wow_set_hw_filter(ar);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set hw filter: %d\n",
|
||||
|
@ -1744,7 +1744,7 @@ static void ar9003_hw_spectral_scan_config(struct ath_hw *ah,
|
||||
REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_FFT_ENA);
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE);
|
||||
|
||||
/* on AR93xx and newer, count = 0 will make the the chip send
|
||||
/* on AR93xx and newer, count = 0 will make the chip send
|
||||
* spectral samples endlessly. Check if this really was intended,
|
||||
* and fix otherwise.
|
||||
*/
|
||||
|
@ -1113,7 +1113,7 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
|
||||
if (!avp->assoc)
|
||||
return false;
|
||||
|
||||
skb = ieee80211_nullfunc_get(sc->hw, vif, false);
|
||||
skb = ieee80211_nullfunc_get(sc->hw, vif, -1, false);
|
||||
if (!skb)
|
||||
return false;
|
||||
|
||||
|
@ -710,7 +710,7 @@ struct ath_spec_scan {
|
||||
/**
|
||||
* struct ath_hw_ops - callbacks used by hardware code and driver code
|
||||
*
|
||||
* This structure contains callbacks designed to to be used internally by
|
||||
* This structure contains callbacks designed to be used internally by
|
||||
* hardware code and also by the lower level driver.
|
||||
*
|
||||
* @config_pci_powersave:
|
||||
|
@ -2160,7 +2160,7 @@ static void setup_frame_info(struct ieee80211_hw *hw,
|
||||
fi->keyix = an->ps_key;
|
||||
else
|
||||
fi->keyix = ATH9K_TXKEYIX_INVALID;
|
||||
fi->dyn_smps = sta && sta->smps_mode == IEEE80211_SMPS_DYNAMIC;
|
||||
fi->dyn_smps = sta && sta->deflink.smps_mode == IEEE80211_SMPS_DYNAMIC;
|
||||
fi->keytype = keytype;
|
||||
fi->framelen = framelen;
|
||||
fi->tx_power = txpower;
|
||||
|
@ -2677,7 +2677,7 @@ struct ani_global_security_stats {
|
||||
* management information base (MIB) object is enabled */
|
||||
u32 rx_wep_unencrypted_frm_cnt;
|
||||
|
||||
/* The number of received MSDU packets that that the 802.11 station
|
||||
/* The number of received MSDU packets that the 802.11 station
|
||||
* discarded because of MIC failures */
|
||||
u32 rx_mic_fail_cnt;
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/random.h>
|
||||
#include "txrx.h"
|
||||
|
||||
static inline int get_rssi0(struct wcn36xx_rx_bd *bd)
|
||||
@ -278,6 +279,7 @@ static void wcn36xx_update_survey(struct wcn36xx *wcn, int rssi, int snr,
|
||||
struct ieee80211_supported_band *sband;
|
||||
int idx;
|
||||
int i;
|
||||
u8 snr_sample = snr & 0xff;
|
||||
|
||||
idx = 0;
|
||||
if (band == NL80211_BAND_5GHZ)
|
||||
@ -297,6 +299,8 @@ static void wcn36xx_update_survey(struct wcn36xx *wcn, int rssi, int snr,
|
||||
wcn->chan_survey[idx].rssi = rssi;
|
||||
wcn->chan_survey[idx].snr = snr;
|
||||
spin_unlock(&wcn->survey_lock);
|
||||
|
||||
add_device_randomness(&snr_sample, sizeof(snr_sample));
|
||||
}
|
||||
|
||||
int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
|
||||
|
@ -2479,11 +2479,7 @@ static void b43_nphy_gain_ctl_workarounds_rev19(struct b43_wldev *dev)
|
||||
|
||||
static void b43_nphy_gain_ctl_workarounds_rev7(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
|
||||
switch (phy->rev) {
|
||||
/* TODO */
|
||||
}
|
||||
/* TODO - should depend on phy->rev */
|
||||
}
|
||||
|
||||
static void b43_nphy_gain_ctl_workarounds_rev3(struct b43_wldev *dev)
|
||||
|
@ -87,6 +87,8 @@ struct brcmf_proto_bcdc_header {
|
||||
* plus any space that might be needed
|
||||
* for bus alignment padding.
|
||||
*/
|
||||
#define ROUND_UP_MARGIN 2048
|
||||
|
||||
struct brcmf_bcdc {
|
||||
u16 reqid;
|
||||
u8 bus_header[BUS_HEADER_LEN];
|
||||
@ -470,7 +472,7 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
|
||||
|
||||
drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
|
||||
drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN +
|
||||
sizeof(struct brcmf_proto_bcdc_dcmd);
|
||||
sizeof(struct brcmf_proto_bcdc_dcmd) + ROUND_UP_MARGIN;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
@ -983,6 +983,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4359),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43012),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_89359),
|
||||
{ /* end: all zeroes */ }
|
||||
|
@ -6,6 +6,8 @@
|
||||
#ifndef BRCMFMAC_BUS_H
|
||||
#define BRCMFMAC_BUS_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/firmware.h>
|
||||
#include "debug.h"
|
||||
|
||||
/* IDs of the 6 default common rings of msgbuf protocol */
|
||||
@ -34,6 +36,11 @@ enum brcmf_bus_protocol_type {
|
||||
BRCMF_PROTO_MSGBUF
|
||||
};
|
||||
|
||||
/* Firmware blobs that may be available */
|
||||
enum brcmf_blob_type {
|
||||
BRCMF_BLOB_CLM,
|
||||
};
|
||||
|
||||
struct brcmf_mp_device;
|
||||
|
||||
struct brcmf_bus_dcmd {
|
||||
@ -60,7 +67,7 @@ struct brcmf_bus_dcmd {
|
||||
* @wowl_config: specify if dongle is configured for wowl when going to suspend
|
||||
* @get_ramsize: obtain size of device memory.
|
||||
* @get_memdump: obtain device memory dump in provided buffer.
|
||||
* @get_fwname: obtain firmware name.
|
||||
* @get_blob: obtain a firmware blob.
|
||||
*
|
||||
* This structure provides an abstract interface towards the
|
||||
* bus specific driver. For control messages to common driver
|
||||
@ -77,8 +84,8 @@ struct brcmf_bus_ops {
|
||||
void (*wowl_config)(struct device *dev, bool enabled);
|
||||
size_t (*get_ramsize)(struct device *dev);
|
||||
int (*get_memdump)(struct device *dev, void *data, size_t len);
|
||||
int (*get_fwname)(struct device *dev, const char *ext,
|
||||
unsigned char *fw_name);
|
||||
int (*get_blob)(struct device *dev, const struct firmware **fw,
|
||||
enum brcmf_blob_type type);
|
||||
void (*debugfs_create)(struct device *dev);
|
||||
int (*reset)(struct device *dev);
|
||||
};
|
||||
@ -220,10 +227,10 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len)
|
||||
}
|
||||
|
||||
static inline
|
||||
int brcmf_bus_get_fwname(struct brcmf_bus *bus, const char *ext,
|
||||
unsigned char *fw_name)
|
||||
int brcmf_bus_get_blob(struct brcmf_bus *bus, const struct firmware **fw,
|
||||
enum brcmf_blob_type type)
|
||||
{
|
||||
return bus->ops->get_fwname(bus->dev, ext, fw_name);
|
||||
return bus->ops->get_blob(bus->dev, fw, type);
|
||||
}
|
||||
|
||||
static inline
|
||||
|
@ -3164,10 +3164,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_if *ifp)
|
||||
{
|
||||
struct brcmf_pub *drvr = cfg->pub;
|
||||
struct brcmf_bss_info_le *bi;
|
||||
const struct brcmf_tlv *tim;
|
||||
size_t ie_len;
|
||||
u8 *ie;
|
||||
struct brcmf_bss_info_le *bi = NULL;
|
||||
s32 err = 0;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
@ -3181,29 +3178,8 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
|
||||
bphy_err(drvr, "Could not get bss info %d\n", err);
|
||||
goto update_bss_info_out;
|
||||
}
|
||||
|
||||
bi = (struct brcmf_bss_info_le *)(cfg->extra_buf + 4);
|
||||
err = brcmf_inform_single_bss(cfg, bi);
|
||||
if (err)
|
||||
goto update_bss_info_out;
|
||||
|
||||
ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset);
|
||||
ie_len = le32_to_cpu(bi->ie_length);
|
||||
|
||||
tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
|
||||
if (!tim) {
|
||||
/*
|
||||
* active scan was done so we could not get dtim
|
||||
* information out of probe response.
|
||||
* so we speficially query dtim information to dongle.
|
||||
*/
|
||||
u32 var;
|
||||
err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var);
|
||||
if (err) {
|
||||
bphy_err(drvr, "wl dtim_assoc failed (%d)\n", err);
|
||||
goto update_bss_info_out;
|
||||
}
|
||||
}
|
||||
|
||||
update_bss_info_out:
|
||||
brcmf_dbg(TRACE, "Exit");
|
||||
@ -3988,7 +3964,6 @@ brcmf_update_pmklist(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp)
|
||||
struct brcmf_pmk_list_le *pmk_list;
|
||||
int i;
|
||||
u32 npmk;
|
||||
s32 err;
|
||||
|
||||
pmk_list = &cfg->pmk_list;
|
||||
npmk = le32_to_cpu(pmk_list->npmk);
|
||||
@ -3997,10 +3972,8 @@ brcmf_update_pmklist(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp)
|
||||
for (i = 0; i < npmk; i++)
|
||||
brcmf_dbg(CONN, "PMK[%d]: %pM\n", i, &pmk_list->pmk[i].bssid);
|
||||
|
||||
err = brcmf_fil_iovar_data_set(ifp, "pmkid_info", pmk_list,
|
||||
sizeof(*pmk_list));
|
||||
|
||||
return err;
|
||||
return brcmf_fil_iovar_data_set(ifp, "pmkid_info", pmk_list,
|
||||
sizeof(*pmk_list));
|
||||
}
|
||||
|
||||
static s32
|
||||
@ -5046,13 +5019,10 @@ brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev,
|
||||
struct cfg80211_beacon_data *info)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
err = brcmf_config_ap_mgmt_ie(ifp->vif, info);
|
||||
|
||||
return err;
|
||||
return brcmf_config_ap_mgmt_ie(ifp->vif, info);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -7490,6 +7460,7 @@ static bool brmcf_use_iso3166_ccode_fallback(struct brcmf_pub *drvr)
|
||||
return true;
|
||||
|
||||
switch (drvr->bus_if->chip) {
|
||||
case BRCM_CC_43430_CHIP_ID:
|
||||
case BRCM_CC_4345_CHIP_ID:
|
||||
case BRCM_CC_43602_CHIP_ID:
|
||||
return true;
|
||||
|
@ -641,6 +641,7 @@ static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize,
|
||||
*srsize = (32 * 1024);
|
||||
break;
|
||||
case BRCM_CC_43430_CHIP_ID:
|
||||
case CY_CC_43439_CHIP_ID:
|
||||
/* assume sr for now as we can not check
|
||||
* firmware sr capability at this point.
|
||||
*/
|
||||
@ -732,6 +733,10 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
|
||||
return 0x160000;
|
||||
case CY_CC_43752_CHIP_ID:
|
||||
return 0x170000;
|
||||
case BRCM_CC_4378_CHIP_ID:
|
||||
return 0x352000;
|
||||
case CY_CC_89459_CHIP_ID:
|
||||
return ((ci->pub.chiprev < 9) ? 0x180000 : 0x160000);
|
||||
default:
|
||||
brcmf_err("unknown chip: %s\n", ci->pub.name);
|
||||
break;
|
||||
@ -1258,7 +1263,8 @@ brcmf_chip_cm3_set_passive(struct brcmf_chip_priv *chip)
|
||||
brcmf_chip_resetcore(core, 0, 0, 0);
|
||||
|
||||
/* disable bank #3 remap for this device */
|
||||
if (chip->pub.chip == BRCM_CC_43430_CHIP_ID) {
|
||||
if (chip->pub.chip == BRCM_CC_43430_CHIP_ID ||
|
||||
chip->pub.chip == CY_CC_43439_CHIP_ID) {
|
||||
sr = container_of(core, struct brcmf_core_priv, pub);
|
||||
brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankidx), 3);
|
||||
brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankpda), 0);
|
||||
@ -1416,10 +1422,12 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
|
||||
reg = chip->ops->read32(chip->ctx, addr);
|
||||
return (reg & pmu_cc3_mask) != 0;
|
||||
case BRCM_CC_43430_CHIP_ID:
|
||||
case CY_CC_43439_CHIP_ID:
|
||||
addr = CORE_CC_REG(base, sr_control1);
|
||||
reg = chip->ops->read32(chip->ctx, addr);
|
||||
return reg != 0;
|
||||
case CY_CC_4373_CHIP_ID:
|
||||
case CY_CC_89459_CHIP_ID:
|
||||
/* explicitly check SR engine enable bit */
|
||||
addr = CORE_CC_REG(base, sr_control0);
|
||||
reg = chip->ops->read32(chip->ctx, addr);
|
||||
|
@ -123,7 +123,6 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
|
||||
struct brcmf_bus *bus = drvr->bus_if;
|
||||
struct brcmf_dload_data_le *chunk_buf;
|
||||
const struct firmware *clm = NULL;
|
||||
u8 clm_name[BRCMF_FW_NAME_LEN];
|
||||
u32 chunk_len;
|
||||
u32 datalen;
|
||||
u32 cumulative_len;
|
||||
@ -133,15 +132,8 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
memset(clm_name, 0, sizeof(clm_name));
|
||||
err = brcmf_bus_get_fwname(bus, ".clm_blob", clm_name);
|
||||
if (err) {
|
||||
bphy_err(drvr, "get CLM blob file name failed (%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = firmware_request_nowarn(&clm, clm_name, bus->dev);
|
||||
if (err) {
|
||||
err = brcmf_bus_get_blob(bus, &clm, BRCMF_BLOB_CLM);
|
||||
if (err || !clm) {
|
||||
brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
|
||||
err);
|
||||
return 0;
|
||||
|
@ -53,6 +53,7 @@ struct brcmf_mp_device {
|
||||
struct brcmfmac_pd_cc *country_codes;
|
||||
const char *board_type;
|
||||
unsigned char mac[ETH_ALEN];
|
||||
const char *antenna_sku;
|
||||
union {
|
||||
struct brcmfmac_sdio_pd sdio;
|
||||
} bus;
|
||||
|
@ -292,6 +292,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct ethhdr *eh;
|
||||
int head_delta;
|
||||
unsigned int tx_bytes = skb->len;
|
||||
|
||||
brcmf_dbg(DATA, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
|
||||
|
||||
@ -366,7 +367,7 @@ done:
|
||||
ndev->stats.tx_dropped++;
|
||||
} else {
|
||||
ndev->stats.tx_packets++;
|
||||
ndev->stats.tx_bytes += skb->len;
|
||||
ndev->stats.tx_bytes += tx_bytes;
|
||||
}
|
||||
|
||||
/* Return ok: we always eat the packet */
|
||||
|
@ -24,6 +24,13 @@ static const struct brcmf_dmi_data acepc_t8_data = {
|
||||
BRCM_CC_4345_CHIP_ID, 6, "acepc-t8"
|
||||
};
|
||||
|
||||
/* The Chuwi Hi8 Pro uses the same Ampak AP6212 module as the Chuwi Vi8 Plus
|
||||
* and the nvram for the Vi8 Plus is already in linux-firmware, so use that.
|
||||
*/
|
||||
static const struct brcmf_dmi_data chuwi_hi8_pro_data = {
|
||||
BRCM_CC_43430_CHIP_ID, 0, "ilife-S806"
|
||||
};
|
||||
|
||||
static const struct brcmf_dmi_data gpd_win_pocket_data = {
|
||||
BRCM_CC_4356_CHIP_ID, 2, "gpd-win-pocket"
|
||||
};
|
||||
@ -75,6 +82,17 @@ static const struct dmi_system_id dmi_platform_data[] = {
|
||||
},
|
||||
.driver_data = (void *)&acepc_t8_data,
|
||||
},
|
||||
{
|
||||
/* Chuwi Hi8 Pro with D2D3_Hi8Pro.233 BIOS */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
|
||||
DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "MRD"),
|
||||
/* Above strings are too generic, also match on BIOS date */
|
||||
DMI_MATCH(DMI_BIOS_DATE, "05/10/2016"),
|
||||
},
|
||||
.driver_data = (void *)&chuwi_hi8_pro_data,
|
||||
},
|
||||
{
|
||||
/* Cyberbook T116 rugged tablet */
|
||||
.matches = {
|
||||
|
@ -249,7 +249,8 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
|
||||
memset(&gscan_cfg, 0, sizeof(gscan_cfg));
|
||||
if (drvr->bus_if->chip != BRCM_CC_43430_CHIP_ID &&
|
||||
drvr->bus_if->chip != BRCM_CC_4345_CHIP_ID &&
|
||||
drvr->bus_if->chip != BRCM_CC_43454_CHIP_ID)
|
||||
drvr->bus_if->chip != BRCM_CC_43454_CHIP_ID &&
|
||||
drvr->bus_if->chip != CY_CC_43439_CHIP_ID)
|
||||
brcmf_feat_iovar_data_set(ifp, BRCMF_FEAT_GSCAN,
|
||||
"pfn_gscan_cfg",
|
||||
&gscan_cfg, sizeof(gscan_cfg));
|
||||
|
@ -21,6 +21,8 @@
|
||||
#define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
|
||||
#define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */
|
||||
#define BRCMF_FW_DEFAULT_BOARDREV "boardrev=0xff"
|
||||
#define BRCMF_FW_MACADDR_FMT "macaddr=%pM"
|
||||
#define BRCMF_FW_MACADDR_LEN (7 + ETH_ALEN * 3)
|
||||
|
||||
enum nvram_parser_state {
|
||||
IDLE,
|
||||
@ -44,6 +46,7 @@ enum nvram_parser_state {
|
||||
* @multi_dev_v1: detect pcie multi device v1 (compressed).
|
||||
* @multi_dev_v2: detect pcie multi device v2.
|
||||
* @boardrev_found: nvram contains boardrev information.
|
||||
* @strip_mac: strip the MAC address.
|
||||
*/
|
||||
struct nvram_parser {
|
||||
enum nvram_parser_state state;
|
||||
@ -57,6 +60,7 @@ struct nvram_parser {
|
||||
bool multi_dev_v1;
|
||||
bool multi_dev_v2;
|
||||
bool boardrev_found;
|
||||
bool strip_mac;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -121,6 +125,10 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
|
||||
nvp->multi_dev_v2 = true;
|
||||
if (strncmp(&nvp->data[nvp->entry], "boardrev", 8) == 0)
|
||||
nvp->boardrev_found = true;
|
||||
/* strip macaddr if platform MAC overrides */
|
||||
if (nvp->strip_mac &&
|
||||
strncmp(&nvp->data[nvp->entry], "macaddr", 7) == 0)
|
||||
st = COMMENT;
|
||||
} else if (!is_nvram_char(c) || c == ' ') {
|
||||
brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
|
||||
nvp->line, nvp->column);
|
||||
@ -209,6 +217,7 @@ static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
|
||||
size = data_len;
|
||||
/* Add space for properties we may add */
|
||||
size += strlen(BRCMF_FW_DEFAULT_BOARDREV) + 1;
|
||||
size += BRCMF_FW_MACADDR_LEN + 1;
|
||||
/* Alloc for extra 0 byte + roundup by 4 + length field */
|
||||
size += 1 + 3 + sizeof(u32);
|
||||
nvp->nvram = kzalloc(size, GFP_KERNEL);
|
||||
@ -368,22 +377,37 @@ static void brcmf_fw_add_defaults(struct nvram_parser *nvp)
|
||||
nvp->nvram_len++;
|
||||
}
|
||||
|
||||
static void brcmf_fw_add_macaddr(struct nvram_parser *nvp, u8 *mac)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = scnprintf(&nvp->nvram[nvp->nvram_len], BRCMF_FW_MACADDR_LEN + 1,
|
||||
BRCMF_FW_MACADDR_FMT, mac);
|
||||
WARN_ON(len != BRCMF_FW_MACADDR_LEN);
|
||||
nvp->nvram_len += len + 1;
|
||||
}
|
||||
|
||||
/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
|
||||
* and ending in a NUL. Removes carriage returns, empty lines, comment lines,
|
||||
* and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
|
||||
* End of buffer is completed with token identifying length of buffer.
|
||||
*/
|
||||
static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
|
||||
u32 *new_length, u16 domain_nr, u16 bus_nr)
|
||||
u32 *new_length, u16 domain_nr, u16 bus_nr,
|
||||
struct device *dev)
|
||||
{
|
||||
struct nvram_parser nvp;
|
||||
u32 pad;
|
||||
u32 token;
|
||||
__le32 token_le;
|
||||
u8 mac[ETH_ALEN];
|
||||
|
||||
if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0)
|
||||
return NULL;
|
||||
|
||||
if (eth_platform_get_mac_address(dev, mac) == 0)
|
||||
nvp.strip_mac = true;
|
||||
|
||||
while (nvp.pos < data_len) {
|
||||
nvp.state = nv_parser_states[nvp.state](&nvp);
|
||||
if (nvp.state == END)
|
||||
@ -404,6 +428,9 @@ static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
|
||||
|
||||
brcmf_fw_add_defaults(&nvp);
|
||||
|
||||
if (nvp.strip_mac)
|
||||
brcmf_fw_add_macaddr(&nvp, mac);
|
||||
|
||||
pad = nvp.nvram_len;
|
||||
*new_length = roundup(nvp.nvram_len + 1, 4);
|
||||
while (pad != *new_length) {
|
||||
@ -430,6 +457,7 @@ struct brcmf_fw {
|
||||
struct device *dev;
|
||||
struct brcmf_fw_request *req;
|
||||
u32 curpos;
|
||||
unsigned int board_index;
|
||||
void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
|
||||
};
|
||||
|
||||
@ -537,7 +565,8 @@ static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
|
||||
if (data)
|
||||
nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length,
|
||||
fwctx->req->domain_nr,
|
||||
fwctx->req->bus_nr);
|
||||
fwctx->req->bus_nr,
|
||||
fwctx->dev);
|
||||
|
||||
if (free_bcm47xx_nvram)
|
||||
bcm47xx_nvram_release_contents(data);
|
||||
@ -587,39 +616,50 @@ static int brcmf_fw_complete_request(const struct firmware *fw,
|
||||
|
||||
static char *brcm_alt_fw_path(const char *path, const char *board_type)
|
||||
{
|
||||
char alt_path[BRCMF_FW_NAME_LEN];
|
||||
char suffix[5];
|
||||
char base[BRCMF_FW_NAME_LEN];
|
||||
const char *suffix;
|
||||
char *ret;
|
||||
|
||||
strscpy(alt_path, path, BRCMF_FW_NAME_LEN);
|
||||
/* At least one character + suffix */
|
||||
if (strlen(alt_path) < 5)
|
||||
if (!board_type)
|
||||
return NULL;
|
||||
|
||||
/* strip .txt or .bin at the end */
|
||||
strscpy(suffix, alt_path + strlen(alt_path) - 4, 5);
|
||||
alt_path[strlen(alt_path) - 4] = 0;
|
||||
strlcat(alt_path, ".", BRCMF_FW_NAME_LEN);
|
||||
strlcat(alt_path, board_type, BRCMF_FW_NAME_LEN);
|
||||
strlcat(alt_path, suffix, BRCMF_FW_NAME_LEN);
|
||||
suffix = strrchr(path, '.');
|
||||
if (!suffix || suffix == path)
|
||||
return NULL;
|
||||
|
||||
return kstrdup(alt_path, GFP_KERNEL);
|
||||
/* strip extension at the end */
|
||||
strscpy(base, path, BRCMF_FW_NAME_LEN);
|
||||
base[suffix - path] = 0;
|
||||
|
||||
ret = kasprintf(GFP_KERNEL, "%s.%s%s", base, board_type, suffix);
|
||||
if (!ret)
|
||||
brcmf_err("out of memory allocating firmware path for '%s'\n",
|
||||
path);
|
||||
|
||||
brcmf_dbg(TRACE, "FW alt path: %s\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int brcmf_fw_request_firmware(const struct firmware **fw,
|
||||
struct brcmf_fw *fwctx)
|
||||
{
|
||||
struct brcmf_fw_item *cur = &fwctx->req->items[fwctx->curpos];
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
/* Files can be board-specific, first try a board-specific path */
|
||||
if (cur->type == BRCMF_FW_TYPE_NVRAM && fwctx->req->board_type) {
|
||||
/* Files can be board-specific, first try board-specific paths */
|
||||
for (i = 0; i < ARRAY_SIZE(fwctx->req->board_types); i++) {
|
||||
char *alt_path;
|
||||
|
||||
alt_path = brcm_alt_fw_path(cur->path, fwctx->req->board_type);
|
||||
if (!fwctx->req->board_types[i])
|
||||
goto fallback;
|
||||
alt_path = brcm_alt_fw_path(cur->path,
|
||||
fwctx->req->board_types[i]);
|
||||
if (!alt_path)
|
||||
goto fallback;
|
||||
|
||||
ret = request_firmware(fw, alt_path, fwctx->dev);
|
||||
ret = firmware_request_nowarn(fw, alt_path, fwctx->dev);
|
||||
kfree(alt_path);
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
@ -653,15 +693,40 @@ static void brcmf_fw_request_done_alt_path(const struct firmware *fw, void *ctx)
|
||||
{
|
||||
struct brcmf_fw *fwctx = ctx;
|
||||
struct brcmf_fw_item *first = &fwctx->req->items[0];
|
||||
const char *board_type, *alt_path;
|
||||
int ret = 0;
|
||||
|
||||
/* Fall back to canonical path if board firmware not found */
|
||||
if (!fw)
|
||||
ret = request_firmware_nowait(THIS_MODULE, true, first->path,
|
||||
fwctx->dev, GFP_KERNEL, fwctx,
|
||||
brcmf_fw_request_done);
|
||||
if (fw) {
|
||||
brcmf_fw_request_done(fw, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fw || ret < 0)
|
||||
/* Try next board firmware */
|
||||
if (fwctx->board_index < ARRAY_SIZE(fwctx->req->board_types)) {
|
||||
board_type = fwctx->req->board_types[fwctx->board_index++];
|
||||
if (!board_type)
|
||||
goto fallback;
|
||||
alt_path = brcm_alt_fw_path(first->path, board_type);
|
||||
if (!alt_path)
|
||||
goto fallback;
|
||||
|
||||
ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
|
||||
fwctx->dev, GFP_KERNEL, fwctx,
|
||||
brcmf_fw_request_done_alt_path);
|
||||
kfree(alt_path);
|
||||
|
||||
if (ret < 0)
|
||||
brcmf_fw_request_done(fw, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
fallback:
|
||||
/* Fall back to canonical path if board firmware not found */
|
||||
ret = request_firmware_nowait(THIS_MODULE, true, first->path,
|
||||
fwctx->dev, GFP_KERNEL, fwctx,
|
||||
brcmf_fw_request_done);
|
||||
|
||||
if (ret < 0)
|
||||
brcmf_fw_request_done(fw, ctx);
|
||||
}
|
||||
|
||||
@ -705,10 +770,11 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
|
||||
fwctx->done = fw_cb;
|
||||
|
||||
/* First try alternative board-specific path if any */
|
||||
if (fwctx->req->board_type)
|
||||
if (fwctx->req->board_types[0])
|
||||
alt_path = brcm_alt_fw_path(first->path,
|
||||
fwctx->req->board_type);
|
||||
fwctx->req->board_types[0]);
|
||||
if (alt_path) {
|
||||
fwctx->board_index++;
|
||||
ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
|
||||
fwctx->dev, GFP_KERNEL, fwctx,
|
||||
brcmf_fw_request_done_alt_path);
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#define BRCMF_FW_DEFAULT_PATH "brcm/"
|
||||
|
||||
#define BRCMF_FW_MAX_BOARD_TYPES 8
|
||||
|
||||
/**
|
||||
* struct brcmf_firmware_mapping - Used to map chipid/revmask to firmware
|
||||
* filename and nvram filename. Each bus type implementation should create
|
||||
@ -66,7 +68,7 @@ struct brcmf_fw_request {
|
||||
u16 domain_nr;
|
||||
u16 bus_nr;
|
||||
u32 n_items;
|
||||
const char *board_type;
|
||||
const char *board_types[BRCMF_FW_MAX_BOARD_TYPES];
|
||||
struct brcmf_fw_item items[];
|
||||
};
|
||||
|
||||
|
@ -135,7 +135,7 @@
|
||||
/* Link Down indication in WoWL mode: */
|
||||
#define BRCMF_WOWL_LINKDOWN (1 << 31)
|
||||
|
||||
#define BRCMF_WOWL_MAXPATTERNS 8
|
||||
#define BRCMF_WOWL_MAXPATTERNS 16
|
||||
#define BRCMF_WOWL_MAXPATTERNSIZE 128
|
||||
|
||||
#define BRCMF_COUNTRY_BUF_SZ 4
|
||||
|
@ -8,10 +8,10 @@
|
||||
#ifdef CONFIG_BRCMFMAC_PROTO_MSGBUF
|
||||
|
||||
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM 64
|
||||
#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 512
|
||||
#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 1024
|
||||
#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM 64
|
||||
#define BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM 1024
|
||||
#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 512
|
||||
#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 1024
|
||||
#define BRCMF_H2D_TXFLOWRING_MAX_ITEM 512
|
||||
|
||||
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE 40
|
||||
|
@ -70,14 +70,24 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
|
||||
{
|
||||
struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio;
|
||||
struct device_node *root, *np = dev->of_node;
|
||||
const char *prop;
|
||||
int irq;
|
||||
int err;
|
||||
u32 irqf;
|
||||
u32 val;
|
||||
|
||||
/* Apple ARM64 platforms have their own idea of board type, passed in
|
||||
* via the device tree. They also have an antenna SKU parameter
|
||||
*/
|
||||
if (!of_property_read_string(np, "brcm,board-type", &prop))
|
||||
settings->board_type = prop;
|
||||
|
||||
if (!of_property_read_string(np, "apple,antenna-sku", &prop))
|
||||
settings->antenna_sku = prop;
|
||||
|
||||
/* Set board-type to the first string of the machine compatible prop */
|
||||
root = of_find_node_by_path("/");
|
||||
if (root) {
|
||||
if (root && !settings->board_type) {
|
||||
char *board_type;
|
||||
const char *tmp;
|
||||
|
||||
|
@ -59,6 +59,8 @@ BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie");
|
||||
BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie");
|
||||
BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie");
|
||||
BRCMF_FW_DEF(4371, "brcmfmac4371-pcie");
|
||||
BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie");
|
||||
BRCMF_FW_DEF(4355, "brcmfmac89459-pcie");
|
||||
|
||||
/* firmware config files */
|
||||
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt");
|
||||
@ -66,6 +68,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt");
|
||||
|
||||
/* per-board firmware binaries */
|
||||
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.bin");
|
||||
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.clm_blob");
|
||||
|
||||
static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
|
||||
BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
|
||||
@ -87,6 +90,8 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
|
||||
BRCMF_FW_ENTRY(BRCM_CC_43664_CHIP_ID, 0xFFFFFFF0, 4366C),
|
||||
BRCMF_FW_ENTRY(BRCM_CC_43666_CHIP_ID, 0xFFFFFFF0, 4366C),
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFFF, 4378B1), /* revision ID 3 */
|
||||
BRCMF_FW_ENTRY(CY_CC_89459_CHIP_ID, 0xFFFFFFFF, 4355),
|
||||
};
|
||||
|
||||
#define BRCMF_PCIE_FW_UP_TIMEOUT 5000 /* msec */
|
||||
@ -118,6 +123,12 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
|
||||
#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0 0x140
|
||||
#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1 0x144
|
||||
|
||||
#define BRCMF_PCIE_64_PCIE2REG_INTMASK 0xC14
|
||||
#define BRCMF_PCIE_64_PCIE2REG_MAILBOXINT 0xC30
|
||||
#define BRCMF_PCIE_64_PCIE2REG_MAILBOXMASK 0xC34
|
||||
#define BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0 0xA20
|
||||
#define BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1 0xA24
|
||||
|
||||
#define BRCMF_PCIE2_INTA 0x01
|
||||
#define BRCMF_PCIE2_INTB 0x02
|
||||
|
||||
@ -137,6 +148,8 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
|
||||
#define BRCMF_PCIE_MB_INT_D2H3_DB0 0x400000
|
||||
#define BRCMF_PCIE_MB_INT_D2H3_DB1 0x800000
|
||||
|
||||
#define BRCMF_PCIE_MB_INT_FN0 (BRCMF_PCIE_MB_INT_FN0_0 | \
|
||||
BRCMF_PCIE_MB_INT_FN0_1)
|
||||
#define BRCMF_PCIE_MB_INT_D2H_DB (BRCMF_PCIE_MB_INT_D2H0_DB0 | \
|
||||
BRCMF_PCIE_MB_INT_D2H0_DB1 | \
|
||||
BRCMF_PCIE_MB_INT_D2H1_DB0 | \
|
||||
@ -146,6 +159,40 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
|
||||
BRCMF_PCIE_MB_INT_D2H3_DB0 | \
|
||||
BRCMF_PCIE_MB_INT_D2H3_DB1)
|
||||
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H0_DB0 0x1
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H0_DB1 0x2
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H1_DB0 0x4
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H1_DB1 0x8
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H2_DB0 0x10
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H2_DB1 0x20
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H3_DB0 0x40
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H3_DB1 0x80
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H4_DB0 0x100
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H4_DB1 0x200
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H5_DB0 0x400
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H5_DB1 0x800
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H6_DB0 0x1000
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H6_DB1 0x2000
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H7_DB0 0x4000
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H7_DB1 0x8000
|
||||
|
||||
#define BRCMF_PCIE_64_MB_INT_D2H_DB (BRCMF_PCIE_64_MB_INT_D2H0_DB0 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H0_DB1 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H1_DB0 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H1_DB1 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H2_DB0 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H2_DB1 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H3_DB0 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H3_DB1 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H4_DB0 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H4_DB1 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H5_DB0 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H5_DB1 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H6_DB0 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H6_DB1 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H7_DB0 | \
|
||||
BRCMF_PCIE_64_MB_INT_D2H7_DB1)
|
||||
|
||||
#define BRCMF_PCIE_SHARED_VERSION_7 7
|
||||
#define BRCMF_PCIE_MIN_SHARED_VERSION 5
|
||||
#define BRCMF_PCIE_MAX_SHARED_VERSION BRCMF_PCIE_SHARED_VERSION_7
|
||||
@ -255,12 +302,24 @@ struct brcmf_pcie_core_info {
|
||||
u32 wrapbase;
|
||||
};
|
||||
|
||||
#define BRCMF_OTP_MAX_PARAM_LEN 16
|
||||
|
||||
struct brcmf_otp_params {
|
||||
char module[BRCMF_OTP_MAX_PARAM_LEN];
|
||||
char vendor[BRCMF_OTP_MAX_PARAM_LEN];
|
||||
char version[BRCMF_OTP_MAX_PARAM_LEN];
|
||||
bool valid;
|
||||
};
|
||||
|
||||
struct brcmf_pciedev_info {
|
||||
enum brcmf_pcie_state state;
|
||||
bool in_irq;
|
||||
struct pci_dev *pdev;
|
||||
char fw_name[BRCMF_FW_NAME_LEN];
|
||||
char nvram_name[BRCMF_FW_NAME_LEN];
|
||||
char clm_name[BRCMF_FW_NAME_LEN];
|
||||
const struct firmware *clm_fw;
|
||||
const struct brcmf_pcie_reginfo *reginfo;
|
||||
void __iomem *regs;
|
||||
void __iomem *tcm;
|
||||
u32 ram_base;
|
||||
@ -280,6 +339,7 @@ struct brcmf_pciedev_info {
|
||||
void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
|
||||
u16 value);
|
||||
struct brcmf_mp_device *settings;
|
||||
struct brcmf_otp_params otp;
|
||||
};
|
||||
|
||||
struct brcmf_pcie_ringbuf {
|
||||
@ -346,11 +406,49 @@ static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = {
|
||||
BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE
|
||||
};
|
||||
|
||||
struct brcmf_pcie_reginfo {
|
||||
u32 intmask;
|
||||
u32 mailboxint;
|
||||
u32 mailboxmask;
|
||||
u32 h2d_mailbox_0;
|
||||
u32 h2d_mailbox_1;
|
||||
u32 int_d2h_db;
|
||||
u32 int_fn0;
|
||||
};
|
||||
|
||||
static const struct brcmf_pcie_reginfo brcmf_reginfo_default = {
|
||||
.intmask = BRCMF_PCIE_PCIE2REG_INTMASK,
|
||||
.mailboxint = BRCMF_PCIE_PCIE2REG_MAILBOXINT,
|
||||
.mailboxmask = BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
|
||||
.h2d_mailbox_0 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0,
|
||||
.h2d_mailbox_1 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1,
|
||||
.int_d2h_db = BRCMF_PCIE_MB_INT_D2H_DB,
|
||||
.int_fn0 = BRCMF_PCIE_MB_INT_FN0,
|
||||
};
|
||||
|
||||
static const struct brcmf_pcie_reginfo brcmf_reginfo_64 = {
|
||||
.intmask = BRCMF_PCIE_64_PCIE2REG_INTMASK,
|
||||
.mailboxint = BRCMF_PCIE_64_PCIE2REG_MAILBOXINT,
|
||||
.mailboxmask = BRCMF_PCIE_64_PCIE2REG_MAILBOXMASK,
|
||||
.h2d_mailbox_0 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0,
|
||||
.h2d_mailbox_1 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1,
|
||||
.int_d2h_db = BRCMF_PCIE_64_MB_INT_D2H_DB,
|
||||
.int_fn0 = 0,
|
||||
};
|
||||
|
||||
static void brcmf_pcie_setup(struct device *dev, int ret,
|
||||
struct brcmf_fw_request *fwreq);
|
||||
static struct brcmf_fw_request *
|
||||
brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo);
|
||||
|
||||
static u16
|
||||
brcmf_pcie_read_reg16(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
|
||||
{
|
||||
void __iomem *address = devinfo->regs + reg_offset;
|
||||
|
||||
return ioread16(address);
|
||||
}
|
||||
|
||||
static u32
|
||||
brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
|
||||
{
|
||||
@ -496,6 +594,8 @@ brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
|
||||
}
|
||||
|
||||
|
||||
#define READCC32(devinfo, reg) brcmf_pcie_read_reg32(devinfo, \
|
||||
CHIPCREGOFFS(reg))
|
||||
#define WRITECC32(devinfo, reg, value) brcmf_pcie_write_reg32(devinfo, \
|
||||
CHIPCREGOFFS(reg), value)
|
||||
|
||||
@ -779,30 +879,29 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo,
|
||||
|
||||
static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo)
|
||||
{
|
||||
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK, 0);
|
||||
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask, 0);
|
||||
}
|
||||
|
||||
|
||||
static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo)
|
||||
{
|
||||
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
|
||||
BRCMF_PCIE_MB_INT_D2H_DB |
|
||||
BRCMF_PCIE_MB_INT_FN0_0 |
|
||||
BRCMF_PCIE_MB_INT_FN0_1);
|
||||
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask,
|
||||
devinfo->reginfo->int_d2h_db |
|
||||
devinfo->reginfo->int_fn0);
|
||||
}
|
||||
|
||||
static void brcmf_pcie_hostready(struct brcmf_pciedev_info *devinfo)
|
||||
{
|
||||
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1)
|
||||
brcmf_pcie_write_reg32(devinfo,
|
||||
BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1);
|
||||
devinfo->reginfo->h2d_mailbox_1, 1);
|
||||
}
|
||||
|
||||
static irqreturn_t brcmf_pcie_quick_check_isr(int irq, void *arg)
|
||||
{
|
||||
struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
|
||||
|
||||
if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT)) {
|
||||
if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint)) {
|
||||
brcmf_pcie_intr_disable(devinfo);
|
||||
brcmf_dbg(PCIE, "Enter\n");
|
||||
return IRQ_WAKE_THREAD;
|
||||
@ -817,15 +916,14 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
|
||||
u32 status;
|
||||
|
||||
devinfo->in_irq = true;
|
||||
status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
|
||||
status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
|
||||
brcmf_dbg(PCIE, "Enter %x\n", status);
|
||||
if (status) {
|
||||
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
|
||||
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint,
|
||||
status);
|
||||
if (status & (BRCMF_PCIE_MB_INT_FN0_0 |
|
||||
BRCMF_PCIE_MB_INT_FN0_1))
|
||||
if (status & devinfo->reginfo->int_fn0)
|
||||
brcmf_pcie_handle_mb_data(devinfo);
|
||||
if (status & BRCMF_PCIE_MB_INT_D2H_DB) {
|
||||
if (status & devinfo->reginfo->int_d2h_db) {
|
||||
if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
|
||||
brcmf_proto_msgbuf_rx_trigger(
|
||||
&devinfo->pdev->dev);
|
||||
@ -884,8 +982,8 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
|
||||
if (devinfo->in_irq)
|
||||
brcmf_err(bus, "Still in IRQ (processing) !!!\n");
|
||||
|
||||
status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
|
||||
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, status);
|
||||
status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
|
||||
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint, status);
|
||||
|
||||
devinfo->irq_allocated = false;
|
||||
}
|
||||
@ -937,7 +1035,7 @@ static int brcmf_pcie_ring_mb_ring_bell(void *ctx)
|
||||
|
||||
brcmf_dbg(PCIE, "RING !\n");
|
||||
/* Any arbitrary value will do, lets use 1 */
|
||||
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1);
|
||||
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->h2d_mailbox_0, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1382,23 +1480,25 @@ static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int brcmf_pcie_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
|
||||
static int brcmf_pcie_get_blob(struct device *dev, const struct firmware **fw,
|
||||
enum brcmf_blob_type type)
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_fw_request *fwreq;
|
||||
struct brcmf_fw_name fwnames[] = {
|
||||
{ ext, fw_name },
|
||||
};
|
||||
struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
|
||||
struct brcmf_pciedev_info *devinfo = buspub->devinfo;
|
||||
|
||||
fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
|
||||
brcmf_pcie_fwnames,
|
||||
ARRAY_SIZE(brcmf_pcie_fwnames),
|
||||
fwnames, ARRAY_SIZE(fwnames));
|
||||
if (!fwreq)
|
||||
return -ENOMEM;
|
||||
switch (type) {
|
||||
case BRCMF_BLOB_CLM:
|
||||
*fw = devinfo->clm_fw;
|
||||
devinfo->clm_fw = NULL;
|
||||
break;
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!*fw)
|
||||
return -ENOENT;
|
||||
|
||||
kfree(fwreq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1445,7 +1545,7 @@ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
|
||||
.wowl_config = brcmf_pcie_wowl_config,
|
||||
.get_ramsize = brcmf_pcie_get_ramsize,
|
||||
.get_memdump = brcmf_pcie_get_memdump,
|
||||
.get_fwname = brcmf_pcie_get_fwname,
|
||||
.get_blob = brcmf_pcie_get_blob,
|
||||
.reset = brcmf_pcie_reset,
|
||||
};
|
||||
|
||||
@ -1698,15 +1798,22 @@ static int brcmf_pcie_buscoreprep(void *ctx)
|
||||
static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
|
||||
{
|
||||
struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
|
||||
u32 val;
|
||||
struct brcmf_core *core;
|
||||
u32 val, reg;
|
||||
|
||||
devinfo->ci = chip;
|
||||
brcmf_pcie_reset_device(devinfo);
|
||||
|
||||
val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
|
||||
/* reginfo is not ready yet */
|
||||
core = brcmf_chip_get_core(chip, BCMA_CORE_PCIE2);
|
||||
if (core->rev >= 64)
|
||||
reg = BRCMF_PCIE_64_PCIE2REG_MAILBOXINT;
|
||||
else
|
||||
reg = BRCMF_PCIE_PCIE2REG_MAILBOXINT;
|
||||
|
||||
val = brcmf_pcie_read_reg32(devinfo, reg);
|
||||
if (val != 0xffffffff)
|
||||
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
|
||||
val);
|
||||
brcmf_pcie_write_reg32(devinfo, reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1729,8 +1836,206 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
|
||||
.write32 = brcmf_pcie_buscore_write32,
|
||||
};
|
||||
|
||||
#define BRCMF_OTP_SYS_VENDOR 0x15
|
||||
#define BRCMF_OTP_BRCM_CIS 0x80
|
||||
|
||||
#define BRCMF_OTP_VENDOR_HDR 0x00000008
|
||||
|
||||
static int
|
||||
brcmf_pcie_parse_otp_sys_vendor(struct brcmf_pciedev_info *devinfo,
|
||||
u8 *data, size_t size)
|
||||
{
|
||||
int idx = 4;
|
||||
const char *chip_params;
|
||||
const char *board_params;
|
||||
const char *p;
|
||||
|
||||
/* 4-byte header and two empty strings */
|
||||
if (size < 6)
|
||||
return -EINVAL;
|
||||
|
||||
if (get_unaligned_le32(data) != BRCMF_OTP_VENDOR_HDR)
|
||||
return -EINVAL;
|
||||
|
||||
chip_params = &data[idx];
|
||||
|
||||
/* Skip first string, including terminator */
|
||||
idx += strnlen(chip_params, size - idx) + 1;
|
||||
if (idx >= size)
|
||||
return -EINVAL;
|
||||
|
||||
board_params = &data[idx];
|
||||
|
||||
/* Skip to terminator of second string */
|
||||
idx += strnlen(board_params, size - idx);
|
||||
if (idx >= size)
|
||||
return -EINVAL;
|
||||
|
||||
/* At this point both strings are guaranteed NUL-terminated */
|
||||
brcmf_dbg(PCIE, "OTP: chip_params='%s' board_params='%s'\n",
|
||||
chip_params, board_params);
|
||||
|
||||
p = skip_spaces(board_params);
|
||||
while (*p) {
|
||||
char tag = *p++;
|
||||
const char *end;
|
||||
size_t len;
|
||||
|
||||
if (*p++ != '=') /* implicit NUL check */
|
||||
return -EINVAL;
|
||||
|
||||
/* *p might be NUL here, if so end == p and len == 0 */
|
||||
end = strchrnul(p, ' ');
|
||||
len = end - p;
|
||||
|
||||
/* leave 1 byte for NUL in destination string */
|
||||
if (len > (BRCMF_OTP_MAX_PARAM_LEN - 1))
|
||||
return -EINVAL;
|
||||
|
||||
/* Copy len characters plus a NUL terminator */
|
||||
switch (tag) {
|
||||
case 'M':
|
||||
strscpy(devinfo->otp.module, p, len + 1);
|
||||
break;
|
||||
case 'V':
|
||||
strscpy(devinfo->otp.vendor, p, len + 1);
|
||||
break;
|
||||
case 'm':
|
||||
strscpy(devinfo->otp.version, p, len + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip to next arg, if any */
|
||||
p = skip_spaces(end);
|
||||
}
|
||||
|
||||
brcmf_dbg(PCIE, "OTP: module=%s vendor=%s version=%s\n",
|
||||
devinfo->otp.module, devinfo->otp.vendor,
|
||||
devinfo->otp.version);
|
||||
|
||||
if (!devinfo->otp.module[0] ||
|
||||
!devinfo->otp.vendor[0] ||
|
||||
!devinfo->otp.version[0])
|
||||
return -EINVAL;
|
||||
|
||||
devinfo->otp.valid = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
brcmf_pcie_parse_otp(struct brcmf_pciedev_info *devinfo, u8 *otp, size_t size)
|
||||
{
|
||||
int p = 0;
|
||||
int ret = -EINVAL;
|
||||
|
||||
brcmf_dbg(PCIE, "parse_otp size=%zd\n", size);
|
||||
|
||||
while (p < (size - 1)) {
|
||||
u8 type = otp[p];
|
||||
u8 length = otp[p + 1];
|
||||
|
||||
if (type == 0)
|
||||
break;
|
||||
|
||||
if ((p + 2 + length) > size)
|
||||
break;
|
||||
|
||||
switch (type) {
|
||||
case BRCMF_OTP_SYS_VENDOR:
|
||||
brcmf_dbg(PCIE, "OTP @ 0x%x (%d): SYS_VENDOR\n",
|
||||
p, length);
|
||||
ret = brcmf_pcie_parse_otp_sys_vendor(devinfo,
|
||||
&otp[p + 2],
|
||||
length);
|
||||
break;
|
||||
case BRCMF_OTP_BRCM_CIS:
|
||||
brcmf_dbg(PCIE, "OTP @ 0x%x (%d): BRCM_CIS\n",
|
||||
p, length);
|
||||
break;
|
||||
default:
|
||||
brcmf_dbg(PCIE, "OTP @ 0x%x (%d): Unknown type 0x%x\n",
|
||||
p, length, type);
|
||||
break;
|
||||
}
|
||||
|
||||
p += 2 + length;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)
|
||||
{
|
||||
const struct pci_dev *pdev = devinfo->pdev;
|
||||
struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
|
||||
u32 coreid, base, words, idx, sromctl;
|
||||
u16 *otp;
|
||||
struct brcmf_core *core;
|
||||
int ret;
|
||||
|
||||
switch (devinfo->ci->chip) {
|
||||
case BRCM_CC_4378_CHIP_ID:
|
||||
coreid = BCMA_CORE_GCI;
|
||||
base = 0x1120;
|
||||
words = 0x170;
|
||||
break;
|
||||
default:
|
||||
/* OTP not supported on this chip */
|
||||
return 0;
|
||||
}
|
||||
|
||||
core = brcmf_chip_get_core(devinfo->ci, coreid);
|
||||
if (!core) {
|
||||
brcmf_err(bus, "No OTP core\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (coreid == BCMA_CORE_CHIPCOMMON) {
|
||||
/* Chips with OTP accessed via ChipCommon need additional
|
||||
* handling to access the OTP
|
||||
*/
|
||||
brcmf_pcie_select_core(devinfo, coreid);
|
||||
sromctl = READCC32(devinfo, sromcontrol);
|
||||
|
||||
if (!(sromctl & BCMA_CC_SROM_CONTROL_OTP_PRESENT)) {
|
||||
/* Chip lacks OTP, try without it... */
|
||||
brcmf_err(bus,
|
||||
"OTP unavailable, using default firmware\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Map OTP to shadow area */
|
||||
WRITECC32(devinfo, sromcontrol,
|
||||
sromctl | BCMA_CC_SROM_CONTROL_OTPSEL);
|
||||
}
|
||||
|
||||
otp = kcalloc(words, sizeof(u16), GFP_KERNEL);
|
||||
if (!otp)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Map bus window to SROM/OTP shadow area in core */
|
||||
base = brcmf_pcie_buscore_prep_addr(devinfo->pdev, base + core->base);
|
||||
|
||||
brcmf_dbg(PCIE, "OTP data:\n");
|
||||
for (idx = 0; idx < words; idx++) {
|
||||
otp[idx] = brcmf_pcie_read_reg16(devinfo, base + 2 * idx);
|
||||
brcmf_dbg(PCIE, "[%8x] 0x%04x\n", base + 2 * idx, otp[idx]);
|
||||
}
|
||||
|
||||
if (coreid == BCMA_CORE_CHIPCOMMON) {
|
||||
brcmf_pcie_select_core(devinfo, coreid);
|
||||
WRITECC32(devinfo, sromcontrol, sromctl);
|
||||
}
|
||||
|
||||
ret = brcmf_pcie_parse_otp(devinfo, (u8 *)otp, 2 * words);
|
||||
kfree(otp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define BRCMF_PCIE_FW_CODE 0
|
||||
#define BRCMF_PCIE_FW_NVRAM 1
|
||||
#define BRCMF_PCIE_FW_CLM 2
|
||||
|
||||
static void brcmf_pcie_setup(struct device *dev, int ret,
|
||||
struct brcmf_fw_request *fwreq)
|
||||
@ -1755,6 +2060,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
|
||||
fw = fwreq->items[BRCMF_PCIE_FW_CODE].binary;
|
||||
nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data;
|
||||
nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
|
||||
devinfo->clm_fw = fwreq->items[BRCMF_PCIE_FW_CLM].binary;
|
||||
kfree(fwreq);
|
||||
|
||||
ret = brcmf_chip_get_raminfo(devinfo->ci);
|
||||
@ -1830,6 +2136,7 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
|
||||
struct brcmf_fw_name fwnames[] = {
|
||||
{ ".bin", devinfo->fw_name },
|
||||
{ ".txt", devinfo->nvram_name },
|
||||
{ ".clm_blob", devinfo->clm_name },
|
||||
};
|
||||
|
||||
fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,
|
||||
@ -1842,11 +2149,51 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
|
||||
fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
|
||||
fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
|
||||
fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
|
||||
fwreq->board_type = devinfo->settings->board_type;
|
||||
fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
|
||||
fwreq->items[BRCMF_PCIE_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
|
||||
/* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */
|
||||
fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1;
|
||||
fwreq->bus_nr = devinfo->pdev->bus->number;
|
||||
|
||||
/* Apple platforms with fancy firmware/NVRAM selection */
|
||||
if (devinfo->settings->board_type &&
|
||||
devinfo->settings->antenna_sku &&
|
||||
devinfo->otp.valid) {
|
||||
const struct brcmf_otp_params *otp = &devinfo->otp;
|
||||
struct device *dev = &devinfo->pdev->dev;
|
||||
const char **bt = fwreq->board_types;
|
||||
|
||||
brcmf_dbg(PCIE, "Apple board: %s\n",
|
||||
devinfo->settings->board_type);
|
||||
|
||||
/* Example: apple,shikoku-RASP-m-6.11-X3 */
|
||||
bt[0] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s-%s-%s",
|
||||
devinfo->settings->board_type,
|
||||
otp->module, otp->vendor, otp->version,
|
||||
devinfo->settings->antenna_sku);
|
||||
bt[1] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s-%s",
|
||||
devinfo->settings->board_type,
|
||||
otp->module, otp->vendor, otp->version);
|
||||
bt[2] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s",
|
||||
devinfo->settings->board_type,
|
||||
otp->module, otp->vendor);
|
||||
bt[3] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s",
|
||||
devinfo->settings->board_type,
|
||||
otp->module);
|
||||
bt[4] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s",
|
||||
devinfo->settings->board_type,
|
||||
devinfo->settings->antenna_sku);
|
||||
bt[5] = devinfo->settings->board_type;
|
||||
|
||||
if (!bt[0] || !bt[1] || !bt[2] || !bt[3] || !bt[4]) {
|
||||
kfree(fwreq);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
brcmf_dbg(PCIE, "Board: %s\n", devinfo->settings->board_type);
|
||||
fwreq->board_types[0] = devinfo->settings->board_type;
|
||||
}
|
||||
|
||||
return fwreq;
|
||||
}
|
||||
|
||||
@ -1857,6 +2204,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
struct brcmf_fw_request *fwreq;
|
||||
struct brcmf_pciedev_info *devinfo;
|
||||
struct brcmf_pciedev *pcie_bus_dev;
|
||||
struct brcmf_core *core;
|
||||
struct brcmf_bus *bus;
|
||||
|
||||
brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
|
||||
@ -1876,6 +2224,12 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
|
||||
if (core->rev >= 64)
|
||||
devinfo->reginfo = &brcmf_reginfo_64;
|
||||
else
|
||||
devinfo->reginfo = &brcmf_reginfo_default;
|
||||
|
||||
pcie_bus_dev = kzalloc(sizeof(*pcie_bus_dev), GFP_KERNEL);
|
||||
if (pcie_bus_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
@ -1918,6 +2272,12 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
if (ret)
|
||||
goto fail_bus;
|
||||
|
||||
ret = brcmf_pcie_read_otp(devinfo);
|
||||
if (ret) {
|
||||
brcmf_err(bus, "failed to parse OTP\n");
|
||||
goto fail_brcmf;
|
||||
}
|
||||
|
||||
fwreq = brcmf_pcie_prepare_fw_request(devinfo);
|
||||
if (!fwreq) {
|
||||
ret = -ENOMEM;
|
||||
@ -1981,6 +2341,7 @@ brcmf_pcie_remove(struct pci_dev *pdev)
|
||||
brcmf_pcie_release_ringbuffers(devinfo);
|
||||
brcmf_pcie_reset_device(devinfo);
|
||||
brcmf_pcie_release_resource(devinfo);
|
||||
release_firmware(devinfo->clm_fw);
|
||||
|
||||
if (devinfo->ci)
|
||||
brcmf_chip_detach(devinfo->ci);
|
||||
@ -2038,7 +2399,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev)
|
||||
brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);
|
||||
|
||||
/* Check if device is still up and running, if so we are ready */
|
||||
if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0) {
|
||||
if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->intmask) != 0) {
|
||||
brcmf_dbg(PCIE, "Try to wakeup device....\n");
|
||||
if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM))
|
||||
goto cleanup;
|
||||
@ -2105,6 +2466,9 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = {
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(CY_PCIE_89459_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(CY_PCIE_89459_RAW_DEVICE_ID),
|
||||
{ /* end: all zeroes */ }
|
||||
};
|
||||
|
||||
|
@ -618,6 +618,7 @@ BRCMF_FW_DEF(43430A0, "brcmfmac43430a0-sdio");
|
||||
/* Note the names are not postfixed with a1 for backward compatibility */
|
||||
BRCMF_FW_CLM_DEF(43430A1, "brcmfmac43430-sdio");
|
||||
BRCMF_FW_DEF(43430B0, "brcmfmac43430b0-sdio");
|
||||
BRCMF_FW_CLM_DEF(43439, "brcmfmac43439-sdio");
|
||||
BRCMF_FW_CLM_DEF(43455, "brcmfmac43455-sdio");
|
||||
BRCMF_FW_DEF(43456, "brcmfmac43456-sdio");
|
||||
BRCMF_FW_CLM_DEF(4354, "brcmfmac4354-sdio");
|
||||
@ -657,6 +658,7 @@ static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
|
||||
BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359),
|
||||
BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373),
|
||||
BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012),
|
||||
BRCMF_FW_ENTRY(CY_CC_43439_CHIP_ID, 0xFFFFFFFF, 43439),
|
||||
BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752)
|
||||
};
|
||||
|
||||
@ -4129,23 +4131,24 @@ brcmf_sdio_watchdog(struct timer_list *t)
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int brcmf_sdio_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
|
||||
static int brcmf_sdio_get_blob(struct device *dev, const struct firmware **fw,
|
||||
enum brcmf_blob_type type)
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_fw_request *fwreq;
|
||||
struct brcmf_fw_name fwnames[] = {
|
||||
{ ext, fw_name },
|
||||
};
|
||||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
|
||||
fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
|
||||
brcmf_sdio_fwnames,
|
||||
ARRAY_SIZE(brcmf_sdio_fwnames),
|
||||
fwnames, ARRAY_SIZE(fwnames));
|
||||
if (!fwreq)
|
||||
return -ENOMEM;
|
||||
switch (type) {
|
||||
case BRCMF_BLOB_CLM:
|
||||
*fw = sdiodev->clm_fw;
|
||||
sdiodev->clm_fw = NULL;
|
||||
break;
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!*fw)
|
||||
return -ENOENT;
|
||||
|
||||
kfree(fwreq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4180,13 +4183,14 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
|
||||
.wowl_config = brcmf_sdio_wowl_config,
|
||||
.get_ramsize = brcmf_sdio_bus_get_ramsize,
|
||||
.get_memdump = brcmf_sdio_bus_get_memdump,
|
||||
.get_fwname = brcmf_sdio_get_fwname,
|
||||
.get_blob = brcmf_sdio_get_blob,
|
||||
.debugfs_create = brcmf_sdio_debugfs_create,
|
||||
.reset = brcmf_sdio_bus_reset
|
||||
};
|
||||
|
||||
#define BRCMF_SDIO_FW_CODE 0
|
||||
#define BRCMF_SDIO_FW_NVRAM 1
|
||||
#define BRCMF_SDIO_FW_CLM 2
|
||||
|
||||
static void brcmf_sdio_firmware_callback(struct device *dev, int err,
|
||||
struct brcmf_fw_request *fwreq)
|
||||
@ -4209,6 +4213,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
|
||||
code = fwreq->items[BRCMF_SDIO_FW_CODE].binary;
|
||||
nvram = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.data;
|
||||
nvram_len = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.len;
|
||||
sdiod->clm_fw = fwreq->items[BRCMF_SDIO_FW_CLM].binary;
|
||||
kfree(fwreq);
|
||||
|
||||
/* try to download image and nvram to the dongle */
|
||||
@ -4407,6 +4412,7 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
|
||||
struct brcmf_fw_name fwnames[] = {
|
||||
{ ".bin", bus->sdiodev->fw_name },
|
||||
{ ".txt", bus->sdiodev->nvram_name },
|
||||
{ ".clm_blob", bus->sdiodev->clm_name },
|
||||
};
|
||||
|
||||
fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev,
|
||||
@ -4418,7 +4424,9 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
|
||||
|
||||
fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
|
||||
fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
|
||||
fwreq->board_type = bus->sdiodev->settings->board_type;
|
||||
fwreq->items[BRCMF_SDIO_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
|
||||
fwreq->items[BRCMF_SDIO_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
|
||||
fwreq->board_types[0] = bus->sdiodev->settings->board_type;
|
||||
|
||||
return fwreq;
|
||||
}
|
||||
@ -4574,6 +4582,8 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
|
||||
if (bus->sdiodev->settings)
|
||||
brcmf_release_module_param(bus->sdiodev->settings);
|
||||
|
||||
release_firmware(bus->sdiodev->clm_fw);
|
||||
bus->sdiodev->clm_fw = NULL;
|
||||
kfree(bus->rxbuf);
|
||||
kfree(bus->hdrbuf);
|
||||
kfree(bus);
|
||||
|
@ -186,9 +186,11 @@ struct brcmf_sdio_dev {
|
||||
struct sg_table sgtable;
|
||||
char fw_name[BRCMF_FW_NAME_LEN];
|
||||
char nvram_name[BRCMF_FW_NAME_LEN];
|
||||
char clm_name[BRCMF_FW_NAME_LEN];
|
||||
bool wowl_enabled;
|
||||
enum brcmf_sdiod_state state;
|
||||
struct brcmf_sdiod_freezer *freezer;
|
||||
const struct firmware *clm_fw;
|
||||
};
|
||||
|
||||
/* sdio core registers */
|
||||
|
@ -1154,24 +1154,11 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int brcmf_usb_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
|
||||
static int brcmf_usb_get_blob(struct device *dev, const struct firmware **fw,
|
||||
enum brcmf_blob_type type)
|
||||
{
|
||||
struct brcmf_bus *bus = dev_get_drvdata(dev);
|
||||
struct brcmf_fw_request *fwreq;
|
||||
struct brcmf_fw_name fwnames[] = {
|
||||
{ ext, fw_name },
|
||||
};
|
||||
|
||||
fwreq = brcmf_fw_alloc_request(bus->chip, bus->chiprev,
|
||||
brcmf_usb_fwnames,
|
||||
ARRAY_SIZE(brcmf_usb_fwnames),
|
||||
fwnames, ARRAY_SIZE(fwnames));
|
||||
if (!fwreq)
|
||||
return -ENOMEM;
|
||||
|
||||
kfree(fwreq);
|
||||
return 0;
|
||||
/* No blobs for USB devices... */
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
|
||||
@ -1180,7 +1167,7 @@ static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
|
||||
.txdata = brcmf_usb_tx,
|
||||
.txctl = brcmf_usb_tx_ctlpkt,
|
||||
.rxctl = brcmf_usb_rx_ctlpkt,
|
||||
.get_fwname = brcmf_usb_get_fwname,
|
||||
.get_blob = brcmf_usb_get_blob,
|
||||
};
|
||||
|
||||
#define BRCMF_USB_FW_CODE 0
|
||||
|
@ -51,9 +51,12 @@
|
||||
#define BRCM_CC_43664_CHIP_ID 43664
|
||||
#define BRCM_CC_43666_CHIP_ID 43666
|
||||
#define BRCM_CC_4371_CHIP_ID 0x4371
|
||||
#define BRCM_CC_4378_CHIP_ID 0x4378
|
||||
#define CY_CC_4373_CHIP_ID 0x4373
|
||||
#define CY_CC_43012_CHIP_ID 43012
|
||||
#define CY_CC_43439_CHIP_ID 43439
|
||||
#define CY_CC_43752_CHIP_ID 43752
|
||||
#define CY_CC_89459_CHIP_ID 0x4355
|
||||
|
||||
/* USB Device IDs */
|
||||
#define BRCM_USB_43143_DEVICE_ID 0xbd1e
|
||||
@ -87,7 +90,9 @@
|
||||
#define BRCM_PCIE_4366_2G_DEVICE_ID 0x43c4
|
||||
#define BRCM_PCIE_4366_5G_DEVICE_ID 0x43c5
|
||||
#define BRCM_PCIE_4371_DEVICE_ID 0x440d
|
||||
|
||||
#define BRCM_PCIE_4378_DEVICE_ID 0x4425
|
||||
#define CY_PCIE_89459_DEVICE_ID 0x4415
|
||||
#define CY_PCIE_89459_RAW_DEVICE_ID 0x4355
|
||||
|
||||
/* brcmsmac IDs */
|
||||
#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */
|
||||
|
@ -6529,7 +6529,7 @@ static struct pci_driver ipw2100_pci_driver = {
|
||||
.shutdown = ipw2100_shutdown,
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Initialize the ipw2100 driver/module
|
||||
*
|
||||
* @returns 0 if ok, < 0 errno node con error.
|
||||
@ -6561,7 +6561,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Cleanup ipw2100 driver registration
|
||||
*/
|
||||
static void __exit ipw2100_exit(void)
|
||||
|
@ -651,7 +651,7 @@ struct ipw_rx_notification {
|
||||
struct notif_link_deterioration link_deterioration;
|
||||
struct notif_calibration calibration;
|
||||
struct notif_noise noise;
|
||||
u8 raw[0];
|
||||
DECLARE_FLEX_ARRAY(u8, raw);
|
||||
} u;
|
||||
} __packed;
|
||||
|
||||
|
@ -405,7 +405,7 @@ struct libipw_auth {
|
||||
__le16 transaction;
|
||||
__le16 status;
|
||||
/* challenge */
|
||||
struct libipw_info_element info_element[];
|
||||
u8 variable[];
|
||||
} __packed;
|
||||
|
||||
struct libipw_channel_switch {
|
||||
@ -423,7 +423,6 @@ struct libipw_action {
|
||||
union {
|
||||
struct libipw_action_exchange {
|
||||
u8 token;
|
||||
struct libipw_info_element info_element[0];
|
||||
} exchange;
|
||||
struct libipw_channel_switch channel_switch;
|
||||
|
||||
@ -441,7 +440,7 @@ struct libipw_disassoc {
|
||||
struct libipw_probe_request {
|
||||
struct libipw_hdr_3addr header;
|
||||
/* SSID, supported rates */
|
||||
struct libipw_info_element info_element[];
|
||||
u8 variable[];
|
||||
} __packed;
|
||||
|
||||
struct libipw_probe_response {
|
||||
@ -451,7 +450,7 @@ struct libipw_probe_response {
|
||||
__le16 capability;
|
||||
/* SSID, supported rates, FH params, DS params,
|
||||
* CF params, IBSS params, TIM (if beacon), RSN */
|
||||
struct libipw_info_element info_element[];
|
||||
u8 variable[];
|
||||
} __packed;
|
||||
|
||||
/* Alias beacon for probe_response */
|
||||
@ -462,7 +461,7 @@ struct libipw_assoc_request {
|
||||
__le16 capability;
|
||||
__le16 listen_interval;
|
||||
/* SSID, supported rates, RSN */
|
||||
struct libipw_info_element info_element[];
|
||||
u8 variable[];
|
||||
} __packed;
|
||||
|
||||
struct libipw_reassoc_request {
|
||||
@ -470,7 +469,7 @@ struct libipw_reassoc_request {
|
||||
__le16 capability;
|
||||
__le16 listen_interval;
|
||||
u8 current_ap[ETH_ALEN];
|
||||
struct libipw_info_element info_element[];
|
||||
u8 variable[];
|
||||
} __packed;
|
||||
|
||||
struct libipw_assoc_response {
|
||||
@ -479,7 +478,7 @@ struct libipw_assoc_response {
|
||||
__le16 status;
|
||||
__le16 aid;
|
||||
/* supported rates */
|
||||
struct libipw_info_element info_element[];
|
||||
u8 variable[];
|
||||
} __packed;
|
||||
|
||||
struct libipw_txb {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user