From d944e09ea839033476e43fe03db0121b7be5154e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 May 2022 18:02:01 +0200 Subject: wifi: libertas: use variable-size data in assoc req/resp cmd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The firmware has a 512 limit here, but we use less, so gcc starts complaining about it: drivers/net/wireless/marvell/libertas/cfg.c:1198:63: warning: array subscript ‘struct cmd_ds_802_11_associate_response[0]’ is partly outside array bounds of ‘unsigned char[203]’ [-Warray-bounds] 1198 | "aid 0x%04x\n", status, le16_to_cpu(resp->statuscode), | ^~ Since we size the command and response buffer per our needs and not per the firmware maximum, change to a variable size data array and put the 512 only into a comment. In the end, that's actually what the code always wanted, and it simplifies the code that used to subtract the fixed size buffer size in two places. Reported-by: Jakub Kicinski Signed-off-by: Johannes Berg Acked-by: Kalle Valo Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220523180200.115fa27fbece.Ie66d874b047e7afad63900aa2df70f031711147e@changeid --- drivers/net/wireless/marvell/libertas/cfg.c | 4 +--- drivers/net/wireless/marvell/libertas/host.h | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c index 4e3de684928b..b0b3f59dabc6 100644 --- a/drivers/net/wireless/marvell/libertas/cfg.c +++ b/drivers/net/wireless/marvell/libertas/cfg.c @@ -1053,7 +1053,6 @@ static int lbs_set_authtype(struct lbs_private *priv, */ #define LBS_ASSOC_MAX_CMD_SIZE \ (sizeof(struct cmd_ds_802_11_associate) \ - - 512 /* cmd_ds_802_11_associate.iebuf */ \ + LBS_MAX_SSID_TLV_SIZE \ + LBS_MAX_CHANNEL_TLV_SIZE \ + LBS_MAX_CF_PARAM_TLV_SIZE \ @@ -1130,8 +1129,7 @@ static int lbs_associate(struct lbs_private *priv, if (sme->ie && sme->ie_len) pos += lbs_add_wpa_tlv(pos, sme->ie, sme->ie_len); - len = (sizeof(*cmd) - sizeof(cmd->iebuf)) + - (u16)(pos - (u8 *) &cmd->iebuf); + len = sizeof(*cmd) + (u16)(pos - (u8 *) &cmd->iebuf); cmd->hdr.size = cpu_to_le16(len); lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_CMD", (u8 *) cmd, diff --git a/drivers/net/wireless/marvell/libertas/host.h b/drivers/net/wireless/marvell/libertas/host.h index ceff4b92e7a1..a202b716ad5d 100644 --- a/drivers/net/wireless/marvell/libertas/host.h +++ b/drivers/net/wireless/marvell/libertas/host.h @@ -528,7 +528,8 @@ struct cmd_ds_802_11_associate { __le16 listeninterval; __le16 bcnperiod; u8 dtimperiod; - u8 iebuf[512]; /* Enough for required and most optional IEs */ + /* 512 permitted - enough for required and most optional IEs */ + u8 iebuf[]; } __packed; struct cmd_ds_802_11_associate_response { @@ -537,7 +538,8 @@ struct cmd_ds_802_11_associate_response { __le16 capability; __le16 statuscode; __le16 aid; - u8 iebuf[512]; + /* max 512 */ + u8 iebuf[]; } __packed; struct cmd_ds_802_11_set_wep { -- cgit v1.2.3 From 9c6837311f437701b398bfaed963458aa292e9d7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 May 2022 22:03:01 +0200 Subject: wifi: iwlwifi: pcie: rename CAUSE macro At least mips64 has ist own CAUSE macro, so rename ours to IWL_CAUSE to fix build issues. Reported-by: Jakub Kicinski Fixes: c1918196427b ("iwlwifi: pcie: simplify MSI-X cause mapping") Signed-off-by: Johannes Berg Acked-by: Gregory Greenman Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220523220300.682be2029361.I283200b18da589a975a284073dca8ed001ee107a@changeid --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 6fc69c42f36e..bd50f52a1aad 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1090,7 +1090,7 @@ struct iwl_causes_list { u8 addr; }; -#define CAUSE(reg, mask) \ +#define IWL_CAUSE(reg, mask) \ { \ .mask_reg = reg, \ .bit = ilog2(mask), \ @@ -1101,28 +1101,28 @@ struct iwl_causes_list { } static const struct iwl_causes_list causes_list_common[] = { - CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_D2S_CH0_NUM), - CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_D2S_CH1_NUM), - CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_S2D), - CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_FH_ERR), - CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_ALIVE), - CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_WAKEUP), - CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_RESET_DONE), - CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_CT_KILL), - CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_RF_KILL), - CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_PERIODIC), - CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SCD), - CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_FH_TX), - CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_HW_ERR), - CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_HAP), + IWL_CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_D2S_CH0_NUM), + IWL_CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_D2S_CH1_NUM), + IWL_CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_S2D), + IWL_CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_FH_ERR), + IWL_CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_ALIVE), + IWL_CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_WAKEUP), + IWL_CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_RESET_DONE), + IWL_CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_CT_KILL), + IWL_CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_RF_KILL), + IWL_CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_PERIODIC), + IWL_CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SCD), + IWL_CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_FH_TX), + IWL_CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_HW_ERR), + IWL_CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_HAP), }; static const struct iwl_causes_list causes_list_pre_bz[] = { - CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SW_ERR), + IWL_CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SW_ERR), }; static const struct iwl_causes_list causes_list_bz[] = { - CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ), + IWL_CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ), }; static void iwl_pcie_map_list(struct iwl_trans *trans, -- cgit v1.2.3 From 7711fe713a4987695ac6c68c9f175cb2d1d06e83 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Thu, 26 May 2022 13:12:51 +0800 Subject: wifi: rtw88: add a work to correct atomic scheduling warning of ::set_tim MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The set_tim is supposed to be atomic, but we should download beacon context to firmware with a mutex lock. To avoid warning, do the thing in another work. BUG: scheduling while atomic: swapper/1/0/0x00000700 Modules linked in: CPU: 1 PID: 0 Comm: swapper/1 Tainted: G W 5.18.0-rc7-00703-g33b5ee09a0c1 #4 Hardware name: Pine64 RK3566 Quartz64-A Board (DT) Call trace: dump_backtrace.part.0+0xc4/0xd0 show_stack+0x14/0x60 dump_stack_lvl+0x60/0x78 dump_stack+0x14/0x2c __schedule_bug+0x5c/0x70 __schedule+0x5c4/0x630 schedule+0x44/0xb0 schedule_preempt_disabled+0xc/0x14 __mutex_lock.constprop.0+0x538/0x56c __mutex_lock_slowpath+0x10/0x20 mutex_lock+0x54/0x60 rtw_ops_set_tim+0x20/0x40 __sta_info_recalc_tim+0x150/0x250 sta_info_recalc_tim+0x10/0x20 invoke_tx_handlers_early+0x4e4/0x5c0 ieee80211_tx+0x78/0x110 ieee80211_xmit+0x94/0xc0 __ieee80211_subif_start_xmit+0x818/0xd20 ieee80211_subif_start_xmit+0x44/0x2d0 dev_hard_start_xmit+0xd0/0x150 __dev_queue_xmit+0x250/0xb30 dev_queue_xmit+0x10/0x20 br_dev_queue_push_xmit+0x94/0x174 br_forward_finish+0x90/0xa0 __br_forward+0xc0/0x13c br_forward+0x108/0x134 br_dev_xmit+0x1cc/0x3a4 dev_hard_start_xmit+0xd0/0x150 __dev_queue_xmit+0x250/0xb30 dev_queue_xmit+0x10/0x20 arp_xmit+0x6c/0x7c arp_send_dst+0x8c/0xc0 arp_solicit+0xd4/0x1e0 neigh_probe+0x58/0xa0 neigh_timer_handler+0x27c/0x380 call_timer_fn.constprop.0+0x20/0x80 __run_timers.part.0+0x230/0x280 run_timer_softirq+0x38/0x70 _stext+0x104/0x278 __irq_exit_rcu+0xa4/0xdc irq_exit_rcu+0xc/0x14 el1_interrupt+0x34/0x50 el1h_64_irq_handler+0x14/0x20 el1h_64_irq+0x64/0x68 arch_cpu_idle+0x14/0x20 do_idle+0x208/0x290 cpu_startup_entry+0x20/0x30 secondary_start_kernel+0x130/0x144 __secondary_switched+0x54/0x58 Fixes: f2217968ffda ("rtw88: Add update beacon flow for AP mode") Reported-by: Ondřej Jirman Signed-off-by: Ping-Ke Shih Tested-by: Ondřej Jirman Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220526051251.281905-1-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw88/fw.c | 10 ++++++++++ drivers/net/wireless/realtek/rtw88/fw.h | 1 + drivers/net/wireless/realtek/rtw88/mac80211.c | 4 +--- drivers/net/wireless/realtek/rtw88/main.c | 2 ++ drivers/net/wireless/realtek/rtw88/main.h | 1 + 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 090610e48d08..c3ae631c2264 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -1602,6 +1602,16 @@ free: return ret; } +void rtw_fw_update_beacon_work(struct work_struct *work) +{ + struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, + update_beacon_work); + + mutex_lock(&rtwdev->mutex); + rtw_fw_download_rsvd_page(rtwdev); + mutex_unlock(&rtwdev->mutex); +} + static void rtw_fw_read_fifo_page(struct rtw_dev *rtwdev, u32 offset, u32 size, u32 *buf, u32 residue, u16 start_pg) { diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h index 734113fba184..7a37675c61e8 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.h +++ b/drivers/net/wireless/realtek/rtw88/fw.h @@ -809,6 +809,7 @@ void rtw_add_rsvd_page_pno(struct rtw_dev *rtwdev, void rtw_add_rsvd_page_sta(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif); int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev); +void rtw_fw_update_beacon_work(struct work_struct *work); void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev); int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev, u32 offset, u32 size, u32 *buf); diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index 30903c567cd9..4310362dc333 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -493,9 +493,7 @@ static int rtw_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, { struct rtw_dev *rtwdev = hw->priv; - mutex_lock(&rtwdev->mutex); - rtw_fw_download_rsvd_page(rtwdev); - mutex_unlock(&rtwdev->mutex); + ieee80211_queue_work(hw, &rtwdev->update_beacon_work); return 0; } diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 14289f83feb5..efabd5b1bf5b 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -1442,6 +1442,7 @@ void rtw_core_stop(struct rtw_dev *rtwdev) mutex_unlock(&rtwdev->mutex); cancel_work_sync(&rtwdev->c2h_work); + cancel_work_sync(&rtwdev->update_beacon_work); cancel_delayed_work_sync(&rtwdev->watch_dog_work); cancel_delayed_work_sync(&coex->bt_relink_work); cancel_delayed_work_sync(&coex->bt_reenable_work); @@ -1998,6 +1999,7 @@ int rtw_core_init(struct rtw_dev *rtwdev) INIT_WORK(&rtwdev->c2h_work, rtw_c2h_work); INIT_WORK(&rtwdev->ips_work, rtw_ips_work); INIT_WORK(&rtwdev->fw_recovery_work, rtw_fw_recovery_work); + INIT_WORK(&rtwdev->update_beacon_work, rtw_fw_update_beacon_work); INIT_WORK(&rtwdev->ba_work, rtw_txq_ba_work); skb_queue_head_init(&rtwdev->c2h_queue); skb_queue_head_init(&rtwdev->coex.queue); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 0baaf5a32e82..c02be4ac159e 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -2008,6 +2008,7 @@ struct rtw_dev { struct work_struct c2h_work; struct work_struct ips_work; struct work_struct fw_recovery_work; + struct work_struct update_beacon_work; /* used to protect txqs list */ spinlock_t txq_lock; -- cgit v1.2.3 From 2965c4cdf7ad9ce0796fac5e57debb9519ea721e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 1 Jun 2022 09:19:36 +0200 Subject: wifi: mac80211: fix use-after-free in chanctx code In ieee80211_vif_use_reserved_context(), when we have an old context and the new context's replace_state is set to IEEE80211_CHANCTX_REPLACE_NONE, we free the old context in ieee80211_vif_use_reserved_reassign(). Therefore, we cannot check the old_ctx anymore, so we should set it to NULL after this point. However, since the new_ctx replace state is clearly not IEEE80211_CHANCTX_REPLACES_OTHER, we're not going to do anything else in this function and can just return to avoid accessing the freed old_ctx. Cc: stable@vger.kernel.org Fixes: 5bcae31d9cb1 ("mac80211: implement multi-vif in-place reservations") Signed-off-by: Johannes Berg Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220601091926.df419d91b165.I17a9b3894ff0b8323ce2afdb153b101124c821e5@changeid --- net/mac80211/chan.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index e3452445b363..d8246e00a10b 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -1749,12 +1749,9 @@ int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata) if (new_ctx->replace_state == IEEE80211_CHANCTX_REPLACE_NONE) { if (old_ctx) - err = ieee80211_vif_use_reserved_reassign(sdata); - else - err = ieee80211_vif_use_reserved_assign(sdata); + return ieee80211_vif_use_reserved_reassign(sdata); - if (err) - return err; + return ieee80211_vif_use_reserved_assign(sdata); } /* -- cgit v1.2.3