Lots of new things, notably:

* ath12k: monitor mode for WCN7850, better 6 GHz regulatory
  * brcmfmac: SAE for some Cypress devices
  * iwlwifi: rework device configuration
  * mac80211: scan improvements with MLO
  * mt76: EHT improvements, new device IDs
  * rtw88: throughput improvements
  * rtw89: MLO, STA/P2P concurrency improvements, SAR
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEpeA8sTs3M8SN2hR410qiO8sPaAAFAmgvVpAACgkQ10qiO8sP
 aADeJg//dShJQPKKUw7s4qY9y0lr1kimFw7cKE1vhHAq0eyQE8VP/05sj7XkeLdO
 2MDFCmWmTRZW1Av925xhicEhdiggxdOaT3n3RQ82y+Vjx7+6BsqqRE0YVRmK28vM
 MhUQocSzbd+Gh75wd4ti8G8dDPRJ9sbLTlZhIqPXMth2Ljl9EklMNzOlhzfo8N8+
 TgZ8oJx0EZ2n+sObtI5US27rNiPzLCtAM10Nl03F5yxfSk7gh3UpLHFhmu7384Nx
 56qqMwsmHHQSaRudg1ls8p30ztwve8/zHkOM6UeVksbb7CS2GHoPoVFtJUWBYmn9
 Ckd/XNItniRmIbsABgOyybawJV7EKZAWHclffeICQc526VMZWxeD9xukxQZSykiu
 3YXbHbPUkaCi3MlC3arc8SNQpW2l/BQvrC0SHqds4r/h/j4yUbA0wLs0OwqNXXwh
 NFoXnPTlkhMjNcX0W0t/A+EzXt/EsGKjBasiWC/tVZG9gHpMWKO3G8kLKmDyN/i9
 NsUh7E7zJTBjYjS2Bhm4xGmSy3DdgKSkBV2d4qCG/0LoKAW2eIRw97DGyn0pfVlA
 BAmio94xDJ3AM565WeySmWi/ZqvuDgQy2rd3J1ji0F/QDhdwqUdIHXy9C3VbN9zB
 TegAIgDjnqpOLzCn2P2FzWZlXwcXsxG13XMvqr2DfhBZtNUmRsw=
 =NXiI
 -----END PGP SIGNATURE-----

Merge tag 'wireless-next-2025-05-22' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next

Johannes Berg says:

====================
Lots of new things, notably:
 * ath12k: monitor mode for WCN7850, better 6 GHz regulatory
 * brcmfmac: SAE for some Cypress devices
 * iwlwifi: rework device configuration
 * mac80211: scan improvements with MLO
 * mt76: EHT improvements, new device IDs
 * rtw88: throughput improvements
 * rtw89: MLO, STA/P2P concurrency improvements, SAR

* tag 'wireless-next-2025-05-22' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (389 commits)
  wifi: mt76: mt7925: add rfkill_poll for hardware rfkill
  wifi: mt76: support power delta calculation for 5 TX paths
  wifi: mt76: fix available_antennas setting
  wifi: mt76: mt7996: fix RX buffer size of MCU event
  wifi: mt76: mt7996: change max beacon size
  wifi: mt76: mt7996: fix invalid NSS setting when TX path differs from NSS
  wifi: mt76: mt7996: drop fragments with multicast or broadcast RA
  wifi: mt76: mt7996: set EHT max ampdu length capability
  wifi: mt76: mt7996: fix beamformee SS field
  wifi: mt76: remove capability of partial bandwidth UL MU-MIMO
  wifi: mt76: mt7925: add test mode support
  wifi: mt76: mt7925: extend MCU support for testmode
  wifi: mt76: mt7925: ensure all MCU commands wait for response
  wifi: mt76: mt7925: refine the sniffer commnad
  wifi: mt76: mt7925: prevent multiple scan commands
  wifi: mt76: mt7915: Fix null-ptr-deref in mt7915_mmio_wed_init()
  wifi: mt76: mt7996: Fix null-ptr-deref in mt7996_mmio_wed_init()
  wifi: mt76: mt7925: add RNR scan support for 6GHz
  wifi: mt76: add mt76_connac_mcu_build_rnr_scan_param routine
  wifi: mt76: scan: Fix 'mlink' dereferenced before IS_ERR_OR_NULL check
  ...
====================

Link: https://patch.msgid.link/20250522165501.189958-50-johannes@sipsolutions.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2025-05-22 14:05:18 -07:00
commit ea15e04626
349 changed files with 14677 additions and 7180 deletions

@ -21,6 +21,12 @@ properties:
reg:
maxItems: 1
firmware-name:
maxItems: 1
description:
If present, a board or platform specific string used to lookup
usecase-specific firmware files for the device.
vddaon-supply:
description: VDD_AON supply regulator handle

@ -80,7 +80,7 @@ static inline u32 shadow_sr_wr_ind_addr(struct ath10k *ar,
static inline unsigned int
ath10k_set_ring_byte(unsigned int offset,
struct ath10k_hw_ce_regs_addr_map *addr_map)
const struct ath10k_hw_ce_regs_addr_map *addr_map)
{
return ((offset << addr_map->lsb) & addr_map->mask);
}
@ -203,7 +203,7 @@ static inline void ath10k_ce_src_ring_dmax_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
const struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
u32 ctrl1_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
ctrl_regs->addr);
@ -217,7 +217,7 @@ static inline void ath10k_ce_src_ring_byte_swap_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
const struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
u32 ctrl1_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
ctrl_regs->addr);
@ -231,7 +231,7 @@ static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
const struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs;
u32 ctrl1_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
ctrl_regs->addr);
@ -313,7 +313,7 @@ static inline void ath10k_ce_src_ring_highmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr;
const struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr;
u32 addr = ath10k_ce_read32(ar, ce_ctrl_addr + srcr_wm->addr);
ath10k_ce_write32(ar, ce_ctrl_addr + srcr_wm->addr,
@ -325,7 +325,7 @@ static inline void ath10k_ce_src_ring_lowmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr;
const struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr;
u32 addr = ath10k_ce_read32(ar, ce_ctrl_addr + srcr_wm->addr);
ath10k_ce_write32(ar, ce_ctrl_addr + srcr_wm->addr,
@ -337,7 +337,7 @@ static inline void ath10k_ce_dest_ring_highmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr;
const struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr;
u32 addr = ath10k_ce_read32(ar, ce_ctrl_addr + dstr_wm->addr);
ath10k_ce_write32(ar, ce_ctrl_addr + dstr_wm->addr,
@ -349,7 +349,7 @@ static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr;
const struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr;
u32 addr = ath10k_ce_read32(ar, ce_ctrl_addr + dstr_wm->addr);
ath10k_ce_write32(ar, ce_ctrl_addr + dstr_wm->addr,
@ -360,7 +360,7 @@ static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar,
static inline void ath10k_ce_copy_complete_inter_enable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie;
const struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie;
u32 host_ie_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
ar->hw_ce_regs->host_ie_addr);
@ -372,7 +372,7 @@ static inline void ath10k_ce_copy_complete_inter_enable(struct ath10k *ar,
static inline void ath10k_ce_copy_complete_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie;
const struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie;
u32 host_ie_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
ar->hw_ce_regs->host_ie_addr);
@ -384,7 +384,7 @@ static inline void ath10k_ce_copy_complete_intr_disable(struct ath10k *ar,
static inline void ath10k_ce_watermark_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
const struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
u32 host_ie_addr = ath10k_ce_read32(ar, ce_ctrl_addr +
ar->hw_ce_regs->host_ie_addr);
@ -396,7 +396,7 @@ static inline void ath10k_ce_watermark_intr_disable(struct ath10k *ar,
static inline void ath10k_ce_error_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs;
const struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs;
u32 misc_ie_addr = ath10k_ce_read32(ar,
ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr);
@ -410,7 +410,7 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int mask)
{
struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
const struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
ath10k_ce_write32(ar, ce_ctrl_addr + wm_regs->addr, mask);
}
@ -1230,7 +1230,7 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
{
struct ath10k_ce *ce = ath10k_ce_priv(ar);
struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id];
struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
const struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
u32 ctrl_addr = ce_state->ctrl_addr;
/*

@ -212,40 +212,40 @@ const struct ath10k_hw_regs wcn3990_regs = {
.pcie_intr_fw_mask = 0x00100000,
};
static struct ath10k_hw_ce_regs_addr_map wcn3990_src_ring = {
static const struct ath10k_hw_ce_regs_addr_map wcn3990_src_ring = {
.msb = 0x00000010,
.lsb = 0x00000010,
.mask = GENMASK(17, 17),
};
static struct ath10k_hw_ce_regs_addr_map wcn3990_dst_ring = {
static const struct ath10k_hw_ce_regs_addr_map wcn3990_dst_ring = {
.msb = 0x00000012,
.lsb = 0x00000012,
.mask = GENMASK(18, 18),
};
static struct ath10k_hw_ce_regs_addr_map wcn3990_dmax = {
static const struct ath10k_hw_ce_regs_addr_map wcn3990_dmax = {
.msb = 0x00000000,
.lsb = 0x00000000,
.mask = GENMASK(15, 0),
};
static struct ath10k_hw_ce_ctrl1 wcn3990_ctrl1 = {
static const struct ath10k_hw_ce_ctrl1 wcn3990_ctrl1 = {
.addr = 0x00000018,
.src_ring = &wcn3990_src_ring,
.dst_ring = &wcn3990_dst_ring,
.dmax = &wcn3990_dmax,
};
static struct ath10k_hw_ce_regs_addr_map wcn3990_host_ie_cc = {
static const struct ath10k_hw_ce_regs_addr_map wcn3990_host_ie_cc = {
.mask = GENMASK(0, 0),
};
static struct ath10k_hw_ce_host_ie wcn3990_host_ie = {
static const struct ath10k_hw_ce_host_ie wcn3990_host_ie = {
.copy_complete = &wcn3990_host_ie_cc,
};
static struct ath10k_hw_ce_host_wm_regs wcn3990_wm_reg = {
static const struct ath10k_hw_ce_host_wm_regs wcn3990_wm_reg = {
.dstr_lmask = 0x00000010,
.dstr_hmask = 0x00000008,
.srcr_lmask = 0x00000004,
@ -255,7 +255,7 @@ static struct ath10k_hw_ce_host_wm_regs wcn3990_wm_reg = {
.addr = 0x00000030,
};
static struct ath10k_hw_ce_misc_regs wcn3990_misc_reg = {
static const struct ath10k_hw_ce_misc_regs wcn3990_misc_reg = {
.axi_err = 0x00000100,
.dstr_add_err = 0x00000200,
.srcr_len_err = 0x00000100,
@ -266,19 +266,19 @@ static struct ath10k_hw_ce_misc_regs wcn3990_misc_reg = {
.addr = 0x00000038,
};
static struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_low = {
static const struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_low = {
.msb = 0x00000000,
.lsb = 0x00000010,
.mask = GENMASK(31, 16),
};
static struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_high = {
static const struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_high = {
.msb = 0x0000000f,
.lsb = 0x00000000,
.mask = GENMASK(15, 0),
};
static struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_src_ring = {
static const struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_src_ring = {
.addr = 0x0000004c,
.low_rst = 0x00000000,
.high_rst = 0x00000000,
@ -286,18 +286,18 @@ static struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_src_ring = {
.wm_high = &wcn3990_src_wm_high,
};
static struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_low = {
static const struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_low = {
.lsb = 0x00000010,
.mask = GENMASK(31, 16),
};
static struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_high = {
static const struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_high = {
.msb = 0x0000000f,
.lsb = 0x00000000,
.mask = GENMASK(15, 0),
};
static struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_dst_ring = {
static const struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_dst_ring = {
.addr = 0x00000050,
.low_rst = 0x00000000,
.high_rst = 0x00000000,
@ -305,7 +305,7 @@ static struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_dst_ring = {
.wm_high = &wcn3990_dst_wm_high,
};
static struct ath10k_hw_ce_ctrl1_upd wcn3990_ctrl1_upd = {
static const struct ath10k_hw_ce_ctrl1_upd wcn3990_ctrl1_upd = {
.shift = 19,
.mask = 0x00080000,
.enable = 0x00000000,
@ -344,25 +344,25 @@ const struct ath10k_hw_values wcn3990_values = {
.ce_desc_meta_data_lsb = 4,
};
static struct ath10k_hw_ce_regs_addr_map qcax_src_ring = {
static const struct ath10k_hw_ce_regs_addr_map qcax_src_ring = {
.msb = 0x00000010,
.lsb = 0x00000010,
.mask = GENMASK(16, 16),
};
static struct ath10k_hw_ce_regs_addr_map qcax_dst_ring = {
static const struct ath10k_hw_ce_regs_addr_map qcax_dst_ring = {
.msb = 0x00000011,
.lsb = 0x00000011,
.mask = GENMASK(17, 17),
};
static struct ath10k_hw_ce_regs_addr_map qcax_dmax = {
static const struct ath10k_hw_ce_regs_addr_map qcax_dmax = {
.msb = 0x0000000f,
.lsb = 0x00000000,
.mask = GENMASK(15, 0),
};
static struct ath10k_hw_ce_ctrl1 qcax_ctrl1 = {
static const struct ath10k_hw_ce_ctrl1 qcax_ctrl1 = {
.addr = 0x00000010,
.hw_mask = 0x0007ffff,
.sw_mask = 0x0007ffff,
@ -375,31 +375,31 @@ static struct ath10k_hw_ce_ctrl1 qcax_ctrl1 = {
.dmax = &qcax_dmax,
};
static struct ath10k_hw_ce_regs_addr_map qcax_cmd_halt_status = {
static const struct ath10k_hw_ce_regs_addr_map qcax_cmd_halt_status = {
.msb = 0x00000003,
.lsb = 0x00000003,
.mask = GENMASK(3, 3),
};
static struct ath10k_hw_ce_cmd_halt qcax_cmd_halt = {
static const struct ath10k_hw_ce_cmd_halt qcax_cmd_halt = {
.msb = 0x00000000,
.mask = GENMASK(0, 0),
.status_reset = 0x00000000,
.status = &qcax_cmd_halt_status,
};
static struct ath10k_hw_ce_regs_addr_map qcax_host_ie_cc = {
static const struct ath10k_hw_ce_regs_addr_map qcax_host_ie_cc = {
.msb = 0x00000000,
.lsb = 0x00000000,
.mask = GENMASK(0, 0),
};
static struct ath10k_hw_ce_host_ie qcax_host_ie = {
static const struct ath10k_hw_ce_host_ie qcax_host_ie = {
.copy_complete_reset = 0x00000000,
.copy_complete = &qcax_host_ie_cc,
};
static struct ath10k_hw_ce_host_wm_regs qcax_wm_reg = {
static const struct ath10k_hw_ce_host_wm_regs qcax_wm_reg = {
.dstr_lmask = 0x00000010,
.dstr_hmask = 0x00000008,
.srcr_lmask = 0x00000004,
@ -409,7 +409,7 @@ static struct ath10k_hw_ce_host_wm_regs qcax_wm_reg = {
.addr = 0x00000030,
};
static struct ath10k_hw_ce_misc_regs qcax_misc_reg = {
static const struct ath10k_hw_ce_misc_regs qcax_misc_reg = {
.axi_err = 0x00000400,
.dstr_add_err = 0x00000200,
.srcr_len_err = 0x00000100,
@ -420,19 +420,19 @@ static struct ath10k_hw_ce_misc_regs qcax_misc_reg = {
.addr = 0x00000038,
};
static struct ath10k_hw_ce_regs_addr_map qcax_src_wm_low = {
static const struct ath10k_hw_ce_regs_addr_map qcax_src_wm_low = {
.msb = 0x0000001f,
.lsb = 0x00000010,
.mask = GENMASK(31, 16),
};
static struct ath10k_hw_ce_regs_addr_map qcax_src_wm_high = {
static const struct ath10k_hw_ce_regs_addr_map qcax_src_wm_high = {
.msb = 0x0000000f,
.lsb = 0x00000000,
.mask = GENMASK(15, 0),
};
static struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_src_ring = {
static const struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_src_ring = {
.addr = 0x0000004c,
.low_rst = 0x00000000,
.high_rst = 0x00000000,
@ -440,18 +440,18 @@ static struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_src_ring = {
.wm_high = &qcax_src_wm_high,
};
static struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_low = {
static const struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_low = {
.lsb = 0x00000010,
.mask = GENMASK(31, 16),
};
static struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_high = {
static const struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_high = {
.msb = 0x0000000f,
.lsb = 0x00000000,
.mask = GENMASK(15, 0),
};
static struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_dst_ring = {
static const struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_dst_ring = {
.addr = 0x00000050,
.low_rst = 0x00000000,
.high_rst = 0x00000000,

@ -289,19 +289,22 @@ struct ath10k_hw_ce_ctrl1 {
u32 sw_wr_mask;
u32 reset_mask;
u32 reset;
struct ath10k_hw_ce_regs_addr_map *src_ring;
struct ath10k_hw_ce_regs_addr_map *dst_ring;
struct ath10k_hw_ce_regs_addr_map *dmax; };
const struct ath10k_hw_ce_regs_addr_map *src_ring;
const struct ath10k_hw_ce_regs_addr_map *dst_ring;
const struct ath10k_hw_ce_regs_addr_map *dmax;
};
struct ath10k_hw_ce_cmd_halt {
u32 status_reset;
u32 msb;
u32 mask;
struct ath10k_hw_ce_regs_addr_map *status; };
const struct ath10k_hw_ce_regs_addr_map *status;
};
struct ath10k_hw_ce_host_ie {
u32 copy_complete_reset;
struct ath10k_hw_ce_regs_addr_map *copy_complete; };
const struct ath10k_hw_ce_regs_addr_map *copy_complete;
};
struct ath10k_hw_ce_host_wm_regs {
u32 dstr_lmask;
@ -328,8 +331,9 @@ struct ath10k_hw_ce_dst_src_wm_regs {
u32 addr;
u32 low_rst;
u32 high_rst;
struct ath10k_hw_ce_regs_addr_map *wm_low;
struct ath10k_hw_ce_regs_addr_map *wm_high; };
const struct ath10k_hw_ce_regs_addr_map *wm_low;
const struct ath10k_hw_ce_regs_addr_map *wm_high;
};
struct ath10k_hw_ce_ctrl1_upd {
u32 shift;
@ -355,14 +359,14 @@ struct ath10k_hw_ce_regs {
u32 ce_rri_low;
u32 ce_rri_high;
u32 host_ie_addr;
struct ath10k_hw_ce_host_wm_regs *wm_regs;
struct ath10k_hw_ce_misc_regs *misc_regs;
struct ath10k_hw_ce_ctrl1 *ctrl1_regs;
struct ath10k_hw_ce_cmd_halt *cmd_halt;
struct ath10k_hw_ce_host_ie *host_ie;
struct ath10k_hw_ce_dst_src_wm_regs *wm_srcr;
struct ath10k_hw_ce_dst_src_wm_regs *wm_dstr;
struct ath10k_hw_ce_ctrl1_upd *upd;
const struct ath10k_hw_ce_host_wm_regs *wm_regs;
const struct ath10k_hw_ce_misc_regs *misc_regs;
const struct ath10k_hw_ce_ctrl1 *ctrl1_regs;
const struct ath10k_hw_ce_cmd_halt *cmd_halt;
const struct ath10k_hw_ce_host_ie *host_ie;
const struct ath10k_hw_ce_dst_src_wm_regs *wm_srcr;
const struct ath10k_hw_ce_dst_src_wm_regs *wm_dstr;
const struct ath10k_hw_ce_ctrl1_upd *upd;
};
struct ath10k_hw_values {

@ -1844,7 +1844,7 @@ static int ath10k_sdio_get_htt_tx_complete(struct ath10k *ar)
ret = ath10k_sdio_diag_read32(ar, addr, &val);
if (ret) {
ath10k_warn(ar,
"unable to read hi_acs_flags for htt tx comple : %d\n", ret);
"unable to read hi_acs_flags for htt tx complete: %d\n", ret);
return ret;
}

@ -393,11 +393,10 @@ static int ath11k_ce_completed_recv_next(struct ath11k_ce_pipe *pipe,
goto err;
}
/* Make sure descriptor is read after the head pointer. */
dma_rmb();
*nbytes = ath11k_hal_ce_dst_status_get_length(desc);
if (*nbytes == 0) {
ret = -EIO;
goto err;
}
*skb = pipe->dest_ring->skb[sw_index];
pipe->dest_ring->skb[sw_index] = NULL;
@ -430,8 +429,8 @@ static void ath11k_ce_recv_process_cb(struct ath11k_ce_pipe *pipe)
dma_unmap_single(ab->dev, ATH11K_SKB_RXCB(skb)->paddr,
max_nbytes, DMA_FROM_DEVICE);
if (unlikely(max_nbytes < nbytes)) {
ath11k_warn(ab, "rxed more than expected (nbytes %d, max %d)",
if (unlikely(max_nbytes < nbytes || nbytes == 0)) {
ath11k_warn(ab, "unexpected rx length (nbytes %d, max %d)",
nbytes, max_nbytes);
dev_kfree_skb_any(skb);
continue;

@ -2637,7 +2637,7 @@ int ath11k_dp_process_rx(struct ath11k_base *ab, int ring_id,
struct ath11k *ar;
struct hal_reo_dest_ring *desc;
enum hal_reo_dest_ring_push_reason push_reason;
u32 cookie;
u32 cookie, info0, rx_msdu_info0, rx_mpdu_info0;
int i;
for (i = 0; i < MAX_RADIOS; i++)
@ -2650,11 +2650,14 @@ int ath11k_dp_process_rx(struct ath11k_base *ab, int ring_id,
try_again:
ath11k_hal_srng_access_begin(ab, srng);
/* Make sure descriptor is read after the head pointer. */
dma_rmb();
while (likely(desc =
(struct hal_reo_dest_ring *)ath11k_hal_srng_dst_get_next_entry(ab,
srng))) {
cookie = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE,
desc->buf_addr_info.info1);
READ_ONCE(desc->buf_addr_info.info1));
buf_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_BUF_ID,
cookie);
mac_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_PDEV_ID, cookie);
@ -2683,8 +2686,9 @@ int ath11k_dp_process_rx(struct ath11k_base *ab, int ring_id,
num_buffs_reaped[mac_id]++;
info0 = READ_ONCE(desc->info0);
push_reason = FIELD_GET(HAL_REO_DEST_RING_INFO0_PUSH_REASON,
desc->info0);
info0);
if (unlikely(push_reason !=
HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION)) {
dev_kfree_skb_any(msdu);
@ -2692,18 +2696,21 @@ int ath11k_dp_process_rx(struct ath11k_base *ab, int ring_id,
continue;
}
rxcb->is_first_msdu = !!(desc->rx_msdu_info.info0 &
rx_msdu_info0 = READ_ONCE(desc->rx_msdu_info.info0);
rx_mpdu_info0 = READ_ONCE(desc->rx_mpdu_info.info0);
rxcb->is_first_msdu = !!(rx_msdu_info0 &
RX_MSDU_DESC_INFO0_FIRST_MSDU_IN_MPDU);
rxcb->is_last_msdu = !!(desc->rx_msdu_info.info0 &
rxcb->is_last_msdu = !!(rx_msdu_info0 &
RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU);
rxcb->is_continuation = !!(desc->rx_msdu_info.info0 &
rxcb->is_continuation = !!(rx_msdu_info0 &
RX_MSDU_DESC_INFO0_MSDU_CONTINUATION);
rxcb->peer_id = FIELD_GET(RX_MPDU_DESC_META_DATA_PEER_ID,
desc->rx_mpdu_info.meta_data);
READ_ONCE(desc->rx_mpdu_info.meta_data));
rxcb->seq_no = FIELD_GET(RX_MPDU_DESC_INFO0_SEQ_NUM,
desc->rx_mpdu_info.info0);
rx_mpdu_info0);
rxcb->tid = FIELD_GET(HAL_REO_DEST_RING_INFO0_RX_QUEUE_NUM,
desc->info0);
info0);
rxcb->mac_id = mac_id;
__skb_queue_tail(&msdu_list[mac_id], msdu);

@ -599,7 +599,7 @@ u32 ath11k_hal_ce_dst_status_get_length(void *buf)
struct hal_ce_srng_dst_status_desc *desc = buf;
u32 len;
len = FIELD_GET(HAL_CE_DST_STATUS_DESC_FLAGS_LEN, desc->flags);
len = FIELD_GET(HAL_CE_DST_STATUS_DESC_FLAGS_LEN, READ_ONCE(desc->flags));
desc->flags &= ~HAL_CE_DST_STATUS_DESC_FLAGS_LEN;
return len;
@ -829,7 +829,7 @@ void ath11k_hal_srng_access_begin(struct ath11k_base *ab, struct hal_srng *srng)
srng->u.src_ring.cached_tp =
*(volatile u32 *)srng->u.src_ring.tp_addr;
} else {
srng->u.dst_ring.cached_hp = *srng->u.dst_ring.hp_addr;
srng->u.dst_ring.cached_hp = READ_ONCE(*srng->u.dst_ring.hp_addr);
/* Try to prefetch the next descriptor in the ring */
if (srng->flags & HAL_SRNG_FLAGS_CACHED)

@ -9972,12 +9972,17 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
struct ath11k_base *ab = ar->ab;
struct ieee80211_iface_combination *combinations;
struct ieee80211_iface_limit *limits;
int n_limits;
int n_limits, n_combos;
bool p2p;
p2p = ab->hw_params.interface_modes & BIT(NL80211_IFTYPE_P2P_DEVICE);
combinations = kzalloc(sizeof(*combinations), GFP_KERNEL);
if (ab->hw_params.support_dual_stations)
n_combos = 2;
else
n_combos = 1;
combinations = kcalloc(n_combos, sizeof(*combinations), GFP_KERNEL);
if (!combinations)
return -ENOMEM;
@ -9992,7 +9997,9 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
return -ENOMEM;
}
limits[0].max = 1;
limits[0].types |= BIT(NL80211_IFTYPE_STATION);
limits[1].max = 16;
limits[1].types |= BIT(NL80211_IFTYPE_AP);
if (IS_ENABLED(CONFIG_MAC80211_MESH) &&
ab->hw_params.interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
@ -10002,25 +10009,24 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
combinations[0].n_limits = n_limits;
combinations[0].beacon_int_infra_match = true;
combinations[0].beacon_int_min_gcd = 100;
combinations[0].max_interfaces = 16;
combinations[0].num_different_channels = 1;
combinations[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
BIT(NL80211_CHAN_WIDTH_20) |
BIT(NL80211_CHAN_WIDTH_40) |
BIT(NL80211_CHAN_WIDTH_80) |
BIT(NL80211_CHAN_WIDTH_80P80) |
BIT(NL80211_CHAN_WIDTH_160);
if (ab->hw_params.support_dual_stations) {
limits[0].max = 2;
limits[1].max = 1;
combinations[0].max_interfaces = ab->hw_params.num_vdevs;
combinations[0].num_different_channels = 2;
} else {
limits[0].max = 1;
limits[1].max = 16;
combinations[0].max_interfaces = 16;
combinations[0].num_different_channels = 1;
combinations[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
BIT(NL80211_CHAN_WIDTH_20) |
BIT(NL80211_CHAN_WIDTH_40) |
BIT(NL80211_CHAN_WIDTH_80) |
BIT(NL80211_CHAN_WIDTH_80P80) |
BIT(NL80211_CHAN_WIDTH_160);
combinations[1].limits = limits;
combinations[1].n_limits = n_limits;
combinations[1].beacon_int_infra_match = true;
combinations[1].beacon_int_min_gcd = 100;
combinations[1].max_interfaces = ab->hw_params.num_vdevs;
combinations[1].num_different_channels = 2;
}
if (p2p) {
@ -10031,7 +10037,7 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
}
ar->hw->wiphy->iface_combinations = combinations;
ar->hw->wiphy->n_iface_combinations = 1;
ar->hw->wiphy->n_iface_combinations = n_combos;
return 0;
}

@ -1993,6 +1993,15 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
chunk->prev_size == chunk->size)
continue;
if (ab->qmi.mem_seg_count <= ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT) {
ath11k_dbg(ab, ATH11K_DBG_QMI,
"size/type mismatch (current %d %u) (prev %d %u), try later with small size\n",
chunk->size, chunk->type,
chunk->prev_size, chunk->prev_type);
ab->qmi.target_mem_delayed = true;
return 0;
}
/* cannot reuse the existing chunk */
dma_free_coherent(ab->dev, chunk->prev_size,
chunk->vaddr, chunk->paddr);

@ -1125,14 +1125,13 @@ static void ath12k_ahb_remove(struct platform_device *pdev)
if (test_bit(ATH12K_FLAG_QMI_FAIL, &ab->dev_flags)) {
ath12k_ahb_power_down(ab, false);
ath12k_qmi_deinit_service(ab);
goto qmi_fail;
}
ath12k_ahb_remove_prepare(ab);
ath12k_core_deinit(ab);
ath12k_core_hw_group_cleanup(ab->ag);
qmi_fail:
ath12k_core_deinit(ab);
ath12k_ahb_free_resources(ab);
}

@ -433,11 +433,10 @@ static int ath12k_ce_completed_recv_next(struct ath12k_ce_pipe *pipe,
goto err;
}
/* Make sure descriptor is read after the head pointer. */
dma_rmb();
*nbytes = ath12k_hal_ce_dst_status_get_length(desc);
if (*nbytes == 0) {
ret = -EIO;
goto err;
}
*skb = pipe->dest_ring->skb[sw_index];
pipe->dest_ring->skb[sw_index] = NULL;
@ -470,8 +469,8 @@ static void ath12k_ce_recv_process_cb(struct ath12k_ce_pipe *pipe)
dma_unmap_single(ab->dev, ATH12K_SKB_RXCB(skb)->paddr,
max_nbytes, DMA_FROM_DEVICE);
if (unlikely(max_nbytes < nbytes)) {
ath12k_warn(ab, "rxed more than expected (nbytes %d, max %d)",
if (unlikely(max_nbytes < nbytes || nbytes == 0)) {
ath12k_warn(ab, "unexpected rx length (nbytes %d, max %d)",
nbytes, max_nbytes);
dev_kfree_skb_any(skb);
continue;

@ -697,7 +697,7 @@ static void ath12k_core_stop(struct ath12k_base *ab)
/* De-Init of components as needed */
}
static void ath12k_core_check_bdfext(const struct dmi_header *hdr, void *data)
static void ath12k_core_check_cc_code_bdfext(const struct dmi_header *hdr, void *data)
{
struct ath12k_base *ab = data;
const char *magic = ATH12K_SMBIOS_BDF_EXT_MAGIC;
@ -719,6 +719,28 @@ static void ath12k_core_check_bdfext(const struct dmi_header *hdr, void *data)
return;
}
spin_lock_bh(&ab->base_lock);
switch (smbios->country_code_flag) {
case ATH12K_SMBIOS_CC_ISO:
ab->new_alpha2[0] = u16_get_bits(smbios->cc_code >> 8, 0xff);
ab->new_alpha2[1] = u16_get_bits(smbios->cc_code, 0xff);
ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot smbios cc_code %c%c\n",
ab->new_alpha2[0], ab->new_alpha2[1]);
break;
case ATH12K_SMBIOS_CC_WW:
ab->new_alpha2[0] = '0';
ab->new_alpha2[1] = '0';
ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot smbios worldwide regdomain\n");
break;
default:
ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot ignore smbios country code setting %d\n",
smbios->country_code_flag);
break;
}
spin_unlock_bh(&ab->base_lock);
if (!smbios->bdf_enabled) {
ath12k_dbg(ab, ATH12K_DBG_BOOT, "bdf variant name not found.\n");
return;
@ -758,7 +780,7 @@ static void ath12k_core_check_bdfext(const struct dmi_header *hdr, void *data)
int ath12k_core_check_smbios(struct ath12k_base *ab)
{
ab->qmi.target.bdf_ext[0] = '\0';
dmi_walk(ath12k_core_check_bdfext, ab);
dmi_walk(ath12k_core_check_cc_code_bdfext, ab);
if (ab->qmi.target.bdf_ext[0] == '\0')
return -ENODATA;
@ -789,6 +811,8 @@ static int ath12k_core_soc_create(struct ath12k_base *ab)
goto err_qmi_deinit;
}
ath12k_debugfs_pdev_create(ab);
return 0;
err_qmi_deinit:
@ -1812,9 +1836,9 @@ static int ath12k_core_get_wsi_info(struct ath12k_hw_group *ag,
of_node_put(next_rx_endpoint);
device_count++;
if (device_count > ATH12K_MAX_SOCS) {
if (device_count > ATH12K_MAX_DEVICES) {
ath12k_warn(ab, "device count in DT %d is more than limit %d\n",
device_count, ATH12K_MAX_SOCS);
device_count, ATH12K_MAX_DEVICES);
of_node_put(next_wsi_dev);
return -EINVAL;
}
@ -1990,7 +2014,7 @@ static void ath12k_core_hw_group_destroy(struct ath12k_hw_group *ag)
}
}
static void ath12k_core_hw_group_cleanup(struct ath12k_hw_group *ag)
void ath12k_core_hw_group_cleanup(struct ath12k_hw_group *ag)
{
struct ath12k_base *ab;
int i;
@ -2136,10 +2160,9 @@ int ath12k_core_init(struct ath12k_base *ab)
void ath12k_core_deinit(struct ath12k_base *ab)
{
ath12k_core_panic_notifier_unregister(ab);
ath12k_core_hw_group_cleanup(ab->ag);
ath12k_core_hw_group_destroy(ab->ag);
ath12k_core_hw_group_unassign(ab);
ath12k_core_panic_notifier_unregister(ab);
}
void ath12k_core_free(struct ath12k_base *ab)

@ -17,6 +17,7 @@
#include <linux/of_reserved_mem.h>
#include <linux/panic_notifier.h>
#include <linux/average.h>
#include <linux/of.h>
#include "qmi.h"
#include "htc.h"
#include "wmi.h"
@ -63,8 +64,8 @@
#define ATH12K_RECONFIGURE_TIMEOUT_HZ (10 * HZ)
#define ATH12K_RECOVER_START_TIMEOUT_HZ (20 * HZ)
#define ATH12K_MAX_SOCS 3
#define ATH12K_GROUP_MAX_RADIO (ATH12K_MAX_SOCS * MAX_RADIOS)
#define ATH12K_MAX_DEVICES 3
#define ATH12K_GROUP_MAX_RADIO (ATH12K_MAX_DEVICES * MAX_RADIOS)
#define ATH12K_INVALID_GROUP_ID 0xFF
#define ATH12K_INVALID_DEVICE_ID 0xFF
@ -175,9 +176,34 @@ struct ath12k_ext_irq_grp {
struct net_device *napi_ndev;
};
enum ath12k_smbios_cc_type {
/* disable country code setting from SMBIOS */
ATH12K_SMBIOS_CC_DISABLE = 0,
/* set country code by ANSI country name, based on ISO3166-1 alpha2 */
ATH12K_SMBIOS_CC_ISO = 1,
/* worldwide regdomain */
ATH12K_SMBIOS_CC_WW = 2,
};
struct ath12k_smbios_bdf {
struct dmi_header hdr;
u32 padding;
u8 features_disabled;
/* enum ath12k_smbios_cc_type */
u8 country_code_flag;
/* To set specific country, you need to set country code
* flag=ATH12K_SMBIOS_CC_ISO first, then if country is United
* States, then country code value = 0x5553 ("US",'U' = 0x55, 'S'=
* 0x53). To set country to INDONESIA, then country code value =
* 0x4944 ("IN", 'I'=0x49, 'D'=0x44). If country code flag =
* ATH12K_SMBIOS_CC_WW, then you can use worldwide regulatory
* setting.
*/
u16 cc_code;
u8 bdf_enabled;
u8 bdf_ext[];
} __packed;
@ -317,6 +343,8 @@ struct ath12k_link_vif {
/* only used in station mode */
bool is_sta_assoc_link;
struct ath12k_reg_tpc_power_info reg_tpc_info;
};
struct ath12k_vif {
@ -784,6 +812,8 @@ struct ath12k {
u8 ftm_msgref;
struct ath12k_fw_stats fw_stats;
unsigned long last_tx_power_update;
s8 max_allowed_tx_power;
};
struct ath12k_hw {
@ -875,7 +905,7 @@ struct ath12k_board_data {
size_t len;
};
struct ath12k_soc_dp_tx_err_stats {
struct ath12k_device_dp_tx_err_stats {
/* TCL Ring Descriptor unavailable */
u32 desc_na[DP_TCL_NUM_RING_MAX];
/* Other failures during dp_tx due to mem allocation failure
@ -884,13 +914,20 @@ struct ath12k_soc_dp_tx_err_stats {
atomic_t misc_fail;
};
struct ath12k_soc_dp_stats {
struct ath12k_device_dp_stats {
u32 err_ring_pkts;
u32 invalid_rbm;
u32 rxdma_error[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX];
u32 reo_error[HAL_REO_DEST_RING_ERROR_CODE_MAX];
u32 hal_reo_error[DP_REO_DST_RING_MAX];
struct ath12k_soc_dp_tx_err_stats tx_err;
struct ath12k_device_dp_tx_err_stats tx_err;
u32 reo_rx[DP_REO_DST_RING_MAX][ATH12K_MAX_DEVICES];
u32 rx_wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX][ATH12K_MAX_DEVICES];
u32 tqm_rel_reason[MAX_TQM_RELEASE_REASON];
u32 fw_tx_status[MAX_FW_TX_STATUS];
u32 tx_wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX];
u32 tx_enqueued[DP_TCL_NUM_RING_MAX];
u32 tx_completed[DP_TCL_NUM_RING_MAX];
};
struct ath12k_reg_freq {
@ -919,7 +956,7 @@ struct ath12k_hw_group {
u8 num_probed;
u8 num_started;
unsigned long flags;
struct ath12k_base *ab[ATH12K_MAX_SOCS];
struct ath12k_base *ab[ATH12K_MAX_DEVICES];
/* protects access to this struct */
struct mutex mutex;
@ -933,7 +970,7 @@ struct ath12k_hw_group {
struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO];
u8 num_hw;
bool mlo_capable;
struct device_node *wsi_node[ATH12K_MAX_SOCS];
struct device_node *wsi_node[ATH12K_MAX_DEVICES];
struct ath12k_mlo_memory mlo_mem;
struct ath12k_hw_link hw_links[ATH12K_GROUP_MAX_RADIO];
bool hw_link_id_init_done;
@ -1041,9 +1078,11 @@ struct ath12k_base {
*/
struct ieee80211_regdomain *new_regd[MAX_RADIOS];
struct ath12k_reg_info *reg_info[MAX_RADIOS];
/* Current DFS Regulatory */
enum ath12k_dfs_region dfs_region;
struct ath12k_soc_dp_stats soc_stats;
struct ath12k_device_dp_stats device_stats;
#ifdef CONFIG_ATH12K_DEBUGFS
struct dentry *debugfs_soc;
#endif
@ -1072,8 +1111,6 @@ struct ath12k_base {
struct ath12k_dbring_cap *db_caps;
u32 num_db_cap;
struct timer_list mon_reap_timer;
struct completion htc_suspend;
u64 fw_soc_drop_count;
@ -1246,6 +1283,7 @@ struct ath12k_fw_stats_pdev {
};
int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab);
void ath12k_core_hw_group_cleanup(struct ath12k_hw_group *ag);
int ath12k_core_pre_init(struct ath12k_base *ab);
int ath12k_core_init(struct ath12k_base *ath12k);
void ath12k_core_deinit(struct ath12k_base *ath12k);
@ -1342,8 +1380,16 @@ static inline void ath12k_core_create_firmware_path(struct ath12k_base *ab,
const char *filename,
void *buf, size_t buf_len)
{
snprintf(buf, buf_len, "%s/%s/%s", ATH12K_FW_DIR,
ab->hw_params->fw.dir, filename);
const char *fw_name = NULL;
of_property_read_string(ab->dev->of_node, "firmware-name", &fw_name);
if (fw_name && strncmp(filename, "board", 5))
snprintf(buf, buf_len, "%s/%s/%s/%s", ATH12K_FW_DIR,
ab->hw_params->fw.dir, fw_name, filename);
else
snprintf(buf, buf_len, "%s/%s/%s", ATH12K_FW_DIR,
ab->hw_params->fw.dir, filename);
}
static inline const char *ath12k_bus_str(enum ath12k_bus bus)

@ -33,6 +33,76 @@ static const struct file_operations fops_simulate_radar = {
.open = simple_open
};
static ssize_t ath12k_read_simulate_fw_crash(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
const char buf[] =
"To simulate firmware crash write one of the keywords to this file:\n"
"`assert` - send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n";
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
}
static ssize_t
ath12k_write_simulate_fw_crash(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath12k_base *ab = file->private_data;
struct ath12k_pdev *pdev;
struct ath12k *ar = NULL;
char buf[32] = {0};
int i, ret;
ssize_t rc;
/* filter partial writes and invalid commands */
if (*ppos != 0 || count >= sizeof(buf) || count == 0)
return -EINVAL;
rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
if (rc < 0)
return rc;
/* drop the possible '\n' from the end */
if (buf[*ppos - 1] == '\n')
buf[*ppos - 1] = '\0';
for (i = 0; i < ab->num_radios; i++) {
pdev = &ab->pdevs[i];
ar = pdev->ar;
if (ar)
break;
}
if (!ar)
return -ENETDOWN;
if (!strcmp(buf, "assert")) {
ath12k_info(ab, "simulating firmware assert crash\n");
ret = ath12k_wmi_force_fw_hang_cmd(ar,
ATH12K_WMI_FW_HANG_ASSERT_TYPE,
ATH12K_WMI_FW_HANG_DELAY);
} else {
return -EINVAL;
}
if (ret) {
ath12k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
return ret;
}
return count;
}
static const struct file_operations fops_simulate_fw_crash = {
.read = ath12k_read_simulate_fw_crash,
.write = ath12k_write_simulate_fw_crash,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t ath12k_write_tpc_stats_type(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
@ -951,6 +1021,199 @@ void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,
&ath12k_fops_link_stats);
}
static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath12k_base *ab = file->private_data;
struct ath12k_device_dp_stats *device_stats = &ab->device_stats;
int len = 0, i, j, ret;
struct ath12k *ar;
const int size = 4096;
static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
[HAL_REO_ENTR_RING_RXDMA_ECODE_OVERFLOW_ERR] = "Overflow",
[HAL_REO_ENTR_RING_RXDMA_ECODE_MPDU_LEN_ERR] = "MPDU len",
[HAL_REO_ENTR_RING_RXDMA_ECODE_FCS_ERR] = "FCS",
[HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR] = "Decrypt",
[HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR] = "TKIP MIC",
[HAL_REO_ENTR_RING_RXDMA_ECODE_UNECRYPTED_ERR] = "Unencrypt",
[HAL_REO_ENTR_RING_RXDMA_ECODE_MSDU_LEN_ERR] = "MSDU len",
[HAL_REO_ENTR_RING_RXDMA_ECODE_MSDU_LIMIT_ERR] = "MSDU limit",
[HAL_REO_ENTR_RING_RXDMA_ECODE_WIFI_PARSE_ERR] = "WiFi parse",
[HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_PARSE_ERR] = "AMSDU parse",
[HAL_REO_ENTR_RING_RXDMA_ECODE_SA_TIMEOUT_ERR] = "SA timeout",
[HAL_REO_ENTR_RING_RXDMA_ECODE_DA_TIMEOUT_ERR] = "DA timeout",
[HAL_REO_ENTR_RING_RXDMA_ECODE_FLOW_TIMEOUT_ERR] = "Flow timeout",
[HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR] = "Flush req",
[HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_FRAG_ERR] = "AMSDU frag",
[HAL_REO_ENTR_RING_RXDMA_ECODE_MULTICAST_ECHO_ERR] = "Multicast echo",
[HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_MISMATCH_ERR] = "AMSDU mismatch",
[HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR] = "Unauth WDS",
[HAL_REO_ENTR_RING_RXDMA_ECODE_GRPCAST_AMSDU_WDS_ERR] = "AMSDU or WDS"};
static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
[HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO] = "Desc addr zero",
[HAL_REO_DEST_RING_ERROR_CODE_DESC_INVALID] = "Desc inval",
[HAL_REO_DEST_RING_ERROR_CODE_AMPDU_IN_NON_BA] = "AMPDU in non BA",
[HAL_REO_DEST_RING_ERROR_CODE_NON_BA_DUPLICATE] = "Non BA dup",
[HAL_REO_DEST_RING_ERROR_CODE_BA_DUPLICATE] = "BA dup",
[HAL_REO_DEST_RING_ERROR_CODE_FRAME_2K_JUMP] = "Frame 2k jump",
[HAL_REO_DEST_RING_ERROR_CODE_BAR_2K_JUMP] = "BAR 2k jump",
[HAL_REO_DEST_RING_ERROR_CODE_FRAME_OOR] = "Frame OOR",
[HAL_REO_DEST_RING_ERROR_CODE_BAR_OOR] = "BAR OOR",
[HAL_REO_DEST_RING_ERROR_CODE_NO_BA_SESSION] = "No BA session",
[HAL_REO_DEST_RING_ERROR_CODE_FRAME_SN_EQUALS_SSN] = "Frame SN equal SSN",
[HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED] = "PN check fail",
[HAL_REO_DEST_RING_ERROR_CODE_2K_ERR_FLAG_SET] = "2k err",
[HAL_REO_DEST_RING_ERROR_CODE_PN_ERR_FLAG_SET] = "PN err",
[HAL_REO_DEST_RING_ERROR_CODE_DESC_BLOCKED] = "Desc blocked"};
static const char *wbm_rel_src[HAL_WBM_REL_SRC_MODULE_MAX] = {
[HAL_WBM_REL_SRC_MODULE_TQM] = "TQM",
[HAL_WBM_REL_SRC_MODULE_RXDMA] = "Rxdma",
[HAL_WBM_REL_SRC_MODULE_REO] = "Reo",
[HAL_WBM_REL_SRC_MODULE_FW] = "FW",
[HAL_WBM_REL_SRC_MODULE_SW] = "SW"};
char *buf __free(kfree) = kzalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
len += scnprintf(buf + len, size - len, "DEVICE RX STATS:\n\n");
len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
device_stats->err_ring_pkts);
len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
device_stats->invalid_rbm);
len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
len += scnprintf(buf + len, size - len, "%s: %u\n",
rxdma_err[i], device_stats->rxdma_error[i]);
len += scnprintf(buf + len, size - len, "\nREO errors:\n");
for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
len += scnprintf(buf + len, size - len, "%s: %u\n",
reo_err[i], device_stats->reo_error[i]);
len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
for (i = 0; i < DP_REO_DST_RING_MAX; i++)
len += scnprintf(buf + len, size - len,
"ring%d: %u\n", i,
device_stats->hal_reo_error[i]);
len += scnprintf(buf + len, size - len, "\nDEVICE TX STATS:\n");
len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
len += scnprintf(buf + len, size - len, "ring%d: %u\n",
i, device_stats->tx_err.desc_na[i]);
len += scnprintf(buf + len, size - len,
"\nMisc Transmit Failures: %d\n",
atomic_read(&device_stats->tx_err.misc_fail));
len += scnprintf(buf + len, size - len, "\ntx_wbm_rel_source:");
for (i = 0; i < HAL_WBM_REL_SRC_MODULE_MAX; i++)
len += scnprintf(buf + len, size - len, " %d:%u",
i, device_stats->tx_wbm_rel_source[i]);
len += scnprintf(buf + len, size - len, "\n");
len += scnprintf(buf + len, size - len, "\ntqm_rel_reason:");
for (i = 0; i < MAX_TQM_RELEASE_REASON; i++)
len += scnprintf(buf + len, size - len, " %d:%u",
i, device_stats->tqm_rel_reason[i]);
len += scnprintf(buf + len, size - len, "\n");
len += scnprintf(buf + len, size - len, "\nfw_tx_status:");
for (i = 0; i < MAX_FW_TX_STATUS; i++)
len += scnprintf(buf + len, size - len, " %d:%u",
i, device_stats->fw_tx_status[i]);
len += scnprintf(buf + len, size - len, "\n");
len += scnprintf(buf + len, size - len, "\ntx_enqueued:");
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
len += scnprintf(buf + len, size - len, " %d:%u", i,
device_stats->tx_enqueued[i]);
len += scnprintf(buf + len, size - len, "\n");
len += scnprintf(buf + len, size - len, "\ntx_completed:");
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
len += scnprintf(buf + len, size - len, " %d:%u",
i, device_stats->tx_completed[i]);
len += scnprintf(buf + len, size - len, "\n");
for (i = 0; i < ab->num_radios; i++) {
ar = ath12k_mac_get_ar_by_pdev_id(ab, DP_SW2HW_MACID(i));
if (ar) {
len += scnprintf(buf + len, size - len,
"\nradio%d tx_pending: %u\n", i,
atomic_read(&ar->dp.num_tx_pending));
}
}
len += scnprintf(buf + len, size - len, "\nREO Rx Received:\n");
for (i = 0; i < DP_REO_DST_RING_MAX; i++) {
len += scnprintf(buf + len, size - len, "Ring%d:", i + 1);
for (j = 0; j < ATH12K_MAX_DEVICES; j++) {
len += scnprintf(buf + len, size - len,
"\t%d:%u", j,
device_stats->reo_rx[i][j]);
}
len += scnprintf(buf + len, size - len, "\n");
}
len += scnprintf(buf + len, size - len, "\nRx WBM REL SRC Errors:\n");
for (i = 0; i < HAL_WBM_REL_SRC_MODULE_MAX; i++) {
len += scnprintf(buf + len, size - len, "%s:", wbm_rel_src[i]);
for (j = 0; j < ATH12K_MAX_DEVICES; j++) {
len += scnprintf(buf + len,
size - len,
"\t%d:%u", j,
device_stats->rx_wbm_rel_source[i][j]);
}
len += scnprintf(buf + len, size - len, "\n");
}
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
return ret;
}
static const struct file_operations fops_device_dp_stats = {
.read = ath12k_debugfs_dump_device_dp_stats,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
void ath12k_debugfs_pdev_create(struct ath12k_base *ab)
{
debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
&fops_simulate_fw_crash);
debugfs_create_file("device_dp_stats", 0400, ab->debugfs_soc, ab,
&fops_device_dp_stats);
}
void ath12k_debugfs_soc_create(struct ath12k_base *ab)
{
bool dput_needed;

@ -16,6 +16,7 @@ void ath12k_debugfs_fw_stats_process(struct ath12k *ar,
struct ath12k_fw_stats *stats);
void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
void ath12k_debugfs_pdev_create(struct ath12k_base *ab);
static inline bool ath12k_debugfs_is_extd_rx_stats_enabled(struct ath12k *ar)
{
@ -144,6 +145,10 @@ static inline void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
}
static inline void ath12k_debugfs_pdev_create(struct ath12k_base *ab)
{
}
#endif /* CONFIG_ATH12K_DEBUGFS */
#endif /* _ATH12K_DEBUGFS_H_ */

@ -168,6 +168,8 @@ static int ath12k_dp_srng_calculate_msi_group(struct ath12k_base *ab,
grp_mask = &ab->hw_params->ring_mask->reo_status[0];
break;
case HAL_RXDMA_MONITOR_STATUS:
grp_mask = &ab->hw_params->ring_mask->rx_mon_status[0];
break;
case HAL_RXDMA_MONITOR_DST:
grp_mask = &ab->hw_params->ring_mask->rx_mon_dest[0];
break;
@ -274,12 +276,17 @@ int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring,
break;
case HAL_RXDMA_BUF:
case HAL_RXDMA_MONITOR_BUF:
case HAL_RXDMA_MONITOR_STATUS:
params.low_threshold = num_entries >> 3;
params.flags |= HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN;
params.intr_batch_cntr_thres_entries = 0;
params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_RX;
break;
case HAL_RXDMA_MONITOR_STATUS:
params.low_threshold = num_entries >> 3;
params.flags |= HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN;
params.intr_batch_cntr_thres_entries = 1;
params.intr_timer_thres_us = HAL_SRNG_INT_TIMER_THRESHOLD_RX;
break;
case HAL_TX_MONITOR_DST:
params.low_threshold = DP_TX_MONITOR_BUF_SIZE_MAX >> 3;
params.flags |= HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN;
@ -354,7 +361,10 @@ u32 ath12k_dp_tx_get_vdev_bank_config(struct ath12k_base *ab,
u32_encode_bits(0, HAL_TX_BANK_CONFIG_EPD);
/* only valid if idx_lookup_override is not set in tcl_data_cmd */
bank_config |= u32_encode_bits(0, HAL_TX_BANK_CONFIG_INDEX_LOOKUP_EN);
if (ahvif->vdev_type == WMI_VDEV_TYPE_STA)
bank_config |= u32_encode_bits(1, HAL_TX_BANK_CONFIG_INDEX_LOOKUP_EN);
else
bank_config |= u32_encode_bits(0, HAL_TX_BANK_CONFIG_INDEX_LOOKUP_EN);
bank_config |= u32_encode_bits(arvif->hal_addr_search_flags & HAL_TX_ADDRX_EN,
HAL_TX_BANK_CONFIG_ADDRX_EN) |
@ -919,6 +929,25 @@ int ath12k_dp_service_srng(struct ath12k_base *ab,
goto done;
}
if (ab->hw_params->ring_mask->rx_mon_status[grp_id]) {
ring_mask = ab->hw_params->ring_mask->rx_mon_status[grp_id];
for (i = 0; i < ab->num_radios; i++) {
for (j = 0; j < ab->hw_params->num_rxdma_per_pdev; j++) {
int id = i * ab->hw_params->num_rxdma_per_pdev + j;
if (ring_mask & BIT(id)) {
work_done =
ath12k_dp_mon_process_ring(ab, id, napi, budget,
0);
budget -= work_done;
tot_work_done += work_done;
if (budget <= 0)
goto done;
}
}
}
}
if (ab->hw_params->ring_mask->rx_mon_dest[grp_id]) {
monitor_mode = ATH12K_DP_RX_MONITOR_MODE;
ring_mask = ab->hw_params->ring_mask->rx_mon_dest[grp_id];
@ -982,11 +1011,6 @@ void ath12k_dp_pdev_free(struct ath12k_base *ab)
{
int i;
if (!ab->mon_reap_timer.function)
return;
timer_delete_sync(&ab->mon_reap_timer);
for (i = 0; i < ab->num_radios; i++)
ath12k_dp_rx_pdev_free(ab, i);
}
@ -1024,27 +1048,6 @@ void ath12k_dp_hal_rx_desc_init(struct ath12k_base *ab)
ab->hal_rx_ops->rx_desc_get_desc_size();
}
static void ath12k_dp_service_mon_ring(struct timer_list *t)
{
struct ath12k_base *ab = from_timer(ab, t, mon_reap_timer);
int i;
for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++)
ath12k_dp_mon_process_ring(ab, i, NULL, DP_MON_SERVICE_BUDGET,
ATH12K_DP_RX_MONITOR_MODE);
mod_timer(&ab->mon_reap_timer, jiffies +
msecs_to_jiffies(ATH12K_MON_TIMER_INTERVAL));
}
static void ath12k_dp_mon_reap_timer_init(struct ath12k_base *ab)
{
if (ab->hw_params->rxdma1_enable)
return;
timer_setup(&ab->mon_reap_timer, ath12k_dp_service_mon_ring, 0);
}
int ath12k_dp_pdev_alloc(struct ath12k_base *ab)
{
struct ath12k *ar;
@ -1055,8 +1058,6 @@ int ath12k_dp_pdev_alloc(struct ath12k_base *ab)
if (ret)
goto out;
ath12k_dp_mon_reap_timer_init(ab);
/* TODO: Per-pdev rx ring unlike tx ring which is mapped to different AC's */
for (i = 0; i < ab->num_radios; i++) {
ar = ab->pdevs[i].ar;
@ -1107,11 +1108,8 @@ static void ath12k_dp_update_vdev_search(struct ath12k_link_vif *arvif)
{
switch (arvif->ahvif->vdev_type) {
case WMI_VDEV_TYPE_STA:
/* TODO: Verify the search type and flags since ast hash
* is not part of peer mapv3
*/
arvif->hal_addr_search_flags = HAL_TX_ADDRY_EN;
arvif->search_type = HAL_TX_ADDR_SEARCH_DEFAULT;
arvif->search_type = HAL_TX_ADDR_SEARCH_INDEX;
break;
case WMI_VDEV_TYPE_AP:
case WMI_VDEV_TYPE_IBSS:

@ -70,6 +70,16 @@ struct ath12k_pdev_mon_stats {
u32 dest_mpdu_drop;
u32 dup_mon_linkdesc_cnt;
u32 dup_mon_buf_cnt;
u32 dest_mon_stuck;
u32 dest_mon_not_reaped;
};
enum dp_mon_status_buf_state {
DP_MON_STATUS_MATCH,
DP_MON_STATUS_NO_DMA,
DP_MON_STATUS_LAG,
DP_MON_STATUS_LEAD,
DP_MON_STATUS_REPLINISH,
};
struct dp_link_desc_bank {
@ -121,8 +131,11 @@ struct ath12k_mon_data {
u32 mon_last_buf_cookie;
u64 mon_last_linkdesc_paddr;
u16 chan_noise_floor;
u32 err_bitmap;
u8 decap_format;
struct ath12k_pdev_mon_stats rx_mon_stats;
enum dp_mon_status_buf_state buf_state;
/* lock for monitor data */
spinlock_t mon_lock;
struct sk_buff_head rx_status_q;
@ -191,6 +204,14 @@ struct ath12k_pdev_dp {
#define DP_RX_BUFFER_SIZE_LITE 1024
#define DP_RX_BUFFER_ALIGN_SIZE 128
#define RX_MON_STATUS_BASE_BUF_SIZE 2048
#define RX_MON_STATUS_BUF_ALIGN 128
#define RX_MON_STATUS_BUF_RESERVATION 128
#define RX_MON_STATUS_BUF_SIZE (RX_MON_STATUS_BASE_BUF_SIZE - \
(RX_MON_STATUS_BUF_RESERVATION + \
RX_MON_STATUS_BUF_ALIGN + \
SKB_DATA_ALIGN(sizeof(struct skb_shared_info))))
#define DP_RXDMA_BUF_COOKIE_BUF_ID GENMASK(17, 0)
#define DP_RXDMA_BUF_COOKIE_PDEV_ID GENMASK(19, 18)
@ -266,6 +287,9 @@ struct ath12k_pdev_dp {
/* Invalid TX Bank ID value */
#define DP_INVALID_BANK_ID -1
#define MAX_TQM_RELEASE_REASON 15
#define MAX_FW_TX_STATUS 7
struct ath12k_dp_tx_bank_profile {
u8 is_configured;
u32 num_users;
@ -338,6 +362,7 @@ struct ath12k_link_stats {
struct ath12k_dp {
struct ath12k_base *ab;
u32 mon_dest_ring_stuck_cnt;
u8 num_bank_profiles;
/* protects the access and update of bank_profiles */
spinlock_t tx_bank_lock;
@ -390,6 +415,7 @@ struct ath12k_dp {
struct dp_srng rxdma_err_dst_ring[MAX_RXDMA_PER_PDEV];
struct dp_rxdma_mon_ring rxdma_mon_buf_ring;
struct dp_rxdma_mon_ring tx_mon_buf_ring;
struct dp_rxdma_mon_ring rx_mon_status_refill_ring[MAX_RXDMA_PER_PDEV];
struct ath12k_reo_q_addr_lut reoq_lut;
struct ath12k_reo_q_addr_lut ml_reoq_lut;
};
@ -1330,6 +1356,8 @@ struct htt_t2h_version_conf_msg {
#define HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16 GENMASK(15, 0)
#define HTT_T2H_PEER_MAP_INFO1_HW_PEER_ID GENMASK(31, 16)
#define HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL GENMASK(15, 0)
#define HTT_T2H_PEER_MAP3_INFO2_HW_PEER_ID GENMASK(15, 0)
#define HTT_T2H_PEER_MAP3_INFO2_AST_HASH_VAL GENMASK(31, 16)
#define HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_M BIT(16)
#define HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_S 16

@ -1416,6 +1416,40 @@ ath12k_dp_mon_hal_rx_parse_user_info(const struct hal_receive_user_info *rx_usr_
}
}
static void ath12k_dp_mon_parse_rx_msdu_end_err(u32 info, u32 *errmap)
{
if (info & RX_MSDU_END_INFO13_FCS_ERR)
*errmap |= HAL_RX_MPDU_ERR_FCS;
if (info & RX_MSDU_END_INFO13_DECRYPT_ERR)
*errmap |= HAL_RX_MPDU_ERR_DECRYPT;
if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR)
*errmap |= HAL_RX_MPDU_ERR_TKIP_MIC;
if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR)
*errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR;
if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR)
*errmap |= HAL_RX_MPDU_ERR_OVERFLOW;
if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR)
*errmap |= HAL_RX_MPDU_ERR_MSDU_LEN;
if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR)
*errmap |= HAL_RX_MPDU_ERR_MPDU_LEN;
}
static void
ath12k_dp_mon_parse_status_msdu_end(struct ath12k_mon_data *pmon,
const struct hal_rx_msdu_end *msdu_end)
{
ath12k_dp_mon_parse_rx_msdu_end_err(__le32_to_cpu(msdu_end->info2),
&pmon->err_bitmap);
pmon->decap_format = le32_get_bits(msdu_end->info1,
RX_MSDU_END_INFO11_DECAP_FORMAT);
}
static enum hal_rx_mon_status
ath12k_dp_mon_rx_parse_status_tlv(struct ath12k *ar,
struct ath12k_mon_data *pmon,
@ -1655,6 +1689,7 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k *ar,
case HAL_MON_BUF_ADDR:
return HAL_RX_MON_STATUS_BUF_ADDR;
case HAL_RX_MSDU_END:
ath12k_dp_mon_parse_status_msdu_end(pmon, tlv_data);
return HAL_RX_MON_STATUS_MSDU_END;
case HAL_RX_MPDU_END:
return HAL_RX_MON_STATUS_MPDU_END;
@ -1716,6 +1751,124 @@ ath12k_dp_mon_fill_rx_stats_info(struct ath12k *ar,
}
}
static struct sk_buff
*ath12k_dp_rx_alloc_mon_status_buf(struct ath12k_base *ab,
struct dp_rxdma_mon_ring *rx_ring,
int *buf_id)
{
struct sk_buff *skb;
dma_addr_t paddr;
skb = dev_alloc_skb(RX_MON_STATUS_BUF_SIZE);
if (!skb)
goto fail_alloc_skb;
if (!IS_ALIGNED((unsigned long)skb->data,
RX_MON_STATUS_BUF_ALIGN)) {
skb_pull(skb, PTR_ALIGN(skb->data, RX_MON_STATUS_BUF_ALIGN) -
skb->data);
}
paddr = dma_map_single(ab->dev, skb->data,
skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(ab->dev, paddr)))
goto fail_free_skb;
spin_lock_bh(&rx_ring->idr_lock);
*buf_id = idr_alloc(&rx_ring->bufs_idr, skb, 0,
rx_ring->bufs_max, GFP_ATOMIC);
spin_unlock_bh(&rx_ring->idr_lock);
if (*buf_id < 0)
goto fail_dma_unmap;
ATH12K_SKB_RXCB(skb)->paddr = paddr;
return skb;
fail_dma_unmap:
dma_unmap_single(ab->dev, paddr, skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
fail_free_skb:
dev_kfree_skb_any(skb);
fail_alloc_skb:
return NULL;
}
static enum dp_mon_status_buf_state
ath12k_dp_rx_mon_buf_done(struct ath12k_base *ab, struct hal_srng *srng,
struct dp_rxdma_mon_ring *rx_ring)
{
struct ath12k_skb_rxcb *rxcb;
struct hal_tlv_64_hdr *tlv;
struct sk_buff *skb;
void *status_desc;
dma_addr_t paddr;
u32 cookie;
int buf_id;
u8 rbm;
status_desc = ath12k_hal_srng_src_next_peek(ab, srng);
if (!status_desc)
return DP_MON_STATUS_NO_DMA;
ath12k_hal_rx_buf_addr_info_get(status_desc, &paddr, &cookie, &rbm);
buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID);
spin_lock_bh(&rx_ring->idr_lock);
skb = idr_find(&rx_ring->bufs_idr, buf_id);
spin_unlock_bh(&rx_ring->idr_lock);
if (!skb)
return DP_MON_STATUS_NO_DMA;
rxcb = ATH12K_SKB_RXCB(skb);
dma_sync_single_for_cpu(ab->dev, rxcb->paddr,
skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
tlv = (struct hal_tlv_64_hdr *)skb->data;
if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) != HAL_RX_STATUS_BUFFER_DONE)
return DP_MON_STATUS_NO_DMA;
return DP_MON_STATUS_REPLINISH;
}
static u32 ath12k_dp_mon_comp_ppduid(u32 msdu_ppdu_id, u32 *ppdu_id)
{
u32 ret = 0;
if ((*ppdu_id < msdu_ppdu_id) &&
((msdu_ppdu_id - *ppdu_id) < DP_NOT_PPDU_ID_WRAP_AROUND)) {
/* Hold on mon dest ring, and reap mon status ring. */
*ppdu_id = msdu_ppdu_id;
ret = msdu_ppdu_id;
} else if ((*ppdu_id > msdu_ppdu_id) &&
((*ppdu_id - msdu_ppdu_id) > DP_NOT_PPDU_ID_WRAP_AROUND)) {
/* PPDU ID has exceeded the maximum value and will
* restart from 0.
*/
*ppdu_id = msdu_ppdu_id;
ret = msdu_ppdu_id;
}
return ret;
}
static
void ath12k_dp_mon_next_link_desc_get(struct hal_rx_msdu_link *msdu_link,
dma_addr_t *paddr, u32 *sw_cookie, u8 *rbm,
struct ath12k_buffer_addr **pp_buf_addr_info)
{
struct ath12k_buffer_addr *buf_addr_info;
buf_addr_info = &msdu_link->buf_addr_info;
ath12k_hal_rx_buf_addr_info_get(buf_addr_info, paddr, sw_cookie, rbm);
*pp_buf_addr_info = buf_addr_info;
}
static void
ath12k_dp_mon_fill_rx_rate(struct ath12k *ar,
struct hal_rx_mon_ppdu_info *ppdu_info,
@ -1795,6 +1948,24 @@ ath12k_dp_mon_fill_rx_rate(struct ath12k *ar,
}
}
static void ath12k_dp_mon_rx_msdus_set_payload(struct ath12k *ar,
struct sk_buff *head_msdu,
struct sk_buff *tail_msdu)
{
u32 rx_pkt_offset, l2_hdr_offset, total_offset;
rx_pkt_offset = ar->ab->hal.hal_desc_sz;
l2_hdr_offset =
ath12k_dp_rx_h_l3pad(ar->ab, (struct hal_rx_desc *)tail_msdu->data);
if (ar->ab->hw_params->rxdma1_enable)
total_offset = ATH12K_MON_RX_PKT_OFFSET;
else
total_offset = rx_pkt_offset + l2_hdr_offset;
skb_pull(head_msdu, total_offset);
}
static struct sk_buff *
ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
struct dp_mon_mpdu *mon_mpdu,
@ -1803,7 +1974,7 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
{
struct ath12k_base *ab = ar->ab;
struct sk_buff *msdu, *mpdu_buf, *prev_buf, *head_frag_list;
struct sk_buff *head_msdu;
struct sk_buff *head_msdu, *tail_msdu;
struct hal_rx_desc *rx_desc;
u8 *hdr_desc, *dest, decap_format = mon_mpdu->decap_format;
struct ieee80211_hdr_3addr *wh;
@ -1813,8 +1984,9 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
mpdu_buf = NULL;
head_msdu = mon_mpdu->head;
tail_msdu = mon_mpdu->tail;
if (!head_msdu)
if (!head_msdu || !tail_msdu)
goto err_merge_fail;
ath12k_dp_mon_fill_rx_stats_info(ar, ppdu_info, rxs);
@ -1842,14 +2014,14 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
ath12k_dp_mon_fill_rx_rate(ar, ppdu_info, rxs);
if (decap_format == DP_RX_DECAP_TYPE_RAW) {
skb_pull(head_msdu, ATH12K_MON_RX_PKT_OFFSET);
ath12k_dp_mon_rx_msdus_set_payload(ar, head_msdu, tail_msdu);
prev_buf = head_msdu;
msdu = head_msdu->next;
head_frag_list = NULL;
while (msdu) {
skb_pull(msdu, ATH12K_MON_RX_PKT_OFFSET);
ath12k_dp_mon_rx_msdus_set_payload(ar, head_msdu, tail_msdu);
if (!head_frag_list)
head_frag_list = msdu;
@ -1884,7 +2056,7 @@ ath12k_dp_mon_rx_merg_msdus(struct ath12k *ar,
msdu = head_msdu;
while (msdu) {
skb_pull(msdu, ATH12K_MON_RX_PKT_OFFSET);
ath12k_dp_mon_rx_msdus_set_payload(ar, head_msdu, tail_msdu);
if (qos_pkt) {
dest = skb_push(msdu, sizeof(__le16));
if (!dest)
@ -2223,43 +2395,30 @@ static int ath12k_dp_pkt_set_pktlen(struct sk_buff *skb, u32 len)
return 0;
}
static void ath12k_dp_mon_parse_rx_msdu_end_err(u32 info, u32 *errmap)
/* Hardware fill buffer with 128 bytes aligned. So need to reap it
* with 128 bytes aligned.
*/
#define RXDMA_DATA_DMA_BLOCK_SIZE 128
static void
ath12k_dp_mon_get_buf_len(struct hal_rx_msdu_desc_info *info,
bool *is_frag, u32 *total_len,
u32 *frag_len, u32 *msdu_cnt)
{
if (info & RX_MSDU_END_INFO13_FCS_ERR)
*errmap |= HAL_RX_MPDU_ERR_FCS;
if (info->msdu_flags & RX_MSDU_DESC_INFO0_MSDU_CONTINUATION) {
*is_frag = true;
*frag_len = (RX_MON_STATUS_BASE_BUF_SIZE -
sizeof(struct hal_rx_desc)) &
~(RXDMA_DATA_DMA_BLOCK_SIZE - 1);
*total_len += *frag_len;
} else {
if (*is_frag)
*frag_len = info->msdu_len - *total_len;
else
*frag_len = info->msdu_len;
if (info & RX_MSDU_END_INFO13_DECRYPT_ERR)
*errmap |= HAL_RX_MPDU_ERR_DECRYPT;
if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR)
*errmap |= HAL_RX_MPDU_ERR_TKIP_MIC;
if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR)
*errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR;
if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR)
*errmap |= HAL_RX_MPDU_ERR_OVERFLOW;
if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR)
*errmap |= HAL_RX_MPDU_ERR_MSDU_LEN;
if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR)
*errmap |= HAL_RX_MPDU_ERR_MPDU_LEN;
}
static int
ath12k_dp_mon_parse_status_msdu_end(struct ath12k_mon_data *pmon,
const struct hal_rx_msdu_end *msdu_end)
{
struct dp_mon_mpdu *mon_mpdu = pmon->mon_mpdu;
ath12k_dp_mon_parse_rx_msdu_end_err(__le32_to_cpu(msdu_end->info2),
&mon_mpdu->err_bitmap);
mon_mpdu->decap_format = le32_get_bits(msdu_end->info1,
RX_MSDU_END_INFO11_DECAP_FORMAT);
return 0;
*msdu_cnt -= 1;
}
}
static int
@ -2335,7 +2494,9 @@ ath12k_dp_mon_parse_rx_dest_tlv(struct ath12k *ar,
pmon->mon_mpdu = NULL;
break;
case HAL_RX_MON_STATUS_MSDU_END:
return ath12k_dp_mon_parse_status_msdu_end(pmon, tlv_data);
pmon->mon_mpdu->decap_format = pmon->decap_format;
pmon->mon_mpdu->err_bitmap = pmon->err_bitmap;
break;
default:
break;
}
@ -2370,7 +2531,7 @@ ath12k_dp_mon_parse_rx_dest(struct ath12k *ar, struct ath12k_mon_data *pmon,
hal_status = ath12k_dp_mon_rx_parse_status_tlv(ar, pmon, tlv);
if (ar->monitor_started &&
if (ar->monitor_started && ar->ab->hw_params->rxdma1_enable &&
ath12k_dp_mon_parse_rx_dest_tlv(ar, pmon, hal_status, tlv->value))
return HAL_RX_MON_STATUS_PPDU_DONE;
@ -2495,6 +2656,94 @@ int ath12k_dp_mon_buf_replenish(struct ath12k_base *ab,
return -ENOMEM;
}
int ath12k_dp_mon_status_bufs_replenish(struct ath12k_base *ab,
struct dp_rxdma_mon_ring *rx_ring,
int req_entries)
{
enum hal_rx_buf_return_buf_manager mgr =
ab->hw_params->hal_params->rx_buf_rbm;
int num_free, num_remain, buf_id;
struct ath12k_buffer_addr *desc;
struct hal_srng *srng;
struct sk_buff *skb;
dma_addr_t paddr;
u32 cookie;
req_entries = min(req_entries, rx_ring->bufs_max);
srng = &ab->hal.srng_list[rx_ring->refill_buf_ring.ring_id];
spin_lock_bh(&srng->lock);
ath12k_hal_srng_access_begin(ab, srng);
num_free = ath12k_hal_srng_src_num_free(ab, srng, true);
if (!req_entries && (num_free > (rx_ring->bufs_max * 3) / 4))
req_entries = num_free;
req_entries = min(num_free, req_entries);
num_remain = req_entries;
while (num_remain > 0) {
skb = dev_alloc_skb(RX_MON_STATUS_BUF_SIZE);
if (!skb)
break;
if (!IS_ALIGNED((unsigned long)skb->data,
RX_MON_STATUS_BUF_ALIGN)) {
skb_pull(skb,
PTR_ALIGN(skb->data, RX_MON_STATUS_BUF_ALIGN) -
skb->data);
}
paddr = dma_map_single(ab->dev, skb->data,
skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
if (dma_mapping_error(ab->dev, paddr))
goto fail_free_skb;
spin_lock_bh(&rx_ring->idr_lock);
buf_id = idr_alloc(&rx_ring->bufs_idr, skb, 0,
rx_ring->bufs_max * 3, GFP_ATOMIC);
spin_unlock_bh(&rx_ring->idr_lock);
if (buf_id < 0)
goto fail_dma_unmap;
cookie = u32_encode_bits(buf_id, DP_RXDMA_BUF_COOKIE_BUF_ID);
desc = ath12k_hal_srng_src_get_next_entry(ab, srng);
if (!desc)
goto fail_buf_unassign;
ATH12K_SKB_RXCB(skb)->paddr = paddr;
num_remain--;
ath12k_hal_rx_buf_addr_info_set(desc, paddr, cookie, mgr);
}
ath12k_hal_srng_access_end(ab, srng);
spin_unlock_bh(&srng->lock);
return req_entries - num_remain;
fail_buf_unassign:
spin_lock_bh(&rx_ring->idr_lock);
idr_remove(&rx_ring->bufs_idr, buf_id);
spin_unlock_bh(&rx_ring->idr_lock);
fail_dma_unmap:
dma_unmap_single(ab->dev, paddr, skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
fail_free_skb:
dev_kfree_skb_any(skb);
ath12k_hal_srng_access_end(ab, srng);
spin_unlock_bh(&srng->lock);
return req_entries - num_remain;
}
static struct dp_mon_tx_ppdu_info *
ath12k_dp_mon_tx_get_ppdu_info(struct ath12k_mon_data *pmon,
unsigned int ppdu_id,
@ -3641,6 +3890,487 @@ int ath12k_dp_mon_srng_process(struct ath12k *ar, int *budget,
return num_buffs_reaped;
}
static int ath12k_dp_rx_reap_mon_status_ring(struct ath12k_base *ab, int mac_id,
int *budget, struct sk_buff_head *skb_list)
{
const struct ath12k_hw_hal_params *hal_params;
int buf_id, srng_id, num_buffs_reaped = 0;
enum dp_mon_status_buf_state reap_status;
struct dp_rxdma_mon_ring *rx_ring;
struct ath12k_mon_data *pmon;
struct ath12k_skb_rxcb *rxcb;
struct hal_tlv_64_hdr *tlv;
void *rx_mon_status_desc;
struct hal_srng *srng;
struct ath12k_dp *dp;
struct sk_buff *skb;
struct ath12k *ar;
dma_addr_t paddr;
u32 cookie;
u8 rbm;
ar = ab->pdevs[ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id)].ar;
dp = &ab->dp;
pmon = &ar->dp.mon_data;
srng_id = ath12k_hw_mac_id_to_srng_id(ab->hw_params, mac_id);
rx_ring = &dp->rx_mon_status_refill_ring[srng_id];
srng = &ab->hal.srng_list[rx_ring->refill_buf_ring.ring_id];
spin_lock_bh(&srng->lock);
ath12k_hal_srng_access_begin(ab, srng);
while (*budget) {
*budget -= 1;
rx_mon_status_desc = ath12k_hal_srng_src_peek(ab, srng);
if (!rx_mon_status_desc) {
pmon->buf_state = DP_MON_STATUS_REPLINISH;
break;
}
ath12k_hal_rx_buf_addr_info_get(rx_mon_status_desc, &paddr,
&cookie, &rbm);
if (paddr) {
buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID);
spin_lock_bh(&rx_ring->idr_lock);
skb = idr_find(&rx_ring->bufs_idr, buf_id);
spin_unlock_bh(&rx_ring->idr_lock);
if (!skb) {
ath12k_warn(ab, "rx monitor status with invalid buf_id %d\n",
buf_id);
pmon->buf_state = DP_MON_STATUS_REPLINISH;
goto move_next;
}
rxcb = ATH12K_SKB_RXCB(skb);
dma_sync_single_for_cpu(ab->dev, rxcb->paddr,
skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
tlv = (struct hal_tlv_64_hdr *)skb->data;
if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) !=
HAL_RX_STATUS_BUFFER_DONE) {
pmon->buf_state = DP_MON_STATUS_NO_DMA;
ath12k_warn(ab,
"mon status DONE not set %llx, buf_id %d\n",
le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG),
buf_id);
/* RxDMA status done bit might not be set even
* though tp is moved by HW.
*/
/* If done status is missing:
* 1. As per MAC team's suggestion,
* when HP + 1 entry is peeked and if DMA
* is not done and if HP + 2 entry's DMA done
* is set. skip HP + 1 entry and
* start processing in next interrupt.
* 2. If HP + 2 entry's DMA done is not set,
* poll onto HP + 1 entry DMA done to be set.
* Check status for same buffer for next time
* dp_rx_mon_status_srng_process
*/
reap_status = ath12k_dp_rx_mon_buf_done(ab, srng,
rx_ring);
if (reap_status == DP_MON_STATUS_NO_DMA)
continue;
spin_lock_bh(&rx_ring->idr_lock);
idr_remove(&rx_ring->bufs_idr, buf_id);
spin_unlock_bh(&rx_ring->idr_lock);
dma_unmap_single(ab->dev, rxcb->paddr,
skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
pmon->buf_state = DP_MON_STATUS_REPLINISH;
goto move_next;
}
spin_lock_bh(&rx_ring->idr_lock);
idr_remove(&rx_ring->bufs_idr, buf_id);
spin_unlock_bh(&rx_ring->idr_lock);
dma_unmap_single(ab->dev, rxcb->paddr,
skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
if (ath12k_dp_pkt_set_pktlen(skb, RX_MON_STATUS_BUF_SIZE)) {
dev_kfree_skb_any(skb);
goto move_next;
}
__skb_queue_tail(skb_list, skb);
} else {
pmon->buf_state = DP_MON_STATUS_REPLINISH;
}
move_next:
skb = ath12k_dp_rx_alloc_mon_status_buf(ab, rx_ring,
&buf_id);
if (!skb) {
ath12k_warn(ab, "failed to alloc buffer for status ring\n");
hal_params = ab->hw_params->hal_params;
ath12k_hal_rx_buf_addr_info_set(rx_mon_status_desc, 0, 0,
hal_params->rx_buf_rbm);
num_buffs_reaped++;
break;
}
rxcb = ATH12K_SKB_RXCB(skb);
cookie = u32_encode_bits(mac_id, DP_RXDMA_BUF_COOKIE_PDEV_ID) |
u32_encode_bits(buf_id, DP_RXDMA_BUF_COOKIE_BUF_ID);
ath12k_hal_rx_buf_addr_info_set(rx_mon_status_desc, rxcb->paddr,
cookie,
ab->hw_params->hal_params->rx_buf_rbm);
ath12k_hal_srng_src_get_next_entry(ab, srng);
num_buffs_reaped++;
}
ath12k_hal_srng_access_end(ab, srng);
spin_unlock_bh(&srng->lock);
return num_buffs_reaped;
}
static u32
ath12k_dp_rx_mon_mpdu_pop(struct ath12k *ar, int mac_id,
void *ring_entry, struct sk_buff **head_msdu,
struct sk_buff **tail_msdu,
struct list_head *used_list,
u32 *npackets, u32 *ppdu_id)
{
struct ath12k_mon_data *pmon = (struct ath12k_mon_data *)&ar->dp.mon_data;
struct ath12k_buffer_addr *p_buf_addr_info, *p_last_buf_addr_info;
u32 msdu_ppdu_id = 0, msdu_cnt = 0, total_len = 0, frag_len = 0;
u32 rx_buf_size, rx_pkt_offset, sw_cookie;
bool is_frag, is_first_msdu, drop_mpdu = false;
struct hal_reo_entrance_ring *ent_desc =
(struct hal_reo_entrance_ring *)ring_entry;
u32 rx_bufs_used = 0, i = 0, desc_bank = 0;
struct hal_rx_desc *rx_desc, *tail_rx_desc;
struct hal_rx_msdu_link *msdu_link_desc;
struct sk_buff *msdu = NULL, *last = NULL;
struct ath12k_rx_desc_info *desc_info;
struct ath12k_buffer_addr buf_info;
struct hal_rx_msdu_list msdu_list;
struct ath12k_skb_rxcb *rxcb;
u16 num_msdus = 0;
dma_addr_t paddr;
u8 rbm;
ath12k_hal_rx_reo_ent_buf_paddr_get(ring_entry, &paddr,
&sw_cookie,
&p_last_buf_addr_info, &rbm,
&msdu_cnt);
spin_lock_bh(&pmon->mon_lock);
if (le32_get_bits(ent_desc->info1,
HAL_REO_ENTR_RING_INFO1_RXDMA_PUSH_REASON) ==
HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED) {
u8 rxdma_err = le32_get_bits(ent_desc->info1,
HAL_REO_ENTR_RING_INFO1_RXDMA_ERROR_CODE);
if (rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR ||
rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_MPDU_LEN_ERR ||
rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_OVERFLOW_ERR) {
drop_mpdu = true;
pmon->rx_mon_stats.dest_mpdu_drop++;
}
}
is_frag = false;
is_first_msdu = true;
rx_pkt_offset = sizeof(struct hal_rx_desc);
do {
if (pmon->mon_last_linkdesc_paddr == paddr) {
pmon->rx_mon_stats.dup_mon_linkdesc_cnt++;
spin_unlock_bh(&pmon->mon_lock);
return rx_bufs_used;
}
desc_bank = u32_get_bits(sw_cookie, DP_LINK_DESC_BANK_MASK);
msdu_link_desc =
ar->ab->dp.link_desc_banks[desc_bank].vaddr +
(paddr - ar->ab->dp.link_desc_banks[desc_bank].paddr);
ath12k_hal_rx_msdu_list_get(ar, msdu_link_desc, &msdu_list,
&num_msdus);
desc_info = ath12k_dp_get_rx_desc(ar->ab,
msdu_list.sw_cookie[num_msdus - 1]);
tail_rx_desc = (struct hal_rx_desc *)(desc_info->skb)->data;
for (i = 0; i < num_msdus; i++) {
u32 l2_hdr_offset;
if (pmon->mon_last_buf_cookie == msdu_list.sw_cookie[i]) {
ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
"i %d last_cookie %d is same\n",
i, pmon->mon_last_buf_cookie);
drop_mpdu = true;
pmon->rx_mon_stats.dup_mon_buf_cnt++;
continue;
}
desc_info =
ath12k_dp_get_rx_desc(ar->ab, msdu_list.sw_cookie[i]);
msdu = desc_info->skb;
if (!msdu) {
ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
"msdu_pop: invalid msdu (%d/%d)\n",
i + 1, num_msdus);
goto next_msdu;
}
rxcb = ATH12K_SKB_RXCB(msdu);
if (rxcb->paddr != msdu_list.paddr[i]) {
ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
"i %d paddr %lx != %lx\n",
i, (unsigned long)rxcb->paddr,
(unsigned long)msdu_list.paddr[i]);
drop_mpdu = true;
continue;
}
if (!rxcb->unmapped) {
dma_unmap_single(ar->ab->dev, rxcb->paddr,
msdu->len +
skb_tailroom(msdu),
DMA_FROM_DEVICE);
rxcb->unmapped = 1;
}
if (drop_mpdu) {
ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
"i %d drop msdu %p *ppdu_id %x\n",
i, msdu, *ppdu_id);
dev_kfree_skb_any(msdu);
msdu = NULL;
goto next_msdu;
}
rx_desc = (struct hal_rx_desc *)msdu->data;
l2_hdr_offset = ath12k_dp_rx_h_l3pad(ar->ab, tail_rx_desc);
if (is_first_msdu) {
if (!ath12k_dp_rxdesc_mpdu_valid(ar->ab, rx_desc)) {
drop_mpdu = true;
dev_kfree_skb_any(msdu);
msdu = NULL;
pmon->mon_last_linkdesc_paddr = paddr;
goto next_msdu;
}
msdu_ppdu_id =
ath12k_dp_rxdesc_get_ppduid(ar->ab, rx_desc);
if (ath12k_dp_mon_comp_ppduid(msdu_ppdu_id,
ppdu_id)) {
spin_unlock_bh(&pmon->mon_lock);
return rx_bufs_used;
}
pmon->mon_last_linkdesc_paddr = paddr;
is_first_msdu = false;
}
ath12k_dp_mon_get_buf_len(&msdu_list.msdu_info[i],
&is_frag, &total_len,
&frag_len, &msdu_cnt);
rx_buf_size = rx_pkt_offset + l2_hdr_offset + frag_len;
if (ath12k_dp_pkt_set_pktlen(msdu, rx_buf_size)) {
dev_kfree_skb_any(msdu);
goto next_msdu;
}
if (!(*head_msdu))
*head_msdu = msdu;
else if (last)
last->next = msdu;
last = msdu;
next_msdu:
pmon->mon_last_buf_cookie = msdu_list.sw_cookie[i];
rx_bufs_used++;
desc_info->skb = NULL;
list_add_tail(&desc_info->list, used_list);
}
ath12k_hal_rx_buf_addr_info_set(&buf_info, paddr, sw_cookie, rbm);
ath12k_dp_mon_next_link_desc_get(msdu_link_desc, &paddr,
&sw_cookie, &rbm,
&p_buf_addr_info);
ath12k_dp_rx_link_desc_return(ar->ab, &buf_info,
HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
p_last_buf_addr_info = p_buf_addr_info;
} while (paddr && msdu_cnt);
spin_unlock_bh(&pmon->mon_lock);
if (last)
last->next = NULL;
*tail_msdu = msdu;
if (msdu_cnt == 0)
*npackets = 1;
return rx_bufs_used;
}
/* The destination ring processing is stuck if the destination is not
* moving while status ring moves 16 PPDU. The destination ring processing
* skips this destination ring PPDU as a workaround.
*/
#define MON_DEST_RING_STUCK_MAX_CNT 16
static void ath12k_dp_rx_mon_dest_process(struct ath12k *ar, int mac_id,
u32 quota, struct napi_struct *napi)
{
struct ath12k_mon_data *pmon = (struct ath12k_mon_data *)&ar->dp.mon_data;
struct ath12k_pdev_mon_stats *rx_mon_stats;
u32 ppdu_id, rx_bufs_used = 0, ring_id;
u32 mpdu_rx_bufs_used, npackets = 0;
struct ath12k_dp *dp = &ar->ab->dp;
struct ath12k_base *ab = ar->ab;
void *ring_entry, *mon_dst_srng;
struct dp_mon_mpdu *tmp_mpdu;
LIST_HEAD(rx_desc_used_list);
struct hal_srng *srng;
ring_id = dp->rxdma_err_dst_ring[mac_id].ring_id;
srng = &ab->hal.srng_list[ring_id];
mon_dst_srng = &ab->hal.srng_list[ring_id];
spin_lock_bh(&srng->lock);
ath12k_hal_srng_access_begin(ab, mon_dst_srng);
ppdu_id = pmon->mon_ppdu_info.ppdu_id;
rx_mon_stats = &pmon->rx_mon_stats;
while ((ring_entry = ath12k_hal_srng_dst_peek(ar->ab, mon_dst_srng))) {
struct sk_buff *head_msdu, *tail_msdu;
head_msdu = NULL;
tail_msdu = NULL;
mpdu_rx_bufs_used = ath12k_dp_rx_mon_mpdu_pop(ar, mac_id, ring_entry,
&head_msdu, &tail_msdu,
&rx_desc_used_list,
&npackets, &ppdu_id);
rx_bufs_used += mpdu_rx_bufs_used;
if (mpdu_rx_bufs_used) {
dp->mon_dest_ring_stuck_cnt = 0;
} else {
dp->mon_dest_ring_stuck_cnt++;
rx_mon_stats->dest_mon_not_reaped++;
}
if (dp->mon_dest_ring_stuck_cnt > MON_DEST_RING_STUCK_MAX_CNT) {
rx_mon_stats->dest_mon_stuck++;
ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
"status ring ppdu_id=%d dest ring ppdu_id=%d mon_dest_ring_stuck_cnt=%d dest_mon_not_reaped=%u dest_mon_stuck=%u\n",
pmon->mon_ppdu_info.ppdu_id, ppdu_id,
dp->mon_dest_ring_stuck_cnt,
rx_mon_stats->dest_mon_not_reaped,
rx_mon_stats->dest_mon_stuck);
spin_lock_bh(&pmon->mon_lock);
pmon->mon_ppdu_info.ppdu_id = ppdu_id;
spin_unlock_bh(&pmon->mon_lock);
continue;
}
if (ppdu_id != pmon->mon_ppdu_info.ppdu_id) {
spin_lock_bh(&pmon->mon_lock);
pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
spin_unlock_bh(&pmon->mon_lock);
ath12k_dbg(ar->ab, ATH12K_DBG_DATA,
"dest_rx: new ppdu_id %x != status ppdu_id %x dest_mon_not_reaped = %u dest_mon_stuck = %u\n",
ppdu_id, pmon->mon_ppdu_info.ppdu_id,
rx_mon_stats->dest_mon_not_reaped,
rx_mon_stats->dest_mon_stuck);
break;
}
if (head_msdu && tail_msdu) {
tmp_mpdu = kzalloc(sizeof(*tmp_mpdu), GFP_ATOMIC);
if (!tmp_mpdu)
break;
tmp_mpdu->head = head_msdu;
tmp_mpdu->tail = tail_msdu;
tmp_mpdu->err_bitmap = pmon->err_bitmap;
tmp_mpdu->decap_format = pmon->decap_format;
ath12k_dp_mon_rx_deliver(ar, tmp_mpdu,
&pmon->mon_ppdu_info, napi);
rx_mon_stats->dest_mpdu_done++;
kfree(tmp_mpdu);
}
ring_entry = ath12k_hal_srng_dst_get_next_entry(ar->ab,
mon_dst_srng);
}
ath12k_hal_srng_access_end(ar->ab, mon_dst_srng);
spin_unlock_bh(&srng->lock);
if (rx_bufs_used) {
rx_mon_stats->dest_ppdu_done++;
ath12k_dp_rx_bufs_replenish(ar->ab,
&dp->rx_refill_buf_ring,
&rx_desc_used_list,
rx_bufs_used);
}
}
static int
__ath12k_dp_mon_process_ring(struct ath12k *ar, int mac_id,
struct napi_struct *napi, int *budget)
{
struct ath12k_mon_data *pmon = (struct ath12k_mon_data *)&ar->dp.mon_data;
struct ath12k_pdev_mon_stats *rx_mon_stats = &pmon->rx_mon_stats;
struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
enum hal_rx_mon_status hal_status;
struct sk_buff_head skb_list;
int num_buffs_reaped;
struct sk_buff *skb;
__skb_queue_head_init(&skb_list);
num_buffs_reaped = ath12k_dp_rx_reap_mon_status_ring(ar->ab, mac_id,
budget, &skb_list);
if (!num_buffs_reaped)
goto exit;
while ((skb = __skb_dequeue(&skb_list))) {
memset(ppdu_info, 0, sizeof(*ppdu_info));
ppdu_info->peer_id = HAL_INVALID_PEERID;
hal_status = ath12k_dp_mon_parse_rx_dest(ar, pmon, skb);
if (ar->monitor_started &&
pmon->mon_ppdu_status == DP_PPDU_STATUS_START &&
hal_status == HAL_TLV_STATUS_PPDU_DONE) {
rx_mon_stats->status_ppdu_done++;
pmon->mon_ppdu_status = DP_PPDU_STATUS_DONE;
ath12k_dp_rx_mon_dest_process(ar, mac_id, *budget, napi);
pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
}
dev_kfree_skb_any(skb);
}
exit:
return num_buffs_reaped;
}
int ath12k_dp_mon_process_ring(struct ath12k_base *ab, int mac_id,
struct napi_struct *napi, int budget,
enum dp_monitor_mode monitor_mode)
@ -3651,6 +4381,10 @@ int ath12k_dp_mon_process_ring(struct ath12k_base *ab, int mac_id,
if (ab->hw_params->rxdma1_enable) {
if (monitor_mode == ATH12K_DP_RX_MONITOR_MODE)
num_buffs_reaped = ath12k_dp_mon_srng_process(ar, &budget, napi);
} else {
if (ar->monitor_started)
num_buffs_reaped =
__ath12k_dp_mon_process_ring(ar, mac_id, napi, &budget);
}
return num_buffs_reaped;

@ -85,6 +85,9 @@ ath12k_dp_mon_rx_parse_mon_status(struct ath12k *ar,
int ath12k_dp_mon_buf_replenish(struct ath12k_base *ab,
struct dp_rxdma_mon_ring *buf_ring,
int req_entries);
int ath12k_dp_mon_status_bufs_replenish(struct ath12k_base *ab,
struct dp_rxdma_mon_ring *rx_ring,
int req_entries);
int ath12k_dp_mon_process_ring(struct ath12k_base *ab, int mac_id,
struct napi_struct *napi, int budget,
enum dp_monitor_mode monitor_mode);

@ -194,6 +194,22 @@ static void ath12k_dp_rxdesc_set_msdu_len(struct ath12k_base *ab,
ab->hal_rx_ops->rx_desc_set_msdu_len(desc, len);
}
u32 ath12k_dp_rxdesc_get_ppduid(struct ath12k_base *ab,
struct hal_rx_desc *rx_desc)
{
return ab->hal_rx_ops->rx_desc_get_mpdu_ppdu_id(rx_desc);
}
bool ath12k_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
struct hal_rx_desc *rx_desc)
{
u32 tlv_tag;
tlv_tag = ab->hal_rx_ops->rx_desc_get_mpdu_start_tag(rx_desc);
return tlv_tag == HAL_RX_MPDU_START;
}
static bool ath12k_dp_rx_h_is_da_mcbc(struct ath12k_base *ab,
struct hal_rx_desc *desc)
{
@ -414,9 +430,17 @@ static int ath12k_dp_rxdma_mon_buf_ring_free(struct ath12k_base *ab,
static int ath12k_dp_rxdma_buf_free(struct ath12k_base *ab)
{
struct ath12k_dp *dp = &ab->dp;
int i;
ath12k_dp_rxdma_mon_buf_ring_free(ab, &dp->rxdma_mon_buf_ring);
if (ab->hw_params->rxdma1_enable)
return 0;
for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++)
ath12k_dp_rxdma_mon_buf_ring_free(ab,
&dp->rx_mon_status_refill_ring[i]);
return 0;
}
@ -430,7 +454,12 @@ static int ath12k_dp_rxdma_mon_ring_buf_setup(struct ath12k_base *ab,
ath12k_hal_srng_get_entrysize(ab, ringtype);
rx_ring->bufs_max = num_entries;
ath12k_dp_mon_buf_replenish(ab, rx_ring, num_entries);
if (ringtype == HAL_RXDMA_MONITOR_STATUS)
ath12k_dp_mon_status_bufs_replenish(ab, rx_ring,
num_entries);
else
ath12k_dp_mon_buf_replenish(ab, rx_ring, num_entries);
return 0;
}
@ -451,7 +480,8 @@ static int ath12k_dp_rxdma_ring_buf_setup(struct ath12k_base *ab,
static int ath12k_dp_rxdma_buf_setup(struct ath12k_base *ab)
{
struct ath12k_dp *dp = &ab->dp;
int ret;
struct dp_rxdma_mon_ring *mon_ring;
int ret, i;
ret = ath12k_dp_rxdma_ring_buf_setup(ab, &dp->rx_refill_buf_ring);
if (ret) {
@ -464,9 +494,19 @@ static int ath12k_dp_rxdma_buf_setup(struct ath12k_base *ab)
ret = ath12k_dp_rxdma_mon_ring_buf_setup(ab,
&dp->rxdma_mon_buf_ring,
HAL_RXDMA_MONITOR_BUF);
if (ret) {
if (ret)
ath12k_warn(ab,
"failed to setup HAL_RXDMA_MONITOR_BUF\n");
return ret;
}
for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
mon_ring = &dp->rx_mon_status_refill_ring[i];
ret = ath12k_dp_rxdma_mon_ring_buf_setup(ab, mon_ring,
HAL_RXDMA_MONITOR_STATUS);
if (ret) {
ath12k_warn(ab,
"failed to setup HAL_RXDMA_MONITOR_STATUS\n");
return ret;
}
}
@ -819,15 +859,10 @@ void ath12k_dp_rx_peer_tid_delete(struct ath12k *ar,
rx_tid->active = false;
}
/* TODO: it's strange (and ugly) that struct hal_reo_dest_ring is converted
* to struct hal_wbm_release_ring, I couldn't figure out the logic behind
* that.
*/
static int ath12k_dp_rx_link_desc_return(struct ath12k_base *ab,
struct hal_reo_dest_ring *ring,
enum hal_wbm_rel_bm_act action)
int ath12k_dp_rx_link_desc_return(struct ath12k_base *ab,
struct ath12k_buffer_addr *buf_addr_info,
enum hal_wbm_rel_bm_act action)
{
struct hal_wbm_release_ring *link_desc = (struct hal_wbm_release_ring *)ring;
struct hal_wbm_release_ring *desc;
struct ath12k_dp *dp = &ab->dp;
struct hal_srng *srng;
@ -845,7 +880,7 @@ static int ath12k_dp_rx_link_desc_return(struct ath12k_base *ab,
goto exit;
}
ath12k_hal_rx_msdu_link_desc_set(ab, desc, link_desc, action);
ath12k_hal_rx_msdu_link_desc_set(ab, desc, buf_addr_info, action);
exit:
ath12k_hal_srng_access_end(ab, srng);
@ -858,14 +893,17 @@ static int ath12k_dp_rx_link_desc_return(struct ath12k_base *ab,
static void ath12k_dp_rx_frags_cleanup(struct ath12k_dp_rx_tid *rx_tid,
bool rel_link_desc)
{
struct ath12k_buffer_addr *buf_addr_info;
struct ath12k_base *ab = rx_tid->ab;
lockdep_assert_held(&ab->base_lock);
if (rx_tid->dst_ring_desc) {
if (rel_link_desc)
ath12k_dp_rx_link_desc_return(ab, rx_tid->dst_ring_desc,
if (rel_link_desc) {
buf_addr_info = &rx_tid->dst_ring_desc->buf_addr_info;
ath12k_dp_rx_link_desc_return(ab, buf_addr_info,
HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
}
kfree(rx_tid->dst_ring_desc);
rx_tid->dst_ring_desc = NULL;
}
@ -1802,8 +1840,12 @@ void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,
HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16);
ath12k_dp_get_mac_addr(le32_to_cpu(resp->peer_map_ev.mac_addr_l32),
peer_mac_h16, mac_addr);
ast_hash = le32_get_bits(resp->peer_map_ev.info2,
HTT_T2H_PEER_MAP3_INFO2_AST_HASH_VAL);
hw_peer_id = le32_get_bits(resp->peer_map_ev.info2,
HTT_T2H_PEER_MAP3_INFO2_HW_PEER_ID);
ath12k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash,
peer_id);
hw_peer_id);
break;
case HTT_T2H_MSG_TYPE_PEER_UNMAP:
case HTT_T2H_MSG_TYPE_PEER_UNMAP2:
@ -2592,7 +2634,7 @@ static bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_base *ab,
if ((likely(hdr_len <= DP_MAX_NWIFI_HDR_LEN)))
return true;
ab->soc_stats.invalid_rbm++;
ab->device_stats.invalid_rbm++;
WARN_ON_ONCE(1);
return false;
}
@ -2755,9 +2797,9 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
struct napi_struct *napi, int budget)
{
struct ath12k_hw_group *ag = ab->ag;
struct list_head rx_desc_used_list[ATH12K_MAX_SOCS];
struct list_head rx_desc_used_list[ATH12K_MAX_DEVICES];
struct ath12k_hw_link *hw_links = ag->hw_links;
int num_buffs_reaped[ATH12K_MAX_SOCS] = {};
int num_buffs_reaped[ATH12K_MAX_DEVICES] = {};
struct ath12k_rx_desc_info *desc_info;
struct ath12k_dp *dp = &ab->dp;
struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
@ -2774,7 +2816,7 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
__skb_queue_head_init(&msdu_list);
for (device_id = 0; device_id < ATH12K_MAX_SOCS; device_id++)
for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++)
INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
srng = &ab->hal.srng_list[dp->reo_dst_ring[ring_id].ring_id];
@ -2835,13 +2877,14 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
DMA_FROM_DEVICE);
num_buffs_reaped[device_id]++;
ab->device_stats.reo_rx[ring_id][ab->device_id]++;
push_reason = le32_get_bits(desc->info0,
HAL_REO_DEST_RING_INFO0_PUSH_REASON);
if (push_reason !=
HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION) {
dev_kfree_skb_any(msdu);
ab->soc_stats.hal_reo_error[ring_id]++;
ab->device_stats.hal_reo_error[ring_id]++;
continue;
}
@ -2891,7 +2934,7 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
if (!total_msdu_reaped)
goto exit;
for (device_id = 0; device_id < ATH12K_MAX_SOCS; device_id++) {
for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++) {
if (!num_buffs_reaped[device_id])
continue;
@ -3483,7 +3526,7 @@ static int ath12k_dp_rx_frag_h_mpdu(struct ath12k *ar,
goto out_unlock;
}
} else {
ath12k_dp_rx_link_desc_return(ab, ring_desc,
ath12k_dp_rx_link_desc_return(ab, &ring_desc->buf_addr_info,
HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
}
@ -3596,7 +3639,7 @@ ath12k_dp_process_rx_err_buf(struct ath12k *ar, struct hal_reo_dest_ring *desc,
if (ath12k_dp_rx_frag_h_mpdu(ar, msdu, desc)) {
dev_kfree_skb_any(msdu);
ath12k_dp_rx_link_desc_return(ar->ab, desc,
ath12k_dp_rx_link_desc_return(ar->ab, &desc->buf_addr_info,
HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
}
exit:
@ -3608,9 +3651,9 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
int budget)
{
struct ath12k_hw_group *ag = ab->ag;
struct list_head rx_desc_used_list[ATH12K_MAX_SOCS];
struct list_head rx_desc_used_list[ATH12K_MAX_DEVICES];
u32 msdu_cookies[HAL_NUM_RX_MSDUS_PER_LINK_DESC];
int num_buffs_reaped[ATH12K_MAX_SOCS] = {};
int num_buffs_reaped[ATH12K_MAX_DEVICES] = {};
struct dp_link_desc_bank *link_desc_banks;
enum hal_rx_buf_return_buf_manager rbm;
struct hal_rx_msdu_link *link_desc_va;
@ -3632,7 +3675,7 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
tot_n_bufs_reaped = 0;
quota = budget;
for (device_id = 0; device_id < ATH12K_MAX_SOCS; device_id++)
for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++)
INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
reo_except = &ab->dp.reo_except_ring;
@ -3646,7 +3689,7 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
while (budget &&
(reo_desc = ath12k_hal_srng_dst_get_next_entry(ab, srng))) {
drop = false;
ab->soc_stats.err_ring_pkts++;
ab->device_stats.err_ring_pkts++;
ret = ath12k_hal_desc_reo_parse_err(ab, reo_desc, &paddr,
&desc_bank);
@ -3673,9 +3716,10 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
if (rbm != partner_ab->dp.idle_link_rbm &&
rbm != HAL_RX_BUF_RBM_SW3_BM &&
rbm != partner_ab->hw_params->hal_params->rx_buf_rbm) {
ab->soc_stats.invalid_rbm++;
ab->device_stats.invalid_rbm++;
ath12k_warn(ab, "invalid return buffer manager %d\n", rbm);
ath12k_dp_rx_link_desc_return(partner_ab, reo_desc,
ath12k_dp_rx_link_desc_return(partner_ab,
&reo_desc->buf_addr_info,
HAL_WBM_REL_BM_ACT_REL_MSDU);
continue;
}
@ -3693,7 +3737,8 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
drop = true;
/* Return the link desc back to wbm idle list */
ath12k_dp_rx_link_desc_return(partner_ab, reo_desc,
ath12k_dp_rx_link_desc_return(partner_ab,
&reo_desc->buf_addr_info,
HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
}
@ -3720,7 +3765,7 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
spin_unlock_bh(&srng->lock);
for (device_id = 0; device_id < ATH12K_MAX_SOCS; device_id++) {
for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++) {
if (!num_buffs_reaped[device_id])
continue;
@ -3836,7 +3881,7 @@ static bool ath12k_dp_rx_h_reo_err(struct ath12k *ar, struct sk_buff *msdu,
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
bool drop = false;
ar->ab->soc_stats.reo_error[rxcb->err_code]++;
ar->ab->device_stats.reo_error[rxcb->err_code]++;
switch (rxcb->err_code) {
case HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO:
@ -3909,7 +3954,7 @@ static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu,
bool drop = false;
u32 err_bitmap;
ar->ab->soc_stats.rxdma_error[rxcb->err_code]++;
ar->ab->device_stats.rxdma_error[rxcb->err_code]++;
switch (rxcb->err_code) {
case HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR:
@ -3968,7 +4013,7 @@ static void ath12k_dp_rx_wbm_err(struct ath12k *ar,
int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
struct napi_struct *napi, int budget)
{
struct list_head rx_desc_used_list[ATH12K_MAX_SOCS];
struct list_head rx_desc_used_list[ATH12K_MAX_DEVICES];
struct ath12k_hw_group *ag = ab->ag;
struct ath12k *ar;
struct ath12k_dp *dp = &ab->dp;
@ -3979,9 +4024,10 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
struct sk_buff_head msdu_list, scatter_msdu_list;
struct ath12k_skb_rxcb *rxcb;
void *rx_desc;
int num_buffs_reaped[ATH12K_MAX_SOCS] = {};
int num_buffs_reaped[ATH12K_MAX_DEVICES] = {};
int total_num_buffs_reaped = 0;
struct ath12k_rx_desc_info *desc_info;
struct ath12k_device_dp_stats *device_stats = &ab->device_stats;
struct ath12k_hw_link *hw_links = ag->hw_links;
struct ath12k_base *partner_ab;
u8 hw_link_id, device_id;
@ -3991,7 +4037,7 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
__skb_queue_head_init(&msdu_list);
__skb_queue_head_init(&scatter_msdu_list);
for (device_id = 0; device_id < ATH12K_MAX_SOCS; device_id++)
for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++)
INIT_LIST_HEAD(&rx_desc_used_list[device_id]);
srng = &ab->hal.srng_list[dp->rx_rel_ring.ring_id];
@ -4115,7 +4161,7 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
if (!total_num_buffs_reaped)
goto done;
for (device_id = 0; device_id < ATH12K_MAX_SOCS; device_id++) {
for (device_id = 0; device_id < ATH12K_MAX_DEVICES; device_id++) {
if (!num_buffs_reaped[device_id])
continue;
@ -4155,6 +4201,12 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
dev_kfree_skb_any(msdu);
continue;
}
if (rxcb->err_rel_src < HAL_WBM_REL_SRC_MODULE_MAX) {
device_id = ar->ab->device_id;
device_stats->rx_wbm_rel_source[rxcb->err_rel_src][device_id]++;
}
ath12k_dp_rx_wbm_err(ar, napi, msdu, &msdu_list);
}
rcu_read_unlock();
@ -4244,6 +4296,7 @@ void ath12k_dp_rx_process_reo_status(struct ath12k_base *ab)
void ath12k_dp_rx_free(struct ath12k_base *ab)
{
struct ath12k_dp *dp = &ab->dp;
struct dp_srng *srng;
int i;
ath12k_dp_srng_cleanup(ab, &dp->rx_refill_buf_ring.refill_buf_ring);
@ -4251,6 +4304,10 @@ void ath12k_dp_rx_free(struct ath12k_base *ab)
for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
if (ab->hw_params->rx_mac_buf_ring)
ath12k_dp_srng_cleanup(ab, &dp->rx_mac_buf_ring[i]);
if (!ab->hw_params->rxdma1_enable) {
srng = &dp->rx_mon_status_refill_ring[i].refill_buf_ring;
ath12k_dp_srng_cleanup(ab, srng);
}
}
for (i = 0; i < ab->hw_params->num_rxdma_dst_ring; i++)
@ -4399,6 +4456,19 @@ int ath12k_dp_rx_htt_setup(struct ath12k_base *ab)
ret);
return ret;
}
} else {
for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
ring_id =
dp->rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
ret = ath12k_dp_tx_htt_srng_setup(ab, ring_id, i,
HAL_RXDMA_MONITOR_STATUS);
if (ret) {
ath12k_warn(ab,
"failed to configure mon_status_refill_ring%d %d\n",
i, ret);
return ret;
}
}
}
ret = ab->hw_params->hw_ops->rxdma_ring_sel_config(ab);
@ -4413,6 +4483,7 @@ int ath12k_dp_rx_htt_setup(struct ath12k_base *ab)
int ath12k_dp_rx_alloc(struct ath12k_base *ab)
{
struct ath12k_dp *dp = &ab->dp;
struct dp_srng *srng;
int i, ret;
idr_init(&dp->rxdma_mon_buf_ring.bufs_idr);
@ -4460,6 +4531,23 @@ int ath12k_dp_rx_alloc(struct ath12k_base *ab)
ath12k_warn(ab, "failed to setup HAL_RXDMA_MONITOR_BUF\n");
return ret;
}
} else {
for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
idr_init(&dp->rx_mon_status_refill_ring[i].bufs_idr);
spin_lock_init(&dp->rx_mon_status_refill_ring[i].idr_lock);
}
for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
srng = &dp->rx_mon_status_refill_ring[i].refill_buf_ring;
ret = ath12k_dp_srng_setup(ab, srng,
HAL_RXDMA_MONITOR_STATUS, 0, i,
DP_RXDMA_MON_STATUS_RING_SIZE);
if (ret) {
ath12k_warn(ab, "failed to setup mon status ring %d\n",
i);
return ret;
}
}
}
ret = ath12k_dp_rxdma_buf_setup(ab);
@ -4530,17 +4618,15 @@ int ath12k_dp_rx_pdev_mon_attach(struct ath12k *ar)
return ret;
}
/* if rxdma1_enable is false, no need to setup
* rxdma_mon_desc_ring.
*/
pmon->mon_last_linkdesc_paddr = 0;
pmon->mon_last_buf_cookie = DP_RX_DESC_COOKIE_MAX + 1;
spin_lock_init(&pmon->mon_lock);
if (!ar->ab->hw_params->rxdma1_enable)
return 0;
pmon->mon_last_linkdesc_paddr = 0;
pmon->mon_last_buf_cookie = DP_RX_DESC_COOKIE_MAX + 1;
INIT_LIST_HEAD(&pmon->dp_rx_mon_mpdu_list);
pmon->mon_mpdu = NULL;
spin_lock_init(&pmon->mon_lock);
return 0;
}

@ -165,5 +165,13 @@ void ath12k_dp_rx_h_fetch_info(struct ath12k_base *ab, struct hal_rx_desc *rx_d
struct ath12k_dp_rx_info *rx_info);
int ath12k_dp_rx_crypto_mic_len(struct ath12k *ar, enum hal_encrypt_type enctype);
u32 ath12k_dp_rxdesc_get_ppduid(struct ath12k_base *ab,
struct hal_rx_desc *rx_desc);
bool ath12k_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
struct hal_rx_desc *rx_desc);
int ath12k_dp_rx_link_desc_return(struct ath12k_base *ab,
struct ath12k_buffer_addr *buf_addr_info,
enum hal_wbm_rel_bm_act action);
bool ath12k_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
struct hal_rx_desc *rx_desc);
#endif /* ATH12K_DP_RX_H */

@ -350,7 +350,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
default:
/* TODO: Take care of other encap modes as well */
ret = -EINVAL;
atomic_inc(&ab->soc_stats.tx_err.misc_fail);
atomic_inc(&ab->device_stats.tx_err.misc_fail);
goto fail_remove_tx_buf;
}
@ -373,7 +373,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
map:
ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
if (dma_mapping_error(ab->dev, ti.paddr)) {
atomic_inc(&ab->soc_stats.tx_err.misc_fail);
atomic_inc(&ab->device_stats.tx_err.misc_fail);
ath12k_warn(ab, "failed to DMA map data Tx buffer\n");
ret = -ENOMEM;
goto fail_remove_tx_buf;
@ -448,7 +448,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
* desc because the desc is directly enqueued onto hw queue.
*/
ath12k_hal_srng_access_end(ab, tcl_ring);
ab->soc_stats.tx_err.desc_na[ti.ring_id]++;
ab->device_stats.tx_err.desc_na[ti.ring_id]++;
spin_unlock_bh(&tcl_ring->lock);
ret = -ENOMEM;
@ -477,6 +477,8 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
arvif->link_stats.tx_enqueued++;
spin_unlock_bh(&arvif->link_stats_lock);
ab->device_stats.tx_enqueued[ti.ring_id]++;
ath12k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc, &ti);
ath12k_hal_srng_access_end(ab, tcl_ring);
@ -557,6 +559,7 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab,
info = IEEE80211_SKB_CB(msdu);
ar = skb_cb->ar;
ab->device_stats.tx_completed[tx_ring->tcl_data_ring_id]++;
if (atomic_dec_and_test(&ar->dp.num_tx_pending))
wake_up(&ar->dp.tx_empty_waitq);
@ -614,6 +617,7 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab, void *desc,
wbm_status = le32_get_bits(status_desc->info0,
HTT_TX_WBM_COMP_INFO0_STATUS);
ab->device_stats.fw_tx_status[wbm_status]++;
switch (wbm_status) {
case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK:
@ -760,7 +764,8 @@ static void ath12k_dp_tx_update_txcompl(struct ath12k *ar, struct hal_tx_status
static void ath12k_dp_tx_complete_msdu(struct ath12k *ar,
struct ath12k_tx_desc_params *desc_params,
struct hal_tx_status *ts)
struct hal_tx_status *ts,
int ring)
{
struct ath12k_base *ab = ar->ab;
struct ath12k_hw *ah = ar->ah;
@ -777,6 +782,7 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar,
}
skb_cb = ATH12K_SKB_CB(msdu);
ab->device_stats.tx_completed[ring]++;
dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
if (skb_cb->paddr_ext_desc) {
@ -907,6 +913,8 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id)
struct hal_wbm_release_ring *desc;
u8 pdev_id;
u64 desc_va;
enum hal_wbm_rel_src_module buf_rel_source;
enum hal_wbm_tqm_rel_reason rel_status;
spin_lock_bh(&status_ring->lock);
@ -963,6 +971,15 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id)
desc_params.skb = tx_desc->skb;
desc_params.skb_ext_desc = tx_desc->skb_ext_desc;
/* Find the HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE value */
buf_rel_source = le32_get_bits(tx_status->info0,
HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE);
ab->device_stats.tx_wbm_rel_source[buf_rel_source]++;
rel_status = le32_get_bits(tx_status->info0,
HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON);
ab->device_stats.tqm_rel_reason[rel_status]++;
/* Release descriptor as soon as extracting necessary info
* to reduce contention
*/
@ -979,7 +996,8 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id)
if (atomic_dec_and_test(&ar->dp.num_tx_pending))
wake_up(&ar->dp.tx_empty_waitq);
ath12k_dp_tx_complete_msdu(ar, &desc_params, &ts);
ath12k_dp_tx_complete_msdu(ar, &desc_params, &ts,
tx_ring->tcl_data_ring_id);
}
}
@ -1511,6 +1529,44 @@ int ath12k_dp_tx_htt_rx_monitor_mode_ring_config(struct ath12k *ar, bool reset)
return ret;
}
}
return 0;
}
if (!reset) {
for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
ring_id = ab->dp.rx_mac_buf_ring[i].ring_id;
ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id,
i,
HAL_RXDMA_BUF,
DP_RXDMA_REFILL_RING_SIZE,
&tlv_filter);
if (ret) {
ath12k_err(ab,
"failed to setup filter for mon rx buf %d\n",
ret);
return ret;
}
}
}
for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
ring_id = ab->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
if (!reset) {
tlv_filter.rx_filter =
HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING;
}
ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id,
i,
HAL_RXDMA_MONITOR_STATUS,
RX_MON_STATUS_BUF_SIZE,
&tlv_filter);
if (ret) {
ath12k_err(ab,
"failed to setup filter for mon status buf %d\n",
ret);
return ret;
}
}
return 0;

@ -154,7 +154,14 @@ static const struct hal_srng_config hw_srng_config_template[] = {
.ring_dir = HAL_SRNG_DIR_SRC,
.max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
},
[HAL_RXDMA_MONITOR_STATUS] = { 0, },
[HAL_RXDMA_MONITOR_STATUS] = {
.start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_STATBUF,
.max_rings = 1,
.entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
.mac_type = ATH12K_HAL_SRNG_PMAC,
.ring_dir = HAL_SRNG_DIR_SRC,
.max_size = HAL_RXDMA_RING_MAX_SIZE_BE,
},
[HAL_RXDMA_MONITOR_DESC] = { 0, },
[HAL_RXDMA_DIR_BUF] = {
.start_ring_id = HAL_SRNG_RING_ID_RXDMA_DIR_BUF,
@ -1943,7 +1950,7 @@ u32 ath12k_hal_ce_dst_status_get_length(struct hal_ce_srng_dst_status_desc *desc
{
u32 len;
len = le32_get_bits(desc->flags, HAL_CE_DST_STATUS_DESC_FLAGS_LEN);
len = le32_get_bits(READ_ONCE(desc->flags), HAL_CE_DST_STATUS_DESC_FLAGS_LEN);
desc->flags &= ~cpu_to_le32(HAL_CE_DST_STATUS_DESC_FLAGS_LEN);
return len;
@ -2035,6 +2042,24 @@ int ath12k_hal_srng_src_num_free(struct ath12k_base *ab, struct hal_srng *srng,
return ((srng->ring_size - hp + tp) / srng->entry_size) - 1;
}
void *ath12k_hal_srng_src_next_peek(struct ath12k_base *ab,
struct hal_srng *srng)
{
void *desc;
u32 next_hp;
lockdep_assert_held(&srng->lock);
next_hp = (srng->u.src_ring.hp + srng->entry_size) % srng->ring_size;
if (next_hp == srng->u.src_ring.cached_tp)
return NULL;
desc = srng->ring_base_vaddr + next_hp;
return desc;
}
void *ath12k_hal_srng_src_get_next_entry(struct ath12k_base *ab,
struct hal_srng *srng)
{
@ -2068,6 +2093,17 @@ void *ath12k_hal_srng_src_get_next_entry(struct ath12k_base *ab,
return desc;
}
void *ath12k_hal_srng_src_peek(struct ath12k_base *ab, struct hal_srng *srng)
{
lockdep_assert_held(&srng->lock);
if (((srng->u.src_ring.hp + srng->entry_size) % srng->ring_size) ==
srng->u.src_ring.cached_tp)
return NULL;
return srng->ring_base_vaddr + srng->u.src_ring.hp;
}
void *ath12k_hal_srng_src_reap_next(struct ath12k_base *ab,
struct hal_srng *srng)
{
@ -2113,7 +2149,7 @@ void ath12k_hal_srng_access_begin(struct ath12k_base *ab, struct hal_srng *srng)
srng->u.src_ring.cached_tp =
*(volatile u32 *)srng->u.src_ring.tp_addr;
else
srng->u.dst_ring.cached_hp = *srng->u.dst_ring.hp_addr;
srng->u.dst_ring.cached_hp = READ_ONCE(*srng->u.dst_ring.hp_addr);
}
/* Update cached ring head/tail pointers to HW. ath12k_hal_srng_access_begin()

@ -498,6 +498,7 @@ enum hal_srng_ring_id {
HAL_SRNG_RING_ID_WMAC1_SW2RXMON_BUF0 = HAL_SRNG_RING_ID_PMAC1_ID_START,
HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_STATBUF,
HAL_SRNG_RING_ID_WMAC1_RXDMA2SW0,
HAL_SRNG_RING_ID_WMAC1_RXDMA2SW1,
HAL_SRNG_RING_ID_WMAC1_RXMON2SW0 = HAL_SRNG_RING_ID_WMAC1_RXDMA2SW1,
@ -1143,6 +1144,7 @@ void ath12k_hal_srng_get_params(struct ath12k_base *ab, struct hal_srng *srng,
struct hal_srng_params *params);
void *ath12k_hal_srng_dst_get_next_entry(struct ath12k_base *ab,
struct hal_srng *srng);
void *ath12k_hal_srng_src_peek(struct ath12k_base *ab, struct hal_srng *srng);
void *ath12k_hal_srng_dst_peek(struct ath12k_base *ab, struct hal_srng *srng);
int ath12k_hal_srng_dst_num_free(struct ath12k_base *ab, struct hal_srng *srng,
bool sync_hw_ptr);
@ -1150,6 +1152,8 @@ void *ath12k_hal_srng_src_get_next_reaped(struct ath12k_base *ab,
struct hal_srng *srng);
void *ath12k_hal_srng_src_reap_next(struct ath12k_base *ab,
struct hal_srng *srng);
void *ath12k_hal_srng_src_next_peek(struct ath12k_base *ab,
struct hal_srng *srng);
void *ath12k_hal_srng_src_get_next_entry(struct ath12k_base *ab,
struct hal_srng *srng);
int ath12k_hal_srng_src_num_free(struct ath12k_base *ab, struct hal_srng *srng,

@ -707,7 +707,7 @@ enum hal_rx_msdu_desc_reo_dest_ind {
#define RX_MSDU_DESC_INFO0_DECAP_FORMAT GENMASK(30, 29)
#define HAL_RX_MSDU_PKT_LENGTH_GET(val) \
(u32_get_bits((val), RX_MSDU_DESC_INFO0_MSDU_LENGTH))
(le32_get_bits((val), RX_MSDU_DESC_INFO0_MSDU_LENGTH))
struct rx_msdu_desc {
__le32 info0;
@ -1008,6 +1008,10 @@ enum hal_reo_entr_rxdma_ecode {
HAL_REO_ENTR_RING_RXDMA_ECODE_FLOW_TIMEOUT_ERR,
HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR,
HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_FRAG_ERR,
HAL_REO_ENTR_RING_RXDMA_ECODE_MULTICAST_ECHO_ERR,
HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_MISMATCH_ERR,
HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR,
HAL_REO_ENTR_RING_RXDMA_ECODE_GRPCAST_AMSDU_WDS_ERR,
HAL_REO_ENTR_RING_RXDMA_ECODE_MAX,
};
@ -1809,6 +1813,7 @@ enum hal_wbm_rel_src_module {
HAL_WBM_REL_SRC_MODULE_REO,
HAL_WBM_REL_SRC_MODULE_FW,
HAL_WBM_REL_SRC_MODULE_SW,
HAL_WBM_REL_SRC_MODULE_MAX,
};
enum hal_wbm_rel_desc_type {

@ -326,7 +326,7 @@ int ath12k_hal_desc_reo_parse_err(struct ath12k_base *ab,
HAL_REO_DEST_RING_INFO0_PUSH_REASON);
err_code = le32_get_bits(desc->info0,
HAL_REO_DEST_RING_INFO0_ERROR_CODE);
ab->soc_stats.reo_error[err_code]++;
ab->device_stats.reo_error[err_code]++;
if (push_reason != HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED &&
push_reason != HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION) {
@ -381,7 +381,7 @@ int ath12k_hal_wbm_desc_parse_err(struct ath12k_base *ab, void *desc,
val = le32_get_bits(wbm_desc->buf_addr_info.info1,
BUFFER_ADDR_INFO1_RET_BUF_MGR);
if (val != HAL_RX_BUF_RBM_SW3_BM) {
ab->soc_stats.invalid_rbm++;
ab->device_stats.invalid_rbm++;
return -EINVAL;
}
@ -393,7 +393,7 @@ int ath12k_hal_wbm_desc_parse_err(struct ath12k_base *ab, void *desc,
val = le32_get_bits(wbm_cc_desc->info0,
HAL_WBM_RELEASE_RX_CC_INFO0_RBM);
if (val != HAL_RX_BUF_RBM_SW3_BM) {
ab->soc_stats.invalid_rbm++;
ab->device_stats.invalid_rbm++;
return -EINVAL;
}
@ -446,17 +446,97 @@ void ath12k_hal_rx_reo_ent_paddr_get(struct ath12k_base *ab,
*cookie = le32_get_bits(buff_addr->info1, BUFFER_ADDR_INFO1_SW_COOKIE);
}
void ath12k_hal_rx_reo_ent_buf_paddr_get(void *rx_desc, dma_addr_t *paddr,
u32 *sw_cookie,
struct ath12k_buffer_addr **pp_buf_addr,
u8 *rbm, u32 *msdu_cnt)
{
struct hal_reo_entrance_ring *reo_ent_ring =
(struct hal_reo_entrance_ring *)rx_desc;
struct ath12k_buffer_addr *buf_addr_info;
struct rx_mpdu_desc *rx_mpdu_desc_info_details;
rx_mpdu_desc_info_details =
(struct rx_mpdu_desc *)&reo_ent_ring->rx_mpdu_info;
*msdu_cnt = le32_get_bits(rx_mpdu_desc_info_details->info0,
RX_MPDU_DESC_INFO0_MSDU_COUNT);
buf_addr_info = (struct ath12k_buffer_addr *)&reo_ent_ring->buf_addr_info;
*paddr = (((u64)le32_get_bits(buf_addr_info->info1,
BUFFER_ADDR_INFO1_ADDR)) << 32) |
le32_get_bits(buf_addr_info->info0,
BUFFER_ADDR_INFO0_ADDR);
*sw_cookie = le32_get_bits(buf_addr_info->info1,
BUFFER_ADDR_INFO1_SW_COOKIE);
*rbm = le32_get_bits(buf_addr_info->info1,
BUFFER_ADDR_INFO1_RET_BUF_MGR);
*pp_buf_addr = (void *)buf_addr_info;
}
void ath12k_hal_rx_msdu_list_get(struct ath12k *ar,
struct hal_rx_msdu_link *link_desc,
struct hal_rx_msdu_list *msdu_list,
u16 *num_msdus)
{
struct hal_rx_msdu_details *msdu_details = NULL;
struct rx_msdu_desc *msdu_desc_info = NULL;
u32 last = 0, first = 0;
u8 tmp = 0;
int i;
last = u32_encode_bits(last, RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU);
first = u32_encode_bits(first, RX_MSDU_DESC_INFO0_FIRST_MSDU_IN_MPDU);
msdu_details = &link_desc->msdu_link[0];
for (i = 0; i < HAL_RX_NUM_MSDU_DESC; i++) {
if (!i && le32_get_bits(msdu_details[i].buf_addr_info.info0,
BUFFER_ADDR_INFO0_ADDR) == 0)
break;
if (le32_get_bits(msdu_details[i].buf_addr_info.info0,
BUFFER_ADDR_INFO0_ADDR) == 0) {
msdu_desc_info = &msdu_details[i - 1].rx_msdu_info;
msdu_desc_info->info0 |= cpu_to_le32(last);
break;
}
msdu_desc_info = &msdu_details[i].rx_msdu_info;
if (!i)
msdu_desc_info->info0 |= cpu_to_le32(first);
else if (i == (HAL_RX_NUM_MSDU_DESC - 1))
msdu_desc_info->info0 |= cpu_to_le32(last);
msdu_list->msdu_info[i].msdu_flags = le32_to_cpu(msdu_desc_info->info0);
msdu_list->msdu_info[i].msdu_len =
HAL_RX_MSDU_PKT_LENGTH_GET(msdu_desc_info->info0);
msdu_list->sw_cookie[i] =
le32_get_bits(msdu_details[i].buf_addr_info.info1,
BUFFER_ADDR_INFO1_SW_COOKIE);
tmp = le32_get_bits(msdu_details[i].buf_addr_info.info1,
BUFFER_ADDR_INFO1_RET_BUF_MGR);
msdu_list->paddr[i] =
((u64)(le32_get_bits(msdu_details[i].buf_addr_info.info1,
BUFFER_ADDR_INFO1_ADDR)) << 32) |
le32_get_bits(msdu_details[i].buf_addr_info.info0,
BUFFER_ADDR_INFO0_ADDR);
msdu_list->rbm[i] = tmp;
}
*num_msdus = i;
}
void ath12k_hal_rx_msdu_link_desc_set(struct ath12k_base *ab,
struct hal_wbm_release_ring *dst_desc,
struct hal_wbm_release_ring *src_desc,
struct hal_wbm_release_ring *desc,
struct ath12k_buffer_addr *buf_addr_info,
enum hal_wbm_rel_bm_act action)
{
dst_desc->buf_addr_info = src_desc->buf_addr_info;
dst_desc->info0 |= le32_encode_bits(HAL_WBM_REL_SRC_MODULE_SW,
HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE) |
le32_encode_bits(action, HAL_WBM_RELEASE_INFO0_BM_ACTION) |
le32_encode_bits(HAL_WBM_REL_DESC_TYPE_MSDU_LINK,
HAL_WBM_RELEASE_INFO0_DESC_TYPE);
desc->buf_addr_info = *buf_addr_info;
desc->info0 |= le32_encode_bits(HAL_WBM_REL_SRC_MODULE_SW,
HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE) |
le32_encode_bits(action, HAL_WBM_RELEASE_INFO0_BM_ACTION) |
le32_encode_bits(HAL_WBM_REL_DESC_TYPE_MSDU_LINK,
HAL_WBM_RELEASE_INFO0_DESC_TYPE);
}
void ath12k_hal_reo_status_queue_stats(struct ath12k_base *ab, struct hal_tlv_64_hdr *tlv,

@ -538,6 +538,7 @@ struct hal_rx_msdu_desc_info {
#define HAL_RX_NUM_MSDU_DESC 6
struct hal_rx_msdu_list {
struct hal_rx_msdu_desc_info msdu_info[HAL_RX_NUM_MSDU_DESC];
u64 paddr[HAL_RX_NUM_MSDU_DESC];
u32 sw_cookie[HAL_RX_NUM_MSDU_DESC];
u8 rbm[HAL_RX_NUM_MSDU_DESC];
};
@ -1141,8 +1142,8 @@ void ath12k_hal_rx_msdu_link_info_get(struct hal_rx_msdu_link *link, u32 *num_ms
u32 *msdu_cookies,
enum hal_rx_buf_return_buf_manager *rbm);
void ath12k_hal_rx_msdu_link_desc_set(struct ath12k_base *ab,
struct hal_wbm_release_ring *dst_desc,
struct hal_wbm_release_ring *src_desc,
struct hal_wbm_release_ring *desc,
struct ath12k_buffer_addr *buf_addr_info,
enum hal_wbm_rel_bm_act action);
void ath12k_hal_rx_buf_addr_info_set(struct ath12k_buffer_addr *binfo,
dma_addr_t paddr, u32 cookie, u8 manager);
@ -1157,5 +1158,12 @@ int ath12k_hal_wbm_desc_parse_err(struct ath12k_base *ab, void *desc,
void ath12k_hal_rx_reo_ent_paddr_get(struct ath12k_base *ab,
struct ath12k_buffer_addr *buff_addr,
dma_addr_t *paddr, u32 *cookie);
void ath12k_hal_rx_reo_ent_buf_paddr_get(void *rx_desc, dma_addr_t *paddr, u32 *sw_cookie,
struct ath12k_buffer_addr **pp_buf_addr,
u8 *rbm, u32 *msdu_cnt);
void ath12k_hal_rx_msdu_list_get(struct ath12k *ar,
struct hal_rx_msdu_link *link_desc,
struct hal_rx_msdu_list *msdu_list,
u16 *num_msdus);
#endif

@ -118,6 +118,10 @@ static const struct ath12k_hw_ops wcn7850_ops = {
#define ATH12K_TX_MON_RING_MASK_0 0x1
#define ATH12K_TX_MON_RING_MASK_1 0x2
#define ATH12K_RX_MON_STATUS_RING_MASK_0 0x1
#define ATH12K_RX_MON_STATUS_RING_MASK_1 0x2
#define ATH12K_RX_MON_STATUS_RING_MASK_2 0x4
/* Target firmware's Copy Engine configuration. */
static const struct ce_pipe_config ath12k_target_ce_config_wlan_qcn9274[] = {
/* CE0: host->target HTC control and raw streams */
@ -836,6 +840,12 @@ static const struct ath12k_hw_ring_mask ath12k_hw_ring_mask_wcn7850 = {
},
.rx_mon_dest = {
},
.rx_mon_status = {
0, 0, 0, 0,
ATH12K_RX_MON_STATUS_RING_MASK_0,
ATH12K_RX_MON_STATUS_RING_MASK_1,
ATH12K_RX_MON_STATUS_RING_MASK_2,
},
.rx = {
0, 0, 0,
ATH12K_RX_RING_MASK_0,
@ -1370,7 +1380,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO),
.supports_monitor = false,
.supports_monitor = true,
.idle_ps = true,
.download_calib = false,

@ -135,6 +135,7 @@ enum hal_encrypt_type;
struct ath12k_hw_ring_mask {
u8 tx[ATH12K_EXT_IRQ_GRP_NUM_MAX];
u8 rx_mon_dest[ATH12K_EXT_IRQ_GRP_NUM_MAX];
u8 rx_mon_status[ATH12K_EXT_IRQ_GRP_NUM_MAX];
u8 rx[ATH12K_EXT_IRQ_GRP_NUM_MAX];
u8 rx_err[ATH12K_EXT_IRQ_GRP_NUM_MAX];
u8 rx_wbm_rel[ATH12K_EXT_IRQ_GRP_NUM_MAX];

@ -229,7 +229,8 @@ ath12k_phymodes[NUM_NL80211_BANDS][ATH12K_CHAN_WIDTH_NUM] = {
const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default = {
.rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START |
HTT_RX_FILTER_TLV_FLAGS_PPDU_END |
HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE,
HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE |
HTT_RX_FILTER_TLV_FLAGS_PPDU_START_USER_INFO,
.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0,
.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1,
.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2,
@ -580,22 +581,16 @@ static int ath12k_mac_vif_link_chan(struct ieee80211_vif *vif, u8 link_id,
return 0;
}
static struct ath12k_link_vif *ath12k_mac_get_tx_arvif(struct ath12k_link_vif *arvif)
static struct ath12k_link_vif *
ath12k_mac_get_tx_arvif(struct ath12k_link_vif *arvif,
struct ieee80211_bss_conf *link_conf)
{
struct ieee80211_bss_conf *link_conf, *tx_bss_conf;
struct ieee80211_bss_conf *tx_bss_conf;
struct ath12k *ar = arvif->ar;
struct ath12k_vif *tx_ahvif;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
link_conf = ath12k_mac_get_link_bss_conf(arvif);
if (!link_conf) {
ath12k_warn(ar->ab,
"unable to access bss link conf for link %u required to retrieve transmitting link conf\n",
arvif->link_id);
return NULL;
}
tx_bss_conf = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
link_conf->tx_bss_conf);
if (tx_bss_conf) {
@ -1623,7 +1618,7 @@ static int ath12k_mac_setup_bcn_tmpl(struct ath12k_link_vif *arvif)
return -ENOLINK;
}
tx_arvif = ath12k_mac_get_tx_arvif(arvif);
tx_arvif = ath12k_mac_get_tx_arvif(arvif, link_conf);
if (tx_arvif) {
if (tx_arvif != arvif && arvif->is_up)
return 0;
@ -1693,6 +1688,7 @@ static void ath12k_control_beaconing(struct ath12k_link_vif *arvif,
{
struct ath12k_wmi_vdev_up_params params = {};
struct ath12k_vif *ahvif = arvif->ahvif;
struct ieee80211_bss_conf *link_conf;
struct ath12k_link_vif *tx_arvif;
struct ath12k *ar = arvif->ar;
int ret;
@ -1725,7 +1721,15 @@ static void ath12k_control_beaconing(struct ath12k_link_vif *arvif,
params.aid = ahvif->aid;
params.bssid = arvif->bssid;
tx_arvif = ath12k_mac_get_tx_arvif(arvif);
link_conf = ath12k_mac_get_link_bss_conf(arvif);
if (!link_conf) {
ath12k_warn(ar->ab,
"unable to access bss link conf for link %u required to retrieve transmitting link conf\n",
arvif->link_id);
return;
}
tx_arvif = ath12k_mac_get_tx_arvif(arvif, link_conf);
if (tx_arvif) {
params.tx_bssid = tx_arvif->bssid;
params.nontx_profile_idx = info->bssid_index;
@ -2935,6 +2939,7 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
const struct ieee80211_sta_eht_cap *eht_cap;
const struct ieee80211_sta_he_cap *he_cap;
struct ieee80211_link_sta *link_sta;
struct ieee80211_bss_conf *link_conf;
u32 *rx_mcs, *tx_mcs;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@ -2946,6 +2951,12 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
return;
}
link_conf = ath12k_mac_get_link_bss_conf(arvif);
if (!link_conf) {
ath12k_warn(ar->ab, "unable to access link_conf in peer assoc eht set\n");
return;
}
eht_cap = &link_sta->eht_cap;
he_cap = &link_sta->he_cap;
if (!he_cap->has_he || !eht_cap->has_eht)
@ -3017,6 +3028,7 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
}
arg->punct_bitmap = ~arvif->punct_bitmap;
arg->eht_disable_mcs15 = link_conf->eht_disable_mcs15;
}
static void ath12k_peer_assoc_h_mlo(struct ath12k_link_sta *arsta,
@ -3047,6 +3059,7 @@ static void ath12k_peer_assoc_h_mlo(struct ath12k_link_sta *arsta,
ml->ml_peer_id = ahsta->ml_peer_id;
ml->ieee_link_id = arsta->link_id;
ml->num_partner_links = 0;
ml->eml_cap = sta->eml_cap;
links = ahsta->links_map;
rcu_read_lock();
@ -3480,25 +3493,18 @@ static struct ath12k_link_vif *ath12k_mac_assign_link_vif(struct ath12k_hw *ah,
if (arvif)
return arvif;
if (!vif->valid_links) {
/* Use deflink for Non-ML VIFs and mark the link id as 0
*/
link_id = 0;
/* If this is the first link arvif being created for an ML VIF
* use the preallocated deflink memory except for scan arvifs
*/
if (!ahvif->links_map && link_id != ATH12K_DEFAULT_SCAN_LINK) {
arvif = &ahvif->deflink;
if (vif->type == NL80211_IFTYPE_STATION)
arvif->is_sta_assoc_link = true;
} else {
/* If this is the first link arvif being created for an ML VIF
* use the preallocated deflink memory except for scan arvifs
*/
if (!ahvif->links_map && link_id != ATH12K_DEFAULT_SCAN_LINK) {
arvif = &ahvif->deflink;
if (vif->type == NL80211_IFTYPE_STATION)
arvif->is_sta_assoc_link = true;
} else {
arvif = (struct ath12k_link_vif *)
kzalloc(sizeof(struct ath12k_link_vif), GFP_KERNEL);
if (!arvif)
return NULL;
}
arvif = kzalloc(sizeof(*arvif), GFP_KERNEL);
if (!arvif)
return NULL;
}
ath12k_mac_init_arvif(ahvif, arvif, link_id);
@ -3746,6 +3752,18 @@ static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif)
psmode, arvif->vdev_id, ret);
}
static bool ath12k_mac_supports_station_tpc(struct ath12k *ar,
struct ath12k_vif *ahvif,
const struct cfg80211_chan_def *chandef)
{
return ath12k_wmi_supports_6ghz_cc_ext(ar) &&
test_bit(WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT, ar->ab->wmi_ab.svc_map) &&
ahvif->vdev_type == WMI_VDEV_TYPE_STA &&
ahvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE &&
chandef->chan &&
chandef->chan->band == NL80211_BAND_6GHZ;
}
static void ath12k_mac_bss_info_changed(struct ath12k *ar,
struct ath12k_link_vif *arvif,
struct ieee80211_bss_conf *info,
@ -4647,6 +4665,7 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
spin_lock_bh(&ar->data_lock);
ar->scan.state = ATH12K_SCAN_IDLE;
spin_unlock_bh(&ar->data_lock);
goto exit;
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac scan started");
@ -5779,12 +5798,15 @@ static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
enum ieee80211_sta_state new_state)
{
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_bss_conf *link_conf;
struct ath12k *ar = arvif->ar;
struct ath12k_reg_info *reg_info;
struct ath12k_base *ab = ar->ab;
int ret = 0;
lockdep_assert_wiphy(hw->wiphy);
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac handle link %u sta %pM state %d -> %d\n",
ath12k_dbg(ab, ATH12K_DBG_MAC, "mac handle link %u sta %pM state %d -> %d\n",
arsta->link_id, arsta->addr, old_state, new_state);
/* IEEE80211_STA_NONE -> IEEE80211_STA_NOTEXIST: Remove the station
@ -5794,7 +5816,7 @@ static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
new_state == IEEE80211_STA_NOTEXIST)) {
ret = ath12k_mac_station_remove(ar, arvif, arsta);
if (ret) {
ath12k_warn(ar->ab, "Failed to remove station: %pM for VDEV: %d\n",
ath12k_warn(ab, "Failed to remove station: %pM for VDEV: %d\n",
arsta->addr, arvif->vdev_id);
goto exit;
}
@ -5805,7 +5827,7 @@ static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
new_state == IEEE80211_STA_NONE) {
ret = ath12k_mac_station_add(ar, arvif, arsta);
if (ret)
ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n",
ath12k_warn(ab, "Failed to add station: %pM for VDEV: %d\n",
arsta->addr, arvif->vdev_id);
/* IEEE80211_STA_AUTH -> IEEE80211_STA_ASSOC: Send station assoc command for
@ -5818,7 +5840,7 @@ static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
vif->type == NL80211_IFTYPE_ADHOC)) {
ret = ath12k_mac_station_assoc(ar, arvif, arsta, false);
if (ret)
ath12k_warn(ar->ab, "Failed to associate station: %pM\n",
ath12k_warn(ab, "Failed to associate station: %pM\n",
arsta->addr);
/* IEEE80211_STA_ASSOC -> IEEE80211_STA_AUTHORIZED: set peer status as
@ -5827,9 +5849,21 @@ static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTHORIZED) {
ret = ath12k_mac_station_authorize(ar, arvif, arsta);
if (ret)
ath12k_warn(ar->ab, "Failed to authorize station: %pM\n",
if (ret) {
ath12k_warn(ab, "Failed to authorize station: %pM\n",
arsta->addr);
goto exit;
}
if (ath12k_wmi_supports_6ghz_cc_ext(ar) &&
arvif->ahvif->vdev_type == WMI_VDEV_TYPE_STA) {
link_conf = ath12k_mac_get_link_bss_conf(arvif);
reg_info = ab->reg_info[ar->pdev_idx];
ath12k_dbg(ab, ATH12K_DBG_MAC, "connection done, update reg rules\n");
ath12k_hw_to_ah(hw)->regd_updated = false;
ath12k_reg_handle_chan_list(ab, reg_info, arvif->ahvif->vdev_type,
link_conf->power_type);
}
/* IEEE80211_STA_AUTHORIZED -> IEEE80211_STA_ASSOC: station may be in removal,
* deauthorize it.
@ -5848,7 +5882,7 @@ static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
vif->type == NL80211_IFTYPE_ADHOC)) {
ret = ath12k_mac_station_disassoc(ar, arvif, arsta);
if (ret)
ath12k_warn(ar->ab, "Failed to disassociate station: %pM\n",
ath12k_warn(ab, "Failed to disassociate station: %pM\n",
arsta->addr);
}
@ -7466,6 +7500,7 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
struct ath12k_peer *peer;
unsigned long links_map;
bool is_mcast = false;
bool is_dvlan = false;
struct ethhdr *eth;
bool is_prb_rsp;
u16 mcbc_gsn;
@ -7531,7 +7566,14 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_AP && vif->p2p)
ath12k_mac_add_p2p_noa_ie(ar, vif, skb, is_prb_rsp);
if (!vif->valid_links || !is_mcast ||
/* Checking if it is a DVLAN frame */
if (!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags) &&
!(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) &&
!(skb_cb->flags & ATH12K_SKB_CIPHER_SET) &&
ieee80211_has_protected(hdr->frame_control))
is_dvlan = true;
if (!vif->valid_links || !is_mcast || is_dvlan ||
test_bit(ATH12K_FLAG_RAW_MODE, &ar->ab->dev_flags)) {
ret = ath12k_dp_tx(ar, arvif, skb, false, 0, is_mcast);
if (unlikely(ret)) {
@ -7990,7 +8032,7 @@ static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_link_vif *arvif,
return -ENOLINK;
}
tx_arvif = ath12k_mac_get_tx_arvif(arvif);
tx_arvif = ath12k_mac_get_tx_arvif(arvif, link_conf);
if (!tx_arvif)
return 0;
@ -8319,50 +8361,9 @@ void ath12k_mac_11d_scan_stop_all(struct ath12k_base *ab)
}
}
int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
static void ath12k_mac_determine_vdev_type(struct ieee80211_vif *vif,
struct ath12k_vif *ahvif)
{
struct ath12k_hw *ah = ar->ah;
struct ath12k_base *ab = ar->ab;
struct ieee80211_hw *hw = ah->hw;
struct ath12k_vif *ahvif = arvif->ahvif;
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ath12k_wmi_vdev_create_arg vdev_arg = {0};
struct ath12k_wmi_peer_create_arg peer_param = {0};
struct ieee80211_bss_conf *link_conf;
u32 param_id, param_value;
u16 nss;
int i;
int ret, vdev_id;
u8 link_id;
lockdep_assert_wiphy(hw->wiphy);
/* In NO_VIRTUAL_MONITOR, its necessary to restrict only one monitor
* interface in each radio
*/
if (vif->type == NL80211_IFTYPE_MONITOR && ar->monitor_vdev_created)
return -EINVAL;
/* If no link is active and scan vdev is requested
* use a default link conf for scan address purpose.
*/
if (arvif->link_id == ATH12K_DEFAULT_SCAN_LINK && vif->valid_links)
link_id = ffs(vif->valid_links) - 1;
else
link_id = arvif->link_id;
link_conf = wiphy_dereference(hw->wiphy, vif->link_conf[link_id]);
if (!link_conf) {
ath12k_warn(ar->ab, "unable to access bss link conf in vdev create for vif %pM link %u\n",
vif->addr, arvif->link_id);
return -ENOLINK;
}
memcpy(arvif->bssid, link_conf->addr, ETH_ALEN);
arvif->ar = ar;
vdev_id = __ffs64(ab->free_vdev_map);
arvif->vdev_id = vdev_id;
ahvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
switch (vif->type) {
@ -8386,7 +8387,6 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
break;
case NL80211_IFTYPE_MONITOR:
ahvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
ar->monitor_vdev_id = vdev_id;
break;
case NL80211_IFTYPE_P2P_DEVICE:
ahvif->vdev_type = WMI_VDEV_TYPE_STA;
@ -8396,6 +8396,53 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
WARN_ON(1);
break;
}
}
int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
{
struct ath12k_hw *ah = ar->ah;
struct ath12k_base *ab = ar->ab;
struct ieee80211_hw *hw = ah->hw;
struct ath12k_vif *ahvif = arvif->ahvif;
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ath12k_wmi_vdev_create_arg vdev_arg = {0};
struct ath12k_wmi_peer_create_arg peer_param = {0};
struct ieee80211_bss_conf *link_conf = NULL;
u32 param_id, param_value;
u16 nss;
int i;
int ret, vdev_id;
u8 link_id;
lockdep_assert_wiphy(hw->wiphy);
/* In NO_VIRTUAL_MONITOR, its necessary to restrict only one monitor
* interface in each radio
*/
if (vif->type == NL80211_IFTYPE_MONITOR && ar->monitor_vdev_created)
return -EINVAL;
link_id = arvif->link_id;
if (link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
link_conf = wiphy_dereference(hw->wiphy, vif->link_conf[link_id]);
if (!link_conf) {
ath12k_warn(ar->ab, "unable to access bss link conf in vdev create for vif %pM link %u\n",
vif->addr, arvif->link_id);
return -ENOLINK;
}
}
if (link_conf)
memcpy(arvif->bssid, link_conf->addr, ETH_ALEN);
else
memcpy(arvif->bssid, vif->addr, ETH_ALEN);
arvif->ar = ar;
vdev_id = __ffs64(ab->free_vdev_map);
arvif->vdev_id = vdev_id;
if (vif->type == NL80211_IFTYPE_MONITOR)
ar->monitor_vdev_id = vdev_id;
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev create id %d type %d subtype %d map %llx\n",
arvif->vdev_id, ahvif->vdev_type, ahvif->vdev_subtype,
@ -8513,7 +8560,11 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
break;
}
arvif->txpower = link_conf->txpower;
if (link_conf)
arvif->txpower = link_conf->txpower;
else
arvif->txpower = NL80211_TX_POWER_AUTOMATIC;
ret = ath12k_mac_txpower_recalc(ar);
if (ret)
goto err_peer_del;
@ -8751,7 +8802,10 @@ static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_reg_info *reg_info;
struct ath12k_link_vif *arvif;
struct ath12k_base *ab;
struct ath12k *ar;
int i;
lockdep_assert_wiphy(hw->wiphy);
@ -8770,6 +8824,22 @@ static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
vif->hw_queue[i] = ATH12K_HW_DEFAULT_QUEUE;
vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
ath12k_mac_determine_vdev_type(vif, ahvif);
for_each_ar(ah, ar, i) {
if (!ath12k_wmi_supports_6ghz_cc_ext(ar))
continue;
ab = ar->ab;
reg_info = ab->reg_info[ar->pdev_idx];
ath12k_dbg(ab, ATH12K_DBG_MAC, "interface added to change reg rules\n");
ah->regd_updated = false;
ath12k_reg_handle_chan_list(ab, reg_info, ahvif->vdev_type,
IEEE80211_REG_UNSET_AP);
break;
}
/* Defer vdev creation until assign_chanctx or hw_scan is initiated as driver
* will not know if this interface is an ML vif at this point.
*/
@ -9326,6 +9396,15 @@ ath12k_mac_vdev_start_restart(struct ath12k_link_vif *arvif,
return ret;
}
/* TODO: For now we only set TPC power here. However when
* channel changes, say CSA, it should be updated again.
*/
if (ath12k_mac_supports_station_tpc(ar, ahvif, chandef)) {
ath12k_mac_fill_reg_tpc_info(ar, arvif, ctx);
ath12k_wmi_send_vdev_set_tpc_power(ar, arvif->vdev_id,
&arvif->reg_tpc_info);
}
ar->num_started_vdevs++;
ath12k_dbg(ab, ATH12K_DBG_MAC, "vdev %pM started, vdev_id %d\n",
ahvif->vif->addr, arvif->vdev_id);
@ -9581,7 +9660,7 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
params.aid = ahvif->aid;
params.bssid = arvif->bssid;
tx_arvif = ath12k_mac_get_tx_arvif(arvif);
tx_arvif = ath12k_mac_get_tx_arvif(arvif, link_conf);
if (tx_arvif) {
params.tx_bssid = tx_arvif->bssid;
params.nontx_profile_idx = link_conf->bssid_index;
@ -9718,6 +9797,391 @@ static int ath12k_start_vdev_delay(struct ath12k *ar,
return 0;
}
static u8 ath12k_mac_get_num_pwr_levels(struct cfg80211_chan_def *chan_def)
{
if (chan_def->chan->flags & IEEE80211_CHAN_PSD) {
switch (chan_def->width) {
case NL80211_CHAN_WIDTH_20:
return 1;
case NL80211_CHAN_WIDTH_40:
return 2;
case NL80211_CHAN_WIDTH_80:
return 4;
case NL80211_CHAN_WIDTH_160:
return 8;
case NL80211_CHAN_WIDTH_320:
return 16;
default:
return 1;
}
} else {
switch (chan_def->width) {
case NL80211_CHAN_WIDTH_20:
return 1;
case NL80211_CHAN_WIDTH_40:
return 2;
case NL80211_CHAN_WIDTH_80:
return 3;
case NL80211_CHAN_WIDTH_160:
return 4;
case NL80211_CHAN_WIDTH_320:
return 5;
default:
return 1;
}
}
}
static u16 ath12k_mac_get_6ghz_start_frequency(struct cfg80211_chan_def *chan_def)
{
u16 diff_seq;
/* It is to get the lowest channel number's center frequency of the chan.
* For example,
* bandwidth=40 MHz, center frequency is 5965, lowest channel is 1
* with center frequency 5955, its diff is 5965 - 5955 = 10.
* bandwidth=80 MHz, center frequency is 5985, lowest channel is 1
* with center frequency 5955, its diff is 5985 - 5955 = 30.
* bandwidth=160 MHz, center frequency is 6025, lowest channel is 1
* with center frequency 5955, its diff is 6025 - 5955 = 70.
* bandwidth=320 MHz, center frequency is 6105, lowest channel is 1
* with center frequency 5955, its diff is 6105 - 5955 = 70.
*/
switch (chan_def->width) {
case NL80211_CHAN_WIDTH_320:
diff_seq = 150;
break;
case NL80211_CHAN_WIDTH_160:
diff_seq = 70;
break;
case NL80211_CHAN_WIDTH_80:
diff_seq = 30;
break;
case NL80211_CHAN_WIDTH_40:
diff_seq = 10;
break;
default:
diff_seq = 0;
}
return chan_def->center_freq1 - diff_seq;
}
static u16 ath12k_mac_get_seg_freq(struct cfg80211_chan_def *chan_def,
u16 start_seq, u8 seq)
{
u16 seg_seq;
/* It is to get the center frequency of the specific bandwidth.
* start_seq means the lowest channel number's center frequency.
* seq 0/1/2/3 means 20 MHz/40 MHz/80 MHz/160 MHz.
* For example,
* lowest channel is 1, its center frequency 5955,
* center frequency is 5955 when bandwidth=20 MHz, its diff is 5955 - 5955 = 0.
* lowest channel is 1, its center frequency 5955,
* center frequency is 5965 when bandwidth=40 MHz, its diff is 5965 - 5955 = 10.
* lowest channel is 1, its center frequency 5955,
* center frequency is 5985 when bandwidth=80 MHz, its diff is 5985 - 5955 = 30.
* lowest channel is 1, its center frequency 5955,
* center frequency is 6025 when bandwidth=160 MHz, its diff is 6025 - 5955 = 70.
*/
seg_seq = 10 * (BIT(seq) - 1);
return seg_seq + start_seq;
}
static void ath12k_mac_get_psd_channel(struct ath12k *ar,
u16 step_freq,
u16 *start_freq,
u16 *center_freq,
u8 i,
struct ieee80211_channel **temp_chan,
s8 *tx_power)
{
/* It is to get the center frequency for each 20 MHz.
* For example, if the chan is 160 MHz and center frequency is 6025,
* then it include 8 channels, they are 1/5/9/13/17/21/25/29,
* channel number 1's center frequency is 5955, it is parameter start_freq.
* parameter i is the step of the 8 channels. i is 0~7 for the 8 channels.
* the channel 1/5/9/13/17/21/25/29 maps i=0/1/2/3/4/5/6/7,
* and maps its center frequency is 5955/5975/5995/6015/6035/6055/6075/6095,
* the gap is 20 for each channel, parameter step_freq means the gap.
* after get the center frequency of each channel, it is easy to find the
* struct ieee80211_channel of it and get the max_reg_power.
*/
*center_freq = *start_freq + i * step_freq;
*temp_chan = ieee80211_get_channel(ar->ah->hw->wiphy, *center_freq);
*tx_power = (*temp_chan)->max_reg_power;
}
static void ath12k_mac_get_eirp_power(struct ath12k *ar,
u16 *start_freq,
u16 *center_freq,
u8 i,
struct ieee80211_channel **temp_chan,
struct cfg80211_chan_def *def,
s8 *tx_power)
{
/* It is to get the center frequency for 20 MHz/40 MHz/80 MHz/
* 160 MHz bandwidth, and then plus 10 to the center frequency,
* it is the center frequency of a channel number.
* For example, when configured channel number is 1.
* center frequency is 5965 when bandwidth=40 MHz, after plus 10, it is 5975,
* then it is channel number 5.
* center frequency is 5985 when bandwidth=80 MHz, after plus 10, it is 5995,
* then it is channel number 9.
* center frequency is 6025 when bandwidth=160 MHz, after plus 10, it is 6035,
* then it is channel number 17.
* after get the center frequency of each channel, it is easy to find the
* struct ieee80211_channel of it and get the max_reg_power.
*/
*center_freq = ath12k_mac_get_seg_freq(def, *start_freq, i);
/* For the 20 MHz, its center frequency is same with same channel */
if (i != 0)
*center_freq += 10;
*temp_chan = ieee80211_get_channel(ar->ah->hw->wiphy, *center_freq);
*tx_power = (*temp_chan)->max_reg_power;
}
void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar,
struct ath12k_link_vif *arvif,
struct ieee80211_chanctx_conf *ctx)
{
struct ath12k_base *ab = ar->ab;
struct ath12k_reg_tpc_power_info *reg_tpc_info = &arvif->reg_tpc_info;
struct ieee80211_bss_conf *bss_conf = ath12k_mac_get_link_bss_conf(arvif);
struct ieee80211_channel *chan, *temp_chan;
u8 pwr_lvl_idx, num_pwr_levels, pwr_reduction;
bool is_psd_power = false, is_tpe_present = false;
s8 max_tx_power[ATH12K_NUM_PWR_LEVELS],
psd_power, tx_power, eirp_power;
u16 start_freq, center_freq;
chan = ctx->def.chan;
start_freq = ath12k_mac_get_6ghz_start_frequency(&ctx->def);
pwr_reduction = bss_conf->pwr_reduction;
if (arvif->reg_tpc_info.num_pwr_levels) {
is_tpe_present = true;
num_pwr_levels = arvif->reg_tpc_info.num_pwr_levels;
} else {
num_pwr_levels = ath12k_mac_get_num_pwr_levels(&ctx->def);
}
for (pwr_lvl_idx = 0; pwr_lvl_idx < num_pwr_levels; pwr_lvl_idx++) {
/* STA received TPE IE*/
if (is_tpe_present) {
/* local power is PSD power*/
if (chan->flags & IEEE80211_CHAN_PSD) {
/* Connecting AP is psd power */
if (reg_tpc_info->is_psd_power) {
is_psd_power = true;
ath12k_mac_get_psd_channel(ar, 20,
&start_freq,
&center_freq,
pwr_lvl_idx,
&temp_chan,
&tx_power);
psd_power = temp_chan->psd;
eirp_power = tx_power;
max_tx_power[pwr_lvl_idx] =
min_t(s8,
psd_power,
reg_tpc_info->tpe[pwr_lvl_idx]);
/* Connecting AP is not psd power */
} else {
ath12k_mac_get_eirp_power(ar,
&start_freq,
&center_freq,
pwr_lvl_idx,
&temp_chan,
&ctx->def,
&tx_power);
psd_power = temp_chan->psd;
/* convert psd power to EIRP power based
* on channel width
*/
tx_power =
min_t(s8, tx_power,
psd_power + 13 + pwr_lvl_idx * 3);
max_tx_power[pwr_lvl_idx] =
min_t(s8,
tx_power,
reg_tpc_info->tpe[pwr_lvl_idx]);
}
/* local power is not PSD power */
} else {
/* Connecting AP is psd power */
if (reg_tpc_info->is_psd_power) {
is_psd_power = true;
ath12k_mac_get_psd_channel(ar, 20,
&start_freq,
&center_freq,
pwr_lvl_idx,
&temp_chan,
&tx_power);
eirp_power = tx_power;
max_tx_power[pwr_lvl_idx] =
reg_tpc_info->tpe[pwr_lvl_idx];
/* Connecting AP is not psd power */
} else {
ath12k_mac_get_eirp_power(ar,
&start_freq,
&center_freq,
pwr_lvl_idx,
&temp_chan,
&ctx->def,
&tx_power);
max_tx_power[pwr_lvl_idx] =
min_t(s8,
tx_power,
reg_tpc_info->tpe[pwr_lvl_idx]);
}
}
/* STA not received TPE IE */
} else {
/* local power is PSD power*/
if (chan->flags & IEEE80211_CHAN_PSD) {
is_psd_power = true;
ath12k_mac_get_psd_channel(ar, 20,
&start_freq,
&center_freq,
pwr_lvl_idx,
&temp_chan,
&tx_power);
psd_power = temp_chan->psd;
eirp_power = tx_power;
max_tx_power[pwr_lvl_idx] = psd_power;
} else {
ath12k_mac_get_eirp_power(ar,
&start_freq,
&center_freq,
pwr_lvl_idx,
&temp_chan,
&ctx->def,
&tx_power);
max_tx_power[pwr_lvl_idx] = tx_power;
}
}
if (is_psd_power) {
/* If AP local power constraint is present */
if (pwr_reduction)
eirp_power = eirp_power - pwr_reduction;
/* If firmware updated max tx power is non zero, then take
* the min of firmware updated ap tx power
* and max power derived from above mentioned parameters.
*/
ath12k_dbg(ab, ATH12K_DBG_MAC,
"eirp power : %d firmware report power : %d\n",
eirp_power, ar->max_allowed_tx_power);
/* Firmware reports lower max_allowed_tx_power during vdev
* start response. In case of 6 GHz, firmware is not aware
* of EIRP power unless driver sets EIRP power through WMI
* TPC command. So radio which does not support idle power
* save can set maximum calculated EIRP power directly to
* firmware through TPC command without min comparison with
* vdev start response's max_allowed_tx_power.
*/
if (ar->max_allowed_tx_power && ab->hw_params->idle_ps)
eirp_power = min_t(s8,
eirp_power,
ar->max_allowed_tx_power);
} else {
/* If AP local power constraint is present */
if (pwr_reduction)
max_tx_power[pwr_lvl_idx] =
max_tx_power[pwr_lvl_idx] - pwr_reduction;
/* If firmware updated max tx power is non zero, then take
* the min of firmware updated ap tx power
* and max power derived from above mentioned parameters.
*/
if (ar->max_allowed_tx_power && ab->hw_params->idle_ps)
max_tx_power[pwr_lvl_idx] =
min_t(s8,
max_tx_power[pwr_lvl_idx],
ar->max_allowed_tx_power);
}
reg_tpc_info->chan_power_info[pwr_lvl_idx].chan_cfreq = center_freq;
reg_tpc_info->chan_power_info[pwr_lvl_idx].tx_power =
max_tx_power[pwr_lvl_idx];
}
reg_tpc_info->num_pwr_levels = num_pwr_levels;
reg_tpc_info->is_psd_power = is_psd_power;
reg_tpc_info->eirp_power = eirp_power;
reg_tpc_info->ap_power_type =
ath12k_reg_ap_pwr_convert(bss_conf->power_type);
}
static void ath12k_mac_parse_tx_pwr_env(struct ath12k *ar,
struct ath12k_link_vif *arvif)
{
struct ieee80211_bss_conf *bss_conf = ath12k_mac_get_link_bss_conf(arvif);
struct ath12k_reg_tpc_power_info *tpc_info = &arvif->reg_tpc_info;
struct ieee80211_parsed_tpe_eirp *local_non_psd, *reg_non_psd;
struct ieee80211_parsed_tpe_psd *local_psd, *reg_psd;
struct ieee80211_parsed_tpe *tpe = &bss_conf->tpe;
enum wmi_reg_6g_client_type client_type;
struct ath12k_reg_info *reg_info;
struct ath12k_base *ab = ar->ab;
bool psd_valid, non_psd_valid;
int i;
reg_info = ab->reg_info[ar->pdev_idx];
client_type = reg_info->client_type;
local_psd = &tpe->psd_local[client_type];
reg_psd = &tpe->psd_reg_client[client_type];
local_non_psd = &tpe->max_local[client_type];
reg_non_psd = &tpe->max_reg_client[client_type];
psd_valid = local_psd->valid | reg_psd->valid;
non_psd_valid = local_non_psd->valid | reg_non_psd->valid;
if (!psd_valid && !non_psd_valid) {
ath12k_warn(ab,
"no transmit power envelope match client power type %d\n",
client_type);
return;
};
if (psd_valid) {
tpc_info->is_psd_power = true;
tpc_info->num_pwr_levels = max(local_psd->count,
reg_psd->count);
if (tpc_info->num_pwr_levels > ATH12K_NUM_PWR_LEVELS)
tpc_info->num_pwr_levels = ATH12K_NUM_PWR_LEVELS;
for (i = 0; i < tpc_info->num_pwr_levels; i++) {
tpc_info->tpe[i] = min(local_psd->power[i],
reg_psd->power[i]) / 2;
ath12k_dbg(ab, ATH12K_DBG_MAC,
"TPE PSD power[%d] : %d\n",
i, tpc_info->tpe[i]);
}
} else {
tpc_info->is_psd_power = false;
tpc_info->eirp_power = 0;
tpc_info->num_pwr_levels = max(local_non_psd->count,
reg_non_psd->count);
if (tpc_info->num_pwr_levels > ATH12K_NUM_PWR_LEVELS)
tpc_info->num_pwr_levels = ATH12K_NUM_PWR_LEVELS;
for (i = 0; i < tpc_info->num_pwr_levels; i++) {
tpc_info->tpe[i] = min(local_non_psd->power[i],
reg_non_psd->power[i]) / 2;
ath12k_dbg(ab, ATH12K_DBG_MAC,
"non PSD power[%d] : %d\n",
i, tpc_info->tpe[i]);
}
}
}
static int
ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@ -9756,6 +10220,11 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
"mac chanctx assign ptr %p vdev_id %i\n",
ctx, arvif->vdev_id);
if (ath12k_wmi_supports_6ghz_cc_ext(ar) &&
ctx->def.chan->band == NL80211_BAND_6GHZ &&
ahvif->vdev_type == WMI_VDEV_TYPE_STA)
ath12k_mac_parse_tx_pwr_env(ar, arvif);
arvif->punct_bitmap = ctx->def.punctured;
/* for some targets bss peer must be created before vdev_start */
@ -9860,6 +10329,11 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
reinit_completion(&ar->completed_11d_scan);
ar->state_11d = ATH12K_11D_PREPARING;
}
if (ar->scan.arvif == arvif && ar->scan.state == ATH12K_SCAN_RUNNING) {
ath12k_scan_abort(ar);
ar->scan.arvif = NULL;
}
}
static int
@ -10889,8 +11363,20 @@ void ath12k_mac_update_freq_range(struct ath12k *ar,
if (!(freq_low && freq_high))
return;
ar->freq_range.start_freq = MHZ_TO_KHZ(freq_low);
ar->freq_range.end_freq = MHZ_TO_KHZ(freq_high);
if (ar->freq_range.start_freq || ar->freq_range.end_freq) {
ar->freq_range.start_freq = min(ar->freq_range.start_freq,
MHZ_TO_KHZ(freq_low));
ar->freq_range.end_freq = max(ar->freq_range.end_freq,
MHZ_TO_KHZ(freq_high));
} else {
ar->freq_range.start_freq = MHZ_TO_KHZ(freq_low);
ar->freq_range.end_freq = MHZ_TO_KHZ(freq_high);
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
"mac pdev %u freq limit updated. New range %u->%u MHz\n",
ar->pdev->pdev_id, KHZ_TO_MHZ(ar->freq_range.start_freq),
KHZ_TO_MHZ(ar->freq_range.end_freq));
}
static void ath12k_mac_update_ch_list(struct ath12k *ar,
@ -11374,6 +11860,7 @@ static void ath12k_mac_hw_unregister(struct ath12k_hw *ah)
for_each_ar(ah, ar, i) {
cancel_work_sync(&ar->regd_update_work);
ath12k_debugfs_unregister(ar);
ath12k_fw_stats_reset(ar);
}
ieee80211_unregister_hw(hw);
@ -11651,6 +12138,18 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
goto err_unregister_hw;
}
if (ar->ab->hw_params->current_cc_support && ab->new_alpha2[0]) {
struct wmi_set_current_country_arg current_cc = {};
memcpy(&current_cc.alpha2, ab->new_alpha2, 2);
memcpy(&ar->alpha2, ab->new_alpha2, 2);
ret = ath12k_wmi_send_set_current_country_cmd(ar, &current_cc);
if (ret)
ath12k_warn(ar->ab,
"failed set cc code for mac register: %d\n",
ret);
}
ath12k_fw_stats_init(ar);
ath12k_debugfs_register(ar);
}
@ -12025,6 +12524,7 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)
if (!ab)
continue;
ath12k_debugfs_pdev_create(ab);
ath12k_mac_set_device_defaults(ab);
total_radio += ab->num_radios;
}

@ -67,6 +67,46 @@ struct ath12k_mac_get_any_chanctx_conf_arg {
struct ieee80211_chanctx_conf *chanctx_conf;
};
/**
* struct ath12k_chan_power_info - TPE containing power info per channel chunk
* @chan_cfreq: channel center freq (MHz)
* e.g.
* channel 37/20 MHz, it is 6135
* channel 37/40 MHz, it is 6125
* channel 37/80 MHz, it is 6145
* channel 37/160 MHz, it is 6185
* @tx_power: transmit power (dBm)
*/
struct ath12k_chan_power_info {
u16 chan_cfreq;
s8 tx_power;
};
/* ath12k only deals with 320 MHz, so 16 subchannels */
#define ATH12K_NUM_PWR_LEVELS 16
/**
* struct ath12k_reg_tpc_power_info - regulatory TPC power info
* @is_psd_power: is PSD power or not
* @eirp_power: Maximum EIRP power (dBm), valid only if power is PSD
* @ap_power_type: type of power (SP/LPI/VLP)
* @num_pwr_levels: number of power levels
* @reg_max: Array of maximum TX power (dBm) per PSD value
* @ap_constraint_power: AP constraint power (dBm)
* @tpe: TPE values processed from TPE IE
* @chan_power_info: power info to send to firmware
*/
struct ath12k_reg_tpc_power_info {
bool is_psd_power;
u8 eirp_power;
enum wmi_reg_6g_ap_type ap_power_type;
u8 num_pwr_levels;
u8 reg_max[ATH12K_NUM_PWR_LEVELS];
u8 ap_constraint_power;
s8 tpe[ATH12K_NUM_PWR_LEVELS];
struct ath12k_chan_power_info chan_power_info[ATH12K_NUM_PWR_LEVELS];
};
extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default;
#define ATH12K_SCAN_11D_INTERVAL 600000
@ -128,4 +168,7 @@ struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw,
int ath12k_mac_get_fw_stats(struct ath12k *ar, struct ath12k_fw_stats_req_params *param);
void ath12k_mac_update_freq_range(struct ath12k *ar,
u32 freq_low, u32 freq_high);
void ath12k_mac_fill_reg_tpc_info(struct ath12k *ar,
struct ath12k_link_vif *arvif,
struct ieee80211_chanctx_conf *ctx);
#endif

@ -600,7 +600,8 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab)
ab->hw_params->ring_mask->rx_wbm_rel[i] ||
ab->hw_params->ring_mask->reo_status[i] ||
ab->hw_params->ring_mask->host2rxdma[i] ||
ab->hw_params->ring_mask->rx_mon_dest[i]) {
ab->hw_params->ring_mask->rx_mon_dest[i] ||
ab->hw_params->ring_mask->rx_mon_status[i]) {
num_irq = 1;
}
@ -1733,8 +1734,6 @@ static void ath12k_pci_remove(struct pci_dev *pdev)
if (test_bit(ATH12K_FLAG_QMI_FAIL, &ab->dev_flags)) {
ath12k_pci_power_down(ab, false);
ath12k_qmi_deinit_service(ab);
ath12k_core_hw_group_unassign(ab);
goto qmi_fail;
}
@ -1742,9 +1741,10 @@ static void ath12k_pci_remove(struct pci_dev *pdev)
cancel_work_sync(&ab->reset_work);
cancel_work_sync(&ab->dump_work);
ath12k_core_deinit(ab);
ath12k_core_hw_group_cleanup(ab->ag);
qmi_fail:
ath12k_core_deinit(ab);
ath12k_fw_unmap(ab);
ath12k_mhi_unregister(ab_pci);

@ -139,7 +139,7 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
int num_channels = 0;
int i, ret, left;
if (wait && ar->state_11d != ATH12K_11D_IDLE) {
if (wait && ar->state_11d == ATH12K_11D_RUNNING) {
left = wait_for_completion_timeout(&ar->completed_11d_scan,
ATH12K_SCAN_TIMEOUT_HZ);
if (!left) {
@ -265,8 +265,8 @@ static void ath12k_copy_regd(struct ieee80211_regdomain *regd_orig,
int ath12k_regd_update(struct ath12k *ar, bool init)
{
u32 phy_id, freq_low = 0, freq_high = 0, supported_bands, band;
struct ath12k_wmi_hal_reg_capabilities_ext_arg *reg_cap;
u32 phy_id, freq_low, freq_high, supported_bands;
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
struct ieee80211_hw *hw = ah->hw;
struct ieee80211_regdomain *regd, *regd_copy = NULL;
@ -276,45 +276,45 @@ int ath12k_regd_update(struct ath12k *ar, bool init)
ab = ar->ab;
supported_bands = ar->pdev->cap.supported_bands;
if (supported_bands & WMI_HOST_WLAN_2GHZ_CAP) {
band = NL80211_BAND_2GHZ;
} else if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && !ar->supports_6ghz) {
band = NL80211_BAND_5GHZ;
} else if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && ar->supports_6ghz) {
band = NL80211_BAND_6GHZ;
} else {
/* This condition is not expected.
*/
WARN_ON(1);
ret = -EINVAL;
goto err;
}
reg_cap = &ab->hal_reg_cap[ar->pdev_idx];
if (ab->hw_params->single_pdev_only && !ar->supports_6ghz) {
phy_id = ar->pdev->cap.band[band].phy_id;
reg_cap = &ab->hal_reg_cap[phy_id];
}
/* Possible that due to reg change, current limits for supported
* frequency changed. Update that
* frequency changed. Update it. As a first step, reset the
* previous values and then compute and set the new values.
*/
ar->freq_range.start_freq = 0;
ar->freq_range.end_freq = 0;
if (supported_bands & WMI_HOST_WLAN_2GHZ_CAP) {
if (ab->hw_params->single_pdev_only) {
phy_id = ar->pdev->cap.band[WMI_HOST_WLAN_2GHZ_CAP].phy_id;
reg_cap = &ab->hal_reg_cap[phy_id];
}
freq_low = max(reg_cap->low_2ghz_chan, ab->reg_freq_2ghz.start_freq);
freq_high = min(reg_cap->high_2ghz_chan, ab->reg_freq_2ghz.end_freq);
} else if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && !ar->supports_6ghz) {
freq_low = max(reg_cap->low_5ghz_chan, ab->reg_freq_5ghz.start_freq);
freq_high = min(reg_cap->high_5ghz_chan, ab->reg_freq_5ghz.end_freq);
} else if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && ar->supports_6ghz) {
freq_low = max(reg_cap->low_5ghz_chan, ab->reg_freq_6ghz.start_freq);
freq_high = min(reg_cap->high_5ghz_chan, ab->reg_freq_6ghz.end_freq);
ath12k_mac_update_freq_range(ar, freq_low, freq_high);
}
ath12k_mac_update_freq_range(ar, freq_low, freq_high);
if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && !ar->supports_6ghz) {
if (ab->hw_params->single_pdev_only) {
phy_id = ar->pdev->cap.band[WMI_HOST_WLAN_5GHZ_CAP].phy_id;
reg_cap = &ab->hal_reg_cap[phy_id];
}
ath12k_dbg(ab, ATH12K_DBG_REG, "pdev %u reg updated freq limits %u->%u MHz\n",
ar->pdev->pdev_id, freq_low, freq_high);
freq_low = max(reg_cap->low_5ghz_chan, ab->reg_freq_5ghz.start_freq);
freq_high = min(reg_cap->high_5ghz_chan, ab->reg_freq_5ghz.end_freq);
ath12k_mac_update_freq_range(ar, freq_low, freq_high);
}
if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP && ar->supports_6ghz) {
freq_low = max(reg_cap->low_5ghz_chan, ab->reg_freq_6ghz.start_freq);
freq_high = min(reg_cap->high_5ghz_chan, ab->reg_freq_6ghz.end_freq);
ath12k_mac_update_freq_range(ar, freq_low, freq_high);
}
/* If one of the radios within ah has already updated the regd for
* the wiphy, then avoid setting regd again
@ -454,129 +454,6 @@ static u32 ath12k_map_fw_phy_flags(u32 phy_flags)
return flags;
}
static bool
ath12k_reg_can_intersect(struct ieee80211_reg_rule *rule1,
struct ieee80211_reg_rule *rule2)
{
u32 start_freq1, end_freq1;
u32 start_freq2, end_freq2;
start_freq1 = rule1->freq_range.start_freq_khz;
start_freq2 = rule2->freq_range.start_freq_khz;
end_freq1 = rule1->freq_range.end_freq_khz;
end_freq2 = rule2->freq_range.end_freq_khz;
if ((start_freq1 >= start_freq2 &&
start_freq1 < end_freq2) ||
(start_freq2 > start_freq1 &&
start_freq2 < end_freq1))
return true;
/* TODO: Should we restrict intersection feasibility
* based on min bandwidth of the intersected region also,
* say the intersected rule should have a min bandwidth
* of 20MHz?
*/
return false;
}
static void ath12k_reg_intersect_rules(struct ieee80211_reg_rule *rule1,
struct ieee80211_reg_rule *rule2,
struct ieee80211_reg_rule *new_rule)
{
u32 start_freq1, end_freq1;
u32 start_freq2, end_freq2;
u32 freq_diff, max_bw;
start_freq1 = rule1->freq_range.start_freq_khz;
start_freq2 = rule2->freq_range.start_freq_khz;
end_freq1 = rule1->freq_range.end_freq_khz;
end_freq2 = rule2->freq_range.end_freq_khz;
new_rule->freq_range.start_freq_khz = max_t(u32, start_freq1,
start_freq2);
new_rule->freq_range.end_freq_khz = min_t(u32, end_freq1, end_freq2);
freq_diff = new_rule->freq_range.end_freq_khz -
new_rule->freq_range.start_freq_khz;
max_bw = min_t(u32, rule1->freq_range.max_bandwidth_khz,
rule2->freq_range.max_bandwidth_khz);
new_rule->freq_range.max_bandwidth_khz = min_t(u32, max_bw, freq_diff);
new_rule->power_rule.max_antenna_gain =
min_t(u32, rule1->power_rule.max_antenna_gain,
rule2->power_rule.max_antenna_gain);
new_rule->power_rule.max_eirp = min_t(u32, rule1->power_rule.max_eirp,
rule2->power_rule.max_eirp);
/* Use the flags of both the rules */
new_rule->flags = rule1->flags | rule2->flags;
/* To be safe, lts use the max cac timeout of both rules */
new_rule->dfs_cac_ms = max_t(u32, rule1->dfs_cac_ms,
rule2->dfs_cac_ms);
}
static struct ieee80211_regdomain *
ath12k_regd_intersect(struct ieee80211_regdomain *default_regd,
struct ieee80211_regdomain *curr_regd)
{
u8 num_old_regd_rules, num_curr_regd_rules, num_new_regd_rules;
struct ieee80211_reg_rule *old_rule, *curr_rule, *new_rule;
struct ieee80211_regdomain *new_regd = NULL;
u8 i, j, k;
num_old_regd_rules = default_regd->n_reg_rules;
num_curr_regd_rules = curr_regd->n_reg_rules;
num_new_regd_rules = 0;
/* Find the number of intersecting rules to allocate new regd memory */
for (i = 0; i < num_old_regd_rules; i++) {
old_rule = default_regd->reg_rules + i;
for (j = 0; j < num_curr_regd_rules; j++) {
curr_rule = curr_regd->reg_rules + j;
if (ath12k_reg_can_intersect(old_rule, curr_rule))
num_new_regd_rules++;
}
}
if (!num_new_regd_rules)
return NULL;
new_regd = kzalloc(sizeof(*new_regd) + (num_new_regd_rules *
sizeof(struct ieee80211_reg_rule)),
GFP_ATOMIC);
if (!new_regd)
return NULL;
/* We set the new country and dfs region directly and only trim
* the freq, power, antenna gain by intersecting with the
* default regdomain. Also MAX of the dfs cac timeout is selected.
*/
new_regd->n_reg_rules = num_new_regd_rules;
memcpy(new_regd->alpha2, curr_regd->alpha2, sizeof(new_regd->alpha2));
new_regd->dfs_region = curr_regd->dfs_region;
new_rule = new_regd->reg_rules;
for (i = 0, k = 0; i < num_old_regd_rules; i++) {
old_rule = default_regd->reg_rules + i;
for (j = 0; j < num_curr_regd_rules; j++) {
curr_rule = curr_regd->reg_rules + j;
if (ath12k_reg_can_intersect(old_rule, curr_rule))
ath12k_reg_intersect_rules(old_rule, curr_rule,
(new_rule + k++));
}
}
return new_regd;
}
static const char *
ath12k_reg_get_regdom_str(enum nl80211_dfs_regions dfs_region)
{
@ -613,13 +490,14 @@ ath12k_reg_adjust_bw(u16 start_freq, u16 end_freq, u16 max_bw)
static void
ath12k_reg_update_rule(struct ieee80211_reg_rule *reg_rule, u32 start_freq,
u32 end_freq, u32 bw, u32 ant_gain, u32 reg_pwr,
u32 reg_flags)
s8 psd, u32 reg_flags)
{
reg_rule->freq_range.start_freq_khz = MHZ_TO_KHZ(start_freq);
reg_rule->freq_range.end_freq_khz = MHZ_TO_KHZ(end_freq);
reg_rule->freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw);
reg_rule->power_rule.max_antenna_gain = DBI_TO_MBI(ant_gain);
reg_rule->power_rule.max_eirp = DBM_TO_MBM(reg_pwr);
reg_rule->psd = psd;
reg_rule->flags = reg_flags;
}
@ -641,7 +519,7 @@ ath12k_reg_update_weather_radar_band(struct ath12k_base *ab,
ath12k_reg_update_rule(regd->reg_rules + i, reg_rule->start_freq,
ETSI_WEATHER_RADAR_BAND_LOW, bw,
reg_rule->ant_gain, reg_rule->reg_power,
flags);
reg_rule->psd_eirp, flags);
ath12k_dbg(ab, ATH12K_DBG_REG,
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n",
@ -663,7 +541,7 @@ ath12k_reg_update_weather_radar_band(struct ath12k_base *ab,
ath12k_reg_update_rule(regd->reg_rules + i,
ETSI_WEATHER_RADAR_BAND_LOW, end_freq, bw,
reg_rule->ant_gain, reg_rule->reg_power,
flags);
reg_rule->psd_eirp, flags);
regd->reg_rules[i].dfs_cac_ms = ETSI_WEATHER_RADAR_BAND_CAC_TIMEOUT;
@ -688,7 +566,7 @@ ath12k_reg_update_weather_radar_band(struct ath12k_base *ab,
ath12k_reg_update_rule(regd->reg_rules + i, ETSI_WEATHER_RADAR_BAND_HIGH,
reg_rule->end_freq, bw,
reg_rule->ant_gain, reg_rule->reg_power,
flags);
reg_rule->psd_eirp, flags);
ath12k_dbg(ab, ATH12K_DBG_REG,
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n",
@ -710,26 +588,67 @@ static void ath12k_reg_update_freq_range(struct ath12k_reg_freq *reg_freq,
reg_freq->end_freq = reg_rule->end_freq;
}
enum wmi_reg_6g_ap_type
ath12k_reg_ap_pwr_convert(enum ieee80211_ap_reg_power power_type)
{
switch (power_type) {
case IEEE80211_REG_LPI_AP:
return WMI_REG_INDOOR_AP;
case IEEE80211_REG_SP_AP:
return WMI_REG_STD_POWER_AP;
case IEEE80211_REG_VLP_AP:
return WMI_REG_VLP_AP;
default:
return WMI_REG_MAX_AP_TYPE;
}
}
struct ieee80211_regdomain *
ath12k_reg_build_regd(struct ath12k_base *ab,
struct ath12k_reg_info *reg_info, bool intersect)
struct ath12k_reg_info *reg_info,
enum wmi_vdev_type vdev_type,
enum ieee80211_ap_reg_power power_type)
{
struct ieee80211_regdomain *tmp_regd, *default_regd, *new_regd = NULL;
struct ath12k_reg_rule *reg_rule;
struct ieee80211_regdomain *new_regd = NULL;
struct ath12k_reg_rule *reg_rule, *reg_rule_6ghz;
u32 flags, reg_6ghz_number, max_bw_6ghz;
u8 i = 0, j = 0, k = 0;
u8 num_rules;
u16 max_bw;
u32 flags;
char alpha2[3];
num_rules = reg_info->num_5g_reg_rules + reg_info->num_2g_reg_rules;
/* FIXME: Currently taking reg rules for 6G only from Indoor AP mode list.
* This can be updated to choose the combination dynamically based on AP
* type and client type, after complete 6G regulatory support is added.
*/
if (reg_info->is_ext_reg_event)
num_rules += reg_info->num_6g_reg_rules_ap[WMI_REG_INDOOR_AP];
if (reg_info->is_ext_reg_event) {
if (vdev_type == WMI_VDEV_TYPE_STA) {
enum wmi_reg_6g_ap_type ap_type;
ap_type = ath12k_reg_ap_pwr_convert(power_type);
if (ap_type == WMI_REG_MAX_AP_TYPE)
ap_type = WMI_REG_INDOOR_AP;
reg_6ghz_number = reg_info->num_6g_reg_rules_cl
[ap_type][WMI_REG_DEFAULT_CLIENT];
if (reg_6ghz_number == 0) {
ap_type = WMI_REG_INDOOR_AP;
reg_6ghz_number = reg_info->num_6g_reg_rules_cl
[ap_type][WMI_REG_DEFAULT_CLIENT];
}
reg_rule_6ghz = reg_info->reg_rules_6g_client_ptr
[ap_type][WMI_REG_DEFAULT_CLIENT];
max_bw_6ghz = reg_info->max_bw_6g_client
[ap_type][WMI_REG_DEFAULT_CLIENT];
} else {
reg_6ghz_number = reg_info->num_6g_reg_rules_ap
[WMI_REG_INDOOR_AP];
reg_rule_6ghz =
reg_info->reg_rules_6g_ap_ptr[WMI_REG_INDOOR_AP];
max_bw_6ghz = reg_info->max_bw_6g_ap[WMI_REG_INDOOR_AP];
}
num_rules += reg_6ghz_number;
}
if (!num_rules)
goto ret;
@ -738,20 +657,20 @@ ath12k_reg_build_regd(struct ath12k_base *ab,
if (reg_info->dfs_region == ATH12K_DFS_REG_ETSI)
num_rules += 2;
tmp_regd = kzalloc(sizeof(*tmp_regd) +
new_regd = kzalloc(sizeof(*new_regd) +
(num_rules * sizeof(struct ieee80211_reg_rule)),
GFP_ATOMIC);
if (!tmp_regd)
if (!new_regd)
goto ret;
memcpy(tmp_regd->alpha2, reg_info->alpha2, REG_ALPHA2_LEN + 1);
memcpy(new_regd->alpha2, reg_info->alpha2, REG_ALPHA2_LEN + 1);
memcpy(alpha2, reg_info->alpha2, REG_ALPHA2_LEN + 1);
alpha2[2] = '\0';
tmp_regd->dfs_region = ath12k_map_fw_dfs_region(reg_info->dfs_region);
new_regd->dfs_region = ath12k_map_fw_dfs_region(reg_info->dfs_region);
ath12k_dbg(ab, ATH12K_DBG_REG,
"\r\nCountry %s, CFG Regdomain %s FW Regdomain %d, num_reg_rules %d\n",
alpha2, ath12k_reg_get_regdom_str(tmp_regd->dfs_region),
alpha2, ath12k_reg_get_regdom_str(new_regd->dfs_region),
reg_info->dfs_region, num_rules);
/* Reset start and end frequency for each band
@ -788,13 +707,13 @@ ath12k_reg_build_regd(struct ath12k_base *ab,
*/
flags = NL80211_RRF_AUTO_BW;
ath12k_reg_update_freq_range(&ab->reg_freq_5ghz, reg_rule);
} else if (reg_info->is_ext_reg_event &&
reg_info->num_6g_reg_rules_ap[WMI_REG_INDOOR_AP] &&
(k < reg_info->num_6g_reg_rules_ap[WMI_REG_INDOOR_AP])) {
reg_rule = reg_info->reg_rules_6g_ap_ptr[WMI_REG_INDOOR_AP] + k++;
max_bw = min_t(u16, reg_rule->max_bw,
reg_info->max_bw_6g_ap[WMI_REG_INDOOR_AP]);
} else if (reg_info->is_ext_reg_event && reg_6ghz_number &&
(k < reg_6ghz_number)) {
reg_rule = reg_rule_6ghz + k++;
max_bw = min_t(u16, reg_rule->max_bw, max_bw_6ghz);
flags = NL80211_RRF_AUTO_BW;
if (reg_rule->psd_flag)
flags |= NL80211_RRF_PSD;
ath12k_reg_update_freq_range(&ab->reg_freq_6ghz, reg_rule);
} else {
break;
@ -803,11 +722,11 @@ ath12k_reg_build_regd(struct ath12k_base *ab,
flags |= ath12k_map_fw_reg_flags(reg_rule->flags);
flags |= ath12k_map_fw_phy_flags(reg_info->phybitmap);
ath12k_reg_update_rule(tmp_regd->reg_rules + i,
ath12k_reg_update_rule(new_regd->reg_rules + i,
reg_rule->start_freq,
reg_rule->end_freq, max_bw,
reg_rule->ant_gain, reg_rule->reg_power,
flags);
reg_rule->psd_eirp, flags);
/* Update dfs cac timeout if the dfs domain is ETSI and the
* new rule covers weather radar band.
@ -818,7 +737,7 @@ ath12k_reg_build_regd(struct ath12k_base *ab,
reg_info->dfs_region == ATH12K_DFS_REG_ETSI &&
(reg_rule->end_freq > ETSI_WEATHER_RADAR_BAND_LOW &&
reg_rule->start_freq < ETSI_WEATHER_RADAR_BAND_HIGH)){
ath12k_reg_update_weather_radar_band(ab, tmp_regd,
ath12k_reg_update_weather_radar_band(ab, new_regd,
reg_rule, &i,
flags, max_bw);
continue;
@ -828,36 +747,19 @@ ath12k_reg_build_regd(struct ath12k_base *ab,
ath12k_dbg(ab, ATH12K_DBG_REG, "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d) (%d, %d)\n",
i + 1, reg_rule->start_freq, reg_rule->end_freq,
max_bw, reg_rule->ant_gain, reg_rule->reg_power,
tmp_regd->reg_rules[i].dfs_cac_ms,
new_regd->reg_rules[i].dfs_cac_ms,
flags, reg_rule->psd_flag, reg_rule->psd_eirp);
} else {
ath12k_dbg(ab, ATH12K_DBG_REG,
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n",
i + 1, reg_rule->start_freq, reg_rule->end_freq,
max_bw, reg_rule->ant_gain, reg_rule->reg_power,
tmp_regd->reg_rules[i].dfs_cac_ms,
new_regd->reg_rules[i].dfs_cac_ms,
flags);
}
}
tmp_regd->n_reg_rules = i;
if (intersect) {
default_regd = ab->default_regd[reg_info->phy_id];
/* Get a new regd by intersecting the received regd with
* our default regd.
*/
new_regd = ath12k_regd_intersect(default_regd, tmp_regd);
kfree(tmp_regd);
if (!new_regd) {
ath12k_warn(ab, "Unable to create intersected regdomain\n");
goto ret;
}
} else {
new_regd = tmp_regd;
}
new_regd->n_reg_rules = i;
ret:
return new_regd;
}
@ -879,6 +781,105 @@ void ath12k_regd_update_work(struct work_struct *work)
}
}
void ath12k_reg_reset_reg_info(struct ath12k_reg_info *reg_info)
{
u8 i, j;
if (!reg_info)
return;
kfree(reg_info->reg_rules_2g_ptr);
kfree(reg_info->reg_rules_5g_ptr);
if (reg_info->is_ext_reg_event) {
for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) {
kfree(reg_info->reg_rules_6g_ap_ptr[i]);
for (j = 0; j < WMI_REG_MAX_CLIENT_TYPE; j++)
kfree(reg_info->reg_rules_6g_client_ptr[i][j]);
}
}
}
enum ath12k_reg_status ath12k_reg_validate_reg_info(struct ath12k_base *ab,
struct ath12k_reg_info *reg_info)
{
int pdev_idx = reg_info->phy_id;
if (reg_info->status_code != REG_SET_CC_STATUS_PASS) {
/* In case of failure to set the requested country,
* firmware retains the current regd. We print a failure info
* and return from here.
*/
ath12k_warn(ab, "Failed to set the requested Country regulatory setting\n");
return ATH12K_REG_STATUS_DROP;
}
if (pdev_idx >= ab->num_radios) {
/* Process the event for phy0 only if single_pdev_only
* is true. If pdev_idx is valid but not 0, discard the
* event. Otherwise, it goes to fallback.
*/
if (ab->hw_params->single_pdev_only &&
pdev_idx < ab->hw_params->num_rxdma_per_pdev)
return ATH12K_REG_STATUS_DROP;
else
return ATH12K_REG_STATUS_FALLBACK;
}
/* Avoid multiple overwrites to default regd, during core
* stop-start after mac registration.
*/
if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&
!memcmp(ab->default_regd[pdev_idx]->alpha2,
reg_info->alpha2, 2))
return ATH12K_REG_STATUS_DROP;
return ATH12K_REG_STATUS_VALID;
}
int ath12k_reg_handle_chan_list(struct ath12k_base *ab,
struct ath12k_reg_info *reg_info,
enum wmi_vdev_type vdev_type,
enum ieee80211_ap_reg_power power_type)
{
struct ieee80211_regdomain *regd = NULL;
int pdev_idx = reg_info->phy_id;
struct ath12k *ar;
regd = ath12k_reg_build_regd(ab, reg_info, vdev_type, power_type);
if (!regd)
return -EINVAL;
spin_lock_bh(&ab->base_lock);
if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) {
/* Once mac is registered, ar is valid and all CC events from
* firmware is considered to be received due to user requests
* currently.
* Free previously built regd before assigning the newly
* generated regd to ar. NULL pointer handling will be
* taken care by kfree itself.
*/
ar = ab->pdevs[pdev_idx].ar;
kfree(ab->new_regd[pdev_idx]);
ab->new_regd[pdev_idx] = regd;
queue_work(ab->workqueue, &ar->regd_update_work);
} else {
/* Multiple events for the same *ar is not expected. But we
* can still clear any previously stored default_regd if we
* are receiving this event for the same radio by mistake.
* NULL pointer handling will be taken care by kfree itself.
*/
kfree(ab->default_regd[pdev_idx]);
/* This regd would be applied during mac registration */
ab->default_regd[pdev_idx] = regd;
}
ab->dfs_region = reg_info->dfs_region;
spin_unlock_bh(&ab->base_lock);
return 0;
}
void ath12k_reg_init(struct ieee80211_hw *hw)
{
hw->wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED;
@ -891,6 +892,12 @@ void ath12k_reg_free(struct ath12k_base *ab)
int i;
mutex_lock(&ab->core_lock);
for (i = 0; i < MAX_RADIOS; i++) {
ath12k_reg_reset_reg_info(ab->reg_info[i]);
kfree(ab->reg_info[i]);
ab->reg_info[i] = NULL;
}
for (i = 0; i < ab->hw_params->max_radios; i++) {
kfree(ab->default_regd[i]);
kfree(ab->new_regd[i]);

@ -92,13 +92,29 @@ enum ath12k_reg_phy_bitmap {
ATH12K_REG_PHY_BITMAP_NO11BE = BIT(6),
};
enum ath12k_reg_status {
ATH12K_REG_STATUS_VALID,
ATH12K_REG_STATUS_DROP,
ATH12K_REG_STATUS_FALLBACK,
};
void ath12k_reg_init(struct ieee80211_hw *hw);
void ath12k_reg_free(struct ath12k_base *ab);
void ath12k_regd_update_work(struct work_struct *work);
struct ieee80211_regdomain *ath12k_reg_build_regd(struct ath12k_base *ab,
struct ath12k_reg_info *reg_info,
bool intersect);
enum wmi_vdev_type vdev_type,
enum ieee80211_ap_reg_power power_type);
int ath12k_regd_update(struct ath12k *ar, bool init);
int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait);
void ath12k_reg_reset_reg_info(struct ath12k_reg_info *reg_info);
int ath12k_reg_handle_chan_list(struct ath12k_base *ab,
struct ath12k_reg_info *reg_info,
enum wmi_vdev_type vdev_type,
enum ieee80211_ap_reg_power power_type);
enum wmi_reg_6g_ap_type
ath12k_reg_ap_pwr_convert(enum ieee80211_ap_reg_power power_type);
enum ath12k_reg_status ath12k_reg_validate_reg_info(struct ath12k_base *ab,
struct ath12k_reg_info *reg_info);
#endif

@ -2187,9 +2187,10 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
struct sk_buff *skb;
struct wmi_tlv *tlv;
void *ptr;
u32 peer_legacy_rates_align;
u32 peer_ht_rates_align;
u32 peer_legacy_rates_align, eml_pad_delay, eml_trans_delay;
u32 peer_ht_rates_align, eml_trans_timeout;
int i, ret, len;
u16 eml_cap;
__le32 v;
peer_legacy_rates_align = roundup(arg->peer_legacy_rates.num_rates,
@ -2361,6 +2362,24 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
ml_params->logical_link_idx = cpu_to_le32(arg->ml.logical_link_idx);
ml_params->ml_peer_id = cpu_to_le32(arg->ml.ml_peer_id);
ml_params->ieee_link_id = cpu_to_le32(arg->ml.ieee_link_id);
eml_cap = arg->ml.eml_cap;
if (u16_get_bits(eml_cap, IEEE80211_EML_CAP_EMLSR_SUPP)) {
/* Padding delay */
eml_pad_delay = ieee80211_emlsr_pad_delay_in_us(eml_cap);
ml_params->emlsr_padding_delay_us = cpu_to_le32(eml_pad_delay);
/* Transition delay */
eml_trans_delay = ieee80211_emlsr_trans_delay_in_us(eml_cap);
ml_params->emlsr_trans_delay_us = cpu_to_le32(eml_trans_delay);
/* Transition timeout */
eml_trans_timeout = ieee80211_eml_trans_timeout_in_us(eml_cap);
ml_params->emlsr_trans_timeout_us =
cpu_to_le32(eml_trans_timeout);
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi peer %pM emlsr padding delay %u, trans delay %u trans timeout %u",
arg->peer_mac, eml_pad_delay, eml_trans_delay,
eml_trans_timeout);
}
ptr += sizeof(*ml_params);
skip_ml_params:
@ -2380,6 +2399,10 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
ptr += sizeof(*eht_mcs);
}
/* Update MCS15 capability */
if (arg->eht_disable_mcs15)
cmd->peer_eht_ops = cpu_to_le32(IEEE80211_EHT_OPER_MCS15_DISABLE);
tlv = ptr;
len = arg->ml.enabled ? arg->ml.num_partner_links * sizeof(*partner_info) : 0;
/* fill ML Partner links */
@ -2420,7 +2443,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
send:
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
"wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x peer_flags_ext %x eht mac_cap %x %x eht phy_cap %x %x %x\n",
"wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x peer_flags_ext %x eht mac_cap %x %x eht phy_cap %x %x %x peer_eht_ops %x\n",
cmd->vdev_id, cmd->peer_associd, arg->peer_mac,
cmd->peer_flags, cmd->peer_rate_caps, cmd->peer_caps,
cmd->peer_listen_intval, cmd->peer_ht_caps,
@ -2433,7 +2456,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
cmd->peer_bw_rxnss_override, cmd->peer_flags_ext,
cmd->peer_eht_cap_mac[0], cmd->peer_eht_cap_mac[1],
cmd->peer_eht_cap_phy[0], cmd->peer_eht_cap_phy[1],
cmd->peer_eht_cap_phy[2]);
cmd->peer_eht_cap_phy[2], cmd->peer_eht_ops);
ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_ASSOC_CMDID);
if (ret) {
@ -4733,6 +4756,7 @@ static int ath12k_service_ready_ext_event(struct ath12k_base *ab,
return 0;
err:
kfree(svc_rdy_ext.mac_phy_caps);
ath12k_wmi_free_dbring_caps(ab);
return ret;
}
@ -6101,6 +6125,7 @@ static int ath12k_reg_11d_new_cc_event(struct ath12k_base *ab, struct sk_buff *s
pdev = &ab->pdevs[i];
ar = pdev->ar;
ar->state_11d = ATH12K_11D_IDLE;
ar->ah->regd_updated = false;
complete(&ar->completed_11d_scan);
}
@ -6115,24 +6140,11 @@ static void ath12k_wmi_htc_tx_complete(struct ath12k_base *ab,
dev_kfree_skb(skb);
}
static bool ath12k_reg_is_world_alpha(char *alpha)
{
if (alpha[0] == '0' && alpha[1] == '0')
return true;
if (alpha[0] == 'n' && alpha[1] == 'a')
return true;
return false;
}
static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *skb)
{
struct ath12k_reg_info *reg_info = NULL;
struct ieee80211_regdomain *regd = NULL;
bool intersect = false;
int ret = 0, pdev_idx, i, j;
struct ath12k *ar;
struct ath12k_reg_info *reg_info;
u8 pdev_idx;
int ret;
reg_info = kzalloc(sizeof(*reg_info), GFP_ATOMIC);
if (!reg_info) {
@ -6141,86 +6153,52 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
}
ret = ath12k_pull_reg_chan_list_ext_update_ev(ab, skb, reg_info);
if (ret) {
ath12k_warn(ab, "failed to extract regulatory info from received event\n");
goto fallback;
}
if (reg_info->status_code != REG_SET_CC_STATUS_PASS) {
/* In case of failure to set the requested ctry,
* fw retains the current regd. We print a failure info
* and return from here.
*/
ath12k_warn(ab, "Failed to set the requested Country regulatory setting\n");
goto mem_free;
}
ret = ath12k_reg_validate_reg_info(ab, reg_info);
if (ret == ATH12K_REG_STATUS_FALLBACK) {
ath12k_warn(ab, "failed to validate reg info %d\n", ret);
/* firmware has successfully switches to new regd but host can not
* continue, so free reginfo and fallback to old regd
*/
goto mem_free;
} else if (ret == ATH12K_REG_STATUS_DROP) {
/* reg info is valid but we will not store it and
* not going to create new regd for it
*/
ret = ATH12K_REG_STATUS_VALID;
goto mem_free;
}
/* free old reg_info if it exist */
pdev_idx = reg_info->phy_id;
if (pdev_idx >= ab->num_radios) {
/* Process the event for phy0 only if single_pdev_only
* is true. If pdev_idx is valid but not 0, discard the
* event. Otherwise, it goes to fallback.
*/
if (ab->hw_params->single_pdev_only &&
pdev_idx < ab->hw_params->num_rxdma_per_pdev)
goto mem_free;
else
goto fallback;
if (ab->reg_info[pdev_idx]) {
ath12k_reg_reset_reg_info(ab->reg_info[pdev_idx]);
kfree(ab->reg_info[pdev_idx]);
}
/* Avoid multiple overwrites to default regd, during core
* stop-start after mac registration.
/* reg_info is valid, we store it for later use
* even below regd build failed
*/
if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&
!memcmp(ab->default_regd[pdev_idx]->alpha2,
reg_info->alpha2, 2))
goto mem_free;
ab->reg_info[pdev_idx] = reg_info;
/* Intersect new rules with default regd if a new country setting was
* requested, i.e a default regd was already set during initialization
* and the regd coming from this event has a valid country info.
*/
if (ab->default_regd[pdev_idx] &&
!ath12k_reg_is_world_alpha((char *)
ab->default_regd[pdev_idx]->alpha2) &&
!ath12k_reg_is_world_alpha((char *)reg_info->alpha2))
intersect = true;
regd = ath12k_reg_build_regd(ab, reg_info, intersect);
if (!regd) {
ath12k_warn(ab, "failed to build regd from reg_info\n");
ret = ath12k_reg_handle_chan_list(ab, reg_info, WMI_VDEV_TYPE_UNSPEC,
IEEE80211_REG_UNSET_AP);
if (ret) {
ath12k_warn(ab, "failed to handle chan list %d\n", ret);
goto fallback;
}
spin_lock(&ab->base_lock);
if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) {
/* Once mac is registered, ar is valid and all CC events from
* fw is considered to be received due to user requests
* currently.
* Free previously built regd before assigning the newly
* generated regd to ar. NULL pointer handling will be
* taken care by kfree itself.
*/
ar = ab->pdevs[pdev_idx].ar;
kfree(ab->new_regd[pdev_idx]);
ab->new_regd[pdev_idx] = regd;
queue_work(ab->workqueue, &ar->regd_update_work);
} else {
/* Multiple events for the same *ar is not expected. But we
* can still clear any previously stored default_regd if we
* are receiving this event for the same radio by mistake.
* NULL pointer handling will be taken care by kfree itself.
*/
kfree(ab->default_regd[pdev_idx]);
/* This regd would be applied during mac registration */
ab->default_regd[pdev_idx] = regd;
}
ab->dfs_region = reg_info->dfs_region;
spin_unlock(&ab->base_lock);
goto out;
goto mem_free;
mem_free:
ath12k_reg_reset_reg_info(reg_info);
kfree(reg_info);
if (ret == ATH12K_REG_STATUS_VALID)
return ret;
fallback:
/* Fallback to older reg (by sending previous country setting
@ -6232,20 +6210,8 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
*/
/* TODO: This is rare, but still should also be handled */
WARN_ON(1);
mem_free:
if (reg_info) {
kfree(reg_info->reg_rules_2g_ptr);
kfree(reg_info->reg_rules_5g_ptr);
if (reg_info->is_ext_reg_event) {
for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++)
kfree(reg_info->reg_rules_6g_ap_ptr[i]);
for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++)
for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++)
kfree(reg_info->reg_rules_6g_client_ptr[j][i]);
}
kfree(reg_info);
}
out:
return ret;
}
@ -6401,13 +6367,14 @@ static void ath12k_vdev_start_resp_event(struct ath12k_base *ab, struct sk_buff
ar->last_wmi_vdev_start_status = 0;
status = le32_to_cpu(vdev_start_resp.status);
if (WARN_ON_ONCE(status)) {
ath12k_warn(ab, "vdev start resp error status %d (%s)\n",
status, ath12k_wmi_vdev_resp_print(status));
ar->last_wmi_vdev_start_status = status;
}
ar->max_allowed_tx_power = (s8)le32_to_cpu(vdev_start_resp.max_allowed_tx_power);
complete(&ar->vdev_setup_done);
rcu_read_unlock();
@ -9878,3 +9845,69 @@ int ath12k_wmi_mlo_teardown(struct ath12k *ar)
return 0;
}
bool ath12k_wmi_supports_6ghz_cc_ext(struct ath12k *ar)
{
return test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT,
ar->ab->wmi_ab.svc_map) && ar->supports_6ghz;
}
int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar,
u32 vdev_id,
struct ath12k_reg_tpc_power_info *param)
{
struct wmi_vdev_set_tpc_power_cmd *cmd;
struct ath12k_wmi_pdev *wmi = ar->wmi;
struct wmi_vdev_ch_power_params *ch;
int i, ret, len, array_len;
struct sk_buff *skb;
struct wmi_tlv *tlv;
u8 *ptr;
array_len = sizeof(*ch) * param->num_pwr_levels;
len = sizeof(*cmd) + TLV_HDR_SIZE + array_len;
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
ptr = skb->data;
cmd = (struct wmi_vdev_set_tpc_power_cmd *)ptr;
cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_SET_TPC_POWER_CMD,
sizeof(*cmd));
cmd->vdev_id = cpu_to_le32(vdev_id);
cmd->psd_power = cpu_to_le32(param->is_psd_power);
cmd->eirp_power = cpu_to_le32(param->eirp_power);
cmd->power_type_6ghz = cpu_to_le32(param->ap_power_type);
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
"tpc vdev id %d is psd power %d eirp power %d 6 ghz power type %d\n",
vdev_id, param->is_psd_power, param->eirp_power, param->ap_power_type);
ptr += sizeof(*cmd);
tlv = (struct wmi_tlv *)ptr;
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, array_len);
ptr += TLV_HDR_SIZE;
ch = (struct wmi_vdev_ch_power_params *)ptr;
for (i = 0; i < param->num_pwr_levels; i++, ch++) {
ch->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_CH_POWER_INFO,
sizeof(*ch));
ch->chan_cfreq = cpu_to_le32(param->chan_power_info[i].chan_cfreq);
ch->tx_power = cpu_to_le32(param->chan_power_info[i].tx_power);
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "tpc chan freq %d TX power %d\n",
ch->chan_cfreq, ch->tx_power);
}
ret = ath12k_wmi_cmd_send(wmi, skb, WMI_VDEV_SET_TPC_POWER_CMDID);
if (ret) {
ath12k_warn(ar->ab, "failed to send WMI_VDEV_SET_TPC_POWER_CMDID\n");
dev_kfree_skb(skb);
return ret;
}
return 0;
}

@ -26,6 +26,7 @@ struct ath12k_base;
struct ath12k;
struct ath12k_link_vif;
struct ath12k_fw_stats;
struct ath12k_reg_tpc_power_info;
/* There is no signed version of __le32, so for a temporary solution come
* up with our own version. The idea is from fs/ntfs/endian.h.
@ -386,6 +387,22 @@ enum wmi_tlv_cmd_id {
WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID,
WMI_VDEV_ENCRYPT_DECRYPT_DATA_REQ_CMDID,
WMI_VDEV_ADD_MAC_ADDR_TO_RX_FILTER_CMDID,
WMI_VDEV_SET_ARP_STAT_CMDID,
WMI_VDEV_GET_ARP_STAT_CMDID,
WMI_VDEV_GET_TX_POWER_CMDID,
WMI_VDEV_LIMIT_OFFCHAN_CMDID,
WMI_VDEV_SET_CUSTOM_SW_RETRY_TH_CMDID,
WMI_VDEV_CHAINMASK_CONFIG_CMDID,
WMI_VDEV_GET_BCN_RECEPTION_STATS_CMDID,
WMI_VDEV_GET_MWS_COEX_INFO_CMDID,
WMI_VDEV_DELETE_ALL_PEER_CMDID,
WMI_VDEV_BSS_MAX_IDLE_TIME_CMDID,
WMI_VDEV_AUDIO_SYNC_TRIGGER_CMDID,
WMI_VDEV_AUDIO_SYNC_QTIMER_CMDID,
WMI_VDEV_SET_PCL_CMDID,
WMI_VDEV_GET_BIG_DATA_CMDID,
WMI_VDEV_GET_BIG_DATA_P2_CMDID,
WMI_VDEV_SET_TPC_POWER_CMDID,
WMI_PEER_CREATE_CMDID = WMI_TLV_CMD(WMI_GRP_PEER),
WMI_PEER_DELETE_CMDID,
WMI_PEER_FLUSH_TIDS_CMDID,
@ -1955,6 +1972,8 @@ enum wmi_tlv_tag {
WMI_TAG_TPC_STATS_REG_PWR_ALLOWED,
WMI_TAG_TPC_STATS_RATES_ARRAY,
WMI_TAG_TPC_STATS_CTL_PWR_TABLE_EVENT,
WMI_TAG_VDEV_SET_TPC_POWER_CMD = 0x3B5,
WMI_TAG_VDEV_CH_POWER_INFO,
WMI_TAG_EHT_RATE_SET = 0x3C4,
WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5,
WMI_TAG_MLO_TX_SEND_PARAMS,
@ -2201,6 +2220,8 @@ enum wmi_tlv_service {
WMI_MAX_EXT_SERVICE = 256,
WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT = 280,
WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
WMI_TLV_SERVICE_11BE = 289,
@ -3755,6 +3776,7 @@ struct peer_assoc_mlo_params {
u32 ieee_link_id;
u8 num_partner_links;
struct wmi_ml_partner_info partner_info[ATH12K_WMI_MLO_MAX_LINKS];
u16 eml_cap;
};
struct wmi_rate_set_arg {
@ -3833,6 +3855,7 @@ struct ath12k_wmi_peer_assoc_arg {
u32 punct_bitmap;
bool is_assoc;
struct peer_assoc_mlo_params ml;
bool eht_disable_mcs15;
};
#define ATH12K_WMI_FLAG_MLO_ENABLED BIT(0)
@ -4162,6 +4185,7 @@ struct wmi_vdev_start_resp_event {
};
__le32 cfgd_tx_streams;
__le32 cfgd_rx_streams;
__le32 max_allowed_tx_power;
} __packed;
/* VDEV start response status codes */
@ -4507,6 +4531,7 @@ struct ath12k_wmi_target_cap_arg {
};
enum wmi_vdev_type {
WMI_VDEV_TYPE_UNSPEC = 0,
WMI_VDEV_TYPE_AP = 1,
WMI_VDEV_TYPE_STA = 2,
WMI_VDEV_TYPE_IBSS = 3,
@ -5937,6 +5962,41 @@ struct wmi_tpc_stats_arg {
struct wmi_tpc_ctl_pwr_table_arg ctl_array;
};
struct wmi_vdev_ch_power_params {
__le32 tlv_header;
/* Channel center frequency (MHz) */
__le32 chan_cfreq;
/* Unit: dBm, either PSD/EIRP power for this frequency or
* incremental for non-PSD BW
*/
__le32 tx_power;
} __packed;
struct wmi_vdev_set_tpc_power_cmd {
__le32 tlv_header;
__le32 vdev_id;
/* Value: 0 or 1, is PSD power or not */
__le32 psd_power;
/* Maximum EIRP power (dBm units), valid only if power is PSD */
__le32 eirp_power;
/* Type: WMI_6GHZ_REG_TYPE, used for halphy CTL lookup */
__le32 power_type_6ghz;
/* This fixed_param TLV is followed by the below TLVs:
* num_pwr_levels of wmi_vdev_ch_power_info
* For PSD power, it is the PSD/EIRP power of the frequency (20 MHz chunks).
* For non-PSD power, the power values are for 20, 40, and till
* BSS BW power levels.
* The num_pwr_levels will be checked by sw how many elements present
* in the variable-length array.
*/
} __packed;
void ath12k_wmi_init_qcn9274(struct ath12k_base *ab,
struct ath12k_wmi_resource_config_arg *config);
void ath12k_wmi_init_wcn7850(struct ath12k_base *ab,
@ -6131,5 +6191,9 @@ int ath12k_wmi_mlo_teardown(struct ath12k *ar);
void ath12k_wmi_fw_stats_dump(struct ath12k *ar,
struct ath12k_fw_stats *fw_stats, u32 stats_id,
char *buf);
bool ath12k_wmi_supports_6ghz_cc_ext(struct ath12k *ar);
int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar,
u32 vdev_id,
struct ath12k_reg_tpc_power_info *param);
#endif

@ -74,7 +74,6 @@ static int ath_ahb_probe(struct platform_device *pdev)
void __iomem *mem;
struct ath_softc *sc;
struct ieee80211_hw *hw;
struct resource *res;
const struct platform_device_id *id = platform_get_device_id(pdev);
int irq;
int ret = 0;
@ -86,16 +85,10 @@ static int ath_ahb_probe(struct platform_device *pdev)
return -EINVAL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&pdev->dev, "no memory resource found\n");
return -ENXIO;
}
mem = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (mem == NULL) {
mem = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mem)) {
dev_err(&pdev->dev, "ioremap failed\n");
return -ENOMEM;
return PTR_ERR(mem);
}
irq = platform_get_irq(pdev, 0);

@ -290,6 +290,9 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv,
struct ath_common *common = ath9k_hw_common(priv->ah);
int slot;
if (!priv->cur_beacon_conf.enable_beacon)
return;
if (swba->beacon_pending != 0) {
priv->beacon.bmisscnt++;
if (priv->beacon.bmisscnt > BSTUCK_THRESHOLD) {

@ -366,8 +366,7 @@ static void carl9170_tx_shift_bm(struct ar9170 *ar,
if (WARN_ON_ONCE(off >= CARL9170_BAW_BITS))
return;
if (!bitmap_empty(tid_info->bitmap, off))
off = find_first_bit(tid_info->bitmap, off);
off = min(off, find_first_bit(tid_info->bitmap, off));
tid_info->bsn += off;
tid_info->bsn &= 0x0fff;

@ -617,8 +617,7 @@ static inline bool wil_need_txstat(struct sk_buff *skb)
{
const u8 *da = wil_skb_get_da(skb);
return is_unicast_ether_addr(da) && skb->sk &&
sock_flag(skb->sk, SOCK_WIFI_STATUS);
return is_unicast_ether_addr(da) && sk_requests_wifi_status(skb->sk);
}
static inline void wil_consume_skb(struct sk_buff *skb, bool acked)

@ -74,7 +74,6 @@
#define VNDR_IE_HDR_SIZE 12
#define VNDR_IE_PARSE_LIMIT 5
#define DOT11_MGMT_HDR_LEN 24 /* d11 management header len */
#define DOT11_BCN_PRB_FIXED_LEN 12 /* beacon/probe fixed length */
#define BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS 320
@ -1945,17 +1944,22 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_cfg80211_security *sec;
s32 val = 0;
s32 err = 0;
s32 val;
s32 err;
if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) {
val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3)
} else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {
if (drvr->bus_if->fwvid == BRCMF_FWVENDOR_CYW &&
sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_SAE)
val = WPA3_AUTH_SAE_PSK;
else
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
} else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3) {
val = WPA3_AUTH_SAE_PSK;
else
} else {
val = WPA_AUTH_DISABLED;
}
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", val);
if (err) {
@ -2163,28 +2167,25 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
switch (sme->crypto.akm_suites[0]) {
case WLAN_AKM_SUITE_SAE:
val = WPA3_AUTH_SAE_PSK;
if (sme->crypto.sae_pwd) {
brcmf_dbg(INFO, "using SAE offload\n");
profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE;
}
break;
case WLAN_AKM_SUITE_FT_OVER_SAE:
val = WPA3_AUTH_SAE_PSK | WPA2_AUTH_FT;
profile->is_ft = true;
if (sme->crypto.sae_pwd) {
brcmf_dbg(INFO, "using SAE offload\n");
profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE;
}
break;
default:
bphy_err(drvr, "invalid akm suite (%d)\n",
sme->crypto.akm_suites[0]);
return -EINVAL;
}
if (sme->crypto.sae_pwd) {
profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE;
}
}
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X)
brcmf_dbg(INFO, "using 1X offload\n");
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE)
brcmf_dbg(INFO, "using SAE offload\n");
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
goto skip_mfp_config;
@ -2221,7 +2222,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "mfp", mfp);
skip_mfp_config:
brcmf_dbg(CONN, "setting wpa_auth to %d\n", val);
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);
if (err) {
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
@ -5509,7 +5510,7 @@ brcmf_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
}
static int
int
brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct cfg80211_mgmt_tx_params *params, u64 *cookie)
{
@ -5616,6 +5617,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
exit:
return err;
}
BRCMF_EXPORT_SYMBOL_GPL(brcmf_cfg80211_mgmt_tx);
static int brcmf_cfg80211_set_cqm_rssi_range_config(struct wiphy *wiphy,
struct net_device *ndev,
@ -6009,6 +6011,7 @@ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
vif->wdev.wiphy = cfg->wiphy;
vif->wdev.iftype = type;
init_completion(&vif->mgmt_tx);
brcmf_init_prof(&vif->profile);
@ -6760,6 +6763,8 @@ static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
brcmf_fweh_register(cfg->pub, BRCMF_E_PSK_SUP,
brcmf_notify_connect_status);
brcmf_fweh_register(cfg->pub, BRCMF_E_RSSI, brcmf_notify_rssi);
brcmf_fwvid_register_event_handlers(cfg->pub);
}
static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
@ -7346,6 +7351,7 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
[NL80211_IFTYPE_STATION] = {
.tx = 0xffff,
.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
BIT(IEEE80211_STYPE_AUTH >> 4) |
BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
},
[NL80211_IFTYPE_P2P_CLIENT] = {
@ -7653,6 +7659,8 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
wiphy_ext_feature_set(wiphy,
NL80211_EXT_FEATURE_SAE_OFFLOAD_AP);
}
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SAE_EXT))
wiphy->features |= NL80211_FEATURE_SAE;
wiphy->mgmt_stypes = brcmf_txrx_stypes;
wiphy->max_remain_on_channel_duration = 5000;
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {

@ -13,6 +13,8 @@
#include "fwil_types.h"
#include "p2p.h"
#define DOT11_MGMT_HDR_LEN 24 /* d11 management header len */
#define BRCMF_SCAN_IE_LEN_MAX 2048
#define WL_NUM_SCAN_MAX 10
@ -141,6 +143,21 @@ enum brcmf_profile_fwauth {
BRCMF_PROFILE_FWAUTH_SAE
};
/**
* enum brcmf_mgmt_tx_status - mgmt frame tx status
*
* @BRCMF_MGMT_TX_ACK: mgmt frame acked
* @BRCMF_MGMT_TX_NOACK: mgmt frame not acked
* @BRCMF_MGMT_TX_OFF_CHAN_COMPLETED: off-channel complete
* @BRCMF_MGMT_TX_SEND_FRAME: mgmt frame tx is in progres
*/
enum brcmf_mgmt_tx_status {
BRCMF_MGMT_TX_ACK,
BRCMF_MGMT_TX_NOACK,
BRCMF_MGMT_TX_OFF_CHAN_COMPLETED,
BRCMF_MGMT_TX_SEND_FRAME
};
/**
* struct brcmf_cfg80211_profile - profile information.
*
@ -211,6 +228,9 @@ struct vif_saved_ie {
* @profile: profile information.
* @sme_state: SME state using enum brcmf_vif_status bits.
* @list: linked list.
* @mgmt_tx: completion for management frame transmit.
* @mgmt_tx_status: status of last management frame sent to firmware.
* @mgmt_tx_id:
* @mgmt_rx_reg: registered rx mgmt frame types.
* @mbss: Multiple BSS type, set if not first AP (not relevant for P2P).
* @cqm_rssi_low: Lower RSSI limit for CQM monitoring
@ -224,6 +244,9 @@ struct brcmf_cfg80211_vif {
unsigned long sme_state;
struct vif_saved_ie saved_ie;
struct list_head list;
struct completion mgmt_tx;
unsigned long mgmt_tx_status;
u32 mgmt_tx_id;
u16 mgmt_rx_reg;
bool mbss;
int is_11d;
@ -468,5 +491,7 @@ void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
void brcmf_cfg80211_free_netdev(struct net_device *ndev);
int brcmf_set_wsec(struct brcmf_if *ifp, const u8 *key, u16 key_len, u16 flags);
int brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct cfg80211_mgmt_tx_params *params, u64 *cookie);
#endif /* BRCMFMAC_CFG80211_H */

@ -491,6 +491,7 @@ void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)
trace_brcmf_dbg(level, func, &vaf);
va_end(args);
}
BRCMF_EXPORT_SYMBOL_GPL(__brcmf_dbg);
#endif
static void brcmf_mp_attach(void)

@ -1363,6 +1363,8 @@ int brcmf_attach(struct device *dev)
brcmf_fweh_register(drvr, BRCMF_E_PSM_WATCHDOG,
brcmf_psm_watchdog_notify);
brcmf_fwvid_get_cfg80211_ops(drvr);
ret = brcmf_bus_started(drvr, drvr->ops);
if (ret != 0) {
bphy_err(drvr, "dongle is not responding: err=%d\n", ret);

@ -8,11 +8,21 @@
#include <bus.h>
#include <fwvid.h>
#include <fwil.h>
#include <fweh.h>
#include "vops.h"
#include "fwil_types.h"
/* event definitions */
#define BRCMF_CYW_E_EXT_AUTH_REQ 187
#define BRCMF_CYW_E_EXT_AUTH_FRAME_RX 188
#define BRCMF_CYW_E_MGMT_FRAME_TXS 189
#define BRCMF_CYW_E_MGMT_FRAME_TXS_OC 190
#define BRCMF_CYW_E_LAST 197
#define MGMT_AUTH_FRAME_DWELL_TIME 4000
#define MGMT_AUTH_FRAME_WAIT_TIME (MGMT_AUTH_FRAME_DWELL_TIME + 100)
static int brcmf_cyw_set_sae_pwd(struct brcmf_if *ifp,
struct cfg80211_crypto_settings *crypto)
{
@ -39,6 +49,19 @@ static int brcmf_cyw_set_sae_pwd(struct brcmf_if *ifp,
return err;
}
static const struct brcmf_fweh_event_map brcmf_cyw_event_map = {
.items = {
{ BRCMF_E_EXT_AUTH_REQ, BRCMF_CYW_E_EXT_AUTH_REQ },
{ BRCMF_E_EXT_AUTH_FRAME_RX, BRCMF_CYW_E_EXT_AUTH_FRAME_RX },
{ BRCMF_E_MGMT_FRAME_TXSTATUS, BRCMF_CYW_E_MGMT_FRAME_TXS },
{
BRCMF_E_MGMT_FRAME_OFFCHAN_DONE,
BRCMF_CYW_E_MGMT_FRAME_TXS_OC
},
},
.n_items = 4
};
static int brcmf_cyw_alloc_fweh_info(struct brcmf_pub *drvr)
{
struct brcmf_fweh_info *fweh;
@ -49,11 +72,296 @@ static int brcmf_cyw_alloc_fweh_info(struct brcmf_pub *drvr)
return -ENOMEM;
fweh->num_event_codes = BRCMF_CYW_E_LAST;
fweh->event_map = &brcmf_cyw_event_map;
drvr->fweh = fweh;
return 0;
}
static int brcmf_cyw_activate_events(struct brcmf_if *ifp)
{
struct brcmf_fweh_info *fweh = ifp->drvr->fweh;
struct brcmf_eventmsgs_ext *eventmask_msg;
u32 msglen;
int err;
msglen = sizeof(*eventmask_msg) + fweh->event_mask_len;
eventmask_msg = kzalloc(msglen, GFP_KERNEL);
if (!eventmask_msg)
return -ENOMEM;
eventmask_msg->ver = EVENTMSGS_VER;
eventmask_msg->command = CYW_EVENTMSGS_SET_MASK;
eventmask_msg->len = fweh->event_mask_len;
memcpy(eventmask_msg->mask, fweh->event_mask, fweh->event_mask_len);
err = brcmf_fil_iovar_data_set(ifp, "event_msgs_ext", eventmask_msg,
msglen);
kfree(eventmask_msg);
return err;
}
static
int brcmf_cyw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct cfg80211_mgmt_tx_params *params, u64 *cookie)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct ieee80211_channel *chan = params->chan;
struct brcmf_pub *drvr = cfg->pub;
const u8 *buf = params->buf;
size_t len = params->len;
const struct ieee80211_mgmt *mgmt;
struct brcmf_cfg80211_vif *vif;
s32 err = 0;
bool ack = false;
s32 chan_nr;
u32 freq;
struct brcmf_mf_params_le *mf_params;
u32 mf_params_len;
s32 ready;
brcmf_dbg(TRACE, "Enter\n");
mgmt = (const struct ieee80211_mgmt *)buf;
if (!ieee80211_is_auth(mgmt->frame_control))
return brcmf_cfg80211_mgmt_tx(wiphy, wdev, params, cookie);
*cookie = 0;
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
reinit_completion(&vif->mgmt_tx);
clear_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status);
clear_bit(BRCMF_MGMT_TX_NOACK, &vif->mgmt_tx_status);
clear_bit(BRCMF_MGMT_TX_OFF_CHAN_COMPLETED,
&vif->mgmt_tx_status);
mf_params_len = offsetof(struct brcmf_mf_params_le, data) +
(len - DOT11_MGMT_HDR_LEN);
mf_params = kzalloc(mf_params_len, GFP_KERNEL);
if (!mf_params)
return -ENOMEM;
mf_params->dwell_time = cpu_to_le32(MGMT_AUTH_FRAME_DWELL_TIME);
mf_params->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN);
mf_params->frame_control = mgmt->frame_control;
if (chan)
freq = chan->center_freq;
else
brcmf_fil_cmd_int_get(vif->ifp, BRCMF_C_GET_CHANNEL,
&freq);
chan_nr = ieee80211_frequency_to_channel(freq);
mf_params->channel = cpu_to_le16(chan_nr);
memcpy(&mf_params->da[0], &mgmt->da[0], ETH_ALEN);
memcpy(&mf_params->bssid[0], &mgmt->bssid[0], ETH_ALEN);
mf_params->packet_id = cpu_to_le32(*cookie);
memcpy(mf_params->data, &buf[DOT11_MGMT_HDR_LEN],
le16_to_cpu(mf_params->len));
brcmf_dbg(TRACE, "Auth frame, cookie=%d, fc=%04x, len=%d, channel=%d\n",
le32_to_cpu(mf_params->packet_id),
le16_to_cpu(mf_params->frame_control),
le16_to_cpu(mf_params->len), chan_nr);
vif->mgmt_tx_id = le32_to_cpu(mf_params->packet_id);
set_bit(BRCMF_MGMT_TX_SEND_FRAME, &vif->mgmt_tx_status);
err = brcmf_fil_bsscfg_data_set(vif->ifp, "mgmt_frame",
mf_params, mf_params_len);
if (err) {
bphy_err(drvr, "Failed to send Auth frame: err=%d\n",
err);
goto tx_status;
}
ready = wait_for_completion_timeout(&vif->mgmt_tx,
MGMT_AUTH_FRAME_WAIT_TIME);
if (test_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status)) {
brcmf_dbg(TRACE, "TX Auth frame operation is success\n");
ack = true;
} else {
bphy_err(drvr, "TX Auth frame operation is %s: status=%ld)\n",
ready ? "failed" : "timedout", vif->mgmt_tx_status);
}
tx_status:
cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack,
GFP_KERNEL);
kfree(mf_params);
return err;
}
static int
brcmf_cyw_external_auth(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_external_auth_params *params)
{
struct brcmf_if *ifp;
struct brcmf_pub *drvr;
struct brcmf_auth_req_status_le auth_status;
int ret = 0;
brcmf_dbg(TRACE, "Enter\n");
ifp = netdev_priv(dev);
drvr = ifp->drvr;
if (params->status == WLAN_STATUS_SUCCESS) {
auth_status.flags = cpu_to_le16(BRCMF_EXTAUTH_SUCCESS);
} else {
bphy_err(drvr, "External authentication failed: status=%d\n",
params->status);
auth_status.flags = cpu_to_le16(BRCMF_EXTAUTH_FAIL);
}
memcpy(auth_status.peer_mac, params->bssid, ETH_ALEN);
params->ssid.ssid_len = min_t(u8, params->ssid.ssid_len,
IEEE80211_MAX_SSID_LEN);
auth_status.ssid_len = cpu_to_le32(params->ssid.ssid_len);
memcpy(auth_status.ssid, params->ssid.ssid, params->ssid.ssid_len);
ret = brcmf_fil_iovar_data_set(ifp, "auth_status", &auth_status,
sizeof(auth_status));
if (ret < 0)
bphy_err(drvr, "auth_status iovar failed: ret=%d\n", ret);
return ret;
}
static void brcmf_cyw_get_cfg80211_ops(struct brcmf_pub *drvr)
{
drvr->ops->mgmt_tx = brcmf_cyw_mgmt_tx;
drvr->ops->external_auth = brcmf_cyw_external_auth;
}
static s32
brcmf_cyw_notify_ext_auth_req(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
struct brcmf_pub *drvr = ifp->drvr;
struct cfg80211_external_auth_params params;
struct brcmf_auth_req_status_le *auth_req =
(struct brcmf_auth_req_status_le *)data;
s32 err = 0;
brcmf_dbg(INFO, "Enter: event %s (%d) received\n",
brcmf_fweh_event_name(e->event_code), e->event_code);
if (e->datalen < sizeof(*auth_req)) {
bphy_err(drvr, "Event %s (%d) data too small. Ignore\n",
brcmf_fweh_event_name(e->event_code), e->event_code);
return -EINVAL;
}
memset(&params, 0, sizeof(params));
params.action = NL80211_EXTERNAL_AUTH_START;
params.key_mgmt_suite = WLAN_AKM_SUITE_SAE;
params.status = WLAN_STATUS_SUCCESS;
params.ssid.ssid_len = min_t(u32, 32, le32_to_cpu(auth_req->ssid_len));
memcpy(params.ssid.ssid, auth_req->ssid, params.ssid.ssid_len);
memcpy(params.bssid, auth_req->peer_mac, ETH_ALEN);
err = cfg80211_external_auth_request(ifp->ndev, &params, GFP_KERNEL);
if (err)
bphy_err(drvr, "Ext Auth request to supplicant failed (%d)\n",
err);
return err;
}
static s32
brcmf_notify_auth_frame_rx(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_cfg80211_info *cfg = drvr->config;
struct wireless_dev *wdev;
u32 mgmt_frame_len = e->datalen - sizeof(struct brcmf_rx_mgmt_data);
struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
u8 *frame = (u8 *)(rxframe + 1);
struct brcmu_chan ch;
struct ieee80211_mgmt *mgmt_frame;
s32 freq;
brcmf_dbg(INFO, "Enter: event %s (%d) received\n",
brcmf_fweh_event_name(e->event_code), e->event_code);
if (e->datalen < sizeof(*rxframe)) {
bphy_err(drvr, "Event %s (%d) data too small. Ignore\n",
brcmf_fweh_event_name(e->event_code), e->event_code);
return -EINVAL;
}
wdev = &ifp->vif->wdev;
WARN_ON(!wdev);
ch.chspec = be16_to_cpu(rxframe->chanspec);
cfg->d11inf.decchspec(&ch);
mgmt_frame = kzalloc(mgmt_frame_len, GFP_KERNEL);
if (!mgmt_frame)
return -ENOMEM;
mgmt_frame->frame_control = cpu_to_le16(IEEE80211_STYPE_AUTH);
memcpy(mgmt_frame->da, ifp->mac_addr, ETH_ALEN);
memcpy(mgmt_frame->sa, e->addr, ETH_ALEN);
brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSSID, mgmt_frame->bssid,
ETH_ALEN);
frame += offsetof(struct ieee80211_mgmt, u);
memcpy(&mgmt_frame->u, frame,
mgmt_frame_len - offsetof(struct ieee80211_mgmt, u));
freq = ieee80211_channel_to_frequency(ch.control_ch_num,
ch.band == BRCMU_CHAN_BAND_2G ?
NL80211_BAND_2GHZ :
NL80211_BAND_5GHZ);
cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len,
NL80211_RXMGMT_FLAG_EXTERNAL_AUTH);
kfree(mgmt_frame);
return 0;
}
static s32
brcmf_notify_mgmt_tx_status(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
struct brcmf_cfg80211_vif *vif = ifp->vif;
u32 *packet_id = (u32 *)data;
brcmf_dbg(INFO, "Enter: event %s (%d), status=%d\n",
brcmf_fweh_event_name(e->event_code), e->event_code,
e->status);
if (!test_bit(BRCMF_MGMT_TX_SEND_FRAME, &vif->mgmt_tx_status) ||
(*packet_id != vif->mgmt_tx_id))
return 0;
if (e->event_code == BRCMF_E_MGMT_FRAME_TXSTATUS) {
if (e->status == BRCMF_E_STATUS_SUCCESS)
set_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status);
else
set_bit(BRCMF_MGMT_TX_NOACK, &vif->mgmt_tx_status);
} else {
set_bit(BRCMF_MGMT_TX_OFF_CHAN_COMPLETED, &vif->mgmt_tx_status);
}
complete(&vif->mgmt_tx);
return 0;
}
static void brcmf_cyw_register_event_handlers(struct brcmf_pub *drvr)
{
brcmf_fweh_register(drvr, BRCMF_E_EXT_AUTH_REQ,
brcmf_cyw_notify_ext_auth_req);
brcmf_fweh_register(drvr, BRCMF_E_EXT_AUTH_FRAME_RX,
brcmf_notify_auth_frame_rx);
brcmf_fweh_register(drvr, BRCMF_E_MGMT_FRAME_TXSTATUS,
brcmf_notify_mgmt_tx_status);
brcmf_fweh_register(drvr, BRCMF_E_MGMT_FRAME_OFFCHAN_DONE,
brcmf_notify_mgmt_tx_status);
}
const struct brcmf_fwvid_ops brcmf_cyw_ops = {
.set_sae_password = brcmf_cyw_set_sae_pwd,
.alloc_fweh_info = brcmf_cyw_alloc_fweh_info,
.activate_events = brcmf_cyw_activate_events,
.get_cfg80211_ops = brcmf_cyw_get_cfg80211_ops,
.register_event_handlers = brcmf_cyw_register_event_handlers,
};

@ -0,0 +1,87 @@
// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2012 Broadcom Corporation
*/
#ifndef CYW_FWIL_TYPES_H_
#define CYW_FWIL_TYPES_H_
#include <fwil_types.h>
enum brcmf_event_msgs_ext_command {
CYW_EVENTMSGS_NONE = 0,
CYW_EVENTMSGS_SET_BIT = 1,
CYW_EVENTMSGS_RESET_BIT = 2,
CYW_EVENTMSGS_SET_MASK = 3,
};
#define EVENTMSGS_VER 1
#define EVENTMSGS_EXT_STRUCT_SIZE offsetof(struct eventmsgs_ext, mask[0])
/**
* struct brcmf_eventmsgs_ext - structure used with "eventmsgs_ext" iovar.
*
* @ver: version.
* @command: requested operation (see &enum event_msgs_ext_command).
* @len: length of the @mask array.
* @maxgetsize: indicates maximum mask size that may be returned by firmware
* upon iovar GET.
* @mask: array where each bit represents firmware event.
*/
struct brcmf_eventmsgs_ext {
u8 ver;
u8 command;
u8 len;
u8 maxgetsize;
u8 mask[] __counted_by(len);
};
#define BRCMF_EXTAUTH_START 1
#define BRCMF_EXTAUTH_ABORT 2
#define BRCMF_EXTAUTH_FAIL 3
#define BRCMF_EXTAUTH_SUCCESS 4
/**
* struct brcmf_auth_req_status_le - external auth request and status update
*
* @flags: flags for external auth status
* @peer_mac: peer MAC address
* @ssid_len: length of ssid
* @ssid: ssid characters
* @pmkid: PMKSA identifier
*/
struct brcmf_auth_req_status_le {
__le16 flags;
u8 peer_mac[ETH_ALEN];
__le32 ssid_len;
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 pmkid[WLAN_PMKID_LEN];
};
/**
* struct brcmf_mf_params_le - management frame parameters for mgmt_frame iovar
*
* @version: version of the iovar
* @dwell_time: dwell duration in ms
* @len: length of frame data
* @frame_control: frame control
* @channel: channel
* @da: peer MAC address
* @bssid: BSS network identifier
* @packet_id: packet identifier
* @data: frame data
*/
struct brcmf_mf_params_le {
__le32 version;
__le32 dwell_time;
__le16 len;
__le16 frame_control;
__le16 channel;
u8 da[ETH_ALEN];
u8 bssid[ETH_ALEN];
__le32 packet_id;
u8 data[] __counted_by(len);
};
#endif /* CYW_FWIL_TYPES_H_ */

@ -42,8 +42,9 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
{ BRCMF_FEAT_MONITOR_FLAG, "rtap" },
{ BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" },
{ BRCMF_FEAT_DOT11H, "802.11h" },
{ BRCMF_FEAT_SAE, "sae" },
{ BRCMF_FEAT_SAE, "sae " },
{ BRCMF_FEAT_FWAUTH, "idauth" },
{ BRCMF_FEAT_SAE_EXT, "sae_ext" },
};
#ifdef DEBUG

@ -31,6 +31,7 @@
* FWAUTH: Firmware authenticator
* DUMP_OBSS: Firmware has capable to dump obss info to support ACS
* SCAN_V2: Version 2 scan params
* SAE_EXT: SAE authentication handled by user-space supplicant
*/
#define BRCMF_FEAT_LIST \
BRCMF_FEAT_DEF(MBSS) \
@ -57,7 +58,8 @@
BRCMF_FEAT_DEF(DUMP_OBSS) \
BRCMF_FEAT_DEF(SCAN_V2) \
BRCMF_FEAT_DEF(PMKID_V2) \
BRCMF_FEAT_DEF(PMKID_V3)
BRCMF_FEAT_DEF(PMKID_V3) \
BRCMF_FEAT_DEF(SAE_EXT)
/*
* Quirks:

@ -75,6 +75,7 @@ const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
return "nodebug";
}
#endif
BRCMF_EXPORT_SYMBOL_GPL(brcmf_fweh_event_name);
/**
* brcmf_fweh_queue_event() - create and queue event.
@ -405,6 +406,7 @@ int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
brcmf_fweh_event_name(code));
return 0;
}
BRCMF_EXPORT_SYMBOL_GPL(brcmf_fweh_register);
/**
* brcmf_fweh_unregister() - remove handler for given code.
@ -448,11 +450,14 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp)
brcmf_dbg(EVENT, "enable event IF\n");
setbit(fweh->event_mask, BRCMF_E_IF);
/* allow per-vendor method to activate firmware events */
if (!brcmf_fwvid_activate_events(ifp))
return 0;
err = brcmf_fil_iovar_data_set(ifp, "event_msgs", fweh->event_mask,
fweh->event_mask_len);
if (err)
bphy_err(fweh->drvr, "Set event_msgs error (%d)\n", err);
return err;
}

@ -94,7 +94,11 @@ struct brcmf_cfg80211_info;
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \
BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \
BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127)
BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \
BRCMF_ABSTRACT_ENUM_DEF(EXT_AUTH_REQ, 0) \
BRCMF_ABSTRACT_ENUM_DEF(EXT_AUTH_FRAME_RX, 1) \
BRCMF_ABSTRACT_ENUM_DEF(MGMT_FRAME_TXSTATUS, 2) \
BRCMF_ABSTRACT_ENUM_DEF(MGMT_FRAME_OFFCHAN_DONE, 3)
#define BRCMF_ENUM_DEF(id, val) \
BRCMF_E_##id = (val),
@ -337,7 +341,7 @@ struct brcmf_fweh_info {
struct list_head event_q;
uint event_mask_len;
u8 *event_mask;
struct brcmf_fweh_event_map *event_map;
const struct brcmf_fweh_event_map *event_map;
uint num_event_codes;
brcmf_fweh_handler_t evt_handler[] __counted_by(num_event_codes);
};

@ -15,6 +15,9 @@ struct brcmf_fwvid_ops {
void (*feat_attach)(struct brcmf_if *ifp);
int (*set_sae_password)(struct brcmf_if *ifp, struct cfg80211_crypto_settings *crypto);
int (*alloc_fweh_info)(struct brcmf_pub *drvr);
int (*activate_events)(struct brcmf_if *ifp);
void (*get_cfg80211_ops)(struct brcmf_pub *drvr);
void (*register_event_handlers)(struct brcmf_pub *drvr);
};
/* exported functions */
@ -56,4 +59,30 @@ static inline int brcmf_fwvid_alloc_fweh_info(struct brcmf_pub *drvr)
return drvr->vops->alloc_fweh_info(drvr);
}
static inline int brcmf_fwvid_activate_events(struct brcmf_if *ifp)
{
const struct brcmf_fwvid_ops *vops = ifp->drvr->vops;
if (!vops || !vops->activate_events)
return -EOPNOTSUPP;
return vops->activate_events(ifp);
}
static inline void brcmf_fwvid_get_cfg80211_ops(struct brcmf_pub *drvr)
{
if (!drvr->vops || !drvr->vops->get_cfg80211_ops)
return;
drvr->vops->get_cfg80211_ops(drvr);
}
static inline void brcmf_fwvid_register_event_handlers(struct brcmf_pub *drvr)
{
if (!drvr->vops || !drvr->vops->register_event_handlers)
return;
drvr->vops->register_event_handlers(drvr);
}
#endif /* FWVID_H_ */

@ -8,12 +8,23 @@ iwlwifi-objs += iwl-nvm-utils.o
iwlwifi-objs += iwl-utils.o
iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-gen3.o
iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o
iwlwifi-objs += pcie/trans-gen2.o pcie/tx-gen2.o
iwlwifi-$(CONFIG_IWLDVM) += cfg/1000.o cfg/2000.o cfg/5000.o cfg/6000.o
iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o cfg/9000.o cfg/22000.o
CFLAGS_pcie/drv.o += -Wno-override-init
# combined MAC/RF configurations
iwlwifi-$(CONFIG_IWLDVM) += cfg/1000.o cfg/2000.o
iwlwifi-$(CONFIG_IWLDVM) += cfg/5000.o cfg/6000.o
iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o
# MAC configurations
iwlwifi-$(CONFIG_IWLMVM) += cfg/9000.o cfg/22000.o
iwlwifi-$(CONFIG_IWLMVM) += cfg/ax210.o
iwlwifi-$(CONFIG_IWLMLD) += cfg/bz.o cfg/sc.o cfg/dr.o
# RF configurations
iwlwifi-$(CONFIG_IWLMVM) += cfg/rf-jf.o cfg/rf-hr.o cfg/rf-gf.o
iwlwifi-$(CONFIG_IWLMLD) += cfg/rf-fm.o cfg/rf-wh.o cfg/rf-pe.o
iwlwifi-objs += iwl-dbg-tlv.o
iwlwifi-objs += iwl-trans.o

@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2018 - 2020, 2023 Intel Corporation
* Copyright(c) 2018 - 2020, 2023, 2025 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@ -29,7 +29,7 @@
#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl1000_base_params = {
static const struct iwl_family_base_params iwl1000_base = {
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
@ -42,12 +42,6 @@ static const struct iwl_base_params iwl1000_base_params = {
.scd_chain_ext_wa = true,
};
static const struct iwl_ht_params iwl1000_ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ),
};
static const struct iwl_eeprom_params iwl1000_eeprom_params = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@ -60,54 +54,67 @@ static const struct iwl_eeprom_params iwl1000_eeprom_params = {
}
};
const struct iwl_mac_cfg iwl1000_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_1000,
.base = &iwl1000_base,
};
#define IWL_DEVICE_1000 \
.fw_name_pre = IWL1000_FW_PRE, \
.ucode_api_max = IWL1000_UCODE_API_MAX, \
.ucode_api_min = IWL1000_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_1000, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_1000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
.trans.base_params = &iwl1000_base_params, \
.eeprom_params = &iwl1000_eeprom_params, \
.led_mode = IWL_LED_BLINK
const struct iwl_cfg iwl1000_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
const struct iwl_rf_cfg iwl1000_bgn_cfg = {
IWL_DEVICE_1000,
.ht_params = &iwl1000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ),
},
};
const struct iwl_cfg iwl1000_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1000 BG",
const char iwl1000_bgn_name[] = "Intel(R) Centrino(R) Wireless-N 1000 BGN";
const struct iwl_rf_cfg iwl1000_bg_cfg = {
IWL_DEVICE_1000,
};
const char iwl1000_bg_name[] = "Intel(R) Centrino(R) Wireless-N 1000 BG";
#define IWL_DEVICE_100 \
.fw_name_pre = IWL100_FW_PRE, \
.ucode_api_max = IWL100_UCODE_API_MAX, \
.ucode_api_min = IWL100_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_100, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_1000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
.trans.base_params = &iwl1000_base_params, \
.eeprom_params = &iwl1000_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \
.rx_with_siso_diversity = true
const struct iwl_cfg iwl100_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 100 BGN",
const struct iwl_rf_cfg iwl100_bgn_cfg = {
IWL_DEVICE_100,
.ht_params = &iwl1000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ),
},
};
const struct iwl_cfg iwl100_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 100 BG",
const char iwl100_bgn_name[] = "Intel(R) Centrino(R) Wireless-N 100 BGN";
const struct iwl_rf_cfg iwl100_bg_cfg = {
IWL_DEVICE_100,
};
const char iwl100_bg_name[] = "Intel(R) Centrino(R) Wireless-N 100 BG";
MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL100_MODULE_FIRMWARE(IWL100_UCODE_API_MAX));

@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2018 - 2020, 2023 Intel Corporation
* Copyright(c) 2018 - 2020, 2023, 2025 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@ -40,7 +40,7 @@
#define IWL135_FW_PRE "iwlwifi-135"
#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl2000_base_params = {
static const struct iwl_family_base_params iwl2000_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
@ -54,7 +54,7 @@ static const struct iwl_base_params iwl2000_base_params = {
};
static const struct iwl_base_params iwl2030_base_params = {
static const struct iwl_family_base_params iwl2030_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
@ -67,12 +67,6 @@ static const struct iwl_base_params iwl2030_base_params = {
.scd_chain_ext_wa = true,
};
static const struct iwl_ht_params iwl2000_ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ),
};
static const struct iwl_eeprom_params iwl20x0_eeprom_params = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@ -86,97 +80,119 @@ static const struct iwl_eeprom_params iwl20x0_eeprom_params = {
.enhanced_txpower = true,
};
const struct iwl_mac_cfg iwl2000_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_2000,
.base = &iwl2000_base,
};
#define IWL_DEVICE_2000 \
.fw_name_pre = IWL2000_FW_PRE, \
.ucode_api_max = IWL2000_UCODE_API_MAX, \
.ucode_api_min = IWL2000_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_2000, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
.trans.base_params = &iwl2000_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \
.led_mode = IWL_LED_RF_STATE
const struct iwl_cfg iwl2000_2bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 2200 BGN",
const struct iwl_rf_cfg iwl2000_2bgn_cfg = {
IWL_DEVICE_2000,
.ht_params = &iwl2000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ),
},
};
const struct iwl_cfg iwl2000_2bgn_d_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 2200D BGN",
IWL_DEVICE_2000,
.ht_params = &iwl2000_ht_params,
const char iwl2000_2bgn_name[] = "Intel(R) Centrino(R) Wireless-N 2200 BGN";
const char iwl2000_2bgn_d_name[] = "Intel(R) Centrino(R) Wireless-N 2200D BGN";
const struct iwl_mac_cfg iwl2030_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_2030,
.base = &iwl2030_base,
};
#define IWL_DEVICE_2030 \
.fw_name_pre = IWL2030_FW_PRE, \
.ucode_api_max = IWL2030_UCODE_API_MAX, \
.ucode_api_min = IWL2030_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_2030, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
.trans.base_params = &iwl2030_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \
.led_mode = IWL_LED_RF_STATE
const struct iwl_cfg iwl2030_2bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 2230 BGN",
const struct iwl_rf_cfg iwl2030_2bgn_cfg = {
IWL_DEVICE_2030,
.ht_params = &iwl2000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ),
},
};
const char iwl2030_2bgn_name[] = "Intel(R) Centrino(R) Wireless-N 2230 BGN";
const struct iwl_mac_cfg iwl105_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_105,
.base = &iwl2000_base,
};
#define IWL_DEVICE_105 \
.fw_name_pre = IWL105_FW_PRE, \
.ucode_api_max = IWL105_UCODE_API_MAX, \
.ucode_api_min = IWL105_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_105, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
.trans.base_params = &iwl2000_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \
.rx_with_siso_diversity = true
const struct iwl_cfg iwl105_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 105 BGN",
const struct iwl_rf_cfg iwl105_bgn_cfg = {
IWL_DEVICE_105,
.ht_params = &iwl2000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ),
},
};
const struct iwl_cfg iwl105_bgn_d_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 105D BGN",
IWL_DEVICE_105,
.ht_params = &iwl2000_ht_params,
const char iwl105_bgn_name[] = "Intel(R) Centrino(R) Wireless-N 105 BGN";
const char iwl105_bgn_d_name[] = "Intel(R) Centrino(R) Wireless-N 105D BGN";
const struct iwl_mac_cfg iwl135_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_135,
.base = &iwl2030_base,
};
#define IWL_DEVICE_135 \
.fw_name_pre = IWL135_FW_PRE, \
.ucode_api_max = IWL135_UCODE_API_MAX, \
.ucode_api_min = IWL135_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_135, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_2000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
.trans.base_params = &iwl2030_base_params, \
.eeprom_params = &iwl20x0_eeprom_params, \
.led_mode = IWL_LED_RF_STATE, \
.rx_with_siso_diversity = true
const struct iwl_cfg iwl135_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 135 BGN",
const struct iwl_rf_cfg iwl135_bgn_cfg = {
IWL_DEVICE_135,
.ht_params = &iwl2000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ),
},
};
const char iwl135_bgn_name[] = "Intel(R) Centrino(R) Wireless-N 135 BGN";
MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX));
MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX));

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2024 Intel Corporation
* Copyright (C) 2018-2025 Intel Corporation
*/
#include <linux/module.h>
#include <linux/stringify.h>
@ -15,14 +15,7 @@
/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 77
/* NVM versions */
#define IWL_22000_NVM_VERSION 0x0a1d
/* Memory offsets and lengths */
#define IWL_22000_DCCM_OFFSET 0x800000 /* LMAC1 */
#define IWL_22000_DCCM_LEN 0x10000 /* LMAC1 */
#define IWL_22000_DCCM2_OFFSET 0x880000
#define IWL_22000_DCCM2_LEN 0x8000
#define IWL_22000_SMEM_OFFSET 0x400000
#define IWL_22000_SMEM_LEN 0xD0000
@ -49,8 +42,7 @@
#define IWL_CC_A_MODULE_FIRMWARE(api) \
IWL_CC_A_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl_22000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
static const struct iwl_family_base_params iwl_22000_base = {
.num_of_queues = 512,
.max_tfd_queue_size = 256,
.shadow_ram_support = true,
@ -59,155 +51,78 @@ static const struct iwl_base_params iwl_22000_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
.smem_offset = IWL_22000_SMEM_OFFSET,
.smem_len = IWL_22000_SMEM_LEN,
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
.apmg_not_supported = true,
.mac_addr_from_csr = 0x380,
.min_umac_error_event_table = 0x400000,
.d3_debug_data_base_addr = 0x401000,
.d3_debug_data_length = 60 * 1024,
.mon_smem_regs = {
.write_ptr = {
.addr = LDBG_M2S_BUF_WPTR,
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
},
.cycle_cnt = {
.addr = LDBG_M2S_BUF_WRAP_CNT,
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
},
},
.gp2_reg_addr = 0xa02c68,
.mon_dram_regs = {
.write_ptr = {
.addr = MON_BUFF_WRPTR_VER2,
.mask = 0xffffffff,
},
.cycle_cnt = {
.addr = MON_BUFF_CYCLE_CNT_VER2,
.mask = 0xffffffff,
},
},
.ucode_api_min = IWL_22000_UCODE_API_MIN,
.ucode_api_max = IWL_22000_UCODE_API_MAX,
};
const struct iwl_ht_params iwl_22000_ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) |
BIT(NL80211_BAND_6GHZ),
};
#define IWL_DEVICE_22000_COMMON \
.ucode_api_min = IWL_22000_UCODE_API_MIN, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = 10, \
.non_shared_ant = ANT_B, \
.dccm_offset = IWL_22000_DCCM_OFFSET, \
.dccm_len = IWL_22000_DCCM_LEN, \
.dccm2_offset = IWL_22000_DCCM2_OFFSET, \
.dccm2_len = IWL_22000_DCCM2_LEN, \
.smem_offset = IWL_22000_SMEM_OFFSET, \
.smem_len = IWL_22000_SMEM_LEN, \
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
.apmg_not_supported = true, \
.trans.mq_rx_supported = true, \
.vht_mu_mimo_supported = true, \
.mac_addr_from_csr = 0x380, \
.ht_params = &iwl_22000_ht_params, \
.nvm_ver = IWL_22000_NVM_VERSION, \
.trans.rf_id = true, \
.trans.gen2 = true, \
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true, \
.min_umac_error_event_table = 0x400000, \
.d3_debug_data_base_addr = 0x401000, \
.d3_debug_data_length = 60 * 1024, \
.mon_smem_regs = { \
.write_ptr = { \
.addr = LDBG_M2S_BUF_WPTR, \
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
}, \
.cycle_cnt = { \
.addr = LDBG_M2S_BUF_WRAP_CNT, \
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
}, \
}
#define IWL_DEVICE_22500 \
IWL_DEVICE_22000_COMMON, \
.ucode_api_max = IWL_22000_UCODE_API_MAX, \
.trans.device_family = IWL_DEVICE_FAMILY_22000, \
.trans.base_params = &iwl_22000_base_params, \
.gp2_reg_addr = 0xa02c68, \
.mon_dram_regs = { \
.write_ptr = { \
.addr = MON_BUFF_WRPTR_VER2, \
.mask = 0xffffffff, \
}, \
.cycle_cnt = { \
.addr = MON_BUFF_CYCLE_CNT_VER2, \
.mask = 0xffffffff, \
}, \
}
const struct iwl_cfg_trans_params iwl_qu_trans_cfg = {
const struct iwl_mac_cfg iwl_qu_mac_cfg = {
.mq_rx_supported = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
.base_params = &iwl_22000_base_params,
.base = &iwl_22000_base,
.integrated = true,
.xtal_latency = 500,
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US,
};
const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg = {
const struct iwl_mac_cfg iwl_qu_medium_latency_mac_cfg = {
.mq_rx_supported = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
.base_params = &iwl_22000_base_params,
.base = &iwl_22000_base,
.integrated = true,
.xtal_latency = 1820,
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_1820US,
};
const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg = {
const struct iwl_mac_cfg iwl_qu_long_latency_mac_cfg = {
.mq_rx_supported = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
.base_params = &iwl_22000_base_params,
.base = &iwl_22000_base,
.integrated = true,
.xtal_latency = 12000,
.low_latency_xtal = true,
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
/*
* If the device doesn't support HE, no need to have that many buffers.
* 22000 devices can split multiple frames into a single RB, so fewer are
* needed; AX210 cannot (but use smaller RBs by default) - these sizes
* were picked according to 8 MSDUs inside 256 A-MSDUs in an A-MPDU, with
* additional overhead to account for processing time.
*/
#define IWL_NUM_RBDS_NON_HE 512
#define IWL_NUM_RBDS_22000_HE 2048
/*
* All JF radio modules are part of the 9000 series, but the MAC part
* looks more like 22000. That's why this device is here, but called
* 9560 nevertheless.
*/
const struct iwl_cfg iwl9560_qu_b0_jf_b0_cfg = {
.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
IWL_DEVICE_22500,
.num_rbds = IWL_NUM_RBDS_NON_HE,
};
const struct iwl_cfg iwl9560_qu_c0_jf_b0_cfg = {
.fw_name_pre = IWL_QU_C_JF_B_FW_PRE,
IWL_DEVICE_22500,
.num_rbds = IWL_NUM_RBDS_NON_HE,
};
const struct iwl_cfg iwl9560_quz_a0_jf_b0_cfg = {
.fw_name_pre = IWL_QUZ_A_JF_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_NON_HE,
};
const struct iwl_cfg_trans_params iwl_ax200_trans_cfg = {
const struct iwl_mac_cfg iwl_ax200_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_22000,
.base_params = &iwl_22000_base_params,
.base = &iwl_22000_base,
.mq_rx_supported = true,
.rf_id = true,
.gen2 = true,
.bisr_workaround = 1,
};
const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101";
const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz";
const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz";
const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203";
const char iwl_ax200_killer_1650w_name[] =
"Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)";
const char iwl_ax200_killer_1650x_name[] =
@ -217,210 +132,6 @@ const char iwl_ax201_killer_1650s_name[] =
const char iwl_ax201_killer_1650i_name[] =
"Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)";
const struct iwl_cfg iwl_qu_b0_hr1_b0 = {
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.tx_with_siso_diversity = true,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg iwl_qu_b0_hr_b0 = {
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg iwl_ax201_cfg_qu_hr = {
.name = "Intel(R) Wi-Fi 6 AX201 160MHz",
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg iwl_qu_c0_hr1_b0 = {
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.tx_with_siso_diversity = true,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg iwl_qu_c0_hr_b0 = {
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg iwl_ax201_cfg_qu_c0_hr_b0 = {
.name = "Intel(R) Wi-Fi 6 AX201 160MHz",
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg iwl_quz_a0_hr1_b0 = {
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.tx_with_siso_diversity = true,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg iwl_ax201_cfg_quz_hr = {
.name = "Intel(R) Wi-Fi 6 AX201 160MHz",
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg iwl_ax1650s_cfg_quz_hr = {
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)",
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg iwl_ax1650i_cfg_quz_hr = {
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)",
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg iwl_ax200_cfg_cc = {
.fw_name_pre = IWL_CC_A_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = {
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201NGW)",
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201D2W)",
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = {
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201NGW)",
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = {
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201D2W)",
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = {
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
IWL_DEVICE_22500,
/*
* This device doesn't support receiving BlockAck with a large bitmap
* so we need to restrict the size of transmitted aggregation to the
* HT size; mac80211 would otherwise pick the HE max (256) by default.
*/
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));

@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2018 - 2020, 2023 Intel Corporation
* Copyright(c) 2018 - 2020, 2023, 2025 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@ -30,7 +30,7 @@
#define IWL5150_FW_PRE "iwlwifi-5150"
#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl5000_base_params = {
static const struct iwl_family_base_params iwl5000_base = {
.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
@ -41,11 +41,6 @@ static const struct iwl_base_params iwl5000_base_params = {
.scd_chain_ext_wa = true,
};
static const struct iwl_ht_params iwl5000_ht_params = {
.ht_greenfield_support = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
};
static const struct iwl_eeprom_params iwl5000_eeprom_params = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@ -58,93 +53,107 @@ static const struct iwl_eeprom_params iwl5000_eeprom_params = {
},
};
const struct iwl_mac_cfg iwl5000_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_5000,
.base = &iwl5000_base,
};
#define IWL_DEVICE_5000 \
.fw_name_pre = IWL5000_FW_PRE, \
.ucode_api_max = IWL5000_UCODE_API_MAX, \
.ucode_api_min = IWL5000_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_5000, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_5000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_5000_TX_POWER_VERSION, \
.trans.base_params = &iwl5000_base_params, \
.eeprom_params = &iwl5000_eeprom_params, \
.led_mode = IWL_LED_BLINK
const struct iwl_cfg iwl5300_agn_cfg = {
.name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
const struct iwl_rf_cfg iwl5300_agn_cfg = {
IWL_DEVICE_5000,
/* at least EEPROM 0x11A has wrong info */
.valid_tx_ant = ANT_ABC, /* .cfg overwrite */
.valid_rx_ant = ANT_ABC, /* .cfg overwrite */
.ht_params = &iwl5000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
};
const struct iwl_cfg iwl5100_bgn_cfg = {
.name = "Intel(R) WiFi Link 5100 BGN",
const char iwl5300_agn_name[] = "Intel(R) Ultimate N WiFi Link 5300 AGN";
const struct iwl_rf_cfg iwl5100_n_cfg = {
IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */
.valid_rx_ant = ANT_AB, /* .cfg overwrite */
.ht_params = &iwl5000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
};
const struct iwl_cfg iwl5100_abg_cfg = {
.name = "Intel(R) WiFi Link 5100 ABG",
const char iwl5100_bgn_name[] = "Intel(R) WiFi Link 5100 BGN";
const struct iwl_rf_cfg iwl5100_abg_cfg = {
IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */
.valid_rx_ant = ANT_AB, /* .cfg overwrite */
};
const struct iwl_cfg iwl5100_agn_cfg = {
.name = "Intel(R) WiFi Link 5100 AGN",
IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */
.valid_rx_ant = ANT_AB, /* .cfg overwrite */
.ht_params = &iwl5000_ht_params,
};
const char iwl5100_abg_name[] = "Intel(R) WiFi Link 5100 ABG";
const char iwl5100_agn_name[] = "Intel(R) WiFi Link 5100 AGN";
const struct iwl_cfg iwl5350_agn_cfg = {
.name = "Intel(R) WiMAX/WiFi Link 5350 AGN",
const struct iwl_rf_cfg iwl5350_agn_cfg = {
.fw_name_pre = IWL5000_FW_PRE,
.ucode_api_max = IWL5000_UCODE_API_MAX,
.ucode_api_min = IWL5000_UCODE_API_MIN,
.trans.device_family = IWL_DEVICE_FAMILY_5000,
.max_inst_size = IWLAGN_RTC_INST_SIZE,
.max_data_size = IWLAGN_RTC_DATA_SIZE,
.nvm_ver = EEPROM_5050_EEPROM_VERSION,
.nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION,
.trans.base_params = &iwl5000_base_params,
.eeprom_params = &iwl5000_eeprom_params,
.ht_params = &iwl5000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
.led_mode = IWL_LED_BLINK,
.internal_wimax_coex = true,
};
const char iwl5350_agn_name[] = "Intel(R) WiMAX/WiFi Link 5350 AGN";
const struct iwl_mac_cfg iwl5150_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_5150,
.base = &iwl5000_base,
};
#define IWL_DEVICE_5150 \
.fw_name_pre = IWL5150_FW_PRE, \
.ucode_api_max = IWL5150_UCODE_API_MAX, \
.ucode_api_min = IWL5150_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_5150, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_5050_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION, \
.trans.base_params = &iwl5000_base_params, \
.eeprom_params = &iwl5000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true
const struct iwl_cfg iwl5150_agn_cfg = {
.name = "Intel(R) WiMAX/WiFi Link 5150 AGN",
const struct iwl_rf_cfg iwl5150_agn_cfg = {
IWL_DEVICE_5150,
.ht_params = &iwl5000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
};
const struct iwl_cfg iwl5150_abg_cfg = {
.name = "Intel(R) WiMAX/WiFi Link 5150 ABG",
const char iwl5150_agn_name[] = "Intel(R) WiMAX/WiFi Link 5150 AGN";
const struct iwl_rf_cfg iwl5150_abg_cfg = {
IWL_DEVICE_5150,
};
const char iwl5150_abg_name[] = "Intel(R) WiMAX/WiFi Link 5150 ABG";
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));

@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2018 - 2020, 2023 Intel Corporation
* Copyright(c) 2018 - 2020, 2023, 2025 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@ -49,7 +49,7 @@
#define IWL6030_FW_PRE "iwlwifi-6000g2b"
#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl6000_base_params = {
static const struct iwl_family_base_params iwl6000_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
@ -62,7 +62,7 @@ static const struct iwl_base_params iwl6000_base_params = {
.scd_chain_ext_wa = true,
};
static const struct iwl_base_params iwl6050_base_params = {
static const struct iwl_family_base_params iwl6050_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
@ -75,7 +75,7 @@ static const struct iwl_base_params iwl6050_base_params = {
.scd_chain_ext_wa = true,
};
static const struct iwl_base_params iwl6000_g2_base_params = {
static const struct iwl_family_base_params iwl6000_g2_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
.num_of_queues = IWLAGN_NUM_QUEUES,
.max_tfd_queue_size = 256,
@ -88,12 +88,6 @@ static const struct iwl_base_params iwl6000_g2_base_params = {
.scd_chain_ext_wa = true,
};
static const struct iwl_ht_params iwl6000_ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
};
static const struct iwl_eeprom_params iwl6000_eeprom_params = {
.regulatory_bands = {
EEPROM_REG_BAND_1_CHANNELS,
@ -107,143 +101,128 @@ static const struct iwl_eeprom_params iwl6000_eeprom_params = {
.enhanced_txpower = true,
};
const struct iwl_mac_cfg iwl6005_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_6005,
.base = &iwl6000_g2_base,
};
#define IWL_DEVICE_6005 \
.fw_name_pre = IWL6005_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_6005, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_6005_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6005_TX_POWER_VERSION, \
.trans.base_params = &iwl6000_g2_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_RF_STATE
const struct iwl_cfg iwl6005_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205 AGN",
const struct iwl_rf_cfg iwl6005_n_cfg = {
IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
};
const struct iwl_cfg iwl6005_2abg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205 ABG",
const char iwl6005_2agn_name[] = "Intel(R) Centrino(R) Advanced-N 6205 AGN";
const char iwl6005_2agn_sff_name[] = "Intel(R) Centrino(R) Advanced-N 6205S AGN";
const char iwl6005_2agn_d_name[] = "Intel(R) Centrino(R) Advanced-N 6205D AGN";
const char iwl6005_2agn_mow1_name[] = "Intel(R) Centrino(R) Advanced-N 6206 AGN";
const char iwl6005_2agn_mow2_name[] = "Intel(R) Centrino(R) Advanced-N 6207 AGN";
const struct iwl_rf_cfg iwl6005_non_n_cfg = {
IWL_DEVICE_6005,
};
const struct iwl_cfg iwl6005_2bg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205 BG",
IWL_DEVICE_6005,
};
const char iwl6005_2abg_name[] = "Intel(R) Centrino(R) Advanced-N 6205 ABG";
const char iwl6005_2bg_name[] = "Intel(R) Centrino(R) Advanced-N 6205 BG";
const struct iwl_cfg iwl6005_2agn_sff_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205S AGN",
IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params,
};
const struct iwl_cfg iwl6005_2agn_d_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205D AGN",
IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params,
};
const struct iwl_cfg iwl6005_2agn_mow1_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6206 AGN",
IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params,
};
const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6207 AGN",
IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params,
const struct iwl_mac_cfg iwl6030_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_6030,
.base = &iwl6000_g2_base,
};
#define IWL_DEVICE_6030 \
.fw_name_pre = IWL6030_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_6030, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_6030_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
.trans.base_params = &iwl6000_g2_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_RF_STATE
const struct iwl_cfg iwl6030_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6230 AGN",
const struct iwl_rf_cfg iwl6030_n_cfg = {
IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
};
const struct iwl_cfg iwl6030_2abg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6230 ABG",
const char iwl6030_2agn_name[] = "Intel(R) Centrino(R) Advanced-N 6230 AGN";
const char iwl6030_2bgn_name[] = "Intel(R) Centrino(R) Advanced-N 6230 BGN";
const char iwl1030_bgn_name[] = "Intel(R) Centrino(R) Wireless-N 1030 BGN";
const char iwl1030_bg_name[] = "Intel(R) Centrino(R) Wireless-N 1030 BG";
const struct iwl_rf_cfg iwl6030_non_n_cfg = {
IWL_DEVICE_6030,
};
const struct iwl_cfg iwl6030_2bgn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6230 BGN",
IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params,
};
const struct iwl_cfg iwl6030_2bg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6230 BG",
IWL_DEVICE_6030,
};
const char iwl6030_2abg_name[] = "Intel(R) Centrino(R) Advanced-N 6230 ABG";
const char iwl6030_2bg_name[] = "Intel(R) Centrino(R) Advanced-N 6230 BG";
#define IWL_DEVICE_6035 \
.fw_name_pre = IWL6030_FW_PRE, \
.ucode_api_max = IWL6035_UCODE_API_MAX, \
.ucode_api_min = IWL6035_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_6030, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_6030_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
.trans.base_params = &iwl6000_g2_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_RF_STATE
const struct iwl_cfg iwl6035_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6235 AGN",
const struct iwl_rf_cfg iwl6035_2agn_cfg = {
IWL_DEVICE_6035,
.ht_params = &iwl6000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
};
const struct iwl_cfg iwl6035_2agn_sff_cfg = {
.name = "Intel(R) Centrino(R) Ultimate-N 6235 AGN",
IWL_DEVICE_6035,
.ht_params = &iwl6000_ht_params,
};
const char iwl6035_2agn_name[] = "Intel(R) Centrino(R) Advanced-N 6235 AGN";
const char iwl6035_2agn_sff_name[] = "Intel(R) Centrino(R) Ultimate-N 6235 AGN";
const struct iwl_cfg iwl1030_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
const struct iwl_rf_cfg iwl130_bgn_cfg = {
IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params,
};
const struct iwl_cfg iwl1030_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1030 BG",
IWL_DEVICE_6030,
};
const struct iwl_cfg iwl130_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 130 BGN",
IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
.rx_with_siso_diversity = true,
};
const struct iwl_cfg iwl130_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 130 BG",
const char iwl130_bgn_name[] = "Intel(R) Centrino(R) Wireless-N 130 BGN";
const struct iwl_rf_cfg iwl130_bg_cfg = {
IWL_DEVICE_6030,
.rx_with_siso_diversity = true,
};
const char iwl130_bg_name[] = "Intel(R) Centrino(R) Wireless-N 130 BG";
const struct iwl_mac_cfg iwl6000i_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_6000i,
.base = &iwl6000_base,
};
/*
* "i": Internal configuration, use internal Power Amplifier
*/
@ -251,101 +230,127 @@ const struct iwl_cfg iwl130_bg_cfg = {
.fw_name_pre = IWL6000_FW_PRE, \
.ucode_api_max = IWL6000_UCODE_API_MAX, \
.ucode_api_min = IWL6000_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_6000i, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.valid_tx_ant = ANT_BC, /* .cfg overwrite */ \
.valid_rx_ant = ANT_BC, /* .cfg overwrite */ \
.nvm_ver = EEPROM_6000_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION, \
.trans.base_params = &iwl6000_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_BLINK
const struct iwl_cfg iwl6000i_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6200 AGN",
const struct iwl_rf_cfg iwl6000i_2agn_cfg = {
IWL_DEVICE_6000i,
.ht_params = &iwl6000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
};
const struct iwl_cfg iwl6000i_2abg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6200 ABG",
const char iwl6000i_2agn_name[] = "Intel(R) Centrino(R) Advanced-N 6200 AGN";
const struct iwl_rf_cfg iwl6000i_non_n_cfg = {
IWL_DEVICE_6000i,
};
const struct iwl_cfg iwl6000i_2bg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6200 BG",
IWL_DEVICE_6000i,
const char iwl6000i_2abg_name[] = "Intel(R) Centrino(R) Advanced-N 6200 ABG";
const char iwl6000i_2bg_name[] = "Intel(R) Centrino(R) Advanced-N 6200 BG";
const struct iwl_mac_cfg iwl6050_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_6050,
.base = &iwl6050_base,
};
#define IWL_DEVICE_6050 \
.fw_name_pre = IWL6050_FW_PRE, \
.ucode_api_max = IWL6050_UCODE_API_MAX, \
.ucode_api_min = IWL6050_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_6050, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.valid_tx_ant = ANT_AB, /* .cfg overwrite */ \
.valid_rx_ant = ANT_AB, /* .cfg overwrite */ \
.nvm_ver = EEPROM_6050_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6050_TX_POWER_VERSION, \
.trans.base_params = &iwl6050_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true
const struct iwl_cfg iwl6050_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN",
const struct iwl_rf_cfg iwl6050_2agn_cfg = {
IWL_DEVICE_6050,
.ht_params = &iwl6000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
};
const struct iwl_cfg iwl6050_2abg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG",
const char iwl6050_2agn_name[] = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN";
const struct iwl_rf_cfg iwl6050_2abg_cfg = {
IWL_DEVICE_6050,
};
const char iwl6050_2abg_name[] = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG";
const struct iwl_mac_cfg iwl6150_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_6150,
.base = &iwl6050_base,
};
#define IWL_DEVICE_6150 \
.fw_name_pre = IWL6050_FW_PRE, \
.ucode_api_max = IWL6050_UCODE_API_MAX, \
.ucode_api_min = IWL6050_UCODE_API_MIN, \
.trans.device_family = IWL_DEVICE_FAMILY_6150, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.nvm_ver = EEPROM_6150_EEPROM_VERSION, \
.nvm_calib_ver = EEPROM_6150_TX_POWER_VERSION, \
.trans.base_params = &iwl6050_base_params, \
.eeprom_params = &iwl6000_eeprom_params, \
.led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true
const struct iwl_cfg iwl6150_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN",
const struct iwl_rf_cfg iwl6150_bgn_cfg = {
IWL_DEVICE_6150,
.ht_params = &iwl6000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
};
const struct iwl_cfg iwl6150_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG",
const char iwl6150_bgn_name[] = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN";
const struct iwl_rf_cfg iwl6150_bg_cfg = {
IWL_DEVICE_6150,
};
const struct iwl_cfg iwl6000_3agn_cfg = {
.name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN",
const char iwl6150_bg_name[] = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG";
const struct iwl_mac_cfg iwl6000_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_6000,
.base = &iwl6000_base,
};
const struct iwl_rf_cfg iwl6000_3agn_cfg = {
.fw_name_pre = IWL6000_FW_PRE,
.ucode_api_max = IWL6000_UCODE_API_MAX,
.ucode_api_min = IWL6000_UCODE_API_MIN,
.trans.device_family = IWL_DEVICE_FAMILY_6000,
.max_inst_size = IWL60_RTC_INST_SIZE,
.max_data_size = IWL60_RTC_DATA_SIZE,
.nvm_ver = EEPROM_6000_EEPROM_VERSION,
.nvm_calib_ver = EEPROM_6000_TX_POWER_VERSION,
.trans.base_params = &iwl6000_base_params,
.eeprom_params = &iwl6000_eeprom_params,
.ht_params = &iwl6000_ht_params,
.ht_params = {
.ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
.led_mode = IWL_LED_BLINK,
};
const char iwl6000_3agn_name[] = "Intel(R) Centrino(R) Ultimate-N 6300 AGN";
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2012-2014, 2018-2020, 2023 Intel Corporation
* Copyright (C) 2012-2014, 2018-2020, 2023, 2025 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 Intel Deutschland GmbH
*/
@ -49,7 +49,7 @@
#define IWL7265D_FW_PRE "iwlwifi-7265D"
#define IWL7265D_MODULE_FIRMWARE(api) IWL7265D_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl7000_base_params = {
static const struct iwl_family_base_params iwl7000_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_16K,
.num_of_queues = 31,
.max_tfd_queue_size = 256,
@ -60,6 +60,7 @@ static const struct iwl_base_params iwl7000_base_params = {
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
.apmg_wake_up_wa = true,
.nvm_hw_section_num = 0,
};
static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
@ -84,16 +85,13 @@ static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
.support_tx_backoff = true,
};
static const struct iwl_ht_params iwl7000_ht_params = {
.stbc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
const struct iwl_mac_cfg iwl7000_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_7000,
.base = &iwl7000_base,
};
#define IWL_DEVICE_7000_COMMON \
.trans.device_family = IWL_DEVICE_FAMILY_7000, \
.trans.base_params = &iwl7000_base_params, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = 0, \
.non_shared_ant = ANT_A, \
.dccm_offset = IWL7000_DCCM_OFFSET
@ -117,77 +115,52 @@ static const struct iwl_ht_params iwl7000_ht_params = {
.ucode_api_max = IWL7265D_UCODE_API_MAX, \
.ucode_api_min = IWL7265D_UCODE_API_MIN
const struct iwl_cfg iwl7260_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 7260",
const char iwl7260_2ac_name[] = "Intel(R) Dual Band Wireless AC 7260";
const char iwl7260_2n_name[] = "Intel(R) Dual Band Wireless N 7260";
const char iwl7260_n_name[] = "Intel(R) Wireless N 7260";
const char iwl3160_2ac_name[] = "Intel(R) Dual Band Wireless AC 3160";
const char iwl3160_2n_name[] = "Intel(R) Dual Band Wireless N 3160";
const char iwl3160_n_name[] = "Intel(R) Wireless N 3160";
const char iwl3165_2ac_name[] = "Intel(R) Dual Band Wireless-AC 3165";
const char iwl3168_2ac_name[] = "Intel(R) Dual Band Wireless-AC 3168";
const char iwl7265_2ac_name[] = "Intel(R) Dual Band Wireless-AC 7265";
const char iwl7265_2n_name[] = "Intel(R) Dual Band Wireless-N 7265";
const char iwl7265_n_name[] = "Intel(R) Wireless-N 7265";
const struct iwl_rf_cfg iwl7260_cfg = {
.fw_name_pre = IWL7260_FW_PRE,
IWL_DEVICE_7000,
.ht_params = &iwl7000_ht_params,
.ht_params = {
.stbc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
.nvm_ver = IWL7260_NVM_VERSION,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
};
const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
.name = "Intel(R) Dual Band Wireless AC 7260",
const struct iwl_rf_cfg iwl7260_high_temp_cfg = {
.fw_name_pre = IWL7260_FW_PRE,
IWL_DEVICE_7000,
.ht_params = &iwl7000_ht_params,
.ht_params = {
.stbc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
.nvm_ver = IWL7260_NVM_VERSION,
.high_temp = true,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
.thermal_params = &iwl7000_high_temp_tt_params,
};
const struct iwl_cfg iwl7260_2n_cfg = {
.name = "Intel(R) Dual Band Wireless N 7260",
.fw_name_pre = IWL7260_FW_PRE,
IWL_DEVICE_7000,
.ht_params = &iwl7000_ht_params,
.nvm_ver = IWL7260_NVM_VERSION,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
};
const struct iwl_cfg iwl7260_n_cfg = {
.name = "Intel(R) Wireless N 7260",
.fw_name_pre = IWL7260_FW_PRE,
IWL_DEVICE_7000,
.ht_params = &iwl7000_ht_params,
.nvm_ver = IWL7260_NVM_VERSION,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
};
const struct iwl_cfg iwl3160_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 3160",
const struct iwl_rf_cfg iwl3160_cfg = {
.fw_name_pre = IWL3160_FW_PRE,
IWL_DEVICE_7000,
.ht_params = &iwl7000_ht_params,
.nvm_ver = IWL3160_NVM_VERSION,
.host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
};
const struct iwl_cfg iwl3160_2n_cfg = {
.name = "Intel(R) Dual Band Wireless N 3160",
.fw_name_pre = IWL3160_FW_PRE,
IWL_DEVICE_7000,
.ht_params = &iwl7000_ht_params,
.nvm_ver = IWL3160_NVM_VERSION,
.host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
};
const struct iwl_cfg iwl3160_n_cfg = {
.name = "Intel(R) Wireless N 3160",
.fw_name_pre = IWL3160_FW_PRE,
IWL_DEVICE_7000,
.ht_params = &iwl7000_ht_params,
.ht_params = {
.stbc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
.nvm_ver = IWL3160_NVM_VERSION,
.host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
@ -204,88 +177,52 @@ static const struct iwl_pwr_tx_backoff iwl7265_pwr_tx_backoffs[] = {
{0},
};
static const struct iwl_ht_params iwl7265_ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
};
const struct iwl_cfg iwl3165_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 3165",
const struct iwl_rf_cfg iwl3165_2ac_cfg = {
.fw_name_pre = IWL7265D_FW_PRE,
IWL_DEVICE_7005D,
.ht_params = &iwl7000_ht_params,
.ht_params = {
.stbc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
.nvm_ver = IWL3165_NVM_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl3168_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 3168",
const struct iwl_rf_cfg iwl3168_2ac_cfg = {
.fw_name_pre = IWL3168_FW_PRE,
IWL_DEVICE_3008,
.ht_params = &iwl7000_ht_params,
.ht_params = {
.stbc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
.nvm_ver = IWL3168_NVM_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
.nvm_type = IWL_NVM_SDP,
};
const struct iwl_cfg iwl7265_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 7265",
const struct iwl_rf_cfg iwl7265_cfg = {
.fw_name_pre = IWL7265_FW_PRE,
IWL_DEVICE_7005,
.ht_params = &iwl7265_ht_params,
.ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
.nvm_ver = IWL7265_NVM_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265_2n_cfg = {
.name = "Intel(R) Dual Band Wireless N 7265",
.fw_name_pre = IWL7265_FW_PRE,
IWL_DEVICE_7005,
.ht_params = &iwl7265_ht_params,
.nvm_ver = IWL7265_NVM_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265_n_cfg = {
.name = "Intel(R) Wireless N 7265",
.fw_name_pre = IWL7265_FW_PRE,
IWL_DEVICE_7005,
.ht_params = &iwl7265_ht_params,
.nvm_ver = IWL7265_NVM_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265d_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 7265",
const struct iwl_rf_cfg iwl7265d_cfg = {
.fw_name_pre = IWL7265D_FW_PRE,
IWL_DEVICE_7005D,
.ht_params = &iwl7265_ht_params,
.nvm_ver = IWL7265D_NVM_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265d_2n_cfg = {
.name = "Intel(R) Dual Band Wireless N 7265",
.fw_name_pre = IWL7265D_FW_PRE,
IWL_DEVICE_7005D,
.ht_params = &iwl7265_ht_params,
.nvm_ver = IWL7265D_NVM_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265d_n_cfg = {
.name = "Intel(R) Wireless N 7265",
.fw_name_pre = IWL7265D_FW_PRE,
IWL_DEVICE_7005D,
.ht_params = &iwl7265_ht_params,
.ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
.nvm_ver = IWL7265D_NVM_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2014, 2018-2020, 2023 Intel Corporation
* Copyright (C) 2014, 2018-2020, 2023, 2025 Intel Corporation
* Copyright (C) 2014-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
@ -35,9 +35,7 @@
#define IWL8265_MODULE_FIRMWARE(api) \
IWL8265_FW_PRE "-" __stringify(api) ".ucode"
#define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C"
static const struct iwl_base_params iwl8000_base_params = {
static const struct iwl_family_base_params iwl8000_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
.num_of_queues = 31,
.max_tfd_queue_size = 256,
@ -47,12 +45,12 @@ static const struct iwl_base_params iwl8000_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
};
static const struct iwl_ht_params iwl8000_ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
.nvm_hw_section_num = 10,
.features = NETIF_F_RXCSUM,
.smem_offset = IWL8260_SMEM_OFFSET,
.smem_len = IWL8260_SMEM_LEN,
.apmg_not_supported = true,
.min_umac_error_event_table = 0x800000,
};
static const struct iwl_tt_params iwl8000_tt_params = {
@ -76,30 +74,20 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.support_tx_backoff = true,
};
const struct iwl_mac_cfg iwl8000_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_8000,
.base = &iwl8000_base,
};
#define IWL_DEVICE_8000_COMMON \
.trans.device_family = IWL_DEVICE_FAMILY_8000, \
.trans.base_params = &iwl8000_base_params, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = 10, \
.features = NETIF_F_RXCSUM, \
.non_shared_ant = ANT_A, \
.dccm_offset = IWL8260_DCCM_OFFSET, \
.dccm_len = IWL8260_DCCM_LEN, \
.dccm2_offset = IWL8260_DCCM2_OFFSET, \
.dccm2_len = IWL8260_DCCM2_LEN, \
.smem_offset = IWL8260_SMEM_OFFSET, \
.smem_len = IWL8260_SMEM_LEN, \
.default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C, \
.thermal_params = &iwl8000_tt_params, \
.apmg_not_supported = true, \
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true, \
.min_umac_error_event_table = 0x800000
#define IWL_DEVICE_8000 \
IWL_DEVICE_8000_COMMON, \
.ucode_api_max = IWL8000_UCODE_API_MAX, \
.ucode_api_min = IWL8000_UCODE_API_MIN \
.nvm_type = IWL_NVM_EXT
#define IWL_DEVICE_8260 \
IWL_DEVICE_8000_COMMON, \
@ -111,47 +99,39 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.ucode_api_max = IWL8265_UCODE_API_MAX, \
.ucode_api_min = IWL8265_UCODE_API_MIN \
const struct iwl_cfg iwl8260_2n_cfg = {
.name = "Intel(R) Dual Band Wireless N 8260",
const char iwl8260_2n_name[] = "Intel(R) Dual Band Wireless-N 8260";
const char iwl8260_2ac_name[] = "Intel(R) Dual Band Wireless-AC 8260";
const char iwl8265_2ac_name[] = "Intel(R) Dual Band Wireless-AC 8265";
const char iwl8275_2ac_name[] = "Intel(R) Dual Band Wireless-AC 8275";
const char iwl4165_2ac_name[] = "Intel(R) Dual Band Wireless-AC 4165";
const char iwl_killer_1435i_name[] =
"Killer(R) Wireless-AC 1435i Wireless Network Adapter (8265D2W)";
const char iwl_killer_1434_kix_name[] =
"Killer(R) Wireless-AC 1435-KIX Wireless Network Adapter (8265NGW)";
const struct iwl_rf_cfg iwl8260_cfg = {
.fw_name_pre = IWL8000_FW_PRE,
IWL_DEVICE_8260,
.ht_params = &iwl8000_ht_params,
.ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
.nvm_ver = IWL8000_NVM_VERSION,
};
const struct iwl_cfg iwl8260_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 8260",
.fw_name_pre = IWL8000_FW_PRE,
IWL_DEVICE_8260,
.ht_params = &iwl8000_ht_params,
.nvm_ver = IWL8000_NVM_VERSION,
};
const struct iwl_cfg iwl8265_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 8265",
const struct iwl_rf_cfg iwl8265_cfg = {
.fw_name_pre = IWL8265_FW_PRE,
IWL_DEVICE_8265,
.ht_params = &iwl8000_ht_params,
.ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
},
.nvm_ver = IWL8000_NVM_VERSION,
.vht_mu_mimo_supported = true,
};
const struct iwl_cfg iwl8275_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 8275",
.fw_name_pre = IWL8265_FW_PRE,
IWL_DEVICE_8265,
.ht_params = &iwl8000_ht_params,
.nvm_ver = IWL8000_NVM_VERSION,
.vht_mu_mimo_supported = true,
};
const struct iwl_cfg iwl4165_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 4165",
.fw_name_pre = IWL8000_FW_PRE,
IWL_DEVICE_8000,
.ht_params = &iwl8000_ht_params,
.nvm_ver = IWL8000_NVM_VERSION,
};
MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL8265_MODULE_FIRMWARE(IWL8265_UCODE_API_MAX));

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2021, 2023 Intel Corporation
* Copyright (C) 2018-2021, 2023, 2025 Intel Corporation
*/
#include <linux/module.h>
#include <linux/stringify.h>
@ -15,14 +15,7 @@
/* Lowest firmware API version supported */
#define IWL9000_UCODE_API_MIN 30
/* NVM versions */
#define IWL9000_NVM_VERSION 0x0a1d
/* Memory offsets and lengths */
#define IWL9000_DCCM_OFFSET 0x800000
#define IWL9000_DCCM_LEN 0x18000
#define IWL9000_DCCM2_OFFSET 0x880000
#define IWL9000_DCCM2_LEN 0x8000
#define IWL9000_SMEM_OFFSET 0x400000
#define IWL9000_SMEM_LEN 0x68000
@ -33,7 +26,7 @@
#define IWL9260_MODULE_FIRMWARE(api) \
IWL9260_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl9000_base_params = {
static const struct iwl_family_base_params iwl9000_base = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
.num_of_queues = 31,
.max_tfd_queue_size = 256,
@ -43,150 +36,69 @@ static const struct iwl_base_params iwl9000_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
};
static const struct iwl_ht_params iwl9000_ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
};
static const struct iwl_tt_params iwl9000_tt_params = {
.ct_kill_entry = 115,
.ct_kill_exit = 93,
.ct_kill_duration = 5,
.dynamic_smps_entry = 111,
.dynamic_smps_exit = 107,
.tx_protection_entry = 112,
.tx_protection_exit = 105,
.tx_backoff = {
{.temperature = 110, .backoff = 200},
{.temperature = 111, .backoff = 600},
{.temperature = 112, .backoff = 1200},
{.temperature = 113, .backoff = 2000},
{.temperature = 114, .backoff = 4000},
.smem_offset = IWL9000_SMEM_OFFSET,
.smem_len = IWL9000_SMEM_LEN,
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
.apmg_not_supported = true,
.mac_addr_from_csr = 0x380,
.min_umac_error_event_table = 0x800000,
.d3_debug_data_base_addr = 0x401000,
.d3_debug_data_length = 92 * 1024,
.nvm_hw_section_num = 10,
.mon_smem_regs = {
.write_ptr = {
.addr = LDBG_M2S_BUF_WPTR,
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
},
.cycle_cnt = {
.addr = LDBG_M2S_BUF_WRAP_CNT,
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
},
},
.support_ct_kill = true,
.support_dynamic_smps = true,
.support_tx_protection = true,
.support_tx_backoff = true,
.mon_dram_regs = {
.write_ptr = {
.addr = MON_BUFF_WRPTR_VER2,
.mask = 0xffffffff,
},
.cycle_cnt = {
.addr = MON_BUFF_CYCLE_CNT_VER2,
.mask = 0xffffffff,
},
},
.ucode_api_max = IWL9000_UCODE_API_MAX,
.ucode_api_min = IWL9000_UCODE_API_MIN,
};
#define IWL_DEVICE_9000 \
.ucode_api_max = IWL9000_UCODE_API_MAX, \
.ucode_api_min = IWL9000_UCODE_API_MIN, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = 10, \
.non_shared_ant = ANT_B, \
.dccm_offset = IWL9000_DCCM_OFFSET, \
.dccm_len = IWL9000_DCCM_LEN, \
.dccm2_offset = IWL9000_DCCM2_OFFSET, \
.dccm2_len = IWL9000_DCCM2_LEN, \
.smem_offset = IWL9000_SMEM_OFFSET, \
.smem_len = IWL9000_SMEM_LEN, \
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
.thermal_params = &iwl9000_tt_params, \
.apmg_not_supported = true, \
.num_rbds = 512, \
.vht_mu_mimo_supported = true, \
.mac_addr_from_csr = 0x380, \
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true, \
.min_umac_error_event_table = 0x800000, \
.d3_debug_data_base_addr = 0x401000, \
.d3_debug_data_length = 92 * 1024, \
.ht_params = &iwl9000_ht_params, \
.nvm_ver = IWL9000_NVM_VERSION, \
.mon_smem_regs = { \
.write_ptr = { \
.addr = LDBG_M2S_BUF_WPTR, \
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
}, \
.cycle_cnt = { \
.addr = LDBG_M2S_BUF_WRAP_CNT, \
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
}, \
}, \
.mon_dram_regs = { \
.write_ptr = { \
.addr = MON_BUFF_WRPTR_VER2, \
.mask = 0xffffffff, \
}, \
.cycle_cnt = { \
.addr = MON_BUFF_CYCLE_CNT_VER2, \
.mask = 0xffffffff, \
}, \
}
const struct iwl_cfg_trans_params iwl9000_trans_cfg = {
const struct iwl_mac_cfg iwl9000_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_9000,
.base_params = &iwl9000_base_params,
.base = &iwl9000_base,
.mq_rx_supported = true,
.rf_id = true,
};
const struct iwl_cfg_trans_params iwl9560_trans_cfg = {
const struct iwl_mac_cfg iwl9560_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_9000,
.base_params = &iwl9000_base_params,
.base = &iwl9000_base,
.mq_rx_supported = true,
.rf_id = true,
.integrated = true,
.xtal_latency = 650,
};
const struct iwl_cfg_trans_params iwl9560_long_latency_trans_cfg = {
const struct iwl_mac_cfg iwl9560_long_latency_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_9000,
.base_params = &iwl9000_base_params,
.base = &iwl9000_base,
.mq_rx_supported = true,
.rf_id = true,
.integrated = true,
.xtal_latency = 2820,
};
const struct iwl_cfg_trans_params iwl9560_shared_clk_trans_cfg = {
const struct iwl_mac_cfg iwl9560_shared_clk_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_9000,
.base_params = &iwl9000_base_params,
.base = &iwl9000_base,
.mq_rx_supported = true,
.rf_id = true,
.integrated = true,
.xtal_latency = 670,
.extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK
};
const char iwl9162_name[] = "Intel(R) Wireless-AC 9162";
const char iwl9260_name[] = "Intel(R) Wireless-AC 9260";
const char iwl9260_1_name[] = "Intel(R) Wireless-AC 9260-1";
const char iwl9270_name[] = "Intel(R) Wireless-AC 9270";
const char iwl9461_name[] = "Intel(R) Wireless-AC 9461";
const char iwl9462_name[] = "Intel(R) Wireless-AC 9462";
const char iwl9560_name[] = "Intel(R) Wireless-AC 9560";
const char iwl9162_160_name[] = "Intel(R) Wireless-AC 9162 160MHz";
const char iwl9260_160_name[] = "Intel(R) Wireless-AC 9260 160MHz";
const char iwl9270_160_name[] = "Intel(R) Wireless-AC 9270 160MHz";
const char iwl9461_160_name[] = "Intel(R) Wireless-AC 9461 160MHz";
const char iwl9462_160_name[] = "Intel(R) Wireless-AC 9462 160MHz";
const char iwl9560_160_name[] = "Intel(R) Wireless-AC 9560 160MHz";
const char iwl9260_killer_1550_name[] =
"Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW) 160MHz";
const char iwl9560_killer_1550i_name[] =
"Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)";
const char iwl9560_killer_1550i_160_name[] =
"Killer(R) Wireless-AC 1550i Wireless Network Adapter (9560NGW) 160MHz";
const char iwl9560_killer_1550s_name[] =
"Killer (R) Wireless-AC 1550s Wireless Network Adapter (9560NGW)";
const char iwl9560_killer_1550s_160_name[] =
"Killer(R) Wireless-AC 1550s Wireless Network Adapter (9560D2W) 160MHz";
const struct iwl_cfg iwl9260_2ac_cfg = {
.fw_name_pre = IWL9260_FW_PRE,
IWL_DEVICE_9000,
};
const struct iwl_cfg iwl9560_2ac_cfg_soc = {
.fw_name_pre = IWL9000_FW_PRE,
IWL_DEVICE_9000,
};
MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL9260_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2024 Intel Corporation
* Copyright (C) 2018-2025 Intel Corporation
*/
#include <linux/module.h>
#include <linux/stringify.h>
@ -15,14 +15,7 @@
/* Lowest firmware API version supported */
#define IWL_AX210_UCODE_API_MIN 77
/* NVM versions */
#define IWL_AX210_NVM_VERSION 0x0a1d
/* Memory offsets and lengths */
#define IWL_AX210_DCCM_OFFSET 0x800000 /* LMAC1 */
#define IWL_AX210_DCCM_LEN 0x10000 /* LMAC1 */
#define IWL_AX210_DCCM2_OFFSET 0x880000
#define IWL_AX210_DCCM2_LEN 0x8000
#define IWL_AX210_SMEM_OFFSET 0x400000
#define IWL_AX210_SMEM_LEN 0xD0000
@ -47,8 +40,7 @@
#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \
IWL_MA_B_HR_B_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl_ax210_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
static const struct iwl_family_base_params iwl_ax210_base = {
.num_of_queues = 512,
.max_tfd_queue_size = 65536,
.shadow_ram_support = true,
@ -57,74 +49,60 @@ static const struct iwl_base_params iwl_ax210_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
.smem_offset = IWL_AX210_SMEM_OFFSET,
.smem_len = IWL_AX210_SMEM_LEN,
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
.apmg_not_supported = true,
.mac_addr_from_csr = 0x380,
.min_umac_error_event_table = 0x400000,
.d3_debug_data_base_addr = 0x401000,
.d3_debug_data_length = 60 * 1024,
.mon_smem_regs = {
.write_ptr = {
.addr = LDBG_M2S_BUF_WPTR,
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
},
.cycle_cnt = {
.addr = LDBG_M2S_BUF_WRAP_CNT,
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
},
},
.min_txq_size = 128,
.gp2_reg_addr = 0xd02c68,
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_HE,
.mon_dram_regs = {
.write_ptr = {
.addr = DBGC_CUR_DBGBUF_STATUS,
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK,
},
.cycle_cnt = {
.addr = DBGC_DBGBUF_WRAP_AROUND,
.mask = 0xffffffff,
},
.cur_frag = {
.addr = DBGC_CUR_DBGBUF_STATUS,
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK,
},
},
.ucode_api_min = IWL_AX210_UCODE_API_MIN,
.ucode_api_max = IWL_AX210_UCODE_API_MAX,
};
#define IWL_DEVICE_AX210_COMMON \
.ucode_api_min = IWL_AX210_UCODE_API_MIN, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = 10, \
.non_shared_ant = ANT_B, \
.dccm_offset = IWL_AX210_DCCM_OFFSET, \
.dccm_len = IWL_AX210_DCCM_LEN, \
.dccm2_offset = IWL_AX210_DCCM2_OFFSET, \
.dccm2_len = IWL_AX210_DCCM2_LEN, \
.smem_offset = IWL_AX210_SMEM_OFFSET, \
.smem_len = IWL_AX210_SMEM_LEN, \
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
.apmg_not_supported = true, \
.trans.mq_rx_supported = true, \
.vht_mu_mimo_supported = true, \
.mac_addr_from_csr = 0x380, \
.ht_params = &iwl_22000_ht_params, \
.nvm_ver = IWL_AX210_NVM_VERSION, \
.trans.rf_id = true, \
.trans.gen2 = true, \
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true, \
.min_umac_error_event_table = 0x400000, \
.d3_debug_data_base_addr = 0x401000, \
.d3_debug_data_length = 60 * 1024, \
.mon_smem_regs = { \
.write_ptr = { \
.addr = LDBG_M2S_BUF_WPTR, \
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
}, \
.cycle_cnt = { \
.addr = LDBG_M2S_BUF_WRAP_CNT, \
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
}, \
}
#define IWL_DEVICE_AX210 \
IWL_DEVICE_AX210_COMMON, \
.ucode_api_max = IWL_AX210_UCODE_API_MAX, \
.trans.umac_prph_offset = 0x300000, \
.trans.device_family = IWL_DEVICE_FAMILY_AX210, \
.trans.base_params = &iwl_ax210_base_params, \
.min_txq_size = 128, \
.gp2_reg_addr = 0xd02c68, \
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_HE, \
.mon_dram_regs = { \
.write_ptr = { \
.addr = DBGC_CUR_DBGBUF_STATUS, \
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
}, \
.cycle_cnt = { \
.addr = DBGC_DBGBUF_WRAP_AROUND, \
.mask = 0xffffffff, \
}, \
.cur_frag = { \
.addr = DBGC_CUR_DBGBUF_STATUS, \
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
}, \
}
const struct iwl_cfg_trans_params iwl_so_trans_cfg = {
const struct iwl_mac_cfg iwl_ty_mac_cfg = {
.mq_rx_supported = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_AX210,
.base_params = &iwl_ax210_base_params,
.base = &iwl_ax210_base,
.umac_prph_offset = 0x300000,
/* TODO: the following values need to be checked */
.xtal_latency = 500,
};
const struct iwl_mac_cfg iwl_so_mac_cfg = {
.mq_rx_supported = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_AX210,
.base = &iwl_ax210_base,
.umac_prph_offset = 0x300000,
.integrated = true,
/* TODO: the following values need to be checked */
@ -132,12 +110,11 @@ const struct iwl_cfg_trans_params iwl_so_trans_cfg = {
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US,
};
const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {
const struct iwl_mac_cfg iwl_so_long_latency_mac_cfg = {
.mq_rx_supported = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_AX210,
.base_params = &iwl_ax210_base_params,
.base = &iwl_ax210_base,
.umac_prph_offset = 0x300000,
.integrated = true,
.low_latency_xtal = true,
@ -145,12 +122,11 @@ const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = {
const struct iwl_mac_cfg iwl_so_long_latency_imr_mac_cfg = {
.mq_rx_supported = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_AX210,
.base_params = &iwl_ax210_base_params,
.base = &iwl_ax210_base,
.umac_prph_offset = 0x300000,
.integrated = true,
.low_latency_xtal = true,
@ -159,107 +135,15 @@ const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = {
.imr_enabled = true,
};
/*
* If the device doesn't support HE, no need to have that many buffers.
* AX210 devices can split multiple frames into a single RB, so fewer are
* needed; AX210 cannot (but use smaller RBs by default) - these sizes
* were picked according to 8 MSDUs inside 256 A-MSDUs in an A-MPDU, with
* additional overhead to account for processing time.
*/
#define IWL_NUM_RBDS_NON_HE 512
#define IWL_NUM_RBDS_AX210_HE 4096
const struct iwl_cfg_trans_params iwl_ma_trans_cfg = {
const struct iwl_mac_cfg iwl_ma_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_AX210,
.base_params = &iwl_ax210_base_params,
.base = &iwl_ax210_base,
.mq_rx_supported = true,
.rf_id = true,
.gen2 = true,
.integrated = true,
.umac_prph_offset = 0x300000
};
const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz";
const char iwl_ax231_name[] = "Intel(R) Wi-Fi 6E AX231 160MHz";
const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz";
const char iwl_ax210_killer_1675w_name[] =
"Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)";
const char iwl_ax210_killer_1675x_name[] =
"Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)";
const char iwl_ax211_killer_1675s_name[] =
"Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211NGW)";
const char iwl_ax211_killer_1675i_name[] =
"Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)";
const char iwl_ax411_killer_1690s_name[] =
"Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)";
const char iwl_ax411_killer_1690i_name[] =
"Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)";
const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = {
.name = "Intel(R) Wireless-AC 9560 160MHz",
.fw_name_pre = IWL_SO_A_JF_B_FW_PRE,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_NON_HE,
};
const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = {
.name = iwl_ax211_name,
.fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long = {
.name = iwl_ax211_name,
.fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
.trans.xtal_latency = 12000,
.trans.low_latency_xtal = true,
};
const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {
.name = "Intel(R) Wi-Fi 6 AX210 160MHz",
.fw_name_pre = IWL_TY_A_GF_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = {
.name = iwl_ax411_name,
.fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long = {
.name = iwl_ax411_name,
.fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
.trans.xtal_latency = 12000,
.trans.low_latency_xtal = true,
};
const struct iwl_cfg iwl_cfg_ma = {
.fw_name_mac = "ma",
.uhb_supported = true,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
const struct iwl_cfg iwl_cfg_so_a0_hr_a0 = {
.fw_name_pre = IWL_SO_A_HR_B_FW_PRE,
IWL_DEVICE_AX210,
.num_rbds = IWL_NUM_RBDS_AX210_HE,
};
MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
IWL_FW_AND_PNVM(IWL_SO_A_GF_A_FW_PRE, IWL_AX210_UCODE_API_MAX);

@ -10,19 +10,12 @@
#include "fw/api/txq.h"
/* Highest firmware API version supported */
#define IWL_BZ_UCODE_API_MAX 98
#define IWL_BZ_UCODE_API_MAX 99
/* Lowest firmware API version supported */
#define IWL_BZ_UCODE_API_MIN 93
/* NVM versions */
#define IWL_BZ_NVM_VERSION 0x0a1d
/* Memory offsets and lengths */
#define IWL_BZ_DCCM_OFFSET 0x800000 /* LMAC1 */
#define IWL_BZ_DCCM_LEN 0x10000 /* LMAC1 */
#define IWL_BZ_DCCM2_OFFSET 0x880000
#define IWL_BZ_DCCM2_LEN 0x8000
#define IWL_BZ_SMEM_OFFSET 0x400000
#define IWL_BZ_SMEM_LEN 0xD0000
@ -38,13 +31,7 @@
#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \
IWL_BZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
#if !IS_ENABLED(CONFIG_IWLMVM)
const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz";
const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz";
#endif
static const struct iwl_base_params iwl_bz_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
static const struct iwl_family_base_params iwl_bz_base = {
.num_of_queues = 512,
.max_tfd_queue_size = 65536,
.shadow_ram_support = true,
@ -53,91 +40,55 @@ static const struct iwl_base_params iwl_bz_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
.smem_offset = IWL_BZ_SMEM_OFFSET,
.smem_len = IWL_BZ_SMEM_LEN,
.apmg_not_supported = true,
.mac_addr_from_csr = 0x30,
.min_umac_error_event_table = 0xD0000,
.d3_debug_data_base_addr = 0x401000,
.d3_debug_data_length = 60 * 1024,
.mon_smem_regs = {
.write_ptr = {
.addr = LDBG_M2S_BUF_WPTR,
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
},
.cycle_cnt = {
.addr = LDBG_M2S_BUF_WRAP_CNT,
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
},
},
.min_txq_size = 128,
.gp2_reg_addr = 0xd02c68,
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT,
.mon_dram_regs = {
.write_ptr = {
.addr = DBGC_CUR_DBGBUF_STATUS,
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK,
},
.cycle_cnt = {
.addr = DBGC_DBGBUF_WRAP_AROUND,
.mask = 0xffffffff,
},
.cur_frag = {
.addr = DBGC_CUR_DBGBUF_STATUS,
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK,
},
},
.mon_dbgi_regs = {
.write_ptr = {
.addr = DBGI_SRAM_FIFO_POINTERS,
.mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK,
},
},
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
.ucode_api_max = IWL_BZ_UCODE_API_MAX,
.ucode_api_min = IWL_BZ_UCODE_API_MIN,
};
const struct iwl_ht_params iwl_bz_ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) |
BIT(NL80211_BAND_6GHZ),
};
#define IWL_DEVICE_BZ_COMMON \
.ucode_api_max = IWL_BZ_UCODE_API_MAX, \
.ucode_api_min = IWL_BZ_UCODE_API_MIN, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = 10, \
.non_shared_ant = ANT_B, \
.dccm_offset = IWL_BZ_DCCM_OFFSET, \
.dccm_len = IWL_BZ_DCCM_LEN, \
.dccm2_offset = IWL_BZ_DCCM2_OFFSET, \
.dccm2_len = IWL_BZ_DCCM2_LEN, \
.smem_offset = IWL_BZ_SMEM_OFFSET, \
.smem_len = IWL_BZ_SMEM_LEN, \
.apmg_not_supported = true, \
.trans.mq_rx_supported = true, \
.vht_mu_mimo_supported = true, \
.mac_addr_from_csr = 0x30, \
.nvm_ver = IWL_BZ_NVM_VERSION, \
.trans.rf_id = true, \
.trans.gen2 = true, \
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true, \
.min_umac_error_event_table = 0xD0000, \
.d3_debug_data_base_addr = 0x401000, \
.d3_debug_data_length = 60 * 1024, \
.mon_smem_regs = { \
.write_ptr = { \
.addr = LDBG_M2S_BUF_WPTR, \
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
}, \
.cycle_cnt = { \
.addr = LDBG_M2S_BUF_WRAP_CNT, \
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
}, \
}, \
.trans.umac_prph_offset = 0x300000, \
.trans.device_family = IWL_DEVICE_FAMILY_BZ, \
.trans.base_params = &iwl_bz_base_params, \
.min_txq_size = 128, \
.gp2_reg_addr = 0xd02c68, \
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
.mon_dram_regs = { \
.write_ptr = { \
.addr = DBGC_CUR_DBGBUF_STATUS, \
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
}, \
.cycle_cnt = { \
.addr = DBGC_DBGBUF_WRAP_AROUND, \
.mask = 0xffffffff, \
}, \
.cur_frag = { \
.addr = DBGC_CUR_DBGBUF_STATUS, \
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
}, \
}, \
.mon_dbgi_regs = { \
.write_ptr = { \
.addr = DBGI_SRAM_FIFO_POINTERS, \
.mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
}, \
}
#define IWL_DEVICE_BZ \
IWL_DEVICE_BZ_COMMON, \
.ht_params = &iwl_bz_ht_params
/*
* This size was picked according to 8 MSDUs inside 512 A-MSDUs in an
* A-MPDU, with additional overhead to account for processing time.
*/
#define IWL_NUM_RBDS_BZ_EHT (512 * 16)
const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
const struct iwl_mac_cfg iwl_bz_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_BZ,
.base_params = &iwl_bz_base_params,
.base = &iwl_bz_base,
.mq_rx_supported = true,
.rf_id = true,
.gen2 = true,
.integrated = true,
.umac_prph_offset = 0x300000,
@ -146,38 +97,16 @@ const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
const struct iwl_cfg_trans_params iwl_gl_trans_cfg = {
const struct iwl_mac_cfg iwl_gl_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_BZ,
.base_params = &iwl_bz_base_params,
.base = &iwl_bz_base,
.mq_rx_supported = true,
.rf_id = true,
.gen2 = true,
.umac_prph_offset = 0x300000,
.xtal_latency = 12000,
.low_latency_xtal = true,
};
const char iwl_fm_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz";
const char iwl_wh_name[] = "Intel(R) Wi-Fi 7 BE211 320MHz";
const char iwl_gl_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz";
const char iwl_mtp_name[] = "Intel(R) Wi-Fi 7 BE202 160MHz";
const struct iwl_cfg iwl_cfg_bz = {
.fw_name_mac = "bz",
.uhb_supported = true,
IWL_DEVICE_BZ,
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
.num_rbds = IWL_NUM_RBDS_BZ_EHT,
};
const struct iwl_cfg iwl_cfg_gl = {
.fw_name_mac = "gl",
.uhb_supported = true,
IWL_DEVICE_BZ,
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
.num_rbds = IWL_NUM_RBDS_BZ_EHT,
};
MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
IWL_FW_AND_PNVM(IWL_BZ_A_GF_A_FW_PRE, IWL_BZ_UCODE_API_MAX);
IWL_FW_AND_PNVM(IWL_BZ_A_GF4_A_FW_PRE, IWL_BZ_UCODE_API_MAX);

@ -9,35 +9,21 @@
#include "fw/api/txq.h"
/* Highest firmware API version supported */
#define IWL_DR_UCODE_API_MAX 98
#define IWL_DR_UCODE_API_MAX 99
/* Lowest firmware API version supported */
#define IWL_DR_UCODE_API_MIN 96
/* NVM versions */
#define IWL_DR_NVM_VERSION 0x0a1d
#define IWL_DR_UCODE_API_MIN 97
/* Memory offsets and lengths */
#define IWL_DR_DCCM_OFFSET 0x800000 /* LMAC1 */
#define IWL_DR_DCCM_LEN 0x10000 /* LMAC1 */
#define IWL_DR_DCCM2_OFFSET 0x880000
#define IWL_DR_DCCM2_LEN 0x8000
#define IWL_DR_SMEM_OFFSET 0x400000
#define IWL_DR_SMEM_LEN 0xD0000
#define IWL_DR_A_PE_A_FW_PRE "iwlwifi-dr-a0-pe-a0"
#define IWL_BR_A_PET_A_FW_PRE "iwlwifi-br-a0-petc-a0"
#define IWL_BR_A_PE_A_FW_PRE "iwlwifi-br-a0-pe-a0"
#define IWL_DR_A_PE_A_FW_MODULE_FIRMWARE(api) \
IWL_DR_A_PE_A_FW_PRE "-" __stringify(api) ".ucode"
#define IWL_BR_A_PET_A_FW_MODULE_FIRMWARE(api) \
IWL_BR_A_PET_A_FW_PRE "-" __stringify(api) ".ucode"
#define IWL_BR_A_PE_A_FW_MODULE_FIRMWARE(api) \
IWL_BR_A_PE_A_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl_dr_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
static const struct iwl_family_base_params iwl_dr_base = {
.num_of_queues = 512,
.max_tfd_queue_size = 65536,
.shadow_ram_support = true,
@ -46,87 +32,55 @@ static const struct iwl_base_params iwl_dr_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
.smem_offset = IWL_DR_SMEM_OFFSET,
.smem_len = IWL_DR_SMEM_LEN,
.apmg_not_supported = true,
.mac_addr_from_csr = 0x30,
.min_umac_error_event_table = 0xD0000,
.d3_debug_data_base_addr = 0x401000,
.d3_debug_data_length = 60 * 1024,
.mon_smem_regs = {
.write_ptr = {
.addr = LDBG_M2S_BUF_WPTR,
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
},
.cycle_cnt = {
.addr = LDBG_M2S_BUF_WRAP_CNT,
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
},
},
.min_txq_size = 128,
.gp2_reg_addr = 0xd02c68,
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT,
.mon_dram_regs = {
.write_ptr = {
.addr = DBGC_CUR_DBGBUF_STATUS,
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK,
},
.cycle_cnt = {
.addr = DBGC_DBGBUF_WRAP_AROUND,
.mask = 0xffffffff,
},
.cur_frag = {
.addr = DBGC_CUR_DBGBUF_STATUS,
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK,
},
},
.mon_dbgi_regs = {
.write_ptr = {
.addr = DBGI_SRAM_FIFO_POINTERS,
.mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK,
},
},
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
.ucode_api_max = IWL_DR_UCODE_API_MAX,
.ucode_api_min = IWL_DR_UCODE_API_MIN,
};
#define IWL_DEVICE_DR_COMMON \
.ucode_api_max = IWL_DR_UCODE_API_MAX, \
.ucode_api_min = IWL_DR_UCODE_API_MIN, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = 10, \
.non_shared_ant = ANT_B, \
.dccm_offset = IWL_DR_DCCM_OFFSET, \
.dccm_len = IWL_DR_DCCM_LEN, \
.dccm2_offset = IWL_DR_DCCM2_OFFSET, \
.dccm2_len = IWL_DR_DCCM2_LEN, \
.smem_offset = IWL_DR_SMEM_OFFSET, \
.smem_len = IWL_DR_SMEM_LEN, \
.apmg_not_supported = true, \
.trans.mq_rx_supported = true, \
.vht_mu_mimo_supported = true, \
.mac_addr_from_csr = 0x30, \
.nvm_ver = IWL_DR_NVM_VERSION, \
.trans.rf_id = true, \
.trans.gen2 = true, \
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true, \
.min_umac_error_event_table = 0xD0000, \
.d3_debug_data_base_addr = 0x401000, \
.d3_debug_data_length = 60 * 1024, \
.mon_smem_regs = { \
.write_ptr = { \
.addr = LDBG_M2S_BUF_WPTR, \
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
}, \
.cycle_cnt = { \
.addr = LDBG_M2S_BUF_WRAP_CNT, \
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
}, \
}, \
.trans.umac_prph_offset = 0x300000, \
.trans.device_family = IWL_DEVICE_FAMILY_DR, \
.trans.base_params = &iwl_dr_base_params, \
.min_txq_size = 128, \
.gp2_reg_addr = 0xd02c68, \
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
.mon_dram_regs = { \
.write_ptr = { \
.addr = DBGC_CUR_DBGBUF_STATUS, \
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
}, \
.cycle_cnt = { \
.addr = DBGC_DBGBUF_WRAP_AROUND, \
.mask = 0xffffffff, \
}, \
.cur_frag = { \
.addr = DBGC_CUR_DBGBUF_STATUS, \
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
}, \
}, \
.mon_dbgi_regs = { \
.write_ptr = { \
.addr = DBGI_SRAM_FIFO_POINTERS, \
.mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
}, \
}
#define IWL_DEVICE_DR \
IWL_DEVICE_DR_COMMON, \
.uhb_supported = true, \
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
.num_rbds = IWL_NUM_RBDS_DR_EHT, \
.ht_params = &iwl_bz_ht_params
/*
* This size was picked according to 8 MSDUs inside 512 A-MSDUs in an
* A-MPDU, with additional overhead to account for processing time.
*/
#define IWL_NUM_RBDS_DR_EHT (512 * 16)
const struct iwl_cfg_trans_params iwl_dr_trans_cfg = {
const struct iwl_mac_cfg iwl_dr_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_DR,
.base_params = &iwl_dr_base_params,
.base = &iwl_dr_base,
.mq_rx_supported = true,
.rf_id = true,
.gen2 = true,
.integrated = true,
.umac_prph_offset = 0x300000,
@ -135,31 +89,5 @@ const struct iwl_cfg_trans_params iwl_dr_trans_cfg = {
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
const char iwl_dr_name[] = "Intel(R) TBD Dr device";
const struct iwl_cfg iwl_cfg_dr = {
.fw_name_mac = "dr",
IWL_DEVICE_DR,
};
const struct iwl_cfg_trans_params iwl_br_trans_cfg = {
.device_family = IWL_DEVICE_FAMILY_DR,
.base_params = &iwl_dr_base_params,
.mq_rx_supported = true,
.rf_id = true,
.gen2 = true,
.umac_prph_offset = 0x300000,
.xtal_latency = 12000,
.low_latency_xtal = true,
};
const char iwl_br_name[] = "Intel(R) TBD Br device";
const struct iwl_cfg iwl_cfg_br = {
.fw_name_mac = "br",
IWL_DEVICE_DR,
};
MODULE_FIRMWARE(IWL_DR_A_PE_A_FW_MODULE_FIRMWARE(IWL_DR_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BR_A_PET_A_FW_MODULE_FIRMWARE(IWL_DR_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_BR_A_PE_A_FW_MODULE_FIRMWARE(IWL_DR_UCODE_API_MAX));

@ -0,0 +1,51 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2025 Intel Corporation
*/
#include "iwl-config.h"
/* NVM versions */
#define IWL_FM_NVM_VERSION 0x0a1d
#define IWL_DEVICE_FM \
.ht_params = { \
.stbc = true, \
.ldpc = true, \
.ht40_bands = BIT(NL80211_BAND_2GHZ) | \
BIT(NL80211_BAND_5GHZ), \
}, \
.led_mode = IWL_LED_RF_STATE, \
.non_shared_ant = ANT_B, \
.vht_mu_mimo_supported = true, \
.uhb_supported = true, \
.num_rbds = IWL_NUM_RBDS_EHT, \
.nvm_ver = IWL_FM_NVM_VERSION, \
.nvm_type = IWL_NVM_EXT
const struct iwl_rf_cfg iwl_rf_fm = {
IWL_DEVICE_FM,
};
const struct iwl_rf_cfg iwl_rf_fm_160mhz = {
IWL_DEVICE_FM,
.bw_limit = 160,
};
const char iwl_killer_be1750s_name[] =
"Killer(R) Wi-Fi 7 BE1750s 320MHz Wireless Network Adapter (BE201D2W)";
const char iwl_killer_be1750i_name[] =
"Killer(R) Wi-Fi 7 BE1750i 320MHz Wireless Network Adapter (BE201NGW)";
const char iwl_killer_be1750w_name[] =
"Killer(TM) Wi-Fi 7 BE1750w 320MHz Wireless Network Adapter (BE200D2W)";
const char iwl_killer_be1750x_name[] =
"Killer(TM) Wi-Fi 7 BE1750x 320MHz Wireless Network Adapter (BE200NGW)";
const char iwl_killer_be1790s_name[] =
"Killer(R) Wi-Fi 7 BE1790s 320MHz Wireless Network Adapter (BE401D2W)";
const char iwl_killer_be1790i_name[] =
"Killer(R) Wi-Fi 7 BE1790i 320MHz Wireless Network Adapter (BE401NGW)";
const char iwl_be201_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz";
const char iwl_be200_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz";
const char iwl_be202_name[] = "Intel(R) Wi-Fi 7 BE202 160MHz";
const char iwl_be401_name[] = "Intel(R) Wi-Fi 7 BE401 320MHz";

@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2025 Intel Corporation
*/
#include "iwl-config.h"
/* NVM versions */
#define IWL_GF_NVM_VERSION 0x0a1d
const struct iwl_rf_cfg iwl_rf_gf = {
.uhb_supported = true,
.led_mode = IWL_LED_RF_STATE,
.non_shared_ant = ANT_B,
.vht_mu_mimo_supported = true,
.ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) |
BIT(NL80211_BAND_5GHZ),
},
.nvm_ver = IWL_GF_NVM_VERSION,
.nvm_type = IWL_NVM_EXT,
.num_rbds = IWL_NUM_RBDS_HE,
};
const char iwl_ax210_killer_1675w_name[] =
"Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)";
const char iwl_ax210_killer_1675x_name[] =
"Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)";
const char iwl_ax211_killer_1675s_name[] =
"Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211D2W)";
const char iwl_ax211_killer_1675i_name[] =
"Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)";
const char iwl_ax411_killer_1690s_name[] =
"Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)";
const char iwl_ax411_killer_1690i_name[] =
"Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)";
const char iwl_ax210_name[] = "Intel(R) Wi-Fi 6E AX210 160MHz";
const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz";
const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz";

@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2025 Intel Corporation
*/
#include "iwl-config.h"
/* NVM versions */
#define IWL_HR_NVM_VERSION 0x0a1d
#define IWL_DEVICE_HR \
.led_mode = IWL_LED_RF_STATE, \
.non_shared_ant = ANT_B, \
.vht_mu_mimo_supported = true, \
.ht_params = { \
.stbc = true, \
.ldpc = true, \
.ht40_bands = BIT(NL80211_BAND_2GHZ) | \
BIT(NL80211_BAND_5GHZ), \
}, \
.num_rbds = IWL_NUM_RBDS_HE, \
.nvm_ver = IWL_HR_NVM_VERSION, \
.nvm_type = IWL_NVM_EXT
const struct iwl_rf_cfg iwl_rf_hr1 = {
IWL_DEVICE_HR,
.tx_with_siso_diversity = true,
};
const struct iwl_rf_cfg iwl_rf_hr = {
IWL_DEVICE_HR,
};
const struct iwl_rf_cfg iwl_rf_hr_80mhz = {
IWL_DEVICE_HR,
.bw_limit = 80,
};
const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101";
const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz";
const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz";
const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203";

@ -0,0 +1,84 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2021, 2023, 2025 Intel Corporation
*/
#include "iwl-config.h"
/* NVM versions */
#define IWL_JF_NVM_VERSION 0x0a1d
/* Memory offsets and lengths */
#define IWL9000_DCCM_OFFSET 0x800000
#define IWL9000_DCCM_LEN 0x18000
#define IWL9000_DCCM2_OFFSET 0x880000
#define IWL9000_DCCM2_LEN 0x8000
static const struct iwl_tt_params iwl_jf_tt_params = {
.ct_kill_entry = 115,
.ct_kill_exit = 93,
.ct_kill_duration = 5,
.dynamic_smps_entry = 111,
.dynamic_smps_exit = 107,
.tx_protection_entry = 112,
.tx_protection_exit = 105,
.tx_backoff = {
{.temperature = 110, .backoff = 200},
{.temperature = 111, .backoff = 600},
{.temperature = 112, .backoff = 1200},
{.temperature = 113, .backoff = 2000},
{.temperature = 114, .backoff = 4000},
},
.support_ct_kill = true,
.support_dynamic_smps = true,
.support_tx_protection = true,
.support_tx_backoff = true,
};
/* these values are ignored if not with Pu/Th MAC firmware, due to offload */
#define IWL_DEVICE_JF_PU \
.dccm_offset = IWL9000_DCCM_OFFSET, \
.dccm_len = IWL9000_DCCM_LEN, \
.dccm2_offset = IWL9000_DCCM2_OFFSET, \
.dccm2_len = IWL9000_DCCM2_LEN, \
.thermal_params = &iwl_jf_tt_params
#define IWL_DEVICE_JF \
IWL_DEVICE_JF_PU, \
.led_mode = IWL_LED_RF_STATE, \
.non_shared_ant = ANT_B, \
.num_rbds = IWL_NUM_RBDS_NON_HE, \
.vht_mu_mimo_supported = true, \
.ht_params = { \
.stbc = true, \
.ldpc = true, \
.ht40_bands = BIT(NL80211_BAND_2GHZ) | \
BIT(NL80211_BAND_5GHZ), \
}, \
.nvm_ver = IWL_JF_NVM_VERSION, \
.nvm_type = IWL_NVM_EXT
const struct iwl_rf_cfg iwl_rf_jf = {
IWL_DEVICE_JF,
};
const struct iwl_rf_cfg iwl_rf_jf_80mhz = {
IWL_DEVICE_JF,
.bw_limit = 80,
};
const char iwl9260_name[] = "Intel(R) Wireless-AC 9260";
const char iwl9461_name[] = "Intel(R) Wireless-AC 9461";
const char iwl9462_name[] = "Intel(R) Wireless-AC 9462";
const char iwl9560_name[] = "Intel(R) Wireless-AC 9560";
const char iwl9260_160_name[] = "Intel(R) Wireless-AC 9260 160MHz";
const char iwl9461_160_name[] = "Intel(R) Wireless-AC 9461 160MHz";
const char iwl9462_160_name[] = "Intel(R) Wireless-AC 9462 160MHz";
const char iwl9560_160_name[] = "Intel(R) Wireless-AC 9560 160MHz";
const char iwl9260_killer_1550_name[] =
"Killer(R) Wireless-AC 1550 Wireless Network Adapter (9260NGW) 160MHz";
const char iwl9560_killer_1550i_name[] =
"Killer(R) Wireless-AC 1550i Wireless Network Adapter (9560NGW) 160MHz";
const char iwl9560_killer_1550s_name[] =
"Killer(R) Wireless-AC 1550s Wireless Network Adapter (9560D2W) 160MHz";

@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2025 Intel Corporation
*/
#include "iwl-config.h"
/* currently iwl_rf_wh/iwl_rf_wh_160mhz are just defines for the FM ones */
const char iwl_killer_bn1850w2_name[] =
"Killer(R) Wi-Fi 8 BN1850w2 320MHz Wireless Network Adapter (BN201.D2W)";
const char iwl_killer_bn1850i_name[] =
"Killer(R) Wi-Fi 8 BN1850i 320MHz Wireless Network Adapter (BN201.NGW)";
const char iwl_bn201_name[] = "Intel(R) Wi-Fi 8 BN201";
const char iwl_be221_name[] = "Intel(R) Wi-Fi 7 BE221";
const char iwl_be223_name[] = "Intel(R) Wi-Fi 7 BE223";

@ -0,0 +1,15 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2025 Intel Corporation
*/
#include "iwl-config.h"
/* currently iwl_rf_wh/iwl_rf_wh_160mhz are just defines for the FM ones */
const char iwl_killer_be1775s_name[] =
"Killer(R) Wi-Fi 7 BE1775s 320MHz Wireless Network Adapter (BE211D2W)";
const char iwl_killer_be1775i_name[] =
"Killer(R) Wi-Fi 7 BE1775i 320MHz Wireless Network Adapter (BE211NGW)";
const char iwl_be211_name[] = "Intel(R) Wi-Fi 7 BE211 320MHz";
const char iwl_be213_name[] = "Intel(R) Wi-Fi 7 BE213 160MHz";

@ -10,19 +10,15 @@
#include "fw/api/txq.h"
/* Highest firmware API version supported */
#define IWL_SC_UCODE_API_MAX 98
#define IWL_SC_UCODE_API_MAX 99
/* Lowest firmware API version supported */
#define IWL_SC_UCODE_API_MIN 93
#define IWL_SC_UCODE_API_MIN 97
/* NVM versions */
#define IWL_SC_NVM_VERSION 0x0a1d
/* Memory offsets and lengths */
#define IWL_SC_DCCM_OFFSET 0x800000 /* LMAC1 */
#define IWL_SC_DCCM_LEN 0x10000 /* LMAC1 */
#define IWL_SC_DCCM2_OFFSET 0x880000
#define IWL_SC_DCCM2_LEN 0x8000
#define IWL_SC_SMEM_OFFSET 0x400000
#define IWL_SC_SMEM_LEN 0xD0000
@ -43,8 +39,7 @@
#define IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(api) \
IWL_SC_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl_sc_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
static const struct iwl_family_base_params iwl_sc_base = {
.num_of_queues = 512,
.max_tfd_queue_size = 65536,
.shadow_ram_support = true,
@ -53,87 +48,55 @@ static const struct iwl_base_params iwl_sc_base_params = {
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
.smem_offset = IWL_SC_SMEM_OFFSET,
.smem_len = IWL_SC_SMEM_LEN,
.apmg_not_supported = true,
.mac_addr_from_csr = 0x30,
.min_umac_error_event_table = 0xD0000,
.d3_debug_data_base_addr = 0x401000,
.d3_debug_data_length = 60 * 1024,
.mon_smem_regs = {
.write_ptr = {
.addr = LDBG_M2S_BUF_WPTR,
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK,
},
.cycle_cnt = {
.addr = LDBG_M2S_BUF_WRAP_CNT,
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK,
},
},
.min_txq_size = 128,
.gp2_reg_addr = 0xd02c68,
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT,
.mon_dram_regs = {
.write_ptr = {
.addr = DBGC_CUR_DBGBUF_STATUS,
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK,
},
.cycle_cnt = {
.addr = DBGC_DBGBUF_WRAP_AROUND,
.mask = 0xffffffff,
},
.cur_frag = {
.addr = DBGC_CUR_DBGBUF_STATUS,
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK,
},
},
.mon_dbgi_regs = {
.write_ptr = {
.addr = DBGI_SRAM_FIFO_POINTERS,
.mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK,
},
},
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
.ucode_api_max = IWL_SC_UCODE_API_MAX,
.ucode_api_min = IWL_SC_UCODE_API_MIN,
};
#define IWL_DEVICE_BZ_COMMON \
.ucode_api_max = IWL_SC_UCODE_API_MAX, \
.ucode_api_min = IWL_SC_UCODE_API_MIN, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = 10, \
.non_shared_ant = ANT_B, \
.dccm_offset = IWL_SC_DCCM_OFFSET, \
.dccm_len = IWL_SC_DCCM_LEN, \
.dccm2_offset = IWL_SC_DCCM2_OFFSET, \
.dccm2_len = IWL_SC_DCCM2_LEN, \
.smem_offset = IWL_SC_SMEM_OFFSET, \
.smem_len = IWL_SC_SMEM_LEN, \
.apmg_not_supported = true, \
.trans.mq_rx_supported = true, \
.vht_mu_mimo_supported = true, \
.mac_addr_from_csr = 0x30, \
.nvm_ver = IWL_SC_NVM_VERSION, \
.trans.rf_id = true, \
.trans.gen2 = true, \
.nvm_type = IWL_NVM_EXT, \
.dbgc_supported = true, \
.min_umac_error_event_table = 0xD0000, \
.d3_debug_data_base_addr = 0x401000, \
.d3_debug_data_length = 60 * 1024, \
.mon_smem_regs = { \
.write_ptr = { \
.addr = LDBG_M2S_BUF_WPTR, \
.mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
}, \
.cycle_cnt = { \
.addr = LDBG_M2S_BUF_WRAP_CNT, \
.mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
}, \
}, \
.trans.umac_prph_offset = 0x300000, \
.trans.device_family = IWL_DEVICE_FAMILY_SC, \
.trans.base_params = &iwl_sc_base_params, \
.min_txq_size = 128, \
.gp2_reg_addr = 0xd02c68, \
.min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
.mon_dram_regs = { \
.write_ptr = { \
.addr = DBGC_CUR_DBGBUF_STATUS, \
.mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
}, \
.cycle_cnt = { \
.addr = DBGC_DBGBUF_WRAP_AROUND, \
.mask = 0xffffffff, \
}, \
.cur_frag = { \
.addr = DBGC_CUR_DBGBUF_STATUS, \
.mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
}, \
}, \
.mon_dbgi_regs = { \
.write_ptr = { \
.addr = DBGI_SRAM_FIFO_POINTERS, \
.mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
}, \
}
#define IWL_DEVICE_SC \
IWL_DEVICE_BZ_COMMON, \
.uhb_supported = true, \
.features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
.num_rbds = IWL_NUM_RBDS_SC_EHT, \
.ht_params = &iwl_bz_ht_params
/*
* This size was picked according to 8 MSDUs inside 512 A-MSDUs in an
* A-MPDU, with additional overhead to account for processing time.
*/
#define IWL_NUM_RBDS_SC_EHT (512 * 16)
const struct iwl_cfg_trans_params iwl_sc_trans_cfg = {
const struct iwl_mac_cfg iwl_sc_mac_cfg = {
.device_family = IWL_DEVICE_FAMILY_SC,
.base_params = &iwl_sc_base_params,
.base = &iwl_sc_base,
.mq_rx_supported = true,
.rf_id = true,
.gen2 = true,
.integrated = true,
.umac_prph_offset = 0x300000,
@ -142,21 +105,6 @@ const struct iwl_cfg_trans_params iwl_sc_trans_cfg = {
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
const struct iwl_cfg iwl_cfg_sc = {
.fw_name_mac = "sc",
IWL_DEVICE_SC,
};
const struct iwl_cfg iwl_cfg_sc2 = {
.fw_name_mac = "sc2",
IWL_DEVICE_SC,
};
const struct iwl_cfg iwl_cfg_sc2f = {
.fw_name_mac = "sc2f",
IWL_DEVICE_SC,
};
IWL_FW_AND_PNVM(IWL_SC_A_FM_B_FW_PRE, IWL_SC_UCODE_API_MAX);
IWL_FW_AND_PNVM(IWL_SC_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX);
MODULE_FIRMWARE(IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2021, 2024 Intel Corporation
* Copyright (C) 2005-2014, 2021, 2024-2025 Intel Corporation
*/
#ifndef __iwl_agn_h__
#define __iwl_agn_h__
@ -399,7 +399,7 @@ static inline void iwl_dvm_set_pmi(struct iwl_priv *priv, bool state)
* later with iwl_free_nvm_data().
*/
struct iwl_nvm_data *
iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
const u8 *eeprom, size_t eeprom_size);
int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size);

@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2018 Intel Corporation
* Copyright (C) 2018, 2025 Intel Corporation
*****************************************************************************/
#include <linux/slab.h>
@ -2097,7 +2097,8 @@ static ssize_t iwl_dbgfs_protection_mode_read(struct file *file,
char buf[40];
const size_t bufsz = sizeof(buf);
if (priv->cfg->ht_params)
/* HT devices also have at least one HT40 band */
if (priv->cfg->ht_params.ht40_bands)
pos += scnprintf(buf + pos, bufsz - pos,
"use %s for aggregation\n",
(priv->hw_params.use_rts_for_aggregation) ?
@ -2117,7 +2118,8 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
int buf_size;
int rts;
if (!priv->cfg->ht_params)
/* HT devices also have at least one HT40 band */
if (!priv->cfg->ht_params.ht40_bands)
return -EINVAL;
memset(buf, 0, sizeof(buf));

@ -2,6 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014, 2020, 2023 Intel Corporation. All rights reserved.
* Copyright (C) 2025 Intel Corporation
*****************************************************************************/
/*
* Please use this file (dev.h) for driver implementation definitions.
@ -627,7 +628,7 @@ struct iwl_priv {
struct iwl_trans *trans;
struct device *dev; /* for debug prints only */
const struct iwl_cfg *cfg;
const struct iwl_rf_cfg *cfg;
const struct iwl_fw *fw;
const struct iwl_dvm_cfg *lib;
unsigned long status;

@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2019, 2025 Intel Corporation
*****************************************************************************/
#include <linux/units.h>
@ -481,7 +481,7 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
/* NIC configuration for 6000 series */
static void iwl6000_nic_config(struct iwl_priv *priv)
{
switch (priv->trans->trans_cfg->device_family) {
switch (priv->trans->mac_cfg->device_family) {
case IWL_DEVICE_FAMILY_6005:
case IWL_DEVICE_FAMILY_6030:
case IWL_DEVICE_FAMILY_6000:

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2005-2014, 2018-2019, 2021, 2024 Intel Corporation
* Copyright (C) 2005-2014, 2018-2019, 2021, 2024-2025 Intel Corporation
*/
#include <linux/types.h>
#include <linux/slab.h>
@ -151,7 +151,7 @@ static u16 iwl_eeprom_query16(const u8 *eeprom, size_t eeprom_size, int offset)
{
if (WARN_ON(offset + sizeof(u16) > eeprom_size))
return 0;
return le16_to_cpup((__le16 *)(eeprom + offset));
return le16_to_cpup((const __le16 *)(eeprom + offset));
}
static u32 eeprom_indirect_address(const u8 *eeprom, size_t eeprom_size,
@ -204,8 +204,8 @@ static u32 eeprom_indirect_address(const u8 *eeprom, size_t eeprom_size,
return (address & ADDRESS_MSK) + (offset << 1);
}
static const u8 *iwl_eeprom_query_addr(const u8 *eeprom, size_t eeprom_size,
u32 offset)
static const void *iwl_eeprom_query_addr(const u8 *eeprom, size_t eeprom_size,
u32 offset)
{
u32 address = eeprom_indirect_address(eeprom, eeprom_size, offset);
@ -218,10 +218,9 @@ static const u8 *iwl_eeprom_query_addr(const u8 *eeprom, size_t eeprom_size,
static int iwl_eeprom_read_calib(const u8 *eeprom, size_t eeprom_size,
struct iwl_nvm_data *data)
{
struct iwl_eeprom_calib_hdr *hdr;
const struct iwl_eeprom_calib_hdr *hdr;
hdr = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size,
EEPROM_CALIB_ALL);
hdr = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_CALIB_ALL);
if (!hdr)
return -ENODATA;
data->calib_version = hdr->version;
@ -295,7 +294,7 @@ struct iwl_eeprom_enhanced_txpwr {
} __packed;
static s8 iwl_get_max_txpwr_half_dbm(const struct iwl_nvm_data *data,
struct iwl_eeprom_enhanced_txpwr *txp)
const struct iwl_eeprom_enhanced_txpwr *txp)
{
s8 result = 0; /* (.5 dBm) */
@ -329,7 +328,7 @@ static s8 iwl_get_max_txpwr_half_dbm(const struct iwl_nvm_data *data,
static void
iwl_eeprom_enh_txp_read_element(struct iwl_nvm_data *data,
struct iwl_eeprom_enhanced_txpwr *txp,
const struct iwl_eeprom_enhanced_txpwr *txp,
int n_channels, s8 max_txpower_avg)
{
int ch_idx;
@ -360,20 +359,18 @@ static void iwl_eeprom_enhanced_txpower(struct device *dev,
const u8 *eeprom, size_t eeprom_size,
int n_channels)
{
struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
const struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
int idx, entries;
__le16 *txp_len;
const __le16 *txp_len;
s8 max_txp_avg_halfdbm;
BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
/* the length is in 16-bit words, but we want entries */
txp_len = (__le16 *)iwl_eeprom_query_addr(eeprom, eeprom_size,
EEPROM_TXP_SZ_OFFS);
txp_len = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_TXP_SZ_OFFS);
entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
txp_array = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size,
EEPROM_TXP_OFFS);
txp_array = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_TXP_OFFS);
for (idx = 0; idx < entries; idx++) {
txp = &txp_array[idx];
@ -416,7 +413,7 @@ static void iwl_eeprom_enhanced_txpower(struct device *dev,
}
}
static void iwl_init_band_reference(const struct iwl_cfg *cfg,
static void iwl_init_band_reference(const struct iwl_rf_cfg *cfg,
const u8 *eeprom, size_t eeprom_size,
int eeprom_band, int *eeprom_ch_count,
const struct iwl_eeprom_channel **ch_info,
@ -426,7 +423,7 @@ static void iwl_init_band_reference(const struct iwl_cfg *cfg,
offset |= INDIRECT_ADDRESS | INDIRECT_REGULATORY;
*ch_info = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, offset);
*ch_info = iwl_eeprom_query_addr(eeprom, eeprom_size, offset);
switch (eeprom_band) {
case 1: /* 2.4GHz band */
@ -510,7 +507,7 @@ static void iwl_mod_ht40_chan_info(struct device *dev,
#define CHECK_AND_PRINT_I(x) \
((eeprom_ch_info[ch_idx].flags & EEPROM_CHANNEL_##x) ? # x " " : "")
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
static int iwl_init_channel_map(struct device *dev, const struct iwl_rf_cfg *cfg,
struct iwl_nvm_data *data,
const u8 *eeprom, size_t eeprom_size)
{
@ -749,7 +746,7 @@ static int iwl_nvm_is_otp(struct iwl_trans *trans)
u32 otpgp;
/* OTP only valid for CP/PP and after */
switch (trans->hw_rev & CSR_HW_REV_TYPE_MSK) {
switch (trans->info.hw_rev & CSR_HW_REV_TYPE_MSK) {
case CSR_HW_REV_TYPE_NONE:
IWL_ERR(trans, "Unknown hardware type\n");
return -EIO;
@ -784,7 +781,7 @@ static int iwl_init_otp_access(struct iwl_trans *trans)
* CSR auto clock gate disable bit -
* this is only applicable for HW with OTP shadow RAM
*/
if (trans->trans_cfg->base_params->shadow_ram_support)
if (trans->mac_cfg->base->shadow_ram_support)
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
CSR_RESET_LINK_PWR_MGMT_DISABLED);
@ -905,7 +902,7 @@ static int iwl_find_otp_image(struct iwl_trans *trans,
}
/* more in the link list, continue */
usedblocks++;
} while (usedblocks <= trans->trans_cfg->base_params->max_ll_items);
} while (usedblocks <= trans->mac_cfg->base->max_ll_items);
/* OTP has no valid blocks */
IWL_DEBUG_EEPROM(trans->dev, "OTP has no valid blocks\n");
@ -938,7 +935,7 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
if (nvm_is_otp < 0)
return nvm_is_otp;
sz = trans->trans_cfg->base_params->eeprom_size;
sz = trans->mac_cfg->base->eeprom_size;
IWL_DEBUG_EEPROM(trans->dev, "NVM size = %d\n", sz);
e = kmalloc(sz, GFP_KERNEL);
@ -973,7 +970,7 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
/* traversing the linked list if no shadow ram supported */
if (!trans->trans_cfg->base_params->shadow_ram_support) {
if (!trans->mac_cfg->base->shadow_ram_support) {
ret = iwl_find_otp_image(trans, &validblockaddr);
if (ret)
goto err_unlock;
@ -1027,7 +1024,7 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
return ret;
}
static void iwl_init_sbands(struct iwl_trans *trans, const struct iwl_cfg *cfg,
static void iwl_init_sbands(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
struct iwl_nvm_data *data,
const u8 *eeprom, size_t eeprom_size)
{
@ -1062,7 +1059,7 @@ static void iwl_init_sbands(struct iwl_trans *trans, const struct iwl_cfg *cfg,
/* EEPROM data functions */
struct iwl_nvm_data *
iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
const u8 *eeprom, size_t eeprom_size)
{
struct iwl_nvm_data *data;
@ -1098,14 +1095,14 @@ iwl_parse_eeprom_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
EEPROM_RAW_TEMPERATURE);
if (!tmp)
goto err_free;
data->raw_temperature = *(__le16 *)tmp;
data->raw_temperature = *(const __le16 *)tmp;
tmp = iwl_eeprom_query_addr(eeprom, eeprom_size,
EEPROM_KELVIN_TEMPERATURE);
if (!tmp)
goto err_free;
data->kelvin_temperature = *(__le16 *)tmp;
data->kelvin_voltage = *((__le16 *)tmp + 1);
data->kelvin_temperature = *(const __le16 *)tmp;
data->kelvin_voltage = *((const __le16 *)tmp + 1);
radio_cfg =
iwl_eeprom_query16(eeprom, eeprom_size, EEPROM_RADIO_CONFIG);

@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2019, 2025 Intel Corporation
*****************************************************************************/
@ -116,9 +116,9 @@ static int iwl_led_cmd(struct iwl_priv *priv,
}
led_cmd.on = iwl_blink_compensation(priv, on,
priv->trans->trans_cfg->base_params->led_compensation);
priv->trans->mac_cfg->base->led_compensation);
led_cmd.off = iwl_blink_compensation(priv, off,
priv->trans->trans_cfg->base_params->led_compensation);
priv->trans->mac_cfg->base->led_compensation);
ret = iwl_send_led_cmd(priv, &led_cmd);
if (!ret) {

@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(C) 2018 - 2019, 2022 - 2024 Intel Corporation
* Copyright(C) 2018 - 2019, 2022 - 2025 Intel Corporation
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@ -96,7 +96,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
if (priv->trans->max_skb_frags)
if (priv->trans->info.max_skb_frags)
hw->netdev_features = NETIF_F_HIGHDMA | NETIF_F_SG;
hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE;
@ -188,7 +188,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
priv->hw->wiphy->bands[NL80211_BAND_5GHZ] =
&priv->nvm_data->bands[NL80211_BAND_5GHZ];
hw->wiphy->hw_version = priv->trans->hw_id;
hw->wiphy->hw_version = priv->trans->info.hw_id;
iwl_leds_init(priv);
@ -549,7 +549,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
iwlagn_prepare_restart(priv);
memset((void *)&ctx->active, 0, sizeof(ctx->active));
memset((void *)(uintptr_t)&ctx->active, 0, sizeof(ctx->active));
iwl_connection_init_rx_config(priv, ctx);
iwlagn_set_rxon_chain(priv, ctx);
@ -1091,7 +1091,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
goto done;
}
scd_queues = BIT(priv->trans->trans_cfg->base_params->num_of_queues) - 1;
scd_queues = BIT(priv->trans->mac_cfg->base->num_of_queues) - 1;
scd_queues &= ~(BIT(IWL_IPAN_CMD_QUEUE_NUM) |
BIT(IWL_DEFAULT_CMD_QUEUE_NUM));

@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014, 2018 - 2022 Intel Corporation. All rights reserved.
* Copyright(c) 2024 Intel Corporation. All rights reserved.
* Copyright(c) 2024-2025 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
*
* Portions of this file are derived from the ipw3945 project, as well
@ -824,11 +824,11 @@ int iwl_alive_start(struct iwl_priv *priv)
iwlagn_send_tx_ant_config(priv, priv->nvm_data->valid_tx_ant);
if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
struct iwl_rxon_cmd *active_rxon =
(struct iwl_rxon_cmd *)&ctx->active;
struct iwl_rxon_cmd *active = (void *)(uintptr_t)&ctx->active;
/* apply any changes in staging */
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
active->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else {
struct iwl_rxon_context *tmp;
/* Initialize our rx_config data */
@ -1137,9 +1137,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
static void iwl_set_hw_params(struct iwl_priv *priv)
{
if (priv->cfg->ht_params)
/* there are no devices with HT but without HT40 on all bands */
if (priv->cfg->ht_params.ht40_bands)
priv->hw_params.use_rts_for_aggregation =
priv->cfg->ht_params->use_rts_for_aggregation;
priv->cfg->ht_params.use_rts_for_aggregation;
/* Device-specific setup */
priv->lib->set_hw_params(priv);
@ -1173,8 +1174,9 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
{
struct iwl_nvm_data *data = priv->nvm_data;
/* all HT devices also have HT40 on at least one band */
if (data->sku_cap_11n_enable &&
!priv->cfg->ht_params) {
!priv->cfg->ht_params.ht40_bands) {
IWL_ERR(priv, "Invalid 11n configuration\n");
return -EINVAL;
}
@ -1224,7 +1226,7 @@ static int iwl_nvm_check_version(struct iwl_nvm_data *data,
}
static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
const struct iwl_cfg *cfg,
const struct iwl_rf_cfg *cfg,
const struct iwl_fw *fw,
struct dentry *dbgfs_dir)
{
@ -1233,7 +1235,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
struct iwl_op_mode *op_mode;
u16 num_mac;
u32 ucode_flags;
struct iwl_trans_config trans_cfg = {};
static const u8 no_reclaim_cmds[] = {
REPLY_RX_PHY_CMD,
REPLY_RX_MPDU_CMD,
@ -1248,7 +1249,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
************************/
hw = iwl_alloc_all();
if (!hw) {
pr_err("%s: Cannot allocate network device\n", trans->name);
pr_err("%s: Cannot allocate network device\n",
trans->info.name);
err = -ENOMEM;
goto out;
}
@ -1261,7 +1263,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
priv->cfg = cfg;
priv->fw = fw;
switch (priv->trans->trans_cfg->device_family) {
switch (priv->trans->mac_cfg->device_family) {
case IWL_DEVICE_FAMILY_1000:
case IWL_DEVICE_FAMILY_100:
priv->lib = &iwl_dvm_1000_cfg;
@ -1309,52 +1311,50 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
* Populate the state variables that the transport layer needs
* to know about.
*/
trans_cfg.op_mode = op_mode;
trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
BUILD_BUG_ON(sizeof(no_reclaim_cmds) >
sizeof(trans->conf.no_reclaim_cmds));
memcpy(trans->conf.no_reclaim_cmds, no_reclaim_cmds,
sizeof(no_reclaim_cmds));
switch (iwlwifi_mod_params.amsdu_size) {
case IWL_AMSDU_DEF:
case IWL_AMSDU_4K:
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
trans->conf.rx_buf_size = IWL_AMSDU_4K;
break;
case IWL_AMSDU_8K:
trans_cfg.rx_buf_size = IWL_AMSDU_8K;
trans->conf.rx_buf_size = IWL_AMSDU_8K;
break;
case IWL_AMSDU_12K:
default:
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
trans->conf.rx_buf_size = IWL_AMSDU_4K;
pr_err("Unsupported amsdu_size: %d\n",
iwlwifi_mod_params.amsdu_size);
}
trans_cfg.command_groups = iwl_dvm_groups;
trans_cfg.command_groups_size = ARRAY_SIZE(iwl_dvm_groups);
trans->conf.command_groups = iwl_dvm_groups;
trans->conf.command_groups_size = ARRAY_SIZE(iwl_dvm_groups);
trans_cfg.cmd_fifo = IWLAGN_CMD_FIFO_NUM;
trans_cfg.cb_data_offs = offsetof(struct ieee80211_tx_info,
driver_data[2]);
trans->conf.cmd_fifo = IWLAGN_CMD_FIFO_NUM;
trans->conf.cb_data_offs = offsetof(struct ieee80211_tx_info,
driver_data[2]);
WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE <
priv->trans->trans_cfg->base_params->num_of_queues);
priv->trans->mac_cfg->base->num_of_queues);
ucode_flags = fw->ucode_capa.flags;
if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
trans->conf.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
} else {
priv->sta_key_max_num = STA_KEY_MAX_NUM;
trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
trans->conf.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
}
/* Configure transport layer */
iwl_trans_configure(priv->trans, &trans_cfg);
trans->conf.rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
trans->conf.rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
trans->command_groups = trans_cfg.command_groups;
trans->command_groups_size = trans_cfg.command_groups_size;
iwl_trans_op_mode_enter(priv->trans, op_mode);
/* At this point both hw and priv are allocated. */
@ -1378,18 +1378,18 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
* 2. Read REV register
***********************/
IWL_INFO(priv, "Detected %s, REV=0x%X\n",
priv->trans->name, priv->trans->hw_rev);
priv->trans->info.name, priv->trans->info.hw_rev);
err = iwl_trans_start_hw(priv->trans);
if (err)
goto out_free_hw;
goto out_leave_trans;
/* Read the EEPROM */
err = iwl_read_eeprom(priv->trans, &priv->eeprom_blob,
&priv->eeprom_blob_size);
if (err) {
IWL_ERR(priv, "Unable to init EEPROM\n");
goto out_free_hw;
goto out_leave_trans;
}
/* Reset chip to save power until we load uCode during "up". */
@ -1437,10 +1437,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
* packaging bug or due to the eeprom check above
*/
priv->sta_key_max_num = STA_KEY_MAX_NUM;
trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
/* Configure transport layer again*/
iwl_trans_configure(priv->trans, &trans_cfg);
trans->conf.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
}
/*******************
@ -1508,6 +1505,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
kfree(priv->eeprom_blob);
out_free_eeprom:
kfree(priv->nvm_data);
out_leave_trans:
iwl_trans_op_mode_leave(priv->trans);
out_free_hw:
ieee80211_free_hw(priv->hw);
out:
@ -1992,7 +1991,7 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
/* SKU Control */
iwl_trans_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP_DASH,
CSR_HW_REV_STEP_DASH(priv->trans->hw_rev));
CSR_HW_REV_STEP_DASH(priv->trans->info.hw_rev));
/* write radio config values to register */
if (priv->nvm_data->radio_cfg_type <= EEPROM_RF_CONFIG_TYPE_MAX) {

@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2019, 2025 Intel Corporation
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@ -64,32 +64,32 @@ struct iwl_power_vec_entry {
/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */
/* DTIM 0 - 2 */
static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 1, 2, 2, 0xFF)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1},
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 2, 4, 6, 0xFF)}, 2}
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 1, 2, 2, 0xFF), 0}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF), 0}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF), 0}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF), 0}, 1},
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 2, 4, 6, 0xFF), 0}, 2}
};
/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
/* DTIM 3 - 10 */
static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1},
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 6, 10, 10)}, 2}
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4), 0}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7), 0}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9), 0}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10), 0}, 1},
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 6, 10, 10), 0}, 2}
};
/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
/* DTIM 11 - */
static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF), 0}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF), 0}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF), 0}, 0},
{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF), 0}, 0},
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF), 0}, 0}
};
/* advance power management */
@ -196,7 +196,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
else
cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
if (priv->trans->trans_cfg->base_params->shadow_reg_enable)
if (priv->trans->mac_cfg->base->shadow_reg_enable)
cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
else
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;

@ -3,7 +3,7 @@
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
* Copyright(c) 2018, 2020-2021 Intel Corporation
* Copyright(c) 2018, 2020-2021, 2025 Intel Corporation
*
* Portions of this file are derived from the ipw3945 project, as well
* as portionhelp of the ieee80211 subsystem header files.
@ -50,7 +50,7 @@ static void iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb)
* See iwlagn_mac_channel_switch.
*/
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
struct iwl_rxon_cmd *rxon = (void *)(uintptr_t)&ctx->active;
if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
return;
@ -643,8 +643,8 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
fraglen = len - hdrlen;
if (fraglen) {
int offset = (void *)hdr + hdrlen -
rxb_addr(rxb) + rxb_offset(rxb);
int offset = (u8 *)hdr + hdrlen -
(u8 *)rxb_addr(rxb) + rxb_offset(rxb);
skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset,
fraglen, rxb->truesize);

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2003 - 2014, 2025 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
*****************************************************************************/
@ -341,7 +341,7 @@ static int iwlagn_rxon_disconn(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
int ret;
struct iwl_rxon_cmd *active = (void *)&ctx->active;
struct iwl_rxon_cmd *active = (void *)(uintptr_t)&ctx->active;
if (ctx->ctxid == IWL_RXON_CTX_BSS) {
ret = iwlagn_disable_bss(priv, ctx, &ctx->staging);
@ -441,7 +441,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
int ret;
struct iwl_rxon_cmd *active = (void *)&ctx->active;
struct iwl_rxon_cmd *active = (void *)(uintptr_t)&ctx->active;
/* RXON timing must be before associated RXON */
if (ctx->ctxid == IWL_RXON_CTX_BSS) {
@ -1023,7 +1023,7 @@ static void iwl_calc_basic_rates(struct iwl_priv *priv,
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
/* cast away the const for active_rxon in this function */
struct iwl_rxon_cmd *active = (void *)&ctx->active;
struct iwl_rxon_cmd *active = (void *)(uintptr_t)&ctx->active;
bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
int ret;

@ -3,7 +3,7 @@
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2023 Intel Corporation
* Copyright (C) 2023, 2025 Intel Corporation
*****************************************************************************/
#include <linux/kernel.h>
@ -463,7 +463,7 @@ static int iwlagn_alloc_agg_txq(struct iwl_priv *priv, int mq)
int q;
for (q = IWLAGN_FIRST_AMPDU_QUEUE;
q < priv->trans->trans_cfg->base_params->num_of_queues; q++) {
q < priv->trans->mac_cfg->base->num_of_queues; q++) {
if (!test_and_set_bit(q, priv->agg_q_alloc)) {
priv->queue_to_mac80211[q] = mq;
return q;
@ -1277,7 +1277,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
* (in Tx queue's circular buffer) of first TFD/frame in window */
u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
if (scd_flow >= priv->trans->trans_cfg->base_params->num_of_queues) {
if (scd_flow >= priv->trans->mac_cfg->base->num_of_queues) {
IWL_ERR(priv,
"BUG_ON scd_flow is bigger than number of queues\n");
return;

@ -3,6 +3,7 @@
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
* Copyright (C) 2025 Intel Corporation
*****************************************************************************/
#include <linux/kernel.h>
@ -222,7 +223,7 @@ static int iwl_alive_notify(struct iwl_priv *priv)
int ret;
int i;
iwl_trans_fw_alive(priv->trans, 0);
iwl_trans_fw_alive(priv->trans);
if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN &&
priv->nvm_data->sku_cap_ipan_enable) {
@ -293,15 +294,10 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
{
struct iwl_notification_wait alive_wait;
struct iwl_alive_data alive_data;
const struct fw_img *fw;
int ret;
enum iwl_ucode_type old_type;
static const u16 alive_cmd[] = { REPLY_ALIVE };
fw = iwl_get_ucode_image(priv->fw, ucode_type);
if (WARN_ON(!fw))
return -EINVAL;
old_type = priv->cur_ucode;
priv->cur_ucode = ucode_type;
priv->ucode_loaded = false;
@ -310,7 +306,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
alive_cmd, ARRAY_SIZE(alive_cmd),
iwl_alive_fn, &alive_data);
ret = iwl_trans_start_fw(priv->trans, fw, false);
ret = iwl_trans_start_fw(priv->trans, priv->fw, ucode_type, false);
if (ret) {
priv->cur_ucode = old_type;
iwl_remove_notification(&priv->notif_wait, &alive_wait);

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2019-2024 Intel Corporation
* Copyright (C) 2019-2025 Intel Corporation
*/
#include <linux/uuid.h>
#include "iwl-drv.h"
@ -847,12 +847,12 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
if (IS_ERR(data))
return PTR_ERR(data);
/* try to read ppag table rev 3, 2 or 1 (all have the same data size) */
/* try to read ppag table rev 1 to 4 (all have the same data size) */
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
ACPI_PPAG_WIFI_DATA_SIZE_V2, &tbl_rev);
if (!IS_ERR(wifi_pkg)) {
if (tbl_rev >= 1 && tbl_rev <= 3) {
if (tbl_rev >= 1 && tbl_rev <= 4) {
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
IWL_DEBUG_RADIO(fwrt,
"Reading PPAG table (tbl_rev=%d)\n",
@ -882,7 +882,7 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
goto out_free;
read_table:
fwrt->ppag_ver = tbl_rev;
fwrt->ppag_bios_rev = tbl_rev;
flags = &wifi_pkg->package.elements[1];
if (flags->type != ACPI_TYPE_INTEGER) {
@ -891,7 +891,7 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
}
fwrt->ppag_flags = iwl_bios_get_ppag_flags(flags->integer.value,
fwrt->ppag_ver);
fwrt->ppag_bios_rev);
/*
* read, verify gain values and save them into the PPAG table.
@ -912,6 +912,7 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
}
}
fwrt->ppag_bios_source = BIOS_SOURCE_ACPI;
ret = 0;
out_free:
@ -919,40 +920,39 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
return ret;
}
void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
struct iwl_phy_specific_cfg *filters)
int iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt)
{
struct iwl_phy_specific_cfg *filters = &fwrt->phy_filters;
struct iwl_phy_specific_cfg tmp = {};
union acpi_object *wifi_pkg, *data;
union acpi_object *wifi_pkg, *data __free(kfree);
int tbl_rev, i;
data = iwl_acpi_get_object(fwrt->dev, ACPI_WPFC_METHOD);
if (IS_ERR(data))
return;
return PTR_ERR(data);
wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
ACPI_WPFC_WIFI_DATA_SIZE,
&tbl_rev);
if (IS_ERR(wifi_pkg))
goto out_free;
return PTR_ERR(wifi_pkg);
if (tbl_rev != 0)
goto out_free;
return -EINVAL;
BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) !=
ACPI_WPFC_WIFI_DATA_SIZE - 1);
for (i = 0; i < ARRAY_SIZE(filters->filter_cfg_chains); i++) {
if (wifi_pkg->package.elements[i + 1].type != ACPI_TYPE_INTEGER)
goto out_free;
return -EINVAL;
tmp.filter_cfg_chains[i] =
cpu_to_le32(wifi_pkg->package.elements[i + 1].integer.value);
}
IWL_DEBUG_RADIO(fwrt, "Loaded WPFC filter config from ACPI\n");
*filters = tmp;
out_free:
kfree(data);
return 0;
}
IWL_EXPORT_SYMBOL(iwl_acpi_get_phy_filters);

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
* Copyright (C) 2018-2023 Intel Corporation
* Copyright (C) 2018-2023, 2025 Intel Corporation
*/
#ifndef __iwl_fw_acpi__
#define __iwl_fw_acpi__
@ -180,8 +180,7 @@ int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt,
int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt);
void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
struct iwl_phy_specific_cfg *filters);
int iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt);
void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt);
@ -244,8 +243,10 @@ static inline int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt)
return -ENOENT;
}
/* macro since the second argument doesn't always exist */
#define iwl_acpi_get_phy_filters(fwrt, filters) do { } while (0)
static inline int iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt)
{
return -ENOENT;
}
static inline void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt)
{

@ -112,6 +112,16 @@ struct iwl_alive_ntf_v6 {
struct iwl_imr_alive_info imr;
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_6 */
struct iwl_alive_ntf {
__le16 status;
__le16 flags;
struct iwl_lmac_alive lmac_data[2];
struct iwl_umac_alive umac_data;
struct iwl_sku_id sku_id;
struct iwl_imr_alive_info imr;
__le64 platform_id;
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_8 */
/**
* enum iwl_extended_cfg_flags - commands driver may send before
* finishing init flow

@ -2,7 +2,7 @@
/*
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2022, 2024 Intel Corporation
* Copyright (C) 2018-2022, 2024-2025 Intel Corporation
*/
#ifndef __iwl_fw_api_commands_h__
#define __iwl_fw_api_commands_h__
@ -145,8 +145,8 @@ enum iwl_legacy_cmds {
REMOVE_STA = 0x19,
/**
* @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2 or
* &struct iwl_tx_cmd_gen3,
* @TX_CMD: uses &struct iwl_tx_cmd_v6 or &struct iwl_tx_cmd_v9 or
* &struct iwl_tx_cmd,
* response in &struct iwl_tx_resp or
* &struct iwl_tx_resp_v3
*/

@ -98,7 +98,7 @@ enum iwl_data_path_subcmd_ids {
/**
* @ESR_MODE_NOTIF: notification to recommend/force a wanted esr mode,
* uses &struct iwl_esr_mode_notif
* uses &struct iwl_esr_mode_notif or &struct iwl_esr_mode_notif_v1
*/
ESR_MODE_NOTIF = 0xF3,

@ -6,6 +6,11 @@
*/
#ifndef __iwl_fw_api_location_h__
#define __iwl_fw_api_location_h__
#include <linux/ieee80211.h>
#include <linux/if_ether.h>
#include <linux/types.h>
#include <linux/bits.h>
#include "rs.h"
/**
* enum iwl_location_subcmd_ids - location group command IDs
@ -1609,7 +1614,7 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v5 {
} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_5 */
/**
* struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response)
* struct iwl_tof_range_rsp_ap_entry_ntfy_v7 - AP parameters (response)
* @bssid: BSSID of the AP
* @measure_status: current APs measurement status, one of
* &enum iwl_tof_entry_status.
@ -1645,7 +1650,7 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v5 {
* @tx_pn: the last PN used for this responder Tx in case PMF is configured in
* LE byte order.
*/
struct iwl_tof_range_rsp_ap_entry_ntfy {
struct iwl_tof_range_rsp_ap_entry_ntfy_v7 {
u8 bssid[ETH_ALEN];
u8 measure_status;
u8 measure_bw;
@ -1672,6 +1677,65 @@ struct iwl_tof_range_rsp_ap_entry_ntfy {
} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_6,
LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_7 */
/**
* struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response)
* @bssid: BSSID of the AP
* @measure_status: current APs measurement status, one of
* &enum iwl_tof_entry_status.
* @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz
* @rtt: The Round Trip Time that took for the last measurement for
* current AP [pSec]
* @rtt_variance: The Variance of the RTT values measured for current AP
* @rtt_spread: The Difference between the maximum and the minimum RTT
* values measured for current AP in the current session [pSec]
* @rssi: RSSI as uploaded in the Channel Estimation notification
* @rssi_spread: The Difference between the maximum and the minimum RSSI values
* measured for current AP in the current session
* @last_burst: 1 if no more FTM sessions are scheduled for this responder
* @refusal_period: refusal period in case of
* @IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE [sec]
* @timestamp: The GP2 Clock [usec] where Channel Estimation notification was
* uploaded by the LMAC
* @start_tsf: measurement start time in TSF of the mac specified in the range
* request
* @reserved1: reserved, for backwards compatibility
* @t2t3_initiator: as calculated from the algo in the initiator
* @t1t4_responder: as calculated from the algo in the responder
* @common_calib: Calib val that was used in for this AP measurement
* @specific_calib: val that was used in for this AP measurement
* @papd_calib_output: The result of the tof papd calibration that was injected
* into the algorithm.
* @rttConfidence: a value between 0 - 31 that represents the rtt accuracy.
* @reserved: for alignment
* @rx_pn: the last PN used for this responder Rx in case PMF is configured in
* LE byte order.
* @tx_pn: the last PN used for this responder Tx in case PMF is configured in
* LE byte order.
*/
struct iwl_tof_range_rsp_ap_entry_ntfy {
u8 bssid[ETH_ALEN];
u8 measure_status;
u8 measure_bw;
__le32 rtt;
__le32 rtt_variance;
__le32 rtt_spread;
s8 rssi;
u8 rssi_spread;
u8 last_burst;
u8 refusal_period;
__le32 timestamp;
__le32 start_tsf;
__le32 reserved1[2];
__le32 t2t3_initiator;
__le32 t1t4_responder;
__le16 common_calib;
__le16 specific_calib;
__le32 papd_calib_output;
u8 rttConfidence;
u8 reserved[3];
u8 rx_pn[IEEE80211_CCMP_PN_LEN];
u8 tx_pn[IEEE80211_CCMP_PN_LEN];
} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_8 */
/**
* enum iwl_tof_response_status - tof response status
@ -1738,6 +1802,24 @@ struct iwl_tof_range_rsp_ntfy_v7 {
struct iwl_tof_range_rsp_ap_entry_ntfy_v5 ap[IWL_TOF_MAX_APS];
} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_7 */
/**
* struct iwl_tof_range_rsp_ntfy_v9 - ranging response notification
* @request_id: A Token ID of the corresponding Range request
* @num_of_aps: Number of APs results
* @last_report: 1 if no more FTM sessions are scheduled, 0 otherwise.
* @reserved: reserved
* @ap: per-AP data
*/
struct iwl_tof_range_rsp_ntfy_v9 {
u8 request_id;
u8 num_of_aps;
u8 last_report;
u8 reserved;
struct iwl_tof_range_rsp_ap_entry_ntfy_v7 ap[IWL_TOF_MAX_APS];
} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_8,
* LOCATION_RANGE_RSP_NTFY_API_S_VER_9
*/
/**
* struct iwl_tof_range_rsp_ntfy - ranging response notification
* @request_id: A Token ID of the corresponding Range request
@ -1752,8 +1834,7 @@ struct iwl_tof_range_rsp_ntfy {
u8 last_report;
u8 reserved;
struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_TOF_MAX_APS];
} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_8,
LOCATION_RANGE_RSP_NTFY_API_S_VER_9 */
} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_10 */
#define IWL_MVM_TOF_MCSI_BUF_SIZE (245)
/**

@ -310,9 +310,42 @@ enum iwl_mac_config_filter_flags {
MAC_CFG_FILTER_ACCEPT_PROBE_REQ = BIT(5),
}; /* MAC_FILTER_FLAGS_MASK_E_VER_1 */
/**
* struct iwl_mac_wifi_gen_support_v2 - parameters of iwl_mac_config_cmd
* with support up to eht as in version 2 of the command
*
* @he_support: does this MAC support HE
* @he_ap_support: HE AP enabled, "pseudo HE", no trigger frame handling
* @eht_support: does this MAC support EHT. Requires he_support
*/
struct iwl_mac_wifi_gen_support_v2 {
__le16 he_support;
__le16 he_ap_support;
__le32 eht_support;
} __packed;
/**
* struct iwl_mac_wifi_gen_support - parameters of iwl_mac_config_cmd
* with support up to uhr as in version 3 of the command
* ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
*
* @he_support: does this MAC support HE
* @he_ap_support: HE AP enabled, "pseudo HE", no trigger frame handling
* @eht_support: does this MAC support EHT. Requires he_support
* @uhr_support: does this MAC support UHR. Requires eht_support
* @reserved: reserved for alignment and to match version 2's size
*/
struct iwl_mac_wifi_gen_support {
u8 he_support;
u8 he_ap_support;
u8 eht_support;
u8 uhr_support;
__le32 reserved;
} __packed;
/**
* struct iwl_mac_config_cmd - command structure to configure MAC contexts in
* MLD API
* MLD API for versions 2 and 3
* ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
*
* @id_and_color: ID and color of the MAC
@ -321,9 +354,8 @@ enum iwl_mac_config_filter_flags {
* @local_mld_addr: mld address
* @reserved_for_local_mld_addr: reserved
* @filter_flags: combination of &enum iwl_mac_config_filter_flags
* @he_support: does this MAC support HE
* @he_ap_support: HE AP enabled, "pseudo HE", no trigger frame handling
* @eht_support: does this MAC support EHT. Requires he_support
* @wifi_gen_v2: he/eht parameters as in cmd version 2
* @wifi_gen: he/eht/uhr parameters as in cmd version 3
* @nic_not_ack_enabled: mark that the NIC doesn't support receiving
* ACK-enabled AGG, (i.e. both BACK and non-BACK frames in single AGG).
* If the NIC is not ACK_ENABLED it may use the EOF-bit in first non-0
@ -332,7 +364,6 @@ enum iwl_mac_config_filter_flags {
* @p2p_dev: mac data for p2p device
*/
struct iwl_mac_config_cmd {
/* COMMON_INDEX_HDR_API_S_VER_1 */
__le32 id_and_color;
__le32 action;
/* MAC_CONTEXT_TYPE_API_E */
@ -340,16 +371,17 @@ struct iwl_mac_config_cmd {
u8 local_mld_addr[6];
__le16 reserved_for_local_mld_addr;
__le32 filter_flags;
__le16 he_support;
__le16 he_ap_support;
__le32 eht_support;
union {
struct iwl_mac_wifi_gen_support_v2 wifi_gen_v2;
struct iwl_mac_wifi_gen_support wifi_gen;
};
__le32 nic_not_ack_enabled;
/* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_2 */
union {
struct iwl_mac_client_data client;
struct iwl_mac_p2p_dev_data p2p_dev;
};
} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2 */
} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2_VER_3 */
/**
* enum iwl_link_ctx_modify_flags - indicate to the fw what fields are being
@ -456,6 +488,24 @@ enum iwl_link_modify_bandwidth {
IWL_LINK_MODIFY_BW_320,
};
/**
* struct iwl_npca_params - NPCA parameters (non-primary channel access)
*
* @switch_delay: after switch, delay TX according to destination AP
* @switch_back_delay: switch back to control channel before OBSS frame end
* @min_dur_threshold: minimum PPDU time to switch to the non-primary
* NPCA channel
* @flags: NPCA flags - bit 0: puncturing allowed, bit 1: new TX allowed
* @reserved: reserved for alignment purposes
*/
struct iwl_npca_params {
u8 switch_delay;
u8 switch_back_delay;
__le16 min_dur_threshold;
__le16 flags;
__le16 reserved;
} __packed; /* NPCA_PARAM_API_S_VER_1 */
/**
* struct iwl_link_config_cmd - command structure to configure the LINK context
* in MLD API
@ -513,6 +563,8 @@ enum iwl_link_modify_bandwidth {
* IEEE802.11REVme-D5.0
* @ibss_bssid_addr: bssid for ibss
* @reserved_for_ibss_bssid_addr: reserved
* @npca_params: NPCA parameters
* @prio_edca_params: priority EDCA parameters for enhanced QoS
* @reserved3: reserved for future use
*/
struct iwl_link_config_cmd {
@ -560,8 +612,10 @@ struct iwl_link_config_cmd {
u8 ul_mu_data_disable;
u8 ibss_bssid_addr[6];
__le16 reserved_for_ibss_bssid_addr;
__le32 reserved3[8];
} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3, _VER_4, _VER_5, _VER_6 */
struct iwl_npca_params npca_params; /* since _VER_7 */
struct iwl_ac_qos prio_edca_params; /* since _VER_7 */
__le32 reserved3[4];
} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3, _VER_4, _VER_5, _VER_6, _VER_7 */
/* Currently FW supports link ids in the range 0-3 and can have
* at most two active links for each vif.
@ -588,6 +642,62 @@ enum iwl_fw_sta_type {
STATION_TYPE_AUX,
}; /* STATION_TYPE_E_VER_1 */
/**
* struct iwl_sta_cfg_cmd_v1 - cmd structure to add a peer sta to the uCode's
* station table
* ( STA_CONFIG_CMD = 0xA )
*
* @sta_id: index of station in uCode's station table
* @link_id: the id of the link that is used to communicate with this sta
* @peer_mld_address: the peers mld address
* @reserved_for_peer_mld_address: reserved
* @peer_link_address: the address of the link that is used to communicate
* with this sta
* @reserved_for_peer_link_address: reserved
* @station_type: type of this station. See &enum iwl_fw_sta_type
* @assoc_id: for GO only
* @beamform_flags: beam forming controls
* @mfp: indicates whether the STA uses management frame protection or not.
* @mimo: indicates whether the sta uses mimo or not
* @mimo_protection: indicates whether the sta uses mimo protection or not
* @ack_enabled: indicates that the AP supports receiving ACK-
* enabled AGG, i.e. both BACK and non-BACK frames in a single AGG
* @trig_rnd_alloc: indicates that trigger based random allocation
* is enabled according to UORA element existence
* @tx_ampdu_spacing: minimum A-MPDU spacing:
* 4 - 2us density, 5 - 4us density, 6 - 8us density, 7 - 16us density
* @tx_ampdu_max_size: maximum A-MPDU length: 0 - 8K, 1 - 16K, 2 - 32K,
* 3 - 64K, 4 - 128K, 5 - 256K, 6 - 512K, 7 - 1024K.
* @sp_length: the size of the SP in actual number of frames
* @uapsd_acs: 4 LS bits are trigger enabled ACs, 4 MS bits are the deliver
* enabled ACs.
* @pkt_ext: optional, exists according to PPE-present bit in the HE/EHT-PHY
* capa
* @htc_flags: which features are supported in HTC
*/
struct iwl_sta_cfg_cmd_v1 {
__le32 sta_id;
__le32 link_id;
u8 peer_mld_address[ETH_ALEN];
__le16 reserved_for_peer_mld_address;
u8 peer_link_address[ETH_ALEN];
__le16 reserved_for_peer_link_address;
__le32 station_type;
__le32 assoc_id;
__le32 beamform_flags;
__le32 mfp;
__le32 mimo;
__le32 mimo_protection;
__le32 ack_enabled;
__le32 trig_rnd_alloc;
__le32 tx_ampdu_spacing;
__le32 tx_ampdu_max_size;
__le32 sp_length;
__le32 uapsd_acs;
struct iwl_he_pkt_ext_v2 pkt_ext;
__le32 htc_flags;
} __packed; /* STA_CMD_API_S_VER_1 */
/**
* struct iwl_sta_cfg_cmd - cmd structure to add a peer sta to the uCode's
* station table
@ -620,6 +730,14 @@ enum iwl_fw_sta_type {
* @pkt_ext: optional, exists according to PPE-present bit in the HE/EHT-PHY
* capa
* @htc_flags: which features are supported in HTC
* @use_ldpc_x2_cw: Indicates whether to use LDPC with double CW
* @use_icf: Indicates whether to use ICF instead of RTS
* @dps_pad_time: DPS (Dynamic Power Save) padding delay resolution to ensure
* proper timing alignment
* @dps_trans_delay: DPS minimal time that takes the peer to return to low power
* @mic_prep_pad_delay: MIC prep time padding
* @mic_compute_pad_delay: MIC compute time padding
* @reserved: Reserved for alignment
*/
struct iwl_sta_cfg_cmd {
__le32 sta_id;
@ -642,7 +760,14 @@ struct iwl_sta_cfg_cmd {
__le32 uapsd_acs;
struct iwl_he_pkt_ext_v2 pkt_ext;
__le32 htc_flags;
} __packed; /* STA_CMD_API_S_VER_1 */
u8 use_ldpc_x2_cw;
u8 use_icf;
u8 dps_pad_time;
u8 dps_trans_delay;
u8 mic_prep_pad_delay;
u8 mic_compute_pad_delay;
u8 reserved[2];
} __packed; /* STA_CMD_API_S_VER_2 */
/**
* struct iwl_aux_sta_cmd - command for AUX STA configuration
@ -686,9 +811,9 @@ struct iwl_mvm_sta_disable_tx_cmd {
/**
* enum iwl_mvm_fw_esr_recommendation - FW recommendation code
* @ESR_RECOMMEND_LEAVE: recommendation to leave esr
* @ESR_FORCE_LEAVE: force exiting esr
* @ESR_RECOMMEND_ENTER: recommendation to enter esr
* @ESR_RECOMMEND_LEAVE: recommendation to leave EMLSR
* @ESR_FORCE_LEAVE: force exiting EMLSR
* @ESR_RECOMMEND_ENTER: recommendation to enter EMLSR
*/
enum iwl_mvm_fw_esr_recommendation {
ESR_RECOMMEND_LEAVE,
@ -697,13 +822,44 @@ enum iwl_mvm_fw_esr_recommendation {
}; /* ESR_MODE_RECOMMENDATION_CODE_API_E_VER_1 */
/**
* struct iwl_esr_mode_notif - FWs recommendation/force for esr mode
* struct iwl_esr_mode_notif_v1 - FW recommendation/force for EMLSR mode
*
* @action: the action to apply on esr state. See &iwl_mvm_fw_esr_recommendation
* @action: the action to apply on EMLSR state.
* See &iwl_mvm_fw_esr_recommendation
*/
struct iwl_esr_mode_notif_v1 {
__le32 action;
} __packed; /* ESR_MODE_RECOMMENDATION_NTFY_API_S_VER_1 */
/**
* enum iwl_esr_leave_reason - reasons for leaving EMLSR mode
*
* @ESR_LEAVE_REASON_OMI_MU_UL_DISALLOWED: OMI MU UL disallowed
* @ESR_LEAVE_REASON_NO_TRIG_FOR_ESR_STA: No trigger for EMLSR station
* @ESR_LEAVE_REASON_NO_ESR_STA_IN_MU_DL: No EMLSR station in MU DL
* @ESR_LEAVE_REASON_BAD_ACTIV_FRAME_TH: Bad activation frame threshold
* @ESR_LEAVE_REASON_RTS_IN_DUAL_LISTEN: RTS in dual listen
*/
enum iwl_esr_leave_reason {
ESR_LEAVE_REASON_OMI_MU_UL_DISALLOWED = BIT(0),
ESR_LEAVE_REASON_NO_TRIG_FOR_ESR_STA = BIT(1),
ESR_LEAVE_REASON_NO_ESR_STA_IN_MU_DL = BIT(2),
ESR_LEAVE_REASON_BAD_ACTIV_FRAME_TH = BIT(3),
ESR_LEAVE_REASON_RTS_IN_DUAL_LISTEN = BIT(4),
};
/**
* struct iwl_esr_mode_notif - FW recommendation/force for EMLSR mode
*
* @action: the action to apply on EMLSR state.
* See &iwl_mvm_fw_esr_recommendation
* @leave_reason_mask: mask for various reasons to leave EMLSR mode.
* See &iwl_esr_leave_reason
*/
struct iwl_esr_mode_notif {
__le32 action;
} __packed; /* ESR_MODE_RECOMMENDATION_NTFY_API_S_VER_1 */
__le32 leave_reason_mask;
} __packed; /* ESR_MODE_RECOMMENDATION_NTFY_API_S_VER_2 */
/**
* struct iwl_missed_beacons_notif - sent when by the firmware upon beacon loss

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2022, 2024 Intel Corporation
* Copyright (C) 2012-2014, 2018-2022, 2024-2025 Intel Corporation
* Copyright (C) 2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_mac_h__
@ -287,9 +287,9 @@ struct iwl_ac_qos {
__le16 cw_min;
__le16 cw_max;
u8 aifsn;
u8 fifos_mask;
u8 fifos_mask; /* not in use since _VER_3 */
__le16 edca_txop;
} __packed; /* AC_QOS_API_S_VER_2 */
} __packed; /* AC_QOS_API_S_VER_2, _VER_3 */
/**
* struct iwl_mac_ctx_cmd - command structure to configure MAC contexts

@ -7,6 +7,8 @@
#ifndef __iwl_fw_api_power_h__
#define __iwl_fw_api_power_h__
#include "nvm-reg.h"
/* Power Management Commands, Responses, Notifications */
/**
@ -629,28 +631,37 @@ enum iwl_ppag_flags {
/**
* union iwl_ppag_table_cmd - union for all versions of PPAG command
* @v1: version 1
* @v2: version 2
* version 3, 4, 5 and 6 are the same structure as v2,
* @v1: command version 1 structure.
* @v2: command version from 2 to 6 are same structure as v2.
* but has a different format of the flags bitmap
* @v3: command version 7 structure.
* @v1.flags: values from &enum iwl_ppag_flags
* @v1.gain: table of antenna gain values per chain and sub-band
* @v1.reserved: reserved
* @v2.flags: values from &enum iwl_ppag_flags
* @v2.gain: table of antenna gain values per chain and sub-band
* @v2.reserved: reserved
* @v3.ppag_config_info: see @struct bios_value_u32
* @v3.gain: table of antenna gain values per chain and sub-band
* @v3.reserved: reserved
*/
union iwl_ppag_table_cmd {
struct {
__le32 flags;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1];
s8 reserved[2];
} v1;
} __packed v1; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_1 */
struct {
__le32 flags;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
s8 reserved[2];
} v2;
} __packed v2; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_2, VER3, VER4,
* VER5, VER6
*/
struct {
struct bios_value_u32 ppag_config_info;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
s8 reserved[2];
} __packed v3; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */
} __packed;
#define IWL_PPAG_CMD_V4_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK)
@ -658,6 +669,15 @@ union iwl_ppag_table_cmd {
IWL_PPAG_ETSI_LPI_UHB_MASK | \
IWL_PPAG_USA_LPI_UHB_MASK)
#define IWL_PPAG_CMD_V6_MASK (IWL_PPAG_CMD_V5_MASK | \
IWL_PPAG_ETSI_VLP_UHB_MASK | \
IWL_PPAG_ETSI_SP_UHB_MASK | \
IWL_PPAG_USA_VLP_UHB_MASK | \
IWL_PPAG_USA_SP_UHB_MASK | \
IWL_PPAG_CANADA_LPI_UHB_MASK | \
IWL_PPAG_CANADA_VLP_UHB_MASK | \
IWL_PPAG_CANADA_SP_UHB_MASK)
#define MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE 26
#define MCC_TO_SAR_OFFSET_TABLE_COL_SIZE 13

@ -1,11 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2022, 2024 Intel Corporation
* Copyright (C) 2012-2014, 2018-2022, 2024-2025 Intel Corporation
* Copyright (C) 2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_rs_h__
#define __iwl_fw_api_rs_h__
#include <linux/bitfield.h>
#include <linux/types.h>
#include <linux/bits.h>
#include "mac.h"
/**
@ -213,7 +215,8 @@ enum iwl_tlc_update_flags {
* @sta_id: station id
* @reserved: reserved
* @flags: bitmap of notifications reported
* @rate: current initial rate
* @rate: current initial rate, format depends on the notification
* version
* @amsdu_size: Max AMSDU size, in bytes
* @amsdu_enabled: bitmap for per-TID AMSDU enablement
*/
@ -224,7 +227,7 @@ struct iwl_tlc_update_notif {
__le32 rate;
__le32 amsdu_size;
__le32 amsdu_enabled;
} __packed; /* TLC_MNG_UPDATE_NTFY_API_S_VER_2 */
} __packed; /* TLC_MNG_UPDATE_NTFY_API_S_VER_2, _VER_3, _VER_4 */
/**
* enum iwl_tlc_debug_types - debug options
@ -427,6 +430,7 @@ enum {
/* Bit 4-5: (0) SISO, (1) MIMO2 (2) MIMO3 */
#define RATE_VHT_MCS_RATE_CODE_MSK 0xf
#define RATE_VHT_MCS_NSS_MSK 0x30
/*
* Legacy OFDM rate format for bits 7:0
@ -541,7 +545,7 @@ enum {
#define RATE_MCS_CTS_REQUIRED_POS (31)
#define RATE_MCS_CTS_REQUIRED_MSK (0x1 << RATE_MCS_CTS_REQUIRED_POS)
/* rate_n_flags bit field version 2
/* rate_n_flags bit field version 2 and 3
*
* The 32-bit value has different layouts in the low 8 bits depending on the
* format. There are three formats, HT, VHT and legacy (11abg, with subformats
@ -553,23 +557,25 @@ enum {
* (0) Legacy CCK (1) Legacy OFDM (2) High-throughput (HT)
* (3) Very High-throughput (VHT) (4) High-efficiency (HE)
* (5) Extremely High-throughput (EHT)
* (6) Ultra High Reliability (UHR) (v3 rate format only)
*/
#define RATE_MCS_MOD_TYPE_POS 8
#define RATE_MCS_MOD_TYPE_MSK (0x7 << RATE_MCS_MOD_TYPE_POS)
#define RATE_MCS_CCK_MSK (0 << RATE_MCS_MOD_TYPE_POS)
#define RATE_MCS_LEGACY_OFDM_MSK (1 << RATE_MCS_MOD_TYPE_POS)
#define RATE_MCS_HT_MSK (2 << RATE_MCS_MOD_TYPE_POS)
#define RATE_MCS_VHT_MSK (3 << RATE_MCS_MOD_TYPE_POS)
#define RATE_MCS_HE_MSK (4 << RATE_MCS_MOD_TYPE_POS)
#define RATE_MCS_EHT_MSK (5 << RATE_MCS_MOD_TYPE_POS)
#define RATE_MCS_MOD_TYPE_CCK (0 << RATE_MCS_MOD_TYPE_POS)
#define RATE_MCS_MOD_TYPE_LEGACY_OFDM (1 << RATE_MCS_MOD_TYPE_POS)
#define RATE_MCS_MOD_TYPE_HT (2 << RATE_MCS_MOD_TYPE_POS)
#define RATE_MCS_MOD_TYPE_VHT (3 << RATE_MCS_MOD_TYPE_POS)
#define RATE_MCS_MOD_TYPE_HE (4 << RATE_MCS_MOD_TYPE_POS)
#define RATE_MCS_MOD_TYPE_EHT (5 << RATE_MCS_MOD_TYPE_POS)
#define RATE_MCS_MOD_TYPE_UHR (6 << RATE_MCS_MOD_TYPE_POS)
/*
* Legacy CCK rate format for bits 0:3:
*
* (0) 0xa - 1 Mbps
* (1) 0x14 - 2 Mbps
* (2) 0x37 - 5.5 Mbps
* (3) 0x6e - 11 nbps
* (0) 1 Mbps
* (1) 2 Mbps
* (2) 5.5 Mbps
* (3) 11 Mbps
*
* Legacy OFDM rate format for bis 3:0:
*
@ -586,15 +592,19 @@ enum {
#define RATE_LEGACY_RATE_MSK 0x7
/*
* HT, VHT, HE, EHT rate format for bits 3:0
* 3-0: MCS
*
* HT, VHT, HE, EHT, UHR rate format
* Version 2: (not applicable for UHR)
* 3-0: MCS
* 4: NSS==2 indicator
* Version 3:
* 4-0: MCS
* 5: NSS==2 indicator
*/
#define RATE_HT_MCS_CODE_MSK 0x7
#define RATE_MCS_NSS_POS 4
#define RATE_MCS_NSS_MSK (1 << RATE_MCS_NSS_POS)
#define RATE_MCS_CODE_MSK 0xf
#define RATE_HT_MCS_INDEX(r) ((((r) & RATE_MCS_NSS_MSK) >> 1) | \
#define RATE_MCS_NSS_MSK_V2 0x10
#define RATE_MCS_NSS_MSK 0x20
#define RATE_MCS_CODE_MSK 0x1f
#define RATE_HT_MCS_INDEX(r) ((((r) & RATE_MCS_NSS_MSK) >> 2) | \
((r) & RATE_HT_MCS_CODE_MSK))
/* Bits 7-5: reserved */
@ -810,11 +820,38 @@ struct iwl_lq_cmd {
}; /* LINK_QUALITY_CMD_API_S_VER_1 */
u8 iwl_fw_rate_idx_to_plcp(int idx);
u32 iwl_new_rate_from_v1(u32 rate_v1);
const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx);
const char *iwl_rs_pretty_ant(u8 ant);
const char *iwl_rs_pretty_bw(int bw);
int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate);
bool iwl_he_is_sgi(u32 rate_n_flags);
static inline u32 iwl_v3_rate_from_v2_v3(__le32 rate, bool fw_v3)
{
u32 val;
if (fw_v3)
return le32_to_cpu(rate);
val = le32_to_cpu(rate) & ~RATE_MCS_NSS_MSK_V2;
val |= u32_encode_bits(le32_get_bits(rate, RATE_MCS_NSS_MSK_V2),
RATE_MCS_NSS_MSK);
return val;
}
static inline __le32 iwl_v3_rate_to_v2_v3(u32 rate, bool fw_v3)
{
__le32 val;
if (fw_v3)
return cpu_to_le32(rate);
val = cpu_to_le32(rate & ~RATE_MCS_NSS_MSK);
val |= le32_encode_bits(u32_get_bits(rate, RATE_MCS_NSS_MSK),
RATE_MCS_NSS_MSK_V2);
return val;
}
#endif /* __iwl_fw_api_rs_h__ */

@ -640,7 +640,9 @@ struct iwl_rx_mpdu_desc_v3 {
*/
__le32 reserved[1];
} __packed; /* RX_MPDU_RES_START_API_S_VER_3,
RX_MPDU_RES_START_API_S_VER_5 */
* RX_MPDU_RES_START_API_S_VER_5,
* RX_MPDU_RES_START_API_S_VER_6
*/
/**
* struct iwl_rx_mpdu_desc - RX MPDU descriptor
@ -724,8 +726,10 @@ struct iwl_rx_mpdu_desc {
struct iwl_rx_mpdu_desc_v3 v3;
};
} __packed; /* RX_MPDU_RES_START_API_S_VER_3,
RX_MPDU_RES_START_API_S_VER_4,
RX_MPDU_RES_START_API_S_VER_5 */
* RX_MPDU_RES_START_API_S_VER_4,
* RX_MPDU_RES_START_API_S_VER_5,
* RX_MPDU_RES_START_API_S_VER_6
*/
#define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1)
@ -821,7 +825,7 @@ struct iwl_rx_no_data {
* 15:8 chain-B, measured at FINA time (FINA_ENERGY), 16:23 channel
* @on_air_rise_time: GP2 during on air rise
* @fr_time: frame time
* @rate: rate/mcs of frame
* @rate: rate/mcs of frame, format depends on the notification version
* @phy_info: &enum iwl_rx_phy_eht_data0 and &enum iwl_rx_phy_info_type
* @rx_vec: DW-12:9 raw RX vectors from DSP according to modulation type.
* for VHT: OFDM_RX_VECTOR_SIGA1_OUT, OFDM_RX_VECTOR_SIGA2_OUT
@ -837,9 +841,7 @@ struct iwl_rx_no_data_ver_3 {
__le32 rate;
__le32 phy_info[2];
__le32 rx_vec[4];
} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1,
RX_NO_DATA_NTFY_API_S_VER_2
RX_NO_DATA_NTFY_API_S_VER_3 */
} __packed; /* RX_NO_DATA_NTFY_API_S_VER_3, _VER_4 */
struct iwl_frame_release {
u8 baid;

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018, 2024 Intel Corporation
* Copyright (C) 2012-2014, 2018, 2024-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@ -50,7 +50,7 @@ struct iwl_tdls_channel_switch_timing {
*/
struct iwl_tdls_channel_switch_frame {
__le32 switch_time_offset;
struct iwl_tx_cmd tx_cmd;
struct iwl_tx_cmd_v6 tx_cmd;
u8 data[IWL_TDLS_CH_SW_FRAME_MAX_SIZE];
} __packed; /* TDLS_STA_CHANNEL_SWITCH_FRAME_API_S_VER_1 */
@ -131,7 +131,7 @@ struct iwl_tdls_config_cmd {
struct iwl_tdls_sta_info sta_info[IWL_TDLS_STA_COUNT];
__le32 pti_req_data_offset;
struct iwl_tx_cmd pti_req_tx_cmd;
struct iwl_tx_cmd_v6 pti_req_tx_cmd;
u8 pti_req_template[];
} __packed; /* TDLS_CONFIG_CMD_API_S_VER_1 */

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_tx_h__
@ -151,7 +151,7 @@ enum iwl_tx_cmd_sec_ctrl {
#define IWL_LOW_RETRY_LIMIT 7
/**
* enum iwl_tx_offload_assist_flags_pos - set %iwl_tx_cmd offload_assist values
* enum iwl_tx_offload_assist_flags_pos - set %iwl_tx_cmd_v6 offload_assist values
* @TX_CMD_OFFLD_IP_HDR: offset to start of IP header (in words)
* from mac header end. For normal case it is 4 words for SNAP.
* note: tx_cmd, mac header and pad are not counted in the offset.
@ -181,7 +181,7 @@ enum iwl_tx_offload_assist_flags_pos {
/* TODO: complete documentation for try_cnt and btkill_cnt */
/**
* struct iwl_tx_cmd - TX command struct to FW
* struct iwl_tx_cmd_v6 - TX command struct to FW
* ( TX_CMD = 0x1c )
* @len: in bytes of the payload, see below for details
* @offload_assist: TX offload configuration
@ -221,7 +221,7 @@ enum iwl_tx_offload_assist_flags_pos {
* After the struct fields the MAC header is placed, plus any padding,
* and then the actial payload.
*/
struct iwl_tx_cmd {
struct iwl_tx_cmd_v6 {
__le16 len;
__le16 offload_assist;
__le32 tx_flags;
@ -258,7 +258,7 @@ struct iwl_dram_sec_info {
} __packed; /* DRAM_SEC_INFO_API_S_VER_1 */
/**
* struct iwl_tx_cmd_gen2 - TX command struct to FW for 22000 devices
* struct iwl_tx_cmd_v9 - TX command struct to FW for 22000 devices
* ( TX_CMD = 0x1c )
* @len: in bytes of the payload, see below for details
* @offload_assist: TX offload configuration
@ -268,7 +268,7 @@ struct iwl_dram_sec_info {
* cleared. Combination of RATE_MCS_*
* @hdr: 802.11 header
*/
struct iwl_tx_cmd_gen2 {
struct iwl_tx_cmd_v9 {
__le16 len;
__le16 offload_assist;
__le32 flags;
@ -279,18 +279,18 @@ struct iwl_tx_cmd_gen2 {
TX_CMD_API_S_VER_9 */
/**
* struct iwl_tx_cmd_gen3 - TX command struct to FW for AX210+ devices
* struct iwl_tx_cmd - TX command struct to FW for AX210+ devices
* ( TX_CMD = 0x1c )
* @len: in bytes of the payload, see below for details
* @flags: combination of &enum iwl_tx_cmd_flags
* @offload_assist: TX offload configuration
* @dram_info: FW internal DRAM storage
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
* cleared. Combination of RATE_MCS_*
* cleared. Combination of RATE_MCS_*; format depends on version
* @reserved: reserved
* @hdr: 802.11 header
*/
struct iwl_tx_cmd_gen3 {
struct iwl_tx_cmd {
__le16 len;
__le16 flags;
__le32 offload_assist;
@ -298,7 +298,9 @@ struct iwl_tx_cmd_gen3 {
__le32 rate_n_flags;
u8 reserved[8];
struct ieee80211_hdr hdr[];
} __packed; /* TX_CMD_API_S_VER_8, TX_CMD_API_S_VER_10 */
} __packed; /* TX_CMD_API_S_VER_10,
* TX_CMD_API_S_VER_11
*/
/*
* TX response related data
@ -549,7 +551,7 @@ struct iwl_tx_resp_v3 {
* @failure_rts: num of failures due to unsuccessful RTS
* @failure_frame: num failures due to no ACK (unused for agg)
* @initial_rate: for non-agg: rate of the successful Tx. For agg: rate of the
* Tx of all the batch. RATE_MCS_*
* Tx of all the batch. RATE_MCS_*; format depends on command version
* @wireless_media_time: for non-agg: RTS + CTS + frame tx attempts time + ACK.
* for agg: RTS + CTS + aggregation tx time + block-ack time.
* in usec.
@ -600,8 +602,10 @@ struct iwl_tx_resp {
__le16 reserved2;
struct agg_tx_status status;
} __packed; /* TX_RSP_API_S_VER_6,
TX_RSP_API_S_VER_7,
TX_RSP_API_S_VER_8 */
* TX_RSP_API_S_VER_7,
* TX_RSP_API_S_VER_8,
* TX_RSP_API_S_VER_9
*/
/**
* struct iwl_mvm_ba_notif - notifies about reception of BA
@ -701,7 +705,8 @@ enum iwl_mvm_ba_resp_flags {
* @rts_retry_cnt: RTS retry count
* @reserved: reserved (for alignment)
* @wireless_time: Wireless-media time
* @tx_rate: the rate the aggregation was sent at
* @tx_rate: the rate the aggregation was sent at. Format depends on command
* version.
* @tfd_cnt: number of TFD-Q elements
* @ra_tid_cnt: number of RATID-Q elements
* @tfd: array of TFD queue status updates. See &iwl_compressed_ba_tfd
@ -730,7 +735,8 @@ struct iwl_compressed_ba_notif {
DECLARE_FLEX_ARRAY(struct iwl_compressed_ba_tfd, tfd);
};
} __packed; /* COMPRESSED_BA_RES_API_S_VER_4,
COMPRESSED_BA_RES_API_S_VER_5 */
COMPRESSED_BA_RES_API_S_VER_6,
COMPRESSED_BA_RES_API_S_VER_7 */
/**
* struct iwl_mac_beacon_cmd_v6 - beacon template command
@ -742,7 +748,7 @@ struct iwl_compressed_ba_notif {
* @frame: the template of the beacon frame
*/
struct iwl_mac_beacon_cmd_v6 {
struct iwl_tx_cmd tx;
struct iwl_tx_cmd_v6 tx;
__le32 template_id;
__le32 tim_idx;
__le32 tim_size;
@ -761,7 +767,7 @@ struct iwl_mac_beacon_cmd_v6 {
* @frame: the template of the beacon frame
*/
struct iwl_mac_beacon_cmd_v7 {
struct iwl_tx_cmd tx;
struct iwl_tx_cmd_v6 tx;
__le32 template_id;
__le32 tim_idx;
__le32 tim_size;

@ -187,7 +187,7 @@ static void iwl_fw_dump_rxf(struct iwl_fw_runtime *fwrt,
/* Pull RXF2 */
iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
RXF_DIFF_FROM_PREV +
fwrt->trans->trans_cfg->umac_prph_offset, 1);
fwrt->trans->mac_cfg->umac_prph_offset, 1);
/* Pull LMAC2 RXF1 */
if (fwrt->smem_cfg.num_lmacs > 1)
iwl_fwrt_dump_rxf(fwrt, dump_data,
@ -654,10 +654,10 @@ static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr,
{
u32 range_len;
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
range_len = ARRAY_SIZE(iwl_prph_dump_addr_ax210);
handler(fwrt, iwl_prph_dump_addr_ax210, range_len, ptr);
} else if (fwrt->trans->trans_cfg->device_family >=
} else if (fwrt->trans->mac_cfg->device_family >=
IWL_DEVICE_FAMILY_22000) {
range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000);
handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr);
@ -665,7 +665,7 @@ static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr,
range_len = ARRAY_SIZE(iwl_prph_dump_addr_comm);
handler(fwrt, iwl_prph_dump_addr_comm, range_len, ptr);
if (fwrt->trans->trans_cfg->mq_rx_supported) {
if (fwrt->trans->mac_cfg->mq_rx_supported) {
range_len = ARRAY_SIZE(iwl_prph_dump_addr_9000);
handler(fwrt, iwl_prph_dump_addr_9000, range_len, ptr);
}
@ -809,13 +809,14 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
const struct iwl_fw_dbg_mem_seg_tlv *fw_mem = fwrt->fw->dbg.mem_tlv;
struct iwl_fwrt_shared_mem_cfg *mem_cfg = &fwrt->smem_cfg;
u32 file_len, fifo_len = 0, prph_len = 0, radio_len = 0;
u32 smem_len = fwrt->fw->dbg.n_mem_tlv ? 0 : fwrt->trans->cfg->smem_len;
u32 smem_len = fwrt->fw->dbg.n_mem_tlv ? 0 : fwrt->trans->mac_cfg->base->smem_len;
u32 sram2_len = fwrt->fw->dbg.n_mem_tlv ?
0 : fwrt->trans->cfg->dccm2_len;
int i;
/* SRAM - include stack CCM if driver knows the values for it */
if (!fwrt->trans->cfg->dccm_offset || !fwrt->trans->cfg->dccm_len) {
if (!fwrt->trans->cfg->dccm_offset ||
!fwrt->trans->cfg->dccm_len) {
const struct fw_img *img;
if (fwrt->cur_fw_img >= IWL_UCODE_TYPE_MAX)
@ -838,7 +839,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
iwl_fw_prph_handler(fwrt, &prph_len,
iwl_fw_get_prph_len);
if (fwrt->trans->trans_cfg->device_family ==
if (fwrt->trans->mac_cfg->device_family ==
IWL_DEVICE_FAMILY_7000 &&
iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RADIO_REG))
radio_len = sizeof(*dump_data) + RADIO_REG_MAX_READ;
@ -876,7 +877,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
file_len += sizeof(*dump_data) +
fwrt->trans->cfg->d3_debug_data_length * 2;
fwrt->trans->mac_cfg->base->d3_debug_data_length * 2;
}
/* If we only want a monitor dump, reset the file length */
@ -904,13 +905,14 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
dump_data->len = cpu_to_le32(sizeof(*dump_info));
dump_info = (void *)dump_data->data;
dump_info->hw_type =
cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->hw_rev));
cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->info.hw_rev));
dump_info->hw_step =
cpu_to_le32(fwrt->trans->hw_rev_step);
cpu_to_le32(fwrt->trans->info.hw_rev_step);
memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
sizeof(dump_info->fw_human_readable));
strscpy_pad(dump_info->dev_human_readable, fwrt->trans->name,
sizeof(dump_info->dev_human_readable));
strscpy_pad(dump_info->dev_human_readable,
fwrt->trans->info.name,
sizeof(dump_info->dev_human_readable));
strscpy_pad(dump_info->bus_human_readable, fwrt->dev->bus->name,
sizeof(dump_info->bus_human_readable));
dump_info->num_of_lmacs = fwrt->smem_cfg.num_lmacs;
@ -996,7 +998,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
}
iwl_fw_dump_mem(fwrt, &dump_data, smem_len,
fwrt->trans->cfg->smem_offset,
fwrt->trans->mac_cfg->base->smem_offset,
IWL_FW_ERROR_DUMP_MEM_SMEM);
iwl_fw_dump_mem(fwrt, &dump_data, sram2_len,
@ -1005,8 +1007,8 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
}
if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) {
u32 addr = fwrt->trans->cfg->d3_debug_data_base_addr;
size_t data_size = fwrt->trans->cfg->d3_debug_data_length;
u32 addr = fwrt->trans->mac_cfg->base->d3_debug_data_base_addr;
size_t data_size = fwrt->trans->mac_cfg->base->d3_debug_data_length;
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
dump_data->len = cpu_to_le32(data_size * 2);
@ -1109,7 +1111,7 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt,
range->internal_base_addr = cpu_to_le32(addr);
range->range_data_size = size;
if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
if (fwrt->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
indirect_wr_addr = WMAL_INDRCT_CMD1;
indirect_wr_addr += le32_to_cpu(offset);
@ -1266,7 +1268,7 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt,
/* all paged index start from 1 to skip CSS section */
idx++;
if (!fwrt->trans->trans_cfg->gen2)
if (!fwrt->trans->mac_cfg->gen2)
return _iwl_dump_ini_paging_iter(fwrt, range_ptr, range_len, idx);
range = range_ptr;
@ -1790,7 +1792,7 @@ iwl_dump_ini_mon_fill_header(struct iwl_fw_runtime *fwrt, u32 alloc_id,
data->write_ptr = iwl_get_mon_reg(fwrt, alloc_id,
&addrs->write_ptr);
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
u32 wrt_ptr = le32_to_cpu(data->write_ptr);
data->write_ptr = cpu_to_le32(wrt_ptr >> 2);
@ -1817,7 +1819,7 @@ iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt,
u32 alloc_id = le32_to_cpu(reg->dram_alloc_id);
return iwl_dump_ini_mon_fill_header(fwrt, alloc_id, mon_dump,
&fwrt->trans->cfg->mon_dram_regs);
&fwrt->trans->mac_cfg->base->mon_dram_regs);
}
static void *
@ -1830,7 +1832,7 @@ iwl_dump_ini_mon_smem_fill_header(struct iwl_fw_runtime *fwrt,
u32 alloc_id = le32_to_cpu(reg->internal_buffer.alloc_id);
return iwl_dump_ini_mon_fill_header(fwrt, alloc_id, mon_dump,
&fwrt->trans->cfg->mon_smem_regs);
&fwrt->trans->mac_cfg->base->mon_smem_regs);
}
static void *
@ -1844,7 +1846,7 @@ iwl_dump_ini_mon_dbgi_fill_header(struct iwl_fw_runtime *fwrt,
/* no offset calculation later */
IWL_FW_INI_ALLOCATION_ID_DBGC1,
mon_dump,
&fwrt->trans->cfg->mon_dbgi_regs);
&fwrt->trans->mac_cfg->base->mon_dbgi_regs);
}
static void *
@ -1909,7 +1911,7 @@ iwl_dump_ini_mem_block_ranges(struct iwl_fw_runtime *fwrt,
static u32 iwl_dump_ini_paging_ranges(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data)
{
if (fwrt->trans->trans_cfg->gen2) {
if (fwrt->trans->mac_cfg->gen2) {
if (fwrt->trans->init_dram.paging_cnt)
return fwrt->trans->init_dram.paging_cnt - 1;
else
@ -2021,7 +2023,7 @@ iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt,
/* start from 1 to skip CSS section */
for (i = 1; i <= iwl_dump_ini_paging_ranges(fwrt, reg_data); i++) {
size += range_header_len;
if (fwrt->trans->trans_cfg->gen2)
if (fwrt->trans->mac_cfg->gen2)
size += fwrt->trans->init_dram.paging[i].size;
else
size += fwrt->fw_paging_db[i].fw_paging_size;
@ -2375,7 +2377,7 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
struct iwl_fw_ini_dump_cfg_name *cfg_name;
u32 size = sizeof(*tlv) + sizeof(*dump);
u32 num_of_cfg_names = 0;
u32 hw_type;
u32 hw_type, is_cdb, is_jacket;
list_for_each_entry(node, &fwrt->trans->dbg.debug_info_tlv_list, list) {
size += sizeof(*cfg_name);
@ -2403,33 +2405,24 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
dump->ver_type = cpu_to_le32(fwrt->dump.fw_ver.type);
dump->ver_subtype = cpu_to_le32(fwrt->dump.fw_ver.subtype);
dump->hw_step = cpu_to_le32(fwrt->trans->hw_rev_step);
dump->hw_step = cpu_to_le32(fwrt->trans->info.hw_rev_step);
/*
* Several HWs all have type == 0x42, so we'll override this value
* according to the detected HW
*/
hw_type = CSR_HW_REV_TYPE(fwrt->trans->hw_rev);
if (hw_type == IWL_AX210_HW_TYPE) {
u32 prph_val = iwl_read_umac_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR);
u32 is_jacket = !!(prph_val & WFPM_OTP_CFG1_IS_JACKET_BIT);
u32 is_cdb = !!(prph_val & WFPM_OTP_CFG1_IS_CDB_BIT);
u32 masked_bits = is_jacket | (is_cdb << 1);
hw_type = CSR_HW_REV_TYPE(fwrt->trans->info.hw_rev);
is_cdb = CSR_HW_RFID_IS_CDB(fwrt->trans->info.hw_rf_id);
is_jacket = !!(iwl_read_umac_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR) &
WFPM_OTP_CFG1_IS_JACKET_BIT);
/* Use bits 12 and 13 to indicate jacket/CDB, respectively */
hw_type |= (is_jacket | (is_cdb << 1)) << IWL_JACKET_CDB_SHIFT;
/*
* The HW type depends on certain bits in this case, so add
* these bits to the HW type. We won't have collisions since we
* add these bits after the highest possible bit in the mask.
*/
hw_type |= masked_bits << IWL_AX210_HW_TYPE_ADDITION_SHIFT;
}
dump->hw_type = cpu_to_le32(hw_type);
dump->rf_id_flavor =
cpu_to_le32(CSR_HW_RFID_FLAVOR(fwrt->trans->hw_rf_id));
dump->rf_id_dash = cpu_to_le32(CSR_HW_RFID_DASH(fwrt->trans->hw_rf_id));
dump->rf_id_step = cpu_to_le32(CSR_HW_RFID_STEP(fwrt->trans->hw_rf_id));
dump->rf_id_type = cpu_to_le32(CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id));
cpu_to_le32(CSR_HW_RFID_FLAVOR(fwrt->trans->info.hw_rf_id));
dump->rf_id_dash = cpu_to_le32(CSR_HW_RFID_DASH(fwrt->trans->info.hw_rf_id));
dump->rf_id_step = cpu_to_le32(CSR_HW_RFID_STEP(fwrt->trans->info.hw_rf_id));
dump->rf_id_type = cpu_to_le32(CSR_HW_RFID_TYPE(fwrt->trans->info.hw_rf_id));
dump->lmac_major = cpu_to_le32(fwrt->dump.fw_ver.lmac_major);
dump->lmac_minor = cpu_to_le32(fwrt->dump.fw_ver.lmac_minor);
@ -2731,7 +2724,7 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
BUILD_BUG_ON((sizeof(trigger->regions_mask) * BITS_PER_BYTE) <
ARRAY_SIZE(fwrt->trans->dbg.active_regions));
if (trigger->time_point &
if (trigger->apply_policy &
cpu_to_le32(IWL_FW_INI_APPLY_POLICY_SPLIT_DUMP_RESET)) {
size += iwl_dump_ini_dump_regions(fwrt, dump_data, list, tp_id,
regions_mask, &imr_reg_data,
@ -3291,13 +3284,13 @@ void iwl_fw_error_dump_wk(struct work_struct *work)
void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)
{
const struct iwl_cfg *cfg = fwrt->trans->cfg;
const struct iwl_mac_cfg *mac_cfg = fwrt->trans->mac_cfg;
if (!iwl_fw_dbg_is_d3_debug_enabled(fwrt))
return;
if (!fwrt->dump.d3_debug_data) {
fwrt->dump.d3_debug_data = kmalloc(cfg->d3_debug_data_length,
fwrt->dump.d3_debug_data = kmalloc(mac_cfg->base->d3_debug_data_length,
GFP_KERNEL);
if (!fwrt->dump.d3_debug_data) {
IWL_ERR(fwrt,
@ -3307,15 +3300,15 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)
}
/* if the buffer holds previous debug data it is overwritten */
iwl_trans_read_mem_bytes(fwrt->trans, cfg->d3_debug_data_base_addr,
iwl_trans_read_mem_bytes(fwrt->trans, mac_cfg->base->d3_debug_data_base_addr,
fwrt->dump.d3_debug_data,
cfg->d3_debug_data_length);
mac_cfg->base->d3_debug_data_length);
if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx,
cfg->d3_debug_data_base_addr,
mac_cfg->base->d3_debug_data_base_addr,
fwrt->dump.d3_debug_data,
cfg->d3_debug_data_length);
mac_cfg->base->d3_debug_data_length);
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data);
@ -3350,7 +3343,7 @@ static int iwl_fw_dbg_suspend_resume_hcmd(struct iwl_trans *trans, bool suspend)
static void iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
struct iwl_fw_dbg_params *params)
{
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
return;
}
@ -3374,7 +3367,7 @@ static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
if (!params)
return -EIO;
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
@ -3476,7 +3469,7 @@ void iwl_fw_disable_dbg_asserts(struct iwl_fw_runtime *fwrt)
GENMASK(31, IWL_FW_DBG_DOMAIN_POS + 1));
/* supported starting from 9000 devices */
if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
if (fwrt->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000)
return;
if (fwrt->trans->dbg.yoyo_bin_loaded || (preset && preset != 1))

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2019, 2021-2024 Intel Corporation
* Copyright (C) 2005-2014, 2018-2019, 2021-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@ -201,7 +201,7 @@ static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt)
{
return fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_D3_DEBUG) &&
fwrt->trans->cfg->d3_debug_data_length && fwrt->ops &&
fwrt->trans->mac_cfg->base->d3_debug_data_length && fwrt->ops &&
fwrt->ops->d3_debug_enable &&
fwrt->ops->d3_debug_enable(fwrt->ops_ctx) &&
iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_D3_DEBUG_DATA);
@ -210,7 +210,7 @@ static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt)
static inline bool iwl_fw_dbg_is_paging_enabled(struct iwl_fw_runtime *fwrt)
{
return iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PAGING) &&
!fwrt->trans->trans_cfg->gen2 &&
!fwrt->trans->mac_cfg->gen2 &&
fwrt->cur_fw_img < IWL_UCODE_TYPE_MAX &&
fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size &&
fwrt->fw_paging_db[0].fw_paging_block;

@ -311,7 +311,7 @@ static ssize_t iwl_dbgfs_fw_ver_read(struct iwl_fw_runtime *fwrt,
pos += scnprintf(pos, endpos - pos, "FW: %s\n",
fwrt->fw->human_readable);
pos += scnprintf(pos, endpos - pos, "Device: %s\n",
fwrt->trans->name);
fwrt->trans->info.name);
pos += scnprintf(pos, endpos - pos, "Bus: %s\n",
fwrt->dev->bus->name);

Some files were not shown because too many files have changed in this diff Show More