6.18.32-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 75/957 wifi: mt76: mt7996: fix iface combination for different chipsets
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shayne Chen <[email protected]>
[ Upstream commit 5ef0e8e2653b1ba325eb883ffb94073f19cb669a ]
MT7992 and MT7990 support up to 19 interfaces per band and 32 in total.
--- .../net/wireless/mediatek/mt76/mt7996/init.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7996/init.c +16 -1
@@ -34,6 +34,20 @@ static const struct ieee80211_iface_combination if_comb_global = {BIT (NL80211_CHAN_WIDTH_40 ) |BIT (NL80211_CHAN_WIDTH_80 ) | BIT(NL80211_CHAN_WIDTH_160), + .beacon_int_min_gcd = 100, +}; + +static const struct ieee80211_iface_combination if_comb_global_7992 = { + .limits = &if_limits_global, + .n_limits =1 , + .max_interfaces =32 , + .num_different_channels =MT7996_MAX_RADIOS -1 , + .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_160 ), + .beacon_int_min_gcd =100 , };static const struct ieee80211_iface_limit if_limits[] = {
@@ -485,7 +499,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed) hw->vif_data_size =sizeof (struct mt7996_vif ); hw->chanctx_data_size =sizeof (struct mt76_chanctx ); - wiphy->iface_combinations = &if_comb_global; + wiphy->iface_combinations =is_mt7996 (&dev->mt76) ? &if_comb_global : + &if_comb_global_7992; wiphy->n_iface_combinations =1 ; wiphy->radio = dev->radios;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 76/957 wifi: mt76: mt7996: Set mtxq->wcid just for primary link
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 654abcbe4528f74428b69292fad5c4224414fa1b ]
Set WCID index in mt76_txq struct just for the primary link in mt7996_vif_link_add routine.
--- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/main.c +6 -8
@@ -301,7 +301,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif, .cmd = SET_KEY, .link_id = link_conf->link_id, }; -struct mt76_txq *mtxq;int mld_idx, idx, ret; mlink->idx =__ffs64 (~dev->mt76.vif_mask);
@@ -344,11 +343,6 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,mt7996_mac_wtbl_update (dev, idx,MT_WTBL_UPDATE_ADM_COUNT_CLEAR ); -if (vif->txq) { - mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = idx; - } -if (vif->type !=NL80211_IFTYPE_AP && (!mlink->omac_idx || mlink->omac_idx >3 )) vif->offload_flags =0 ;
@@ -371,9 +365,13 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,ieee80211_iter_keys (mphy->hw, vif, mt7996_key_iter, &it); -if (!mlink->wcid->offchannel && - mvif->mt76.deflink_id ==IEEE80211_LINK_UNSPECIFIED ) +if (vif->txq && !mlink->wcid->offchannel && + mvif->mt76.deflink_id ==IEEE80211_LINK_UNSPECIFIED ) { +struct mt76_txq *mtxq = (struct mt76_txq *)vif->txq->drv_priv; + mvif->mt76.deflink_id = link_conf->link_id; + mtxq->wcid = idx; + }return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 77/957 wifi: mt76: mt7996: Reset mtxq->idx if primary link is removed in mt7996_vif_link_remove()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 751a2679b15e3a0fa8fc9175862f0ec40643db68 ]
Reset WCID index in mt76_txq struct if primary link is removed in mt7996_vif_link_remove routine.
--- .../net/wireless/mediatek/mt76/mt7996/main.c | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/main.c +16 -5
@@ -402,17 +402,28 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,rcu_assign_pointer (dev->mt76.wcid[idx],NULL ); -if (!mlink->wcid->offchannel && +if (vif->txq && !mlink->wcid->offchannel && mvif->mt76.deflink_id == link_conf->link_id) {struct ieee80211_bss_conf *iter; +struct mt76_txq *mtxq;unsigned int link_id; mvif->mt76.deflink_id =IEEE80211_LINK_UNSPECIFIED ; + mtxq = (struct mt76_txq *)vif->txq->drv_priv; +/* Primary link will be removed, look for a new one */ for_each_vif_active_link (vif, iter, link_id) { -if (link_id !=IEEE80211_LINK_UNSPECIFIED ) { - mvif->mt76.deflink_id = link_id; -break ; - } +struct mt7996_vif_link *link; + +if (link_id == link_conf->link_id) +continue ; + + link =mt7996_vif_link (dev, vif, link_id); +if (!link) +continue ; + + mtxq->wcid = link->msta_link.wcid.idx; + mvif->mt76.deflink_id = link_id; +break ; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 78/957 wifi: mt76: mt7996: Clear wcid pointer in mt7996_mac_sta_deinit_link()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 88973240dc7c976dd320b36a9e6d925c9be083ae ]
Clear WCID pointer removing the sta link in mt7996_mac_sta_deinit_link routine.
--- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/mt7996/main.c +1 -0
@@ -1032,6 +1032,7 @@ void mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,list_del_init (&msta_link->rc_list);spin_unlock_bh (&dev->mt76.sta_poll_lock); +rcu_assign_pointer (dev->mt76.wcid[msta_link->wcid.idx],NULL );mt76_wcid_cleanup (&dev->mt76, &msta_link->wcid);mt76_wcid_mask_clear (dev->mt76.wcid_mask, msta_link->wcid.idx); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 79/957 wifi: mt76: mt7996: Reset ampdu_state state in case of failure in mt7996_tx_check_aggr()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit c0747db7c10c2dfbdcff0e8e97021e3df1f1e362 ]
Reset the ampdu_state configured state if ieee80211_start_tx_ba_session routine fails in mt7996_tx_check_aggr()
--- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +3 -2
@@ -1243,8 +1243,9 @@ mt7996_tx_check_aggr(struct ieee80211_link_sta *link_sta,if (unlikely (fc != (IEEE80211_FTYPE_DATA |IEEE80211_STYPE_QOS_DATA )))return ; -if (!test_and_set_bit (tid, &wcid->ampdu_state)) -ieee80211_start_tx_ba_session (link_sta->sta, tid,0 ); +if (!test_and_set_bit (tid, &wcid->ampdu_state) && +ieee80211_start_tx_ba_session (link_sta->sta, tid,0 )) +clear_bit (tid, &wcid->ampdu_state); } static void
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 80/957 wifi: mt76: mt7921: Reset ampdu_state state in case of failure in mt76_connac2_tx_check_aggr()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Wang <[email protected]>
[ Upstream commit 53ffffeb9624ffab6d9a3b1da8635a23f1172b5e ]
Reset ampdu_state if ieee80211_start_tx_ba_session() fails in mt76_connac2_tx_check_aggr(), otherwise the driver may incorrectly assume aggregation is active and skip future BA setup attempts.
--- drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +4 -2
@@ -1150,8 +1150,10 @@ void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)return ; wcid = (struct mt76_wcid *)sta->drv_priv; -if (!test_and_set_bit (tid, &wcid->ampdu_state)) -ieee80211_start_tx_ba_session (sta, tid,0 ); +if (!test_and_set_bit (tid, &wcid->ampdu_state)) { +if (ieee80211_start_tx_ba_session (sta, tid,0 )) +clear_bit (tid, &wcid->ampdu_state); + } }EXPORT_SYMBOL_GPL (mt76_connac2_tx_check_aggr);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 81/957 wifi: mt76: mt7925: Fix incorrect MLO mode in firmware control
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Yen <[email protected]>
[ Upstream commit 1695f662329faa07c860c73453c097823852df28 ]
The selection of MLO mode should depend on the capabilities of the STA rather than those of the peer AP to avoid compatibility issues with certain APs, such as Xiaomi BE5000 WiFi7 router.
--- drivers/net/wireless/mediatek/mt76/mt7925/main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 9 ++++++--- drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7925/main.c +1 -1
@@ -533,7 +533,7 @@ static int mt7925_set_mlo_roc(struct mt792x_phy *phy, phy->roc_grant = false; - err =mt7925_mcu_set_mlo_roc (mconf, sel_links,5 , ++phy->roc_token_id); + err =mt7925_mcu_set_mlo_roc (phy, mconf, sel_links,5 , ++phy->roc_token_id);if (err <0 ) {clear_bit (MT76_STATE_ROC , &phy->mt76->state); goto out;
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +6 -3
@@ -1243,8 +1243,8 @@ int mt7925_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,return mt76_mcu_skb_send_msg (dev, skb, mcu_cmd, true); } -int mt7925_mcu_set_mlo_roc (struct mt792x_bss_conf *mconf,u16 sel_links, -int duration,u8 token_id) +int mt7925_mcu_set_mlo_roc (struct mt792x_phy *phy,struct mt792x_bss_conf *mconf, +u16 sel_links,int duration,u8 token_id) {struct mt792x_vif *mvif = mconf->vif; struct ieee80211_vif *vif = container_of((void *)mvif,
@@ -1279,6 +1279,8 @@ int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links, .roc[1].len = cpu_to_le16(sizeof(struct roc_acquire_tlv)) }; +struct wiphy *wiphy = phy->mt76->hw->wiphy; +if (!mconf ||hweight16 (vif->valid_links) <2 ||hweight16 (sel_links) !=2 )return -EPERM ;
@@ -1301,7 +1303,8 @@ int mt7925_mcu_set_mlo_roc(struct mt792x_bss_conf *mconf, u16 sel_links, is_AG_band |= links[i].chan->band ==NL80211_BAND_2GHZ ; } -if (vif->cfg.eml_cap &IEEE80211_EML_CAP_EMLSR_SUPP ) +if (!(wiphy->iftype_ext_capab[0 ].mld_capa_and_ops & +IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS )) type = is_AG_band ?MT7925_ROC_REQ_MLSR_AG :MT7925_ROC_REQ_MLSR_AA ;else
drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h +2 -2
@@ -345,8 +345,8 @@ int mt7925_set_tx_sar_pwr(struct ieee80211_hw *hw,int mt7925_mcu_regval (struct mt792x_dev *dev,u32 regidx,u32 *val,bool set);int mt7925_mcu_set_clc (struct mt792x_dev *dev,u8 *alpha2,enum environment_cap env_cap); -int mt7925_mcu_set_mlo_roc (struct mt792x_bss_conf *mconf,u16 sel_links, -int duration,u8 token_id); +int mt7925_mcu_set_mlo_roc (struct mt792x_phy *phy,struct mt792x_bss_conf *mconf, +u16 sel_links,int duration,u8 token_id);int mt7925_mcu_set_roc (struct mt792x_phy *phy,struct mt792x_bss_conf *mconf,struct ieee80211_channel *chan,int duration,enum mt7925_roc_req type,u8 token_id);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 82/957 wifi: mt76: mt7615: fix use_cts_prot support
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryder Lee <[email protected]>
[ Upstream commit 1974a67d9b65c29a0a9426e32e8cd8c056de48b7 ]
Driver should not directly write WTBL to prevent overwritten issues.
With this fix, when driver needs to adjust its behavior for compatibility, especially concerning older 11g/n devices, by enabling or disabling CTS protection frames, often for hidden SSIDs or to manage legacy clients.
--- .../net/wireless/mediatek/mt76/mt7615/mac.c | 15 ------ .../net/wireless/mediatek/mt76/mt7615/main.c | 7 +-- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 47 +++++++++++++++++++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 5 +- .../net/wireless/mediatek/mt76/mt7615/regs.h | 2 - 5 files changed, 53 insertions(+), 23 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +0 -15
@@ -1167,21 +1167,6 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, }EXPORT_SYMBOL_GPL (mt7615_mac_set_rates); -void mt7615_mac_enable_rtscts (struct mt7615_dev *dev, -struct ieee80211_vif *vif,bool enable) -{ -struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; -u32 addr; - - addr =mt7615_mac_wtbl_addr (dev, mvif->sta.wcid.idx) +3 *4 ; - -if (enable) -mt76_set (dev, addr,MT_WTBL_W3_RTS ); -else -mt76_clear (dev, addr,MT_WTBL_W3_RTS ); -} -EXPORT_SYMBOL_GPL (mt7615_mac_enable_rtscts); - static int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, struct ieee80211_key_conf *key,
drivers/net/wireless/mediatek/mt76/mt7615/main.c +4 -3
@@ -583,9 +583,6 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, } } -if (changed &BSS_CHANGED_ERP_CTS_PROT ) -mt7615_mac_enable_rtscts (dev, vif, info->use_cts_prot); -if (changed &BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {mt7615_mcu_add_bss_info (phy, vif,NULL , true);mt7615_mcu_sta_add (phy, vif,NULL , true);
@@ -598,6 +595,10 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, BSS_CHANGED_BEACON_ENABLED)) mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon); +if (changed &BSS_CHANGED_HT || changed &BSS_CHANGED_ERP_CTS_PROT ) +mt7615_mcu_set_protection (phy, vif, info->ht_operation_mode, + info->use_cts_prot); +if (changed &BSS_CHANGED_PS )mt76_connac_mcu_set_vif_ps (&dev->mt76, vif);
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +47 -0
50 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +2 -3
@@ -466,8 +466,6 @@ void mt7615_mac_reset_counters(struct mt7615_phy *phy);void mt7615_mac_cca_stats_reset (struct mt7615_phy *phy);void mt7615_mac_set_scs (struct mt7615_phy *phy,bool enable);void mt7615_mac_enable_nf (struct mt7615_dev *dev,bool ext_phy); -void mt7615_mac_enable_rtscts (struct mt7615_dev *dev, -struct ieee80211_vif *vif,bool enable);void mt7615_mac_sta_poll (struct mt7615_dev *dev); int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid,
@@ -522,7 +520,8 @@ int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable);int mt7615_mcu_apply_rx_dcoc (struct mt7615_phy *phy);int mt7615_mcu_apply_tx_dpd (struct mt7615_phy *phy);int mt7615_dfs_init_radar_detector (struct mt7615_phy *phy); - +int mt7615_mcu_set_protection (struct mt7615_phy *phy,struct ieee80211_vif *vif, +u8 ht_mode,bool use_cts_prot);int mt7615_mcu_set_roc (struct mt7615_phy *phy,struct ieee80211_vif *vif,struct ieee80211_channel *chan,int duration);
drivers/net/wireless/mediatek/mt76/mt7615/regs.h +0 -2
@@ -455,8 +455,6 @@ enum mt7615_reg_base {#define MT_WTBL_RIUCR3_RATE6 GENMASK(19, 8)#define MT_WTBL_RIUCR3_RATE7 GENMASK(31, 20) -#define MT_WTBL_W3_RTS BIT(22) -#define MT_WTBL_W5_CHANGE_BW_RATE GENMASK(7, 5)#define MT_WTBL_W5_SHORT_GI_20 BIT(8)#define MT_WTBL_W5_SHORT_GI_40 BIT(9)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 83/957 wifi: mt76: mt7915: fix use_cts_prot support
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryder Lee <[email protected]>
[ Upstream commit 8b2c26562b95c6397e132d21f2bd3d73aaee0c0a ]
With this fix, when driver needs to adjust its behavior for compatibility, especially concerning older 11g/n devices, by enabling or disabling CTS protection frames, often for hidden SSIDs or to manage legacy clients.
--- .../net/wireless/mediatek/mt76/mt7915/mac.c | 13 ---- .../net/wireless/mediatek/mt76/mt7915/main.c | 7 ++- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 62 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7915/mcu.h | 11 ++++ .../wireless/mediatek/mt76/mt7915/mt7915.h | 4 ++ 5 files changed, 81 insertions(+), 16 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +0 -13
@@ -232,19 +232,6 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)rcu_read_unlock (); } -void mt7915_mac_enable_rtscts (struct mt7915_dev *dev, -struct ieee80211_vif *vif,bool enable) -{ -struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; -u32 addr; - - addr =mt7915_mac_wtbl_lmac_addr (dev, mvif->sta.wcid.idx,5 ); -if (enable) -mt76_set (dev, addr,BIT (5 )); -else -mt76_clear (dev, addr,BIT (5 )); -} - static void mt7915_wed_check_ppe(struct mt7915_dev *dev, struct mt76_queue *q, struct mt7915_sta *msta, struct sk_buff *skb,
drivers/net/wireless/mediatek/mt76/mt7915/main.c +4 -3
@@ -68,7 +68,7 @@ int mt7915_run(struct ieee80211_hw *hw)if (ret) goto out; - ret =mt76_connac_mcu_set_rts_thresh (&dev->mt76,0x92b , + ret =mt76_connac_mcu_set_rts_thresh (&dev->mt76,MT7915_RTS_LEN_THRES , phy->mt76->band_idx);if (ret) goto out;
@@ -633,8 +633,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,if (set_sta ==1 )mt7915_mcu_add_sta (dev, vif,NULL ,CONN_STATE_PORT_SECURE , false); -if (changed &BSS_CHANGED_ERP_CTS_PROT ) -mt7915_mac_enable_rtscts (dev, vif, info->use_cts_prot); +if (changed &BSS_CHANGED_HT || changed &BSS_CHANGED_ERP_CTS_PROT ) +mt7915_mcu_set_protection (phy, vif, info->ht_operation_mode, + info->use_cts_prot);if (changed &BSS_CHANGED_ERP_SLOT ) {int slottime =9 ;
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +62 -0
68 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +11 -0
@@ -399,6 +399,17 @@ struct bss_info_inband_discovery {__le16 prob_rsp_len; } __packed__aligned(4) ; +struct bss_info_prot { +__le16 tag; +__le16 len; +__le32 prot_type; +__le32 prot_mode; +__le32 rts_len_thres; +__le16 he_rts_thres; +u8 rts_pkt_thres; +u8 rsv[5 ]; +} __packed; +enum {BSS_INFO_BCN_CSA ,BSS_INFO_BCN_BCC ,
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +4 -0
@@ -83,6 +83,8 @@#define MT7915_CRIT_TEMP 110#define MT7915_MAX_TEMP 120 +#define MT7915_RTS_LEN_THRES 0x92b +struct mt7915_vif ;struct mt7915_sta ;struct mt7915_dfs_pulse ;
@@ -469,6 +471,8 @@ int mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *v u32 changed);int mt7915_mcu_add_beacon (struct ieee80211_hw *hw,struct ieee80211_vif *vif,int enable,u32 changed); +int mt7915_mcu_set_protection (struct mt7915_phy *phy,struct ieee80211_vif *vif, +u8 ht_mode,bool use_cts_prot);int mt7915_mcu_add_obss_spr (struct mt7915_phy *phy,struct ieee80211_vif *vif,struct ieee80211_he_obss_pd *he_obss_pd); int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 84/957 wifi: mt76: mt7925: prevent NULL pointer dereference in mt7925_tx_check_aggr()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Yen Hsieh <[email protected]>
[ Upstream commit 83ae3a18ba957257b4c406273d2da2caeea2b439 ]
Move the NULL check for 'sta' before dereferencing it to prevent a possible crash.
--- drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7925/mac.c +4 -1
@@ -845,11 +845,14 @@ static void mt7925_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb,bool is_8023;u16 fc, tid; +if (!sta) +return ; + link_sta =rcu_dereference (sta->link[wcid->link_id]);if (!link_sta)return ; -if (!sta || !(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he)) +if (!(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))return ; tid = skb->priority &IEEE80211_QOS_CTL_TID_MASK ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 85/957 wifi: mt76: mt7925: prevent NULL vif dereference in mt7925_mac_write_txwi
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Yen Hsieh <[email protected]>
[ Upstream commit 962eb04e67552be406c906c83099c1d736aae3b6 ]
Check for a NULL vif before accessing ieee80211_vif_is_mld(vif) to avoid a potential kernel panic in scenarios where vif might not be initialized.
--- drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7925/mac.c +2 -2
@@ -803,8 +803,8 @@ mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, txwi[5 ] =cpu_to_le32 (val); val =MT_TXD6_DAS |FIELD_PREP (MT_TXD6_MSDU_CNT ,1 ); -if (!ieee80211_vif_is_mld (vif) || - (q_idx >=MT_LMAC_ALTX0 && q_idx <=MT_LMAC_BCN0 )) +if (vif && (!ieee80211_vif_is_mld (vif) || + (q_idx >=MT_LMAC_ALTX0 && q_idx <=MT_LMAC_BCN0 ))) val |=MT_TXD6_DIS_MAT ; txwi[6 ] =cpu_to_le32 (val); txwi[7 ] =0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 86/957 wifi: mt76: mt7996: fix FCS error flag check in RX descriptor
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alok Tiwari <[email protected]>
[ Upstream commit d8db56142e531f060c938fa0b5175ed6c8cabb11 ]
The mt7996 driver currently checks the MT_RXD3_NORMAL_FCS_ERR bit in rxd1 whereas other Connac3-based drivers(mt7925) correctly check this bit in rxd3.
Since the MT_RXD3_NORMAL_FCS_ERR bit is defined in the fourth RX descriptor word (rxd3), update mt7996 to use the proper descriptor field. This change aligns mt7996 with mt7925 and the rest of the Connac3 family.
--- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +1 -1
@@ -527,7 +527,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) skb->ip_summed = CHECKSUM_UNNECESSARY; -if (rxd1 &MT_RXD3_NORMAL_FCS_ERR ) +if (rxd3 &MT_RXD3_NORMAL_FCS_ERR ) status->flag |=RX_FLAG_FAILED_FCS_CRC ;if (rxd1 &MT_RXD1_NORMAL_TKIP_MIC_ERR )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 87/957 wifi: mt76: mt7921: Place upper limit on station AID
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rory Little <[email protected]>
[ Upstream commit 4d0bf21e3e20619d51d06c0c36207aabab8b712c ]
Any station configured with an AID over 20 causes a firmware crash. This situation occurred in our testing using an AP interface on 7922 hardware, with a modified hostapd, sourced from Mediatek's OpenWRT feeds.
In stock hostapd, station AIDs begin counting at 1, and this configuration is prevented with an upper limit on associated stations. However, the modified hostapd began allocation at 65, which caused the firmware to crash. This fix does not allow these AIDs to work, but will prevent the firmware crash.
This crash was only seen on IFTYPE_AP interfaces, and the fix does not appear to have an effect on IFTYPE_STATION behavior.
--- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 6 ++++++ drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 2 ++ 2 files changed, 8 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7921/main.c +6 -0
@@ -808,6 +808,9 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;int ret, idx; +if (sta->aid >MT7921_MAX_AID ) +return -ENOENT ; + idx =mt76_wcid_alloc (dev->mt76.wcid_mask, MT792x_WTBL_STA -1 );if (idx <0 )return -ENOSPC ;
@@ -851,6 +854,9 @@ int mt7921_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; +if (sta->aid >MT7921_MAX_AID ) +return -ENOENT ; +if (ev !=MT76_STA_EVENT_ASSOC )return 0 ;
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +2 -0
@@ -7,6 +7,8 @@#include "../mt792x.h" #include "regs.h" +#define MT7921_MAX_AID 20 +#define MT7921_TX_RING_SIZE 2048#define MT7921_TX_MCU_RING_SIZE 256#define MT7921_TX_FWDL_RING_SIZE 128
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 88/957 wifi: mt76: Fix memory leak destroying device
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 6b470f36616e3448d44b0ef4b1de2a3e3a31b5be ]
All MT76 rx queues have an associated page_pool even if the queue is not associated to a NAPI (e.g. WED RRO queues with WED enabled). Destroy the page_pool running mt76_dma_cleanup routine during module unload. Moreover returns pages to the page pool if WED is not enabled for WED RRO queues.
--- drivers/net/wireless/mediatek/mt76/dma.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/dma.c +6 -5
@@ -878,7 +878,12 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)if (!buf)break ; -if (!mt76_queue_is_wed_rro (q)) +if (mtk_wed_device_active (&dev->mmio.wed) && +mt76_queue_is_wed_rro (q)) +continue ; + +if (!mt76_queue_is_wed_rro_rxdmad_c (q) && + !mt76_queue_is_wed_rro_ind (q))mt76_put_page_pool_buf (buf, false); }while (1 );
@@ -1169,10 +1174,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)mt76_for_each_q_rx (dev, i) {struct mt76_queue *q = &dev->q_rx[i]; -if (mtk_wed_device_active (&dev->mmio.wed) && -mt76_queue_is_wed_rro (q)) -continue ; -netif_napi_del (&dev->napi[i]);mt76_dma_rx_cleanup (dev, q);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 89/957 wifi: mt76: mt7925: cqm rssi low/high event notify
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jack Kao <[email protected]>
[ Upstream commit 2a035ae2062f38dc5183002d1c5a64ca682170c1 ]
The implementation amounts to setting the driver flag IEEE80211_VIF_SUPPORTS_CQM_RSSI, and then providing mechanisms for continuously updating enough information to be able to provide notifications to userspace when RSSI drops below a certain threshold
Stable-dep-of: 59a1864509d0 ("wifi: mt76: mt7925: drop puncturing handling from BSS change path")
--- .../wireless/mediatek/mt76/mt76_connac_mcu.h | 2 + .../net/wireless/mediatek/mt76/mt7925/main.c | 6 ++ .../net/wireless/mediatek/mt76/mt7925/mcu.c | 82 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7925/mcu.h | 8 ++ .../wireless/mediatek/mt76/mt7925/mt7925.h | 7 ++ 5 files changed, 105 insertions(+)
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +2 -0
@@ -1062,6 +1062,7 @@ enum {MCU_UNI_EVENT_ROC =0x27 ,MCU_UNI_EVENT_TX_DONE =0x2d ,MCU_UNI_EVENT_THERMAL =0x35 , +MCU_UNI_EVENT_RSSI_MONITOR =0x41 ,MCU_UNI_EVENT_NIC_CAPAB =0x43 ,MCU_UNI_EVENT_WED_RRO =0x57 , MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
@@ -1300,6 +1301,7 @@ enum {MCU_UNI_CMD_THERMAL =0x35 ,MCU_UNI_CMD_VOW =0x37 ,MCU_UNI_CMD_FIXED_RATE_TABLE =0x40 , +MCU_UNI_CMD_RSSI_MONITOR =0x41 ,MCU_UNI_CMD_TESTMODE_CTRL =0x46 ,MCU_UNI_CMD_RRO =0x57 , MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
drivers/net/wireless/mediatek/mt76/mt7925/main.c +6 -0
@@ -430,6 +430,9 @@ mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) goto out; vif->driver_flags |=IEEE80211_VIF_BEACON_FILTER ; +if (phy->chip_cap & MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN) + vif->driver_flags |=IEEE80211_VIF_SUPPORTS_CQM_RSSI ; + out:mt792x_mutex_release (dev);
@@ -1958,6 +1961,9 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw,mt7925_mcu_set_eht_pp (mvif->phy->mt76, &mconf->mt76, link_conf,NULL ); +if (changed &BSS_CHANGED_CQM ) +mt7925_mcu_set_rssimonitor (dev, vif); +mt792x_mutex_release (dev); }
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +82 -0
97 lines not on this page · raw message
drivers/net/wireless/mediatek/mt76/mt7925/mcu.h +8 -0
@@ -152,6 +152,14 @@ enum { UNI_EVENT_SCAN_DONE_NLO = 3, }; +enum { +UNI_CMD_RSSI_MONITOR_SET =0 , +}; + +enum { +UNI_EVENT_RSSI_MONITOR_INFO =0 , +}; +enum connac3_mcu_cipher_type {CONNAC3_CIPHER_NONE =0 ,CONNAC3_CIPHER_WEP40 =1 ,
drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h +7 -0
@@ -103,6 +103,12 @@ struct mt7925_uni_beacon_loss_event {struct mt7925_beacon_loss_tlv beacon_loss; } __packed; +struct mt7925_uni_rssi_monitor_event { +__le16 tag; +__le16 len; +__le32 rssi; +} __packed; +#define to_rssi (field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)#define to_rcpi (rssi) (2 * (rssi) + 220)
@@ -372,4 +378,5 @@ int mt7925_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,int mt7925_testmode_dump (struct ieee80211_hw *hw,struct sk_buff *msg,struct netlink_callback *cb,void *data,int len); +int mt7925_mcu_set_rssimonitor (struct mt792x_dev *dev,struct ieee80211_vif *vif);#endif
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 90/957 wifi: mt76: mt7925: drop puncturing handling from BSS change path
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Wang <[email protected]>
[ Upstream commit 59a1864509d084a4b34117e693951c06b846b00a ]
IEEE80211_CHANCTX_CHANGE_PUNCTURING is a channel context change flag and should not be checked in the BSS change handler, where the changed mask represents enum ieee80211_bss_change.
Remove the puncturing handling from the BSS path and rely on mt7925_change_chanctx() to update puncturing configuration.
--- drivers/net/wireless/mediatek/mt76/mt7925/main.c | 6 ------ 1 file changed, 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7925/main.c +0 -6
@@ -1912,10 +1912,8 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw,struct mt792x_phy *phy =mt792x_hw_phy (hw);struct mt792x_dev *dev =mt792x_hw_dev (hw);struct mt792x_bss_conf *mconf; -struct ieee80211_bss_conf *link_conf; mconf =mt792x_vif_to_link (mvif, info->link_id); - link_conf =mt792x_vif_to_bss_conf (vif, mconf->link_id);mt792x_mutex_acquire (dev);
@@ -1957,10 +1955,6 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw, mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS; } -if (changed &IEEE80211_CHANCTX_CHANGE_PUNCTURING ) -mt7925_mcu_set_eht_pp (mvif->phy->mt76, &mconf->mt76, - link_conf,NULL ); -if (changed &BSS_CHANGED_CQM )mt7925_mcu_set_rssimonitor (dev, vif);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 91/957 wifi: mt76: mt7925: fix potential deadlock in mt7925_roc_abort_sync
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Wang <[email protected]>
[ Upstream commit dd08ca3f092f4185ece69ce2a835c23198b1628a ]
roc_abort_sync() can deadlock with roc_work(). roc_work() holds dev->mt76.mutex, while cancel_work_sync() waits for roc_work() to finish. If the caller already owns the same mutex, both sides block and no progress is possible.
This deadlock can occur during station removal when mt76_sta_state() -> mt76_sta_remove() -> mt7925_mac_sta_remove_link() -> mt7925_mac_link_sta_remove() -> mt7925_roc_abort_sync() invokes cancel_work_sync() while roc_work() is still running and holding dev->mt76.mutex.
This avoids the mutex deadlock and preserves exactly-once work ownership.
--- drivers/net/wireless/mediatek/mt76/mt7925/main.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7925/main.c +9 -5
@@ -452,12 +452,16 @@ void mt7925_roc_abort_sync(struct mt792x_dev *dev) {struct mt792x_phy *phy = &dev->phy; +if (!test_and_clear_bit (MT76_STATE_ROC , &phy->mt76->state)) +return ; +timer_delete_sync (&phy->roc_timer); -cancel_work_sync (&phy->roc_work); -if (test_and_clear_bit (MT76_STATE_ROC , &phy->mt76->state)) -ieee80211_iterate_interfaces (mt76_hw (dev), -IEEE80211_IFACE_ITER_RESUME_ALL , - mt7925_roc_iter, (void *)phy); + +cancel_work (&phy->roc_work); + +ieee80211_iterate_interfaces (mt76_hw (dev), +IEEE80211_IFACE_ITER_RESUME_ALL , + mt7925_roc_iter, (void *)phy); }EXPORT_SYMBOL_GPL (mt7925_roc_abort_sync);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 92/957 wifi: mt76: mt7921: fix potential deadlock in mt7921_roc_abort_sync
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Wang <[email protected]>
[ Upstream commit d5059e52fd8bc624ec4255c9fa01a266513d126b ]
roc_abort_sync() can deadlock with roc_work(). roc_work() holds dev->mt76.mutex, while cancel_work_sync() waits for roc_work() to finish. If the caller already owns the same mutex, both sides block and no progress is possible.
This deadlock can occur during station removal when mt76_sta_state() -> mt76_sta_remove() -> mt7921_mac_sta_remove() -> mt7921_roc_abort_sync() invokes cancel_work_sync() while roc_work() is still running and holding dev->mt76.mutex.
This avoids the mutex deadlock and preserves exactly-once work ownership.
--- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/main.c +8 -5
@@ -371,12 +371,15 @@ void mt7921_roc_abort_sync(struct mt792x_dev *dev) {struct mt792x_phy *phy = &dev->phy; +if (!test_and_clear_bit (MT76_STATE_ROC , &phy->mt76->state)) +return ; +timer_delete_sync (&phy->roc_timer); -cancel_work_sync (&phy->roc_work); -if (test_and_clear_bit (MT76_STATE_ROC , &phy->mt76->state)) -ieee80211_iterate_interfaces (mt76_hw (dev), -IEEE80211_IFACE_ITER_RESUME_ALL , - mt7921_roc_iter, (void *)phy); +cancel_work (&phy->roc_work); + +ieee80211_iterate_interfaces (mt76_hw (dev), +IEEE80211_IFACE_ITER_RESUME_ALL , + mt7921_roc_iter, (void *)phy); }EXPORT_SYMBOL_GPL (mt7921_roc_abort_sync);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 93/957 wifi: mt76: fix deadlock in remain-on-channel
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chad Monroe <[email protected]>
[ Upstream commit 6939b97ddad3cf3dfbb3b5a0a12ef79cb886747e ]
mt76_remain_on_channel() and mt76_roc_complete() call mt76_set_channel() while already holding dev->mutex. Since mt76_set_channel() also acquires dev->mutex, this results in a deadlock.
Use __mt76_set_channel() instead of mt76_set_channel().
Add cancel_delayed_work_sync() for mac_work before acquiring the mutex in mt76_remain_on_channel() to prevent a secondary deadlock with the mac_work workqueue.
--- drivers/net/wireless/mediatek/mt76/channel.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/channel.c +11 -2
@@ -326,7 +326,7 @@ void mt76_roc_complete(struct mt76_phy *phy) mlink->mvif->roc_phy =NULL ;if (phy->main_chandef.chan && !test_bit (MT76_MCU_RESET , &dev->phy.state)) -mt76_set_channel (phy, &phy->main_chandef, false); +__mt76_set_channel (phy, &phy->main_chandef, false);mt76_put_vif_phy_link (phy, phy->roc_vif, phy->roc_link); phy->roc_vif =NULL ; phy->roc_link =NULL ;
@@ -370,6 +370,8 @@ int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif,if (!phy)return -EINVAL ; +cancel_delayed_work_sync (&phy->mac_work); +mutex_lock (&dev->mutex); if (phy->roc_vif || dev->scan.phy == phy ||
@@ -388,7 +390,14 @@ int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif, phy->roc_vif = vif; phy->roc_link = mlink;cfg80211_chandef_create (&chandef, chan,NL80211_CHAN_HT20 ); -mt76_set_channel (phy, &chandef, true); + ret =__mt76_set_channel (phy, &chandef, true); +if (ret) { + mlink->mvif->roc_phy =NULL ; + phy->roc_vif =NULL ; + phy->roc_link =NULL ; +mt76_put_vif_phy_link (phy, vif, mlink); + goto out; + }ieee80211_ready_on_channel (hw);ieee80211_queue_delayed_work (phy->hw, &phy->roc_work,msecs_to_jiffies (duration));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 94/957 arm64: cpufeature: Make PMUVer and PerfMon unsigned
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Clark <[email protected]>
[ Upstream commit d1dcc20bcc40efe1f1c71639376c91dafa489222 ]
On the host, this change doesn't make a difference because the fields are defined as FTR_EXACT. However, KVM allows userspace to set these fields for a guest and overrides the type to be FTR_LOWER_SAFE. And while KVM used to do an unsigned comparison to validate that the new value is lower than what the hardware provides, since the linked commit it uses the generic sanitization framework which does a signed comparison.
Fix it by defining these fields as unsigned. In theory, without this fix, userspace could set a higher PMU version than the hardware supports by providing any value with the top bit set.
--- arch/arm64/kernel/cpufeature.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/kernel/cpufeature.c +2 -2
@@ -564,7 +564,7 @@ static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = {* We can instantiate multiple PMU instances with different levels * of support. */ -S_ARM64_FTR_BITS (FTR_HIDDEN ,FTR_NONSTRICT ,FTR_EXACT , ID_AA64DFR0_EL1_PMUVer_SHIFT,4 ,0 ), +ARM64_FTR_BITS (FTR_HIDDEN ,FTR_NONSTRICT ,FTR_EXACT , ID_AA64DFR0_EL1_PMUVer_SHIFT,4 ,0 ),ARM64_FTR_BITS (FTR_HIDDEN ,FTR_STRICT ,FTR_EXACT , ID_AA64DFR0_EL1_DebugVer_SHIFT,4 ,0x6 ), ARM64_FTR_END, };
@@ -708,7 +708,7 @@ static const struct arm64_ftr_bits ftr_id_pfr2[] = {static const struct arm64_ftr_bits ftr_id_dfr0[] = {/* [31:28] TraceFilt */ -S_ARM64_FTR_BITS (FTR_HIDDEN ,FTR_NONSTRICT ,FTR_EXACT , ID_DFR0_EL1_PerfMon_SHIFT,4 ,0 ), +ARM64_FTR_BITS (FTR_HIDDEN ,FTR_NONSTRICT ,FTR_EXACT , ID_DFR0_EL1_PerfMon_SHIFT,4 ,0 ),ARM64_FTR_BITS (FTR_HIDDEN ,FTR_STRICT ,FTR_LOWER_SAFE , ID_DFR0_EL1_MProfDbg_SHIFT,4 ,0 ),ARM64_FTR_BITS (FTR_HIDDEN ,FTR_STRICT ,FTR_LOWER_SAFE , ID_DFR0_EL1_MMapTrc_SHIFT,4 ,0 ),ARM64_FTR_BITS (FTR_HIDDEN ,FTR_STRICT ,FTR_LOWER_SAFE , ID_DFR0_EL1_CopTrc_SHIFT,4 ,0 ),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 95/957 wifi: mt76: mt7996: fix wrong DMAD length when using MAC TXP
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shayne Chen <[email protected]>
[ Upstream commit 97b9f9831bf297f3ffa62018721601ed2736f2c3 ]
The struct mt76_connac_fw_txp is used for HIF TXP. Change to use the struct mt76_connac_hw_txp to fix the wrong DMAD length for MAC TXP.
--- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +4 -2
@@ -1109,10 +1109,10 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,* req */ if (le32_to_cpu (ptr[7 ]) &MT_TXD7_MAC_TXD ) { -u32 val; +u32 val, mac_txp_size =sizeof (struct mt76_connac_hw_txp ); ptr = (__le32 *)(txwi +MT_TXD_SIZE ); -memset ((void *)ptr,0 ,sizeof (struct mt76_connac_fw_txp )); +memset ((void *)ptr,0 , mac_txp_size); val =FIELD_PREP (MT_TXP0_TOKEN_ID0 , id) |MT_TXP0_TOKEN_ID0_VALID_MASK ;
@@ -1131,6 +1131,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, tx_info->buf[1].addr >> 32);#endif ptr[3 ] =cpu_to_le32 (val); + + tx_info->buf[0 ].len =MT_TXD_SIZE + mac_txp_size; }else {struct mt76_connac_txp_common *txp;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 96/957 wifi: mt76: mt7996: fix struct mt7996_mcu_uni_event
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: StanleyYP Wang <[email protected]>
[ Upstream commit efbd5bf395f4e6b45a87f3835d4c2e28170c77c5 ]
The cid field is defined as a two-byte value in the firmware.
--- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +1 -1
@@ -233,7 +233,7 @@ mt7996_mcu_parse_response(struct mt76_dev *mdev, int cmd, event = (struct mt7996_mcu_uni_event *)skb->data; ret =le32_to_cpu (event->status);/* skip invalid event */ -if (mcu_cmd != event->cid) +if (mcu_cmd !=le16_to_cpu (event->cid)) ret = -EAGAIN ; }else {skb_pull (skb,sizeof (struct mt7996_mcu_rxd ));
drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +2 -2
@@ -25,8 +25,8 @@ struct mt7996_mcu_rxd { };struct mt7996_mcu_uni_event { -u8 cid; -u8 __rsv[3 ]; +__le16 cid; +u8 __rsv[2 ];__le32 status;/* 0: success, others: fail */ } __packed;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 97/957 wifi: mt76: mt7915: fix use-after-free bugs in mt7915_mac_dump_work()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Duoming Zhou <[email protected]>
[ Upstream commit 1146d0946b5358fad24812bd39d68f31cd40cc34 ]
When the mt7915 pci chip is detaching, the mt7915_crash_data is released in mt7915_coredump_unregister(). However, the work item dump_work may still be running or pending, leading to UAF bugs when the already freed crash_data is dereferenced again in mt7915_mac_dump_work().
The race condition can occur as follows:
CPU 0 (removal path) | CPU 1 (workqueue)
mt7915_pci_remove() | mt7915_sys_recovery_set()
mt7915_unregister_device() | mt7915_reset()
mt7915_coredump_unregister() | queue_work()
vfree(dev->coredump.crash_data) | mt7915_mac_dump_work()
| crash_data-> // UAFFix this by ensuring dump_work is properly canceled before the crash_data is deallocated. Add cancel_work_sync() in mt7915_unregister_device() to synchronize with any pending or executing dump work.
--- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/mt7915/init.c +1 -0
@@ -1287,6 +1287,7 @@ int mt7915_register_device(struct mt7915_dev *dev)void mt7915_unregister_device (struct mt7915_dev *dev) { +cancel_work_sync (&dev->dump_work);mt7915_unregister_ext_phy (dev);mt7915_coredump_unregister (dev);mt7915_unregister_thermal (&dev->phy);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 98/957 wifi: mt76: mt7996: fix use-after-free bugs in mt7996_mac_dump_work()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Duoming Zhou <[email protected]>
[ Upstream commit c8f62f73bbced3a79894655bdb0b625462d956fc ]
When the mt7996 pci chip is detaching, the mt7996_crash_data is released in mt7996_coredump_unregister(). However, the work item dump_work may still be running or pending, leading to UAF bugs when the already freed crash_data is dereferenced again in mt7996_mac_dump_work().
The race condition can occur as follows:
CPU 0 (removal path) | CPU 1 (workqueue)
mt7996_pci_remove() | mt7996_sys_recovery_set()
mt7996_unregister_device() | mt7996_reset()
mt7996_coredump_unregister() | queue_work()
vfree(dev->coredump.crash_data) | mt7996_mac_dump_work()
| crash_data-> // UAFFix this by ensuring dump_work is properly canceled before the crash_data is deallocated. Add cancel_work_sync() in mt7996_unregister_device() to synchronize with any pending or executing dump work.
--- drivers/net/wireless/mediatek/mt76/mt7996/init.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/mt7996/init.c +1 -0
@@ -1732,6 +1732,7 @@ int mt7996_register_device(struct mt7996_dev *dev)void mt7996_unregister_device (struct mt7996_dev *dev) { +cancel_work_sync (&dev->dump_work);cancel_work_sync (&dev->wed_rro.work);mt7996_unregister_phy (mt7996_phy3 (dev));mt7996_unregister_phy (mt7996_phy2 (dev));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 99/957 wifi: mt76: mt7921: fix 6GHz regulatory update on connection
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Lo <[email protected]>
[ Upstream commit 3dc0c40d7806c72cfe88cf4e1e2650c1673f9db4 ]
Call mt7921_regd_update() instead of mt7921_mcu_set_clc() when setting the 6GHz power type after connection, so that regulatory limits and SAR power are also applied.
--- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7921/main.c +2 -1
@@ -800,7 +800,8 @@ mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif, bool is_add) } out: -mt7921_mcu_set_clc (dev, dev->mt76.alpha2, dev->country_ie_env); +if (vif->bss_conf.chanreq.oper.chan->band ==NL80211_BAND_6GHZ ) +mt7921_regd_update (dev); } int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 100/957 wifi: mt76: mt7996: Add missing CHANCTX_STA_CSA property
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit c0a47ffc4caaf5161955add553322112c3a211b0 ]
Enable missing CHANCTX_STA_CSA property required for MLO.
--- drivers/net/wireless/mediatek/mt76/mt7996/init.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/mt7996/init.c +1 -0
@@ -536,6 +536,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)ieee80211_hw_set (hw,SUPPORTS_RX_DECAP_OFFLOAD );ieee80211_hw_set (hw,NO_VIRTUAL_MONITOR );ieee80211_hw_set (hw,SUPPORTS_MULTI_BSSID ); +ieee80211_hw_set (hw,CHANCTX_STA_CSA ); hw->max_tx_fragments =4 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 101/957 wifi: mt76: mt7996: Remove link pointer dependency in mt7996_mac_sta_remove_links()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 569ce4340268915911fc356ec9ad27e92fb82289 ]
Remove link pointer dependency in mt7996_mac_sta_remove_links routine to get the mt7996_phy pointer since the link can be already offchannel running mt7996_mac_sta_remove_links(). Rely on __mt7996_phy routine instead.
--- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/main.c +4 -10
@@ -1047,8 +1047,7 @@ mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,for_each_set_bit (link_id, &links,IEEE80211_MLD_MAX_NUM_LINKS ) {struct mt7996_sta_link *msta_link =NULL ; -struct mt7996_vif_link *link; -struct mt76_phy *mphy; +struct mt7996_phy *phy; msta_link =rcu_replace_pointer (msta->link[link_id], msta_link,lockdep_is_held (&mdev->mutex));
@@ -1057,17 +1056,12 @@ mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,mt7996_mac_wtbl_update (dev, msta_link->wcid.idx,MT_WTBL_UPDATE_ADM_COUNT_CLEAR ); -mt7996_mac_sta_deinit_link (dev, msta_link); - link =mt7996_vif_link (dev, vif, link_id); -if (!link) -continue ; - mphy =mt76_vif_link_phy (&link->mt76); -if (!mphy) -continue ; + phy =__mt7996_phy (dev, msta_link->wcid.phy_idx); +if (phy) + phy->mt76->num_sta--; - mphy->num_sta--;if (msta->deflink_id == link_id) { msta->deflink_id =IEEE80211_LINK_UNSPECIFIED ;continue ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 102/957 wifi: mt76: mt7996: use correct link_id when filling TXD and TXP
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shayne Chen <[email protected]>
[ Upstream commit 85cd5534a3f2ec93e7d88713a77df5b4255520df ]
Obtain the correct link ID and, if needed, switch to the corresponding wcid before populating the TX descriptor and TX payload.
Rules for link id:
- For QoS data of MLD peers (excluding EAPOL), select the primary or secondary wcid based on whether the TID is odd or even to meet FW/HW requirements
- For other packets, use IEEE80211_TX_CTRL_MLO_LINK if specified (such as multicast and broadcast packets)
Stable-dep-of: e648051d52af ("wifi: mt76: mt7996: Decrement sta counter removing the link in mt7996_mac_reset_sta_iter()")
--- .../net/wireless/mediatek/mt76/mt7996/mac.c | 34 ++++++++++++++++--- .../net/wireless/mediatek/mt76/mt7996/main.c | 9 +++++ .../net/wireless/mediatek/mt76/mt7996/mcu.c | 4 +-- .../wireless/mediatek/mt76/mt7996/mt7996.h | 1 + 4 files changed, 42 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +30 -4
@@ -1040,15 +1040,20 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,struct ieee80211_sta *sta, struct mt76_tx_info *tx_info) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);struct ieee80211_tx_info *info =IEEE80211_SKB_CB (tx_info->skb);struct ieee80211_key_conf *key = info->control.hw_key;struct ieee80211_vif *vif = info->control.vif; +struct mt7996_vif *mvif = vif ? (struct mt7996_vif *)vif->drv_priv :NULL ; +struct mt7996_sta *msta = sta ? (struct mt7996_sta *)sta->drv_priv :NULL ; +struct mt76_vif_link *mlink =NULL ;struct mt76_txwi_cache *t;int id, i, pid, nbuf = tx_info->nbuf -1 ;bool is_8023 = info->flags &IEEE80211_TX_CTL_HW_80211_ENCAP ;__le32 *ptr = (__le32 *)txwi_ptr;u8 *txwi = (u8 *)txwi_ptr; +u8 link_id;if (unlikely (tx_info->skb->len <=ETH_HLEN ))return -EINVAL ;
@@ -1056,6 +1061,30 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,if (!wcid) wcid = &dev->mt76.global_wcid; +if ((is_8023 ||ieee80211_is_data_qos (hdr->frame_control)) && sta->mlo && +likely (tx_info->skb->protocol !=cpu_to_be16 (ETH_P_PAE ))) { +u8 tid = tx_info->skb->priority &IEEE80211_QOS_CTL_TID_MASK ; + + link_id = (tid %2 ) ? msta->seclink_id : msta->deflink_id; + }else { + link_id =u32_get_bits (info->control.flags, +IEEE80211_TX_CTRL_MLO_LINK ); + } + +if (link_id != wcid->link_id && link_id !=IEEE80211_LINK_UNSPECIFIED ) { +if (msta) { +struct mt7996_sta_link *msta_link = +rcu_dereference (msta->link[link_id]); + +if (msta_link) + wcid = &msta_link->wcid; + }else if (mvif) { + mlink =rcu_dereference (mvif->mt76.link[link_id]); +if (mlink && mlink->wcid) + wcid = mlink->wcid; + } + } + t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); t->skb = tx_info->skb;
@@ -1162,10 +1191,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,if (!is_8023 &&mt7996_tx_use_mgmt (dev, tx_info->skb)) txp->fw.flags |=cpu_to_le16 (MT_CT_INFO_MGMT_FRAME ); -if (vif) { -struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; -struct mt76_vif_link *mlink =NULL ; - +if (mvif) {if (wcid->offchannel) mlink =rcu_dereference (mvif->mt76.offchannel_link);if (!mlink)
drivers/net/wireless/mediatek/mt76/mt7996/main.c +9 -0
@@ -982,6 +982,7 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev, msta_link = &msta->deflink; msta->deflink_id = link_id; + msta->seclink_id = msta->deflink_id;for (i =0 ; i <ARRAY_SIZE (sta->txq); i++) {struct mt76_txq *mtxq;
@@ -996,6 +997,11 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev, msta_link =kzalloc (sizeof (*msta_link),GFP_KERNEL );if (!msta_link)return -ENOMEM ; + +if (msta->seclink_id == msta->deflink_id && + (sta->valid_links & ~BIT (msta->deflink_id))) + msta->seclink_id =__ffs (sta->valid_links & + ~BIT (msta->deflink_id)); }INIT_LIST_HEAD (&msta_link->rc_list);
@@ -1065,6 +1071,8 @@ mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,if (msta->deflink_id == link_id) { msta->deflink_id =IEEE80211_LINK_UNSPECIFIED ;continue ; + }else if (msta->seclink_id == link_id) { + msta->seclink_id =IEEE80211_LINK_UNSPECIFIED ; }kfree_rcu (msta_link, rcu_head);
@@ -1160,6 +1168,7 @@ mt7996_mac_sta_add(struct mt7996_dev *dev, struct ieee80211_vif *vif,mutex_lock (&dev->mt76.mutex); msta->deflink_id =IEEE80211_LINK_UNSPECIFIED ; + msta->seclink_id =IEEE80211_LINK_UNSPECIFIED ; msta->vif = mvif; err =mt7996_mac_sta_add_links (dev, vif, sta, links);
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +2 -2
@@ -2399,8 +2399,8 @@ mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb, mld_setup->primary_id =cpu_to_le16 (msta_link->wcid.idx);if (nlinks >1 ) { - link_id =__ffs (sta->valid_links & ~BIT (msta->deflink_id)); - msta_link =mt76_dereference (msta->link[link_id], &dev->mt76); + msta_link =mt76_dereference (msta->link[msta->seclink_id], + &dev->mt76);if (!msta_link)return ; }
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +1 -0
@@ -243,6 +243,7 @@ struct mt7996_sta {struct mt7996_sta_link deflink;/* must be first */ struct mt7996_sta_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS ];u8 deflink_id; +u8 seclink_id;struct mt7996_vif *vif; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 103/957 wifi: mt76: mt7996: Switch to the secondary link if the default one is removed
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 5ef44c200618430b004233cbfc1b0929a13d5ac8 ]
Switch to the secondary link if available in mt7996_mac_sta_remove_links routine if the primary one is removed.
Moreover reset secondary link index for single link scenario.
Stable-dep-of: e648051d52af ("wifi: mt76: mt7996: Decrement sta counter removing the link in mt7996_mac_reset_sta_iter()")
--- .../net/wireless/mediatek/mt76/mt7996/mac.c | 12 ++--- .../net/wireless/mediatek/mt76/mt7996/main.c | 51 +++++++++++++------ 2 files changed, 41 insertions(+), 22 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +5 -7
@@ -2406,14 +2406,12 @@ mt7996_mac_reset_sta_iter(void *data, struct ieee80211_sta *sta)continue ;mt7996_mac_sta_deinit_link (dev, msta_link); - -if (msta->deflink_id == i) { - msta->deflink_id =IEEE80211_LINK_UNSPECIFIED ; -continue ; - } - -kfree_rcu (msta_link, rcu_head); +if (msta_link != &msta->deflink) +kfree_rcu (msta_link, rcu_head); } + + msta->deflink_id =IEEE80211_LINK_UNSPECIFIED ; + msta->seclink_id = msta->deflink_id; } static void
drivers/net/wireless/mediatek/mt76/mt7996/main.c +36 -15
75 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 104/957 wifi: mt76: mt7996: Decrement sta counter removing the link in mt7996_mac_reset_sta_iter()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit e648051d52afbdb360bd586218961f5fffff63e8 ]
Fixes tracking per-phy stations for offchannel switching.
--- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +5 -0
@@ -2399,6 +2399,7 @@ mt7996_mac_reset_sta_iter(void *data, struct ieee80211_sta *sta)for (i =0 ; i <ARRAY_SIZE (msta->link); i++) {struct mt7996_sta_link *msta_link =NULL ; +struct mt7996_phy *phy; msta_link =rcu_replace_pointer (msta->link[i], msta_link,lockdep_is_held (&dev->mt76.mutex));
@@ -2406,6 +2407,10 @@ mt7996_mac_reset_sta_iter(void *data, struct ieee80211_sta *sta)continue ;mt7996_mac_sta_deinit_link (dev, msta_link); + phy =__mt7996_phy (dev, msta_link->wcid.phy_idx); +if (phy) + phy->mt76->num_sta--; +if (msta_link != &msta->deflink)kfree_rcu (msta_link, rcu_head); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 105/957 wifi: mt76: fix multi-radio on-channel scanning
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chad Monroe <[email protected]>
[ Upstream commit 0420180df092419a96351fb2afec1e2a74d385c3 ]
avoid unnecessary channel switch when performing an on-channel scan using a multi-radio device.
--- drivers/net/wireless/mediatek/mt76/scan.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/scan.c +12 -5
@@ -16,7 +16,7 @@ static void mt76_scan_complete(struct mt76_dev *dev, bool abort)clear_bit (MT76_SCANNING , &phy->state); -if (dev->scan.chan && phy->main_chandef.chan && +if (dev->scan.chan && phy->main_chandef.chan && phy->offchannel && !test_bit (MT76_MCU_RESET , &dev->phy.state))mt76_set_channel (phy, &phy->main_chandef, false);mt76_put_vif_phy_link (phy, dev->scan.vif, dev->scan.mlink);
@@ -85,6 +85,7 @@ void mt76_scan_work(struct work_struct *work)struct cfg80211_chan_def chandef = {};struct mt76_phy *phy = dev->scan.phy;int duration =HZ /9 ;/* ~110 ms */ +bool offchannel = true;int i;if (dev->scan.chan_idx >= req->n_channels) {
@@ -92,7 +93,7 @@ void mt76_scan_work(struct work_struct *work)return ; } -if (dev->scan.chan && phy->num_sta) { +if (dev->scan.chan && phy->num_sta && phy->offchannel) { dev->scan.chan =NULL ;mt76_set_channel (phy, &phy->main_chandef, false); goto out;
@@ -100,20 +101,26 @@ void mt76_scan_work(struct work_struct *work) dev->scan.chan = req->channels[dev->scan.chan_idx++];cfg80211_chandef_create (&chandef, dev->scan.chan,NL80211_CHAN_HT20 ); -mt76_set_channel (phy, &chandef, true); +if (phy->main_chandef.chan == dev->scan.chan) { + chandef = phy->main_chandef; + offchannel = false; + } + +mt76_set_channel (phy, &chandef, offchannel);if (!req->n_ssids || chandef.chan->flags & (IEEE80211_CHAN_NO_IR |IEEE80211_CHAN_RADAR )) goto out; - duration =HZ /16 ;/* ~60 ms */ +if (phy->offchannel) + duration =HZ /16 ;/* ~60 ms */ local_bh_disable ();for (i =0 ; i < req->n_ssids; i++)mt76_scan_send_probe (dev, &req->ssids[i]);local_bh_enable (); out: -if (dev->scan.chan) +if (dev->scan.chan && phy->offchannel) duration =max_t (int, duration,msecs_to_jiffies (req->duration + (req->duration >>5 )));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 106/957 wifi: mt76: support upgrading passive scans to active
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chad Monroe <[email protected]>
[ Upstream commit 360552c8592dab3c69e0bbff786b55137f1a81bb ]
On channels with NO_IR or RADAR flags, wait for beacon before sending probe requests. Allows active scanning and WPS on restricted channels if another AP is already present.
--- drivers/net/wireless/mediatek/mt76/mac80211.c | 1 + drivers/net/wireless/mediatek/mt76/mt76.h | 4 ++ .../net/wireless/mediatek/mt76/mt7996/mac.c | 3 ++ drivers/net/wireless/mediatek/mt76/scan.c | 51 +++++++++++++++++-- 4 files changed, 56 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mac80211.c +1 -0
@@ -724,6 +724,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,INIT_LIST_HEAD (&dev->rxwi_cache); dev->token_size = dev->drv->token_size;INIT_DELAYED_WORK (&dev->scan_work, mt76_scan_work); +spin_lock_init (&dev->scan_lock);for (i =0 ; i <ARRAY_SIZE (dev->q_rx); i++)skb_queue_head_init (&dev->rx_skb[i]);
drivers/net/wireless/mediatek/mt76/mt76.h +4 -0
@@ -985,6 +985,7 @@ struct mt76_dev {u32 rxfilter;struct delayed_work scan_work; +spinlock_t scan_lock;struct {struct cfg80211_scan_request *req;struct ieee80211_channel *chan;
@@ -992,6 +993,8 @@ struct mt76_dev {struct mt76_vif_link *mlink;struct mt76_phy *phy;int chan_idx; +bool beacon_wait; +bool beacon_received; } scan;#ifdef CONFIG_NL80211_TESTMODE
@@ -1571,6 +1574,7 @@ int mt76_get_rate(struct mt76_dev *dev,int mt76_hw_scan (struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_scan_request *hw_req);void mt76_cancel_hw_scan (struct ieee80211_hw *hw,struct ieee80211_vif *vif); +void mt76_scan_rx_beacon (struct mt76_dev *dev,struct ieee80211_channel *chan);void mt76_sw_scan (struct ieee80211_hw *hw,struct ieee80211_vif *vif,const u8 *mac); void mt76_sw_scan_complete(struct ieee80211_hw *hw,
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +3 -0
@@ -554,6 +554,9 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q, qos_ctl =FIELD_GET (MT_RXD10_QOS_CTL , v2); seq_ctrl =FIELD_GET (MT_RXD10_SEQ_CTRL , v2); +if (ieee80211_is_beacon (fc)) +mt76_scan_rx_beacon (&dev->mt76, mphy->chandef.chan); + rxd +=4 ;if ((u8 *)rxd - skb->data >= skb->len)return -EINVAL ;
drivers/net/wireless/mediatek/mt76/scan.c +48 -3
79 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 107/957 wifi: mt76: mt7996: fix RRO EMU configuration
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Chiu <[email protected]>
[ Upstream commit 73b46379e5231138025b271ce8e158d2a8aa0768 ]
Use the correct helper to update specific bitfields instead of overwriting the entire register.
--- drivers/net/wireless/mediatek/mt76/mt7996/init.c | 3 +-- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/init.c +1 -2
@@ -857,8 +857,7 @@ void mt7996_rro_hw_init(struct mt7996_dev *dev) } }else {/* set emul 3.0 function */ -mt76_wr (dev,MT_RRO_3_0_EMU_CONF , -MT_RRO_3_0_EMU_CONF_EN_MASK ); +mt76_set (dev,MT_RRO_3_0_EMU_CONF ,MT_RRO_3_0_EMU_CONF_EN_MASK );mt76_wr (dev,MT_RRO_ADDR_ARRAY_BASE0 , dev->wed_rro.addr_elem[0 ].phy_addr);
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +1 -1
@@ -2597,7 +2597,7 @@ void mt7996_mac_reset_work(struct work_struct *work)mt7996_dma_start (dev, false, false);if (!is_mt7996 (&dev->mt76) && dev->mt76.hwrro_mode ==MT76_HWRRO_V3 ) -mt76_wr (dev,MT_RRO_3_0_EMU_CONF ,MT_RRO_3_0_EMU_CONF_EN_MASK ); +mt76_set (dev,MT_RRO_3_0_EMU_CONF ,MT_RRO_3_0_EMU_CONF_EN_MASK );if (mtk_wed_device_active (&dev->mt76.mmio.wed)) { u32 wed_irq_mask = MT_INT_TX_DONE_BAND2 |
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 108/957 bpf: Fix refcount check in check_struct_ops_btf_id()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Keisuke Nishimura <[email protected]>
[ Upstream commit 25e3e1f1096089a64901ae1faa7b7b13446653db ]
The current implementation only checks whether the first argument is refcounted. Fix this by iterating over all arguments.
--- kernel/bpf/verifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/verifier.c +1 -1
@@ -23687,7 +23687,7 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env) }for (i =0 ; i < st_ops_desc->arg_info[member_idx].cnt; i++) { -if (st_ops_desc->arg_info[member_idx].info->refcounted) { +if (st_ops_desc->arg_info[member_idx].info[i].refcounted) { has_refcounted_arg = true;break ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 109/957 bpf: Use RCU-safe iteration in dev_map_redirect_multi() SKB path
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Carlier <[email protected]>
[ Upstream commit 8ed82f807bb09d2c8455aaa665f2c6cb17bc6a19 ]
The DEVMAP_HASH branch in dev_map_redirect_multi() uses hlist_for_each_entry_safe() to iterate hash buckets, but this function runs under RCU protection (called from xdp_do_generic_redirect_map() in softirq context). Concurrent writers (__dev_map_hash_update_elem, dev_map_hash_delete_elem) modify the list using RCU primitives (hlist_add_head_rcu, hlist_del_rcu).
hlist_for_each_entry_safe() performs plain pointer dereferences without rcu_dereference(), missing the acquire barrier needed to pair with writers' rcu_assign_pointer(). On weakly-ordered architectures (ARM64, POWER), a reader can observe a partially-constructed node. It also defeats CONFIG_PROVE_RCU lockdep validation and KCSAN data-race detection.
Replace with hlist_for_each_entry_rcu() using rcu_read_lock_bh_held() as the lockdep condition, consistent with the rcu_dereference_check() used in the DEVMAP (non-hash) branch of the same functions. Also fix the same incorrect lockdep_is_held(&dtab->index_lock) condition in dev_map_enqueue_multi(), where the lock is not held either.
--- kernel/bpf/devmap.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/bpf/devmap.c +2 -3
@@ -665,7 +665,7 @@ int dev_map_enqueue_multi(struct xdp_frame *xdpf, struct net_device *dev_rx,for (i =0 ; i < dtab->n_buckets; i++) { head =dev_map_index_hash (dtab, i);hlist_for_each_entry_rcu (dst, head, index_hlist, -lockdep_is_held (&dtab->index_lock)) { +rcu_read_lock_bh_held ()) {if (!is_valid_dst (dst, xdpf))continue ;
@@ -747,7 +747,6 @@ int dev_map_redirect_multi(struct net_device *dev, struct sk_buff *skb,struct bpf_dtab_netdev *dst, *last_dst =NULL ;int excluded_devices[1 +MAX_NEST_DEV ];struct hlist_head *head; -struct hlist_node *next;int num_excluded =0 ;unsigned int i;int err;
@@ -787,7 +786,7 @@ int dev_map_redirect_multi(struct net_device *dev, struct sk_buff *skb, }else {/* BPF_MAP_TYPE_DEVMAP_HASH */ for (i =0 ; i < dtab->n_buckets; i++) { head =dev_map_index_hash (dtab, i); -hlist_for_each_entry_safe (dst, next, head, index_hlist) { +hlist_for_each_entry_rcu (dst, head, index_hlist,rcu_read_lock_bh_held ()) {if (is_ifindex_excluded (excluded_devices, num_excluded, dst->dev->ifindex))continue ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 110/957 bpf: Fix variable length stack write over spilled pointers
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexei Starovoitov <[email protected]>
[ Upstream commit 4639eb9e30ab10c7935c7c19e872facf9a94713f ]
Scrub slots if variable-offset stack write goes over spilled pointers. Otherwise is_spilled_reg() may == true && spilled_ptr.type == NOT_INIT and valid program is rejected by check_stack_read_fixed_off() with obscure "invalid size of register fill" message.
--- kernel/bpf/verifier.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-)
kernel/bpf/verifier.c +20 -8
@@ -5095,6 +5095,18 @@ static void check_fastcall_stack_contract(struct bpf_verifier_env *env, } } +static void scrub_special_slot (struct bpf_func_state *state,int spi) +{ +int i; + +/* regular write of data into stack destroys any spilled ptr */ + state->stack[spi].spilled_ptr.type =NOT_INIT ; +/* Mark slots as STACK_MISC if they belonged to spilled ptr/dynptr/iter. */ +if (is_stack_slot_special (&state->stack[spi])) +for (i =0 ; i <BPF_REG_SIZE ; i++) +scrub_spilled_slot (&state->stack[spi].slot_type[i]); +} +/* check_stack_{read,write}_fixed_off functions track spill/fill of registers, * stack boundary and alignment are checked in check_mem_access() */
@@ -5192,12 +5204,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env, }else {u8 type =STACK_MISC ; -/* regular write of data into stack destroys any spilled ptr */ - state->stack[spi].spilled_ptr.type =NOT_INIT ; -/* Mark slots as STACK_MISC if they belonged to spilled ptr/dynptr/iter. */ -if (is_stack_slot_special (&state->stack[spi])) -for (i =0 ; i <BPF_REG_SIZE ; i++) -scrub_spilled_slot (&state->stack[spi].slot_type[i]); +scrub_special_slot (state, spi);/* when we zero initialize stack slots mark them as such */ if ((reg && register_is_null(reg)) ||
@@ -5321,8 +5328,13 @@ static int check_stack_write_var_off(struct bpf_verifier_env *env, } } -/* Erase all other spilled pointers. */ - state->stack[spi].spilled_ptr.type =NOT_INIT ; +/* +* Scrub slots if variable-offset stack write goes over spilled pointers. +* Otherwise is_spilled_reg() may == true && spilled_ptr.type == NOT_INIT +* and valid program is rejected by check_stack_read_fixed_off() +* with obscure "invalid size of register fill" message. +*/ +scrub_special_slot (state, spi);/* Update the slot type. */ new_type =STACK_MISC ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 111/957 bpf,arc_jit: Fix missing newline in pr_err messages
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: haoyu.lu <[email protected]>
[ Upstream commit b6b5e0ebd429d66ce37ae5af649a74ea1f041d92 ]
Add missing newline to pr_err messages in ARC JIT.
--- arch/arc/net/bpf_jit_arcv2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arc/net/bpf_jit_arcv2.c +4 -4
@@ -2427,7 +2427,7 @@ u8 arc_prologue(u8 *buf, u32 usage, u16 frame_size)#ifdef ARC_BPF_JIT_DEBUG if ((usage &BIT (ARC_R_FP )) && frame_size ==0 ) { -pr_err ("FP is being saved while there is no frame." ); +pr_err ("FP is being saved while there is no frame.\n" );BUG (); }#endif
@@ -2454,7 +2454,7 @@ u8 arc_epilogue(u8 *buf, u32 usage, u16 frame_size)#ifdef ARC_BPF_JIT_DEBUG if ((usage &BIT (ARC_R_FP )) && frame_size ==0 ) { -pr_err ("FP is being saved while there is no frame." ); +pr_err ("FP is being saved while there is no frame.\n" );BUG (); }#endif
@@ -2868,7 +2868,7 @@ u8 gen_jmp_64(u8 *buf, u8 rd, u8 rs, u8 cond, u32 curr_off, u32 targ_off)break ;default :#ifdef ARC_BPF_JIT_DEBUG -pr_err ("64-bit jump condition is not known." ); +pr_err ("64-bit jump condition is not known.\n" );BUG ();#endif }
@@ -2948,7 +2948,7 @@ u8 gen_jmp_32(u8 *buf, u8 rd, u8 rs, u8 cond, u32 curr_off, u32 targ_off)*/ if (cond >=ARC_CC_LAST ) {#ifdef ARC_BPF_JIT_DEBUG -pr_err ("32-bit jump condition is not known." ); +pr_err ("32-bit jump condition is not known.\n" );BUG ();#endif return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 112/957 wifi: rtw89: phy: fix uninitialized variable access in rtw89_phy_cfo_set_crystal_cap()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexey Velichayshiy <[email protected]>
[ Upstream commit 047cddf88c611e616d49a00311d4722e46286234 ]
In the rtw89_phy_cfo_set_crystal_cap() function, for chips other than RTL8852A/RTL8851B, the values read by rtw89_mac_read_xtal_si() are stored into the local variables sc_xi_val and sc_xo_val. If either read fails, these variables remain uninitialized, they are later used to update cfo->crystal_cap and in debug print statements. This can lead to undefined behavior.
Fix the issue by initializing sc_xi_val and sc_xo_val to zero, like is implemented in vendor driver.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/net/wireless/realtek/rtw89/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/realtek/rtw89/phy.c +1 -1
@@ -4499,7 +4499,7 @@ static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev, {struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;const struct rtw89_chip_info *chip = rtwdev->chip; -u8 sc_xi_val, sc_xo_val; +u8 sc_xi_val =0 , sc_xo_val =0 ;if (!force && cfo->crystal_cap == crystal_cap)return ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 113/957 vfio: refactor vfio_pci_mmap_huge_fault function
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ankit Agrawal <[email protected]>
[ Upstream commit 9b92bc7554b543dc00a0a0b62904a9ef2ad5c4b0 ]
Refactor vfio_pci_mmap_huge_fault to take out the implementation to map the VMA to the PTE/PMD/PUD as a separate function.
Export the new function to be used by nvgrace-gpu module.
Move the alignment check code to verify that pfn and VMA VA is aligned to the page order to the header file and make it inline.
No functional change is intended.
Stable-dep-of: 948b71aa81cd ("drivers/vfio_pci_core: Change PXD_ORDER check from switch case to if/else block")
--- drivers/vfio/pci/vfio_pci_core.c | 54 ++++++++++++++++---------------- include/linux/vfio_pci_core.h | 13 ++++++++ 2 files changed, 40 insertions(+), 27 deletions(-)
drivers/vfio/pci/vfio_pci_core.c +27 -27
@@ -1677,49 +1677,49 @@ static unsigned long vma_to_pfn(struct vm_area_struct *vma)return (pci_resource_start (vdev->pdev, index) >>PAGE_SHIFT ) + pgoff; } -static vm_fault_t vfio_pci_mmap_huge_fault (struct vm_fault *vmf, -unsigned int order) +vm_fault_t vfio_pci_vmf_insert_pfn (struct vfio_pci_core_device *vdev, +struct vm_fault *vmf, +unsigned long pfn, +unsigned int order) { -struct vm_area_struct *vma = vmf->vma; -struct vfio_pci_core_device *vdev = vma->vm_private_data; -unsigned long addr = vmf->address & ~((PAGE_SIZE << order) -1 ); -unsigned long pgoff = (addr - vma->vm_start) >>PAGE_SHIFT ; -unsigned long pfn =vma_to_pfn (vma) + pgoff; -vm_fault_t ret =VM_FAULT_SIGBUS ; - -if (order && (addr < vma->vm_start || - addr + (PAGE_SIZE << order) > vma->vm_end || - pfn & ((1 << order) -1 ))) { - ret =VM_FAULT_FALLBACK ; - goto out; - } - -down_read (&vdev->memory_lock); +lockdep_assert_held_read (&vdev->memory_lock);if (vdev->pm_runtime_engaged || !__vfio_pci_memory_enabled (vdev)) - goto out_unlock; +return VM_FAULT_SIGBUS ;switch (order) {case 0 : - ret =vmf_insert_pfn (vma, vmf->address, pfn); -break ; +return vmf_insert_pfn (vmf->vma, vmf->address, pfn);#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP case PMD_ORDER : - ret =vmf_insert_pfn_pmd (vmf, pfn, false); -break ; +return vmf_insert_pfn_pmd (vmf, pfn, false);#endif #ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP case PUD_ORDER : - ret =vmf_insert_pfn_pud (vmf, pfn, false); +return vmf_insert_pfn_pud (vmf, pfn, false);break ;#endif default : - ret =VM_FAULT_FALLBACK ; +return VM_FAULT_FALLBACK ; + } +} +EXPORT_SYMBOL_GPL (vfio_pci_vmf_insert_pfn); + +static vm_fault_t vfio_pci_mmap_huge_fault (struct vm_fault *vmf, +unsigned int order) +{ +struct vm_area_struct *vma = vmf->vma; +struct vfio_pci_core_device *vdev = vma->vm_private_data; +unsigned long addr = vmf->address & ~((PAGE_SIZE << order) -1 ); +unsigned long pgoff = (addr - vma->vm_start) >>PAGE_SHIFT ; +unsigned long pfn =vma_to_pfn (vma) + pgoff; +vm_fault_t ret =VM_FAULT_FALLBACK ; + +if (is_aligned_for_order (vma, addr, pfn, order)) { +scoped_guard (rwsem_read, &vdev->memory_lock) + ret = vfio_pci_vmf_insert_pfn(vdev, vmf, pfn, order); } -out_unlock: -up_read (&vdev->memory_lock); -out: dev_dbg_ratelimited(&vdev->pdev->dev, "%s(,order = %d) BAR %ld page offset 0x%lx: 0x%x\n", __func__, order,
include/linux/vfio_pci_core.h +13 -0
@@ -132,6 +132,9 @@ ssize_t vfio_pci_core_read(struct vfio_device *core_vdev, char __user *buf, size_t count, loff_t *ppos);ssize_t vfio_pci_core_write (struct vfio_device *core_vdev,const char __user *buf,size_t count,loff_t *ppos); +vm_fault_t vfio_pci_vmf_insert_pfn (struct vfio_pci_core_device *vdev, +struct vm_fault *vmf,unsigned long pfn, +unsigned int order);int vfio_pci_core_mmap (struct vfio_device *core_vdev,struct vm_area_struct *vma);void vfio_pci_core_request (struct vfio_device *core_vdev,unsigned int count);int vfio_pci_core_match (struct vfio_device *core_vdev,char *buf);
@@ -175,4 +178,14 @@ VFIO_IOREAD_DECLARATION(32) VFIO_IOREAD_DECLARATION(64)#endif +static inline bool is_aligned_for_order (struct vm_area_struct *vma, +unsigned long addr, +unsigned long pfn, +unsigned int order) +{ +return !(order && (addr < vma->vm_start || + addr + (PAGE_SIZE << order) > vma->vm_end || + !IS_ALIGNED (pfn,1 << order))); +} +#endif /* VFIO_PCI_CORE_H */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 114/957 drivers/vfio_pci_core: Change PXD_ORDER check from switch case to if/else block
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ritesh Harjani (IBM) <[email protected]>
[ Upstream commit 948b71aa81cd89b222942db6055e8d9c51c54e78 ]
Architectures like PowerPC uses runtime defined values for PMD_ORDER/PUD_ORDER. This is because it can use either RADIX or HASH MMU at runtime using kernel cmdline. So the pXd_index_size is not known at compile time. Without this fix, when we add huge pfn support on powerpc in the next patch, vfio_pci_core driver compilation can fail with the following errors.
CC [M] drivers/vfio/vfio_main.o
CC [M] drivers/vfio/group.o
CC [M] drivers/vfio/container.o
CC [M] drivers/vfio/virqfd.o
CC [M] drivers/vfio/vfio_iommu_spapr_tce.o
CC [M] drivers/vfio/pci/vfio_pci_core.o
CC [M] drivers/vfio/pci/vfio_pci_intrs.o
CC [M] drivers/vfio/pci/vfio_pci_rdwr.o
CC [M] drivers/vfio/pci/vfio_pci_config.o
CC [M] drivers/vfio/pci/vfio_pci.o
AR kernel/built-in.a
../drivers/vfio/pci/vfio_pci_core.c: In function ‘vfio_pci_vmf_insert_pfn’:
../drivers/vfio/pci/vfio_pci_core.c:1678:9: error: case label does not reduce to an integer constant
1678 | case PMD_ORDER:
| ^~~~
../drivers/vfio/pci/vfio_pci_core.c:1682:9: error: case label does not reduce to an integer constant
1682 | case PUD_ORDER:
| ^~~~make[6]: *** [../scripts/Makefile.build:289: drivers/vfio/pci/vfio_pci_core.o] Error 1 make[6]: *** Waiting for unfinished jobs....
make[5]: *** [../scripts/Makefile.build:546: drivers/vfio/pci] Error 2 make[5]: *** Waiting for unfinished jobs....
make[4]: *** [../scripts/Makefile.build:546: drivers/vfio] Error 2 make[3]: *** [../scripts/Makefile.build:546: drivers] Error 2
--- drivers/vfio/pci/vfio_pci_core.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-)
drivers/vfio/pci/vfio_pci_core.c +7 -12
@@ -1687,21 +1687,16 @@ vm_fault_t vfio_pci_vmf_insert_pfn(struct vfio_pci_core_device *vdev,if (vdev->pm_runtime_engaged || !__vfio_pci_memory_enabled (vdev))return VM_FAULT_SIGBUS ; -switch (order) { -case 0 : +if (!order)return vmf_insert_pfn (vmf->vma, vmf->address, pfn); -#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP -case PMD_ORDER : + +if (IS_ENABLED (CONFIG_ARCH_SUPPORTS_PMD_PFNMAP ) && order ==PMD_ORDER )return vmf_insert_pfn_pmd (vmf, pfn, false); -#endif -#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP -case PUD_ORDER : + +if (IS_ENABLED (CONFIG_ARCH_SUPPORTS_PUD_PFNMAP ) && order ==PUD_ORDER )return vmf_insert_pfn_pud (vmf, pfn, false); -break ; -#endif -default : -return VM_FAULT_FALLBACK ; - } + +return VM_FAULT_FALLBACK ; }EXPORT_SYMBOL_GPL (vfio_pci_vmf_insert_pfn);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 115/957 r8152: fix incorrect register write to USB_UPHY_XTAL
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chih Kai Hsu <[email protected]>
[ Upstream commit 48afd5124fd6129c46fd12cb06155384b1c4a0c4 ]
The old code used ocp_write_byte() to clear the OOBS_POLLING bit (BIT(8)) in the USB_UPHY_XTAL register, but this doesn't correctly clear a bit in the upper byte of the 16-bit register.
Fix this by using ocp_write_word() instead.
--- drivers/net/usb/r8152.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/usb/r8152.c +1 -1
@@ -3896,7 +3896,7 @@ static void r8156_ups_en(struct r8152 *tp, bool enable)case RTL_VER_15 : ocp_data =ocp_read_word (tp,MCU_TYPE_USB ,USB_UPHY_XTAL ); ocp_data &= ~OOBS_POLLING ; -ocp_write_byte (tp,MCU_TYPE_USB ,USB_UPHY_XTAL , ocp_data); +ocp_write_word (tp,MCU_TYPE_USB ,USB_UPHY_XTAL , ocp_data);break ;default :break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 116/957 powerpc/crash: fix backup region offset update to elfcorehdr
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sourabh Jain <[email protected]>
[ Upstream commit 789335cacdf37da93bb7c70322dff8c7e82881df ]
update_backup_region_phdr() in file_load_64.c iterates over all the program headers in the kdump kernel’s elfcorehdr and updates the p_offset of the program header whose physical address starts at 0.
However, the loop logic is incorrect because the program header pointer is not updated during iteration. Since elfcorehdr typically contains PT_NOTE entries first, the PT_LOAD program header with physical address 0 is never reached. As a result, its p_offset is not updated to point to the backup region.
Because of this behavior, the capture kernel exports the first 64 KB of the crashed kernel’s memory at offset 0, even though that memory actually lives in the backup region. When a crash happens, purgatory copies the first 64 KB of the crashed kernel’s memory into the backup region so the capture kernel can safely use it.
This has not caused problems so far because the first 64 KB is usually identical in both the crashed and capture kernels. However, this is just an assumption and is not guaranteed to always hold true.
Fix update_backup_region_phdr() to correctly update the p_offset of the program header with a starting physical address of 0 by correcting the logic used to iterate over the program headers.
--- arch/powerpc/kexec/file_load_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kexec/file_load_64.c +1 -1
@@ -391,7 +391,7 @@ static void update_backup_region_phdr(struct kimage *image, Elf64_Ehdr *ehdr)unsigned int i; phdr = (Elf64_Phdr *)(ehdr +1 ); -for (i =0 ; i < ehdr->e_phnum; i++) { +for (i =0 ; i < ehdr->e_phnum; i++, phdr++) {if (phdr->p_paddr ==BACKUP_SRC_START ) { phdr->p_offset = image->arch.backup_start; kexec_dprintk("Backup region offset updated to 0x%lx\n",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 117/957 powerpc/crash: Update backup region offset in elfcorehdr on memory hotplug
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sourabh Jain <[email protected]>
[ Upstream commit f53b24d1fa263f56155213eabab734c18d884aff ]
When elfcorehdr is prepared for kdump, the program header representing the first 64 KB of memory is expected to have its offset point to the backup region. This is required because purgatory copies the first 64 KB of the crashed kernel memory to this backup region following a kernel crash. This allows the capture kernel to use the first 64 KB of memory to place the exception vectors and other required data.
When elfcorehdr is recreated due to memory hotplug, the offset of the program header representing the first 64 KB is not updated. As a result, the capture kernel exports the first 64 KB at offset 0, even though the data actually resides in the backup region.
Fix this by calling sync_backup_region_phdr() to update the program header offset in the elfcorehdr created during memory hotplug.
sync_backup_region_phdr() works for images loaded via the kexec_file_load syscall. However, it does not work for kexec_load, because image->arch.backup_start is not initialized in that case. So introduce machine_kexec_post_load() to process the elfcorehdr prepared by kexec-tools and initialize image->arch.backup_start for kdump images loaded via kexec_load syscall.
Rename update_backup_region_phdr() to sync_backup_region_phdr() and extend it to synchronize the backup region offset between the kdump image and the ELF core header. The helper now supports updating either the kdump image from the ELF program header or updating the ELF program header from the kdump image, avoiding code duplication.
Define ARCH_HAS_KIMAGE_ARCH and struct kimage_arch when CONFIG_KEXEC_FILE or CONFIG_CRASH_DUMP is enabled so that kimage->arch.backup_start is available with the kexec_load system call.
This patch depends on the patch titled "powerpc/crash: fix backup region offset update to elfcorehdr".
--- arch/powerpc/include/asm/kexec.h | 14 +++++-- arch/powerpc/kexec/crash.c | 64 +++++++++++++++++++++++++++++++ arch/powerpc/kexec/file_load_64.c | 29 +------------- 3 files changed, 76 insertions(+), 31 deletions(-)
arch/powerpc/include/asm/kexec.h +11 -3
@@ -66,11 +66,9 @@ void relocate_new_kernel(unsigned long indirection_page, unsigned long reboot_co unsigned long start_address) __noreturn;void kexec_copy_flush (struct kimage *image); -#ifdef CONFIG_KEXEC_FILE -extern const struct kexec_file_ops kexec_elf64_ops; +#if defined(CONFIG_KEXEC_FILE) || defined(CONFIG_CRASH_DUMP) #define ARCH_HAS_KIMAGE_ARCH - struct kimage_arch { struct crash_mem *exclude_ranges;
@@ -78,6 +76,10 @@ struct kimage_arch {void *backup_buf; void *fdt; }; +#endif + +#ifdef CONFIG_KEXEC_FILE +extern const struct kexec_file_ops kexec_elf64_ops;char *setup_kdump_cmdline (struct kimage *image,char *cmdline,unsigned long cmdline_len);
@@ -143,6 +145,10 @@ int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags);unsigned int arch_crash_get_elfcorehdr_size (void );#define crash_get_elfcorehdr_size arch_crash_get_elfcorehdr_size + +int machine_kexec_post_load (struct kimage *image); +#define machine_kexec_post_load machine_kexec_post_load +#endif /* CONFIG_CRASH_HOTPLUG */ extern int crashing_cpu;
@@ -157,6 +163,8 @@ extern void default_machine_crash_shutdown(struct pt_regs *regs);extern void crash_kexec_prepare (void );extern void crash_kexec_secondary (struct pt_regs *regs); +extern void sync_backup_region_phdr (struct kimage *image,Elf64_Ehdr *ehdr, +bool phdr_to_kimage);static inline bool kdump_in_progress (void ) {return crashing_cpu >=0 ;
arch/powerpc/kexec/crash.c +64 -0
83 lines not on this page · raw message
arch/powerpc/kexec/file_load_64.c +1 -28
@@ -374,33 +374,6 @@ static int load_backup_segment(struct kimage *image, struct kexec_buf *kbuf)return 0 ; } -/** -* update_backup_region_phdr - Update backup region's offset for the core to -* export the region appropriately. -* @image: Kexec image. -* @ehdr: ELF core header. -* -* Assumes an exclusive program header is setup for the backup region -* in the ELF headers -* -* Returns nothing. -*/ -static void update_backup_region_phdr (struct kimage *image,Elf64_Ehdr *ehdr) -{ -Elf64_Phdr *phdr; -unsigned int i; - - phdr = (Elf64_Phdr *)(ehdr +1 ); -for (i =0 ; i < ehdr->e_phnum; i++, phdr++) { -if (phdr->p_paddr ==BACKUP_SRC_START ) { - phdr->p_offset = image->arch.backup_start; -kexec_dprintk ("Backup region offset updated to 0x%lx\n" , - image->arch.backup_start); -return ; - } - } -} -static unsigned int kdump_extra_elfcorehdr_size (struct crash_mem *cmem) {#if defined(CONFIG_CRASH_HOTPLUG ) && defined(CONFIG_MEMORY_HOTPLUG )
@@ -445,7 +418,7 @@ static int load_elfcorehdr_segment(struct kimage *image, struct kexec_buf *kbuf) }/* Fix the offset for backup region in the ELF header */ -update_backup_region_phdr (image, headers); +sync_backup_region_phdr (image, headers, false); kbuf->buffer = headers; kbuf->mem =KEXEC_BUF_MEM_UNKNOWN ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 118/957 selftests/powerpc: Suppress -Wmaybe-uninitialized with GCC 15
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amit Machhiwal <[email protected]>
[ Upstream commit 6e65886fceb23605eff952d6b1975737b4c4b154 ]
GCC 15 reports the below false positive '-Wmaybe-uninitialized' warning in vphn_unpack_associativity() when building the powerpc selftests.
# make -C tools/testing/selftests TARGETS="powerpc"
[...]
CC test-vphn
In file included from test-vphn.c:3:
In function ‘vphn_unpack_associativity’,
inlined from ‘test_one’ at test-vphn.c:371:2,
inlined from ‘test_vphn’ at test-vphn.c:399:9:
test-vphn.c:10:33: error: ‘be_packed’ may be used uninitialized [-Werror=maybe-uninitialized]
10 | #define be16_to_cpup(x) bswap_16(*x)
| ^~~~~~~~
vphn.c:42:27: note: in expansion of macro ‘be16_to_cpup’
42 | u16 new = be16_to_cpup(field++);
| ^~~~~~~~~~~~
In file included from test-vphn.c:19:
vphn.c: In function ‘test_vphn’:
vphn.c:27:16: note: ‘be_packed’ declared here
27 | __be64 be_packed[VPHN_REGISTER_COUNT];
| ^~~~~~~~~
cc1: all warnings being treated as errorsWhen vphn_unpack_associativity() is called from hcall_vphn() in kernel the error is not seen while building vphn.c during kernel compilation. This is because the top level Makefile includes '-fno-strict-aliasing' flag always.
The issue here is that GCC 15 emits '-Wmaybe-uninitialized' due to type punning between __be64[] and __b16* when accessing the buffer via be16_to_cpup(). The underlying object is fully initialized but GCC 15 fails to track the aliasing due to the strict aliasing violation here. Please refer [1] and [2]. This results in a false positive warning which is promoted to an error under '-Werror'. This problem is not seen when the compilation is performed with GCC 13 and 14. An issue [1] has also been created on GCC bugzilla.
The selftest compiles fine with '-fno-strict-aliasing'. Since this GCC flag is used to compile vphn.c in kernel too, the same flag should be used to build vphn tests when compiling vphn.c in the selftest as well.
Fix this by including '-fno-strict-aliasing' during vphn.c compilation in the selftest. This keeps the build working while limiting the scope of the suppression to building vphn tests.
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124427
[2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99768
--- tools/testing/selftests/powerpc/vphn/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/powerpc/vphn/Makefile +1 -1
@@ -5,7 +5,7 @@ top_srcdir = ../../../../.. include ../../lib.mk include ../flags.mk -CFLAGS += -m64 -I$(CURDIR) +CFLAGS += -m64 -I$(CURDIR) -fno-strict-aliasing $(TEST_GEN_PROGS): ../harness.c
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 119/957 bpf: Fix abuse of kprobe_write_ctx via freplace
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Hwang <[email protected]>
[ Upstream commit 611fe4b79af72d00d80f2223354284447daafae9 ]
uprobe programs are allowed to modify struct pt_regs.
Since the actual program type of uprobe is KPROBE, it can be abused to modify struct pt_regs via kprobe+freplace when the kprobe attaches to kernel functions.
For example,
SEC("?kprobe")
int kprobe(struct pt_regs *regs)
{
return 0;
}SEC("?freplace")
int freplace_kprobe(struct pt_regs *regs)
{
regs->di = 0;
return 0;
}freplace_kprobe prog will attach to kprobe prog.
kprobe prog will attach to a kernel function.
Without this patch, when the kernel function runs, its first arg will always be set as 0 via the freplace_kprobe prog.
To fix the abuse of kprobe_write_ctx=true via kprobe+freplace, disallow attaching freplace programs on kprobe programs with different kprobe_write_ctx values.
--- kernel/bpf/syscall.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
kernel/bpf/syscall.c +17 -0
@@ -3708,6 +3708,23 @@ static int bpf_tracing_prog_attach(struct bpf_prog *prog, tr = prog->aux->dst_trampoline; tgt_prog = prog->aux->dst_prog; } +/* +* It is to prevent modifying struct pt_regs via kprobe_write_ctx=true +* freplace prog. Without this check, kprobe_write_ctx=true freplace +* prog is allowed to attach to kprobe_write_ctx=false kprobe prog, and +* then modify the registers of the kprobe prog's target kernel +* function. +* +* This also blocks the combination of uprobe+freplace, because it is +* unable to recognize the use of the tgt_prog as an uprobe or a kprobe +* by tgt_prog itself. At attach time, uprobe/kprobe is recognized by +* the target perf event flags in __perf_event_set_bpf_prog(). +*/ +if (prog->type ==BPF_PROG_TYPE_EXT && + prog->aux->kprobe_write_ctx != tgt_prog->aux->kprobe_write_ctx) { + err = -EINVAL ; + goto out_unlock; + } err =bpf_link_prime (&link->link.link, &link_primer);if (err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 120/957 macvlan: annotate data-races around port->bc_queue_len_used
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 1ef5789d9906df3771c99b7f413caaf2bf473ca5 ]
port->bc_queue_len_used is read and written locklessly, add READ_ONCE()/WRITE_ONCE() annotations.
While WRITE_ONCE() in macvlan_fill_info() is not yet needed, it is a prereq for future RTNL avoidance.
--- drivers/net/macvlan.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/net/macvlan.c +5 -3
@@ -352,6 +352,7 @@ static void macvlan_broadcast_enqueue(struct macvlan_port *port,const struct macvlan_dev *src, struct sk_buff *skb) { + u32 bc_queue_len_used = READ_ONCE(port->bc_queue_len_used);struct sk_buff *nskb;int err = -ENOMEM ;
@@ -362,7 +363,7 @@ static void macvlan_broadcast_enqueue(struct macvlan_port *port,MACVLAN_SKB_CB (nskb)->src = src;spin_lock (&port->bc_queue.lock); -if (skb_queue_len (&port->bc_queue) < port->bc_queue_len_used) { +if (skb_queue_len (&port->bc_queue) < bc_queue_len_used) {if (src)dev_hold (src->dev);__skb_queue_tail (&port->bc_queue, nskb);
@@ -1727,7 +1728,8 @@ static int macvlan_fill_info(struct sk_buff *skb, }if (nla_put_u32 (skb,IFLA_MACVLAN_BC_QUEUE_LEN , vlan->bc_queue_len_req)) goto nla_put_failure; -if (nla_put_u32 (skb,IFLA_MACVLAN_BC_QUEUE_LEN_USED , port->bc_queue_len_used)) +if (nla_put_u32 (skb,IFLA_MACVLAN_BC_QUEUE_LEN_USED , +READ_ONCE (port->bc_queue_len_used))) goto nla_put_failure;if (port->bc_cutoff !=1 &&nla_put_s32 (skb,IFLA_MACVLAN_BC_CUTOFF , port->bc_cutoff))
@@ -1787,7 +1789,7 @@ static void update_port_bc_queue_len(struct macvlan_port *port)if (vlan->bc_queue_len_req > max_bc_queue_len_req) max_bc_queue_len_req = vlan->bc_queue_len_req; } - port->bc_queue_len_used = max_bc_queue_len_req; +WRITE_ONCE (port->bc_queue_len_used, max_bc_queue_len_req); } static int macvlan_device_event(struct notifier_block *unused,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 121/957 bpf: fix end-of-list detection in cgroup_storage_get_next_key()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
[ Upstream commit 5828b9e5b272ecff7cf5d345128d3de7324117f7 ]
list_next_entry() never returns NULL -- when the current element is the last entry it wraps to the list head via container_of(). The subsequent NULL check is therefore dead code and get_next_key() never returns -ENOENT for the last element, instead reading storage->key from a bogus pointer that aliases internal map fields and copying the result to userspace.
Replace it with list_entry_is_head() so the function correctly returns -ENOENT when there are no more entries.
--- kernel/bpf/local_storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/local_storage.c +1 -1
@@ -259,7 +259,7 @@ static int cgroup_storage_get_next_key(struct bpf_map *_map, void *key, goto enoent; storage =list_next_entry (storage, list_map); -if (!storage) +if (list_entry_is_head (storage, &map->list, list_map)) goto enoent; }else { storage = list_first_entry(&map->list,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 122/957 bpf: Fix stale offload->prog pointer after constant blinding
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: MingTao Huang <[email protected]>
[ Upstream commit a1aa9ef47c299c5bbc30594d3c2f0589edf908e6 ]
When a dev-bound-only BPF program (BPF_F_XDP_DEV_BOUND_ONLY) undergoes JIT compilation with constant blinding enabled (bpf_jit_harden >= 2), bpf_jit_blind_constants() clones the program. The original prog is then freed in bpf_jit_prog_release_other(), which updates aux->prog to point to the surviving clone, but fails to update offload->prog.
This leaves offload->prog pointing to the freed original program. When the network namespace is subsequently destroyed, cleanup_net() triggers bpf_dev_bound_netdev_unregister(), which iterates ondev->progs and calls __bpf_prog_offload_destroy(offload->prog). Accessing the freed prog causes a page fault:
BUG: unable to handle page fault for address: ffffc900085f1038 Workqueue: netns cleanup_net RIP: 0010:__bpf_prog_offload_destroy+0xc/0x80 Call Trace: __bpf_offload_dev_netdev_unregister+0x257/0x350 bpf_dev_bound_netdev_unregister+0x4a/0x90 unregister_netdevice_many_notify+0x2a2/0x660
...cleanup_net+0x21a/0x320
The test sequence that triggers this reliably is:
1. Set net.core.bpf_jit_harden=2 (echo 2 > /proc/sys/net/core/bpf_jit_harden)
2. Run xdp_metadata selftest, which creates a dev-bound-only XDP program on a veth inside a netns (./test_progs -t xdp_metadata)
3. cleanup_net -> page fault in __bpf_prog_offload_destroy
Dev-bound-only programs are unique in that they have an offload structure but go through the normal JIT path instead of bpf_prog_offload_compile(). This means they are subject to constant blinding's prog clone-and-replace, while also having offload->prog that must stay in sync.
Fix this by updating offload->prog in bpf_jit_prog_release_other(), alongside the existing aux->prog update. Both are back-pointers to the prog that must be kept in sync when the prog is replaced.
--- kernel/bpf/core.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/bpf/core.c +2 -0
@@ -1468,6 +1468,8 @@ void bpf_jit_prog_release_other(struct bpf_prog *fp, struct bpf_prog *fp_other)* know whether fp here is the clone or the original. */ fp->aux->prog = fp; +if (fp->aux->offload) + fp->aux->offload->prog = fp;bpf_prog_clone_free (fp_other); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 123/957 net: ethernet: ti-cpsw:: rename soft_reset() function
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
[ Upstream commit 961f3c535608df64553f61d64ca086aa9f371bdd ]
While looking at the glob symbols shared between the cpsw drivers, I noticed that soft_reset() is the only one that is missing a proper namespace prefix, and will pollute the kernel namespace, so rename it to be consistent with the other symbols.
Stable-dep-of: df75bd552a87 ("net: ethernet: ti-cpsw: fix linking built-in code to modules")
--- drivers/net/ethernet/ti/cpsw.c | 2 +- drivers/net/ethernet/ti/cpsw_new.c | 2 +- drivers/net/ethernet/ti/cpsw_priv.c | 2 +- drivers/net/ethernet/ti/cpsw_priv.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-)
drivers/net/ethernet/ti/cpsw.c +1 -1
@@ -706,7 +706,7 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)struct cpsw_common *cpsw = priv->cpsw;/* soft reset the controller and initialize ale */ -soft_reset ("cpsw" , &cpsw->regs->soft_reset); +cpsw_soft_reset ("cpsw" , &cpsw->regs->soft_reset);cpsw_ale_start (cpsw->ale);/* switch to vlan aware mode */
drivers/net/ethernet/ti/cpsw_new.c +1 -1
@@ -573,7 +573,7 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)u32 control_reg;/* soft reset the controller and initialize ale */ -soft_reset ("cpsw" , &cpsw->regs->soft_reset); +cpsw_soft_reset ("cpsw" , &cpsw->regs->soft_reset);cpsw_ale_start (cpsw->ale);/* switch to vlan aware mode */
drivers/net/ethernet/ti/cpsw_priv.c +1 -1
@@ -275,7 +275,7 @@ void cpsw_set_slave_mac(struct cpsw_slave *slave, struct cpsw_priv *priv)slave_write (slave,mac_lo (priv->mac_addr),SA_LO ); } -void soft_reset (const char *module,void __iomem *reg) +void cpsw_soft_reset (const char *module,void __iomem *reg) {unsigned long timeout = jiffies +HZ ;
drivers/net/ethernet/ti/cpsw_priv.h +1 -1
@@ -458,7 +458,7 @@ int cpsw_tx_poll(struct napi_struct *napi_tx, int budget);int cpsw_rx_mq_poll (struct napi_struct *napi_rx,int budget);int cpsw_rx_poll (struct napi_struct *napi_rx,int budget);void cpsw_rx_vlan_encap (struct sk_buff *skb); -void soft_reset (const char *module,void __iomem *reg); +void cpsw_soft_reset (const char *module,void __iomem *reg);void cpsw_set_slave_mac (struct cpsw_slave *slave,struct cpsw_priv *priv);void cpsw_ndo_tx_timeout (struct net_device *ndev,unsigned int txqueue);int cpsw_need_resplit (struct cpsw_common *cpsw);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 124/957 net: ethernet: ti-cpsw: fix linking built-in code to modules
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
[ Upstream commit df75bd552a8790e83d4aeb5f112050cf3dc687bf ]
There are six variants of the cpsw driver, sharing various parts of the code: davinci-emac, cpsw, cpsw-switchdev, netcp, netcp_ethss and am65-cpsw-nuss.
I noticed that this means some files can be linked into more than one loadable module, or even part of vmlinux but also linked into a loadable module, both of which mess up assumptions of the build system, and causes warnings:
scripts/Makefile.build:279: cpsw_ale.o is added to multiple modules: ti-am65-cpsw-nuss ti_cpsw ti_cpsw_new scripts/Makefile.build:279: cpsw_priv.o is added to multiple modules: ti_cpsw ti_cpsw_new scripts/Makefile.build:279: cpsw_sl.o is added to multiple modules: ti-am65-cpsw-nuss ti_cpsw ti_cpsw_new scripts/Makefile.build:279: cpsw_ethtool.o is added to multiple modules: ti_cpsw ti_cpsw_new scripts/Makefile.build:279: davinci_cpdma.o is added to multiple modules: ti_cpsw ti_cpsw_new ti_davinci_emac
Change this back to having separate modules for each portion that can be linked standalone, exporting symbols as needed:
- ti-cpsw-common.ko now contains both cpsw-common.o and davinci_cpdma.o as they are always used together
- ti-cpsw-priv.ko contains cpsw_priv.o, cpsw_sl.o and cpsw_ethtool.o, which are the core of the cpsw and cpsw-new drivers.
- ti-cpsw-sl.ko contains the cpsw-sl.o object and is used on ti-am65-cpsw-nuss.ko in addition to the two other cpsw variants.
- ti-cpsw-ale.o is the one standalone module that is used by all except davinci_emac.
Each of these will be built-in if any of its users are built-in, otherwise it's a loadable module if there is at least one module using it. I did not bring back the separate Kconfig symbols for this, but just handle it using Makefile logic.
Note: ideally this is something that Kbuild complains about, but usually we just notice when something using THIS_MODULE misbehaves in a way that a user notices.
--- drivers/net/ethernet/ti/Makefile | 30 ++++++++++---------- drivers/net/ethernet/ti/cpsw_ale.c | 25 +++++++++++++++++ drivers/net/ethernet/ti/cpsw_ethtool.c | 24 ++++++++++++++++ drivers/net/ethernet/ti/cpsw_priv.c | 37 +++++++++++++++++++++++++ drivers/net/ethernet/ti/cpsw_sl.c | 11 ++++++++ drivers/net/ethernet/ti/davinci_cpdma.c | 27 ++++++++++++++++++ 6 files changed, 139 insertions(+), 15 deletions(-)
drivers/net/ethernet/ti/Makefile +15 -15
@@ -6,30 +6,30 @@ obj-$(CONFIG_TI_PRUETH) += icssm-prueth.o icssm-prueth-y := icssm/icssm_prueth.o -obj-$(CONFIG_TI_CPSW) += cpsw-common.o -obj-$(CONFIG_TI_DAVINCI_EMAC) += cpsw-common.o -obj-$(CONFIG_TI_CPSW_SWITCHDEV) += cpsw-common.o +ti-cpsw-common-y += cpsw-common.o davinci_cpdma.o +ti-cpsw-priv-y += cpsw_priv.o cpsw_ethtool.o +ti-cpsw-ale-y += cpsw_ale.o +ti-cpsw-sl-y += cpsw_sl.o obj-$(CONFIG_TLAN) += tlan.o -obj-$(CONFIG_TI_DAVINCI_EMAC) += ti_davinci_emac.o -ti_davinci_emac-y := davinci_emac.o davinci_cpdma.o +obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o ti-cpsw-common.o obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o obj-$(CONFIG_TI_CPSW_PHY_SEL) += cpsw-phy-sel.o obj-$(CONFIG_TI_CPTS) += cpts.o -obj-$(CONFIG_TI_CPSW) += ti_cpsw.o -ti_cpsw-y := cpsw.o davinci_cpdma.o cpsw_ale.o cpsw_priv.o cpsw_sl.o cpsw_ethtool.o -obj-$(CONFIG_TI_CPSW_SWITCHDEV) += ti_cpsw_new.o -ti_cpsw_new-y := cpsw_switchdev.o cpsw_new.o davinci_cpdma.o cpsw_ale.o cpsw_sl.o cpsw_priv.o cpsw_ethtool.o +obj-$(CONFIG_TI_CPSW) += ti_cpsw.o ti-cpsw-common.o ti-cpsw-priv.o ti-cpsw-ale.o ti-cpsw-sl.o +ti_cpsw-y := cpsw.o +obj-$(CONFIG_TI_CPSW_SWITCHDEV) += ti_cpsw_new.o ti-cpsw-common.o ti-cpsw-priv.o ti-cpsw-ale.o ti-cpsw-sl.o +ti_cpsw_new-y := cpsw_switchdev.o cpsw_new.o -obj-$(CONFIG_TI_KEYSTONE_NETCP) += keystone_netcp.o -keystone_netcp-y := netcp_core.o cpsw_ale.o -obj-$(CONFIG_TI_KEYSTONE_NETCP_ETHSS) += keystone_netcp_ethss.o -keystone_netcp_ethss-y := netcp_ethss.o netcp_sgmii.o netcp_xgbepcsr.o cpsw_ale.o +obj-$(CONFIG_TI_KEYSTONE_NETCP) += keystone_netcp.o ti-cpsw-ale.o +keystone_netcp-y := netcp_core.o +obj-$(CONFIG_TI_KEYSTONE_NETCP_ETHSS) += keystone_netcp_ethss.o ti-cpsw-ale.o +keystone_netcp_ethss-y := netcp_ethss.o netcp_sgmii.o netcp_xgbepcsr.o obj-$(CONFIG_TI_K3_CPPI_DESC_POOL) += k3-cppi-desc-pool.o -obj-$(CONFIG_TI_K3_AM65_CPSW_NUSS) += ti-am65-cpsw-nuss.o -ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o +obj-$(CONFIG_TI_K3_AM65_CPSW_NUSS) += ti-am65-cpsw-nuss.o ti-cpsw-sl.o ti-cpsw-ale.o +ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o am65-cpsw-ethtool.o ti-am65-cpsw-nuss-$(CONFIG_TI_AM65_CPSW_QOS) += am65-cpsw-qos.o ti-am65-cpsw-nuss-$(CONFIG_TI_K3_AM65_CPSW_SWITCHDEV) += am65-cpsw-switchdev.o obj-$(CONFIG_TI_K3_AM65_CPTS) += am65-cpts.o
drivers/net/ethernet/ti/cpsw_ale.c +25 -0
@@ -498,6 +498,7 @@ int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid) }return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_flush_multicast);static inline void cpsw_ale_set_vlan_entry_type (u32 *ale_entry,int flags,u16 vid)
@@ -535,6 +536,7 @@ int cpsw_ale_add_ucast(struct cpsw_ale *ale, const u8 *addr, int port,cpsw_ale_write (ale, idx, ale_entry);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_add_ucast);int cpsw_ale_del_ucast (struct cpsw_ale *ale,const u8 *addr,int port,int flags,u16 vid)
@@ -550,6 +552,7 @@ int cpsw_ale_del_ucast(struct cpsw_ale *ale, const u8 *addr, int port,cpsw_ale_write (ale, idx, ale_entry);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_del_ucast);int cpsw_ale_add_mcast (struct cpsw_ale *ale,const u8 *addr,int port_mask,int flags,u16 vid,int mcast_state)
@@ -583,6 +586,7 @@ int cpsw_ale_add_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,cpsw_ale_write (ale, idx, ale_entry);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_add_mcast);int cpsw_ale_del_mcast (struct cpsw_ale *ale,const u8 *addr,int port_mask,int flags,u16 vid)
@@ -612,6 +616,7 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,cpsw_ale_write (ale, idx, ale_entry);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_del_mcast);/* ALE NetCP NU switch specific vlan functions */ static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,
@@ -681,6 +686,7 @@ int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port_mask, int untag,cpsw_ale_write (ale, idx, ale_entry);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_add_vlan);static void cpsw_ale_vlan_del_modify_int (struct cpsw_ale *ale,u32 *ale_entry,u16 vid,int port_mask)
@@ -738,6 +744,7 @@ int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask)return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_vlan_del_modify);int cpsw_ale_del_vlan (struct cpsw_ale *ale,u16 vid,int port_mask) {
@@ -772,6 +779,7 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_del_vlan);int cpsw_ale_vlan_add_modify (struct cpsw_ale *ale,u16 vid,int port_mask,int untag_mask,int reg_mask,int unreg_mask)
@@ -811,6 +819,7 @@ int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,return ret; } +EXPORT_SYMBOL_GPL (cpsw_ale_vlan_add_modify);void cpsw_ale_set_unreg_mcast (struct cpsw_ale *ale,int unreg_mcast_mask,bool add)
@@ -838,6 +847,7 @@ void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,cpsw_ale_write (ale, idx, ale_entry); } } +EXPORT_SYMBOL_GPL (cpsw_ale_set_unreg_mcast);static void cpsw_ale_vlan_set_unreg_mcast (struct cpsw_ale *ale,u32 *ale_entry,int allmulti)
@@ -903,6 +913,7 @@ void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti, int port)cpsw_ale_write (ale, idx, ale_entry); } } +EXPORT_SYMBOL_GPL (cpsw_ale_set_allmulti);struct ale_control_info {const char *name;
@@ -1160,6 +1171,7 @@ int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_control_set);int cpsw_ale_control_get (struct cpsw_ale *ale,int port,int control) {
@@ -1183,6 +1195,7 @@ int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control) tmp =readl_relaxed (ale->params.ale_regs + offset) >> shift;return tmp &BITMASK (info->bits); } +EXPORT_SYMBOL_GPL (cpsw_ale_control_get);int cpsw_ale_rx_ratelimit_mc (struct cpsw_ale *ale,int port,unsigned int ratelimit_pps)
@@ -1205,6 +1218,7 @@ int cpsw_ale_rx_ratelimit_mc(struct cpsw_ale *ale, int port, unsigned int rateli port, val * ALE_RATE_LIMIT_MIN_PPS);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_rx_ratelimit_mc);int cpsw_ale_rx_ratelimit_bc (struct cpsw_ale *ale,int port,unsigned int ratelimit_pps)
@@ -1227,6 +1241,7 @@ int cpsw_ale_rx_ratelimit_bc(struct cpsw_ale *ale, int port, unsigned int rateli port, val * ALE_RATE_LIMIT_MIN_PPS);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_rx_ratelimit_bc);static void cpsw_ale_timer (struct timer_list *t) {
@@ -1316,6 +1331,7 @@ void cpsw_ale_start(struct cpsw_ale *ale)cpsw_ale_aging_start (ale); } +EXPORT_SYMBOL_GPL (cpsw_ale_start);void cpsw_ale_stop (struct cpsw_ale *ale) {
@@ -1323,6 +1339,7 @@ void cpsw_ale_stop(struct cpsw_ale *ale)cpsw_ale_control_set (ale,0 ,ALE_CLEAR ,1 );cpsw_ale_control_set (ale,0 ,ALE_ENABLE ,0 ); } +EXPORT_SYMBOL_GPL (cpsw_ale_stop);static const struct reg_field ale_fields_cpsw[] = {/* CPSW_ALE_IDVER_REG */
@@ -1623,6 +1640,7 @@ struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params)cpsw_ale_control_set (ale,0 ,ALE_CLEAR ,1 );return ale; } +EXPORT_SYMBOL_GPL (cpsw_ale_create);void cpsw_ale_dump (struct cpsw_ale *ale,u32 *data) {
@@ -1633,6 +1651,7 @@ void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data) data +=ALE_ENTRY_WORDS ; } } +EXPORT_SYMBOL_GPL (cpsw_ale_dump);void cpsw_ale_restore (struct cpsw_ale *ale,u32 *data) {
@@ -1643,11 +1662,13 @@ void cpsw_ale_restore(struct cpsw_ale *ale, u32 *data) data +=ALE_ENTRY_WORDS ; } } +EXPORT_SYMBOL_GPL (cpsw_ale_restore);u32 cpsw_ale_get_num_entries (struct cpsw_ale *ale) {return ale ? ale->params.ale_entries :0 ; } +EXPORT_SYMBOL_GPL (cpsw_ale_get_num_entries);/* Reads the specified policer index into ALE POLICER registers */ static void cpsw_ale_policer_read_idx (struct cpsw_ale *ale,u32 idx)
@@ -1750,3 +1771,7 @@ void cpsw_ale_classifier_setup_default(struct cpsw_ale *ale, int num_rx_ch) 1); } } +EXPORT_SYMBOL_GPL (cpsw_ale_classifier_setup_default); + +MODULE_LICENSE ("GPL" ); +MODULE_DESCRIPTION ("TI N-Port Ethernet Switch Address Lookup Engine" );
drivers/net/ethernet/ti/cpsw_ethtool.c +24 -0
@@ -144,6 +144,7 @@ u32 cpsw_get_msglevel(struct net_device *ndev)return priv->msg_enable; } +EXPORT_SYMBOL_GPL (cpsw_get_msglevel);void cpsw_set_msglevel (struct net_device *ndev,u32 value) {
@@ -151,6 +152,7 @@ void cpsw_set_msglevel(struct net_device *ndev, u32 value) priv->msg_enable = value; } +EXPORT_SYMBOL_GPL (cpsw_set_msglevel); int cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal, struct kernel_ethtool_coalesce *kernel_coal,
@@ -161,6 +163,7 @@ int cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal, coal->rx_coalesce_usecs = cpsw->coal_intvl;return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_get_coalesce); int cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal, struct kernel_ethtool_coalesce *kernel_coal,
@@ -220,6 +223,7 @@ int cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_set_coalesce);int cpsw_get_sset_count (struct net_device *ndev,int sset) {
@@ -234,6 +238,7 @@ int cpsw_get_sset_count(struct net_device *ndev, int sset)return -EOPNOTSUPP ; } } +EXPORT_SYMBOL_GPL (cpsw_get_sset_count);static void cpsw_add_ch_strings (u8 **p,int ch_num,int rx_dir) {
@@ -271,6 +276,7 @@ void cpsw_get_strings(struct net_device *ndev, u32 stringset, u8 *data)break ; } } +EXPORT_SYMBOL_GPL (cpsw_get_strings);void cpsw_get_ethtool_stats (struct net_device *ndev,struct ethtool_stats *stats,u64 *data)
@@ -303,6 +309,7 @@ void cpsw_get_ethtool_stats(struct net_device *ndev, } } } +EXPORT_SYMBOL_GPL (cpsw_get_ethtool_stats);void cpsw_get_pauseparam (struct net_device *ndev,struct ethtool_pauseparam *pause)
@@ -313,6 +320,7 @@ void cpsw_get_pauseparam(struct net_device *ndev, pause->rx_pause = priv->rx_pause ? true : false; pause->tx_pause = priv->tx_pause ? true : false; } +EXPORT_SYMBOL_GPL (cpsw_get_pauseparam);void cpsw_get_wol (struct net_device *ndev,struct ethtool_wolinfo *wol) {
@@ -326,6 +334,7 @@ void cpsw_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)if (cpsw->slaves[slave_no].phy)phy_ethtool_get_wol (cpsw->slaves[slave_no].phy, wol); } +EXPORT_SYMBOL_GPL (cpsw_get_wol);int cpsw_set_wol (struct net_device *ndev,struct ethtool_wolinfo *wol) {
@@ -338,6 +347,7 @@ int cpsw_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)else return -EOPNOTSUPP ; } +EXPORT_SYMBOL_GPL (cpsw_set_wol);int cpsw_get_regs_len (struct net_device *ndev) {
@@ -346,6 +356,7 @@ int cpsw_get_regs_len(struct net_device *ndev)return cpsw_ale_get_num_entries (cpsw->ale) *ALE_ENTRY_WORDS *sizeof (u32); } +EXPORT_SYMBOL_GPL (cpsw_get_regs_len);void cpsw_get_regs (struct net_device *ndev,struct ethtool_regs *regs,void *p) {
@@ -357,6 +368,7 @@ void cpsw_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *p)cpsw_ale_dump (cpsw->ale, reg); } +EXPORT_SYMBOL_GPL (cpsw_get_regs);int cpsw_ethtool_op_begin (struct net_device *ndev) {
@@ -370,6 +382,7 @@ int cpsw_ethtool_op_begin(struct net_device *ndev)return ret; } +EXPORT_SYMBOL_GPL (cpsw_ethtool_op_begin);void cpsw_ethtool_op_complete (struct net_device *ndev) {
@@ -380,6 +393,7 @@ void cpsw_ethtool_op_complete(struct net_device *ndev)if (ret <0 )cpsw_err (priv, drv,"ethtool complete failed %d\n" , ret); } +EXPORT_SYMBOL_GPL (cpsw_ethtool_op_complete);void cpsw_get_channels (struct net_device *ndev,struct ethtool_channels *ch) {
@@ -394,6 +408,7 @@ void cpsw_get_channels(struct net_device *ndev, struct ethtool_channels *ch) ch->tx_count = cpsw->tx_ch_num; ch->combined_count =0 ; } +EXPORT_SYMBOL_GPL (cpsw_get_channels);int cpsw_get_link_ksettings (struct net_device *ndev,struct ethtool_link_ksettings *ecmd)
@@ -408,6 +423,7 @@ int cpsw_get_link_ksettings(struct net_device *ndev,phy_ethtool_ksettings_get (cpsw->slaves[slave_no].phy, ecmd);return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_get_link_ksettings);int cpsw_set_link_ksettings (struct net_device *ndev,const struct ethtool_link_ksettings *ecmd)
@@ -421,6 +437,7 @@ int cpsw_set_link_ksettings(struct net_device *ndev,return phy_ethtool_ksettings_set (cpsw->slaves[slave_no].phy, ecmd); } +EXPORT_SYMBOL_GPL (cpsw_set_link_ksettings);int cpsw_get_eee (struct net_device *ndev,struct ethtool_keee *edata) {
@@ -433,6 +450,7 @@ int cpsw_get_eee(struct net_device *ndev, struct ethtool_keee *edata)else return -EOPNOTSUPP ; } +EXPORT_SYMBOL_GPL (cpsw_get_eee);int cpsw_nway_reset (struct net_device *ndev) {
@@ -445,6 +463,7 @@ int cpsw_nway_reset(struct net_device *ndev)else return -EOPNOTSUPP ; } +EXPORT_SYMBOL_GPL (cpsw_nway_reset);static void cpsw_suspend_data_pass (struct net_device *ndev) {
@@ -642,6 +661,7 @@ int cpsw_set_channels_common(struct net_device *ndev,cpsw_fail (cpsw);return ret; } +EXPORT_SYMBOL_GPL (cpsw_set_channels_common); void cpsw_get_ringparam(struct net_device *ndev, struct ethtool_ringparam *ering,
@@ -657,6 +677,7 @@ void cpsw_get_ringparam(struct net_device *ndev, ering->rx_max_pending = cpsw->descs_pool_size -CPSW_MAX_QUEUES ; ering->rx_pending =cpdma_get_num_rx_descs (cpsw->dma); } +EXPORT_SYMBOL_GPL (cpsw_get_ringparam); int cpsw_set_ringparam(struct net_device *ndev, struct ethtool_ringparam *ering,
@@ -703,6 +724,7 @@ int cpsw_set_ringparam(struct net_device *ndev,cpsw_fail (cpsw);return ret; } +EXPORT_SYMBOL_GPL (cpsw_set_ringparam);#if IS_ENABLED (CONFIG_TI_CPTS )int cpsw_get_ts_info (struct net_device *ndev,struct kernel_ethtool_ts_info *info)
@@ -723,6 +745,7 @@ int cpsw_get_ts_info(struct net_device *ndev, struct kernel_ethtool_ts_info *inf (1 <<HWTSTAMP_FILTER_PTP_V2_EVENT ); return 0; } +EXPORT_SYMBOL_GPL (cpsw_get_ts_info);#else int cpsw_get_ts_info (struct net_device *ndev,struct kernel_ethtool_ts_info *info) {
@@ -732,4 +755,5 @@ int cpsw_get_ts_info(struct net_device *ndev, struct kernel_ethtool_ts_info *inf info->rx_filters =0 ; return 0; } +EXPORT_SYMBOL_GPL (cpsw_get_ts_info);#endif
drivers/net/ethernet/ti/cpsw_priv.c +37 -0
@@ -32,6 +32,7 @@#define CPTS_N_ETX_TS 4int (*cpsw_slave_index)(struct cpsw_common *cpsw,struct cpsw_priv *priv); +EXPORT_SYMBOL_GPL (cpsw_slave_index);void cpsw_intr_enable (struct cpsw_common *cpsw) {
@@ -40,6 +41,7 @@ void cpsw_intr_enable(struct cpsw_common *cpsw)cpdma_ctlr_int_ctrl (cpsw->dma, true); } +EXPORT_SYMBOL_GPL (cpsw_intr_enable);void cpsw_intr_disable (struct cpsw_common *cpsw) {
@@ -48,6 +50,7 @@ void cpsw_intr_disable(struct cpsw_common *cpsw)cpdma_ctlr_int_ctrl (cpsw->dma, false); } +EXPORT_SYMBOL_GPL (cpsw_intr_disable);void cpsw_tx_handler (void *token,int len,int status) {
@@ -82,6 +85,7 @@ void cpsw_tx_handler(void *token, int len, int status) ndev->stats.tx_packets++; ndev->stats.tx_bytes += len; } +EXPORT_SYMBOL_GPL (cpsw_tx_handler);irqreturn_t cpsw_tx_interrupt (int irq,void *dev_id) {
@@ -98,6 +102,7 @@ irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)napi_schedule (&cpsw->napi_tx);return IRQ_HANDLED ; } +EXPORT_SYMBOL_GPL (cpsw_tx_interrupt);irqreturn_t cpsw_rx_interrupt (int irq,void *dev_id) {
@@ -114,6 +119,7 @@ irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)napi_schedule (&cpsw->napi_rx);return IRQ_HANDLED ; } +EXPORT_SYMBOL_GPL (cpsw_rx_interrupt);irqreturn_t cpsw_misc_interrupt (int irq,void *dev_id) {
@@ -126,6 +132,7 @@ irqreturn_t cpsw_misc_interrupt(int irq, void *dev_id)return IRQ_HANDLED ; } +EXPORT_SYMBOL_GPL (cpsw_misc_interrupt);int cpsw_tx_mq_poll (struct napi_struct *napi_tx,int budget) {
@@ -158,6 +165,7 @@ int cpsw_tx_mq_poll(struct napi_struct *napi_tx, int budget)return num_tx; } +EXPORT_SYMBOL_GPL (cpsw_tx_mq_poll);int cpsw_tx_poll (struct napi_struct *napi_tx,int budget) {
@@ -176,6 +184,7 @@ int cpsw_tx_poll(struct napi_struct *napi_tx, int budget)return num_tx; } +EXPORT_SYMBOL_GPL (cpsw_tx_poll);int cpsw_rx_mq_poll (struct napi_struct *napi_rx,int budget) {
@@ -208,6 +217,7 @@ int cpsw_rx_mq_poll(struct napi_struct *napi_rx, int budget)return num_rx; } +EXPORT_SYMBOL_GPL (cpsw_rx_mq_poll);int cpsw_rx_poll (struct napi_struct *napi_rx,int budget) {
@@ -226,6 +236,7 @@ int cpsw_rx_poll(struct napi_struct *napi_rx, int budget)return num_rx; } +EXPORT_SYMBOL_GPL (cpsw_rx_poll);void cpsw_rx_vlan_encap (struct sk_buff *skb) {
@@ -268,12 +279,14 @@ void cpsw_rx_vlan_encap(struct sk_buff *skb)skb_pull (skb,VLAN_HLEN ); } } +EXPORT_SYMBOL_GPL (cpsw_rx_vlan_encap);void cpsw_set_slave_mac (struct cpsw_slave *slave,struct cpsw_priv *priv) {slave_write (slave,mac_hi (priv->mac_addr),SA_HI );slave_write (slave,mac_lo (priv->mac_addr),SA_LO ); } +EXPORT_SYMBOL_GPL (cpsw_set_slave_mac);void cpsw_soft_reset (const char *module,void __iomem *reg) {
@@ -286,6 +299,7 @@ void cpsw_soft_reset(const char *module, void __iomem *reg)WARN (readl_relaxed (reg) &1 ,"failed to soft-reset %s\n" , module); } +EXPORT_SYMBOL_GPL (cpsw_soft_reset);void cpsw_ndo_tx_timeout (struct net_device *ndev,unsigned int txqueue) {
@@ -305,6 +319,7 @@ void cpsw_ndo_tx_timeout(struct net_device *ndev, unsigned int txqueue)netif_trans_update (ndev);netif_tx_wake_all_queues (ndev); } +EXPORT_SYMBOL_GPL (cpsw_ndo_tx_timeout);static int cpsw_get_common_speed (struct cpsw_common *cpsw) {
@@ -343,6 +358,7 @@ int cpsw_need_resplit(struct cpsw_common *cpsw)return 1 ; } +EXPORT_SYMBOL_GPL (cpsw_need_resplit);void cpsw_split_res (struct cpsw_common *cpsw) {
@@ -428,6 +444,7 @@ void cpsw_split_res(struct cpsw_common *cpsw)if (budget) cpsw->rxv[0 ].budget += budget; } +EXPORT_SYMBOL_GPL (cpsw_split_res); int cpsw_init_common(struct cpsw_common *cpsw, void __iomem *ss_regs, int ale_ageout, phys_addr_t desc_mem_phys,
@@ -548,6 +565,7 @@ int cpsw_init_common(struct cpsw_common *cpsw, void __iomem *ss_regs,return ret; } +EXPORT_SYMBOL_GPL (cpsw_init_common);#if IS_ENABLED (CONFIG_TI_CPTS )
@@ -678,6 +696,7 @@ int cpsw_hwtstamp_set(struct net_device *dev,return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_hwtstamp_set);int cpsw_hwtstamp_get (struct net_device *dev,struct kernel_hwtstamp_config *cfg)
@@ -695,12 +714,14 @@ int cpsw_hwtstamp_get(struct net_device *dev,return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_hwtstamp_get);#else int cpsw_hwtstamp_get (struct net_device *dev,struct kernel_hwtstamp_config *cfg) {return -EOPNOTSUPP ; } +EXPORT_SYMBOL_GPL (cpsw_hwtstamp_set); int cpsw_hwtstamp_set(struct net_device *dev, struct kernel_hwtstamp_config *cfg,
@@ -708,6 +729,7 @@ int cpsw_hwtstamp_set(struct net_device *dev, {return -EOPNOTSUPP ; } +EXPORT_SYMBOL_GPL (cpsw_hwtstamp_get);#endif /*CONFIG_TI_CPTS*/ int cpsw_ndo_set_tx_maxrate (struct net_device *ndev,int queue,u32 rate)
@@ -758,6 +780,7 @@ int cpsw_ndo_set_tx_maxrate(struct net_device *ndev, int queue, u32 rate)cpsw_split_res (cpsw);return ret; } +EXPORT_SYMBOL_GPL (cpsw_ndo_set_tx_maxrate);static int cpsw_tc_to_fifo (int tc,int num_tc) {
@@ -782,6 +805,7 @@ bool cpsw_shp_is_off(struct cpsw_priv *priv)return !val; } +EXPORT_SYMBOL_GPL (cpsw_shp_is_off);static void cpsw_fifo_shp_on (struct cpsw_priv *priv,int fifo,int on) {
@@ -1043,6 +1067,7 @@ int cpsw_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type,return -EOPNOTSUPP ; } } +EXPORT_SYMBOL_GPL (cpsw_ndo_setup_tc);void cpsw_cbs_resume (struct cpsw_slave *slave,struct cpsw_priv *priv) {
@@ -1056,6 +1081,7 @@ void cpsw_cbs_resume(struct cpsw_slave *slave, struct cpsw_priv *priv)cpsw_set_fifo_rlimit (priv, fifo, bw); } } +EXPORT_SYMBOL_GPL (cpsw_cbs_resume);void cpsw_mqprio_resume (struct cpsw_slave *slave,struct cpsw_priv *priv) {
@@ -1078,6 +1104,7 @@ void cpsw_mqprio_resume(struct cpsw_slave *slave, struct cpsw_priv *priv)slave_write (slave, tx_prio_map, tx_prio_rg); } +EXPORT_SYMBOL_GPL (cpsw_mqprio_resume);int cpsw_fill_rx_channels (struct cpsw_priv *priv) {
@@ -1123,6 +1150,7 @@ int cpsw_fill_rx_channels(struct cpsw_priv *priv)return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_fill_rx_channels);static struct page_pool *cpsw_create_page_pool (struct cpsw_common *cpsw,int size)
@@ -1208,6 +1236,7 @@ void cpsw_destroy_xdp_rxqs(struct cpsw_common *cpsw) cpsw->page_pool[ch] =NULL ; } } +EXPORT_SYMBOL_GPL (cpsw_destroy_xdp_rxqs);int cpsw_create_xdp_rxqs (struct cpsw_common *cpsw) {
@@ -1240,6 +1269,7 @@ int cpsw_create_xdp_rxqs(struct cpsw_common *cpsw)return ret; } +EXPORT_SYMBOL_GPL (cpsw_create_xdp_rxqs);static int cpsw_xdp_prog_setup (struct cpsw_priv *priv,struct netdev_bpf *bpf) {
@@ -1267,6 +1297,7 @@ int cpsw_ndo_bpf(struct net_device *ndev, struct netdev_bpf *bpf)return -EINVAL ; } } +EXPORT_SYMBOL_GPL (cpsw_ndo_bpf);int cpsw_xdp_tx_frame (struct cpsw_priv *priv,struct xdp_frame *xdpf,struct page *page,int port)
@@ -1300,6 +1331,7 @@ int cpsw_xdp_tx_frame(struct cpsw_priv *priv, struct xdp_frame *xdpf,return ret; } +EXPORT_SYMBOL_GPL (cpsw_xdp_tx_frame);int cpsw_run_xdp (struct cpsw_priv *priv,int ch,struct xdp_buff *xdp,struct page *page,int port,int *len)
@@ -1362,6 +1394,7 @@ int cpsw_run_xdp(struct cpsw_priv *priv, int ch, struct xdp_buff *xdp,page_pool_recycle_direct (cpsw->page_pool[ch], page);return ret; } +EXPORT_SYMBOL_GPL (cpsw_run_xdp); static int cpsw_qos_clsflower_add_policer(struct cpsw_priv *priv, struct netlink_ext_ack *extack,
@@ -1564,3 +1597,7 @@ void cpsw_qos_clsflower_resume(struct cpsw_priv *priv)cpsw_ale_rx_ratelimit_mc (priv->cpsw->ale, port_id, priv->ale_mc_ratelimit.rate_packet_ps); } +EXPORT_SYMBOL_GPL (cpsw_qos_clsflower_resume); + +MODULE_LICENSE ("GPL" ); +MODULE_DESCRIPTION ("TI CPSW Ethernet Switch Driver" );
drivers/net/ethernet/ti/cpsw_sl.c +11 -0
@@ -200,6 +200,7 @@ u32 cpsw_sl_reg_read(struct cpsw_sl *sl, enum cpsw_sl_regs reg)dev_dbg (sl->dev,"cpsw_sl: reg: %04X r 0x%08X\n" , sl->regs[reg], val);return val; } +EXPORT_SYMBOL_GPL (cpsw_sl_reg_read);void cpsw_sl_reg_write (struct cpsw_sl *sl,enum cpsw_sl_regs reg,u32 val) {
@@ -212,6 +213,7 @@ void cpsw_sl_reg_write(struct cpsw_sl *sl, enum cpsw_sl_regs reg, u32 val)dev_dbg (sl->dev,"cpsw_sl: reg: %04X w 0x%08X\n" , sl->regs[reg], val);writel (val, sl->sl_base + sl->regs[reg]); } +EXPORT_SYMBOL_GPL (cpsw_sl_reg_write); static const struct cpsw_sl_dev_id *cpsw_sl_match_id( const struct cpsw_sl_dev_id *id,
@@ -252,6 +254,7 @@ struct cpsw_sl *cpsw_sl_get(const char *device_id, struct device *dev,return sl; } +EXPORT_SYMBOL_GPL (cpsw_sl_get);void cpsw_sl_reset (struct cpsw_sl *sl,unsigned long tmo) {
@@ -270,6 +273,7 @@ void cpsw_sl_reset(struct cpsw_sl *sl, unsigned long tmo)if (cpsw_sl_reg_read (sl,CPSW_SL_SOFT_RESET ) &CPSW_SL_SOFT_RESET_BIT )dev_err (sl->dev,"cpsw_sl failed to soft-reset.\n" ); } +EXPORT_SYMBOL_GPL (cpsw_sl_reset);u32 cpsw_sl_ctl_set (struct cpsw_sl *sl,u32 ctl_funcs) {
@@ -287,6 +291,7 @@ u32 cpsw_sl_ctl_set(struct cpsw_sl *sl, u32 ctl_funcs)return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_sl_ctl_set);u32 cpsw_sl_ctl_clr (struct cpsw_sl *sl,u32 ctl_funcs) {
@@ -304,11 +309,13 @@ u32 cpsw_sl_ctl_clr(struct cpsw_sl *sl, u32 ctl_funcs)return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_sl_ctl_clr);void cpsw_sl_ctl_reset (struct cpsw_sl *sl) {cpsw_sl_reg_write (sl,CPSW_SL_MACCONTROL ,0 ); } +EXPORT_SYMBOL_GPL (cpsw_sl_ctl_reset);int cpsw_sl_wait_for_idle (struct cpsw_sl *sl,unsigned long tmo) {
@@ -326,3 +333,7 @@ int cpsw_sl_wait_for_idle(struct cpsw_sl *sl, unsigned long tmo)return 0 ; } +EXPORT_SYMBOL_GPL (cpsw_sl_wait_for_idle); + +MODULE_LICENSE ("GPL" ); +MODULE_DESCRIPTION ("TI Ethernet Switch media-access-controller (MAC) submodule" );
drivers/net/ethernet/ti/davinci_cpdma.c +27 -0
@@ -531,6 +531,7 @@ struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params) ctlr->num_chan =CPDMA_MAX_CHANNELS ;return ctlr; } +EXPORT_SYMBOL_GPL (cpdma_ctlr_create);int cpdma_ctlr_start (struct cpdma_ctlr *ctlr) {
@@ -591,6 +592,7 @@ int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)spin_unlock_irqrestore (&ctlr->lock, flags);return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_ctlr_start);int cpdma_ctlr_stop (struct cpdma_ctlr *ctlr) {
@@ -623,6 +625,7 @@ int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)spin_unlock_irqrestore (&ctlr->lock, flags);return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_ctlr_stop);int cpdma_ctlr_destroy (struct cpdma_ctlr *ctlr) {
@@ -640,6 +643,7 @@ int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)cpdma_desc_pool_destroy (ctlr);return ret; } +EXPORT_SYMBOL_GPL (cpdma_ctlr_destroy);int cpdma_ctlr_int_ctrl (struct cpdma_ctlr *ctlr,bool enable) {
@@ -660,21 +664,25 @@ int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)spin_unlock_irqrestore (&ctlr->lock, flags);return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_ctlr_int_ctrl);void cpdma_ctlr_eoi (struct cpdma_ctlr *ctlr,u32 value) {dma_reg_write (ctlr,CPDMA_MACEOIVECTOR , value); } +EXPORT_SYMBOL_GPL (cpdma_ctlr_eoi);u32 cpdma_ctrl_rxchs_state (struct cpdma_ctlr *ctlr) {return dma_reg_read (ctlr,CPDMA_RXINTSTATMASKED ); } +EXPORT_SYMBOL_GPL (cpdma_ctrl_rxchs_state);u32 cpdma_ctrl_txchs_state (struct cpdma_ctlr *ctlr) {return dma_reg_read (ctlr,CPDMA_TXINTSTATMASKED ); } +EXPORT_SYMBOL_GPL (cpdma_ctrl_txchs_state); static void cpdma_chan_set_descs(struct cpdma_ctlr *ctlr, int rx, int desc_num,
@@ -802,6 +810,7 @@ int cpdma_chan_set_weight(struct cpdma_chan *ch, int weight)spin_unlock_irqrestore (&ctlr->lock, flags);return ret; } +EXPORT_SYMBOL_GPL (cpdma_chan_set_weight);/* cpdma_chan_get_min_rate - get minimum allowed rate for channel * Should be called before cpdma_chan_set_rate.
@@ -816,6 +825,7 @@ u32 cpdma_chan_get_min_rate(struct cpdma_ctlr *ctlr)return DIV_ROUND_UP (divident, divisor); } +EXPORT_SYMBOL_GPL (cpdma_chan_get_min_rate);/* cpdma_chan_set_rate - limits bandwidth for transmit channel. * The bandwidth * limited channels have to be in order beginning from lowest.
@@ -860,6 +870,7 @@ int cpdma_chan_set_rate(struct cpdma_chan *ch, u32 rate)spin_unlock_irqrestore (&ctlr->lock, flags);return ret; } +EXPORT_SYMBOL_GPL (cpdma_chan_set_rate);u32 cpdma_chan_get_rate (struct cpdma_chan *ch) {
@@ -872,6 +883,7 @@ u32 cpdma_chan_get_rate(struct cpdma_chan *ch)return rate; } +EXPORT_SYMBOL_GPL (cpdma_chan_get_rate);struct cpdma_chan *cpdma_chan_create (struct cpdma_ctlr *ctlr,int chan_num,cpdma_handler_fn handler,int rx_type)
@@ -931,6 +943,7 @@ struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,spin_unlock_irqrestore (&ctlr->lock, flags);return chan; } +EXPORT_SYMBOL_GPL (cpdma_chan_create);int cpdma_chan_get_rx_buf_num (struct cpdma_chan *chan) {
@@ -943,6 +956,7 @@ int cpdma_chan_get_rx_buf_num(struct cpdma_chan *chan)return desc_num; } +EXPORT_SYMBOL_GPL (cpdma_chan_get_rx_buf_num);int cpdma_chan_destroy (struct cpdma_chan *chan) {
@@ -964,6 +978,7 @@ int cpdma_chan_destroy(struct cpdma_chan *chan)spin_unlock_irqrestore (&ctlr->lock, flags);return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_chan_destroy);int cpdma_chan_get_stats (struct cpdma_chan *chan,struct cpdma_chan_stats *stats)
@@ -976,6 +991,7 @@ int cpdma_chan_get_stats(struct cpdma_chan *chan,spin_unlock_irqrestore (&chan->lock, flags);return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_chan_get_stats);static void __cpdma_chan_submit (struct cpdma_chan *chan,struct cpdma_desc __iomem *desc)
@@ -1100,6 +1116,7 @@ int cpdma_chan_idle_submit(struct cpdma_chan *chan, void *token, void *data,spin_unlock_irqrestore (&chan->lock, flags);return ret; } +EXPORT_SYMBOL_GPL (cpdma_chan_idle_submit);int cpdma_chan_idle_submit_mapped (struct cpdma_chan *chan,void *token,dma_addr_t data,int len,int directed)
@@ -1125,6 +1142,7 @@ int cpdma_chan_idle_submit_mapped(struct cpdma_chan *chan, void *token,spin_unlock_irqrestore (&chan->lock, flags);return ret; } +EXPORT_SYMBOL_GPL (cpdma_chan_idle_submit_mapped);int cpdma_chan_submit (struct cpdma_chan *chan,void *token,void *data,int len,int directed)
@@ -1150,6 +1168,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,spin_unlock_irqrestore (&chan->lock, flags);return ret; } +EXPORT_SYMBOL_GPL (cpdma_chan_submit);int cpdma_chan_submit_mapped (struct cpdma_chan *chan,void *token,dma_addr_t data,int len,int directed)
@@ -1175,6 +1194,7 @@ int cpdma_chan_submit_mapped(struct cpdma_chan *chan, void *token,spin_unlock_irqrestore (&chan->lock, flags);return ret; } +EXPORT_SYMBOL_GPL (cpdma_chan_submit_mapped);bool cpdma_check_free_tx_desc (struct cpdma_chan *chan) {
@@ -1189,6 +1209,7 @@ bool cpdma_check_free_tx_desc(struct cpdma_chan *chan)spin_unlock_irqrestore (&chan->lock, flags);return free_tx_desc; } +EXPORT_SYMBOL_GPL (cpdma_check_free_tx_desc); static void __cpdma_chan_free(struct cpdma_chan *chan, struct cpdma_desc __iomem *desc,
@@ -1289,6 +1310,7 @@ int cpdma_chan_process(struct cpdma_chan *chan, int quota) }return used; } +EXPORT_SYMBOL_GPL (cpdma_chan_process);int cpdma_chan_start (struct cpdma_chan *chan) {
@@ -1308,6 +1330,7 @@ int cpdma_chan_start(struct cpdma_chan *chan)return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_chan_start);int cpdma_chan_stop (struct cpdma_chan *chan) {
@@ -1370,6 +1393,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan)spin_unlock_irqrestore (&chan->lock, flags);return 0 ; } +EXPORT_SYMBOL_GPL (cpdma_chan_stop);int cpdma_chan_int_ctrl (struct cpdma_chan *chan,bool enable) {
@@ -1416,11 +1440,13 @@ int cpdma_get_num_rx_descs(struct cpdma_ctlr *ctlr) {return ctlr->num_rx_desc; } +EXPORT_SYMBOL_GPL (cpdma_get_num_rx_descs);int cpdma_get_num_tx_descs (struct cpdma_ctlr *ctlr) {return ctlr->num_tx_desc; } +EXPORT_SYMBOL_GPL (cpdma_get_num_tx_descs);int cpdma_set_num_rx_descs (struct cpdma_ctlr *ctlr,int num_rx_desc) {
@@ -1442,3 +1468,4 @@ int cpdma_set_num_rx_descs(struct cpdma_ctlr *ctlr, int num_rx_desc)return ret; } +EXPORT_SYMBOL_GPL (cpdma_set_num_rx_descs);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 125/957 wifi: brcmfmac: Fix error pointer dereference
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ethan Tidmore <[email protected]>
[ Upstream commit dd8592fc6007a451c3e4b9025de365e39de8178a ]
The function brcmf_chip_add_core() can return an error pointer and is not checked. Add checks for error pointer.
Detected by Smatch:drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1010 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1013 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1016 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1019 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1022 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()
--- .../wireless/broadcom/brcm80211/brcmfmac/chip.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +15 -0
@@ -1007,18 +1007,33 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) core =brcmf_chip_add_core (ci,BCMA_CORE_CHIPCOMMON ,SI_ENUM_BASE_DEFAULT ,0 ); +if (IS_ERR (core)) +return PTR_ERR (core); +brcmf_chip_sb_corerev (ci, core); core =brcmf_chip_add_core (ci,BCMA_CORE_SDIO_DEV ,BCM4329_CORE_BUS_BASE ,0 ); +if (IS_ERR (core)) +return PTR_ERR (core); +brcmf_chip_sb_corerev (ci, core); core =brcmf_chip_add_core (ci,BCMA_CORE_INTERNAL_MEM ,BCM4329_CORE_SOCRAM_BASE ,0 ); +if (IS_ERR (core)) +return PTR_ERR (core); +brcmf_chip_sb_corerev (ci, core); core =brcmf_chip_add_core (ci,BCMA_CORE_ARM_CM3 ,BCM4329_CORE_ARM_BASE ,0 ); +if (IS_ERR (core)) +return PTR_ERR (core); +brcmf_chip_sb_corerev (ci, core); core =brcmf_chip_add_core (ci,BCMA_CORE_80211 ,0x18001000 ,0 ); +if (IS_ERR (core)) +return PTR_ERR (core); +brcmf_chip_sb_corerev (ci, core); }else if (socitype ==SOCI_AI ) { ci->iscoreup = brcmf_chip_ai_iscoreup;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 126/957 wifi: mac80211: handle VHT EXT NSS in ieee80211_determine_our_sta_mode()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolas Escande <[email protected]>
[ Upstream commit b5b8e295973083abf823fb66647a7c702a8db8a7 ]
A station which has a NSS ratio on the number of streams it is capable of in 160MHz VHT operation is supposed to use the 'Extended NSS BW Support' as defined by section '9.4.2.156.2 VHT Capabilities Information field'.
This was missing in ieee80211_determine_our_sta_mode() and so we would wrongfully downgrade our bandwidth when connecting to an AP that supported 160MHz with messages such as:
[ 37.638346] wlan1: AP XX:XX:XX:XX:XX:XX changed bandwidth in assoc response, new used config is 5280.000 MHz, width 3 (5290.000/0 MHz)
--- net/mac80211/mlme.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/mac80211/mlme.c +2 -1
@@ -5897,7 +5897,8 @@ ieee80211_determine_our_sta_mode(struct ieee80211_sub_if_data *sdata,if (is_5ghz && !(vht_cap.cap & (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | -IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ ))) { +IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ | +IEEE80211_VHT_CAP_EXT_NSS_BW_MASK ))) { conn->bw_limit =IEEE80211_CONN_BW_LIMIT_80 ;mlme_link_id_dbg (sdata, link_id,"no VHT 160 MHz capability on 5 GHz, limiting to 80 MHz" );
Signature · 1 line
2.53.0
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.32 release. There are 957 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 22 May 2026 16:20:16 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.18.32-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.18.y
and the diffstat can be found below.thanks,
greg k-h
I hope you don't mind me asking, but shouldn't this be 6.18.33-rc1, since 6.18.32 was released a few days ago? I think you forgot to increment the version number.
Signature · 1 line
-Barry K. Nathan <[email protected]>
Greg Kroah-Hartman
maintainerPATCH 127/957 bpf: Drop task_to_inode and inet_conn_established from lsm sleepable hooks
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
[ Upstream commit beaf0e96b1da74549a6cabd040f9667d83b2e97e ]
bpf_lsm_task_to_inode() is called under rcu_read_lock() and bpf_lsm_inet_conn_established() is called from softirq context, so neither hook can be used by sleepable LSM programs.
--- kernel/bpf/bpf_lsm.c | 3 --- 1 file changed, 3 deletions(-)
kernel/bpf/bpf_lsm.c +0 -3
@@ -357,8 +357,6 @@ BTF_ID(func, bpf_lsm_sb_umount) BTF_ID(func, bpf_lsm_settime)#ifdef CONFIG_SECURITY_NETWORK -BTF_ID(func, bpf_lsm_inet_conn_established) - BTF_ID(func, bpf_lsm_socket_accept) BTF_ID(func, bpf_lsm_socket_bind)BTF_ID (func, bpf_lsm_socket_connect)
@@ -379,7 +377,6 @@ BTF_ID(func, bpf_lsm_syslog) BTF_ID(func, bpf_lsm_task_alloc) BTF_ID(func, bpf_lsm_task_prctl) BTF_ID(func, bpf_lsm_task_setscheduler) -BTF_ID(func, bpf_lsm_task_to_inode) BTF_ID(func, bpf_lsm_userns_create)BTF_SET_END (sleepable_lsm_hooks)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 128/957 bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
[ Upstream commit 1c22483a2c4bbf747787f328392ca3e68619c4dc ]
CO-RE accessor strings are colon-separated indices that describe a path from a root BTF type to a target field, e.g. "0:1:2" walks through nested struct members. bpf_core_parse_spec() parses each component with sscanf("%d"), so negative values like -1 are silently accepted. The subsequent bounds checks (access_idx >= btf_vlen(t)) only guard the upper bound and always pass for negative values because C integer promotion converts the __u16 btf_vlen result to int, making the comparison (int)(-1) >= (int)(N) false for any positive N.
When -1 reaches btf_member_bit_offset() it gets cast to u32 0xffffffff, producing an out-of-bounds read far past the members array. A crafted BPF program with a negative CO-RE accessor on any struct that exists in vmlinux BTF (e.g. task_struct) crashes the kernel deterministically during BPF_PROG_LOAD on any system with CONFIG_DEBUG_INFO_BTF=y (default on major distributions). The bug is reachable with CAP_BPF:
BUG: unable to handle page fault for address: ffffed11818b6626 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page Oops: Oops: 0000 [#1] SMP KASAN NOPTI CPU: 0 UID: 0 PID: 85 Comm: poc Not tainted 7.0.0-rc6 #18 PREEMPT(full) RIP: 0010:bpf_core_parse_spec (tools/lib/bpf/relo_core.c:354) RAX: 00000000ffffffff Call Trace: <TASK> bpf_core_calc_relo_insn (tools/lib/bpf/relo_core.c:1321) bpf_core_apply (kernel/bpf/btf.c:9507) check_core_relo (kernel/bpf/verifier.c:19475) bpf_check (kernel/bpf/verifier.c:26031) bpf_prog_load (kernel/bpf/syscall.c:3089) __sys_bpf (kernel/bpf/syscall.c:6228) </TASK>
CO-RE accessor indices are inherently non-negative (struct member index, array element index, or enumerator index), so reject them immediately after parsing.
--- tools/lib/bpf/relo_core.c | 2 ++ 1 file changed, 2 insertions(+)
tools/lib/bpf/relo_core.c +2 -0
@@ -292,6 +292,8 @@ int bpf_core_parse_spec(const char *prog_name, const struct btf *btf, ++spec_str;if (sscanf (spec_str,"%d%n" , &access_idx, &parsed_len) !=1 )return -EINVAL ; +if (access_idx <0 ) +return -EINVAL ;if (spec->raw_len ==BPF_CORE_SPEC_MAX_LEN )return -E2BIG ; spec_str += parsed_len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 129/957 wifi: ath10k: fix station lookup failure during disconnect
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baochen Qiang <[email protected]>
[ Upstream commit 9a34a59c6086ae731a06b3e61b0951feef758648 ]
Recent commit [1] moved station statistics collection to an earlier stage of the disconnect flow. With this change in place, ath10k fails to resolve the station entry when handling a peer stats event triggered during disconnect, resulting in log messages such as:
wlp58s0: deauthenticating from 74:1a:e0:e7:b4:c8 by local choice (Reason: 3=DEAUTH_LEAVING) ath10k_pci 0000:3a:00.0: not found station for peer statsath10k_pci 0000:3a:00.0: failed to parse stats info tlv: -22
The failure occurs because ath10k relies on ieee80211_find_sta_by_ifaddr() for station lookup. That function uses local->sta_hash, but by the time the peer stats request is triggered during disconnect, mac80211 has already removed the station from that hash table, leading to lookup failure.
Before commit [1], this issue was not visible because the transition from IEEE80211_STA_NONE to IEEE80211_STA_NOTEXIST prevented ath10k from sending a peer stats request at all: ath10k_mac_sta_get_peer_stats_info() would fail early to find the peer and skip requesting statistics.
Fix this by switching the lookup path to ath10k_peer_find(), which queries ath10k's internal peer table. At the point where the firmware emits the peer stats event, the peer entry is still present in the driver's list, ensuring lookup succeeds.
Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00309-QCARMSWPZ-1
--- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 26 +++++++++++++---------- 1 file changed, 15 insertions(+), 11 deletions(-)
drivers/net/wireless/ath/ath10k/wmi-tlv.c +15 -11
@@ -3,7 +3,7 @@* Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. -* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. +* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include "core.h" #include "debug.h"
@@ -14,6 +14,7 @@#include "wmi-tlv.h" #include "p2p.h" #include "testmode.h" +#include "txrx.h" #include <linux/bitfield.h> /***************/
@@ -224,8 +225,9 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16 const void *ptr, void *data) { const struct wmi_tlv_peer_stats_info *stat = ptr; -struct ieee80211_sta *sta; +u32 vdev_id = *(u32 *)data;struct ath10k_sta *arsta; +struct ath10k_peer *peer;if (tag !=WMI_TLV_TAG_STRUCT_PEER_STATS_INFO )return -EPROTO ;
@@ -241,20 +243,20 @@ 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" ); +guard (spinlock_bh)(&ar->data_lock); + + peer =ath10k_peer_find (ar, vdev_id, stat->peer_macaddr.addr); +if (!peer || !peer->sta) { +ath10k_warn (ar,"not found %s with vdev id %u mac addr %pM for peer stats\n" , + peer ?"sta" :"peer" , vdev_id, stat->peer_macaddr.addr);return -EINVAL ; } - arsta = (struct ath10k_sta *)sta->drv_priv; + arsta = (struct ath10k_sta *)peer->sta->drv_priv; arsta->rx_rate_code =__le32_to_cpu (stat->last_rx_rate_code); 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 ; }
@@ -266,6 +268,7 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,const struct wmi_tlv_peer_stats_info_ev *ev;const void *data;u32 num_peer_stats; +u32 vdev_id;int ret; tb =ath10k_wmi_tlv_parse_alloc (ar, skb->data, skb->len,GFP_ATOMIC );
@@ -284,15 +287,16 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar, } num_peer_stats =__le32_to_cpu (ev->num_peers); + vdev_id =__le32_to_cpu (ev->vdev_id);ath10k_dbg (ar,ATH10K_DBG_WMI ,"wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n" , -__le32_to_cpu (ev->vdev_id), + vdev_id, num_peer_stats,__le32_to_cpu (ev->more_data)); ret =ath10k_wmi_tlv_iter (ar, data,ath10k_wmi_tlv_len (data), - ath10k_wmi_tlv_parse_peer_stats_info,NULL ); + ath10k_wmi_tlv_parse_peer_stats_info, &vdev_id);if (ret)ath10k_warn (ar,"failed to parse stats info tlv: %d\n" , ret);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 130/957 bpf: Support negative offsets, BPF_SUB, and alu32 for linked register tracking
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Puranjay Mohan <[email protected]>
[ Upstream commit 7a433e519364c3c19643e5c857f4fbfaebec441c ]
Previously, the verifier only tracked positive constant deltas between linked registers using BPF_ADD. This limitation meant patterns like:
r1 = r0;
r1 += -4;
if r1 s>= 0 goto l0_%=; // r1 >= 0 implies r0 >= 4
// verifier couldn't propagate bounds back to r0 if r0 != 0 goto l0_%=;
r0 /= 0; // Verifier thinks this is reachable
l0_%=:
Similar limitation exists for 32-bit registers.
With this change, the verifier can now track negative deltas in reg->off enabling bound propagation for the above pattern.
For alu32, we make sure the destination register has the upper 32 bits as 0s before creating the link. BPF_ADD_CONST is split into BPF_ADD_CONST64 and BPF_ADD_CONST32, the latter is used in case of alu32 and sync_linked_regs uses this to zext the result if known_reg has this flag.
Stable-dep-of: d7f14173c0d5 ("bpf: Fix linked reg delta tracking when src_reg == dst_reg")
--- include/linux/bpf_verifier.h | 6 ++- kernel/bpf/verifier.c | 50 +++++++++++++++---- .../selftests/bpf/progs/verifier_bounds.c | 2 +- 3 files changed, 45 insertions(+), 13 deletions(-)
include/linux/bpf_verifier.h +5 -1
@@ -147,8 +147,12 @@ struct bpf_reg_state {* registers. Example: * r1 = r2; both will have r1->id == r2->id == N * r1 += 10; r1->id == N | BPF_ADD_CONST and r1->off == 10 +* r3 = r2; both will have r3->id == r2->id == N +* w3 += 10; r3->id == N | BPF_ADD_CONST32 and r3->off == 10 */ -#define BPF_ADD_CONST (1U << 31) +#define BPF_ADD_CONST64 (1U << 31) +#define BPF_ADD_CONST32 (1U << 30) +#define BPF_ADD_CONST (BPF_ADD_CONST64 | BPF_ADD_CONST32)u32 id;/* PTR_TO_SOCKET and PTR_TO_TCP_SOCK could be a ptr returned * from a pointer-cast helper, bpf_sk_fullsock() and
kernel/bpf/verifier.c +39 -11
84 lines not on this page · raw message
tools/testing/selftests/bpf/progs/verifier_bounds.c +1 -1
@@ -1477,7 +1477,7 @@ __naked void sub64_full_overflow(void) SEC("socket") __description("64-bit subtraction, partial overflow, result in unbounded reg") __success __log_level(2) -__msg("3: (1f) r3 -= r2 {{.*}} R3=scalar()") +__msg("3: (1f) r3 -= r2 {{.*}} R3=scalar(id=1-1)") __retval(0)__naked void sub64_partial_overflow (void ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 131/957 bpf: Fix linked reg delta tracking when src_reg == dst_reg
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit d7f14173c0d5866c3cae759dee560ad1bed10d2e ]
Consider the case of rX += rX where src_reg and dst_reg are pointers to the same bpf_reg_state in adjust_reg_min_max_vals(). The latter first modifies the dst_reg in-place, and later in the delta tracking, the subsequent is_reg_const(src_reg)/reg_const_value(src_reg) reads the post-{add,sub} value instead of the original source.
This is problematic since it sets an incorrect delta, which sync_linked_regs() then propagates to linked registers, thus creating a verifier-vs-runtime mismatch. Fix it by just skipping this corner case.
--- kernel/bpf/verifier.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/bpf/verifier.c +2 -1
@@ -15808,7 +15808,8 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,*/ if (env->bpf_capable && (BPF_OP (insn->code) ==BPF_ADD ||BPF_OP (insn->code) ==BPF_SUB ) && - dst_reg->id &&is_reg_const (src_reg, alu32)) { + dst_reg->id &&is_reg_const (src_reg, alu32) && + !(BPF_SRC (insn->code) ==BPF_X && insn->src_reg == insn->dst_reg)) {u64 val =reg_const_value (src_reg, alu32);s32 off;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 132/957 arm64: entry: Dont preempt with SError or Debug masked
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Rutland <[email protected]>
[ Upstream commit 2371bd83b3df9d833191fe58dadb0e69a794a1cd ]
On arm64, involuntary kernel preemption has been subtly broken since the move to the generic irqentry code. When preemption occurs, the new task may run with SError and Debug exceptions masked unexpectedly, leading to a loss of RAS events, breakpoints, watchpoints, and single-step exceptions.
Prior to moving to the generic irqentry code, involuntary preemption of kernel mode would only occur when returning from regular interrupts, in a state where interrupts were masked and all other arm64-specific exceptions (SError, Debug, and pseudo-NMI) were unmasked. This is the only state in which it is valid to switch tasks.
As part of moving to the generic irqentry code, the involuntary preemption logic was moved such that involuntary preemption could occur when returning from any (non-NMI) exception. As most exception handlers mask all arm64-specific exceptions before this point, preemption could occur in a state where arm64-specific exceptions were masked. This is not a valid state to switch tasks, and resulted in the loss of exceptions described above.
As a temporary bodge, avoid the loss of exceptions by avoiding involuntary preemption when SError and/or Debug exceptions are masked. Practically speaking this means that involuntary preemption will only occur when returning from regular interrupts, as was the case before moving to the generic irqentry code.
--- arch/arm64/include/asm/entry-common.h | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
arch/arm64/include/asm/entry-common.h +13 -8
@@ -29,14 +29,19 @@ static __always_inline void arch_exit_to_user_mode_work(struct pt_regs *regs,static inline bool arch_irqentry_exit_need_resched (void ) { -/* -* DAIF.DA are cleared at the start of IRQ/FIQ handling, and when GIC -* priority masking is used the GIC irqchip driver will clear DAIF.IF -* using gic_arch_enable_irqs() for normal IRQs. If anything is set in -* DAIF we must have handled an NMI, so skip preemption. -*/ -if (system_uses_irq_prio_masking () &&read_sysreg (daif)) -return false; +if (system_uses_irq_prio_masking ()) { +/* +* DAIF.DA are cleared at the start of IRQ/FIQ handling, and when GIC +* priority masking is used the GIC irqchip driver will clear DAIF.IF +* using gic_arch_enable_irqs() for normal IRQs. If anything is set in +* DAIF we must have handled an NMI, so skip preemption. +*/ +if (read_sysreg (daif)) +return false; + }else { +if (read_sysreg (daif) & (PSR_D_BIT |PSR_A_BIT )) +return false; + }/* * Preempting a task from an IRQ means we leave copies of PSTATE
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 133/957 ACPI: AGDI: fix missing newline in error message
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoyu Lu <[email protected]>
[ Upstream commit b178330b67abb7293b6de28b2a49d49c83962db5 ]
Add the missing trailing newline to the dev_err() message printed when SDEI event registration fails.
This keeps the error output as a properly terminated log line.
--- drivers/acpi/arm64/agdi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/arm64/agdi.c +1 -1
@@ -32,7 +32,7 @@ static int agdi_sdei_probe(struct platform_device *pdev, err =sdei_event_register (adata->sdei_event, agdi_sdei_handler, pdev);if (err) { -dev_err (&pdev->dev,"Failed to register for SDEI event %d" , +dev_err (&pdev->dev,"Failed to register for SDEI event %d\n" , adata->sdei_event);return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 134/957 arm64: kexec: Remove duplicate allocation for trans_pgd
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wang Wensheng <[email protected]>
[ Upstream commit ee020bf6f14094c9ae434bb37e6957a1fdad513c ]
trans_pgd would be allocated in trans_pgd_create_copy(), so remove the duplicate allocation before calling trans_pgd_create_copy().
--- arch/arm64/kernel/machine_kexec.c | 3 --- 1 file changed, 3 deletions(-)
arch/arm64/kernel/machine_kexec.c +0 -3
@@ -129,9 +129,6 @@ int machine_kexec_post_load(struct kimage *kimage) }/* Create a copy of the linear map */ - trans_pgd =kexec_page_alloc (kimage); -if (!trans_pgd) -return -ENOMEM ; rc =trans_pgd_create_copy (&info, &trans_pgd,PAGE_OFFSET ,PAGE_END );if (rc)return rc;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 135/957 macsec: Support VLAN-filtering lower devices
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cosmin Ratiu <[email protected]>
[ Upstream commit a363b1c8be879c79a688eaf93ba01b63f8b0e63c ]
VLAN-filtering is done through two netdev features (NETIF_F_HW_VLAN_CTAG_FILTER and NETIF_F_HW_VLAN_STAG_FILTER) and two netdev ops (ndo_vlan_rx_add_vid and ndo_vlan_rx_kill_vid).
Implement these and advertise the features if the lower device supports them. This allows proper VLAN filtering to work on top of MACsec devices, when the lower device is capable of VLAN filtering. As a concrete example, having this chain of interfaces now works:vlan_filtering_capable_dev(1) -> macsec_dev(2) -> macsec_vlan_dev(3)
Before the mentioned commit this used to accidentally work because the MACsec device (and thus the lower device) was put in promiscuous mode and the VLAN filter was not used. But after commit [1] correctly made the macsec driver expose the IFF_UNICAST_FLT flag, promiscuous mode was no longer used and VLAN filters on dev 1 kicked in. Without support in dev 2 for propagating VLAN filters down, the register_vlan_dev -> vlan_vid_add -> __vlan_vid_add -> vlan_add_rx_filter_info call from dev 3 is silently eaten (because vlan_hw_filter_capable returns false and vlan_add_rx_filter_info silently succeeds).
For MACsec, VLAN filters are only relevant for offload, otherwise the VLANs are encrypted and the lower devices don't care about them. So VLAN filters are only passed on to lower devices in offload mode. Flipping between offload modes now needs to offload/unoffload the filters with vlan_{get,drop}_rx_*_filter_info().
To avoid the back-and-forth filter updating during rollback, the setting of macsec->offload is moved after the add/del secy ops. This is safe since none of the code called from those requires macsec->offload.
In case adding the filters fails, the added ones are rolled back and an error is returned to the operation toggling the offload state.
--- drivers/net/macsec.c | 71 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 8 deletions(-)
drivers/net/macsec.c +63 -8
@@ -2584,7 +2584,9 @@ static void macsec_inherit_tso_max(struct net_device *dev)netif_inherit_tso_max (dev, macsec->real_dev); } -static int macsec_update_offload (struct net_device *dev,enum macsec_offload offload) +static int macsec_update_offload (struct net_device *dev, +enum macsec_offload offload, +struct netlink_ext_ack *extack) {enum macsec_offload prev_offload;const struct macsec_ops *ops;
@@ -2616,14 +2618,35 @@ static int macsec_update_offload(struct net_device *dev, enum macsec_offload offif (!ops)return -EOPNOTSUPP ; - macsec->offload = offload; - ctx.secy = &macsec->secy; ret = offload ==MACSEC_OFFLOAD_OFF ?macsec_offload (ops->mdo_del_secy, &ctx) :macsec_offload (ops->mdo_add_secy, &ctx); -if (ret) { - macsec->offload = prev_offload; +if (ret)return ret; + +/* Remove VLAN filters when disabling offload. */ +if (offload ==MACSEC_OFFLOAD_OFF ) { +vlan_drop_rx_ctag_filter_info (dev); +vlan_drop_rx_stag_filter_info (dev); + } + macsec->offload = offload; +/* Add VLAN filters when enabling offload. */ +if (prev_offload ==MACSEC_OFFLOAD_OFF ) { + ret =vlan_get_rx_ctag_filter_info (dev); +if (ret) { +NL_SET_ERR_MSG_FMT (extack, +"adding ctag VLAN filters failed, err %d" , + ret); + goto rollback_offload; + } + ret =vlan_get_rx_stag_filter_info (dev); +if (ret) { +NL_SET_ERR_MSG_FMT (extack, +"adding stag VLAN filters failed, err %d" , + ret); +vlan_drop_rx_ctag_filter_info (dev); + goto rollback_offload; + } }macsec_set_head_tail_room (dev);
@@ -2633,6 +2656,12 @@ static int macsec_update_offload(struct net_device *dev, enum macsec_offload offnetdev_update_features (dev); +return 0 ; + +rollback_offload: + macsec->offload = prev_offload; +macsec_offload (ops->mdo_del_secy, &ctx); +return ret; }
@@ -2673,7 +2702,7 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info) offload =nla_get_u8 (tb_offload[MACSEC_OFFLOAD_ATTR_TYPE ]);if (macsec->offload != offload) - ret =macsec_update_offload (dev, offload); + ret =macsec_update_offload (dev, offload, info->extack); out:rtnl_unlock ();return ret;
@@ -3486,7 +3515,8 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, }#define MACSEC_FEATURES \ - (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST) + (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ + NETIF_F_HW_VLAN_STAG_FILTER | NETIF_F_HW_VLAN_CTAG_FILTER)#define MACSEC_OFFLOAD_FEATURES \ (MACSEC_FEATURES | NETIF_F_GSO_SOFTWARE | NETIF_F_SOFT_FEATURES | \
@@ -3707,6 +3737,29 @@ static int macsec_set_mac_address(struct net_device *dev, void *p)return err; } +static int macsec_vlan_rx_add_vid (struct net_device *dev, +__be16 proto,u16 vid) +{ +struct macsec_dev *macsec =netdev_priv (dev); + +if (!macsec_is_offloaded (macsec)) +return 0 ; + +return vlan_vid_add (macsec->real_dev, proto, vid); +} + +static int macsec_vlan_rx_kill_vid (struct net_device *dev, +__be16 proto,u16 vid) +{ +struct macsec_dev *macsec =netdev_priv (dev); + +if (!macsec_is_offloaded (macsec)) +return 0 ; + +vlan_vid_del (macsec->real_dev, proto, vid); +return 0 ; +} +static int macsec_change_mtu (struct net_device *dev,int new_mtu) {struct macsec_dev *macsec =macsec_priv (dev);
@@ -3748,6 +3801,8 @@ static const struct net_device_ops macsec_netdev_ops = { .ndo_set_rx_mode = macsec_dev_set_rx_mode, .ndo_change_rx_flags = macsec_dev_change_rx_flags, .ndo_set_mac_address = macsec_set_mac_address, + .ndo_vlan_rx_add_vid = macsec_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = macsec_vlan_rx_kill_vid, .ndo_start_xmit = macsec_start_xmit, .ndo_get_stats64 = macsec_get_stats64, .ndo_get_iflink = macsec_get_iflink,
@@ -3912,7 +3967,7 @@ static int macsec_changelink(struct net_device *dev, struct nlattr *tb[], offload =nla_get_u8 (data[IFLA_MACSEC_OFFLOAD ]);if (macsec->offload != offload) { macsec_offload_state_change = true; - ret =macsec_update_offload (dev, offload); + ret =macsec_update_offload (dev, offload, extack);if (ret) goto cleanup; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 136/957 net: bcmgenet: fix off-by-one in bcmgenet_put_txcb
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Chen <[email protected]>
[ Upstream commit 57f3f53d2c9c5a9e133596e2f7bc1c50688a6d38 ]
The write_ptr points to the next open tx_cb. We want to return the tx_cb that gets rewinded, so we must rewind the pointer first then return the tx_cb that it points to. That way the txcb can be correctly cleaned up.
--- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +3 -3
@@ -1815,15 +1815,15 @@ static struct enet_cb *bcmgenet_put_txcb(struct bcmgenet_priv *priv, {struct enet_cb *tx_cb_ptr; - tx_cb_ptr = ring->cbs; - tx_cb_ptr += ring->write_ptr - ring->cb_ptr; -/* Rewinding local write pointer */ if (ring->write_ptr == ring->cb_ptr) ring->write_ptr = ring->end_ptr;else ring->write_ptr--; + tx_cb_ptr = ring->cbs; + tx_cb_ptr += ring->write_ptr - ring->cb_ptr; +return tx_cb_ptr; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 137/957 net: bcmgenet: fix leaking free_bds
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Chen <[email protected]>
[ Upstream commit 3f3168300efb839028328d720ab3962f91d6a0d0 ]
While reclaiming the tx queue we fast forward the write pointer to drop any data in flight. These dropped frames are not added back to the pool of free bds. We also need to tell the netdev that we are dropping said data.
--- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +2 -0
@@ -1981,6 +1981,7 @@ static unsigned int bcmgenet_tx_reclaim(struct net_device *dev, drop = (ring->prod_index - ring->c_index) &DMA_C_INDEX_MASK ; released += drop; ring->prod_index = ring->c_index &DMA_C_INDEX_MASK ; + ring->free_bds += drop;while (drop--) { cb_ptr =bcmgenet_put_txcb (priv, ring); skb = cb_ptr->skb;
@@ -1992,6 +1993,7 @@ static unsigned int bcmgenet_tx_reclaim(struct net_device *dev, }if (skb)dev_consume_skb_any (skb); +netdev_tx_reset_queue (netdev_get_tx_queue (dev, ring->index));bcmgenet_tdma_ring_writel (priv, ring->index, ring->prod_index,TDMA_PROD_INDEX ); wr_ptr = ring->write_ptr *WORDS_PER_BD (priv);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 138/957 net: bcmgenet: fix racing timeout handler
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Chen <[email protected]>
[ Upstream commit 5393b2b5bee2ac51a0043dc7f4ac3475f053d08d ]
The bcmgenet_timeout handler tries to take down all tx queues when a single queue times out. This is over zealous and causes many race conditions with queues that are still chugging along. Instead lets only restart the timed out queue.
--- .../net/ethernet/broadcom/genet/bcmgenet.c | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +9 -13
@@ -3475,27 +3475,23 @@ static void bcmgenet_dump_tx_queue(struct bcmgenet_tx_ring *ring)static void bcmgenet_timeout (struct net_device *dev,unsigned int txqueue) {struct bcmgenet_priv *priv =netdev_priv (dev); -u32 int1_enable =0 ; -unsigned int q; +struct bcmgenet_tx_ring *ring = &priv->tx_rings[txqueue]; +struct netdev_queue *txq =netdev_get_tx_queue (dev, txqueue);netif_dbg (priv, tx_err, dev,"bcmgenet_timeout\n" ); -for (q =0 ; q <= priv->hw_params->tx_queues; q++) -bcmgenet_dump_tx_queue (&priv->tx_rings[q]); - -bcmgenet_tx_reclaim_all (dev); +bcmgenet_dump_tx_queue (ring); -for (q =0 ; q <= priv->hw_params->tx_queues; q++) - int1_enable |= (1 << q); +bcmgenet_tx_reclaim (dev, ring, true); -/* Re-enable TX interrupts if disabled */ -bcmgenet_intrl2_1_writel (priv, int1_enable,INTRL2_CPU_MASK_CLEAR ); +/* Re-enable the TX interrupt for this ring */ +bcmgenet_intrl2_1_writel (priv,1 << txqueue,INTRL2_CPU_MASK_CLEAR ); -netif_trans_update (dev); +txq_trans_cond_update (txq); -BCMGENET_STATS64_INC ((&priv->tx_rings[txqueue].stats64), errors); +BCMGENET_STATS64_INC ((&ring->stats64), errors); -netif_tx_wake_all_queues (dev); +netif_tx_wake_queue (txq); }#define MAX_MDF_FILTER 17
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 139/957 net: airoha: Add dma_rmb() and READ_ONCE() in airoha_qdma_rx_process()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 4ae0604a0673e11e2075b178387151fcad5111b5 ]
Add missing dma_rmb() in airoha_qdma_rx_process routine to make sure the DMA read operations are completed when the NIC reports the processing on the current descriptor is done. Moreover, add missing READ_ONCE() in airoha_qdma_rx_process() for DMA descriptor control fields in order to avoid any compiler reordering.
--- drivers/net/ethernet/airoha/airoha_eth.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +10 -6
@@ -596,7 +596,7 @@ static int airoha_qdma_fill_rx_queue(struct airoha_queue *q)static int airoha_qdma_get_gdm_port (struct airoha_eth *eth,struct airoha_qdma_desc *desc) { -u32 port, sport, msg1 =le32_to_cpu (desc->msg1); +u32 port, sport, msg1 =le32_to_cpu (READ_ONCE (desc->msg1)); sport =FIELD_GET (QDMA_ETH_RXMSG_SPORT_MASK , msg1);switch (sport) {
@@ -624,21 +624,24 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)while (done < budget) {struct airoha_queue_entry *e = &q->entry[q->tail];struct airoha_qdma_desc *desc = &q->desc[q->tail]; -u32 hash, reason, msg1 =le32_to_cpu (desc->msg1); -struct page *page =virt_to_head_page (e->buf); -u32 desc_ctrl =le32_to_cpu (desc->ctrl); +u32 hash, reason, msg1, desc_ctrl;struct airoha_gdm_port *port;int data_len, len, p; +struct page *page; + desc_ctrl =le32_to_cpu (READ_ONCE (desc->ctrl));if (!(desc_ctrl &QDMA_DESC_DONE_MASK ))break ; +dma_rmb (); + q->tail = (q->tail +1 ) % q->ndesc; q->queued--;dma_sync_single_for_cpu (eth->dev, e->dma_addr,SKB_WITH_OVERHEAD (q->buf_size), dir); + page =virt_to_head_page (e->buf); len =FIELD_GET (QDMA_DESC_LEN_MASK , desc_ctrl); data_len = q->skb ? q->buf_size :SKB_WITH_OVERHEAD (q->buf_size);
@@ -682,8 +685,8 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)* DMA descriptor. Report DSA tag to the DSA stack * via skb dst info. */ -u32 sptag =FIELD_GET (QDMA_ETH_RXMSG_SPTAG , -le32_to_cpu (desc->msg0)); +u32 msg0 =le32_to_cpu (READ_ONCE (desc->msg0)); +u32 sptag =FIELD_GET (QDMA_ETH_RXMSG_SPTAG , msg0);if (sptag <ARRAY_SIZE (port->dsa_meta) && port->dsa_meta[sptag])
@@ -691,6 +694,7 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget) &port->dsa_meta[sptag]->dst); } + msg1 =le32_to_cpu (READ_ONCE (desc->msg1)); hash =FIELD_GET (AIROHA_RXD4_FOE_ENTRY , msg1);if (hash !=AIROHA_RXD4_FOE_ENTRY ) skb_set_hash(q->skb, jhash_1word(hash, 0),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 140/957 eth: fbnic: Use wake instead of start
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mohsin Bashir <[email protected]>
[ Upstream commit 12ff2a4aee6c86746623d5aed24389dbf6dffded ]
fbnic_up() calls netif_tx_start_all_queues(), which only clears __QUEUE_STATE_DRV_XOFF. If qdisc backlog has accumulated on any TX queue before the reconfiguration (e.g. ring resize via ethtool -G), start does not call __netif_schedule() to kick the qdisc, so the pending backlog is never drained and the queue stalls.
Switch to netif_tx_wake_all_queues(), which clears DRV_XOFF and also calls __netif_schedule() on every queue, ensuring any backlog that built up before the down/up cycle is promptly dequeued.
--- drivers/net/ethernet/meta/fbnic/fbnic_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/meta/fbnic/fbnic_pci.c +1 -1
@@ -139,7 +139,7 @@ void fbnic_up(struct fbnic_net *fbn)/* Enable Tx/Rx processing */ fbnic_napi_enable (fbn); -netif_tx_start_all_queues (fbn->netdev); +netif_tx_wake_all_queues (fbn->netdev);fbnic_service_task_start (fbn); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 141/957 netfilter: xt_socket: enable defrag after all other checks
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 542be3fa5aff54210a02954c38f07e53ea9bdafd ]
Originally this did not matter because defrag was enabled once per netns and only disabled again on netns dismantle. When this got changed I should have adjusted checkentry to not leave defrag enabled on error.
--- net/netfilter/xt_socket.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-)
net/netfilter/xt_socket.c +6 -17
@@ -168,52 +168,41 @@ static int socket_mt_enable_defrag(struct net *net, int family)static int socket_mt_v1_check (const struct xt_mtchk_param *par) {const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; -int err; - - err =socket_mt_enable_defrag (par->net, par->family); -if (err) -return err;if (info->flags & ~XT_SOCKET_FLAGS_V1 ) {pr_info_ratelimited ("unknown flags 0x%x\n" , info->flags & ~XT_SOCKET_FLAGS_V1 );return -EINVAL ; } -return 0 ; + +return socket_mt_enable_defrag (par->net, par->family); }static int socket_mt_v2_check (const struct xt_mtchk_param *par) {const struct xt_socket_mtinfo2 *info = (struct xt_socket_mtinfo2 *) par->matchinfo; -int err; - - err =socket_mt_enable_defrag (par->net, par->family); -if (err) -return err;if (info->flags & ~XT_SOCKET_FLAGS_V2 ) {pr_info_ratelimited ("unknown flags 0x%x\n" , info->flags & ~XT_SOCKET_FLAGS_V2 );return -EINVAL ; } -return 0 ; + +return socket_mt_enable_defrag (par->net, par->family); }static int socket_mt_v3_check (const struct xt_mtchk_param *par) {const struct xt_socket_mtinfo3 *info = (struct xt_socket_mtinfo3 *)par->matchinfo; -int err; - err =socket_mt_enable_defrag (par->net, par->family); -if (err) -return err;if (info->flags & ~XT_SOCKET_FLAGS_V3 ) {pr_info_ratelimited ("unknown flags 0x%x\n" , info->flags & ~XT_SOCKET_FLAGS_V3 );return -EINVAL ; } -return 0 ; + +return socket_mt_enable_defrag (par->net, par->family); }static void socket_mt_destroy (const struct xt_mtdtor_param *par)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 142/957 netfilter: nft_fwd_netdev: check ttl/hl before forwarding
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 1dfd95bdf4d18d263aa8fad06bfb9f4d9c992b18 ]
Drop packets if their ttl/hl is too small for forwarding.
--- net/netfilter/nft_fwd_netdev.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
net/netfilter/nft_fwd_netdev.c +10 -0
@@ -116,6 +116,11 @@ static void nft_fwd_neigh_eval(const struct nft_expr *expr, goto out; } iph =ip_hdr (skb); +if (iph->ttl <=1 ) { + verdict =NF_DROP ; + goto out; + } +ip_decrease_ttl (iph); neigh_table =NEIGH_ARP_TABLE ;break ;
@@ -132,6 +137,11 @@ static void nft_fwd_neigh_eval(const struct nft_expr *expr, goto out; } ip6h =ipv6_hdr (skb); +if (ip6h->hop_limit <=1 ) { + verdict =NF_DROP ; + goto out; + } + ip6h->hop_limit--; neigh_table =NEIGH_ND_TABLE ;break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 143/957 bpf: fix mm lifecycle in open-coded task_vma iterator
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Puranjay Mohan <[email protected]>
[ Upstream commit d8e27d2d22b6e2df3a0125b8c08e9aace38c954c ]
The open-coded task_vma iterator reads task->mm locklessly and acquires mmap_read_trylock() but never calls mmget(). If the task exits concurrently, the mm_struct can be freed as it is not SLAB_TYPESAFE_BY_RCU, resulting in a use-after-free.
Safely read task->mm with a trylock on alloc_lock and acquire an mm reference. Drop the reference via bpf_iter_mmput_async() in _destroy() and error paths. bpf_iter_mmput_async() is a local wrapper around mmput_async() with a fallback to mmput() on !CONFIG_MMU.
Reject irqs-disabled contexts (including NMI) up front. Operations used by _next() and _destroy() (mmap_read_unlock, bpf_iter_mmput_async) take spinlocks with IRQs disabled (pool->lock, pi_lock). Running from NMI or from a tracepoint that fires with those locks held could deadlock.
A trylock on alloc_lock is used instead of the blocking task_lock() (get_task_mm) to avoid a deadlock when a softirq BPF program iterates a task that already holds its alloc_lock on the same CPU.
--- kernel/bpf/task_iter.c | 54 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-)
kernel/bpf/task_iter.c +51 -3
@@ -9,6 +9,7 @@#include <linux/bpf_mem_alloc.h> #include <linux/btf_ids.h> #include <linux/mm_types.h> +#include <linux/sched/mm.h> #include "mmap_unlock_work.h" static const char *const iter_task_type_names[] = {
@@ -794,6 +795,15 @@ const struct bpf_func_proto bpf_find_vma_proto = { .arg5_type = ARG_ANYTHING, }; +static inline void bpf_iter_mmput_async (struct mm_struct *mm) +{ +#ifdef CONFIG_MMU +mmput_async (mm); +#else +mmput (mm); +#endif +} +struct bpf_iter_task_vma_kern_data {struct task_struct *task;struct mm_struct *mm;
@@ -825,6 +835,24 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it,BUILD_BUG_ON (sizeof (struct bpf_iter_task_vma_kern ) !=sizeof (struct bpf_iter_task_vma ));BUILD_BUG_ON (__alignof__(struct bpf_iter_task_vma_kern ) != __alignof__(struct bpf_iter_task_vma )); +/* bpf_iter_mmput_async() needs mmput_async() which requires CONFIG_MMU */ +if (!IS_ENABLED (CONFIG_MMU )) { + kit->data =NULL ; +return -EOPNOTSUPP ; + } + +/* +* Reject irqs-disabled contexts including NMI. Operations used +* by _next() and _destroy() (mmap_read_unlock, bpf_iter_mmput_async) +* can take spinlocks with IRQs disabled (pi_lock, pool->lock). +* Running from NMI or from a tracepoint that fires with those +* locks held could deadlock. +*/ +if (irqs_disabled ()) { + kit->data =NULL ; +return -EBUSY ; + } +/* is_iter_reg_valid_uninit guarantees that kit hasn't been initialized * before, so non-NULL kit->data doesn't point to previously * bpf_mem_alloc'd bpf_iter_task_vma_kern_data
@@ -834,7 +862,25 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it,return -ENOMEM ; kit->data->task =get_task_struct (task); +/* +* Safely read task->mm and acquire an mm reference. +* +* Cannot use get_task_mm() because its task_lock() is a +* blocking spin_lock that would deadlock if the target task +* already holds alloc_lock on this CPU (e.g. a softirq BPF +* program iterating a task interrupted while holding its +* alloc_lock). +*/ +if (!spin_trylock (&task->alloc_lock)) { + err = -EBUSY ; + goto err_cleanup_iter; + } kit->data->mm = task->mm; +if (kit->data->mm && !(task->flags &PF_KTHREAD )) +mmget (kit->data->mm); +else + kit->data->mm =NULL ; +spin_unlock (&task->alloc_lock);if (!kit->data->mm) { err = -ENOENT ; goto err_cleanup_iter;
@@ -844,15 +890,16 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it, irq_work_busy =bpf_mmap_unlock_get_irq_work (&kit->data->work);if (irq_work_busy || !mmap_read_trylock (kit->data->mm)) { err = -EBUSY ; - goto err_cleanup_iter; + goto err_cleanup_mmget; }vma_iter_init (&kit->data->vmi, kit->data->mm, addr);return 0 ; +err_cleanup_mmget: +bpf_iter_mmput_async (kit->data->mm); err_cleanup_iter: -if (kit->data->task) -put_task_struct (kit->data->task); +put_task_struct (kit->data->task);bpf_mem_free (&bpf_global_ma, kit->data);/* NULL kit->data signals failed bpf_iter_task_vma initialization */ kit->data =NULL ;
@@ -875,6 +922,7 @@ __bpf_kfunc void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it)if (kit->data) {bpf_mmap_unlock_mm (kit->data->work, kit->data->mm);put_task_struct (kit->data->task); +bpf_iter_mmput_async (kit->data->mm);bpf_mem_free (&bpf_global_ma, kit->data); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 144/957 bpf: switch task_vma iterator from mmap_lock to per-VMA locks
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Puranjay Mohan <[email protected]>
[ Upstream commit bee9ef4a40a277bf401be43d39ba7f7f063cf39c ]
The open-coded task_vma iterator holds mmap_lock for the entire duration of iteration, increasing contention on this highly contended lock.
Switch to per-VMA locking. Find the next VMA via an RCU-protected maple tree walk and lock it with lock_vma_under_rcu(). lock_next_vma() is not used because its fallback takes mmap_read_lock(), and the iterator must work in non-sleepable contexts.
lock_vma_under_rcu() is a point lookup (mas_walk) that finds the VMA containing a given address but cannot iterate across gaps. An RCU-protected vma_next() walk (mas_find) first locates the next VMA's vm_start to pass to lock_vma_under_rcu().
Between the RCU walk and the lock, the VMA may be removed, shrunk, or write-locked. On failure, advance past it using vm_end from the RCU walk. Because the VMA slab is SLAB_TYPESAFE_BY_RCU, vm_end may be stale; fall back to PAGE_SIZE advancement when it does not make forward progress. Concurrent VMA insertions at addresses already passed by the iterator are not detected.
CONFIG_PER_VMA_LOCK is required; return -EOPNOTSUPP without it.
Stable-dep-of: 4cbee026db54 ("bpf: return VMA snapshot from task_vma iterator")
--- kernel/bpf/task_iter.c | 91 +++++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 18 deletions(-)
kernel/bpf/task_iter.c +73 -18
@@ -9,6 +9,7 @@#include <linux/bpf_mem_alloc.h> #include <linux/btf_ids.h> #include <linux/mm_types.h> +#include <linux/mmap_lock.h> #include <linux/sched/mm.h> #include "mmap_unlock_work.h"
@@ -807,8 +808,8 @@ static inline void bpf_iter_mmput_async(struct mm_struct *mm)struct bpf_iter_task_vma_kern_data {struct task_struct *task;struct mm_struct *mm; -struct mmap_unlock_irq_work *work; -struct vma_iterator vmi; +struct vm_area_struct *locked_vma; +u64 next_addr; };struct bpf_iter_task_vma {
@@ -829,21 +830,19 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it, struct task_struct *task, u64 addr) {struct bpf_iter_task_vma_kern *kit = (void *)it; -bool irq_work_busy = false;int err;BUILD_BUG_ON (sizeof (struct bpf_iter_task_vma_kern ) !=sizeof (struct bpf_iter_task_vma ));BUILD_BUG_ON (__alignof__(struct bpf_iter_task_vma_kern ) != __alignof__(struct bpf_iter_task_vma )); -/* bpf_iter_mmput_async() needs mmput_async() which requires CONFIG_MMU */ -if (!IS_ENABLED (CONFIG_MMU )) { +if (!IS_ENABLED (CONFIG_PER_VMA_LOCK )) { kit->data =NULL ;return -EOPNOTSUPP ; }/* * Reject irqs-disabled contexts including NMI. Operations used -* by _next() and _destroy() (mmap_read_unlock, bpf_iter_mmput_async) +* by _next() and _destroy() (vma_end_read, bpf_iter_mmput_async) * can take spinlocks with IRQs disabled (pi_lock, pool->lock). * Running from NMI or from a tracepoint that fires with those * locks held could deadlock.
@@ -886,18 +885,10 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it, goto err_cleanup_iter; } -/* kit->data->work == NULL is valid after bpf_mmap_unlock_get_irq_work */ - irq_work_busy =bpf_mmap_unlock_get_irq_work (&kit->data->work); -if (irq_work_busy || !mmap_read_trylock (kit->data->mm)) { - err = -EBUSY ; - goto err_cleanup_mmget; - } - -vma_iter_init (&kit->data->vmi, kit->data->mm, addr); + kit->data->locked_vma =NULL ; + kit->data->next_addr = addr;return 0 ; -err_cleanup_mmget: -bpf_iter_mmput_async (kit->data->mm); err_cleanup_iter:put_task_struct (kit->data->task);bpf_mem_free (&bpf_global_ma, kit->data);
@@ -906,13 +897,76 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it,return err; } +/* +* Find and lock the next VMA at or after data->next_addr. +* +* lock_vma_under_rcu() is a point lookup (mas_walk): it finds the VMA +* containing a given address but cannot iterate. An RCU-protected +* maple tree walk with vma_next() (mas_find) is needed first to locate +* the next VMA's vm_start across any gap. +* +* Between the RCU walk and the lock, the VMA may be removed, shrunk, +* or write-locked. On failure, advance past it using vm_end from the +* RCU walk. SLAB_TYPESAFE_BY_RCU can make vm_end stale, so fall back +* to PAGE_SIZE advancement to guarantee forward progress. +*/ +static struct vm_area_struct * +bpf_iter_task_vma_find_next (struct bpf_iter_task_vma_kern_data *data) +{ +struct vm_area_struct *vma; +struct vma_iterator vmi; +unsigned long start, end; + +retry: +rcu_read_lock (); +vma_iter_init (&vmi, data->mm, data->next_addr); + vma =vma_next (&vmi); +if (!vma) { +rcu_read_unlock (); +return NULL ; + } + start = vma->vm_start; + end = vma->vm_end; +rcu_read_unlock (); + + vma =lock_vma_under_rcu (data->mm, start); +if (!vma) { +if (end <= data->next_addr) + data->next_addr +=PAGE_SIZE ; +else + data->next_addr = end; + goto retry; + } + +if (unlikely (vma->vm_end <= data->next_addr)) { + data->next_addr +=PAGE_SIZE ; +vma_end_read (vma); + goto retry; + } + +return vma; +} + __bpf_kfunc struct vm_area_struct *bpf_iter_task_vma_next(struct bpf_iter_task_vma *it) {struct bpf_iter_task_vma_kern *kit = (void *)it; +struct vm_area_struct *vma;if (!kit->data)/* bpf_iter_task_vma_new failed */ return NULL ; -return vma_next (&kit->data->vmi); + +if (kit->data->locked_vma) { +vma_end_read (kit->data->locked_vma); + kit->data->locked_vma =NULL ; + } + + vma =bpf_iter_task_vma_find_next (kit->data); +if (!vma) +return NULL ; + + kit->data->locked_vma = vma; + kit->data->next_addr = vma->vm_end; +return vma; } __bpf_kfunc void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it)
@@ -920,7 +974,8 @@ __bpf_kfunc void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it)struct bpf_iter_task_vma_kern *kit = (void *)it;if (kit->data) { -bpf_mmap_unlock_mm (kit->data->work, kit->data->mm); +if (kit->data->locked_vma) +vma_end_read (kit->data->locked_vma);put_task_struct (kit->data->task);bpf_iter_mmput_async (kit->data->mm);bpf_mem_free (&bpf_global_ma, kit->data);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 145/957 bpf: return VMA snapshot from task_vma iterator
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Puranjay Mohan <[email protected]>
[ Upstream commit 4cbee026db54cad39c39db4d356100cb133412b3 ]
Holding the per-VMA lock across the BPF program body creates a lock ordering problem when helpers acquire locks that depend on mmap_lock:
vm_lock -> i_rwsem -> mmap_lock -> vm_lock
Snapshot the VMA under the per-VMA lock in _next() via memcpy(), then drop the lock before returning. The BPF program accesses only the snapshot.
The verifier only trusts vm_mm and vm_file pointers (see BTF_TYPE_SAFE_TRUSTED_OR_NULL in verifier.c). vm_file is reference- counted with get_file() under the lock and released via fput() on the next iteration or in _destroy(). vm_mm is already correct because lock_vma_under_rcu() verifies vma->vm_mm == mm. All other pointers are left as-is by memcpy() since the verifier treats them as untrusted.
--- kernel/bpf/task_iter.c | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-)
kernel/bpf/task_iter.c +30 -12
@@ -808,7 +808,7 @@ static inline void bpf_iter_mmput_async(struct mm_struct *mm)struct bpf_iter_task_vma_kern_data {struct task_struct *task;struct mm_struct *mm; -struct vm_area_struct *locked_vma; +struct vm_area_struct snapshot;u64 next_addr; };
@@ -842,7 +842,7 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it,/* * Reject irqs-disabled contexts including NMI. Operations used -* by _next() and _destroy() (vma_end_read, bpf_iter_mmput_async) +* by _next() and _destroy() (vma_end_read, fput, bpf_iter_mmput_async) * can take spinlocks with IRQs disabled (pi_lock, pool->lock). * Running from NMI or from a tracepoint that fires with those * locks held could deadlock.
@@ -885,7 +885,7 @@ __bpf_kfunc int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it, goto err_cleanup_iter; } - kit->data->locked_vma =NULL ; + kit->data->snapshot.vm_file =NULL ; kit->data->next_addr = addr;return 0 ;
@@ -947,26 +947,45 @@ bpf_iter_task_vma_find_next(struct bpf_iter_task_vma_kern_data *data)return vma; } +static void bpf_iter_task_vma_snapshot_reset (struct vm_area_struct *snap) +{ +if (snap->vm_file) { +fput (snap->vm_file); + snap->vm_file =NULL ; + } +} + __bpf_kfunc struct vm_area_struct *bpf_iter_task_vma_next(struct bpf_iter_task_vma *it) {struct bpf_iter_task_vma_kern *kit = (void *)it; -struct vm_area_struct *vma; +struct vm_area_struct *snap, *vma;if (!kit->data)/* bpf_iter_task_vma_new failed */ return NULL ; -if (kit->data->locked_vma) { -vma_end_read (kit->data->locked_vma); - kit->data->locked_vma =NULL ; - } + snap = &kit->data->snapshot; + +bpf_iter_task_vma_snapshot_reset (snap); vma =bpf_iter_task_vma_find_next (kit->data);if (!vma)return NULL ; - kit->data->locked_vma = vma; +memcpy (snap, vma,sizeof (*snap)); + +/* +* The verifier only trusts vm_mm and vm_file (see +* BTF_TYPE_SAFE_TRUSTED_OR_NULL in verifier.c). Take a reference +* on vm_file; vm_mm is already correct because lock_vma_under_rcu() +* verifies vma->vm_mm == mm. All other pointers are untrusted by +* the verifier and left as-is. +*/ +if (snap->vm_file) +get_file (snap->vm_file); + kit->data->next_addr = vma->vm_end; -return vma; +vma_end_read (vma); +return snap; } __bpf_kfunc void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it)
@@ -974,8 +993,7 @@ __bpf_kfunc void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it)struct bpf_iter_task_vma_kern *kit = (void *)it;if (kit->data) { -if (kit->data->locked_vma) -vma_end_read (kit->data->locked_vma); +bpf_iter_task_vma_snapshot_reset (&kit->data->snapshot);put_task_struct (kit->data->task);bpf_iter_mmput_async (kit->data->mm);bpf_mem_free (&bpf_global_ma, kit->data);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 146/957 bpf: Fix RCU stall in bpf_fd_array_map_clear()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sechang Lim <[email protected]>
[ Upstream commit 4406942e65ca128c56c67443832988873c21d2e9 ]
Add a missing cond_resched() in bpf_fd_array_map_clear() loop.
For PROG_ARRAY maps with many entries this loop calls prog_array_map_poke_run() per entry which can be expensive, and without yielding this can cause RCU stalls under load:
rcu: Stack dump where RCU GP kthread last ran:
CPU: 0 UID: 0 PID: 30932 Comm: kworker/0:2 Not tainted 6.14.0-13195-g967e8def1100 #2 PREEMPT(undef) Workqueue: events prog_array_map_clear_deferred RIP: 0010:write_comp_data+0x38/0x90 kernel/kcov.c:246 Call Trace: <TASK> prog_array_map_poke_run+0x77/0x380 kernel/bpf/arraymap.c:1096 __fd_array_map_delete_elem+0x197/0x310 kernel/bpf/arraymap.c:925 bpf_fd_array_map_clear kernel/bpf/arraymap.c:1000 [inline] prog_array_map_clear_deferred+0x119/0x1b0 kernel/bpf/arraymap.c:1141 process_one_work+0x898/0x19d0 kernel/workqueue.c:3238 process_scheduled_works kernel/workqueue.c:3319 [inline] worker_thread+0x770/0x10b0 kernel/workqueue.c:3400 kthread+0x465/0x880 kernel/kthread.c:464 ret_from_fork+0x4d/0x80 arch/x86/kernel/process.c:153 ret_from_fork_asm+0x19/0x30 arch/x86/entry/entry_64.S:245 </TASK>
--- kernel/bpf/arraymap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/bpf/arraymap.c +3 -1
@@ -1006,8 +1006,10 @@ static void bpf_fd_array_map_clear(struct bpf_map *map, bool need_defer) struct bpf_array *array = container_of(map, struct bpf_array, map);int i; -for (i =0 ; i < array->map.max_entries; i++) +for (i =0 ; i < array->map.max_entries; i++) {__fd_array_map_delete_elem (map, &i, need_defer); +cond_resched (); + } } static void prog_array_map_seq_show_elem(struct bpf_map *map, void *key,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 147/957 net: hamradio: 6pack: fix uninit-value in sixpack_receive_buf
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mashiro Chen <[email protected]>
[ Upstream commit bf9a38803b2626b01cc769aaf13485d8650f576f ]
sixpack_receive_buf() does not properly skip bytes with TTY error flags. The while loop iterates through the flags buffer but never advances the data pointer (cp), and passes the original count (including error bytes) to sixpack_decode(). This causes sixpack_decode() to process bytes that should have been skipped due to TTY errors. The TTY layer does not guarantee that cp[i] holds a meaningful value when fp[i] is set, so passing those positions to sixpack_decode() results in KMSAN reporting an uninit-value read.
Fix this by processing bytes one at a time, advancing cp on each iteration, and only passing valid (non-error) bytes to sixpack_decode(). This matches the pattern used by slip_receive_buf() and mkiss_receive_buf() for the same purpose.
--- drivers/net/hamradio/6pack.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/net/hamradio/6pack.c +4 -5
@@ -391,7 +391,6 @@ static void sixpack_receive_buf(struct tty_struct *tty, const u8 *cp, const u8 *fp, size_t count) {struct sixpack *sp; -size_t count1;if (!count)return ;
@@ -401,16 +400,16 @@ static void sixpack_receive_buf(struct tty_struct *tty, const u8 *cp,return ;/* Read the characters out of the buffer */ - count1 = count; -while (count) { - count--; +while (count--) {if (fp && *fp++) {if (!test_and_set_bit (SIXPF_ERROR , &sp->flags)) sp->dev->stats.rx_errors++; + cp++;continue ; } +sixpack_decode (sp, cp,1 ); + cp++; } -sixpack_decode (sp, cp, count1);tty_unthrottle (tty); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 148/957 net: airoha: Add airoha_ppe_get_num_stats_entries() and airoha_ppe_get_num_total_stats_entries()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 15f357cd4581ce6e02e5e97719320600783140ec ]
Introduce airoha_ppe_get_num_stats_entries and airoha_ppe_get_num_total_stats_entries routines in order to make the code more readable controlling if CONFIG_NET_AIROHA_FLOW_STATS is enabled or disabled.
Modify airoha_ppe_foe_get_flow_stats_index routine signature relying on airoha_ppe_get_num_total_stats_entries().
Stable-dep-of: 02f729643959 ("net: airoha: Fix FE_PSE_BUF_SET configuration if PPE2 is available")
--- drivers/net/ethernet/airoha/airoha_eth.h | 10 +-- drivers/net/ethernet/airoha/airoha_ppe.c | 101 ++++++++++++++++++----- 2 files changed, 81 insertions(+), 30 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.h +2 -8
@@ -50,15 +50,9 @@#define PPE_NUM 2#define PPE1_SRAM_NUM_ENTRIES (8 * 1024) -#define PPE_SRAM_NUM_ENTRIES (2 * PPE1_SRAM_NUM_ENTRIES) -#ifdef CONFIG_NET_AIROHA_FLOW_STATS +#define PPE_SRAM_NUM_ENTRIES (PPE_NUM * PPE1_SRAM_NUM_ENTRIES)#define PPE1_STATS_NUM_ENTRIES (4 * 1024) -#else -#define PPE1_STATS_NUM_ENTRIES 0 -#endif /* CONFIG_NET_AIROHA_FLOW_STATS */ -#define PPE_STATS_NUM_ENTRIES (2 * PPE1_STATS_NUM_ENTRIES) -#define PPE1_SRAM_NUM_DATA_ENTRIES (PPE1_SRAM_NUM_ENTRIES - PPE1_STATS_NUM_ENTRIES) -#define PPE_SRAM_NUM_DATA_ENTRIES (2 * PPE1_SRAM_NUM_DATA_ENTRIES) +#define PPE_STATS_NUM_ENTRIES (PPE_NUM * PPE1_STATS_NUM_ENTRIES)#define PPE_DRAM_NUM_ENTRIES (16 * 1024)#define PPE_NUM_ENTRIES (PPE_SRAM_NUM_ENTRIES + PPE_DRAM_NUM_ENTRIES)#define PPE_HASH_MASK (PPE_NUM_ENTRIES - 1)
drivers/net/ethernet/airoha/airoha_ppe.c +79 -22
183 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 149/957 net: airoha: Add airoha_eth_soc_data struct
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 5863b4e065e2253ef05684f728a04e4972046bcb ]
Introduce airoha_eth_soc_data struct to contain differences between various SoC. Move XSI reset names in airoha_eth_soc_data. This is a preliminary patch to enable AN7583 ethernet controller support in airoha-eth driver.
Stable-dep-of: 02f729643959 ("net: airoha: Fix FE_PSE_BUF_SET configuration if PPE2 is available")
--- drivers/net/ethernet/airoha/airoha_eth.c | 42 +++++++++++++++++++----- drivers/net/ethernet/airoha/airoha_eth.h | 17 ++++++++-- 2 files changed, 48 insertions(+), 11 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +33 -9
@@ -1406,8 +1406,7 @@ static int airoha_hw_init(struct platform_device *pdev,int err, i;/* disable xsi */ - err =reset_control_bulk_assert (ARRAY_SIZE (eth->xsi_rsts), - eth->xsi_rsts); + err =reset_control_bulk_assert (eth->soc->num_xsi_rsts, eth->xsi_rsts);if (err)return err;
@@ -2943,6 +2942,7 @@ static int airoha_register_gdm_devices(struct airoha_eth *eth)static int airoha_probe (struct platform_device *pdev) { +struct reset_control_bulk_data *xsi_rsts;struct device_node *np;struct airoha_eth *eth;int i, err;
@@ -2951,6 +2951,10 @@ static int airoha_probe(struct platform_device *pdev)if (!eth)return -ENOMEM ; + eth->soc =of_device_get_match_data (&pdev->dev); +if (!eth->soc) +return -EINVAL ; + eth->dev = &pdev->dev; err =dma_set_mask_and_coherent (eth->dev,DMA_BIT_MASK (32 ));
@@ -2975,13 +2979,18 @@ static int airoha_probe(struct platform_device *pdev)return err; } - eth->xsi_rsts[0 ].id ="xsi-mac" ; - eth->xsi_rsts[1 ].id ="hsi0-mac" ; - eth->xsi_rsts[2 ].id ="hsi1-mac" ; - eth->xsi_rsts[3 ].id ="hsi-mac" ; - eth->xsi_rsts[4 ].id ="xfp-mac" ; + xsi_rsts =devm_kzalloc (eth->dev, + eth->soc->num_xsi_rsts *sizeof (*xsi_rsts), +GFP_KERNEL ); +if (err) +return err; + + eth->xsi_rsts = xsi_rsts; +for (i =0 ; i < eth->soc->num_xsi_rsts; i++) + eth->xsi_rsts[i].id = eth->soc->xsi_rsts_names[i]; + err =devm_reset_control_bulk_get_exclusive (eth->dev, -ARRAY_SIZE (eth->xsi_rsts), + eth->soc->num_xsi_rsts, eth->xsi_rsts);if (err) {dev_err (eth->dev,"failed to get bulk xsi reset lines\n" );
@@ -3074,8 +3083,23 @@ static void airoha_remove(struct platform_device *pdev)platform_set_drvdata (pdev,NULL ); } +static const char *const en7581_xsi_rsts_names[] = { +"xsi-mac" , +"hsi0-mac" , +"hsi1-mac" , +"hsi-mac" , +"xfp-mac" , +}; + +static const struct airoha_eth_soc_data en7581_soc_data = { + .version =0x7581 , + .xsi_rsts_names = en7581_xsi_rsts_names, + .num_xsi_rsts =ARRAY_SIZE (en7581_xsi_rsts_names), + .num_ppe =2 , +}; +static const struct of_device_id of_airoha_match[] = { - { .compatible ="airoha,en7581-eth" }, + { .compatible ="airoha,en7581-eth" , .data = &en7581_soc_data }, {/* sentinel */ } };MODULE_DEVICE_TABLE (of, of_airoha_match);
drivers/net/ethernet/airoha/airoha_eth.h +15 -2
@@ -21,7 +21,6 @@#define AIROHA_MAX_NUM_IRQ_BANKS 4#define AIROHA_MAX_DSA_PORTS 7#define AIROHA_MAX_NUM_RSTS 3 -#define AIROHA_MAX_NUM_XSI_RSTS 5#define AIROHA_MAX_MTU 9216#define AIROHA_MAX_PACKET_SIZE 2048#define AIROHA_NUM_QOS_CHANNELS 4
@@ -556,9 +555,18 @@ struct airoha_ppe {struct dentry *debugfs_dir; }; +struct airoha_eth_soc_data { +u16 version; +const char *const *xsi_rsts_names; +int num_xsi_rsts; +int num_ppe; +}; +struct airoha_eth {struct device *dev; +const struct airoha_eth_soc_data *soc; +unsigned long state;void __iomem *fe_regs;
@@ -568,7 +576,7 @@ struct airoha_eth {struct rhashtable flow_table;struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS ]; -struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS ]; +struct reset_control_bulk_data *xsi_rsts;struct net_device *napi_dev;
@@ -611,6 +619,11 @@ static inline bool airhoa_is_lan_gdm_port(struct airoha_gdm_port *port)return port->id ==1 ; } +static inline bool airoha_is_7581 (struct airoha_eth *eth) +{ +return eth->soc->version ==0x7581 ; +} +bool airoha_is_valid_gdm_port (struct airoha_eth *eth,struct airoha_gdm_port *port);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 150/957 net: airoha: Generalize airoha_ppe2_is_enabled routine
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit ef9449f080b61920cdc3d3106f8ffc2d9ba8b861 ]
Rename airoha_ppe2_is_enabled() in airoha_ppe_is_enabled() and generalize it in order to check if each PPE module is enabled. Rely on airoha_ppe_is_enabled routine to properly initialize PPE for AN7583 SoC since AN7583 does not support PPE2.
Stable-dep-of: 02f729643959 ("net: airoha: Fix FE_PSE_BUF_SET configuration if PPE2 is available")
--- drivers/net/ethernet/airoha/airoha_eth.c | 32 ++++++++++++++++-------- drivers/net/ethernet/airoha/airoha_eth.h | 1 + drivers/net/ethernet/airoha/airoha_ppe.c | 17 +++++++------ 3 files changed, 32 insertions(+), 18 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +21 -11
@@ -297,8 +297,11 @@ static void airoha_fe_pse_ports_init(struct airoha_eth *eth)int q; all_rsv =airoha_fe_get_pse_all_rsv (eth); -/* hw misses PPE2 oq rsv */ - all_rsv +=PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2 ]; +if (airoha_ppe_is_enabled (eth,1 )) { +/* hw misses PPE2 oq rsv */ + all_rsv +=PSE_RSV_PAGES * + pse_port_num_queues[FE_PSE_PORT_PPE2 ]; + }airoha_fe_set (eth,REG_FE_PSE_BUF_SET , all_rsv);/* CMD1 */
@@ -335,13 +338,17 @@ static void airoha_fe_pse_ports_init(struct airoha_eth *eth)for (q =4 ; q < pse_port_num_queues[FE_PSE_PORT_CDM4 ]; q++)airoha_fe_set_pse_oq_rsv (eth,FE_PSE_PORT_CDM4 , q,PSE_QUEUE_RSV_PAGES ); -/* PPE2 */ -for (q =0 ; q < pse_port_num_queues[FE_PSE_PORT_PPE2 ]; q++) { -if (q < pse_port_num_queues[FE_PSE_PORT_PPE2 ] /2 ) -airoha_fe_set_pse_oq_rsv (eth,FE_PSE_PORT_PPE2 , q, -PSE_QUEUE_RSV_PAGES ); -else -airoha_fe_set_pse_oq_rsv (eth,FE_PSE_PORT_PPE2 , q,0 ); +if (airoha_ppe_is_enabled (eth,1 )) { +/* PPE2 */ +for (q =0 ; q < pse_port_num_queues[FE_PSE_PORT_PPE2 ]; q++) { +if (q < pse_port_num_queues[FE_PSE_PORT_PPE2 ] /2 ) +airoha_fe_set_pse_oq_rsv (eth,FE_PSE_PORT_PPE2 , + q, +PSE_QUEUE_RSV_PAGES ); +else +airoha_fe_set_pse_oq_rsv (eth,FE_PSE_PORT_PPE2 , + q,0 ); + } }/* GMD4 */ for (q =0 ; q < pse_port_num_queues[FE_PSE_PORT_GDM4 ]; q++)
@@ -1781,8 +1788,11 @@ static int airoha_dev_init(struct net_device *dev)airhoha_set_gdm2_loopback (port); fallthrough;case 2 : - pse_port =FE_PSE_PORT_PPE2 ; -break ; +if (airoha_ppe_is_enabled (eth,1 )) { + pse_port =FE_PSE_PORT_PPE2 ; +break ; + } + fallthrough;default : pse_port =FE_PSE_PORT_PPE1 ;break ;
drivers/net/ethernet/airoha/airoha_eth.h +1 -0
@@ -627,6 +627,7 @@ static inline bool airoha_is_7581(struct airoha_eth *eth)bool airoha_is_valid_gdm_port (struct airoha_eth *eth,struct airoha_gdm_port *port); +bool airoha_ppe_is_enabled (struct airoha_eth *eth,int index);void airoha_ppe_check_skb (struct airoha_ppe_dev *dev,struct sk_buff *skb,u16 hash,bool rx_wlan);int airoha_ppe_setup_tc_block_cb (struct airoha_ppe_dev *dev,void *type_data);
drivers/net/ethernet/airoha/airoha_ppe.c +10 -7
@@ -50,9 +50,12 @@ static int airoha_ppe_get_total_num_stats_entries(struct airoha_ppe *ppe)return num_stats; } -static bool airoha_ppe2_is_enabled (struct airoha_eth *eth) +bool airoha_ppe_is_enabled (struct airoha_eth *eth,int index) { -return airoha_fe_rr (eth,REG_PPE_GLO_CFG (1 )) &PPE_GLO_CFG_EN_MASK ; +if (index >= eth->soc->num_ppe) +return false; + +return airoha_fe_rr (eth,REG_PPE_GLO_CFG (index)) &PPE_GLO_CFG_EN_MASK ; }static u32 airoha_ppe_get_timestamp (struct airoha_ppe *ppe)
@@ -120,7 +123,7 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe) AIROHA_MAX_MTU)); } -if (airoha_ppe2_is_enabled (eth)) { +if (airoha_ppe_is_enabled (eth,1 )) { sram_num_entries =PPE1_SRAM_NUM_ENTRIES ; sram_num_stats_entries =airoha_ppe_get_num_stats_entries (ppe);
@@ -520,7 +523,7 @@ static int airoha_ppe_foe_get_flow_stats_index(struct airoha_ppe *ppe,return ppe_num_stats_entries; *index = hash; -if (airoha_ppe2_is_enabled (ppe->eth) && +if (airoha_ppe_is_enabled (ppe->eth,1 ) && hash >= ppe_num_stats_entries) *index = *index -PPE_STATS_NUM_ENTRIES ;
@@ -615,7 +618,7 @@ airoha_ppe_foe_get_entry_locked(struct airoha_ppe *ppe, u32 hash)u32 val;int i; - ppe2 =airoha_ppe2_is_enabled (ppe->eth) && + ppe2 =airoha_ppe_is_enabled (ppe->eth,1 ) && hash >=PPE1_SRAM_NUM_ENTRIES ; airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2), FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) |
@@ -693,7 +696,7 @@ static int airoha_ppe_foe_commit_entry(struct airoha_ppe *ppe,if (hash <PPE_SRAM_NUM_ENTRIES ) {dma_addr_t addr = ppe->foe_dma + hash *sizeof (*hwe); -bool ppe2 =airoha_ppe2_is_enabled (eth) && +bool ppe2 =airoha_ppe_is_enabled (eth,1 ) && hash >=PPE1_SRAM_NUM_ENTRIES ; err = npu->ops.ppe_foe_commit_entry(npu, addr, sizeof(*hwe),
@@ -1288,7 +1291,7 @@ static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe,int i, sram_num_entries =PPE_SRAM_NUM_ENTRIES ;struct airoha_foe_entry *hwe = ppe->foe; -if (airoha_ppe2_is_enabled (ppe->eth)) +if (airoha_ppe_is_enabled (ppe->eth,1 )) sram_num_entries = sram_num_entries /2 ;for (i =0 ; i < sram_num_entries; i++)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 151/957 net: airoha: Fix FE_PSE_BUF_SET configuration if PPE2 is available
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 02f72964395911e7a09bb2ea2fe6f79eda4ea2c2 ]
airoha_fe_set routine is used to set specified bits to 1 in the selected register. In the FE_PSE_BUF_SET case this can due to a overestimation of the required buffers for I/O queues since we can miss to set some bits of PSE_ALLRSV_MASK subfield to 0. Fix the issue relying on airoha_fe_rmw routine instead.
--- drivers/net/ethernet/airoha/airoha_eth.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +5 -3
@@ -293,16 +293,18 @@ static void airoha_fe_pse_ports_init(struct airoha_eth *eth) [FE_PSE_PORT_GDM4] = 2, [FE_PSE_PORT_CDM5] = 2, }; -u32 all_rsv;int q; - all_rsv =airoha_fe_get_pse_all_rsv (eth);if (airoha_ppe_is_enabled (eth,1 )) { +u32 all_rsv; +/* hw misses PPE2 oq rsv */ + all_rsv =airoha_fe_get_pse_all_rsv (eth); all_rsv +=PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2 ]; +airoha_fe_rmw (eth,REG_FE_PSE_BUF_SET ,PSE_ALLRSV_MASK , +FIELD_PREP (PSE_ALLRSV_MASK , all_rsv)); } -airoha_fe_set (eth,REG_FE_PSE_BUF_SET , all_rsv);/* CMD1 */ for (q =0 ; q < pse_port_num_queues[FE_PSE_PORT_CDM1 ]; q++)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 152/957 bpf: Relax scalar id equivalence for state pruning
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Puranjay Mohan <[email protected]>
[ Upstream commit b0388bafa4949bd30af7b3be5ee415f2a25ac014 ]
Scalar register IDs are used by the verifier to track relationships between registers and enable bounds propagation across those relationships. Once an ID becomes singular (i.e. only a single register/stack slot carries it), it can no longer contribute to bounds propagation and effectively becomes stale. The previous commit makes the verifier clear such ids before caching the state.
When comparing the current and cached states for pruning, these stale IDs can cause technically equivalent states to be considered different and thus prevent pruning.
For example, in the selftest added in the next commit, two registers - r6 and r7 are not linked to any other registers and get cached with id=0, in the current state, they are both linked to each other with id=A. Before this commit, check_scalar_ids would give temporary ids to r6 and r7 (say tid1 and tid2) and then check_ids() would map tid1->A, and when it would see tid2->A, it would not consider these state equivalent.
Relax scalar ID equivalence by treating rold->id == 0 as "independent":
if the old state did not rely on any ID relationships for a register, then any ID/linking present in the current state only adds constraints and is always safe to accept for pruning. Implement this by returning true immediately in check_scalar_ids() when old_id == 0.
Maintain correctness for the opposite direction (old_id != 0 && cur_id == 0) by still allocating a temporary ID for cur_id == 0. This avoids incorrectly allowing multiple independent current registers (id==0) to satisfy a single linked old ID during mapping.
Stable-dep-of: 2f2ec8e7730e ("bpf: Enforce regsafe base id consistency for BPF_ADD_CONST scalars")
--- kernel/bpf/verifier.c | 63 +++++++++++++++---- .../selftests/bpf/progs/verifier_scalar_ids.c | 8 ++- 2 files changed, 56 insertions(+), 15 deletions(-)
kernel/bpf/verifier.c +51 -12
@@ -18808,13 +18808,29 @@ static bool check_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap)return false; } -/* Similar to check_ids(), but allocate a unique temporary ID -* for 'old_id' or 'cur_id' of zero. -* This makes pairs like '0 vs unique ID', 'unique ID vs 0' valid. +/* +* Compare scalar register IDs for state equivalence. +* +* When old_id == 0, the old register is independent - not linked to any +* other register. Any linking in the current state only adds constraints, +* making it more restrictive. Since the old state didn't rely on any ID +* relationships for this register, it's always safe to accept cur regardless +* of its ID. Hence, return true immediately. +* +* When old_id != 0 but cur_id == 0, we need to ensure that different +* independent registers in cur don't incorrectly satisfy the ID matching +* requirements of linked registers in old. +* +* Example: if old has r6.id=X and r7.id=X (linked), but cur has r6.id=0 +* and r7.id=0 (both independent), without temp IDs both would map old_id=X +* to cur_id=0 and pass. With temp IDs: r6 maps X->temp1, r7 tries to map +* X->temp2, but X is already mapped to temp1, so the check fails correctly. */ static bool check_scalar_ids (u32 old_id,u32 cur_id,struct bpf_idmap *idmap) { - old_id = old_id ? old_id : ++idmap->tmp_id_gen; +if (!old_id) +return true; + cur_id = cur_id ? cur_id : ++idmap->tmp_id_gen;return check_ids (old_id, cur_id, idmap);
@@ -18975,11 +18991,21 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold, }if (!rold->precise && exact ==NOT_EXACT )return true; -if ((rold->id &BPF_ADD_CONST ) != (rcur->id &BPF_ADD_CONST )) -return false; -if ((rold->id &BPF_ADD_CONST ) && (rold->off != rcur->off)) -return false; -/* Why check_ids() for scalar registers? +/* +* Linked register tracking uses rold->id to detect relationships. +* When rold->id == 0, the register is independent and any linking +* in rcur only adds constraints. When rold->id != 0, we must verify +* id mapping and (for BPF_ADD_CONST) offset consistency. +* +* +------------------+-----------+------------------+---------------+ +* | | rold->id | rold + ADD_CONST | rold->id == 0 | +* |------------------+-----------+------------------+---------------| +* | rcur->id | range,ids | false | range | +* | rcur + ADD_CONST | false | range,ids,off | range | +* | rcur->id == 0 | range,ids | false | range | +* +------------------+-----------+------------------+---------------+ +* +* Why check_ids() for scalar registers? * * Consider the following BPF code: * 1: r6 = ... unbound scalar, ID=a ...
@@ -19003,9 +19029,22 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,* --- * Also verify that new value satisfies old value range knowledge. */ -return range_within (rold, rcur) && -tnum_in (rold->var_off, rcur->var_off) && -check_scalar_ids (rold->id, rcur->id, idmap); + +/* ADD_CONST mismatch: different linking semantics */ +if ((rold->id &BPF_ADD_CONST ) && !(rcur->id &BPF_ADD_CONST )) +return false; + +if (rold->id && !(rold->id &BPF_ADD_CONST ) && (rcur->id &BPF_ADD_CONST )) +return false; + +/* Both have offset linkage: offsets must match */ +if ((rold->id &BPF_ADD_CONST ) && rold->off != rcur->off) +return false; + +if (!check_scalar_ids (rold->id, rcur->id, idmap)) +return false; + +return range_within (rold, rcur) &&tnum_in (rold->var_off, rcur->var_off);case PTR_TO_MAP_KEY :case PTR_TO_MAP_VALUE :case PTR_TO_MEM :
tools/testing/selftests/bpf/progs/verifier_scalar_ids.c +5 -3
@@ -751,9 +751,9 @@ __success __log_level(2)/* The exit instruction should be reachable from two states, * use two matches and "processed .. insns" to ensure this. */ -__msg("13: (95) exit") -__msg("13: (95) exit") -__msg("processed 18 insns") +__msg("15: (95) exit") +__msg("15: (95) exit") +__msg("processed 20 insns")__flag (BPF_F_TEST_STATE_FREQ) __naked void two_old_ids_one_cur_id(void) {
@@ -762,9 +762,11 @@ __naked void two_old_ids_one_cur_id(void)"call %[bpf_ktime_get_ns];" "r0 &= 0xff;" "r6 = r0;" +"r8 = r0;" "call %[bpf_ktime_get_ns];" "r0 &= 0xff;" "r7 = r0;" +"r9 = r0;" "r0 = 0;" /* Maybe make r{6,7} IDs identical */ "if r6 > r7 goto l0_%=;"
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 153/957 bpf: Enforce regsafe base id consistency for BPF_ADD_CONST scalars
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 2f2ec8e7730e21fc9bd49e0de9cdd58213ea24d0 ]
When regsafe() compares two scalar registers that both carry BPF_ADD_CONST, check_scalar_ids() maps their full compound id (aka base | BPF_ADD_CONST flag) as one idmap entry. However, it never verifies that the underlying base ids, that is, with the flag stripped are consistent with existing idmap mappings.
This allows construction of two verifier states where the old state has R3 = R2 + 10 (both sharing base id A) while the current state has R3 = R4 + 10 (base id C, unrelated to R2). The idmap creates two independent entries: A->B (for R2) and A|flag->C|flag (for R3), without catching that A->C conflicts with A->B. State pruning then incorrectly succeeds.
Fix this by additionally verifying base ID mapping consistency whenever BPF_ADD_CONST is set: after mapping the compound ids, also invoke check_ids() on the base IDs (flag bits stripped). This ensures that if A was already mapped to B from comparing the source register, any ADD_CONST derivative must also derive from B, not an unrelated C.
--- kernel/bpf/verifier.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
kernel/bpf/verifier.c +16 -1
@@ -18825,6 +18825,13 @@ static bool check_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap)* and r7.id=0 (both independent), without temp IDs both would map old_id=X * to cur_id=0 and pass. With temp IDs: r6 maps X->temp1, r7 tries to map * X->temp2, but X is already mapped to temp1, so the check fails correctly. +* +* When old_id has BPF_ADD_CONST set, the compound id (base | flag) and the +* base id (flag stripped) must both map consistently. Example: old has +* r2.id=A, r3.id=A|flag (r3 = r2 + delta), cur has r2.id=B, r3.id=C|flag +* (r3 derived from unrelated r4). Without the base check, idmap gets two +* independent entries A->B and A|flag->C|flag, missing that A->C conflicts +* with A->B. The base ID cross-check catches this. */ static bool check_scalar_ids (u32 old_id,u32 cur_id,struct bpf_idmap *idmap) {
@@ -18833,7 +18840,15 @@ static bool check_scalar_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap) cur_id = cur_id ? cur_id : ++idmap->tmp_id_gen; -return check_ids (old_id, cur_id, idmap); +if (!check_ids (old_id, cur_id, idmap)) +return false; +if (old_id &BPF_ADD_CONST ) { + old_id &= ~BPF_ADD_CONST ; + cur_id &= ~BPF_ADD_CONST ; +if (!check_ids (old_id, cur_id, idmap)) +return false; + } +return true; } static void clean_func_state(struct bpf_verifier_env *env,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 154/957 selftests/bpf: fix __jited_unpriv tag name
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eduard Zingerman <[email protected]>
[ Upstream commit cdd54fe98c00549264a92613af6bb0e9a5fd0d1c ]
__jited_unpriv was using "test_jited=" as its tag name, same as the priv variant __jited. Fix by using "test_jited_unpriv=".
--- tools/testing/selftests/bpf/progs/bpf_misc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/progs/bpf_misc.h +1 -1
@@ -137,7 +137,7 @@#define __msg_unpriv (msg) __attribute__((btf_decl_tag("comment:test_expect_msg_unpriv=" XSTR(__COUNTER__) "=" msg)))#define __not_msg_unpriv (msg) __attribute__((btf_decl_tag("comment:test_expect_not_msg_unpriv=" XSTR(__COUNTER__) "=" msg)))#define __xlated_unpriv (msg) __attribute__((btf_decl_tag("comment:test_expect_xlated_unpriv=" XSTR(__COUNTER__) "=" msg))) -#define __jited_unpriv (msg) __attribute__((btf_decl_tag("comment:test_jited=" XSTR(__COUNTER__) "=" msg))) +#define __jited_unpriv (msg) __attribute__((btf_decl_tag("comment:test_jited_unpriv=" XSTR(__COUNTER__) "=" msg)))#define __failure_unpriv __attribute__((btf_decl_tag("comment:test_expect_failure_unpriv")))#define __success_unpriv __attribute__((btf_decl_tag("comment:test_expect_success_unpriv")))#define __log_level (lvl) __attribute__((btf_decl_tag("comment:test_log_level="#lvl)))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 155/957 net/sched: act_ct: Only release RCU read lock after ct_ft
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit f462dca0c8415bf0058d0ffa476354c4476d0f09 ]
When looking up a flow table in act_ct in tcf_ct_flow_table_get(), rhashtable_lookup_fast() internally opens and closes an RCU read critical section before returning ct_ft.
The tcf_ct_flow_table_cleanup_work() can complete before refcount_inc_not_zero() is invoked on the returned ct_ft resulting in a UAF on the already freed ct_ft object. This vulnerability can lead to privilege escalation.
Analysis from [email protected]:
When initializing act_ct, tcf_ct_init() is called, which internally triggers tcf_ct_flow_table_get().
static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
{
struct zones_ht_key key = { .net = net, .zone = params->zone };
struct tcf_ct_flow_table *ct_ft;
int err = -ENOMEM;
mutex_lock(&zones_mutex);
ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params); // [1]
if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) // [2]
goto out_unlock;
...
}static __always_inline void *rhashtable_lookup_fast(
struct rhashtable *ht, const void *key, const struct rhashtable_params params)
{
void *obj;
rcu_read_lock();
obj = rhashtable_lookup(ht, key, params);
rcu_read_unlock();
return obj;
}At [1], rhashtable_lookup_fast() looks up and returns the corresponding ct_ft from zones_ht . The lookup is performed within an RCU read critical section through rcu_read_lock() / rcu_read_unlock(), which prevents the object from being freed. However, at the point of function return, rcu_read_unlock() has already been called, and there is nothing preventing ct_ft from being freed before reaching refcount_inc_not_zero(&ct_ft->ref) at [2]. This interval becomes the race window, during which ct_ft can be freed.
Free Process:
tcf_ct_flow_table_put() is executed through the path tcf_ct_cleanup() call_rcu() tcf_ct_params_free_rcu() tcf_ct_params_free() tcf_ct_flow_table_put().
static void tcf_ct_flow_table_put(struct tcf_ct_flow_table *ct_ft)
{
if (refcount_dec_and_test(&ct_ft->ref)) {
rhashtable_remove_fast(&zones_ht, &ct_ft->node, zones_params);
INIT_RCU_WORK(&ct_ft->rwork, tcf_ct_flow_table_cleanup_work); // [3]
queue_rcu_work(act_ct_wq, &ct_ft->rwork);
}
}At [3], tcf_ct_flow_table_cleanup_work() is scheduled as RCU work
static void tcf_ct_flow_table_cleanup_work(struct work_struct *work)
{
struct tcf_ct_flow_table *ct_ft;
struct flow_block *block;
ct_ft = container_of(to_rcu_work(work), struct tcf_ct_flow_table,
rwork);
nf_flow_table_free(&ct_ft->nf_ft);
block = &ct_ft->nf_ft.flow_block;
down_write(&ct_ft->nf_ft.flow_block_lock);
WARN_ON(!list_empty(&block->cb_list));
up_write(&ct_ft->nf_ft.flow_block_lock);
kfree(ct_ft); // [4]
module_put(THIS_MODULE);
}tcf_ct_flow_table_cleanup_work() frees ct_ft at [4]. When this function executes between [1] and [2], UAF occurs.
This race condition has a very short race window, making it generally difficult to trigger. Therefore, to trigger the vulnerability an msleep(100) was inserted after[1]
--- net/sched/act_ct.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
net/sched/act_ct.c +6 -2
@@ -326,9 +326,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)int err = -ENOMEM ;mutex_lock (&zones_mutex); - ct_ft =rhashtable_lookup_fast (&zones_ht, &key, zones_params); -if (ct_ft &&refcount_inc_not_zero (&ct_ft->ref)) +rcu_read_lock (); + ct_ft =rhashtable_lookup (&zones_ht, &key, zones_params); +if (ct_ft &&refcount_inc_not_zero (&ct_ft->ref)) { +rcu_read_unlock (); goto out_unlock; + } +rcu_read_unlock (); ct_ft =kzalloc (sizeof (*ct_ft),GFP_KERNEL );if (!ct_ft)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 156/957 selftests: netfilter: nft_tproxy.sh: adjust to socat changes
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 61119542663cac70898aef532eb57ee41ea9b477 ]
Like e65d8b6f3092 ("selftests: drv-net: adjust to socat changes") we need to add shut-none for this test too.
The extra 0-packet can trigger a second (unexpected) reply from the server.
--- .../selftests/net/netfilter/nft_tproxy_udp.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
tools/testing/selftests/net/netfilter/nft_tproxy_udp.sh +7 -7
@@ -190,13 +190,13 @@ table inet filter { } EOF - timeout "$timeout" ip netns exec "$nsrouter" socat -u "$socat_ipproto" udp-listen:12345,fork,ip-transparent,reuseport udp:"$ns1_ip_port",ip-transparent,reuseport,bind="$ns2_ip_port" 2>/dev/null & + timeout "$timeout" ip netns exec "$nsrouter" socat -u "$socat_ipproto" udp-listen:12345,fork,ip-transparent,reuseport,shut-none udp:"$ns1_ip_port",ip-transparent,reuseport,bind="$ns2_ip_port",shut-none 2>/dev/null & local tproxy_pid=$! - timeout "$timeout" ip netns exec "$ns2" socat "$socat_ipproto" udp-listen:8080,fork SYSTEM:"echo PONG_NS2" 2>/dev/null & + timeout "$timeout" ip netns exec "$ns2" socat "$socat_ipproto" udp-listen:8080,fork,shut-none SYSTEM:"echo PONG_NS2" 2>/dev/null & local server2_pid=$! - timeout "$timeout" ip netns exec "$ns3" socat "$socat_ipproto" udp-listen:8080,fork SYSTEM:"echo PONG_NS3" 2>/dev/null & + timeout "$timeout" ip netns exec "$ns3" socat "$socat_ipproto" udp-listen:8080,fork,shut-none SYSTEM:"echo PONG_NS3" 2>/dev/null & local server3_pid=$! busywait "$BUSYWAIT_TIMEOUT" listener_ready "$nsrouter" 12345 "-u"
@@ -205,7 +205,7 @@ EOF local result # request from ns1 to ns2 (forwarded traffic) - result=$(echo I_M_PROXIED | ip netns exec "$ns1" socat -t 2 -T 2 STDIO udp:"$ns2_ip_port",sourceport=18888) + result=$(echo I_M_PROXIED | ip netns exec "$ns1" socat -t 2 -T 2 STDIO udp:"$ns2_ip_port",sourceport=18888,shut-none) if [ "$result" == "$expect_ns1_ns2" ] ;then echo "PASS: tproxy test $testname: ns1 got reply \"$result\" connecting to ns2" else
@@ -214,7 +214,7 @@ EOF fi # request from ns1 to ns3 (forwarded traffic) - result=$(echo I_M_PROXIED | ip netns exec "$ns1" socat -t 2 -T 2 STDIO udp:"$ns3_ip_port") + result=$(echo I_M_PROXIED | ip netns exec "$ns1" socat -t 2 -T 2 STDIO udp:"$ns3_ip_port",shut-none) if [ "$result" = "$expect_ns1_ns3" ] ;then echo "PASS: tproxy test $testname: ns1 got reply \"$result\" connecting to ns3" else
@@ -223,7 +223,7 @@ EOF fi # request from nsrouter to ns2 (localy originated traffic) - result=$(echo I_M_PROXIED | ip netns exec "$nsrouter" socat -t 2 -T 2 STDIO udp:"$ns2_ip_port") + result=$(echo I_M_PROXIED | ip netns exec "$nsrouter" socat -t 2 -T 2 STDIO udp:"$ns2_ip_port",shut-none) if [ "$result" == "$expect_nsrouter_ns2" ] ;then echo "PASS: tproxy test $testname: nsrouter got reply \"$result\" connecting to ns2" else
@@ -232,7 +232,7 @@ EOF fi # request from nsrouter to ns3 (localy originated traffic) - result=$(echo I_M_PROXIED | ip netns exec "$nsrouter" socat -t 2 -T 2 STDIO udp:"$ns3_ip_port") + result=$(echo I_M_PROXIED | ip netns exec "$nsrouter" socat -t 2 -T 2 STDIO udp:"$ns3_ip_port",shut-none) if [ "$result" = "$expect_nsrouter_ns3" ] ;then echo "PASS: tproxy test $testname: nsrouter got reply \"$result\" connecting to ns3" else
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 157/957 net: mana: Use pci_name() for debugfs directory naming
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Erni Sri Satya Vennela <[email protected]>
[ Upstream commit c116f07ab9d22bb6f355f3cf9e44c1e6a47fe559 ]
Use pci_name(pdev) for the per-device debugfs directory instead of hardcoded "0" for PFs and pci_slot_name(pdev->slot) for VFs. The previous approach had two issues:
1. pci_slot_name() dereferences pdev->slot, which can be NULL for VFs in environments like generic VFIO passthrough or nested KVM, causing a NULL pointer dereference.
2. Multiple PFs would all use "0", and VFs across different PCI domains or buses could share the same slot name, leading to -EEXIST errors from debugfs_create_dir().
pci_name(pdev) returns the unique BDF address, is always valid, and is unique across the system.
--- drivers/net/ethernet/microsoft/mana/gdma_main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/net/ethernet/microsoft/mana/gdma_main.c +2 -5
@@ -1927,11 +1927,8 @@ static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent) gc->dev = &pdev->dev;xa_init (&gc->irq_contexts); -if (gc->is_pf) - gc->mana_pci_debugfs =debugfs_create_dir ("0" , mana_debugfs_root); -else - gc->mana_pci_debugfs =debugfs_create_dir (pci_slot_name (pdev->slot), - mana_debugfs_root); + gc->mana_pci_debugfs =debugfs_create_dir (pci_name (pdev), + mana_debugfs_root); err =mana_gd_setup (pdev);if (err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 158/957 net: mana: Support HW link state events
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haiyang Zhang <[email protected]>
[ Upstream commit 54133f9b4b53ffa2204eb27cfc9d50072c9a52d2 ]
Handle the NIC hardware link state events received from the HW channel, then set the proper link state accordingly.
And, add a feature bit, GDMA_DRV_CAP_FLAG_1_HW_VPORT_LINK_AWARE, to inform the NIC hardware this handler exists.
Our MANA NIC only sends out the link state down/up messages when we need to let the VM rerun DHCP client and change IP address. So, add netif_carrier_on() in the probe(), let the NIC show the right initial state in /sys/class/net/ethX/operstate.
Stable-dep-of: 3b7c7fc97aea ("net: mana: Move current_speed debugfs file to mana_init_port()")
--- .../net/ethernet/microsoft/mana/gdma_main.c | 1 + .../net/ethernet/microsoft/mana/hw_channel.c | 12 +++++ drivers/net/ethernet/microsoft/mana/mana_en.c | 54 +++++++++++++++++-- include/net/mana/gdma.h | 4 +- include/net/mana/hw_channel.h | 2 + include/net/mana/mana.h | 4 ++ 6 files changed, 71 insertions(+), 6 deletions(-)
drivers/net/ethernet/microsoft/mana/gdma_main.c +1 -0
@@ -528,6 +528,7 @@ static void mana_gd_process_eqe(struct gdma_queue *eq)case GDMA_EQE_HWC_INIT_DONE :case GDMA_EQE_HWC_SOC_SERVICE :case GDMA_EQE_RNIC_QP_FATAL : +case GDMA_EQE_HWC_SOC_RECONFIG_DATA :if (!eq->eq.callback)break ;
drivers/net/ethernet/microsoft/mana/hw_channel.c +12 -0
@@ -118,6 +118,7 @@ static void mana_hwc_init_event_handler(void *ctx, struct gdma_queue *q_self,struct gdma_dev *gd = hwc->gdma_dev;union hwc_init_type_data type_data;union hwc_init_eq_id_db eq_db; +struct mana_context *ac;u32 type, val;int ret;
@@ -196,6 +197,17 @@ static void mana_hwc_init_event_handler(void *ctx, struct gdma_queue *q_self, hwc->hwc_timeout = val;break ; +case HWC_DATA_HW_LINK_CONNECT : +case HWC_DATA_HW_LINK_DISCONNECT : + ac = gd->gdma_context->mana.driver_data; +if (!ac) +break ; + +WRITE_ONCE (ac->link_event, type); +schedule_work (&ac->link_change_work); + +break ; +default :dev_warn (hwc->dev,"Received unknown reconfig type %u\n" , type);break ;
drivers/net/ethernet/microsoft/mana/mana_en.c +49 -5
108 lines not on this page · raw message
include/net/mana/gdma.h +3 -1
@@ -590,6 +590,7 @@ enum {/* Driver can self reset on FPGA Reconfig EQE notification */ #define GDMA_DRV_CAP_FLAG_1_HANDLE_RECONFIG_EQE BIT(17) +#define GDMA_DRV_CAP_FLAG_1_HW_VPORT_LINK_AWARE BIT(6)#define GDMA_DRV_CAP_FLAGS1 \ (GDMA_DRV_CAP_FLAG_1_EQ_SHARING_MULTI_VPORT | \
@@ -599,7 +600,8 @@ enum {GDMA_DRV_CAP_FLAG_1_DEV_LIST_HOLES_SUP | \GDMA_DRV_CAP_FLAG_1_DYNAMIC_IRQ_ALLOC_SUPPORT | \GDMA_DRV_CAP_FLAG_1_SELF_RESET_ON_EQE | \ - GDMA_DRV_CAP_FLAG_1_HANDLE_RECONFIG_EQE) +GDMA_DRV_CAP_FLAG_1_HANDLE_RECONFIG_EQE | \ + GDMA_DRV_CAP_FLAG_1_HW_VPORT_LINK_AWARE) #define GDMA_DRV_CAP_FLAGS2 0
include/net/mana/hw_channel.h +2 -0
@@ -24,6 +24,8 @@#define HWC_INIT_DATA_PF_DEST_CQ_ID 11#define HWC_DATA_CFG_HWC_TIMEOUT 1 +#define HWC_DATA_HW_LINK_CONNECT 2 +#define HWC_DATA_HW_LINK_DISCONNECT 3#define HW_CHANNEL_WAIT_RESOURCE_TIMEOUT_MS 30000
include/net/mana/mana.h +4 -0
@@ -477,6 +477,10 @@ struct mana_context {struct dentry *mana_eqs_debugfs;struct net_device *ports[MAX_PORTS_IN_MANA_DEV ]; + +/* Link state change work */ +struct work_struct link_change_work; +u32 link_event; };struct mana_port_context {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 159/957 net: mana: Move current_speed debugfs file to mana_init_port()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Erni Sri Satya Vennela <[email protected]>
[ Upstream commit 3b7c7fc97aea7b4048001d12f45777201c74a17f ]
Move the current_speed debugfs file creation from mana_probe_port() to mana_init_port(). The file was previously created only during initial probe, but mana_cleanup_port_context() removes the entire vPort debugfs directory during detach/attach cycles. Since mana_init_port() recreates the directory on re-attach, moving current_speed here ensures it survives these cycles.
--- drivers/net/ethernet/microsoft/mana/mana_en.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_en.c +2 -2
@@ -3038,6 +3038,8 @@ static int mana_init_port(struct net_device *ndev)eth_hw_addr_set (ndev, apc->mac_addr);sprintf (vport,"vport%d" , port_idx); apc->mana_port_debugfs =debugfs_create_dir (vport, gc->mana_pci_debugfs); +debugfs_create_u32 ("current_speed" ,0400 , apc->mana_port_debugfs, + &apc->speed);return 0 ; reset_apc:
@@ -3310,8 +3312,6 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,netif_carrier_on (ndev); -debugfs_create_u32 ("current_speed" ,0400 , apc->mana_port_debugfs, &apc->speed); -return 0 ; free_indir:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 160/957 net: airoha: Add missing RX_CPU_IDX() configuration in airoha_qdma_cleanup_rx_queue()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 656121b155030086b01cfce9bd31b0c925ee6860 ]
When the descriptor index written in REG_RX_CPU_IDX() is equal to the one stored in REG_RX_DMA_IDX(), the hw will stop since the QDMA RX ring is empty.
Add missing REG_RX_CPU_IDX() configuration in airoha_qdma_cleanup_rx_queue routine during QDMA RX ring cleanup.
--- drivers/net/ethernet/airoha/airoha_eth.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/net/ethernet/airoha/airoha_eth.c +5 -0
@@ -844,6 +844,11 @@ static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q) } q->head = q->tail; +/* Set RX_DMA_IDX to RX_CPU_IDX to notify the hw the QDMA RX ring is +* empty. +*/ +airoha_qdma_rmw (qdma,REG_RX_CPU_IDX (qid),RX_RING_CPU_IDX_MASK , +FIELD_PREP (RX_RING_CPU_IDX_MASK , q->head));airoha_qdma_rmw (qdma,REG_RX_DMA_IDX (qid),RX_RING_DMA_IDX_MASK ,FIELD_PREP (RX_RING_DMA_IDX_MASK , q->tail)); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 161/957 bpf: Allow instructions with arena source and non-arena dest registers
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Emil Tsalapatis <[email protected]>
[ Upstream commit ac61bffe91d4bda08806e12957c6d64756d042db ]
The compiler sometimes stores the result of a PTR_TO_ARENA and SCALAR operation into the scalar register rather than the pointer register. Relax the verifier to allow operations between a source arena register and a destination non-arena register, marking the destination's value as a PTR_TO_ARENA.
--- kernel/bpf/verifier.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
kernel/bpf/verifier.c +11 -3
@@ -15705,11 +15705,20 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,int err; dst_reg = ®s[insn->dst_reg]; - src_reg =NULL ; +if (BPF_SRC (insn->code) ==BPF_X ) + src_reg = ®s[insn->src_reg]; +else + src_reg =NULL ; -if (dst_reg->type ==PTR_TO_ARENA ) { +/* Case where at least one operand is an arena. */ +if (dst_reg->type ==PTR_TO_ARENA || (src_reg && src_reg->type ==PTR_TO_ARENA )) {struct bpf_insn_aux_data *aux =cur_aux (env); +if (dst_reg->type !=PTR_TO_ARENA ) + *dst_reg = *src_reg; + + dst_reg->subreg_def = env->insn_idx +1 ; +if (BPF_CLASS (insn->code) ==BPF_ALU64 )/* * 32-bit operations zero upper bits automatically.
@@ -15725,7 +15734,6 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env, ptr_reg = dst_reg;if (BPF_SRC (insn->code) ==BPF_X ) { - src_reg = ®s[insn->src_reg];if (src_reg->type !=SCALAR_VALUE ) {if (dst_reg->type !=SCALAR_VALUE ) {/* Combining two pointers by any ALU op yields
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 162/957 selftests/bpf: Fix reg_bounds to match new tnum-based refinement
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Chaignon <[email protected]>
[ Upstream commit 2fefa9c81a25534464911447d51ddb44b04a8e5b ]
Commit efc11a667878 ("bpf: Improve bounds when tnum has a single possible value") improved the bounds refinement to detect when the tnum and u64 range overlap in a single value (and the bounds can thus be set to that value).
Eduard then noticed that it broke the slow-mode reg_bounds selftests because they don't have an equivalent logic and are therefore unable to refine the bounds as much as the verifier. The following test case illustrates this.
ACTUAL TRUE1: scalar(u64=0xffffffff00000000,u32=0,s64=0xffffffff00000000,s32=0)
EXPECTED TRUE1: scalar(u64=[0xfffffffe00000001; 0xffffffff00000000],u32=0,s64=[0xfffffffe00000001; 0xffffffff00000000],s32=0) [...]
#323/1007 reg_bounds_gen_consts_s64_s32/(s64)[0xfffffffe00000001; 0xffffffff00000000] (s32)<op> S64_MIN:FAIL
with the verifier logs:
[...]
19: w0 = w6 ; R0=scalar(smin=0,smax=umax=0xffffffff,
var_off=(0x0; 0xffffffff))
R6=scalar(smin=0xfffffffe00000001,smax=0xffffffff00000000,
umin=0xfffffffe00000001,umax=0xffffffff00000000,
var_off=(0xfffffffe00000000; 0x1ffffffff)) 20: w0 = w7 ; R0=0 R7=0x8000000000000000
21: if w6 == w7 goto pc+3
[...]
from 21 to 25: [...]
25: w0 = w6 ; R0=0 R6=0xffffffff00000000
; ^
; unexpected refined value
26: w0 = w7 ; R0=0 R7=0x8000000000000000
27: exit
When w6 == w7 is true, the verifier can deduce that the R6's tnum is equal to (0xfffffffe00000000; 0x100000000) and then use that information to refine the bounds: the tnum only overlap with the u64 range in 0xffffffff00000000. The reg_bounds selftest doesn't know about tnums and therefore fails to perform the same refinement.
This issue happens when the tnum carries information that cannot be represented in the ranges, as otherwise the selftest could reach the same refined value using just the ranges. The tnum thus needs to represent non-contiguous values (ex., R6's tnum above, after the condition). The only way this can happen in the reg_bounds selftest is at the boundary between the 32 and 64bit ranges. We therefore only need to handle that case.
This patch fixes the selftest refinement logic by checking if the u32 and u64 ranges overlap in a single value. If so, the ranges can be set to that value. We need to handle two cases: either they overlap in umin64...
u64 values
matching u32 range: xxx xxx xxx xxx
|--------------------------------------| u64 range: 0 xxxxx UMAX64
or in umax64:
u64 values
matching u32 range: xxx xxx xxx xxx
|--------------------------------------| u64 range: 0 xxxxx UMAX64
To detect the first case, we decrease umax64 to the maximum value that matches the u32 range. If that happens to be umin64, then umin64 is the only overlap. We proceed similarly for the second case, increasing umin64 to the minimum value that matches the u32 range.
Note this is similar to how the verifier handles the general case using tnum, but we don't need to care about a single-value overlap in the middle of the range. That case is not possible when comparing two ranges.
This patch also adds two test cases reproducing this bug as part of the normal test runs (without SLOW_TESTS=1).
--- .../selftests/bpf/prog_tests/reg_bounds.c | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+)
tools/testing/selftests/bpf/prog_tests/reg_bounds.c +35 -0
@@ -500,6 +500,39 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t, (s64)x.a >= S32_MIN && (s64)x.b <= S32_MAX)return range_intersection (x_t, x, y_cast); +if (y_t ==U32 && x_t ==U64 ) { +u64 xmin_swap, xmax_swap, xmin_lower32, xmax_lower32; + + xmin_lower32 = x.a &0xffffffff ; + xmax_lower32 = x.b &0xffffffff ; +if (xmin_lower32 < y.a || xmin_lower32 > y.b) { +/* The 32 lower bits of the umin64 are outside the u32 +* range. Let's update umin64 to match the u32 range. +* We want to *increase* the umin64 to the *minimum* +* value that matches the u32 range. +*/ + xmin_swap =swap_low32 (x.a, y.a); +/* We should always only increase the minimum, so if +* the new value is lower than before, we need to +* increase the 32 upper bits by 1. +*/ +if (xmin_swap < x.a) + xmin_swap +=0x100000000 ; +if (xmin_swap == x.b) +return range (x_t, x.b, x.b); + }else if (xmax_lower32 < y.a || xmax_lower32 > y.b) { +/* Same for the umax64, but we want to *decrease* +* umax64 to the *maximum* value that matches the u32 +* range. +*/ + xmax_swap =swap_low32 (x.b, y.b); +if (xmax_swap > x.b) + xmax_swap -=0x100000000 ; +if (xmax_swap == x.a) +return range (x_t, x.a, x.a); + } + } +/* the case when new range knowledge, *y*, is a 32-bit subregister * range, while previous range knowledge, *x*, is a full register * 64-bit range, needs special treatment to take into account upper 32
@@ -2143,6 +2176,8 @@ static struct subtest_case crafted_cases[] = { {U64, S64, {0x7fffffff00000001ULL, 0xffffffff00000000ULL}, {0, 0}}, {U64, S64, {0, 0xffffffffULL}, {1, 1}}, {U64, S64, {0, 0xffffffffULL}, {0x7fffffff, 0x7fffffff}}, + {U64, S32, {0xfffffffe00000001, 0xffffffff00000000}, {S64_MIN, S64_MIN}}, + {U64, U32, {0xfffffffe00000000, U64_MAX - 1}, {U64_MAX, U64_MAX}}, {U64, U32, {0, 0x100000000}, {0, 0}}, {U64, U32, {0xfffffffe, 0x300000000}, {0x80000000, 0x80000000}},
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 163/957 net/rds: Optimize rds_ib_laddr_check
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Håkon Bugge <[email protected]>
[ Upstream commit 236f718ac885965fa886440b9898dfae185c9733 ]
rds_ib_laddr_check() creates a CM_ID and attempts to bind the address in question to it. This in order to qualify the allegedly local address as a usable IB/RoCE address.
In the field, ExaWatcher runs rds-ping to all ports in the fabric from all local ports. This using all active ToS'es. In a full rack system, we have 14 cell servers and eight db servers. Typically, 6 ToS'es are used. This implies 528 rds-ping invocations per ExaWatcher's "RDSinfo" interval.
Adding to this, each rds-ping invocation creates eight sockets and binds the local address to them:
socket(AF_RDS, SOCK_SEQPACKET, 0) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 4
bind(4, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 5
bind(5, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 6
bind(6, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 7
bind(7, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 8
bind(8, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 9
bind(9, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0) = 10
bind(10, {sa_family=AF_INET, sin_port=htons(0),
sin_addr=inet_addr("192.168.36.2")}, 16) = 0So, at every interval ExaWatcher executes rds-ping's, 4224 CM_IDs are allocated, considering this full-rack system. After the a CM_ID has been allocated, rdma_bind_addr() is called, with the port number being zero. This implies that the CMA will attempt to search for an un-used ephemeral port. Simplified, the algorithm is to start at a random position in the available port space, and then if needed, iterate until an un-used port is found.
The book-keeping of used ports uses the idr system, which again uses slab to allocate new struct idr_layer's. The size is 2092 bytes and slab tries to reduce the wasted space. Hence, it chooses an order:3 allocation, for which 15 idr_layer structs will fit and only 1388 bytes are wasted per the 32KiB order:3 chunk.
Although this order:3 allocation seems like a good space/speed trade-off, it does not resonate well with how it used by the CMA. The combination of the randomized starting point in the port space (which has close to zero spatial locality) and the close proximity in time of the 4224 invocations of the rds-ping's, creates a memory hog for order:3 allocations.
These costly allocations may need reclaims and/or compaction. At worst, they may fail and produce a stack trace such as (from uek4):
[<ffffffff811a72d5>] __inc_zone_page_state+0x35/0x40 [<ffffffff811c2e97>] page_add_file_rmap+0x57/0x60 [<ffffffffa37ca1df>] remove_migration_pte+0x3f/0x3c0 [ksplice_6cn872bt_vmlinux_new] [<ffffffff811c3de8>] rmap_walk+0xd8/0x340 [<ffffffff811e8860>] remove_migration_ptes+0x40/0x50 [<ffffffff811ea83c>] migrate_pages+0x3ec/0x890 [<ffffffff811afa0d>] compact_zone+0x32d/0x9a0 [<ffffffff811b00ed>] compact_zone_order+0x6d/0x90 [<ffffffff811b03b2>] try_to_compact_pages+0x102/0x270 [<ffffffff81190e56>] __alloc_pages_direct_compact+0x46/0x100 [<ffffffff8119165b>] __alloc_pages_nodemask+0x74b/0xaa0 [<ffffffff811d8411>] alloc_pages_current+0x91/0x110 [<ffffffff811e3b0b>] new_slab+0x38b/0x480 [<ffffffffa41323c7>] __slab_alloc+0x3b7/0x4a0 [ksplice_s0dk66a8_vmlinux_new] [<ffffffff811e42ab>] kmem_cache_alloc+0x1fb/0x250 [<ffffffff8131fdd6>] idr_layer_alloc+0x36/0x90 [<ffffffff8132029c>] idr_get_empty_slot+0x28c/0x3d0 [<ffffffff813204ad>] idr_alloc+0x4d/0xf0 [<ffffffffa051727d>] cma_alloc_port+0x4d/0xa0 [rdma_cm] [<ffffffffa0517cbe>] rdma_bind_addr+0x2ae/0x5b0 [rdma_cm] [<ffffffffa09d8083>] rds_ib_laddr_check+0x83/0x2c0 [ksplice_6l2xst5i_rds_rdma_new] [<ffffffffa05f892b>] rds_trans_get_preferred+0x5b/0xa0 [rds] [<ffffffffa05f09f2>] rds_bind+0x212/0x280 [rds] [<ffffffff815b4016>] SYSC_bind+0xe6/0x120 [<ffffffff815b4d3e>] SyS_bind+0xe/0x10 [<ffffffff816b031a>] system_call_fastpath+0x18/0xd4
To avoid these excessive calls to rdma_bind_addr(), we optimize rds_ib_laddr_check() by simply checking if the address in question has been used before. The rds_rdma module keeps track of addresses associated with IB devices, and the function rds_ib_get_device() is used to determine if the address already has been qualified as a valid local address. If not found, we call the legacy rds_ib_laddr_check(), now renamed to rds_ib_laddr_check_cm().
Stable-dep-of: ebf71dd4aff4 ("net/rds: Restrict use of RDS/IB to the initial network namespace")
--- net/rds/ib.c | 20 ++++++++++++++++++-- net/rds/ib.h | 1 + net/rds/ib_rdma.c | 2 +- 3 files changed, 20 insertions(+), 3 deletions(-)
net/rds/ib.c +18 -2
@@ -403,8 +403,8 @@ static void rds6_ib_ic_info(struct socket *sock, unsigned int len,* allowed to influence which paths have priority. We could call userspace * asserting this policy "routing". */ -static int rds_ib_laddr_check (struct net *net,const struct in6_addr *addr, -__u32 scope_id) +static int rds_ib_laddr_check_cm (struct net *net,const struct in6_addr *addr, +__u32 scope_id) {int ret;struct rdma_cm_id *cm_id;
@@ -489,6 +489,22 @@ static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr,return ret; } +static int rds_ib_laddr_check (struct net *net,const struct in6_addr *addr, +__u32 scope_id) +{ +struct rds_ib_device *rds_ibdev =NULL ; + +if (ipv6_addr_v4mapped (addr)) { + rds_ibdev =rds_ib_get_device (addr->s6_addr32[3 ]); +if (rds_ibdev) { +rds_ib_dev_put (rds_ibdev); +return 0 ; + } + } + +return rds_ib_laddr_check_cm (net, addr, scope_id); +} +static void rds_ib_unregister_client (void ) {ib_unregister_client (&rds_ib_client);
net/rds/ib.h +1 -0
@@ -381,6 +381,7 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn,__rds_ib_conn_error (conn,KERN_WARNING "RDS/IB: " fmt) /* ib_rdma.c */ +struct rds_ib_device *rds_ib_get_device (__be32 ipaddr);int rds_ib_update_ipaddr (struct rds_ib_device *rds_ibdev,struct in6_addr *ipaddr);void rds_ib_add_conn (struct rds_ib_device *rds_ibdev,struct rds_connection *conn);
net/rds/ib_rdma.c +1 -1
@@ -43,7 +43,7 @@ struct workqueue_struct *rds_ib_mr_wq;static void rds_ib_odp_mr_worker (struct work_struct *work); -static struct rds_ib_device *rds_ib_get_device (__be32 ipaddr) +struct rds_ib_device *rds_ib_get_device (__be32 ipaddr) {struct rds_ib_device *rds_ibdev;struct rds_ib_ipaddr *i_ipaddr;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 164/957 net/rds: Restrict use of RDS/IB to the initial network namespace
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Jumper <[email protected]>
[ Upstream commit ebf71dd4aff46e8e421d455db3e231ba43d2fa8a ]
Prevent using RDS/IB in network namespaces other than the initial one. The existing RDS/IB code will not work properly in non-initial network namespaces.
--- net/rds/af_rds.c | 10 ++++++++-- net/rds/ib.c | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-)
net/rds/af_rds.c +8 -2
@@ -357,7 +357,8 @@ static int rds_cong_monitor(struct rds_sock *rs, sockptr_t optval, int optlen)return ret; } -static int rds_set_transport (struct rds_sock *rs,sockptr_t optval,int optlen) +static int rds_set_transport (struct net *net,struct rds_sock *rs, +sockptr_t optval,int optlen) {int t_type;
@@ -373,6 +374,10 @@ static int rds_set_transport(struct rds_sock *rs, sockptr_t optval, int optlen)if (t_type <0 || t_type >=RDS_TRANS_COUNT )return -EINVAL ; +/* RDS/IB is restricted to the initial network namespace */ +if (t_type !=RDS_TRANS_TCP && !net_eq (net, &init_net)) +return -EPROTOTYPE ; + rs->rs_transport =rds_trans_get (t_type);return rs->rs_transport ?0 : -ENOPROTOOPT ;
@@ -433,6 +438,7 @@ static int rds_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval, unsigned int optlen) {struct rds_sock *rs =rds_sk_to_rs (sock->sk); +struct net *net =sock_net (sock->sk);int ret;if (level !=SOL_RDS ) {
@@ -461,7 +467,7 @@ static int rds_setsockopt(struct socket *sock, int level, int optname,break ;case SO_RDS_TRANSPORT :lock_sock (sock->sk); - ret =rds_set_transport (rs, optval, optlen); + ret =rds_set_transport (net, rs, optval, optlen);release_sock (sock->sk);break ;case SO_TIMESTAMP_OLD :
net/rds/ib.c +4 -0
@@ -494,6 +494,10 @@ static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr, {struct rds_ib_device *rds_ibdev =NULL ; +/* RDS/IB is restricted to the initial network namespace */ +if (!net_eq (net, &init_net)) +return -EPROTOTYPE ; +if (ipv6_addr_v4mapped (addr)) { rds_ibdev =rds_ib_get_device (addr->s6_addr32[3 ]);if (rds_ibdev) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 165/957 bpf: Fix OOB in pcpu_init_value
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lang Xu <[email protected]>
[ Upstream commit 576afddfee8d1108ee299bf10f581593540d1a36 ]
An out-of-bounds read occurs when copying element from a BPF_MAP_TYPE_CGROUP_STORAGE map to another pcpu map with the same value_size that is not rounded up to 8 bytes.
The issue happens when:
1. A CGROUP_STORAGE map is created with value_size not aligned to 8 bytes (e.g., 4 bytes)
2. A pcpu map is created with the same value_size (e.g., 4 bytes)
3. Update element in 2 with data in 1
pcpu_init_value assumes that all sources are rounded up to 8 bytes, and invokes copy_map_value_long to make a data copy, However, the assumption doesn't stand since there are some cases where the source may not be rounded up to 8 bytes, e.g., CGROUP_STORAGE, skb->data. the verifier verifies exactly the size that the source claims, not the size rounded up to 8 bytes by kernel, an OOB happens when the source has only 4 bytes while the copy size(4) is rounded up to 8.
--- kernel/bpf/hashtab.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/hashtab.c +1 -1
@@ -981,7 +981,7 @@ static void pcpu_init_value(struct bpf_htab *htab, void __percpu *pptr,for_each_possible_cpu (cpu) {if (cpu == current_cpu) -copy_map_value_long (&htab->map,per_cpu_ptr (pptr, cpu), value); +copy_map_value (&htab->map,per_cpu_ptr (pptr, cpu), value);else /* Since elem is preallocated, we cannot touch special fields */ zero_map_value (&htab->map,per_cpu_ptr (pptr, cpu)); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 166/957 ppp: require CAP_NET_ADMIN in target netns for unattached ioctls
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Taegu Ha <[email protected]>
[ Upstream commit 2bb6379416fd19f44c3423a00bfd8626259f6067 ]
/dev/ppp open is currently authorized against file->f_cred->user_ns, while unattached administrative ioctls operate on current->nsproxy->net_ns.
As a result, a local unprivileged user can create a new user namespace with CLONE_NEWUSER, gain CAP_NET_ADMIN only in that new user namespace, and still issue PPPIOCNEWUNIT, PPPIOCATTACH, or PPPIOCATTCHAN against an inherited network namespace.
Require CAP_NET_ADMIN in the user namespace that owns the target network namespace before handling unattached PPP administrative ioctls.
This preserves normal pppd operation in the network namespace it is actually privileged in, while rejecting the userns-only inherited-netns case.
--- drivers/net/ppp/ppp_generic.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ppp/ppp_generic.c +3 -0
@@ -1057,6 +1057,9 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,struct ppp_net *pn;int __user *p = (int __user *)arg; +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) +return -EPERM ; +switch (cmd) {case PPPIOCNEWUNIT :/* Create a new ppp unit */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 167/957 net: ipa: Fix programming of QTIME_TIMESTAMP_CFG
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luca Weiss <[email protected]>
[ Upstream commit de08f9585692813bd41ee654fca0487664c4de30 ]
The 'val' variable gets overwritten multiple times, discarding previous values. Looking at the git log shows these should be combined with |= instead.
--- drivers/net/ipa/ipa_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ipa/ipa_main.c +3 -3
@@ -361,7 +361,7 @@ static void ipa_qtime_config(struct ipa *ipa) {const struct reg *reg;u32 offset; -u32 val; +u32 val =0 ;/* Timer clock divider must be disabled when we change the rate */ reg =ipa_reg (ipa,TIMERS_XO_CLK_DIV_CFG );
@@ -374,8 +374,8 @@ static void ipa_qtime_config(struct ipa *ipa) val |=reg_bit (reg,DPL_TIMESTAMP_SEL ); }/* Configure tag and NAT Qtime timestamp resolution as well */ - val =reg_encode (reg,TAG_TIMESTAMP_LSB ,TAG_TIMESTAMP_SHIFT ); - val =reg_encode (reg,NAT_TIMESTAMP_LSB ,NAT_TIMESTAMP_SHIFT ); + val |=reg_encode (reg,TAG_TIMESTAMP_LSB ,TAG_TIMESTAMP_SHIFT ); + val |=reg_encode (reg,NAT_TIMESTAMP_LSB ,NAT_TIMESTAMP_SHIFT );iowrite32 (val, ipa->reg_virt +reg_offset (reg));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 168/957 net: ipa: Fix decoding EV_PER_EE for IPA v5.0+
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luca Weiss <[email protected]>
[ Upstream commit 1335b903cf2e8aeaca87fd665683384c731ec941 ]
Initially 'reg' and 'val' are assigned from HW_PARAM_2.
But since IPA v5.0+ takes EV_PER_EE from HW_PARAM_4 (instead of NUM_EV_PER_EE from HW_PARAM_2), we not only need to re-assign 'reg' but also read the register value of that register into 'val' so that reg_decode() works on the correct value.
--- drivers/net/ipa/gsi.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ipa/gsi.c +1 -0
@@ -2044,6 +2044,7 @@ static int gsi_ring_setup(struct gsi *gsi) count =reg_decode (reg,NUM_EV_PER_EE , val); }else { reg =gsi_reg (gsi,HW_PARAM_4 ); + val =ioread32 (gsi->virt +reg_offset (reg)); count =reg_decode (reg,EV_PER_EE , val); }if (!count) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 169/957 dt-bindings: net: dsa: nxp,sja1105: make spi-cpol optional for sja1110
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josua Mayer <[email protected]>
[ Upstream commit 600f01dc4bd0c736b3ffea9f7976136d8bf1b136 ]
Currently, the binding requires 'spi-cpha' for SJA1105 and 'spi-cpol' for SJA1110.
However, the SJA1110 supports both SPI modes 0 and 2. Mode 2 (cpha=0, cpol=1) is used by the NXP LX2160 Bluebox 3.
On the SolidRun i.MX8DXL HummingBoard Telematics, mode 0 is stable, while forcing mode 2 introduces CRC errors especially during bursts.
Drop the requirement on spi-cpol for SJA1110.
--- Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml | 2 -- 1 file changed, 2 deletions(-)
Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml +0 -2
@@ -140,8 +140,6 @@ allOf: else: properties: spi-cpha: false - required: - - spi-cpol unevaluatedProperties: false
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 170/957 net: phy: fix a return path in get_phy_c45_ids()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Charles Perry <[email protected]>
[ Upstream commit 6f533abe7bbad2eef1e42c639b6bb9dad2b02362 ]
The return value of phy_c45_probe_present() is stored in "ret", not "phy_reg", fix this. "phy_reg" always has a positive value if we reach this return path (since it would have returned earlier otherwise), which means that the original goal of the patch of not considering -ENODEV fatal wasn't achieved.
--- drivers/net/phy/phy_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/phy/phy_device.c +2 -2
@@ -963,8 +963,8 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr,/* returning -ENODEV doesn't stop bus * scanning */ -return (phy_reg == -EIO || - phy_reg == -ENODEV ) ? -ENODEV : -EIO ; +return (ret == -EIO || + ret == -ENODEV ) ? -ENODEV : -EIO ;if (!ret)continue ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 171/957 net/mlx5e: Fix features not applied during netdev registration
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <[email protected]>
[ Upstream commit 9994ad4df82d64e57135c0f0906897685f5a9e87 ]
mlx5e_fix_features() returns early when the netdevice is not present. This is correct during profile transitions where priv is cleared, but it also incorrectly blocks feature fixups during register_netdev(), when the device is also not yet present.
It is not trivial to distinguish between both cases as we cannot use priv to carry state, and in both cases reg_state == NETREG_REGISTERED.
Force a netdev features update after register_netdev() completes, where the device is present and fix_features() can actually work.
This is not a pretty solution, as it results in an additional features update call (register_netdevice() already calls __netdev_update_features() internally), but it is the simplest, cleanest, and most robust way I found to fix this issue after multiple attempts.
This fixes an issue on systems where CQE compression is enabled by default, RXHASH remains enabled after registration despite the two features being mutually exclusive.
--- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/net/ethernet/mellanox/mlx5/core/en_main.c +8 -0
@@ -6740,6 +6740,14 @@ static int _mlx5e_probe(struct auxiliary_device *adev) goto err_resume; } +/* mlx5e_fix_features() returns early when the device is not present +* to avoid dereferencing cleared priv during profile changes. +* This also causes it to be a no-op during register_netdev(), where +* the device is not yet present. +* Trigger an additional features update that will actually work. +*/ +mlx5e_update_features (netdev); +mlx5e_dcbnl_init_app (priv);mlx5_core_uplink_netdev_set (mdev, netdev);mlx5e_params_print_info (mdev, &priv->channels.params);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 172/957 net/mlx5e: IPsec, fix ASO poll timeout with read_poll_timeout_atomic()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <[email protected]>
[ Upstream commit edccdd1eb94712da97a6ce71123ec27890add754 ]
The do-while poll loop uses jiffies for its timeout:
expires = jiffies + msecs_to_jiffies(10);
jiffies is sampled at an arbitrary point within the current tick, so the first partial tick contributes anywhere from a full tick down to nearly zero real time. For small msecs_to_jiffies() results this is significant, the effective poll window can be much shorter than the requested 10ms, and in the worst case the loop exits after a single iteration (e.g., when HZ=100), well before the device has delivered the CQE.
Replace the loop with read_poll_timeout_atomic(), which counts elapsed time via udelay() accounting rather than jiffies, guaranteeing the full poll window regardless of HZ.
Additionally, read_poll_timeout_atomic() executes the poll operation one more time after the timeout has expired, giving the CQE a final chance to be detected. The old do-while loop could exit without a final poll if the timeout expired during the udelay() between iterations.
--- .../mellanox/mlx5/core/en_accel/ipsec_offload.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +4 -8
@@ -1,6 +1,8 @@// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB /* Copyright (c) 2017, Mellanox Technologies inc. All rights reserved. */ +#include <linux/iopoll.h> +#include "mlx5_core.h" #include "en.h" #include "ipsec.h"
@@ -592,7 +594,6 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,struct mlx5_wqe_aso_ctrl_seg *ctrl;struct mlx5e_hw_objs *res;struct mlx5_aso_wqe *wqe; -unsigned long expires;u8 ds_cnt;int ret;
@@ -614,13 +615,8 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,mlx5e_ipsec_aso_copy (ctrl, data);mlx5_aso_post_wqe (aso->aso, false, &wqe->ctrl); - expires = jiffies +msecs_to_jiffies (10 ); -do { - ret =mlx5_aso_poll_cq (aso->aso, false); -if (ret) -/* We are in atomic context */ -udelay (10 ); - }while (ret &&time_is_after_jiffies (expires)); +read_poll_timeout_atomic (mlx5_aso_poll_cq, ret, !ret,10 , +10 *USEC_PER_MSEC , false, aso->aso, false);if (!ret)memcpy (sa_entry->ctx, aso->ctx,MLX5_ST_SZ_BYTES (ipsec_aso));spin_unlock_bh (&aso->lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 173/957 bpf: reject short IPv4/IPv6 inputs in bpf_prog_test_run_skb
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sun Jian <[email protected]>
[ Upstream commit 12bec2bd4b76d81c5d3996bd14ec1b7f4d983747 ]
bpf_prog_test_run_skb() calls eth_type_trans() first and then uses skb->protocol to initialize sk family and address fields for the test run.
For IPv4 and IPv6 packets, it may access ip_hdr(skb) or ipv6_hdr(skb) even when the provided test input only contains an Ethernet header.
Reject the input earlier if the Ethernet frame carries IPv4/IPv6 EtherType but the L3 header is too short.
Fold the IPv4/IPv6 header length checks into the existing protocol switch and return -EINVAL before accessing the network headers.
--- net/bpf/test_run.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
net/bpf/test_run.c +12 -8
@@ -1057,19 +1057,23 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,switch (skb->protocol) {case htons (ETH_P_IP ): - sk->sk_family =AF_INET ; -if (sizeof (struct iphdr ) <=skb_headlen (skb)) { - sk->sk_rcv_saddr =ip_hdr (skb)->saddr; - sk->sk_daddr =ip_hdr (skb)->daddr; +if (skb_headlen (skb) <sizeof (struct iphdr )) { + ret = -EINVAL ; + goto out; } + sk->sk_family =AF_INET ; + sk->sk_rcv_saddr =ip_hdr (skb)->saddr; + sk->sk_daddr =ip_hdr (skb)->daddr;break ;#if IS_ENABLED (CONFIG_IPV6 )case htons (ETH_P_IPV6 ): - sk->sk_family =AF_INET6 ; -if (sizeof (struct ipv6hdr ) <=skb_headlen (skb)) { - sk->sk_v6_rcv_saddr =ipv6_hdr (skb)->saddr; - sk->sk_v6_daddr =ipv6_hdr (skb)->daddr; +if (skb_headlen (skb) <sizeof (struct ipv6hdr )) { + ret = -EINVAL ; + goto out; } + sk->sk_family =AF_INET6 ; + sk->sk_v6_rcv_saddr =ipv6_hdr (skb)->saddr; + sk->sk_v6_daddr =ipv6_hdr (skb)->daddr;break ;#endif default :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 174/957 Bluetooth: L2CAP: Fix printing wrong information if SDU length exceeds MTU
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 15bf35a660eb82a49f8397fc3d3acada8dae13db ]
The code was printing skb->len and sdu_len in the places where it should be sdu_len and chan->imtu respectively to match the if conditions.
--- net/bluetooth/l2cap_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/bluetooth/l2cap_core.c +1 -1
@@ -6733,7 +6733,7 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)if (sdu_len > chan->imtu) {BT_ERR ("Too big LE L2CAP SDU length: len %u > %u" , - skb->len, sdu_len); + sdu_len, chan->imtu);l2cap_send_disconn_req (chan,ECONNRESET ); err = -EMSGSIZE ; goto failed;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 175/957 Bluetooth: hci_ldisc: Clear HCI_UART_PROTO_INIT on error
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonathan Rissanen <[email protected]>
[ Upstream commit 68d39ea5e0adc9ecaea1ce8abd842ec972eb8718 ]
When hci_register_dev() fails in hci_uart_register_dev() HCI_UART_PROTO_INIT is not cleared before calling hu->proto->close(hu) and setting hu->hdev to NULL. This means incoming UART data will reach the protocol-specific recv handler in hci_uart_tty_receive() after resources are freed.
Clear HCI_UART_PROTO_INIT with a write lock before calling hu->proto->close() and setting hu->hdev to NULL. The write lock ensures all active readers have completed and no new reader can enter the protocol recv path before resources are freed.
This allows the protocol-specific recv functions to remove the "HCI_UART_REGISTERED" guard without risking a null pointer dereference if hci_register_dev() fails.
--- drivers/bluetooth/hci_ldisc.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/bluetooth/hci_ldisc.c +3 -0
@@ -692,6 +692,9 @@ static int hci_uart_register_dev(struct hci_uart *hu)if (hci_register_dev (hdev) <0 ) {BT_ERR ("Can't register HCI device" ); +percpu_down_write (&hu->proto_lock); +clear_bit (HCI_UART_PROTO_INIT , &hu->flags); +percpu_up_write (&hu->proto_lock); hu->proto->close (hu); hu->hdev =NULL ;hci_free_dev (hdev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 176/957 Bluetooth: fix locking in hci_conn_request_evt() with HCI_PROTO_DEFER
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit 5c7209a341ff2ac338b2b0375c34a307b37c9ac2 ]
When protocol sets HCI_PROTO_DEFER, hci_conn_request_evt() calls hci_connect_cfm(conn) without hdev->lock. Generally hci_connect_cfm() assumes it is held, and if conn is deleted concurrently -> UAF.
Only SCO and ISO set HCI_PROTO_DEFER and only for defer setup listen, and HCI_EV_CONN_REQUEST is not generated for ISO. In the non-deferred listening socket code paths, hci_connect_cfm(conn) is called with hdev->lock held.
Fix by holding the lock.
--- net/bluetooth/hci_event.c | 3 --- 1 file changed, 3 deletions(-)
net/bluetooth/hci_event.c +0 -3
@@ -3309,8 +3309,6 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,memcpy (conn->dev_class, ev->dev_class,3 ); -hci_dev_unlock (hdev); -if (ev->link_type ==ACL_LINK || (!(flags &HCI_PROTO_DEFER ) && !lmp_esco_capable (hdev))) {struct hci_cp_accept_conn_req cp;
@@ -3344,7 +3342,6 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,hci_connect_cfm (conn,0 ); } -return ; unlock:hci_dev_unlock (hdev); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 177/957 Bluetooth: l2cap: Add missing chan lock in l2cap_ecred_reconf_rsp
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dudu Lu <[email protected]>
[ Upstream commit 42776497cdbc9a665b384a6dcb85f0d4bd927eab ]
l2cap_ecred_reconf_rsp() calls l2cap_chan_del() without holding l2cap_chan_lock(). Every other l2cap_chan_del() caller in the file acquires the lock first. A remote BLE device can send a crafted L2CAP ECRED reconfiguration response to corrupt the channel list while another thread is iterating it.
Add l2cap_chan_hold() and l2cap_chan_lock() before l2cap_chan_del(), and l2cap_chan_unlock() and l2cap_chan_put() after, matching the pattern used in l2cap_ecred_conn_rsp() and l2cap_conn_del().
--- net/bluetooth/l2cap_core.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/bluetooth/l2cap_core.c +6 -0
@@ -5473,7 +5473,13 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,if (chan->ident != cmd->ident)continue ; +l2cap_chan_hold (chan); +l2cap_chan_lock (chan); +l2cap_chan_del (chan,ECONNRESET ); + +l2cap_chan_unlock (chan); +l2cap_chan_put (chan); }return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 178/957 Bluetooth: SCO: check for codecs->num_codecs == 1 before assigning to sco_pi(sk)->codec
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Metzmacher <[email protected]>
[ Upstream commit 4e10a9ebbf081c16517cdd9366ac618bf38d7d0c ]
copy_struct_from_sockptr() fill 'buffer' insco_sock_setsockopt() with zeros, so there's no
real problem.
But it actually looks strange to do this,
without checking all of codecs->codecs[0]
really comes from userspace:
sco_pi(sk)->codec = codecs->codecs[0];
As only optlen < sizeof(struct bt_codecs) is checked and codecs->num_codecs is not checked against != 1, but only <= 1, and the space for the additional struct bt_codec is not checked.
Note I don't understand bluetooth and I didn't do any runtime tests with this! I just found it when debugging a problem in copy_struct_from_sockptr().
I just added this to check the size is as expected:
BUILD_BUG_ON(struct_size(codecs, codecs, 0) != 1); BUILD_BUG_ON(struct_size(codecs, codecs, 1) != 8);
And made sure it still compiles using this:
make CF=-D__CHECK_ENDIAN__ W=1ce C=1 net/bluetooth/sco.o
--- net/bluetooth/sco.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/bluetooth/sco.c +2 -1
@@ -1045,7 +1045,8 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, codecs = (void *)buffer; -if (codecs->num_codecs >1 ) { +if (codecs->num_codecs !=1 || + optlen <struct_size (codecs, codecs, codecs->num_codecs)) {hci_dev_put (hdev); err = -EINVAL ;break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 179/957 net: phy: qcom: at803x: Use the correct bit to disable extended next page
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxime Chevallier <[email protected]>
[ Upstream commit e7a62edd34b1b4bc5f979988efc2f81c075733fd ]
As noted in the blamed commit, the AR8035 and other PHYs from this family advertise the Extended Next Page support by default, which may be understood by some partners as this PHY being multi-gig capable.
The fix is to disable XNP advertising, which is done by setting bit 12 of the Auto-Negotiation Advertisement Register (MII_ADVERTISE).
The blamed commit incorrectly uses MDIO_AN_CTRL1_XNP, which is bit 13 as per 802.3 : 45.2.7.1 AN control register (Register 7.0)
BIT 12 in MII_ADVERTISE is wrapped by ADVERTISE_RESV, used by some drivers such as the aquantia one. 802.3 Clause 28 defines bit 12 as Extended Next Page ability, at least in recent versions of the standard.
Let's add a define for it and use it in the at803x driver.
--- drivers/net/phy/qcom/at803x.c | 2 +- include/uapi/linux/mii.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/net/phy/qcom/at803x.c +1 -1
@@ -524,7 +524,7 @@ static int at803x_config_init(struct phy_device *phydev)* behaviour but we still need to accommodate it. XNP is only needed * for 10Gbps support, so disable XNP. */ -return phy_modify (phydev,MII_ADVERTISE ,MDIO_AN_CTRL1_XNP ,0 ); +return phy_modify (phydev,MII_ADVERTISE ,ADVERTISE_XNP ,0 ); }static void at803x_link_change_notify (struct phy_device *phydev)
include/uapi/linux/mii.h +2 -1
@@ -82,7 +82,8 @@#define ADVERTISE_100BASE4 0x0200/* Try for 100mbps 4k packets */ #define ADVERTISE_PAUSE_CAP 0x0400/* Try for pause */ #define ADVERTISE_PAUSE_ASYM 0x0800/* Try for asymetric pause */ -#define ADVERTISE_RESV 0x1000/* Unused... */ +#define ADVERTISE_XNP 0x1000/* Extended Next Page */ +#define ADVERTISE_RESV ADVERTISE_XNP/* Used to be reserved */ #define ADVERTISE_RFAULT 0x2000/* Say we can detect faults */ #define ADVERTISE_LPACK 0x4000/* Ack link partners response */ #define ADVERTISE_NPAGE 0x8000/* Next page bit */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 180/957 udp: Force compute_score to always inline
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit b80a95ccf1604a882bb153c45ccb4056e44c8edb ]
Back in 2024 I reported a 7-12% regression on an iperf3 UDP loopback thoughput test that we traced to the extra overhead of calling compute_score on two places, introduced by commit f0ea27e7bfe1 ("udp:
re-score reuseport groups when connected sockets are present"). At the time, I pointed out the overhead was caused by the multiple calls, associated with cpu-specific mitigations, and merged commit 50aee97d1511 ("udp: Avoid call to compute_score on multiple sites") to jump back explicitly, to force the rescore call in a single place.
Recently though, we got another regression report against a newer distro version, which a team colleague traced back to the same root-cause. Turns out that once we updated to gcc-13, the compiler got smart enough to unroll the loop, undoing my previous mitigation. Let's bite the bullet and __always_inline compute_score on both ipv4 and ipv6 to prevent gcc from de-optimizing it again in the future. These functions are only called in two places each, udpX_lib_lookup1 and udpX_lib_lookup2, so the extra size shouldn't be a problem and it is hot enough to be very visible in profilings. In fact, with gcc13, forcing the inline will prevent gcc from unrolling the fix from commit 50aee97d1511, so we don't end up increasing udpX_lib_lookup2 at all.
I haven't recollected the results myself, as I don't have access to the machine at the moment. But the same colleague reported 4.67% inprovement with this patch in the loopback benchmark, solving the regression report within noise margins.
Eric Dumazet reported no size change to vmlinux when built with clang. I report the same also with gcc-13:
scripts/bloat-o-meter vmlinux vmlinux-inline add/remove: 0/2 grow/shrink: 4/0 up/down: 616/-416 (200)
Function old new delta udp6_lib_lookup2 762 949 +187 __udp6_lib_lookup 810 975 +165 udp4_lib_lookup2 757 906 +149 __udp4_lib_lookup 871 986 +115
__pfx_compute_score 32 - -32compute_score 384 - -384
Total: Before=35011784, After=35011984, chg +0.00%
--- net/ipv4/udp.c | 12 ++++++------ net/ipv6/udp.c | 13 +++++++------ 2 files changed, 13 insertions(+), 12 deletions(-)
net/ipv4/udp.c +6 -6
@@ -365,10 +365,10 @@ int udp_v4_get_port(struct sock *sk, unsigned short snum)return udp_lib_get_port (sk, snum, hash2_nulladdr); } -static int compute_score (struct sock *sk,const struct net *net, -__be32 saddr,__be16 sport, -__be32 daddr,unsigned short hnum, -int dif,int sdif) +static __always_inline int +compute_score (struct sock *sk,const struct net *net, +__be32 saddr,__be16 sport,__be32 daddr, +unsigned short hnum,int dif,int sdif) {int score;struct inet_sock *inet;
@@ -508,8 +508,8 @@ static struct sock *udp4_lib_lookup2(const struct net *net,continue ;/* compute_score is too long of a function to be -* inlined, and calling it again here yields -* measurable overhead for some +* inlined twice here, and calling it uninlined +* here yields measurable overhead for some * workloads. Work around it by jumping * backwards to rescore 'result'. */
net/ipv6/udp.c +7 -6
@@ -127,10 +127,11 @@ void udp_v6_rehash(struct sock *sk)udp_lib_rehash (sk, new_hash, new_hash4); } -static int compute_score (struct sock *sk,const struct net *net, -const struct in6_addr *saddr,__be16 sport, -const struct in6_addr *daddr,unsigned short hnum, -int dif,int sdif) +static __always_inline int +compute_score (struct sock *sk,const struct net *net, +const struct in6_addr *saddr,__be16 sport, +const struct in6_addr *daddr,unsigned short hnum, +int dif,int sdif) {int bound_dev_if, score;struct inet_sock *inet;
@@ -260,8 +261,8 @@ static struct sock *udp6_lib_lookup2(const struct net *net,continue ;/* compute_score is too long of a function to be -* inlined, and calling it again here yields -* measurable overhead for some +* inlined twice here, and calling it uninlined +* here yields measurable overhead for some * workloads. Work around it by jumping * backwards to rescore 'result'. */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 181/957 tcp: Dont set treq->req_usec_ts in cookie_tcp_reqsk_init().
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit c058bbf05b1197c33df7204842665bd8bc70b3a8 ]
Commit de5626b95e13 ("tcp: Factorise cookie-independent fields initialisation in cookie_v[46]_check().") miscategorised tcp_rsk(req)->req_usec_ts init to cookie_tcp_reqsk_init(), which is used by both BPF/non-BPF SYN cookie reqsk.
Rather, it should have been moved to cookie_tcp_reqsk_alloc() by commit 8e7bab6b9652 ("tcp: Factorise cookie-dependent fields initialisation in cookie_v[46]_check()") so that only non-BPF SYN cookie sets tcp_rsk(req)->req_usec_ts to false.
Let's move the initialisation to cookie_tcp_reqsk_alloc() to respect bpf_tcp_req_attrs.usec_ts_ok.
--- net/ipv4/syncookies.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/syncookies.c +1 -1
@@ -286,7 +286,6 @@ static int cookie_tcp_reqsk_init(struct sock *sk, struct sk_buff *skb, treq->rcv_isn =ntohl (th->seq) -1 ; treq->snt_isn =ntohl (th->ack_seq) -1 ; treq->syn_tos =TCP_SKB_CB (skb)->ip_dsfield; - treq->req_usec_ts = false;#if IS_ENABLED (CONFIG_MPTCP ) treq->is_mptcp =sk_is_mptcp (sk);
@@ -349,6 +348,7 @@ struct request_sock *cookie_tcp_reqsk_alloc(const struct request_sock_ops *ops, ireq->wscale_ok = tcp_opt->wscale_ok; ireq->ecn_ok = !!(tcp_opt->rcv_tsecr &TS_OPT_ECN ); + treq->req_usec_ts = false; treq->ts_off = tsoff;return req;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 182/957 sctp: fix missing encap_port propagation for GSO fragments
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xin Long <[email protected]>
[ Upstream commit bf6f95ae3b8b2638c0e1d6d802d50983ce5d0f45 ]
encap_port in SCTP_INPUT_CB(skb) is used by sctp_vtag_verify() for SCTP-over-UDP processing. In the GSO case, it is only set on the head skb, while fragment skbs leave it 0.
This results in fragment skbs seeing encap_port == 0, breaking SCTP-over-UDP connections.
Fix it by propagating encap_port from the head skb cb when initializing fragment skbs in sctp_inq_pop().
--- net/sctp/inqueue.c | 1 + 1 file changed, 1 insertion(+)
net/sctp/inqueue.c +1 -0
@@ -201,6 +201,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) cb->chunk = head_cb->chunk; cb->af = head_cb->af; + cb->encap_port = head_cb->encap_port; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 183/957 net, bpf: fix null-ptr-deref in xdp_master_redirect() for down master
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
[ Upstream commit 1921f91298d1388a0bb9db8f83800c998b649cb3 ]
syzkaller reported a kernel panic in bond_rr_gen_slave_id() reached via xdp_master_redirect(). Full decoded trace:
https://syzkaller.appspot.com/bug?extid=80e046b8da2820b6ba73
bond_rr_gen_slave_id() dereferences bond->rr_tx_counter, a per-CPU counter that bonding only allocates in bond_open() when the mode is round-robin. If the bond device was never brought up, rr_tx_counter stays NULL.
The XDP redirect path can still reach that code on a bond that was never opened: bpf_master_redirect_enabled_key is a global static key, so as soon as any bond device has native XDP attached, the XDP_TX -> xdp_master_redirect() interception is enabled for every slave system-wide. The path xdp_master_redirect() -> bond_xdp_get_xmit_slave() -> bond_xdp_xmit_roundrobin_slave_get() -> bond_rr_gen_slave_id() then runs against a bond that has no rr_tx_counter and crashes.
Fix this in the generic xdp_master_redirect() by refusing to call into the master's ->ndo_xdp_get_xmit_slave() when the master device is not up. IFF_UP is only set after ->ndo_open() has successfully returned, so this reliably excludes masters whose XDP state has not been fully initialized. Drop the frame with XDP_ABORTED so the exception is visible via trace_xdp_exception() rather than silently falling through. This is not specific to bonding: any current or future master that defers XDP state allocation to ->ndo_open() is protected.
--- net/core/filter.c | 2 ++ 1 file changed, 2 insertions(+)
net/core/filter.c +2 -0
@@ -4385,6 +4385,8 @@ u32 xdp_master_redirect(struct xdp_buff *xdp)struct net_device *master, *slave; master =netdev_master_upper_dev_get_rcu (xdp->rxq->dev); +if (unlikely (!(master->flags &IFF_UP ))) +return XDP_ABORTED ; slave = master->netdev_ops->ndo_xdp_get_xmit_slave (master, xdp);if (slave && slave != xdp->rxq->dev) {/* The target device is different from the receiving device, so
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 184/957 net: airoha: Add missing PPE configurations in airoha_ppe_hw_init()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit b9d8b856689d2b968495d79fe653d87fcb8ad98c ]
Add the following PPE configuration in airoha_ppe_hw_init routine:
- 6RD hw offloading is currently not supported by Netfilter flowtable. Disable explicitly PPE 6RD offloading in order to prevent PPE to learn 6RD flows and eventually interrupt the traffic.
- Add missing PPE bind rate configuration for L3 and L2 traffic. PPE bind rate configuration specifies the pps threshold to move a PPE entry state from UNBIND to BIND. Without this configuration this value is random.
- Set ageing thresholds to the values used in the vendor SDK in order to improve connection stability under load and avoid packet loss caused by fast aging.
--- drivers/net/ethernet/airoha/airoha_ppe.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
drivers/net/ethernet/airoha/airoha_ppe.c +11 -3
@@ -83,13 +83,13 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)airoha_fe_rmw (eth,REG_PPE_BND_AGE0 (i),PPE_BIND_AGE0_DELTA_NON_L4 |PPE_BIND_AGE0_DELTA_UDP , -FIELD_PREP (PPE_BIND_AGE0_DELTA_NON_L4 ,1 ) | -FIELD_PREP (PPE_BIND_AGE0_DELTA_UDP ,12 )); +FIELD_PREP (PPE_BIND_AGE0_DELTA_NON_L4 ,60 ) | +FIELD_PREP (PPE_BIND_AGE0_DELTA_UDP ,60 ));airoha_fe_rmw (eth,REG_PPE_BND_AGE1 (i),PPE_BIND_AGE1_DELTA_TCP_FIN |PPE_BIND_AGE1_DELTA_TCP ,FIELD_PREP (PPE_BIND_AGE1_DELTA_TCP_FIN ,1 ) | -FIELD_PREP (PPE_BIND_AGE1_DELTA_TCP ,7 )); +FIELD_PREP (PPE_BIND_AGE1_DELTA_TCP ,60 )); airoha_fe_rmw(eth, REG_PPE_TB_HASH_CFG(i), PPE_SRAM_TABLE_EN_MASK |
@@ -111,7 +111,15 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)FIELD_PREP (PPE_TB_CFG_SEARCH_MISS_MASK ,3 ) | FIELD_PREP(PPE_TB_ENTRY_SIZE_MASK, 0)); +airoha_fe_rmw (eth,REG_PPE_BIND_RATE (i), +PPE_BIND_RATE_L2B_BIND_MASK | +PPE_BIND_RATE_BIND_MASK , +FIELD_PREP (PPE_BIND_RATE_L2B_BIND_MASK ,0x1e ) | +FIELD_PREP (PPE_BIND_RATE_BIND_MASK ,0x1e )); +airoha_fe_wr (eth,REG_PPE_HASH_SEED (i),PPE_HASH_SEED ); +airoha_fe_clear (eth,REG_PPE_PPE_FLOW_CFG (i), +PPE_FLOW_CFG_IP6_6RD_MASK );for (p =0 ; p <ARRAY_SIZE (eth->ports); p++) airoha_fe_rmw(eth, REG_PPE_MTU(i, p),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 185/957 selftests/futex: Fix incorrect result reporting of futex_requeue test item
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuwen Chen <[email protected]>
[ Upstream commit d317e2ef9dcf673c9f37cda784284af7c6812757 ]
When using the TEST_HARNESS_MAIN macro definition to declare the main function, it is required to use the EXPECT*() and ASSERT*() macros in conjunction and not ksft_test_result_*(). Otherwise, even if a test item fails, the test will still return a success result because ksft_test_result_*() does not affect the test harness state.
Convert the code to use EXPECT/ASSERT() variants, which ensures that the overall test result is fail if one of the EXPECT()s fails.
[ tglx: Massaged change log to explain _why_ ksft_test_result*() is the wrong
choice ]
--- .../futex/functional/futex_requeue.c | 49 +++---------------- 1 file changed, 8 insertions(+), 41 deletions(-)
tools/testing/selftests/futex/functional/futex_requeue.c +8 -41
@@ -34,34 +34,18 @@ TEST(requeue_single)volatile futex_t _f1 =0 ;volatile futex_t f2 =0 ;pthread_t waiter[10 ]; -int res; f1 = &_f1;/* * Requeue a waiter from f1 to f2, and wake f2. */ -if (pthread_create (&waiter[0 ],NULL , waiterfn,NULL )) -ksft_exit_fail_msg ("pthread_create failed\n" ); +ASSERT_EQ (0 ,pthread_create (&waiter[0 ],NULL , waiterfn,NULL ));usleep (WAKE_WAIT_US ); -ksft_print_dbg_msg ("Requeuing 1 futex from f1 to f2\n" ); - res =futex_cmp_requeue (f1,0 , &f2,0 ,1 ,0 ); -if (res !=1 ) -ksft_test_result_fail ("futex_requeue simple returned: %d %s\n" , - res ? errno : res, - res ?strerror (errno) :"" ); - -ksft_print_dbg_msg ("Waking 1 futex at f2\n" ); - res =futex_wake (&f2,1 ,0 ); -if (res !=1 ) { -ksft_test_result_fail ("futex_requeue simple returned: %d %s\n" , - res ? errno : res, - res ?strerror (errno) :"" ); - }else { -ksft_test_result_pass ("futex_requeue simple succeeds\n" ); - } +EXPECT_EQ (1 ,futex_cmp_requeue (f1,0 , &f2,0 ,1 ,0 )); +EXPECT_EQ (1 ,futex_wake (&f2,1 ,0 )); }TEST (requeue_multiple)
@@ -69,7 +53,7 @@ TEST(requeue_multiple)volatile futex_t _f1 =0 ;volatile futex_t f2 =0 ;pthread_t waiter[10 ]; -int res, i; +int i; f1 = &_f1;
@@ -77,30 +61,13 @@ TEST(requeue_multiple)* Create 10 waiters at f1. At futex_requeue, wake 3 and requeue 7. * At futex_wake, wake INT_MAX (should be exactly 7). */ -for (i =0 ; i <10 ; i++) { -if (pthread_create (&waiter[i],NULL , waiterfn,NULL )) -ksft_exit_fail_msg ("pthread_create failed\n" ); - } +for (i =0 ; i <10 ; i++) +ASSERT_EQ (0 ,pthread_create (&waiter[i],NULL , waiterfn,NULL ));usleep (WAKE_WAIT_US ); -ksft_print_dbg_msg ("Waking 3 futexes at f1 and requeuing 7 futexes from f1 to f2\n" ); - res =futex_cmp_requeue (f1,0 , &f2,3 ,7 ,0 ); -if (res !=10 ) { -ksft_test_result_fail ("futex_requeue many returned: %d %s\n" , - res ? errno : res, - res ?strerror (errno) :"" ); - } - -ksft_print_dbg_msg ("Waking INT_MAX futexes at f2\n" ); - res =futex_wake (&f2,INT_MAX ,0 ); -if (res !=7 ) { -ksft_test_result_fail ("futex_requeue many returned: %d %s\n" , - res ? errno : res, - res ?strerror (errno) :"" ); - }else { -ksft_test_result_pass ("futex_requeue many succeeds\n" ); - } +EXPECT_EQ (10 ,futex_cmp_requeue (f1,0 , &f2,3 ,7 ,0 )); +EXPECT_EQ (7 ,futex_wake (&f2,INT_MAX ,0 )); }TEST_HARNESS_MAIN
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 186/957 drm/komeda: fix integer overflow in AFBC framebuffer size check
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Konyukhov <[email protected]>
[ Upstream commit 779ec12c85c9e4547519e3903a371a3b26a289de ]
The AFBC framebuffer size validation calculates the minimum required buffer size by adding the AFBC payload size to the framebuffer offset. This addition is performed without checking for integer overflow.
If the addition oveflows, the size check may incorrectly succed and allow userspace to provide an undersized drm_gem_object, potentially leading to out-of-bounds memory access.
Add usage of check_add_overflow() to safely compute the minimum required size and reject the framebuffer if an overflow is detected. This makes the AFBC size validation more robust against malformed.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c +5 -1
@@ -4,6 +4,8 @@* Author: James.Qian.Wang <[email protected]> * */ +#include <linux/overflow.h> +#include <drm/drm_device.h> #include <drm/drm_fb_dma_helper.h> #include <drm/drm_gem.h>
@@ -92,7 +94,9 @@ komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file, kfb->afbc_size = kfb->offset_payload + n_blocks *ALIGN (bpp *AFBC_SUPERBLK_PIXELS /8 ,AFBC_SUPERBLK_ALIGNMENT ); - min_size = kfb->afbc_size + fb->offsets[0 ]; +if (check_add_overflow (kfb->afbc_size, fb->offsets[0 ], &min_size)) { + goto check_failed; + }if (min_size > obj->size) {DRM_DEBUG_KMS ("afbc size check failed, obj_size: 0x%zx. min_size 0x%llx.\n" , obj->size, min_size);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 187/957 drm/virtio: Allow importing prime buffers when 3D is enabled
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Val Packett <[email protected]>
[ Upstream commit df4dc947c46bb9f80038f52c6e38cb2d40c10e50 ]
This functionality was added for using a KMS-only virtgpu with a physical (or SR-IOV) headless GPU in passthrough, but it should not be restricted to KMS-only mode. It can be used with cross-domain to pass guest memfds to the host compositor with zero copies (using udmabuf on both sides).
Drop the check for the absence of virgl_3d to allow for more use cases.
--- drivers/gpu/drm/virtio/virtgpu_prime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/virtio/virtgpu_prime.c +1 -1
@@ -312,7 +312,7 @@ struct drm_gem_object *virtgpu_gem_prime_import(struct drm_device *dev, } } -if (!vgdev->has_resource_blob || vgdev->has_virgl_3d) +if (!vgdev->has_resource_blob)return drm_gem_prime_import (dev, buf); bo =kzalloc (sizeof (*bo),GFP_KERNEL );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 188/957 ASoC: soc-compress: use function to clear symmetric params
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuninori Morimoto <[email protected]>
[ Upstream commit 07c774dd64ba0c605dbf844132122e3edbdbea93 ]
Current soc-compress.c clears symmetric_rate, but it clears rate only, not clear other symmetric_channels/sample_bits.
static int soc_compr_clean(...)
{
...
if (!snd_soc_dai_active(cpu_dai))=> cpu_dai->symmetric_rate = 0;
if (!snd_soc_dai_active(codec_dai)) => codec_dai->symmetric_rate = 0; ... };
This feature was added when v3.7 kernel [1], and there was only symmetric_rate, no symmetric_channels/sample_bits in that timing.
symmetric_channels/sample_bits were added in v3.14 [2],
but I guess it didn't notice that soc-compress.c is updating symmetric_xxx.
We are clearing symmetry_xxx by soc_pcm_set_dai_params(), but is soc-pcm.c local function. Makes it global function and clear symmetry_xxx by it.
[1] commit 1245b7005de02 ("ASoC: add compress stream support")
[2] commit 3635bf09a89cf ("ASoC: soc-pcm: add symmetry for channels and sample bits")
--- include/sound/soc.h | 3 +++ sound/soc/soc-compress.c | 4 ++-- sound/soc/soc-pcm.c | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-)
include/sound/soc.h +3 -0
@@ -1414,6 +1414,9 @@ struct snd_soc_dai *snd_soc_find_dai(struct snd_soc_dai *snd_soc_find_dai_with_mutex (const struct snd_soc_dai_link_component *dlc); +void soc_pcm_set_dai_params (struct snd_soc_dai *dai, +struct snd_pcm_hw_params *params); +#include <sound/soc-dai.h> static inline
sound/soc/soc-compress.c +2 -2
@@ -69,10 +69,10 @@ static int soc_compr_clean(struct snd_compr_stream *cstream, int rollback)snd_soc_dai_digital_mute (codec_dai,1 , stream);if (!snd_soc_dai_active (cpu_dai)) - cpu_dai->symmetric_rate =0 ; +soc_pcm_set_dai_params (cpu_dai,NULL );if (!snd_soc_dai_active (codec_dai)) - codec_dai->symmetric_rate =0 ; +soc_pcm_set_dai_params (codec_dai,NULL );snd_soc_link_compr_shutdown (cstream, rollback);
sound/soc/soc-pcm.c +2 -2
@@ -423,8 +423,8 @@ void dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, int event)snd_soc_dapm_stream_event (fe, dir, event); } -static void soc_pcm_set_dai_params (struct snd_soc_dai *dai, -struct snd_pcm_hw_params *params) +void soc_pcm_set_dai_params (struct snd_soc_dai *dai, +struct snd_pcm_hw_params *params) {if (params) { dai->symmetric_rate =params_rate (params);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 189/957 PCI/TPH: Allow TPH enable for RCiEPs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: George Abraham P <[email protected]>
[ Upstream commit d3e996a596967a62c8a13a279221513461f6ab97 ]
Previously, pcie_enable_tph() only enabled TLP Processing Hints (TPH) if both the Endpoint and its Root Port advertised TPH support.
Root Complex Integrated Endpoints (RCiEPs) are directly integrated into a Root Complex and do not have an associated Root Port, so pcie_enable_tph() never enabled TPH for RCiEPs.
PCIe r7.0 doesn't seem to include a way to learn whether a Root Complex supports TPH, but sec 2.2.7.1.1 says Functions that lack TPH support should ignore TPH, and maybe the same is true for Root Complexes:
A Function that does not support the TPH Completer or Routing capability and receives a transaction with the TH bit [which indicates the presence of TPH in the TLP header] Set is required to ignore the TH bit and handle the Request in the same way as Requests of the same transaction type without the TH bit Set.
Allow drivers to enable TPH for any RCiEP with a TPH Requester Capability.
--- drivers/pci/tph.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/pci/tph.c +6 -3
@@ -397,10 +397,13 @@ int pcie_enable_tph(struct pci_dev *pdev, int mode)else pdev->tph_req_type =PCI_TPH_REQ_TPH_ONLY ; - rp_req_type =get_rp_completer_type (pdev); +/* Check if the device is behind a Root Port */ +if (pci_pcie_type (pdev) !=PCI_EXP_TYPE_RC_END ) { + rp_req_type =get_rp_completer_type (pdev); -/* Final req_type is the smallest value of two */ - pdev->tph_req_type =min (pdev->tph_req_type, rp_req_type); +/* Final req_type is the smallest value of two */ + pdev->tph_req_type =min (pdev->tph_req_type, rp_req_type); + }if (pdev->tph_req_type ==PCI_TPH_REQ_DISABLE )return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 190/957 PCI: endpoint: pci-epf-test: Dont free doorbell IRQ unless requested
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Koichiro Den <[email protected]>
[ Upstream commit e81fa70179aac6ac3a6636565d5d35968dca3900 ]
pci_epf_test_doorbell_cleanup() unconditionally calls free_irq() for the doorbell virq, which can trigger "Trying to free already-free IRQ" warnings when the IRQ was never requested or when request_threaded_irq() failed.
Move free_irq() out of pci_epf_test_doorbell_cleanup() and invoke it only after a successful request, so that free_irq() is not called for an unrequested IRQ.
--- drivers/pci/endpoint/functions/pci-epf-test.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/pci/endpoint/functions/pci-epf-test.c +5 -3
@@ -704,7 +704,6 @@ static void pci_epf_test_doorbell_cleanup(struct pci_epf_test *epf_test)struct pci_epf_test_reg *reg = epf_test->reg[epf_test->test_reg_bar];struct pci_epf *epf = epf_test->epf; -free_irq (epf->db_msg[0 ].virq, epf_test); reg->doorbell_bar =cpu_to_le32 (NO_BAR );pci_epf_free_doorbell (epf);
@@ -748,7 +747,7 @@ static void pci_epf_test_enable_doorbell(struct pci_epf_test *epf_test, &epf_test->db_bar.phys_addr, &offset);if (ret) - goto err_doorbell_cleanup; + goto err_free_irq; reg->doorbell_offset =cpu_to_le32 (offset);
@@ -758,12 +757,14 @@ static void pci_epf_test_enable_doorbell(struct pci_epf_test *epf_test, ret =pci_epc_set_bar (epc, epf->func_no, epf->vfunc_no, &epf_test->db_bar);if (ret) - goto err_doorbell_cleanup; + goto err_free_irq; status |=STATUS_DOORBELL_ENABLE_SUCCESS ; reg->status =cpu_to_le32 (status);return ; +err_free_irq: +free_irq (epf->db_msg[0 ].virq, epf_test); err_doorbell_cleanup:pci_epf_test_doorbell_cleanup (epf_test); set_status_err:
@@ -783,6 +784,7 @@ static void pci_epf_test_disable_doorbell(struct pci_epf_test *epf_test,if (bar <BAR_0 ) goto set_status_err; +free_irq (epf->db_msg[0 ].virq, epf_test);pci_epf_test_doorbell_cleanup (epf_test);/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 191/957 PCI: endpoint: pci-ep-msi: Fix error unwind and prevent double alloc
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Koichiro Den <[email protected]>
[ Upstream commit 1cba96c0a795124c3229293ed7b5b5765e66f259 ]
pci_epf_alloc_doorbell() stores the allocated doorbell message array in epf->db_msg/epf->num_db before requesting MSI vectors. If MSI allocation fails, the array is freed but the EPF state may still point to freed memory.
Clear epf->db_msg and epf->num_db on the MSI allocation failure path so that later cleanup cannot double-free the array and callers can retry allocation.
Also return -EBUSY when doorbells have already been allocated to prevent leaking or overwriting an existing allocation.
--- drivers/pci/endpoint/pci-ep-msi.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/pci/endpoint/pci-ep-msi.c +5 -0
@@ -50,6 +50,9 @@ int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_db)return -EINVAL ; } +if (epf->db_msg) +return -EBUSY ; + domain =of_msi_map_get_device_domain (epc->dev.parent,0 ,DOMAIN_BUS_PLATFORM_MSI );if (!domain) {
@@ -79,6 +82,8 @@ int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_db)if (ret) {dev_err (dev,"Failed to allocate MSI\n" );kfree (msg); + epf->db_msg =NULL ; + epf->num_db =0 ;return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 192/957 drm/sun4i: backend: fix error pointer dereference
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ethan Tidmore <[email protected]>
[ Upstream commit 06277983eca4a31d3c2114fa33d99a6e82484b11 ]
The function drm_atomic_get_plane_state() can return an error pointer and is not checked for it. Add error pointer check.
Detected by Smatch:drivers/gpu/drm/sun4i/sun4i_backend.c:496 sun4i_backend_atomic_check() error:
'plane_state' dereferencing possible ERR_PTR()
--- drivers/gpu/drm/sun4i/sun4i_backend.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/sun4i/sun4i_backend.c +3 -0
@@ -490,6 +490,9 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,drm_for_each_plane_mask (plane, drm, crtc_state->plane_mask) {struct drm_plane_state *plane_state =drm_atomic_get_plane_state (state, plane); +if (IS_ERR (plane_state)) +return PTR_ERR (plane_state); +struct sun4i_layer_state *layer_state =state_to_sun4i_layer_state (plane_state);struct drm_framebuffer *fb = plane_state->fb;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 193/957 PCI: imx6: Fix device node reference leak in imx_pcie_probe()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Gu <[email protected]>
[ Upstream commit 3b55079d6387805ede687e234d84669aeb0f7e98 ]
In imx_pcie_probe(), of_parse_phandle() returns the device node pointer with increased refcount. The pointer reference must be dropped by the caller when it's no longer needed. However, imx_pcie_probe() doesn't drop the reference, causing reference leak.
Fix this by using the __free(device_node) cleanup handler to drop the reference when the function goes out of scope.
--- drivers/pci/controller/dwc/pci-imx6.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/pci/controller/dwc/pci-imx6.c +2 -2
@@ -1619,7 +1619,6 @@ static int imx_pcie_probe(struct platform_device *pdev)struct device *dev = &pdev->dev;struct dw_pcie *pci;struct imx_pcie *imx_pcie; -struct device_node *np;struct device_node *node = dev->of_node;int ret, domain;u16 val;
@@ -1646,7 +1645,8 @@ static int imx_pcie_probe(struct platform_device *pdev) pci->pp.ops = &imx_pcie_host_dw_pme_ops;/* Find the PHY if one is defined, only imx7d uses it */ - np =of_parse_phandle (node,"fsl,imx7d-pcie-phy" ,0 ); + struct device_node *np __free(device_node) = +of_parse_phandle (node,"fsl,imx7d-pcie-phy" ,0 );if (np) {struct resource res;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 194/957 ASoC: SDCA: Update counting of SU/GE DAPM routes
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Charles Keepax <[email protected]>
[ Upstream commit 1fb720d33eecdb9a90ee340b3000ba378d49f5ca ]
Device Layer Selector Unit's are controlled by a Group Entity control rather than by the host directly. For the purposes of the ASoC class driver the number of input routes to the SU is controlled by the number of options within the Group Entity Selected Mode Control. ie. One valid DAPM route for each valid route defined in the Group Entity.
Currently the code assumes that a Device Layer SU will have a number of routes equal to the number of potential sources for the SU. ie. it counts the routes using the SU, but then creates the routes using the GE. However, this isn't actually true, it is perfectly allowed for the GE to only define options for some of the potential sources of the SU.o In such a case the number of routes return will not match those created, leading to either an overflow of the routes array or undefined routes to be past to the ASoC core, both of which generally lead to the sound card failing to probe.
Update the handling for the counting of routes to count the connected routes on the GE itself and then ignore the source routes on the SU. This makes it match the logic generating the routes and ensuring that both remain in sync.
--- sound/soc/sdca/sdca_asoc.c | 41 +++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-)
sound/soc/sdca/sdca_asoc.c +34 -7
@@ -51,6 +51,25 @@ static bool readonly_control(struct sdca_control *control)return control->has_fixed || control->mode ==SDCA_ACCESS_MODE_RO ; } +static int ge_count_routes (struct sdca_entity *entity) +{ +int count =0 ; +int i, j; + +for (i =0 ; i < entity->ge.num_modes; i++) { +struct sdca_ge_mode *mode = &entity->ge.modes[i]; + +for (j =0 ; j < mode->num_controls; j++) { +struct sdca_ge_control *affected = &mode->controls[j]; + +if (affected->sel !=SDCA_CTL_SU_SELECTOR || affected->val) + count++; + } + } + +return count; +} +/** * sdca_asoc_count_component - count the various component parts * @dev: Pointer to the device against which allocations will be done.
@@ -74,6 +93,7 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *fun int *num_widgets, int *num_routes, int *num_controls, int *num_dais) { + struct sdca_control *control;int i, j; *num_widgets = function->num_entities -1 ;
@@ -83,6 +103,7 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *funfor (i =0 ; i < function->num_entities -1 ; i++) {struct sdca_entity *entity = &function->entities[i]; +bool skip_primary_routes = false;/* Add supply/DAI widget connections */ switch (entity->type) {
@@ -96,6 +117,17 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *funcase SDCA_ENTITY_TYPE_PDE : *num_routes += entity->pde.num_managed;break ; +case SDCA_ENTITY_TYPE_GE : + *num_routes +=ge_count_routes (entity); + skip_primary_routes = true; +break ; +case SDCA_ENTITY_TYPE_SU : + control =sdca_selector_find_control (dev, entity,SDCA_CTL_SU_SELECTOR ); +if (!control) +return -EINVAL ; + + skip_primary_routes = (control->layers ==SDCA_ACCESS_LAYER_DEVICE ); +break ;default :break ; }
@@ -104,7 +136,8 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *fun (*num_routes)++;/* Add primary entity connections from DisCo */ - *num_routes += entity->num_sources; +if (!skip_primary_routes) + *num_routes += entity->num_sources;for (j =0 ; j < entity->num_controls; j++) {if (exported_control (entity, &entity->controls[j]))
@@ -451,7 +484,6 @@ static int entity_parse_su_device(struct device *dev, struct snd_soc_dapm_route **route) {struct sdca_control_range *range; -int num_routes =0 ;int i, j;if (!entity->group) {
@@ -487,11 +519,6 @@ static int entity_parse_su_device(struct device *dev,return -EINVAL ; } -if (++num_routes > entity->num_sources) { -dev_err (dev,"%s: too many input routes\n" , entity->label); -return -EINVAL ; - } - term =sdca_range_search (range,SDCA_SELECTED_MODE_INDEX , mode->val,SDCA_SELECTED_MODE_TERM_TYPE );if (!term) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 195/957 crypto: inside-secure/eip93 - fix register definition
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksander Jan Bajkowski <[email protected]>
[ Upstream commit b7abbc8c7acaeb60c114b038f1fa91bbedb3d16a ]
Checked the register definitions with the documentation[1]. Turns out that the PKTE_INBUF_CNT register has a bad offset. It's used in Direct Host Mode (DHM). The driver uses Autonomous Ring Mode (ARM), so it causes no harm.
1. ADSP-SC58x/ADSP-2158x SHARC+ Processor Hardware Reference
--- drivers/crypto/inside-secure/eip93/eip93-regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/crypto/inside-secure/eip93/eip93-regs.h +1 -1
@@ -109,7 +109,7 @@#define EIP93_REG_PE_BUF_THRESH 0x10c#define EIP93_PE_OUTBUF_THRESH GENMASK(23, 16)#define EIP93_PE_INBUF_THRESH GENMASK(7, 0) -#define EIP93_REG_PE_INBUF_COUNT 0x100 +#define EIP93_REG_PE_INBUF_COUNT 0x110#define EIP93_REG_PE_OUTBUF_COUNT 0x114#define EIP93_REG_PE_BUF_RW_PNTR 0x118/* BUF_PNTR */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 196/957 ASoC: sti: Return errors from regmap_field_alloc()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sander Vanheule <[email protected]>
[ Upstream commit 272aabef50bc3fe58edd26de000f4cdd41bdbe60 ]
When regmap_field_alloc() fails, it can return an error. Specifically, it will return PTR_ERR(-ENOMEM) when the allocation returns a NULL pointer. The code then uses these allocations with a simple NULL check:
if (player->clk_sel) {
// May dereference invalid pointer (-ENOMEM)
err = regmap_field_write(player->clk_sel, ...);
}Ensure initialization fails by forwarding the errors from regmap_field_alloc(), thus avoiding the use of the invalid pointers.
--- sound/soc/sti/uniperif_player.c | 5 +++++ 1 file changed, 5 insertions(+)
sound/soc/sti/uniperif_player.c +5 -0
@@ -1029,7 +1029,12 @@ static int uni_player_parse_dt_audio_glue(struct platform_device *pdev, } player->clk_sel =regmap_field_alloc (regmap, regfield[0 ]); +if (IS_ERR (player->clk_sel)) +return PTR_ERR (player->clk_sel); + player->valid_sel =regmap_field_alloc (regmap, regfield[1 ]); +if (IS_ERR (player->valid_sel)) +return PTR_ERR (player->valid_sel);return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 197/957 ASoC: sti: use managed regmap_field allocations
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sander Vanheule <[email protected]>
[ Upstream commit 1696fad8b259a2d46e51cd6e17e4bcdbe02279fa ]
The regmap_field objects allocated at player init are never freed and may leak resources if the driver is removed.
Switch to devm_regmap_field_alloc() to automatically limit the lifetime of the allocations the lifetime of the device.
--- sound/soc/sti/uniperif_player.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
sound/soc/sti/uniperif_player.c +2 -2
@@ -1028,11 +1028,11 @@ static int uni_player_parse_dt_audio_glue(struct platform_device *pdev,return PTR_ERR (regmap); } - player->clk_sel =regmap_field_alloc (regmap, regfield[0 ]); + player->clk_sel =devm_regmap_field_alloc (&pdev->dev, regmap, regfield[0 ]);if (IS_ERR (player->clk_sel))return PTR_ERR (player->clk_sel); - player->valid_sel =regmap_field_alloc (regmap, regfield[1 ]); + player->valid_sel =devm_regmap_field_alloc (&pdev->dev, regmap, regfield[1 ]);if (IS_ERR (player->valid_sel))return PTR_ERR (player->valid_sel);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 198/957 dm cache: fix null-deref with concurrent writes in passthrough mode
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming-Hung Tsai <[email protected]>
[ Upstream commit 7d1f98d668ee34c1d15bdc0420fdd062f24a27c0 ]
In passthrough mode, when dm-cache starts to invalidate a cache entry and bio prison cell lock fails due to concurrent write to the same cached block, mg->cell remains NULL. The error path in invalidate_complete() attempts to unlock and free the cell unconditionally, causing a NULL pointer dereference:
KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] CPU: 0 UID: 0 PID: 134 Comm: fio Not tainted 6.19.0-rc7 #3 PREEMPT RIP: 0010:dm_cell_unlock_v2+0x3f/0x210 <snip> Call Trace: invalidate_complete+0xef/0x430 map_bio+0x130f/0x1a10 cache_map+0x320/0x6b0 __map_bio+0x458/0x510 dm_submit_bio+0x40e/0x16d0 __submit_bio+0x419/0x870
<snip>
Reproduce steps:
1. Create a cache device
dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" dmsetup create cdata --table "0 131072 linear /dev/sdc 8192" dmsetup create corig --table "0 262144 linear /dev/sdc 262144" dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 oflag=direct dmsetup create cache --table "0 262144 cache /dev/mapper/cmeta \/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"
2. Promote the first data block into cache
fio --filename=/dev/mapper/cache --name=populate --rw=write --bs=4k \
--direct=1 --size=64k
3. Reload the cache into passthrough mode
dmsetup suspend cache
dmsetup reload cache --table "0 262144 cache /dev/mapper/cmeta \/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 passthrough smq 0" dmsetup resume cache
4. Write to the first cached block concurrently
fio --filename=/dev/mapper/cache --name test --rw=randwrite --bs=4k \
--randrepeat=0 --direct=1 --numjobs=2 --size 64k
Fix by checking if mg->cell is valid before attempting to unlock it.
--- drivers/md/dm-cache-target.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/md/dm-cache-target.c +4 -2
@@ -1462,8 +1462,10 @@ static void invalidate_complete(struct dm_cache_migration *mg, bool success)struct cache *cache = mg->cache;bio_list_init (&bios); -if (dm_cell_unlock_v2 (cache->prison, mg->cell, &bios)) -free_prison_cell (cache, mg->cell); +if (mg->cell) { +if (dm_cell_unlock_v2 (cache->prison, mg->cell, &bios)) +free_prison_cell (cache, mg->cell); + }if (!success && mg->overwrite_bio)bio_io_error (mg->overwrite_bio);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 199/957 dm cache: fix write path cache coherency in passthrough mode
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming-Hung Tsai <[email protected]>
[ Upstream commit 0c5eef0aad508231d8e43ff8392692925e131b68 ]
In passthrough mode, dm-cache defers write bio submission until cache invalidation completes to maintain existing coherency, requiring the target map function to return DM_MAPIO_SUBMITTED. The current map_bio() returns DM_MAPIO_REMAPPED, violating the required ordering constraint.
Reproduce steps:
1. Create a cache device
dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" dmsetup create cdata --table "0 131072 linear /dev/sdc 8192" dmsetup create corig --table "0 262144 linear /dev/sdc 262144" dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 oflag=direct dmsetup create cache --table "0 262144 cache /dev/mapper/cmeta \/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"
2. Promote the first data block into the cache
fio --filename=/dev/mapper/cache --name=populate --rw=write --bs=4k \
--direct=1 --size=64k
3. Reload the cache into passthrough mode
dmsetup suspend cache
dmsetup reload cache --table "0 262144 cache /dev/mapper/cmeta \/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 passthrough smq 0" dmsetup resume cache
4. Write to the first data block, and check io ordering using ftrace
echo 1 > /sys/kernel/debug/tracing/events/block/block_bio_queue/enable echo 1 > /sys/kernel/debug/tracing/events/block/block_bio_complete/enable echo 1 > /sys/kernel/debug/tracing/events/block/block_rq_complete/enable fio --filename=/dev/mapper/cache --name=test --rw=write --bs=64k \
--direct=1 --size 64k
5. ftrace logs show that write operations to the cache origin (252:2) and metadata operations (252:0) are unsynchronized: the origin write occurs before metadata commit.
<snip>
fio-146 [000] ..... 420.139562: block_bio_queue: 252,3 WS 0 + 128 [fio]
fio-146 [000] ..... 420.149395: block_bio_queue: 252,2 WS 0 + 128 [fio]
fio-146 [000] ..... 420.149763: block_bio_queue: 8,32 WS 262144 + 128 [fio]
fio-146 [000] dNh1. 420.151446: block_rq_complete: 8,32 WS () 262144 + 128 be,0,4 [0]
fio-146 [000] dNh1. 420.152731: block_bio_complete: 252,2 WS 0 + 128 [0]
fio-146 [000] dNh1. 420.154229: block_bio_complete: 252,3 WS 0 + 128 [0]
kworker/0:0-9 [000] ..... 420.160530: block_bio_queue: 252,0 W 408 + 8 [kworker/0:0]
kworker/0:0-9 [000] ..... 420.161641: block_bio_queue: 8,32 W 408 + 8 [kworker/0:0]
kworker/0:0-9 [000] ..... 420.162533: block_bio_queue: 252,0 W 416 + 8 [kworker/0:0]
kworker/0:0-9 [000] ..... 420.162821: block_bio_queue: 8,32 W 416 + 8 [kworker/0:0]<snip>
--- drivers/md/dm-cache-target.c | 1 + 1 file changed, 1 insertion(+)
drivers/md/dm-cache-target.c +1 -0
@@ -1703,6 +1703,7 @@ static int map_bio(struct cache *cache, struct bio *bio, dm_oblock_t block,bio_drop_shared_lock (cache, bio);atomic_inc (&cache->stats.demotion);invalidate_start (cache, cblock, block, bio); +return DM_MAPIO_SUBMITTED ; }else remap_to_origin_clear_discard (cache, bio, block); }else {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 200/957 dm cache: fix write hang in passthrough mode
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming-Hung Tsai <[email protected]>
[ Upstream commit 4ca8b8bd952df7c3ccdc68af9bd3419d0839a04b ]
The invalidate_remove() function has incomplete logic for handling write hit bios after cache invalidation. It sets up the remapping for the overwrite_bio but then drops it immediately without submission, causing write operations to hang.
Fix by adding a new invalidate_committed() continuation that submits the remapped writes to the cache origin after metadata commit completes, while using the overwrite_endio hook to ensure proper completion sequencing. This maintains existing coherency. Also improve error handling in invalidate_complete() to preserve the original error status instead of using bio_io_error() unconditionally.
--- drivers/md/dm-cache-target.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-)
drivers/md/dm-cache-target.c +25 -5
@@ -1467,8 +1467,14 @@ static void invalidate_complete(struct dm_cache_migration *mg, bool success)free_prison_cell (cache, mg->cell); } -if (!success && mg->overwrite_bio) -bio_io_error (mg->overwrite_bio); +if (mg->overwrite_bio) { +// Set generic error if the bio hasn't been issued yet, +// e.g., invalidation or metadata commit failed before bio +// submission. Otherwise preserve the bio's own error status. +if (!success && !mg->overwrite_bio->bi_status) + mg->overwrite_bio->bi_status =BLK_STS_IOERR ; +bio_endio (mg->overwrite_bio); + }free_migration (mg);defer_bios (cache, &bios);
@@ -1508,6 +1514,22 @@ static int invalidate_cblock(struct cache *cache, dm_cblock_t cblock)return r; } +static void invalidate_committed (struct work_struct *ws) +{ +struct dm_cache_migration *mg =ws_to_mg (ws); +struct cache *cache = mg->cache; +struct bio *bio = mg->overwrite_bio; +struct per_bio_data *pb =get_per_bio_data (bio); + +if (mg->k.input) +invalidate_complete (mg, false); + +init_continuation (&mg->k, invalidate_completed); +remap_to_origin_clear_discard (cache, bio, mg->invalidate_oblock); +dm_hook_bio (&pb->hook_info, bio, overwrite_endio, mg); +dm_submit_bio_remap (bio,NULL ); +} +static void invalidate_remove (struct work_struct *ws) {int r;
@@ -1520,10 +1542,8 @@ static void invalidate_remove(struct work_struct *ws)return ; } -init_continuation (&mg->k, invalidate_completed); +init_continuation (&mg->k, invalidate_committed);continue_after_commit (&cache->committer, &mg->k); -remap_to_origin_clear_discard (cache, mg->overwrite_bio, mg->invalidate_oblock); - mg->overwrite_bio =NULL ;schedule_commit (&cache->committer); }
Signature · 1 line
2.53.0