From 2615e3cdbd9c0e864f5906279c952a309871d225 Mon Sep 17 00:00:00 2001 From: Anand K Mistry Date: Mon, 8 Feb 2021 13:32:09 +0200 Subject: [PATCH 01/15] ath10k: Fix suspicious RCU usage warning in ath10k_wmi_tlv_parse_peer_stats_info() The ieee80211_find_sta_by_ifaddr call in ath10k_wmi_tlv_parse_peer_stats_info must be called while holding the RCU read lock. Otherwise, the following warning will be seen when RCU usage checking is enabled: ============================= WARNING: suspicious RCU usage 5.10.3 #8 Tainted: G W ----------------------------- include/linux/rhashtable.h:594 suspicious rcu_dereference_check() usage! other info that might help us debug this: rcu_scheduler_active = 2, debug_locks = 1 no locks held by ksoftirqd/1/16. stack backtrace: CPU: 1 PID: 16 Comm: ksoftirqd/1 Tainted: G W 5.10.3 #8 Hardware name: HP Grunt/Grunt, BIOS Google_Grunt.11031.104.0 09/05/2019 Call Trace: dump_stack+0xab/0x115 sta_info_hash_lookup+0x71/0x1e9 [mac80211] ? lock_is_held_type+0xe6/0x12f ? __kasan_kmalloc+0xfb/0x112 ieee80211_find_sta_by_ifaddr+0x12/0x61 [mac80211] ath10k_wmi_tlv_parse_peer_stats_info+0xbd/0x10b [ath10k_core] ath10k_wmi_tlv_iter+0x8b/0x1a1 [ath10k_core] ? ath10k_wmi_tlv_iter+0x1a1/0x1a1 [ath10k_core] ath10k_wmi_tlv_event_peer_stats_info+0x103/0x13b [ath10k_core] ath10k_wmi_tlv_op_rx+0x722/0x80d [ath10k_core] ath10k_htc_rx_completion_handler+0x16e/0x1d7 [ath10k_core] ath10k_pci_process_rx_cb+0x116/0x22c [ath10k_pci] ? ath10k_htc_process_trailer+0x332/0x332 [ath10k_core] ? _raw_spin_unlock_irqrestore+0x34/0x61 ? lockdep_hardirqs_on+0x8e/0x12e ath10k_ce_per_engine_service+0x55/0x74 [ath10k_core] ath10k_ce_per_engine_service_any+0x76/0x84 [ath10k_core] ath10k_pci_napi_poll+0x49/0x141 [ath10k_pci] net_rx_action+0x11a/0x347 __do_softirq+0x2d3/0x539 run_ksoftirqd+0x4b/0x86 smpboot_thread_fn+0x1d0/0x2ab ? cpu_report_death+0x7f/0x7f kthread+0x189/0x191 ? cpu_report_death+0x7f/0x7f ? kthread_blkcg+0x31/0x31 ret_from_fork+0x22/0x30 Fixes: 0f7cb26830a6e ("ath10k: add rx bitrate report for SDIO") Signed-off-by: Anand K Mistry Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210202134451.1.I0d2e83c42755671b7143504b62787fd06cd914ed@changeid --- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 72d64af8e2296..bfdd017f14052 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -240,8 +240,10 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16 __le32_to_cpu(stat->last_tx_rate_code), __le32_to_cpu(stat->last_tx_bitrate_kbps)); + rcu_read_lock(); sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL); if (!sta) { + rcu_read_unlock(); ath10k_warn(ar, "not found station for peer stats\n"); return -EINVAL; } @@ -251,6 +253,7 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16 arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps); arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code); arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps); + rcu_read_unlock(); return 0; } From 7df28718928d08034b36168200d67b558ce36f3d Mon Sep 17 00:00:00 2001 From: Anand K Mistry Date: Mon, 8 Feb 2021 13:32:10 +0200 Subject: [PATCH 02/15] ath10k: Fix lockdep assertion warning in ath10k_sta_statistics ath10k_debug_fw_stats_request just be called with conf_mutex held, otherwise the following warning is seen when lock debugging is enabled: WARNING: CPU: 0 PID: 793 at drivers/net/wireless/ath/ath10k/debug.c:357 ath10k_debug_fw_stats_request+0x12c/0x133 [ath10k_core] Modules linked in: snd_hda_codec_hdmi designware_i2s snd_hda_intel snd_intel_dspcfg snd_hda_codec i2c_piix4 snd_hwdep snd_hda_core acpi_als kfifo_buf industrialio snd_soc_max98357a snd_soc_adau7002 snd_soc_acp_da7219mx98357_mach snd_soc_da7219 acp_audio_dma ccm xt_MASQUERADE fuse ath10k_pci ath10k_core lzo_rle ath lzo_compress mac80211 zram cfg80211 r8152 mii joydev CPU: 0 PID: 793 Comm: wpa_supplicant Tainted: G W 5.10.9 #5 Hardware name: HP Grunt/Grunt, BIOS Google_Grunt.11031.104.0 09/05/2019 RIP: 0010:ath10k_debug_fw_stats_request+0x12c/0x133 [ath10k_core] Code: 1e bb a1 ff ff ff 4c 89 ef 48 c7 c6 d3 31 2e c0 89 da 31 c0 e8 bd f8 ff ff 89 d8 eb 02 31 c0 5b 41 5c 41 5d 41 5e 41 5f 5d c3 <0f> 0b e9 04 ff ff ff 0f 1f 44 00 00 55 48 89 e5 41 56 53 48 89 fb RSP: 0018:ffffb2478099f7d0 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff9e432700cce0 RCX: 11c85cfd6b8e3b00 RDX: ffff9e432700cce0 RSI: ffff9e43127c5668 RDI: ffff9e4318deddf0 RBP: ffffb2478099f7f8 R08: 0000000000000002 R09: 00000003fd7068cc R10: ffffffffc01b2749 R11: ffffffffc029efaf R12: ffff9e432700c000 R13: ffff9e43127c33e0 R14: ffffb2478099f918 R15: ffff9e43127c33e0 FS: 00007f7ea48e2740(0000) GS:ffff9e432aa00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000059aa799ddf38 CR3: 0000000118de2000 CR4: 00000000001506f0 Call Trace: ath10k_sta_statistics+0x4d/0x270 [ath10k_core] sta_set_sinfo+0x1be/0xaec [mac80211] ieee80211_get_station+0x58/0x76 [mac80211] rdev_get_station+0xf1/0x11e [cfg80211] nl80211_get_station+0x7f/0x146 [cfg80211] genl_rcv_msg+0x32e/0x35e ? nl80211_stop_ap+0x19/0x19 [cfg80211] ? nl80211_get_station+0x146/0x146 [cfg80211] ? genl_rcv+0x19/0x36 ? genl_rcv+0x36/0x36 netlink_rcv_skb+0x89/0xfb genl_rcv+0x28/0x36 netlink_unicast+0x169/0x23b netlink_sendmsg+0x38a/0x402 sock_sendmsg+0x72/0x76 ____sys_sendmsg+0x153/0x1cc ? copy_msghdr_from_user+0x5d/0x85 ___sys_sendmsg+0x7c/0xb5 ? lock_acquire+0x181/0x23d ? syscall_trace_enter+0x15e/0x160 ? find_held_lock+0x3d/0xb2 ? syscall_trace_enter+0x15e/0x160 ? sched_clock_cpu+0x15/0xc6 __sys_sendmsg+0x62/0x9a do_syscall_64+0x43/0x55 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Fixes: 4913e675630e ("ath10k: enable rx duration report default for wmi tlv") Signed-off-by: Anand K Mistry Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210202144033.1.I9e556f9fb1110d58c31d04a8a1293995fb8bb678@changeid --- drivers/net/wireless/ath/ath10k/mac.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index d403c9fd49809..d8937181bbb98 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -9219,7 +9219,9 @@ static void ath10k_sta_statistics(struct ieee80211_hw *hw, if (!ath10k_peer_stats_enabled(ar)) return; + mutex_lock(&ar->conf_mutex); ath10k_debug_fw_stats_request(ar); + mutex_unlock(&ar->conf_mutex); sinfo->rx_duration = arsta->rx_duration; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION); From 4b965be536eefdd16ca0a88120fee23f5b92cd16 Mon Sep 17 00:00:00 2001 From: Karthikeyan Periyasamy Date: Mon, 8 Feb 2021 13:32:11 +0200 Subject: [PATCH 03/15] ath11k: Update tx descriptor search index properly Tx descriptor search index field should be updated with hw peer id and not by AST Hash as per the HW/FW recommendation. Incorrect search index causes throughput degradation in all scenario for all the platforms. so updated the search index field with hw peer id, which is a common change applicable for all the platforms. Also no need of these configuration for non station type. seen 10% throughput increase in WDS traffic with this change. Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-01492-QCAHKSWPL_SILICONZ-1 Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1612410960-9120-1-git-send-email-periyasa@codeaurora.org --- drivers/net/wireless/ath/ath11k/core.h | 1 + drivers/net/wireless/ath/ath11k/dp_rx.c | 8 ++++++-- drivers/net/wireless/ath/ath11k/dp_tx.c | 1 + drivers/net/wireless/ath/ath11k/hal_tx.c | 2 ++ drivers/net/wireless/ath/ath11k/hal_tx.h | 1 + drivers/net/wireless/ath/ath11k/peer.c | 9 +++++++-- drivers/net/wireless/ath/ath11k/peer.h | 3 ++- 7 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 9db375b193def..8d29845774dfa 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -200,6 +200,7 @@ struct ath11k_vif { u32 beacon_interval; u32 dtim_period; u16 ast_hash; + u16 ast_idx; u16 tcl_metadata; u8 hal_addr_search_flags; u8 search_type; diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 859cfcabceb56..850ad38b888f4 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -1652,6 +1652,7 @@ void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab, u8 mac_addr[ETH_ALEN]; u16 peer_mac_h16; u16 ast_hash; + u16 hw_peer_id; ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "dp_htt rx msg type :0x%0x\n", type); @@ -1672,7 +1673,7 @@ void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab, resp->peer_map_ev.info1); ath11k_dp_get_mac_addr(resp->peer_map_ev.mac_addr_l32, peer_mac_h16, mac_addr); - ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0); + ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0, 0); break; case HTT_T2H_MSG_TYPE_PEER_MAP2: vdev_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO_VDEV_ID, @@ -1685,7 +1686,10 @@ void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab, peer_mac_h16, mac_addr); ast_hash = FIELD_GET(HTT_T2H_PEER_MAP_INFO2_AST_HASH_VAL, resp->peer_map_ev.info2); - ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash); + hw_peer_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO1_HW_PEER_ID, + resp->peer_map_ev.info1); + ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash, + hw_peer_id); break; case HTT_T2H_MSG_TYPE_PEER_UNMAP: case HTT_T2H_MSG_TYPE_PEER_UNMAP2: diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index 6a3fcea6c2334..1a0b9be9ce6ae 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -165,6 +165,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif, ti.pkt_offset = 0; ti.lmac_id = ar->lmac_id; ti.bss_ast_hash = arvif->ast_hash; + ti.bss_ast_idx = arvif->ast_idx; ti.dscp_tid_tbl_idx = 0; if (skb->ip_summed == CHECKSUM_PARTIAL && diff --git a/drivers/net/wireless/ath/ath11k/hal_tx.c b/drivers/net/wireless/ath/ath11k/hal_tx.c index a755aa86c5dee..569e790d83a15 100644 --- a/drivers/net/wireless/ath/ath11k/hal_tx.c +++ b/drivers/net/wireless/ath/ath11k/hal_tx.c @@ -71,6 +71,8 @@ void ath11k_hal_tx_cmd_desc_setup(struct ath11k_base *ab, void *cmd, tcl_cmd->info3 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_DSCP_TID_TABLE_IDX, ti->dscp_tid_tbl_idx) | FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_SEARCH_INDEX, + ti->bss_ast_idx) | + FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_CACHE_SET_NUM, ti->bss_ast_hash); tcl_cmd->info4 = 0; } diff --git a/drivers/net/wireless/ath/ath11k/hal_tx.h b/drivers/net/wireless/ath/ath11k/hal_tx.h index d4760a20fdacb..c291e59c3ca6f 100644 --- a/drivers/net/wireless/ath/ath11k/hal_tx.h +++ b/drivers/net/wireless/ath/ath11k/hal_tx.h @@ -29,6 +29,7 @@ struct hal_tx_info { u32 flags1; /* %HAL_TCL_DATA_CMD_INFO2_ */ u16 addr_search_flags; /* %HAL_TCL_DATA_CMD_INFO0_ADDR(X/Y)_ */ u16 bss_ast_hash; + u16 bss_ast_idx; u8 tid; u8 search_type; /* %HAL_TX_ADDR_SEARCH_ */ u8 lmac_id; diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c index b69e7ebfa9303..f49abefa9618e 100644 --- a/drivers/net/wireless/ath/ath11k/peer.c +++ b/drivers/net/wireless/ath/ath11k/peer.c @@ -118,7 +118,7 @@ void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id) } void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, - u8 *mac_addr, u16 ast_hash) + u8 *mac_addr, u16 ast_hash, u16 hw_peer_id) { struct ath11k_peer *peer; @@ -132,6 +132,7 @@ void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, peer->vdev_id = vdev_id; peer->peer_id = peer_id; peer->ast_hash = ast_hash; + peer->hw_peer_id = hw_peer_id; ether_addr_copy(peer->addr, mac_addr); list_add(&peer->list, &ab->peers); wake_up(&ab->peer_mapping_wq); @@ -309,7 +310,11 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, peer->pdev_idx = ar->pdev_idx; peer->sta = sta; - arvif->ast_hash = peer->ast_hash; + + if (arvif->vif->type == NL80211_IFTYPE_STATION) { + arvif->ast_hash = peer->ast_hash; + arvif->ast_idx = peer->hw_peer_id; + } peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; diff --git a/drivers/net/wireless/ath/ath11k/peer.h b/drivers/net/wireless/ath/ath11k/peer.h index 8553ed061aeaa..619db001be8e9 100644 --- a/drivers/net/wireless/ath/ath11k/peer.h +++ b/drivers/net/wireless/ath/ath11k/peer.h @@ -14,6 +14,7 @@ struct ath11k_peer { int peer_id; u16 ast_hash; u8 pdev_idx; + u16 hw_peer_id; /* protected by ab->data_lock */ struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; @@ -31,7 +32,7 @@ struct ath11k_peer { void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id); void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, - u8 *mac_addr, u16 ast_hash); + u8 *mac_addr, u16 ast_hash, u16 hw_peer_id); struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, const u8 *addr); struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, From 84da2a84027c2bb88662dbfad8ebddc357c5c5ae Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Mon, 8 Feb 2021 13:32:11 +0200 Subject: [PATCH 04/15] wcn36xx: del BA session on TX stop Deleting BA session was not correcly performed, causing communication issues with APs that dynamically stop/start new BA sessions. Signed-off-by: Loic Poulain Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1611328304-1010-1-git-send-email-loic.poulain@linaro.org --- drivers/net/wireless/ath/wcn36xx/main.c | 3 ++- drivers/net/wireless/ath/wcn36xx/smd.c | 4 ++-- drivers/net/wireless/ath/wcn36xx/smd.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 5867bd9c2f646..afb4877eaad8f 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -1140,7 +1140,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, session); break; case IEEE80211_AMPDU_RX_STOP: - wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); + wcn36xx_smd_del_ba(wcn, tid, 0, get_sta_index(vif, sta_priv)); break; case IEEE80211_AMPDU_TX_START: spin_lock_bh(&sta_priv->ampdu_lock); @@ -1164,6 +1164,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_NONE; spin_unlock_bh(&sta_priv->ampdu_lock); + wcn36xx_smd_del_ba(wcn, tid, 1, get_sta_index(vif, sta_priv)); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; default: diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 28d3ee3ad4b9c..d0c3a1557e8d6 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -2466,7 +2466,7 @@ int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id) return ret; } -int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index) +int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 direction, u8 sta_index) { struct wcn36xx_hal_del_ba_req_msg msg_body; int ret; @@ -2476,7 +2476,7 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index) msg_body.sta_index = sta_index; msg_body.tid = tid; - msg_body.direction = 0; + msg_body.direction = direction; PREPARE_HAL_BUF(wcn->hal_buf, msg_body); ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h index b1d8083d9d9d5..462860572e1f8 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.h +++ b/drivers/net/wireless/ath/wcn36xx/smd.h @@ -135,7 +135,7 @@ int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, u8 direction, u8 sta_index); int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id); -int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index); +int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 direction, u8 sta_index); int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u8 session_id); int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value); From ca9ad549e4042089d55a68f0312647fca4cc6e87 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 4 Feb 2021 17:29:17 +0100 Subject: [PATCH 05/15] carl9170: fix struct alignment conflict Multiple structures in the carl9170 driver have alignment impossible alignment constraints that gcc warns about when building with 'make W=1': drivers/net/wireless/ath/carl9170/fwcmd.h:243:2: warning: alignment 1 of 'union ' is less than 4 [-Wpacked-not-aligned] drivers/net/wireless/ath/carl9170/wlan.h:373:1: warning: alignment 1 of 'struct ar9170_rx_frame_single' is less than 2 [-Wpacked-not-aligned] In the carl9170_cmd structure, multiple members that have an explicit alignment requirement of four bytes are added into a union with explicit byte alignment, but this in turn is part of a structure that also has four-byte alignment. In the wlan.h header, multiple structures contain a ieee80211_hdr member that is required to be two-byte aligned to avoid alignmnet faults when processing network headers, but all members are forced to be byte-aligned using the __packed tag at the end of the struct definition. In both cases, leaving out the packing does not change the internal layout of the structure but changes the alignment constraint of the structure itself. Change all affected structures to only apply packing where it does not violate the alignment requirement of the contained structure. Signed-off-by: Arnd Bergmann Acked-by: Christian Lamparter Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210204162926.3262598-1-arnd@kernel.org --- drivers/net/wireless/ath/carl9170/fwcmd.h | 2 +- drivers/net/wireless/ath/carl9170/wlan.h | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index 56999a3b9d3bc..4a500095555c6 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h @@ -240,7 +240,7 @@ struct carl9170_cmd { struct carl9170_bcn_ctrl_cmd bcn_ctrl; struct carl9170_rx_filter_cmd rx_filter; u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; - } __packed; + } __packed __aligned(4); } __packed __aligned(4); #define CARL9170_TX_STATUS_QUEUE 3 diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h index ea17995b32f4e..bb73553fd7c27 100644 --- a/drivers/net/wireless/ath/carl9170/wlan.h +++ b/drivers/net/wireless/ath/carl9170/wlan.h @@ -367,27 +367,27 @@ struct ar9170_rx_macstatus { struct ar9170_rx_frame_single { struct ar9170_rx_head phy_head; - struct ieee80211_hdr i3e; + struct ieee80211_hdr i3e __packed __aligned(2); struct ar9170_rx_phystatus phy_tail; struct ar9170_rx_macstatus macstatus; -} __packed; +}; struct ar9170_rx_frame_head { struct ar9170_rx_head phy_head; - struct ieee80211_hdr i3e; + struct ieee80211_hdr i3e __packed __aligned(2); struct ar9170_rx_macstatus macstatus; -} __packed; +}; struct ar9170_rx_frame_middle { - struct ieee80211_hdr i3e; + struct ieee80211_hdr i3e __packed __aligned(2); struct ar9170_rx_macstatus macstatus; -} __packed; +}; struct ar9170_rx_frame_tail { - struct ieee80211_hdr i3e; + struct ieee80211_hdr i3e __packed __aligned(2); struct ar9170_rx_phystatus phy_tail; struct ar9170_rx_macstatus macstatus; -} __packed; +}; struct ar9170_rx_frame { union { @@ -395,8 +395,8 @@ struct ar9170_rx_frame { struct ar9170_rx_frame_head head; struct ar9170_rx_frame_middle middle; struct ar9170_rx_frame_tail tail; - } __packed; -} __packed; + }; +}; static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t) { From 97614c59cb72b26ebebec4334921c9ae8fb895e6 Mon Sep 17 00:00:00 2001 From: Tamizh Chelvam Date: Fri, 5 Feb 2021 00:05:38 +0530 Subject: [PATCH 06/15] ath10k: Add new debug level for sta related logs Add new level ATH10K_DBG_STA debug_mask for printing sta related logs. This will be useful to check the debug logs of connection and changes related to station. Tested-on: QCA9984 hw1.0 PCI 10.4-3.9.0.2-00021 Signed-off-by: Tamizh Chelvam Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1612463738-16542-1-git-send-email-tamizhr@codeaurora.org --- drivers/net/wireless/ath/ath10k/debug.h | 1 + drivers/net/wireless/ath/ath10k/mac.c | 20 ++++++++++---------- drivers/net/wireless/ath/ath10k/wmi.c | 4 ++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 997c1c80aba76..0af787f49b338 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -34,6 +34,7 @@ enum ath10k_debug_mask { ATH10K_DBG_USB_BULK = 0x00080000, ATH10K_DBG_SNOC = 0x00100000, ATH10K_DBG_QMI = 0x00200000, + ATH10K_DBG_STA = 0x00400000, ATH10K_DBG_ANY = 0xffffffff, }; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index d8937181bbb98..c202b167d8c6c 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6667,7 +6667,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) enum wmi_phy_mode mode; mode = chan_to_phymode(&def); - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM peer bw %d phymode %d\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac update sta %pM peer bw %d phymode %d\n", sta->addr, bw, mode); err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, @@ -6686,7 +6686,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) } if (changed & IEEE80211_RC_NSS_CHANGED) { - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM nss %d\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac update sta %pM nss %d\n", sta->addr, nss); err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, @@ -6697,7 +6697,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) } if (changed & IEEE80211_RC_SMPS_CHANGED) { - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM smps %d\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac update sta %pM smps %d\n", sta->addr, smps); err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, @@ -6708,7 +6708,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) } if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) { - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac update sta %pM supp rates\n", sta->addr); err = ath10k_station_assoc(ar, arvif->vif, sta, true); @@ -7404,7 +7404,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, enum wmi_peer_type peer_type = WMI_PEER_TYPE_DEFAULT; u32 num_tdls_stations; - ath10k_dbg(ar, ATH10K_DBG_MAC, + ath10k_dbg(ar, ATH10K_DBG_STA, "mac vdev %d peer create %pM (new sta) sta %d / %d peer %d / %d\n", arvif->vdev_id, sta->addr, ar->num_stations + 1, ar->max_num_stations, @@ -7504,7 +7504,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, /* * Existing station deletion. */ - ath10k_dbg(ar, ATH10K_DBG_MAC, + ath10k_dbg(ar, ATH10K_DBG_STA, "mac vdev %d peer delete %pM sta %pK (sta gone)\n", arvif->vdev_id, sta->addr, sta); @@ -7576,7 +7576,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, /* * New association. */ - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM associated\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac sta %pM associated\n", sta->addr); ret = ath10k_station_assoc(ar, vif, sta, false); @@ -7589,7 +7589,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, /* * Tdls station authorized. */ - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac tdls sta %pM authorized\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac tdls sta %pM authorized\n", sta->addr); ret = ath10k_station_assoc(ar, vif, sta, false); @@ -7612,7 +7612,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, /* * Disassociation. */ - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM disassociated\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "mac sta %pM disassociated\n", sta->addr); ret = ath10k_station_disassoc(ar, vif, sta); @@ -8429,7 +8429,7 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, return; } - ath10k_dbg(ar, ATH10K_DBG_MAC, + ath10k_dbg(ar, ATH10K_DBG_STA, "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n", sta->addr, changed, sta->bandwidth, sta->rx_nss, sta->smps_mode); diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 29f64315a3b50..d48b922215eb6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -3497,7 +3497,7 @@ void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, struct sk_buff *skb) return; } - ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event peer sta kickout %pM\n", + ath10k_dbg(ar, ATH10K_DBG_STA, "wmi event peer sta kickout %pM\n", arg.mac_addr); rcu_read_lock(); @@ -7506,7 +7506,7 @@ ath10k_wmi_op_gen_set_sta_ps(struct ath10k *ar, u32 vdev_id, cmd->param_id = __cpu_to_le32(param_id); cmd->param_value = __cpu_to_le32(value); - ath10k_dbg(ar, ATH10K_DBG_WMI, + ath10k_dbg(ar, ATH10K_DBG_STA, "wmi sta ps param vdev_id 0x%x param %d value %d\n", vdev_id, param_id, value); return skb; From 7064e2193cabcdb8faa9008744e6ceb7f86d314d Mon Sep 17 00:00:00 2001 From: Max Chen Date: Wed, 6 Jan 2021 15:50:50 -0800 Subject: [PATCH 07/15] wil6210: Add Support for Extended DMG MCS 12.1 FW reports Tx/Rx extended MCS 12.1 to driver as "26". Driver will convert this into base MCS 7 + EXTENDED_SC_DMG flag so kernel can do the correct phy rate conversion. Also add log prints to print "12.1" instead of "26" for extended MCS. Signed-off-by: Max Chen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1609977050-7089-3-git-send-email-mxchen@codeaurora.org --- drivers/net/wireless/ath/wil6210/cfg80211.c | 38 +++++++++++++++----- drivers/net/wireless/ath/wil6210/debugfs.c | 17 +++++---- drivers/net/wireless/ath/wil6210/txrx_edma.c | 2 ++ drivers/net/wireless/ath/wil6210/wil6210.h | 3 ++ drivers/net/wireless/ath/wil6210/wmi.c | 11 +++--- 5 files changed, 52 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 60bba5b491e0f..6746fd206d2a9 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -441,7 +441,9 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, } __packed reply; struct wil_net_stats *stats = &wil->sta[cid].stats; int rc; - u8 txflag = RATE_INFO_FLAGS_DMG; + u8 tx_mcs, rx_mcs; + u8 tx_rate_flag = RATE_INFO_FLAGS_DMG; + u8 rx_rate_flag = RATE_INFO_FLAGS_DMG; memset(&reply, 0, sizeof(reply)); @@ -451,13 +453,15 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, if (rc) return rc; + tx_mcs = le16_to_cpu(reply.evt.bf_mcs); + wil_dbg_wmi(wil, "Link status for CID %d MID %d: {\n" - " MCS %d TSF 0x%016llx\n" + " MCS %s TSF 0x%016llx\n" " BF status 0x%08x RSSI %d SQI %d%%\n" " Tx Tpt %d goodput %d Rx goodput %d\n" " Sectors(rx:tx) my %d:%d peer %d:%d\n" " Tx mode %d}\n", - cid, vif->mid, le16_to_cpu(reply.evt.bf_mcs), + cid, vif->mid, WIL_EXTENDED_MCS_CHECK(tx_mcs), le64_to_cpu(reply.evt.tsf), reply.evt.status, reply.evt.rssi, reply.evt.sqi, @@ -481,12 +485,30 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC) | BIT_ULL(NL80211_STA_INFO_TX_FAILED); - if (wil->use_enhanced_dma_hw && reply.evt.tx_mode != WMI_TX_MODE_DMG) - txflag = RATE_INFO_FLAGS_EDMG; + if (wil->use_enhanced_dma_hw && reply.evt.tx_mode != WMI_TX_MODE_DMG) { + tx_rate_flag = RATE_INFO_FLAGS_EDMG; + rx_rate_flag = RATE_INFO_FLAGS_EDMG; + } + + rx_mcs = stats->last_mcs_rx; + + /* check extended MCS (12.1) and convert it into + * base MCS (7) + EXTENDED_SC_DMG flag + */ + if (tx_mcs == WIL_EXTENDED_MCS_26) { + tx_rate_flag = RATE_INFO_FLAGS_EXTENDED_SC_DMG; + tx_mcs = WIL_BASE_MCS_FOR_EXTENDED_26; + } + if (rx_mcs == WIL_EXTENDED_MCS_26) { + rx_rate_flag = RATE_INFO_FLAGS_EXTENDED_SC_DMG; + rx_mcs = WIL_BASE_MCS_FOR_EXTENDED_26; + } + + sinfo->txrate.flags = tx_rate_flag; + sinfo->rxrate.flags = rx_rate_flag; + sinfo->txrate.mcs = tx_mcs; + sinfo->rxrate.mcs = rx_mcs; - sinfo->txrate.flags = txflag; - sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs); - sinfo->rxrate.mcs = stats->last_mcs_rx; sinfo->txrate.n_bonded_ch = wil_tx_cb_mode_to_n_bonded(reply.evt.tx_mode); sinfo->rxrate.n_bonded_ch = diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 2d618f90afa7b..4c944e595978b 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1294,6 +1294,7 @@ static int bf_show(struct seq_file *s, void *data) for (i = 0; i < wil->max_assoc_sta; i++) { u32 status; + u8 bf_mcs; cmd.cid = i; rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, @@ -1305,9 +1306,10 @@ static int bf_show(struct seq_file *s, void *data) continue; status = le32_to_cpu(reply.evt.status); + bf_mcs = le16_to_cpu(reply.evt.bf_mcs); seq_printf(s, "CID %d {\n" " TSF = 0x%016llx\n" - " TxMCS = %2d TxTpt = %4d\n" + " TxMCS = %s TxTpt = %4d\n" " SQI = %4d\n" " RSSI = %4d\n" " Status = 0x%08x %s\n" @@ -1316,7 +1318,7 @@ static int bf_show(struct seq_file *s, void *data) "}\n", i, le64_to_cpu(reply.evt.tsf), - le16_to_cpu(reply.evt.bf_mcs), + WIL_EXTENDED_MCS_CHECK(bf_mcs), le32_to_cpu(reply.evt.tx_tpt), reply.evt.sqi, reply.evt.rssi, @@ -1443,8 +1445,10 @@ static int link_show(struct seq_file *s, void *data) if (rc) goto out; - seq_printf(s, " Tx_mcs = %d\n", sinfo->txrate.mcs); - seq_printf(s, " Rx_mcs = %d\n", sinfo->rxrate.mcs); + seq_printf(s, " Tx_mcs = %s\n", + WIL_EXTENDED_MCS_CHECK(sinfo->txrate.mcs)); + seq_printf(s, " Rx_mcs = %s\n", + WIL_EXTENDED_MCS_CHECK(sinfo->rxrate.mcs)); seq_printf(s, " SQ = %d\n", sinfo->signal); } else { seq_puts(s, " INVALID MID\n"); @@ -1848,7 +1852,7 @@ static void wil_link_stats_print_basic(struct wil6210_vif *vif, snprintf(per, sizeof(per), "%d%%", basic->per_average); seq_printf(s, "CID %d {\n" - "\tTxMCS %d TxTpt %d\n" + "\tTxMCS %s TxTpt %d\n" "\tGoodput(rx:tx) %d:%d\n" "\tRxBcastFrames %d\n" "\tRSSI %d SQI %d SNR %d PER %s\n" @@ -1856,7 +1860,8 @@ static void wil_link_stats_print_basic(struct wil6210_vif *vif, "\tSectors(rx:tx) my %d:%d peer %d:%d\n" "}\n", basic->cid, - basic->bf_mcs, le32_to_cpu(basic->tx_tpt), + WIL_EXTENDED_MCS_CHECK(basic->bf_mcs), + le32_to_cpu(basic->tx_tpt), le32_to_cpu(basic->rx_goodput), le32_to_cpu(basic->tx_goodput), le32_to_cpu(basic->rx_bcast_frames), diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c index 8ca2ce51c83ef..201c8c35e0c9e 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.c +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c @@ -1026,6 +1026,8 @@ static struct sk_buff *wil_sring_reap_rx_edma(struct wil6210_priv *wil, stats->last_mcs_rx = wil_rx_status_get_mcs(msg); if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs)) stats->rx_per_mcs[stats->last_mcs_rx]++; + else if (stats->last_mcs_rx == WIL_EXTENDED_MCS_26) + stats->rx_per_mcs[WIL_BASE_MCS_FOR_EXTENDED_26]++; stats->last_cb_mode_rx = wil_rx_status_get_cb_mode(msg); } diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 5dc881d3c057d..30392eb1cbbd5 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -89,6 +89,9 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) #define WIL_MAX_AGG_WSIZE_64 (64) /* FW/HW limit */ #define WIL6210_MAX_STATUS_RINGS (8) #define WIL_WMI_CALL_GENERAL_TO_MS 100 +#define WIL_EXTENDED_MCS_26 (26) /* FW reports MCS 12.1 to driver as "26" */ +#define WIL_BASE_MCS_FOR_EXTENDED_26 (7) /* MCS 7 is base MCS for MCS 12.1 */ +#define WIL_EXTENDED_MCS_CHECK(x) (((x) == WIL_EXTENDED_MCS_26) ? "12.1" : #x) /* Hardware offload block adds the following: * 26 bytes - 3-address QoS data header diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 8699f8279a8be..823ec6e78a22c 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -851,9 +851,9 @@ static void wmi_evt_rx_mgmt(struct wil6210_vif *vif, int id, void *d, int len) d_status = le16_to_cpu(data->info.status); fc = rx_mgmt_frame->frame_control; - wil_dbg_wmi(wil, "MGMT Rx: channel %d MCS %d RSSI %d SQI %d%%\n", - data->info.channel, data->info.mcs, data->info.rssi, - data->info.sqi); + wil_dbg_wmi(wil, "MGMT Rx: channel %d MCS %s RSSI %d SQI %d%%\n", + data->info.channel, WIL_EXTENDED_MCS_CHECK(data->info.mcs), + data->info.rssi, data->info.sqi); wil_dbg_wmi(wil, "status 0x%04x len %d fc 0x%04x\n", d_status, d_len, le16_to_cpu(fc)); wil_dbg_wmi(wil, "qid %d mid %d cid %d\n", @@ -1422,8 +1422,9 @@ wmi_evt_sched_scan_result(struct wil6210_vif *vif, int id, void *d, int len) else signal = data->info.sqi; - wil_dbg_wmi(wil, "sched scan result: channel %d MCS %d RSSI %d\n", - data->info.channel, data->info.mcs, data->info.rssi); + wil_dbg_wmi(wil, "sched scan result: channel %d MCS %s RSSI %d\n", + data->info.channel, WIL_EXTENDED_MCS_CHECK(data->info.mcs), + data->info.rssi); wil_dbg_wmi(wil, "len %d qid %d mid %d cid %d\n", d_len, data->info.qid, data->info.mid, data->info.cid); wil_hex_dump_wmi("PROBE ", DUMP_PREFIX_OFFSET, 16, 1, rx_mgmt_frame, From c202e2ebe1dc454ad54fd0018c023ec553d47284 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 9 Feb 2021 09:29:43 +0200 Subject: [PATCH 08/15] ath11k: fix a locking bug in ath11k_mac_op_start() This error path leads to a Smatch warning: drivers/net/wireless/ath/ath11k/mac.c:4269 ath11k_mac_op_start() error: double unlocked '&ar->conf_mutex' (orig line 4251) We're not holding the lock when we do the "goto err;" so it leads to a double unlock. The fix is to hold the lock for a little longer. Fixes: c83c500b55b6 ("ath11k: enable idle power save mode") Signed-off-by: Dan Carpenter [kvalo@codeaurora.org: move also rcu_assign_pointer() call] Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/YBk4GoeE+yc0wlJH@mwanda --- drivers/net/wireless/ath/ath11k/mac.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 288720c5ab01c..263a1bff02ac8 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -4248,11 +4248,6 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) /* Configure the hash seed for hash based reo dest ring selection */ ath11k_wmi_pdev_lro_cfg(ar, ar->pdev->pdev_id); - mutex_unlock(&ar->conf_mutex); - - rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], - &ab->pdevs[ar->pdev_idx]); - /* allow device to enter IMPS */ if (ab->hw_params.idle_ps) { ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_IDLE_PS_CONFIG, @@ -4262,6 +4257,12 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) goto err; } } + + mutex_unlock(&ar->conf_mutex); + + rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], + &ab->pdevs[ar->pdev_idx]); + return 0; err: From e6f1c0d26a31a09e83d8aa7ed1a1c796bf2685c8 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Wed, 10 Feb 2021 09:53:24 +0200 Subject: [PATCH 09/15] ath10k: restore tx sk_buff of htt header for SDIO ieee80211_report_used_skb of mac80211 use the frame_control of ieee80211_hdr in sk_buff and indicate it to another function ieee80211_mgd_conn_tx_status, then it queue work ieee80211_sta_work, but ieee80211_is_auth(fc) in ieee80211_sta_work check fail when the authentication has transmitted by ath10k. When the ath10k report it with HTT_TX_COMPL_STATE_DISCARD, it will be set without flag IEEE80211_TX_STAT_ACK, then mac80211 should try the next authentication immeditely, but in fact mac80211 wait 1 second for it, the reason is ieee80211_is_auth(fc) in ieee80211_sta_work check fail for the sk_buff which is not restored, the data of sk_buff is not the begin of ieee80211_hdr, in fact it is the begin of htt_cmd_hdr. dmesg without this patch, it wait 1 second for the next retry when ath10k report without IEEE80211_TX_STAT_ACK for authentication: [ 6973.883116] wlan0: send auth to 5e:6f:2b:0d:fb:d7 (try 1/3) [ 6974.705471] wlan0: send auth to 5e:6f:2b:0d:fb:d7 (try 2/3) [ 6975.712962] wlan0: send auth to 5e:6f:2b:0d:fb:d7 (try 3/3) Restore the sk_buff make mac8011 retry the next authentication immeditely which meet logic of mac80211. dmesg with this patch, it retry the next immeditely when ath10k report without IEEE80211_TX_STAT_ACK for authentication: [ 216.734813] wlan0: send auth to 5e:6f:2b:0d:fb:d7 (try 1/3) [ 216.739914] wlan0: send auth to 5e:6f:2b:0d:fb:d7 (try 2/3) [ 216.745874] wlan0: send auth to 5e:6f:2b:0d:fb:d7 (try 3/3) Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00049 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1612839530-2263-1-git-send-email-wgong@codeaurora.org --- drivers/net/wireless/ath/ath10k/htt_tx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 77f4d27e9d07d..d6b8bdcef4160 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -569,6 +569,8 @@ void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) desc_hdr = (struct htt_data_tx_desc *) (skb->data + sizeof(*htt_hdr)); flags1 = __le16_to_cpu(desc_hdr->flags1); + skb_pull(skb, sizeof(struct htt_cmd_hdr)); + skb_pull(skb, sizeof(struct htt_data_tx_desc)); } } From b56b08aec57dd17404793a76f1b28663b955d95f Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Wed, 10 Feb 2021 09:53:29 +0200 Subject: [PATCH 10/15] ath11k: add support to configure spatial reuse parameter set The SPR parameter set comprises OBSS PD threshold for SRG and non SRG and Bitmap of BSS color and partial BSSID. This adds support to configure fields of SPR element to firmware. Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.1.0.1-01238-QCAHKSWPL_SILICONZ-2 Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.4.0.1-01164-QCAHKSWPL_SILICONZ-1 Tested-by: Muna Sinada Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1612843714-29174-1-git-send-email-rmanohar@codeaurora.org --- .../wireless/ath/ath11k/debugfs_htt_stats.c | 12 + .../wireless/ath/ath11k/debugfs_htt_stats.h | 15 +- drivers/net/wireless/ath/ath11k/mac.c | 155 +++++++++++- drivers/net/wireless/ath/ath11k/mac.h | 6 + drivers/net/wireless/ath/ath11k/wmi.c | 227 ++++++++++++++++++ drivers/net/wireless/ath/ath11k/wmi.h | 37 ++- 6 files changed, 447 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c index 9191ffa081c22..e13684343ec30 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c +++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c @@ -3845,6 +3845,18 @@ htt_print_pdev_obss_pd_stats_tlv_v(const void *tag_buf, htt_stats_buf->num_obss_tx_ppdu_success); len += HTT_DBG_OUT(buf + len, buf_len - len, "OBSS Tx failures PPDU = %u\n", htt_stats_buf->num_obss_tx_ppdu_failure); + len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG Opportunities = %u\n", + htt_stats_buf->num_non_srg_opportunities); + len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG tried PPDU = %u\n", + htt_stats_buf->num_non_srg_ppdu_tried); + len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG success PPDU = %u\n", + htt_stats_buf->num_non_srg_ppdu_success); + len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG Opportunies = %u\n", + htt_stats_buf->num_srg_opportunities); + len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG tried PPDU = %u\n", + htt_stats_buf->num_srg_ppdu_tried); + len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG success PPDU = %u\n", + htt_stats_buf->num_srg_ppdu_success); if (len >= buf_len) buf[buf_len - 1] = 0; diff --git a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h index 74b2086eed9d6..567a26d485a92 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h +++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h @@ -1656,8 +1656,19 @@ struct htt_tx_sounding_stats_tlv { }; struct htt_pdev_obss_pd_stats_tlv { - u32 num_obss_tx_ppdu_success; - u32 num_obss_tx_ppdu_failure; + u32 num_obss_tx_ppdu_success; + u32 num_obss_tx_ppdu_failure; + u32 num_sr_tx_transmissions; + u32 num_spatial_reuse_opportunities; + u32 num_non_srg_opportunities; + u32 num_non_srg_ppdu_tried; + u32 num_non_srg_ppdu_success; + u32 num_srg_opportunities; + u32 num_srg_ppdu_tried; + u32 num_srg_ppdu_success; + u32 num_psr_opportunities; + u32 num_psr_ppdu_tried; + u32 num_psr_ppdu_success; }; struct htt_ring_backpressure_stats_tlv { diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 263a1bff02ac8..b391169576e27 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -1871,6 +1871,158 @@ static int ath11k_mac_fils_discovery(struct ath11k_vif *arvif, return ret; } +static int ath11k_mac_config_obss_pd(struct ath11k *ar, + struct ieee80211_he_obss_pd *he_obss_pd) +{ + u32 bitmap[2], param_id, param_val, pdev_id; + int ret; + s8 non_srg_th = 0, srg_th = 0; + + pdev_id = ar->pdev->pdev_id; + + /* Set and enable SRG/non-SRG OBSS PD Threshold */ + param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD; + if (test_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags)) { + ret = ath11k_wmi_pdev_set_param(ar, param_id, 0, pdev_id); + if (ret) + ath11k_warn(ar->ab, + "failed to set obss_pd_threshold for pdev: %u\n", + pdev_id); + return ret; + } + + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, + "mac obss pd sr_ctrl %x non_srg_thres %u srg_max %u\n", + he_obss_pd->sr_ctrl, he_obss_pd->non_srg_max_offset, + he_obss_pd->max_offset); + + param_val = 0; + + if (he_obss_pd->sr_ctrl & + IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED) { + non_srg_th = ATH11K_OBSS_PD_MAX_THRESHOLD; + } else { + if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT) + non_srg_th = (ATH11K_OBSS_PD_MAX_THRESHOLD + + he_obss_pd->non_srg_max_offset); + else + non_srg_th = ATH11K_OBSS_PD_NON_SRG_MAX_THRESHOLD; + + param_val |= ATH11K_OBSS_PD_NON_SRG_EN; + } + + if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) { + srg_th = ATH11K_OBSS_PD_MAX_THRESHOLD + he_obss_pd->max_offset; + param_val |= ATH11K_OBSS_PD_SRG_EN; + } + + if (test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT, + ar->ab->wmi_ab.svc_map)) { + param_val |= ATH11K_OBSS_PD_THRESHOLD_IN_DBM; + param_val |= FIELD_PREP(GENMASK(15, 8), srg_th); + } else { + non_srg_th -= ATH11K_DEFAULT_NOISE_FLOOR; + /* SRG not supported and threshold in dB */ + param_val &= ~(ATH11K_OBSS_PD_SRG_EN | + ATH11K_OBSS_PD_THRESHOLD_IN_DBM); + } + + param_val |= (non_srg_th & GENMASK(7, 0)); + ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id); + if (ret) { + ath11k_warn(ar->ab, + "failed to set obss_pd_threshold for pdev: %u\n", + pdev_id); + return ret; + } + + /* Enable OBSS PD for all access category */ + param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC; + param_val = 0xf; + ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id); + if (ret) { + ath11k_warn(ar->ab, + "failed to set obss_pd_per_ac for pdev: %u\n", + pdev_id); + return ret; + } + + /* Set SR Prohibit */ + param_id = WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT; + param_val = !!(he_obss_pd->sr_ctrl & + IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED); + ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id); + if (ret) { + ath11k_warn(ar->ab, "failed to set sr_prohibit for pdev: %u\n", + pdev_id); + return ret; + } + + if (!test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT, + ar->ab->wmi_ab.svc_map)) + return 0; + + /* Set SRG BSS Color Bitmap */ + memcpy(bitmap, he_obss_pd->bss_color_bitmap, sizeof(bitmap)); + ret = ath11k_wmi_pdev_set_srg_bss_color_bitmap(ar, bitmap); + if (ret) { + ath11k_warn(ar->ab, + "failed to set bss_color_bitmap for pdev: %u\n", + pdev_id); + return ret; + } + + /* Set SRG Partial BSSID Bitmap */ + memcpy(bitmap, he_obss_pd->partial_bssid_bitmap, sizeof(bitmap)); + ret = ath11k_wmi_pdev_set_srg_patial_bssid_bitmap(ar, bitmap); + if (ret) { + ath11k_warn(ar->ab, + "failed to set partial_bssid_bitmap for pdev: %u\n", + pdev_id); + return ret; + } + + memset(bitmap, 0xff, sizeof(bitmap)); + + /* Enable all BSS Colors for SRG */ + ret = ath11k_wmi_pdev_srg_obss_color_enable_bitmap(ar, bitmap); + if (ret) { + ath11k_warn(ar->ab, + "failed to set srg_color_en_bitmap pdev: %u\n", + pdev_id); + return ret; + } + + /* Enable all patial BSSID mask for SRG */ + ret = ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(ar, bitmap); + if (ret) { + ath11k_warn(ar->ab, + "failed to set srg_bssid_en_bitmap pdev: %u\n", + pdev_id); + return ret; + } + + /* Enable all BSS Colors for non-SRG */ + ret = ath11k_wmi_pdev_non_srg_obss_color_enable_bitmap(ar, bitmap); + if (ret) { + ath11k_warn(ar->ab, + "failed to set non_srg_color_en_bitmap pdev: %u\n", + pdev_id); + return ret; + } + + /* Enable all patial BSSID mask for non-SRG */ + ret = ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(ar, bitmap); + if (ret) { + ath11k_warn(ar->ab, + "failed to set non_srg_bssid_en_bitmap pdev: %u\n", + pdev_id); + return ret; + } + + return 0; +} + static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, @@ -2114,8 +2266,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_HE_OBSS_PD) - ath11k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id, - &info->he_obss_pd); + ath11k_mac_config_obss_pd(ar, &info->he_obss_pd); if (changed & BSS_CHANGED_HE_BSS_COLOR) { if (vif->type == NL80211_IFTYPE_AP) { diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h index 597104a9078d2..455577905505c 100644 --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h @@ -116,6 +116,12 @@ struct ath11k_generic_iter { #define ATH11K_CHAN_WIDTH_NUM 8 +#define ATH11K_OBSS_PD_MAX_THRESHOLD -82 +#define ATH11K_OBSS_PD_NON_SRG_MAX_THRESHOLD -62 +#define ATH11K_OBSS_PD_THRESHOLD_IN_DBM BIT(29) +#define ATH11K_OBSS_PD_SRG_EN BIT(30) +#define ATH11K_OBSS_PD_NON_SRG_EN BIT(31) + extern const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default; void ath11k_mac_destroy(struct ath11k_base *ab); diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index 2e6ce28ecc8d6..cccfd3bd4d27e 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -2970,6 +2970,233 @@ ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id, return ret; } +int +ath11k_wmi_pdev_set_srg_bss_color_bitmap(struct ath11k *ar, u32 *bitmap) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_ab->ab; + struct wmi_pdev_obss_pd_bitmap_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + cmd->pdev_id = ar->pdev->pdev_id; + memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "obss pd pdev_id %d bss color bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID); + if (ret) { + ath11k_warn(ab, + "failed to send WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID"); + dev_kfree_skb(skb); + } + + return ret; +} + +int +ath11k_wmi_pdev_set_srg_patial_bssid_bitmap(struct ath11k *ar, u32 *bitmap) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_ab->ab; + struct wmi_pdev_obss_pd_bitmap_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data; + cmd->tlv_header = + FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + cmd->pdev_id = ar->pdev->pdev_id; + memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "obss pd pdev_id %d partial bssid bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID); + if (ret) { + ath11k_warn(ab, + "failed to send WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID"); + dev_kfree_skb(skb); + } + + return ret; +} + +int +ath11k_wmi_pdev_srg_obss_color_enable_bitmap(struct ath11k *ar, u32 *bitmap) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_ab->ab; + struct wmi_pdev_obss_pd_bitmap_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data; + cmd->tlv_header = + FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_PDEV_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + cmd->pdev_id = ar->pdev->pdev_id; + memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "obss pd srg pdev_id %d bss color enable bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID); + if (ret) { + ath11k_warn(ab, + "failed to send WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID"); + dev_kfree_skb(skb); + } + + return ret; +} + +int +ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(struct ath11k *ar, u32 *bitmap) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_ab->ab; + struct wmi_pdev_obss_pd_bitmap_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data; + cmd->tlv_header = + FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + cmd->pdev_id = ar->pdev->pdev_id; + memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "obss pd srg pdev_id %d bssid enable bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID); + if (ret) { + ath11k_warn(ab, + "failed to send WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID"); + dev_kfree_skb(skb); + } + + return ret; +} + +int +ath11k_wmi_pdev_non_srg_obss_color_enable_bitmap(struct ath11k *ar, u32 *bitmap) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_ab->ab; + struct wmi_pdev_obss_pd_bitmap_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data; + cmd->tlv_header = + FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + cmd->pdev_id = ar->pdev->pdev_id; + memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "obss pd non_srg pdev_id %d bss color enable bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID); + if (ret) { + ath11k_warn(ab, + "failed to send WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID"); + dev_kfree_skb(skb); + } + + return ret; +} + +int +ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath11k *ar, u32 *bitmap) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_ab->ab; + struct wmi_pdev_obss_pd_bitmap_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data; + cmd->tlv_header = + FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + cmd->pdev_id = ar->pdev->pdev_id; + memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap)); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "obss pd non_srg pdev_id %d bssid enable bitmap %08x %08x\n", + cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID); + if (ret) { + ath11k_warn(ab, + "failed to send WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID"); + dev_kfree_skb(skb); + } + + return ret; +} + int ath11k_wmi_send_obss_color_collision_cfg_cmd(struct ath11k *ar, u32 vdev_id, u8 bss_color, u32 period, diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index 993674228c9e1..3ade1ddd35c9d 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -257,6 +257,16 @@ enum wmi_tlv_cmd_id { WMI_PDEV_DMA_RING_CFG_REQ_CMDID, WMI_PDEV_HE_TB_ACTION_FRM_CMDID, WMI_PDEV_PKTLOG_FILTER_CMDID, + WMI_PDEV_SET_RAP_CONFIG_CMDID, + WMI_PDEV_DSM_FILTER_CMDID, + WMI_PDEV_FRAME_INJECT_CMDID, + WMI_PDEV_TBTT_OFFSET_SYNC_CMDID, + WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID, + WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID, + WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID, + WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID, + WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID, + WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID, WMI_VDEV_CREATE_CMDID = WMI_TLV_CMD(WMI_GRP_VDEV), WMI_VDEV_DELETE_CMDID, WMI_VDEV_START_REQUEST_CMDID, @@ -919,6 +929,9 @@ enum wmi_tlv_pdev_param { WMI_PDEV_PARAM_RADIO_CHAN_STATS_ENABLE, WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE, WMI_PDEV_PARAM_MESH_MCAST_ENABLE, + WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD = 0xbc, + WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC = 0xbe, + WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT = 0xc6, }; enum wmi_tlv_vdev_param { @@ -1812,10 +1825,15 @@ enum wmi_tlv_tag { WMI_TAG_NDP_CHANNEL_INFO, WMI_TAG_NDP_CMD, WMI_TAG_NDP_EVENT, - /* TODO add all the missing cmds */ WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301, WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO, WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344, + WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD = 0x37b, + WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD, + WMI_TAG_PDEV_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD = 0x381, + WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, + WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD, + WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, WMI_TAG_MAX }; @@ -2039,6 +2057,7 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET = 213, WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219, WMI_TLV_SERVICE_EXT2_MSG = 220, + WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249, WMI_MAX_EXT_SERVICE }; @@ -4781,6 +4800,12 @@ struct wmi_obss_spatial_reuse_params_cmd { u32 vdev_id; } __packed; +struct wmi_pdev_obss_pd_bitmap_cmd { + u32 tlv_header; + u32 pdev_id; + u32 bitmap[2]; +} __packed; + #define ATH11K_BSS_COLOR_COLLISION_SCAN_PERIOD_MS 200 #define ATH11K_OBSS_COLOR_COLLISION_DETECTION_DISABLE 0 #define ATH11K_OBSS_COLOR_COLLISION_DETECTION 1 @@ -5316,6 +5341,16 @@ int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id); int ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id); int ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id, struct ieee80211_he_obss_pd *he_obss_pd); +int ath11k_wmi_pdev_set_srg_bss_color_bitmap(struct ath11k *ar, u32 *bitmap); +int ath11k_wmi_pdev_set_srg_patial_bssid_bitmap(struct ath11k *ar, u32 *bitmap); +int ath11k_wmi_pdev_srg_obss_color_enable_bitmap(struct ath11k *ar, + u32 *bitmap); +int ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(struct ath11k *ar, + u32 *bitmap); +int ath11k_wmi_pdev_non_srg_obss_color_enable_bitmap(struct ath11k *ar, + u32 *bitmap); +int ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath11k *ar, + u32 *bitmap); int ath11k_wmi_send_obss_color_collision_cfg_cmd(struct ath11k *ar, u32 vdev_id, u8 bss_color, u32 period, bool enable); From 12c8f3d1cdd84f01ee777b756db9dddc1f1c9d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Wed, 10 Feb 2021 09:53:44 +0200 Subject: [PATCH 11/15] ath9k: fix data bus crash when setting nf_override via debugfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When trying to set the noise floor via debugfs, a "data bus error" crash like the following can happen: [ 88.433133] Data bus error, epc == 80221c28, ra == 83314e60 [ 88.438895] Oops[#1]: [ 88.441246] CPU: 0 PID: 7263 Comm: sh Not tainted 4.14.195 #0 [ 88.447174] task: 838a1c20 task.stack: 82d5e000 [ 88.451847] $ 0 : 00000000 00000030 deadc0de 83141de4 [ 88.457248] $ 4 : b810a2c4 0000a2c4 83230fd4 00000000 [ 88.462652] $ 8 : 0000000a 00000000 00000001 00000000 [ 88.468055] $12 : 7f8ef318 00000000 00000000 77f802a0 [ 88.473457] $16 : 83230080 00000002 0000001b 83230080 [ 88.478861] $20 : 83a1c3f8 00841000 77f7adb0 ffffff92 [ 88.484263] $24 : 00000fa4 77edd860 [ 88.489665] $28 : 82d5e000 82d5fda8 00000000 83314e60 [ 88.495070] Hi : 00000000 [ 88.498044] Lo : 00000000 [ 88.501040] epc : 80221c28 ioread32+0x8/0x10 [ 88.505671] ra : 83314e60 ath9k_hw_loadnf+0x88/0x520 [ath9k_hw] [ 88.512049] Status: 1000fc03 KERNEL EXL IE [ 88.516369] Cause : 5080801c (ExcCode 07) [ 88.520508] PrId : 00019374 (MIPS 24Kc) [ 88.524556] Modules linked in: ath9k ath9k_common pppoe ppp_async l2tp_ppp cdc_mbim batman_adv ath9k_hw ath sr9700 smsc95xx sierra_net rndis_host qmi_wwan pppox ppp_generic pl2303 nf_conntrack_ipv6 mcs7830 mac80211 kalmia iptable_nat ipt_REJECT ipt_MASQUERADE huawei_cdc_ncm ftdi_sio dm9601 cfg80211 cdc_subset cdc_ncm cdc_ether cdc_eem ax88179_178a asix xt_time xt_tcpudp xt_tcpmss xt_statistic xt_state xt_nat xt_multiport xt_mark xt_mac xt_limit xt_length xt_hl xt_ecn xt_dscp xt_conntrack xt_comment xt_TCPMSS xt_REDIRECT xt_NETMAP xt_LOG xt_HL xt_FLOWOFFLOAD xt_DSCP xt_CLASSIFY usbserial usbnet usbhid slhc rtl8150 r8152 pegasus nf_reject_ipv4 nf_nat_redirect nf_nat_masquerade_ipv4 nf_conntrack_ipv4 nf_nat_ipv4 nf_nat nf_log_ipv4 nf_flow_table_hw nf_flow_table nf_defrag_ipv6 nf_defrag_ipv4 nf_conntrack [ 88.597894] libcrc32c kaweth iptable_mangle iptable_filter ipt_ECN ipheth ip_tables hso hid_generic crc_ccitt compat cdc_wdm cdc_acm br_netfilter hid evdev input_core nf_log_ipv6 nf_log_common ip6table_mangle ip6table_filter ip6_tables ip6t_REJECT x_tables nf_reject_ipv6 l2tp_netlink l2tp_core udp_tunnel ip6_udp_tunnel xfrm6_mode_tunnel xfrm6_mode_transport xfrm6_mode_beet ipcomp6 xfrm6_tunnel esp6 ah6 xfrm4_tunnel xfrm4_mode_tunnel xfrm4_mode_transport xfrm4_mode_beet ipcomp esp4 ah4 tunnel6 tunnel4 tun xfrm_user xfrm_ipcomp af_key xfrm_algo sha256_generic sha1_generic jitterentropy_rng drbg md5 hmac echainiv des_generic deflate zlib_inflate zlib_deflate cbc authenc crypto_acompress ehci_platform ehci_hcd gpio_button_hotplug usbcore nls_base usb_common crc16 mii aead crypto_null cryptomgr crc32c_generic [ 88.671671] crypto_hash [ 88.674292] Process sh (pid: 7263, threadinfo=82d5e000, task=838a1c20, tls=77f81efc) [ 88.682279] Stack : 00008060 00000008 00000200 00000000 00000000 00000000 00000000 00000002 [ 88.690916] 80500000 83230080 82d5fe22 00841000 77f7adb0 00000000 00000000 83156858 [ 88.699553] 00000000 8352fa00 83ad62b0 835302a8 00000000 300a00f8 00000003 82d5fe38 [ 88.708190] 82d5fef4 00000001 77f54dc4 77f80000 77f7adb0 c79fe901 00000000 00000000 [ 88.716828] 80510000 00000002 00841000 77f54dc4 77f80000 801ce4cc 0000000b 41824292 [ 88.725465] ... [ 88.727994] Call Trace: [ 88.730532] [<80221c28>] ioread32+0x8/0x10 [ 88.734765] Code: 00000000 8c820000 0000000f <03e00008> 00000000 08088708 00000000 aca40000 03e00008 [ 88.744846] [ 88.746464] ---[ end trace db226b2de1b69b9e ]--- [ 88.753477] Kernel panic - not syncing: Fatal exception [ 88.759981] Rebooting in 3 seconds.. The "REG_READ(ah, AR_PHY_AGC_CONTROL)" in ath9k_hw_loadnf() does not like being called when the hardware is asleep, leading to this crash. The easiest way to reproduce this is trying to set nf_override while the hardware is down: $ ip link set down dev wlan0 $ echo "-85" > /sys/kernel/debug/ieee80211/phy0/ath9k/nf_override Fixing this crash by waking the hardware up before trying to set the noise floor. Similar to what other ath9k debugfs files do. Tested on a Lima board from 8devices, which has a QCA 4531 chipset. Fixes: b90189759a7f ("ath9k: add noise floor override option") Cc: Simon Wunderlich Signed-off-by: Linus Lüssing Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210209184352.4272-1-linus.luessing@c0d3.blue --- drivers/net/wireless/ath/ath9k/debug.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 017a43bc400ca..4c81b1d7f4171 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1223,8 +1223,11 @@ static ssize_t write_file_nf_override(struct file *file, ah->nf_override = val; - if (ah->curchan) + if (ah->curchan) { + ath9k_ps_wakeup(sc); ath9k_hw_loadnf(ah, ah->curchan); + ath9k_ps_restore(sc); + } return count; } From 83bae26532ca7318c1308fd80434e1e420bcf407 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Tue, 9 Feb 2021 17:42:24 -0700 Subject: [PATCH 12/15] ath10k: change ath10k_offchan_tx_work() peer present msg to a warn Based on the comment block in this function and the FIXME for this, peer being present for the offchannel tx is unlikely. Peer is deleted once tx is complete. Change peer present msg to a warn to detect this condition. Signed-off-by: Shuah Khan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/3b1f71272d56ee1d7f567fbce13bdb56cc06d342.1612915444.git.skhan@linuxfoundation.org --- drivers/net/wireless/ath/ath10k/mac.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index c202b167d8c6c..bb6c5ee43ac0c 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4115,9 +4115,8 @@ void ath10k_offchan_tx_work(struct work_struct *work) spin_unlock_bh(&ar->data_lock); if (peer) - /* FIXME: should this use ath10k_warn()? */ - ath10k_dbg(ar, ATH10K_DBG_MAC, "peer %pM on vdev %d already present\n", - peer_addr, vdev_id); + ath10k_warn(ar, "peer %pM on vdev %d already present\n", + peer_addr, vdev_id); if (!peer) { ret = ath10k_peer_create(ar, NULL, NULL, vdev_id, From 09078368d516918666a0122f2533dc73676d3d7e Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 10 Feb 2021 14:21:07 -0700 Subject: [PATCH 13/15] ath10k: hold RCU lock when calling ieee80211_find_sta_by_ifaddr() ieee80211_find_sta_by_ifaddr() must be called under the RCU lock and the resulting pointer is only valid under RCU lock as well. Fix ath10k_wmi_tlv_op_pull_peer_stats_info() to hold RCU lock before it calls ieee80211_find_sta_by_ifaddr() and release it when the resulting pointer is no longer needed. This problem was found while reviewing code to debug RCU warn from ath10k_wmi_tlv_parse_peer_stats_info(). Link: https://lore.kernel.org/linux-wireless/7230c9e5-2632-b77e-c4f9-10eca557a5bb@linuxfoundation.org/ Signed-off-by: Shuah Khan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210210212107.40373-1-skhan@linuxfoundation.org --- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index bfdd017f14052..d97b33f789e44 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -576,13 +576,13 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb) case WMI_TDLS_TEARDOWN_REASON_TX: case WMI_TDLS_TEARDOWN_REASON_RSSI: case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT: + rcu_read_lock(); station = ieee80211_find_sta_by_ifaddr(ar->hw, ev->peer_macaddr.addr, NULL); if (!station) { ath10k_warn(ar, "did not find station from tdls peer event"); - kfree(tb); - return; + goto exit; } arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id)); ieee80211_tdls_oper_request( @@ -593,6 +593,9 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb) ); break; } + +exit: + rcu_read_unlock(); kfree(tb); } From 5d18b8a04ba2fd000475411737857995ecf70c9f Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 11 Feb 2021 12:51:37 +0200 Subject: [PATCH 14/15] ath11k: pci: remove experimental warning I have received feedback that QCA6390 PCI support is working for many, and I'm also using QCA6390 on my daily driver^Hlaptop. While there are issues still to be resolved it's not really experimental anymore, so remove the experimental warning from driver initialisation. Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1613040697-20289-1-git-send-email-kvalo@codeaurora.org --- drivers/net/wireless/ath/ath11k/pci.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index 78478b2b3ba57..d14416816acc4 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -1086,8 +1086,6 @@ static int ath11k_pci_probe(struct pci_dev *pdev, u32 soc_hw_version, soc_hw_version_major, soc_hw_version_minor; int ret; - dev_warn(&pdev->dev, "WARNING: ath11k PCI support is experimental!\n"); - ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI, &ath11k_pci_bus_params); if (!ab) { From d5395a54865963089792f241756a7562d18262a1 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 11 Feb 2021 13:05:49 +0200 Subject: [PATCH 15/15] ath11k: qmi: add debug message for allocated memory segment addresses and sizes This helps debugging firmware memory allocation problems. Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1613041549-7265-1-git-send-email-kvalo@codeaurora.org --- drivers/net/wireless/ath/ath11k/qmi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index 0db623ff4bb9b..1aca841cd147c 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -1686,6 +1686,11 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab) req->mem_seg[i].addr = ab->qmi.target_mem[i].paddr; req->mem_seg[i].size = ab->qmi.target_mem[i].size; req->mem_seg[i].type = ab->qmi.target_mem[i].type; + ath11k_dbg(ab, ATH11K_DBG_QMI, + "qmi req mem_seg[%d] 0x%llx %u %u\n", i, + ab->qmi.target_mem[i].paddr, + ab->qmi.target_mem[i].size, + ab->qmi.target_mem[i].type); } }