6.16.8-rc1 review
Greg Kroah-Hartman
maintainerPATCH 128/189 net: phylink: add lock for serializing concurrent pl->phydev writes with resolver
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Oltean <[email protected]>
[ Upstream commit 0ba5b2f2c381dbec9ed9e4ab3ae5d3e667de0dc3 ]
Currently phylink_resolve() protects itself against concurrent phylink_bringup_phy() or phylink_disconnect_phy() calls which modify pl->phydev by relying on pl->state_mutex.
The problem is that in phylink_resolve(), pl->state_mutex is in a lock inversion state with pl->phydev->lock. So pl->phydev->lock needs to be acquired prior to pl->state_mutex. But that requires dereferencing pl->phydev in the first place, and without pl->state_mutex, that is racy.
Hence the reason for the extra lock. Currently it is redundant, but it will serve a functional purpose once mutex_lock(&phy->lock) will be moved outside of the mutex_lock(&pl->state_mutex) section.
Another alternative considered would have been to let phylink_resolve() acquire the rtnl_mutex, which is also held when phylink_bringup_phy() and phylink_disconnect_phy() are called. But since phylink_disconnect_phy() runs under rtnl_lock(), it would deadlock with phylink_resolve() when calling flush_work(&pl->resolve). Additionally, it would have been undesirable because it would have unnecessarily blocked many other call paths as well in the entire kernel, so the smaller-scoped lock was preferred.
Stable-dep-of: e2a10daba849 ("net: phy: transfer phy_config_inband() locking responsibility to phylink")
--- drivers/net/phy/phylink.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
drivers/net/phy/phylink.c +16 -3
@@ -67,6 +67,8 @@ struct phylink {struct timer_list link_poll;struct mutex state_mutex; +/* Serialize updates to pl->phydev with phylink_resolve() */ +struct mutex phydev_mutex;struct phylink_link_state phy_state;unsigned int phy_ib_mode;struct work_struct resolve;
@@ -1568,8 +1570,11 @@ static void phylink_resolve(struct work_struct *w)struct phylink_link_state link_state;bool mac_config = false;bool retrigger = false; +struct phy_device *phy;bool cur_link_state; +mutex_lock (&pl->phydev_mutex); + phy = pl->phydev;mutex_lock (&pl->state_mutex); cur_link_state =phylink_link_is_up (pl);
@@ -1603,11 +1608,11 @@ static void phylink_resolve(struct work_struct *w)/* If we have a phy, the "up" state is the union of both the * PHY and the MAC */ -if (pl->phydev) +if (phy) link_state.link &= pl->phy_state.link;/* Only update if the PHY link is up */ -if (pl->phydev && pl->phy_state.link) { +if (phy && pl->phy_state.link) {/* If the interface has changed, force a link down * event if the link isn't already down, and re-resolve. */
@@ -1671,6 +1676,7 @@ static void phylink_resolve(struct work_struct *w)queue_work (system_power_efficient_wq, &pl->resolve); }mutex_unlock (&pl->state_mutex); +mutex_unlock (&pl->phydev_mutex); }static void phylink_run_resolve (struct phylink *pl)
@@ -1806,6 +1812,7 @@ struct phylink *phylink_create(struct phylink_config *config,if (!pl)return ERR_PTR (-ENOMEM ); +mutex_init (&pl->phydev_mutex);mutex_init (&pl->state_mutex);INIT_WORK (&pl->resolve, phylink_resolve);
@@ -2066,6 +2073,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, dev_name(&phy->mdio.dev), phy->drv->name, irq_str);kfree (irq_str); +mutex_lock (&pl->phydev_mutex);mutex_lock (&phy->lock);mutex_lock (&pl->state_mutex); pl->phydev = phy;
@@ -2111,6 +2119,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,mutex_unlock (&pl->state_mutex);mutex_unlock (&phy->lock); +mutex_unlock (&pl->phydev_mutex); phylink_dbg(pl, "phy: %s setting supported %*pb advertising %*pb\n",
@@ -2289,6 +2298,7 @@ void phylink_disconnect_phy(struct phylink *pl)ASSERT_RTNL (); +mutex_lock (&pl->phydev_mutex); phy = pl->phydev;if (phy) {mutex_lock (&phy->lock);
@@ -2298,8 +2308,11 @@ void phylink_disconnect_phy(struct phylink *pl) pl->mac_tx_clk_stop = false;mutex_unlock (&pl->state_mutex);mutex_unlock (&phy->lock); -flush_work (&pl->resolve); + } +mutex_unlock (&pl->phydev_mutex); +if (phy) { +flush_work (&pl->resolve);phy_disconnect (phy); } }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 129/189 net: phy: transfer phy_config_inband() locking responsibility to phylink
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Oltean <[email protected]>
[ Upstream commit e2a10daba84968f6b5777d150985fd7d6abc9c84 ]
Problem description
===================
Lockdep reports a possible circular locking dependency (AB/BA) between &pl->state_mutex and &phy->lock, as follows.
phylink_resolve() // acquires &pl->state_mutex -> phylink_major_config()
-> phy_config_inband() // acquires &pl->phydev->lock
whereas all the other call sites where &pl->state_mutex and &pl->phydev->lock have the locking scheme reversed. Everywhere else, &pl->phydev->lock is acquired at the top level, and &pl->state_mutex at the lower level. A clear example is phylink_bringup_phy().
The outlier is the newly introduced phy_config_inband() and the existing lock order is the correct one. To understand why it cannot be the other way around, it is sufficient to consider phylink_phy_change(), phylink's callback from the PHY device's phy->phy_link_change() virtual method, invoked by the PHY state machine.
phy_link_up() and phy_link_down(), the (indirect) callers of phylink_phy_change(), are called with &phydev->lock acquired. Then phylink_phy_change() acquires its own &pl->state_mutex, to serialize changes made to its pl->phy_state and pl->link_config. So all other instances of &pl->state_mutex and &phydev->lock must be consistent with this order.
Problem impact
==============
I think the kernel runs a serious deadlock risk if an existing phylink_resolve() thread, which results in a phy_config_inband() call, is concurrent with a phy_link_up() or phy_link_down() call, which will deadlock on &pl->state_mutex in phylink_phy_change(). Practically speaking, the impact may be limited by the slow speed of the medium auto-negotiation protocol, which makes it unlikely for the current state to still be unresolved when a new one is detected, but I think the problem is there. Nonetheless, the problem was discovered using lockdep.
Proposed solution
=================
Practically speaking, the phy_config_inband() requirement of having phydev->lock acquired must transfer to the caller (phylink is the only caller). There, it must bubble up until immediately before &pl->state_mutex is acquired, for the cases where that takes place.
Solution details, considerations, notes
=======================================
This is the phy_config_inband() call graph:
sfp_upstream_ops :: connect_phy()
|
v
phylink_sfp_connect_phy()
|
v
phylink_sfp_config_phy()
|
| sfp_upstream_ops :: module_insert()
| |
| v
| phylink_sfp_module_insert()
| |
| | sfp_upstream_ops :: module_start()
| | |
| | v
| | phylink_sfp_module_start()
| | |
| v v
| phylink_sfp_config_optical()
phylink_start() | |
| phylink_resume() v v
| | phylink_sfp_set_config()
| | |
v v v
phylink_mac_initial_config()
| phylink_resolve()
| | phylink_ethtool_ksettings_set()
v v v
phylink_major_config()
|
v
phy_config_inband()phylink_major_config() caller #1, phylink_mac_initial_config(), does not acquire &pl->state_mutex nor do its callers. It must acquire &pl->phydev->lock prior to calling phylink_major_config().
phylink_major_config() caller #2, phylink_resolve() acquires &pl->state_mutex, thus also needs to acquire &pl->phydev->lock.
phylink_major_config() caller #3, phylink_ethtool_ksettings_set(), is completely uninteresting, because it only calls phylink_major_config() if pl->phydev is NULL (otherwise it calls phy_ethtool_ksettings_set()). We need to change nothing there.
Other solutions
===============
The lock inversion between &pl->state_mutex and &pl->phydev->lock has occurred at least once before, as seen in commit c718af2d00a3 ("net:
phylink: fix ethtool -A with attached PHYs"). The solution there was to simply not call phy_set_asym_pause() under the &pl->state_mutex. That cannot be extended to our case though, where the phy_config_inband() call is much deeper inside the &pl->state_mutex section.
--- drivers/net/phy/phy.c | 12 ++++-------- drivers/net/phy/phylink.c | 9 +++++++++ 2 files changed, 13 insertions(+), 8 deletions(-)
drivers/net/phy/phy.c +4 -8
@@ -1065,23 +1065,19 @@ EXPORT_SYMBOL_GPL(phy_inband_caps);*/ int phy_config_inband (struct phy_device *phydev,unsigned int modes) { -int err; +lockdep_assert_held (&phydev->lock);if (!!(modes &LINK_INBAND_DISABLE ) + !!(modes &LINK_INBAND_ENABLE ) + !!(modes &LINK_INBAND_BYPASS ) !=1 )return -EINVAL ; -mutex_lock (&phydev->lock);if (!phydev->drv) - err = -EIO ; +return -EIO ;else if (!phydev->drv->config_inband) - err = -EOPNOTSUPP ; -else - err = phydev->drv->config_inband (phydev, modes); -mutex_unlock (&phydev->lock); +return -EOPNOTSUPP ; -return err; +return phydev->drv->config_inband (phydev, modes); }EXPORT_SYMBOL (phy_config_inband);
drivers/net/phy/phylink.c +9 -0
@@ -1411,6 +1411,7 @@ static void phylink_get_fixed_state(struct phylink *pl,static void phylink_mac_initial_config (struct phylink *pl,bool force_restart) {struct phylink_link_state link_state; +struct phy_device *phy = pl->phydev;switch (pl->req_link_an_mode) {case MLO_AN_PHY :
@@ -1434,7 +1435,11 @@ static void phylink_mac_initial_config(struct phylink *pl, bool force_restart) link_state.link = false;phylink_apply_manual_flow (pl, &link_state); +if (phy) +mutex_lock (&phy->lock);phylink_major_config (pl, force_restart, &link_state); +if (phy) +mutex_unlock (&phy->lock); }static const char *phylink_pause_to_str (int pause)
@@ -1575,6 +1580,8 @@ static void phylink_resolve(struct work_struct *w)mutex_lock (&pl->phydev_mutex); phy = pl->phydev; +if (phy) +mutex_lock (&phy->lock);mutex_lock (&pl->state_mutex); cur_link_state =phylink_link_is_up (pl);
@@ -1676,6 +1683,8 @@ static void phylink_resolve(struct work_struct *w)queue_work (system_power_efficient_wq, &pl->resolve); }mutex_unlock (&pl->state_mutex); +if (phy) +mutex_unlock (&phy->lock);mutex_unlock (&pl->phydev_mutex); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 130/189 wifi: ath12k: Fix missing station power save configuration
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miaoqing Pan <[email protected]>
[ Upstream commit 4b66d18918f8e4d85e51974a9e3ce9abad5c7c3d ]
Commit afbab6e4e88d ("wifi: ath12k: modify ath12k_mac_op_bss_info_changed() for MLO") replaced the bss_info_changed() callback with vif_cfg_changed() and link_info_changed() to support Multi-Link Operation (MLO). As a result, the station power save configuration is no longer correctly applied in ath12k_mac_bss_info_changed().
Move the handling of 'BSS_CHANGED_PS' into ath12k_mac_op_vif_cfg_changed() to align with the updated callback structure introduced for MLO, ensuring proper power-save behavior for station interfaces.
Tested-on: WCN7850 hw2.0 PCI WLAN.IOE_HMT.1.1-00011-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1
--- drivers/net/wireless/ath/ath12k/mac.c | 122 ++++++++++++++------------ 1 file changed, 67 insertions(+), 55 deletions(-)
drivers/net/wireless/ath/ath12k/mac.c +67 -55
@@ -3650,12 +3650,68 @@ static int ath12k_mac_fils_discovery(struct ath12k_link_vif *arvif,return ret; } +static void ath12k_mac_vif_setup_ps (struct ath12k_link_vif *arvif) +{ +struct ath12k *ar = arvif->ar; +struct ieee80211_vif *vif = arvif->ahvif->vif; +struct ieee80211_conf *conf = &ath12k_ar_to_hw (ar)->conf; +enum wmi_sta_powersave_param param; +struct ieee80211_bss_conf *info; +enum wmi_sta_ps_mode psmode; +int ret; +int timeout; +bool enable_ps; + +lockdep_assert_wiphy (ath12k_ar_to_hw (ar)->wiphy); + +if (vif->type !=NL80211_IFTYPE_STATION ) +return ; + + enable_ps = arvif->ahvif->ps; +if (enable_ps) { + psmode =WMI_STA_PS_MODE_ENABLED ; + param =WMI_STA_PS_PARAM_INACTIVITY_TIME ; + + timeout = conf->dynamic_ps_timeout; +if (timeout ==0 ) { + info =ath12k_mac_get_link_bss_conf (arvif); +if (!info) { +ath12k_warn (ar->ab,"unable to access bss link conf in setup ps for vif %pM link %u\n" , + vif->addr, arvif->link_id); +return ; + } + +/* firmware doesn't like 0 */ + timeout =ieee80211_tu_to_usec (info->beacon_int) /1000 ; + } + + ret =ath12k_wmi_set_sta_ps_param (ar, arvif->vdev_id, param, + timeout); +if (ret) { +ath12k_warn (ar->ab,"failed to set inactivity time for vdev %d: %i\n" , + arvif->vdev_id, ret); +return ; + } + }else { + psmode =WMI_STA_PS_MODE_DISABLED ; + } + +ath12k_dbg (ar->ab,ATH12K_DBG_MAC ,"mac vdev %d psmode %s\n" , + arvif->vdev_id, psmode ?"enable" :"disable" ); + + ret =ath12k_wmi_pdev_set_ps_mode (ar, arvif->vdev_id, psmode); +if (ret) +ath12k_warn (ar->ab,"failed to set sta power save mode %d for vdev %d: %d\n" , + psmode, arvif->vdev_id, ret); +} +static void ath12k_mac_op_vif_cfg_changed (struct ieee80211_hw *hw,struct ieee80211_vif *vif,u64 changed) {struct ath12k_vif *ahvif =ath12k_vif_to_ahvif (vif);unsigned long links = ahvif->links_map; +struct ieee80211_vif_cfg *vif_cfg;struct ieee80211_bss_conf *info;struct ath12k_link_vif *arvif;struct ieee80211_sta *sta;
@@ -3719,61 +3775,24 @@ static void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw, } } } -} - -static void ath12k_mac_vif_setup_ps (struct ath12k_link_vif *arvif) -{ -struct ath12k *ar = arvif->ar; -struct ieee80211_vif *vif = arvif->ahvif->vif; -struct ieee80211_conf *conf = &ath12k_ar_to_hw (ar)->conf; -enum wmi_sta_powersave_param param; -struct ieee80211_bss_conf *info; -enum wmi_sta_ps_mode psmode; -int ret; -int timeout; -bool enable_ps; -lockdep_assert_wiphy (ath12k_ar_to_hw (ar)->wiphy); +if (changed &BSS_CHANGED_PS ) { + links = ahvif->links_map; + vif_cfg = &vif->cfg; -if (vif->type !=NL80211_IFTYPE_STATION ) -return ; +for_each_set_bit (link_id, &links,IEEE80211_MLD_MAX_NUM_LINKS ) { + arvif =wiphy_dereference (hw->wiphy, ahvif->link[link_id]); +if (!arvif || !arvif->ar) +continue ; - enable_ps = arvif->ahvif->ps; -if (enable_ps) { - psmode =WMI_STA_PS_MODE_ENABLED ; - param =WMI_STA_PS_PARAM_INACTIVITY_TIME ; + ar = arvif->ar; - timeout = conf->dynamic_ps_timeout; -if (timeout ==0 ) { - info =ath12k_mac_get_link_bss_conf (arvif); -if (!info) { -ath12k_warn (ar->ab,"unable to access bss link conf in setup ps for vif %pM link %u\n" , - vif->addr, arvif->link_id); -return ; +if (ar->ab->hw_params->supports_sta_ps) { + ahvif->ps = vif_cfg->ps; +ath12k_mac_vif_setup_ps (arvif); } - -/* firmware doesn't like 0 */ - timeout =ieee80211_tu_to_usec (info->beacon_int) /1000 ; } - - ret =ath12k_wmi_set_sta_ps_param (ar, arvif->vdev_id, param, - timeout); -if (ret) { -ath12k_warn (ar->ab,"failed to set inactivity time for vdev %d: %i\n" , - arvif->vdev_id, ret); -return ; - } - }else { - psmode =WMI_STA_PS_MODE_DISABLED ; } - -ath12k_dbg (ar->ab,ATH12K_DBG_MAC ,"mac vdev %d psmode %s\n" , - arvif->vdev_id, psmode ?"enable" :"disable" ); - - ret =ath12k_wmi_pdev_set_ps_mode (ar, arvif->vdev_id, psmode); -if (ret) -ath12k_warn (ar->ab,"failed to set sta power save mode %d for vdev %d: %d\n" , - psmode, arvif->vdev_id, ret); } static bool ath12k_mac_supports_station_tpc(struct ath12k *ar,
@@ -3795,7 +3814,6 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, {struct ath12k_vif *ahvif = arvif->ahvif;struct ieee80211_vif *vif =ath12k_ahvif_to_vif (ahvif); -struct ieee80211_vif_cfg *vif_cfg = &vif->cfg;struct cfg80211_chan_def def;u32 param_id, param_value;enum nl80211_band band;
@@ -4069,12 +4087,6 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar, }ath12k_mac_fils_discovery (arvif, info); - -if (changed &BSS_CHANGED_PS && - ar->ab->hw_params->supports_sta_ps) { - ahvif->ps = vif_cfg->ps; -ath12k_mac_vif_setup_ps (arvif); - } } static struct ath12k_vif_cache *ath12k_ahvif_get_link_cache(struct ath12k_vif *ahvif,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 131/189 wifi: ath12k: add link support for multi-link in arsta
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sarika Sharma <[email protected]>
[ Upstream commit 3b8aa249d0fce93590888a6ed3d22b458091ecb9 ]
Currently, statistics in arsta are updated at deflink for both non-ML and multi-link(ML) station. Link statistics are not updated for multi-link operation(MLO).
Hence, add support to correctly obtain the link ID if the peer is ML, fetch the arsta from the appropriate link ID, and update the statistics in the corresponding arsta.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1
Stable-dep-of: 82e2be57d544 ("wifi: ath12k: fix WMI TLV header misalignment")
--- drivers/net/wireless/ath/ath12k/dp_mon.c | 22 ++++++++++++++------ drivers/net/wireless/ath/ath12k/dp_rx.c | 11 +++++----- drivers/net/wireless/ath/ath12k/peer.h | 26 ++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 11 deletions(-)
drivers/net/wireless/ath/ath12k/dp_mon.c +16 -6
@@ -3610,7 +3610,6 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar, struct hal_rx_mon_ppdu_info *ppdu_info, u32 uid) { -struct ath12k_sta *ahsta;struct ath12k_link_sta *arsta;struct ath12k_rx_peer_stats *rx_stats =NULL ;struct hal_rx_user_status *user_stats = &ppdu_info->userstats[uid];
@@ -3628,8 +3627,13 @@ ath12k_dp_mon_rx_update_user_stats(struct ath12k *ar,return ; } - ahsta =ath12k_sta_to_ahsta (peer->sta); - arsta = &ahsta->deflink; + arsta =ath12k_peer_get_link_sta (ar->ab, peer); +if (!arsta) { +ath12k_warn (ar->ab,"link sta not found on peer %pM id %d\n" , + peer->addr, peer->peer_id); +return ; + } + arsta->rssi_comb = ppdu_info->rssi_comb;ewma_avg_rssi_add (&arsta->avg_rssi, ppdu_info->rssi_comb); rx_stats = arsta->rx_stats;
@@ -3742,7 +3746,6 @@ int ath12k_dp_mon_srng_process(struct ath12k *ar, int *budget,struct dp_srng *mon_dst_ring;struct hal_srng *srng;struct dp_rxdma_mon_ring *buf_ring; -struct ath12k_sta *ahsta =NULL ;struct ath12k_link_sta *arsta;struct ath12k_peer *peer;struct sk_buff_head skb_list;
@@ -3868,8 +3871,15 @@ int ath12k_dp_mon_srng_process(struct ath12k *ar, int *budget, }if (ppdu_info->reception_type ==HAL_RX_RECEPTION_TYPE_SU ) { - ahsta =ath12k_sta_to_ahsta (peer->sta); - arsta = &ahsta->deflink; + arsta =ath12k_peer_get_link_sta (ar->ab, peer); +if (!arsta) { +ath12k_warn (ar->ab,"link sta not found on peer %pM id %d\n" , + peer->addr, peer->peer_id); +spin_unlock_bh (&ab->base_lock); +rcu_read_unlock (); +dev_kfree_skb_any (skb); +continue ; + }ath12k_dp_mon_rx_update_peer_su_stats (ar, arsta, ppdu_info); } else if ((ppdu_info->fc_valid) &&
drivers/net/wireless/ath/ath12k/dp_rx.c +6 -5
@@ -1418,8 +1418,6 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar, {struct ath12k_base *ab = ar->ab;struct ath12k_peer *peer; -struct ieee80211_sta *sta; -struct ath12k_sta *ahsta;struct ath12k_link_sta *arsta;struct htt_ppdu_stats_user_rate *user_rate;struct ath12k_per_peer_tx_stats *peer_stats = &ar->peer_tx_stats;
@@ -1500,9 +1498,12 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar,return ; } - sta = peer->sta; - ahsta =ath12k_sta_to_ahsta (sta); - arsta = &ahsta->deflink; + arsta =ath12k_peer_get_link_sta (ab, peer); +if (!arsta) { +spin_unlock_bh (&ab->base_lock); +rcu_read_unlock (); +return ; + }memset (&arsta->txrate,0 ,sizeof (arsta->txrate));
drivers/net/wireless/ath/ath12k/peer.h +26 -0
@@ -91,5 +91,31 @@ struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, int ast_hashint ath12k_peer_ml_create (struct ath12k_hw *ah,struct ieee80211_sta *sta);int ath12k_peer_ml_delete (struct ath12k_hw *ah,struct ieee80211_sta *sta);int ath12k_peer_mlo_link_peers_delete (struct ath12k_vif *ahvif,struct ath12k_sta *ahsta); +static inline +struct ath12k_link_sta *ath12k_peer_get_link_sta (struct ath12k_base *ab, +struct ath12k_peer *peer) +{ +struct ath12k_sta *ahsta; +struct ath12k_link_sta *arsta; + +if (!peer->sta) +return NULL ; + + ahsta =ath12k_sta_to_ahsta (peer->sta); +if (peer->ml_id &ATH12K_PEER_ML_ID_VALID ) { +if (!(ahsta->links_map &BIT (peer->link_id))) { +ath12k_warn (ab,"peer %pM id %d link_id %d can't found in STA link_map 0x%x\n" , + peer->addr, peer->peer_id, peer->link_id, + ahsta->links_map); +return NULL ; + } + arsta =rcu_dereference (ahsta->link[peer->link_id]); +if (!arsta) +return NULL ; + }else { + arsta = &ahsta->deflink; + } +return arsta; +}#endif /* _PEER_H_ */
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 132/189 wifi: ath12k: Add support to enqueue management frame at MLD level
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sriram R <[email protected]>
[ Upstream commit 9d2abd4162fca8a1eb46f664268dffad35c8ad20 ]
A multi-link client can use any link for transmissions. It can decide to put one link in power save mode for longer periods while listening on the other links as per MLD listen interval. Unicast management frames sent to that link station might get dropped if that link station is in power save mode or inactive. In such cases, firmware can take decision on which link to use.
Allow the firmware to decide on which link management frame should be sent on, by filling the hardware link with maximum value of u32, so that the firmware will not have a specific link to transmit data on and so the management frames will be link agnostic. For QCN devices, all action frames are marked as link agnostic. For WCN devices, if the device is configured as an AP, then all frames other than probe response frames, authentication frames, association response frames, re-association response frames and ADDBA response frames are marked as link agnostic and if the device is configured as a station, then all frames other than probe request frames, authentication frames, de-authentication frames and ADDBA response frames are marked as link agnostic.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
Stable-dep-of: 82e2be57d544 ("wifi: ath12k: fix WMI TLV header misalignment")
--- drivers/net/wireless/ath/ath12k/core.h | 1 + drivers/net/wireless/ath/ath12k/hw.c | 55 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/hw.h | 2 + drivers/net/wireless/ath/ath12k/mac.c | 5 ++- drivers/net/wireless/ath/ath12k/peer.c | 2 +- drivers/net/wireless/ath/ath12k/peer.h | 2 + drivers/net/wireless/ath/ath12k/wmi.c | 56 ++++++++++++++++++++++++-- drivers/net/wireless/ath/ath12k/wmi.h | 16 +++++++- 8 files changed, 131 insertions(+), 8 deletions(-)
drivers/net/wireless/ath/ath12k/core.h +1 -0
@@ -116,6 +116,7 @@ static inline u64 ath12k_le32hilo_to_u64(__le32 hi, __le32 lo)enum ath12k_skb_flags {ATH12K_SKB_HW_80211_ENCAP =BIT (0 ),ATH12K_SKB_CIPHER_SET =BIT (1 ), +ATH12K_SKB_MLO_STA =BIT (2 ), };struct ath12k_skb_cb {
drivers/net/wireless/ath/ath12k/hw.c +55 -0
85 lines not on this page · raw message
drivers/net/wireless/ath/ath12k/hw.h +2 -0
@@ -246,6 +246,8 @@ struct ath12k_hw_ops {int (*rxdma_ring_sel_config)(struct ath12k_base *ab);u8 (*get_ring_selector)(struct sk_buff *skb);bool (*dp_srng_is_tx_comp_ring)(int ring_num); +bool (*is_frame_link_agnostic)(struct ath12k_link_vif *arvif, +struct ieee80211_mgmt *mgmt); }; static inline
drivers/net/wireless/ath/ath12k/mac.c +4 -1
@@ -7685,7 +7685,7 @@ static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_link_vif *arv skb_cb->paddr = paddr; - ret =ath12k_wmi_mgmt_send (ar, arvif->vdev_id, buf_id, skb); + ret =ath12k_wmi_mgmt_send (arvif, buf_id, skb);if (ret) {ath12k_warn (ar->ab,"failed to send mgmt frame: %d\n" , ret); goto err_unmap_buf;
@@ -7997,6 +7997,9 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw, skb_cb->flags |=ATH12K_SKB_HW_80211_ENCAP ; }else if (ieee80211_is_mgmt (hdr->frame_control)) { +if (sta && sta->mlo) + skb_cb->flags |=ATH12K_SKB_MLO_STA ; + ret =ath12k_mac_mgmt_tx (ar, skb, is_prb_rsp);if (ret) { ath12k_warn(ar->ab, "failed to queue management frame %d\n",
drivers/net/wireless/ath/ath12k/peer.c +1 -1
@@ -8,7 +8,7 @@#include "peer.h" #include "debug.h" -static struct ath12k_ml_peer *ath12k_peer_ml_find (struct ath12k_hw *ah,const u8 *addr) +struct ath12k_ml_peer *ath12k_peer_ml_find (struct ath12k_hw *ah,const u8 *addr) {struct ath12k_ml_peer *ml_peer;
drivers/net/wireless/ath/ath12k/peer.h +2 -0
@@ -91,6 +91,8 @@ struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, int ast_hashint ath12k_peer_ml_create (struct ath12k_hw *ah,struct ieee80211_sta *sta);int ath12k_peer_ml_delete (struct ath12k_hw *ah,struct ieee80211_sta *sta);int ath12k_peer_mlo_link_peers_delete (struct ath12k_vif *ahvif,struct ath12k_sta *ahsta); +struct ath12k_ml_peer *ath12k_peer_ml_find (struct ath12k_hw *ah, +const u8 *addr);static inline struct ath12k_link_sta *ath12k_peer_get_link_sta (struct ath12k_base *ab,struct ath12k_peer *peer)
drivers/net/wireless/ath/ath12k/wmi.c +52 -4
78 lines not on this page · raw message
drivers/net/wireless/ath/ath12k/wmi.h +14 -2
@@ -3963,6 +3963,7 @@ struct wmi_scan_chan_list_cmd { } __packed;#define WMI_MGMT_SEND_DOWNLD_LEN 64 +#define WMI_MGMT_LINK_AGNOSTIC_ID 0xFFFFFFFF#define WMI_TX_PARAMS_DWORD0_POWER GENMASK(7, 0)#define WMI_TX_PARAMS_DWORD0_MCS_MASK GENMASK(19, 8)
@@ -3988,7 +3989,18 @@ struct wmi_mgmt_send_cmd {/* This TLV is followed by struct wmi_mgmt_frame */ -/* Followed by struct wmi_mgmt_send_params */ +/* Followed by struct ath12k_wmi_mlo_mgmt_send_params */ +} __packed; + +struct ath12k_wmi_mlo_mgmt_send_params { +__le32 tlv_header; +__le32 hw_link_id; +} __packed; + +struct ath12k_wmi_mgmt_send_tx_params { +__le32 tlv_header; +__le32 tx_param_dword0; +__le32 tx_param_dword1; } __packed;struct wmi_sta_powersave_mode_cmd {
@@ -6183,7 +6195,7 @@ void ath12k_wmi_init_wcn7850(struct ath12k_base *ab,int ath12k_wmi_cmd_send (struct ath12k_wmi_pdev *wmi,struct sk_buff *skb,u32 cmd_id);struct sk_buff *ath12k_wmi_alloc_skb (struct ath12k_wmi_base *wmi_sc,u32 len); -int ath12k_wmi_mgmt_send (struct ath12k *ar,u32 vdev_id,u32 buf_id, +int ath12k_wmi_mgmt_send (struct ath12k_link_vif *arvif,u32 buf_id,struct sk_buff *frame);int ath12k_wmi_p2p_go_bcn_ie (struct ath12k *ar,u32 vdev_id,const u8 *p2p_ie);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 133/189 wifi: ath12k: fix WMI TLV header misalignment
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miaoqing Pan <[email protected]>
[ Upstream commit 82e2be57d544ff9ad4696c85600827b39be8ce9e ]
When buf_len is not 4-byte aligned in ath12k_wmi_mgmt_send(), the firmware asserts and triggers a recovery. The following error messages are observed:
ath12k_pci 0004:01:00.0: failed to submit WMI_MGMT_TX_SEND_CMDID cmd ath12k_pci 0004:01:00.0: failed to send mgmt frame: -108 ath12k_pci 0004:01:00.0: failed to tx mgmt frame, vdev_id 0 :-108 ath12k_pci 0004:01:00.0: waiting recovery start...
This issue was observed when running 'iw wlanx set power_save off/on' in MLO station mode, which triggers the sending of an SMPS action frame with a length of 27 bytes to the AP. To resolve the misalignment, use buf_len_aligned instead of buf_len when constructing the WMI TLV header.
Tested-on: WCN7850 hw2.0 PCI WLAN.IOE_HMT.1.1-00011-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1
--- drivers/net/wireless/ath/ath12k/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/ath/ath12k/wmi.c +1 -1
@@ -840,7 +840,7 @@ int ath12k_wmi_mgmt_send(struct ath12k_link_vif *arvif, u32 buf_id, cmd->tx_params_valid =0 ; frame_tlv = (struct wmi_tlv *)(skb->data +sizeof (*cmd)); - frame_tlv->header =ath12k_wmi_tlv_hdr (WMI_TAG_ARRAY_BYTE , buf_len); + frame_tlv->header =ath12k_wmi_tlv_hdr (WMI_TAG_ARRAY_BYTE , buf_len_aligned);memcpy (frame_tlv->value, frame->data, buf_len);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 134/189 PCI: mvebu: Fix use of for_each_of_range() iterator
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Klaus Kudielka <[email protected]>
[ Upstream commit b816265396daf1beb915e0ffbfd7f3906c2bf4a4 ]
5da3d94a23c6 ("PCI: mvebu: Use for_each_of_range() iterator for parsing "ranges"") simplified code by using the for_each_of_range() iterator, but it broke PCI enumeration on Turris Omnia (and probably other mvebu targets).
Issue #1:
To determine range.flags, of_pci_range_parser_one() uses bus->get_flags(), which resolves to of_bus_pci_get_flags(), which already returns an IORESOURCE bit field, and NOT the original flags from the "ranges" resource.
Then mvebu_get_tgt_attr() attempts the very same conversion again. Remove the misinterpretation of range.flags in mvebu_get_tgt_attr(), to restore the intended behavior.
Issue #2:
The driver needs target and attributes, which are encoded in the raw address values of the "/soc/pcie/ranges" resource. According to of_pci_range_parser_one(), the raw values are stored in range.bus_addr and range.parent_bus_addr, respectively. range.cpu_addr is a translated version of range.parent_bus_addr, and not relevant here.
Use the correct range structure member, to extract target and attributes. This restores the intended behavior.
--- drivers/pci/controller/pci-mvebu.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-)
drivers/pci/controller/pci-mvebu.c +4 -17
@@ -1168,12 +1168,6 @@ static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev,return devm_ioremap_resource (&pdev->dev, &port->regs); } -#define DT_FLAGS_TO_TYPE (flags) (((flags) >> 24) & 0x03) -#define DT_TYPE_IO 0x1 -#define DT_TYPE_MEM32 0x2 -#define DT_CPUADDR_TO_TARGET (cpuaddr) (((cpuaddr) >> 56) & 0xFF) -#define DT_CPUADDR_TO_ATTR (cpuaddr) (((cpuaddr) >> 48) & 0xFF) - static int mvebu_get_tgt_attr(struct device_node *np, int devfn, unsigned long type, unsigned int *tgt,
@@ -1189,19 +1183,12 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,return -EINVAL ;for_each_of_range (&parser, &range) { -unsigned long rtype;u32 slot =upper_32_bits (range.bus_addr); -if (DT_FLAGS_TO_TYPE (range.flags) ==DT_TYPE_IO ) - rtype =IORESOURCE_IO ; -else if (DT_FLAGS_TO_TYPE (range.flags) ==DT_TYPE_MEM32 ) - rtype =IORESOURCE_MEM ; -else -continue ; - -if (slot ==PCI_SLOT (devfn) && type == rtype) { - *tgt =DT_CPUADDR_TO_TARGET (range.cpu_addr); - *attr =DT_CPUADDR_TO_ATTR (range.cpu_addr); +if (slot ==PCI_SLOT (devfn) && + type == (range.flags &IORESOURCE_TYPE_BITS )) { + *tgt = (range.parent_bus_addr >>56 ) &0xFF ; + *attr = (range.parent_bus_addr >>48 ) &0xFF ;return 0 ; } }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 135/189 genetlink: fix genl_bind() invoking bind() after -EPERM
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alok Tiwari <[email protected]>
[ Upstream commit 1dbfb0363224f6da56f6655d596dc5097308d6f5 ]
Per family bind/unbind callbacks were introduced to allow families to track multicast group consumer presence, e.g. to start or stop producing events depending on listeners.
However, in genl_bind() the bind() callback was invoked even if capability checks failed and ret was set to -EPERM. This means that callbacks could run on behalf of unauthorized callers while the syscall still returned failure to user space.
Fix this by only invoking bind() after "if (ret) break;" check i.e. after permission checks have succeeded.
--- net/netlink/genetlink.c | 3 +++ 1 file changed, 3 insertions(+)
net/netlink/genetlink.c +3 -0
@@ -1836,6 +1836,9 @@ static int genl_bind(struct net *net, int group) !ns_capable(net->user_ns, CAP_SYS_ADMIN)) ret = -EPERM ; +if (ret) +break ; +if (family->bind) family->bind (i);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 136/189 net: dsa: b53: fix ageing time for BCM53101
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit 674b34c4c770551e916ae707829c7faea4782d3a ]
For some reason Broadcom decided that BCM53101 uses 0.5s increments for the ageing time register, but kept the field width the same [1]. Due to this, the actual ageing time was always half of what was configured.
Fix this by adapting the limits and value calculation for BCM53101.
So far it looks like this is the only chip with the increased tick speed:
$ grep -l -r "Specifies the aging time in 0.5 seconds" cdk/PKG/chip | sort cdk/PKG/chip/bcm53101/bcm53101_a0_defs.h
$ grep -l -r "Specifies the aging time in seconds" cdk/PKG/chip | sort cdk/PKG/chip/bcm53010/bcm53010_a0_defs.h cdk/PKG/chip/bcm53020/bcm53020_a0_defs.h cdk/PKG/chip/bcm53084/bcm53084_a0_defs.h cdk/PKG/chip/bcm53115/bcm53115_a0_defs.h cdk/PKG/chip/bcm53118/bcm53118_a0_defs.h cdk/PKG/chip/bcm53125/bcm53125_a0_defs.h cdk/PKG/chip/bcm53128/bcm53128_a0_defs.h cdk/PKG/chip/bcm53134/bcm53134_a0_defs.h cdk/PKG/chip/bcm53242/bcm53242_a0_defs.h cdk/PKG/chip/bcm53262/bcm53262_a0_defs.h cdk/PKG/chip/bcm53280/bcm53280_a0_defs.h cdk/PKG/chip/bcm53280/bcm53280_b0_defs.h cdk/PKG/chip/bcm53600/bcm53600_a0_defs.h cdk/PKG/chip/bcm89500/bcm89500_a0_defs.h
--- drivers/net/dsa/b53/b53_common.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
drivers/net/dsa/b53/b53_common.c +13 -4
@@ -1229,9 +1229,15 @@ static int b53_setup(struct dsa_switch *ds)*/ ds->untag_vlan_aware_bridge_pvid = true; -/* Ageing time is set in seconds */ - ds->ageing_time_min =1 *1000 ; - ds->ageing_time_max =AGE_TIME_MAX *1000 ; +if (dev->chip_id ==BCM53101_DEVICE_ID ) { +/* BCM53101 uses 0.5 second increments */ + ds->ageing_time_min =1 *500 ; + ds->ageing_time_max =AGE_TIME_MAX *500 ; + }else { +/* Everything else uses 1 second increments */ + ds->ageing_time_min =1 *1000 ; + ds->ageing_time_max =AGE_TIME_MAX *1000 ; + } ret =b53_reset_switch (dev);if (ret) {
@@ -2448,7 +2454,10 @@ int b53_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)else reg =B53_AGING_TIME_CONTROL ; - atc =DIV_ROUND_CLOSEST (msecs,1000 ); +if (dev->chip_id ==BCM53101_DEVICE_ID ) + atc =DIV_ROUND_CLOSEST (msecs,500 ); +else + atc =DIV_ROUND_CLOSEST (msecs,1000 );if (!is5325 (dev) && !is5365 (dev)) atc |=AGE_CHANGE ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 137/189 net: bridge: Bounce invalid boolopts
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Petr Machata <[email protected]>
[ Upstream commit 8625f5748fea960d2af4f3c3e9891ee8f6f80906 ]
The bridge driver currently tolerates options that it does not recognize. Instead, it should bounce them.
--- net/bridge/br.c | 7 +++++++ 1 file changed, 7 insertions(+)
net/bridge/br.c +7 -0
@@ -324,6 +324,13 @@ int br_boolopt_multi_toggle(struct net_bridge *br,int err =0 ;int opt_id; + opt_id =find_next_bit (&bitmap,BITS_PER_LONG ,BR_BOOLOPT_MAX ); +if (opt_id !=BITS_PER_LONG ) { +NL_SET_ERR_MSG_FMT_MOD (extack,"Unknown boolean option %d" , + opt_id); +return -EINVAL ; + } +for_each_set_bit (opt_id, &bitmap,BR_BOOLOPT_MAX ) {bool on = !!(bm->optval &BIT (opt_id));
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 138/189 tunnels: reset the GSO metadata before reusing the skb
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Antoine Tenart <[email protected]>
[ Upstream commit e3c674db356c4303804b2415e7c2b11776cdd8c3 ]
If a GSO skb is sent through a Geneve tunnel and if Geneve options are added, the split GSO skb might not fit in the MTU anymore and an ICMP frag needed packet can be generated. In such case the ICMP packet might go through the segmentation logic (and dropped) later if it reaches a path were the GSO status is checked and segmentation is required.
This is especially true when an OvS bridge is used with a Geneve tunnel attached to it. The following set of actions could lead to the ICMP packet being wrongfully segmented:
1. An skb is constructed by the TCP layer (e.g. gso_type SKB_GSO_TCPV4, segs >= 2).
2. The skb hits the OvS bridge where Geneve options are added by an OvS action before being sent through the tunnel.
3. When the skb is xmited in the tunnel, the split skb does not fit anymore in the MTU and iptunnel_pmtud_build_icmp is called to generate an ICMP fragmentation needed packet. This is done by reusing the original (GSO!) skb. The GSO metadata is not cleared.
4. The ICMP packet being sent back hits the OvS bridge again and because skb_is_gso returns true, it goes through queue_gso_packets...
5. ...where __skb_gso_segment is called. The skb is then dropped.
6. Note that in the above example on re-transmission the skb won't be a GSO one as it would be segmented (len > MSS) and the ICMP packet should go through.
Fix this by resetting the GSO information before reusing an skb in iptunnel_pmtud_build_icmp and iptunnel_pmtud_build_icmpv6.
--- net/ipv4/ip_tunnel_core.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/ipv4/ip_tunnel_core.c +6 -0
@@ -204,6 +204,9 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)if (!pskb_may_pull (skb,ETH_HLEN +sizeof (struct iphdr )))return -EINVAL ; +if (skb_is_gso (skb)) +skb_gso_reset (skb); +skb_copy_bits (skb,skb_mac_offset (skb), &eh,ETH_HLEN );pskb_pull (skb,ETH_HLEN );skb_reset_network_header (skb);
@@ -298,6 +301,9 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)if (!pskb_may_pull (skb,ETH_HLEN +sizeof (struct ipv6hdr )))return -EINVAL ; +if (skb_is_gso (skb)) +skb_gso_reset (skb); +skb_copy_bits (skb,skb_mac_offset (skb), &eh,ETH_HLEN );pskb_pull (skb,ETH_HLEN );skb_reset_network_header (skb);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 139/189 docs: networking: can: change bcm_msg_head frames member to support flexible array
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Tran <[email protected]>
[ Upstream commit 641427d5bf90af0625081bf27555418b101274cd ]
The documentation of the 'bcm_msg_head' struct does not match how it is defined in 'bcm.h'. Changed the frames member to a flexible array, matching the definition in the header file.
See commit 94dfc73e7cf4 ("treewide: uapi: Replace zero-length arrays with flexible-array members")
--- Documentation/networking/can.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/networking/can.rst +1 -1
@@ -742,7 +742,7 @@ The broadcast manager sends responses to user space in the same form: struct timeval ival1, ival2; /* count and subsequent interval */ canid_t can_id; /* unique can_id for task */ __u32 nframes; /* number of can_frames following */ - struct can_frame frames[0]; + struct can_frame frames[]; }; The aligned payload 'frames' uses the same basic CAN frame structure defined
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 140/189 igb: Fix NULL pointer dereference in ethtool loopback test
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tianyu Xu <[email protected]>
[ Upstream commit 75871a525a596ff4d16c4aebc0018f8d0923c9b1 ]
The igb driver currently causes a NULL pointer dereference when executing the ethtool loopback test. This occurs because there is no associated q_vector for the test ring when it is set up, as interrupts are typically not added to the test rings.
Since commit 5ef44b3cb43b removed the napi_id assignment in __xdp_rxq_info_reg(), there is no longer a need to pass a napi_id to it. Therefore, simply use 0 as the last parameter.
--- drivers/net/ethernet/intel/igb/igb_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/ethernet/intel/igb/igb_main.c +1 -2
@@ -4451,8 +4451,7 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)if (xdp_rxq_info_is_reg (&rx_ring->xdp_rxq))xdp_rxq_info_unreg (&rx_ring->xdp_rxq); res =xdp_rxq_info_reg (&rx_ring->xdp_rxq, rx_ring->netdev, - rx_ring->queue_index, - rx_ring->q_vector->napi.napi_id); + rx_ring->queue_index,0 );if (res <0 ) {dev_err (dev,"Failed to register xdp_rxq index %u\n" , rx_ring->queue_index);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 141/189 igb: fix link test skipping when interface is admin down
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kohei Enju <[email protected]>
[ Upstream commit d709f178abca22a4d3642513df29afe4323a594b ]
The igb driver incorrectly skips the link test when the network interface is admin down (if_running == false), causing the test to always report PASS regardless of the actual physical link state.
This behavior is inconsistent with other drivers (e.g. i40e, ice, ixgbe, etc.) which correctly test the physical link state regardless of admin state.
Remove the if_running check to ensure link test always reflects the physical link state.
--- drivers/net/ethernet/intel/igb/igb_ethtool.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/net/ethernet/intel/igb/igb_ethtool.c +1 -4
@@ -2081,11 +2081,8 @@ static void igb_diag_test(struct net_device *netdev, }else {dev_info (&adapter->pdev->dev,"online testing starting\n" ); -/* PHY is powered down when interface is down */ -if (if_running &&igb_link_test (adapter, &data[TEST_LINK ])) +if (igb_link_test (adapter, &data[TEST_LINK ])) eth_test->flags |=ETH_TEST_FL_FAILED ; -else - data[TEST_LINK ] =0 ;/* Online tests aren't run; pass by default */ data[TEST_REG ] =0 ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 142/189 i40e: fix IRQ freeing in i40e_vsi_request_irq_msix error path
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Schmidt <[email protected]>
[ Upstream commit 915470e1b44e71d1dd07ee067276f003c3521ee3 ]
If request_irq() in i40e_vsi_request_irq_msix() fails in an iteration later than the first, the error path wants to free the IRQs requested so far. However, it uses the wrong dev_id argument for free_irq(), so it does not free the IRQs correctly and instead triggers the warning:
Trying to free already-free IRQ 173
WARNING: CPU: 25 PID: 1091 at kernel/irq/manage.c:1829 __free_irq+0x192/0x2c0 Modules linked in: i40e(+) [...] CPU: 25 UID: 0 PID: 1091 Comm: NetworkManager Not tainted 6.17.0-rc1+ #1 PREEMPT(lazy) Hardware name: [...] RIP: 0010:__free_irq+0x192/0x2c0 [...] Call Trace: <TASK> free_irq+0x32/0x70 i40e_vsi_request_irq_msix.cold+0x63/0x8b [i40e] i40e_vsi_request_irq+0x79/0x80 [i40e] i40e_vsi_open+0x21f/0x2f0 [i40e] i40e_open+0x63/0x130 [i40e] __dev_open+0xfc/0x210 __dev_change_flags+0x1fc/0x240 netif_change_flags+0x27/0x70 do_setlink.isra.0+0x341/0xc70 rtnl_newlink+0x468/0x860 rtnetlink_rcv_msg+0x375/0x450 netlink_rcv_skb+0x5c/0x110 netlink_unicast+0x288/0x3c0 netlink_sendmsg+0x20d/0x430 ____sys_sendmsg+0x3a2/0x3d0 ___sys_sendmsg+0x99/0xe0 __sys_sendmsg+0x8a/0xf0 do_syscall_64+0x82/0x2c0 entry_SYSCALL_64_after_hwframe+0x76/0x7e [...] </TASK> ---[ end trace 0000000000000000 ]---
Use the same dev_id for free_irq() as for request_irq().
I tested this with inserting code to fail intentionally.
--- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/intel/i40e/i40e_main.c +1 -1
@@ -4182,7 +4182,7 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename) irq_num = pf->msix_entries[base + vector].vector;irq_set_affinity_notifier (irq_num,NULL );irq_update_affinity_hint (irq_num,NULL ); -free_irq (irq_num, &vsi->q_vectors[vector]); +free_irq (irq_num, vsi->q_vectors[vector]); }return err; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 143/189 drm/xe/configfs: Dont touch survivability_mode on fini
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Wajdeczko <[email protected]>
[ Upstream commit 7934fdc25ad642ab3dbc16d734ab58638520ea60 ]
This is a user controlled configfs attribute, we should not modify that outside the configfs attr.store() implementation.
--- drivers/gpu/drm/xe/xe_survivability_mode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_survivability_mode.c +2 -1
@@ -40,6 +40,8 @@* * # echo 1 > /sys/kernel/config/xe/0000:03:00.0/survivability_mode * +* It is the responsibility of the user to clear the mode once firmware flash is complete. +* * Refer :ref:`xe_configfs` for more details on how to use configfs * * Survivability mode is indicated by the below admin-only readable sysfs which provides additional
@@ -146,7 +148,6 @@ static void xe_survivability_mode_fini(void *arg)struct pci_dev *pdev =to_pci_dev (xe->drm.dev);struct device *dev = &pdev->dev; -xe_configfs_clear_survivability_mode (pdev);sysfs_remove_file (&dev->kobj, &dev_attr_survivability_mode.attr); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 144/189 drm/amd/display: use udelay rather than fsleep
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
[ Upstream commit 1d66c3f2b8c0b5c51f3f4fe29b362c9851190c5a ]
This function can be called from an atomic context so we can't use fsleep().
--- drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +1 -1
@@ -955,7 +955,7 @@ enum dc_status dcn20_enable_stream_timing(return DC_ERROR_UNEXPECTED ; } -fsleep (stream->timing.v_total * (stream->timing.h_total *10000u / stream->timing.pix_clk_100hz)); +udelay (stream->timing.v_total * (stream->timing.h_total *10000u / stream->timing.pix_clk_100hz)); params.vertical_total_min = stream->adjust.v_total_min; params.vertical_total_max = stream->adjust.v_total_max;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 145/189 net: dev_ioctl: take ops lock in hwtstamp lower paths
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Carolina Jubran <[email protected]>
[ Upstream commit 686cab5a18e443e1d5f2abb17bed45837836425f ]
ndo hwtstamp callbacks are expected to run under the per-device ops lock. Make the lower get/set paths consistent with the rest of ndo invocations.
Kernel log:
WARNING: CPU: 13 PID: 51364 at ./include/net/netdev_lock.h:70 __netdev_update_features+0x4bd/0xe60 ... RIP: 0010:__netdev_update_features+0x4bd/0xe60 ... Call Trace: <TASK> netdev_update_features+0x1f/0x60 mlx5_hwtstamp_set+0x181/0x290 [mlx5_core] mlx5e_hwtstamp_set+0x19/0x30 [mlx5_core] dev_set_hwtstamp_phylib+0x9f/0x220 dev_set_hwtstamp_phylib+0x9f/0x220 dev_set_hwtstamp+0x13d/0x240 dev_ioctl+0x12f/0x4b0 sock_ioctl+0x171/0x370 __x64_sys_ioctl+0x3f7/0x900 ? __sys_setsockopt+0x69/0xb0 do_syscall_64+0x6f/0x2e0 entry_SYSCALL_64_after_hwframe+0x4b/0x53 ... </TASK> .... ---[ end trace 0000000000000000 ]---
Note that the mlx5_hwtstamp_set and mlx5e_hwtstamp_set functions shown in the trace come from an in progress patch converting the legacy ioctl to ndo_hwtstamp_get/set and are not present in mainline.
--- net/core/dev_ioctl.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-)
net/core/dev_ioctl.c +18 -4
@@ -464,8 +464,15 @@ int generic_hwtstamp_get_lower(struct net_device *dev,if (!netif_device_present (dev))return -ENODEV ; -if (ops->ndo_hwtstamp_get) -return dev_get_hwtstamp_phylib (dev, kernel_cfg); +if (ops->ndo_hwtstamp_get) { +int err; + +netdev_lock_ops (dev); + err =dev_get_hwtstamp_phylib (dev, kernel_cfg); +netdev_unlock_ops (dev); + +return err; + }/* Legacy path: unconverted lower driver */ return generic_hwtstamp_ioctl_lower (dev,SIOCGHWTSTAMP , kernel_cfg);
@@ -481,8 +488,15 @@ int generic_hwtstamp_set_lower(struct net_device *dev,if (!netif_device_present (dev))return -ENODEV ; -if (ops->ndo_hwtstamp_set) -return dev_set_hwtstamp_phylib (dev, kernel_cfg, extack); +if (ops->ndo_hwtstamp_set) { +int err; + +netdev_lock_ops (dev); + err =dev_set_hwtstamp_phylib (dev, kernel_cfg, extack); +netdev_unlock_ops (dev); + +return err; + }/* Legacy path: unconverted lower driver */ return generic_hwtstamp_ioctl_lower (dev,SIOCSHWTSTAMP , kernel_cfg);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 146/189 macsec: sync features on RTM_NEWLINK
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stanislav Fomichev <[email protected]>
[ Upstream commit 0f82c3ba66c6b2e3cde0f255156a753b108ee9dc ]
Syzkaller managed to lock the lower device via ETHTOOL_SFEATURES:
netdev_lock include/linux/netdevice.h:2761 [inline] netdev_lock_ops include/net/netdev_lock.h:42 [inline] netdev_sync_lower_features net/core/dev.c:10649 [inline] __netdev_update_features+0xcb1/0x1be0 net/core/dev.c:10819 netdev_update_features+0x6d/0xe0 net/core/dev.c:10876 macsec_notify+0x2f5/0x660 drivers/net/macsec.c:4533 notifier_call_chain+0x1b3/0x3e0 kernel/notifier.c:85 call_netdevice_notifiers_extack net/core/dev.c:2267 [inline] call_netdevice_notifiers net/core/dev.c:2281 [inline] netdev_features_change+0x85/0xc0 net/core/dev.c:1570 __dev_ethtool net/ethtool/ioctl.c:3469 [inline] dev_ethtool+0x1536/0x19b0 net/ethtool/ioctl.c:3502 dev_ioctl+0x392/0x1150 net/core/dev_ioctl.c:759
It happens because lower features are out of sync with the upper:
__dev_ethtool (real_dev)
netdev_lock_ops(real_dev)
ETHTOOL_SFEATURES
__netdev_features_change
netdev_sync_upper_features
disable LRO on the lower
if (old_features != dev->features)
netdev_features_change
fires NETDEV_FEAT_CHANGE
macsec_notify
NETDEV_FEAT_CHANGE
netdev_update_features (for each macsec dev)
netdev_sync_lower_features
if (upper_features != lower_features)
netdev_lock_ops(lower) # lower == real_dev
stuck
...
netdev_unlock_ops(real_dev)Per commit af5f54b0ef9e ("net: Lock lower level devices when updating features"), we elide the lock/unlock when the upper and lower features are synced. Makes sure the lower (real_dev) has proper features after the macsec link has been created. This makes sure we never hit the situation where we need to sync upper flags to the lower.
--- drivers/net/macsec.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/macsec.c +1 -0
@@ -4286,6 +4286,7 @@ static int macsec_newlink(struct net_device *dev,if (err <0 ) goto del_dev; +netdev_update_features (dev);netif_stacked_transfer_operstate (real_dev, dev);linkwatch_fire_event (dev);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 147/189 selftests: can: enable CONFIG_CAN_VCAN as a module
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Davide Caratti <[email protected]>
[ Upstream commit d013ebc3499fd87cb9dee1dafd0c58aeb05c27c1 ]
A proper kernel configuration for running kselftest can be obtained with:
$ yes | make kselftest-merge
Build of 'vcan' driver is currently missing, while the other required knobs are already there because of net/link_netns.py [1]. Add a config file in selftests/net/can to store the minimum set of kconfig needed for CAN selftests.
[1] https://patch.msgid.link/[email protected]
--- tools/testing/selftests/net/can/config | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tools/testing/selftests/net/can/config
tools/testing/selftests/net/can/config new file +3 -0
@@ -0,0 +1,3 @@ +CONFIG_CAN=m +CONFIG_CAN_DEV=m +CONFIG_CAN_VCAN=m
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 148/189 can: j1939: implement NETDEV_UNREGISTER notification handler
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tetsuo Handa <[email protected]>
[ Upstream commit 7fcbe5b2c6a4b5407bf2241fdb71e0a390f6ab9a ]
syzbot is reporting
unregister_netdevice: waiting for vcan0 to become free. Usage count = 2
problem, for j1939 protocol did not have NETDEV_UNREGISTER notification handler for undoing changes made by j1939_sk_bind().
Commit 25fe97cb7620 ("can: j1939: move j1939_priv_put() into sk_destruct callback") expects that a call to j1939_priv_put() can be unconditionally delayed until j1939_sk_sock_destruct() is called. But we need to call j1939_priv_put() against an extra ref held by j1939_sk_bind() call (as a part of undoing changes made by j1939_sk_bind()) as soon as NETDEV_UNREGISTER notification fires (i.e. before j1939_sk_sock_destruct() is called via j1939_sk_release()). Otherwise, the extra ref on "struct j1939_priv" held by j1939_sk_bind() call prevents "struct net_device" from dropping the usage count to 1; making it impossible for unregister_netdevice() to continue.
--- net/can/j1939/j1939-priv.h | 1 + net/can/j1939/main.c | 3 +++ net/can/j1939/socket.c | 49 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+)
net/can/j1939/j1939-priv.h +1 -0
@@ -212,6 +212,7 @@ void j1939_priv_get(struct j1939_priv *priv);/* notify/alert all j1939 sockets bound to ifindex */ void j1939_sk_netdev_event_netdown (struct j1939_priv *priv); +void j1939_sk_netdev_event_unregister (struct j1939_priv *priv);int j1939_cancel_active_session (struct j1939_priv *priv,struct sock *sk);void j1939_tp_init (struct j1939_priv *priv);
net/can/j1939/main.c +3 -0
@@ -377,6 +377,9 @@ static int j1939_netdev_notify(struct notifier_block *nb,j1939_sk_netdev_event_netdown (priv);j1939_ecu_unmap_all (priv);break ; +case NETDEV_UNREGISTER : +j1939_sk_netdev_event_unregister (priv); +break ; }j1939_priv_put (priv);
net/can/j1939/socket.c +49 -0
55 lines not on this page · raw message
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 149/189 can: j1939: j1939_sk_bind(): call j1939_priv_put() immediately when j1939_local_ecu_get() failed
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tetsuo Handa <[email protected]>
[ Upstream commit f214744c8a27c3c1da6b538c232da22cd027530e ]
Commit 25fe97cb7620 ("can: j1939: move j1939_priv_put() into sk_destruct callback") expects that a call to j1939_priv_put() can be unconditionally delayed until j1939_sk_sock_destruct() is called. But a refcount leak will happen when j1939_sk_bind() is called again after j1939_local_ecu_get()
from previous j1939_sk_bind() call returned an error. We need to callj1939_priv_put() before j1939_sk_bind() returns an error.
--- net/can/j1939/socket.c | 3 +++ 1 file changed, 3 insertions(+)
net/can/j1939/socket.c +3 -0
@@ -520,6 +520,9 @@ static int j1939_sk_bind(struct socket *sock, struct sockaddr *uaddr, int len) ret =j1939_local_ecu_get (priv, jsk->addr.src_name, jsk->addr.sa);if (ret) {j1939_netdev_stop (priv); + jsk->priv =NULL ; +synchronize_rcu (); +j1939_priv_put (priv); goto out_release_sock; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 150/189 can: j1939: j1939_local_ecu_get(): undo increment when j1939_local_ecu_get() fails
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tetsuo Handa <[email protected]>
[ Upstream commit 06e02da29f6f1a45fc07bd60c7eaf172dc21e334 ]
Since j1939_sk_bind() and j1939_sk_release() call j1939_local_ecu_put() when J1939_SOCK_BOUND was already set, but the error handling path for j1939_sk_bind() will not set J1939_SOCK_BOUND when j1939_local_ecu_get() fails, j1939_local_ecu_get() needs to undo priv->ents[sa].nusers++ when j1939_local_ecu_get() returns an error.
--- net/can/j1939/bus.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/can/j1939/bus.c +4 -1
@@ -290,8 +290,11 @@ int j1939_local_ecu_get(struct j1939_priv *priv, name_t name, u8 sa)if (!ecu) ecu =j1939_ecu_create_locked (priv, name); err =PTR_ERR_OR_ZERO (ecu); -if (err) +if (err) { +if (j1939_address_is_unicast (sa)) + priv->ents[sa].nusers--; goto done; + } ecu->nusers++;/* TODO: do we care if ecu->addr != sa? */
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 151/189 can: xilinx_can: xcan_write_frame(): fix use-after-free of transmitted SKB
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anssi Hannula <[email protected]>
[ Upstream commit ef79f00be72bd81d2e1e6f060d83cf7e425deee4 ]
can_put_echo_skb() takes ownership of the SKB and it may be freed during or after the call.
However, xilinx_can xcan_write_frame() keeps using SKB after the call.
Fix that by only calling can_put_echo_skb() after the code is done touching the SKB.
The tx_lock is held for the entire xcan_write_frame() execution and also on the can_get_echo_skb() side so the order of operations does not matter.
An earlier fix commit 3d3c817c3a40 ("can: xilinx_can: Fix usage of skb memory") did not move the can_put_echo_skb() call far enough.
--- drivers/net/can/xilinx_can.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
drivers/net/can/xilinx_can.c +8 -8
@@ -690,14 +690,6 @@ static void xcan_write_frame(struct net_device *ndev, struct sk_buff *skb, dlc |=XCAN_DLCR_EDL_MASK ; } -if (!(priv->devtype.flags &XCAN_FLAG_TX_MAILBOXES ) && - (priv->devtype.flags &XCAN_FLAG_TXFEMP )) -can_put_echo_skb (skb, ndev, priv->tx_head % priv->tx_max,0 ); -else -can_put_echo_skb (skb, ndev,0 ,0 ); - - priv->tx_head++; - priv->write_reg (priv,XCAN_FRAME_ID_OFFSET (frame_offset), id);/* If the CAN frame is RTR frame this write triggers transmission * (not on CAN FD)
@@ -730,6 +722,14 @@ static void xcan_write_frame(struct net_device *ndev, struct sk_buff *skb, data[1]); } } + +if (!(priv->devtype.flags &XCAN_FLAG_TX_MAILBOXES ) && + (priv->devtype.flags &XCAN_FLAG_TXFEMP )) +can_put_echo_skb (skb, ndev, priv->tx_head % priv->tx_max,0 ); +else +can_put_echo_skb (skb, ndev,0 ,0 ); + + priv->tx_head++; }/**
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 152/189 netfilter: nft_set_bitmap: fix lockdep splat due to missing annotation
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 5e13f2c491a4100d208e77e92fe577fe3dbad6c2 ]
Running new 'set_flush_add_atomic_bitmap' test case for nftables.git with CONFIG_PROVE_RCU_LIST=y yields:
net/netfilter/nft_set_bitmap.c:231 RCU-list traversed in non-reader section!! rcu_scheduler_active = 2, debug_locks = 1
1 lock held by nft/4008:
#0: ffff888147f79cd8 (&nft_net->commit_mutex){+.+.}-{4:4}, at: nf_tables_valid_genid+0x2f/0xd0
lockdep_rcu_suspicious+0x116/0x160 nft_bitmap_walk+0x22d/0x240 nf_tables_delsetelem+0x1010/0x1a00 ..
This is a false positive, the list cannot be altered while the transaction mutex is held, so pass the relevant argument to the iterator.
Fixes tag intentionally wrong; no point in picking this up if earlier false-positive-fixups were not applied.
--- net/netfilter/nft_set_bitmap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/netfilter/nft_set_bitmap.c +2 -1
@@ -221,7 +221,8 @@ static void nft_bitmap_walk(const struct nft_ctx *ctx,const struct nft_bitmap *priv =nft_set_priv (set);struct nft_bitmap_elem *be; -list_for_each_entry_rcu (be, &priv->list, head) { +list_for_each_entry_rcu (be, &priv->list, head, +lockdep_is_held (&nft_pernet (ctx->net)->commit_mutex)) {if (iter->count < iter->skip) goto cont;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 153/189 netfilter: nft_set_pipapo: remove unused arguments
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 7792c1e03054440c60d4bce0c06a31c134601997 ]
They are not used anymore, so remove them.
Stable-dep-of: c4eaca2e1052 ("netfilter: nft_set_pipapo: don't check genbit from packetpath lookups")
--- net/netfilter/nft_set_pipapo.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-)
net/netfilter/nft_set_pipapo.c +5 -9
@@ -502,8 +502,6 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,/** * pipapo_get() - Get matching element reference given key data -* @net: Network namespace -* @set: nftables API set representation * @m: storage containing active/existing elements * @data: Key data to be matched against existing elements * @genmask: If set, check that element is active in given genmask
@@ -516,9 +514,7 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,* * Return: pointer to &struct nft_pipapo_elem on match, error pointer otherwise. */ -static struct nft_pipapo_elem *pipapo_get (const struct net *net, -const struct nft_set *set, -const struct nft_pipapo_match *m, +static struct nft_pipapo_elem *pipapo_get (const struct nft_pipapo_match *m,const u8 *data,u8 genmask,u64 tstamp,gfp_t gfp) {
@@ -615,7 +611,7 @@ nft_pipapo_get(const struct net *net, const struct nft_set *set,struct nft_pipapo_match *m =rcu_dereference (priv->match);struct nft_pipapo_elem *e; - e =pipapo_get (net, set, m, (const u8 *)elem->key.val.data, + e =pipapo_get (m, (const u8 *)elem->key.val.data,nft_genmask_cur (net),get_jiffies_64 (),GFP_ATOMIC );if (IS_ERR (e))
@@ -1344,7 +1340,7 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,else end = start; - dup =pipapo_get (net, set, m, start, genmask, tstamp,GFP_KERNEL ); + dup =pipapo_get (m, start, genmask, tstamp,GFP_KERNEL );if (!IS_ERR (dup)) {/* Check if we already have the same exact entry */ const struct nft_data *dup_key, *dup_end;
@@ -1366,7 +1362,7 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,if (PTR_ERR (dup) == -ENOENT ) {/* Look for partially overlapping entries */ - dup =pipapo_get (net, set, m, end,nft_genmask_next (net), tstamp, + dup =pipapo_get (m, end,nft_genmask_next (net), tstamp,GFP_KERNEL ); }
@@ -1913,7 +1909,7 @@ nft_pipapo_deactivate(const struct net *net, const struct nft_set *set,if (!m)return NULL ; - e =pipapo_get (net, set, m, (const u8 *)elem->key.val.data, + e =pipapo_get (m, (const u8 *)elem->key.val.data,nft_genmask_next (net),nft_net_tstamp (net),GFP_KERNEL );if (IS_ERR (e))return NULL ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 154/189 netfilter: nft_set: remove one argument from lookup and update functions
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 17a20e09f086f2c574ac87f3cf6e14c4377f65f6 ]
Return the extension pointer instead of passing it as a function argument to be filled in by the callee.
As-is, whenever false is returned, the extension pointer is not used.
For all set types, when true is returned, the extension pointer was set to the matching element.
Only exception: nft_set_bitmap doesn't support extensions. Return a pointer to a static const empty element extension container.
return false -> return NULL
return true -> return the elements' extension pointer.
This saves one function argument.
Stable-dep-of: c4eaca2e1052 ("netfilter: nft_set_pipapo: don't check genbit from packetpath lookups")
--- include/net/netfilter/nf_tables.h | 10 ++--- include/net/netfilter/nf_tables_core.h | 47 ++++++++++++---------- net/netfilter/nft_dynset.c | 5 ++- net/netfilter/nft_lookup.c | 27 ++++++------- net/netfilter/nft_objref.c | 5 +-- net/netfilter/nft_set_bitmap.c | 11 ++++-- net/netfilter/nft_set_hash.c | 54 ++++++++++++-------------- net/netfilter/nft_set_pipapo.c | 19 +++++---- net/netfilter/nft_set_pipapo_avx2.c | 25 ++++++------ net/netfilter/nft_set_rbtree.c | 40 +++++++++---------- 10 files changed, 126 insertions(+), 117 deletions(-)
include/net/netfilter/nf_tables.h +4 -6
@@ -459,19 +459,17 @@ struct nft_set_ext;* control plane functions. */ struct nft_set_ops { -bool (*lookup)(const struct net *net, +const struct nft_set_ext * (*lookup)(const struct net *net,const struct nft_set *set, -const u32 *key, -const struct nft_set_ext **ext); -bool (*update)(struct nft_set *set, +const u32 *key); +const struct nft_set_ext * (*update)(struct nft_set *set,const u32 *key,struct nft_elem_priv * (*new)(struct nft_set *,const struct nft_expr *,struct nft_regs *),const struct nft_expr *expr, -struct nft_regs *regs, -const struct nft_set_ext **ext); +struct nft_regs *regs);bool (*delete)(const struct nft_set *set,const u32 *key);
include/net/netfilter/nf_tables_core.h +27 -20
61 lines not on this page · raw message
net/netfilter/nft_dynset.c +3 -2
@@ -91,8 +91,9 @@ void nft_dynset_eval(const struct nft_expr *expr,return ; } -if (set->ops->update (set, ®s->data[priv->sreg_key], nft_dynset_new, - expr, regs, &ext)) { + ext = set->ops->update (set, ®s->data[priv->sreg_key], nft_dynset_new, + expr, regs); +if (ext) {if (priv->op ==NFT_DYNSET_OP_UPDATE &&nft_set_ext_exists (ext,NFT_SET_EXT_TIMEOUT ) &&READ_ONCE (nft_set_ext_timeout (ext)->timeout) !=0 ) {
net/netfilter/nft_lookup.c +14 -13
@@ -25,32 +25,33 @@ struct nft_lookup { };#ifdef CONFIG_MITIGATION_RETPOLINE -bool nft_set_do_lookup (const struct net *net,const struct nft_set *set, -const u32 *key,const struct nft_set_ext **ext) +const struct nft_set_ext * +nft_set_do_lookup (const struct net *net,const struct nft_set *set, +const u32 *key) {if (set->ops == &nft_set_hash_fast_type.ops) -return nft_hash_lookup_fast (net, set, key, ext); +return nft_hash_lookup_fast (net, set, key);if (set->ops == &nft_set_hash_type.ops) -return nft_hash_lookup (net, set, key, ext); +return nft_hash_lookup (net, set, key);if (set->ops == &nft_set_rhash_type.ops) -return nft_rhash_lookup (net, set, key, ext); +return nft_rhash_lookup (net, set, key);if (set->ops == &nft_set_bitmap_type.ops) -return nft_bitmap_lookup (net, set, key, ext); +return nft_bitmap_lookup (net, set, key);if (set->ops == &nft_set_pipapo_type.ops) -return nft_pipapo_lookup (net, set, key, ext); +return nft_pipapo_lookup (net, set, key);#if defined(CONFIG_X86_64 ) && !defined(CONFIG_UML )if (set->ops == &nft_set_pipapo_avx2_type.ops) -return nft_pipapo_avx2_lookup (net, set, key, ext); +return nft_pipapo_avx2_lookup (net, set, key);#endif if (set->ops == &nft_set_rbtree_type.ops) -return nft_rbtree_lookup (net, set, key, ext); +return nft_rbtree_lookup (net, set, key);WARN_ON_ONCE (1 ); -return set->ops->lookup (net, set, key, ext); +return set->ops->lookup (net, set, key); }EXPORT_SYMBOL_GPL (nft_set_do_lookup);#endif
@@ -61,12 +62,12 @@ void nft_lookup_eval(const struct nft_expr *expr, {const struct nft_lookup *priv =nft_expr_priv (expr);const struct nft_set *set = priv->set; -const struct nft_set_ext *ext =NULL ;const struct net *net =nft_net (pkt); +const struct nft_set_ext *ext;bool found; - found =nft_set_do_lookup (net, set, ®s->data[priv->sreg], &ext) ^ - priv->invert; + ext =nft_set_do_lookup (net, set, ®s->data[priv->sreg]); + found = !!ext ^ priv->invert;if (!found) { ext =nft_set_catchall_lookup (net, set);if (!ext) {
net/netfilter/nft_objref.c +2 -3
@@ -111,10 +111,9 @@ void nft_objref_map_eval(const struct nft_expr *expr,struct net *net =nft_net (pkt);const struct nft_set_ext *ext;struct nft_object *obj; -bool found; - found =nft_set_do_lookup (net, set, ®s->data[priv->sreg], &ext); -if (!found) { + ext =nft_set_do_lookup (net, set, ®s->data[priv->sreg]); +if (!ext) { ext =nft_set_catchall_lookup (net, set);if (!ext) { regs->verdict.code =NFT_BREAK ;
net/netfilter/nft_set_bitmap.c +8 -3
@@ -75,16 +75,21 @@ nft_bitmap_active(const u8 *bitmap, u32 idx, u32 off, u8 genmask) }INDIRECT_CALLABLE_SCOPE -bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set, -const u32 *key,const struct nft_set_ext **ext) +const struct nft_set_ext * +nft_bitmap_lookup (const struct net *net,const struct nft_set *set, +const u32 *key) {const struct nft_bitmap *priv =nft_set_priv (set); +static const struct nft_set_ext found;u8 genmask =nft_genmask_cur (net);u32 idx, off;nft_bitmap_location (set, key, &idx, &off); -return nft_bitmap_active (priv->bitmap, idx, off, genmask); +if (nft_bitmap_active (priv->bitmap, idx, off, genmask)) +return &found; + +return NULL ; } static struct nft_bitmap_elem *
net/netfilter/nft_set_hash.c +24 -30
110 lines not on this page · raw message
net/netfilter/nft_set_pipapo.c +11 -8
@@ -407,8 +407,9 @@ int pipapo_refill(unsigned long *map, unsigned int len, unsigned int rules,* * Return: true on match, false otherwise. */ -bool nft_pipapo_lookup (const struct net *net,const struct nft_set *set, -const u32 *key,const struct nft_set_ext **ext) +const struct nft_set_ext * +nft_pipapo_lookup (const struct net *net,const struct nft_set *set, +const u32 *key) {struct nft_pipapo *priv =nft_set_priv (set);struct nft_pipapo_scratch *scratch;
@@ -465,13 +466,15 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set, scratch->map_index = map_index;local_bh_enable (); -return false; +return NULL ; }if (last) { - *ext = &f->mt[b].e->ext; -if (unlikely (nft_set_elem_expired (*ext) || - !nft_set_elem_active (*ext, genmask))) +const struct nft_set_ext *ext; + + ext = &f->mt[b].e->ext; +if (unlikely (nft_set_elem_expired (ext) || + !nft_set_elem_active (ext, genmask))) goto next_match;/* Last field: we're just returning the key without
@@ -482,7 +485,7 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set, scratch->map_index = map_index;local_bh_enable (); -return true; +return ext; }/* Swap bitmap indices: res_map is the initial bitmap for the
@@ -497,7 +500,7 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set, out:local_bh_enable (); -return false; +return NULL ; }/**
net/netfilter/nft_set_pipapo_avx2.c +14 -11
@@ -1146,8 +1146,9 @@ static inline void pipapo_resmap_init_avx2(const struct nft_pipapo_match *m, uns* * Return: true on match, false otherwise. */ -bool nft_pipapo_avx2_lookup (const struct net *net,const struct nft_set *set, -const u32 *key,const struct nft_set_ext **ext) +const struct nft_set_ext * +nft_pipapo_avx2_lookup (const struct net *net,const struct nft_set *set, +const u32 *key) {struct nft_pipapo *priv =nft_set_priv (set);struct nft_pipapo_scratch *scratch;
@@ -1155,17 +1156,18 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,const struct nft_pipapo_match *m;const struct nft_pipapo_field *f;const u8 *rp = (const u8 *)key; +const struct nft_set_ext *ext;unsigned long *res, *fill;bool map_index; -int i, ret =0 ; +int i;local_bh_disable ();if (unlikely (!irq_fpu_usable ())) { -bool fallback_res =nft_pipapo_lookup (net, set, key, ext); + ext =nft_pipapo_lookup (net, set, key);local_bh_enable (); -return fallback_res; +return ext; } m =rcu_dereference (priv->match);
@@ -1182,7 +1184,7 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,if (unlikely (!scratch)) {kernel_fpu_end ();local_bh_enable (); -return false; +return NULL ; } map_index = scratch->map_index;
@@ -1197,6 +1199,7 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, next_match:nft_pipapo_for_each_field (f, i, m) {bool last = i == m->field_count -1 , first = !i; +int ret =0 ;#define NFT_SET_PIPAPO_AVX2_LOOKUP (b, n) \ (ret = nft_pipapo_avx2_lookup_##b##b_##n(res, fill, f, \
@@ -1244,10 +1247,10 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, goto out;if (last) { - *ext = &f->mt[ret].e->ext; -if (unlikely (nft_set_elem_expired (*ext) || - !nft_set_elem_active (*ext, genmask))) { - ret =0 ; + ext = &f->mt[ret].e->ext; +if (unlikely (nft_set_elem_expired (ext) || + !nft_set_elem_active (ext, genmask))) { + ext =NULL ; goto next_match; }
@@ -1264,5 +1267,5 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,kernel_fpu_end ();local_bh_enable (); -return ret >=0 ; +return ext; }
net/netfilter/nft_set_rbtree.c +19 -21
@@ -52,9 +52,9 @@ static bool nft_rbtree_elem_expired(const struct nft_rbtree_elem *rbe)return nft_set_elem_expired (&rbe->ext); } -static bool __nft_rbtree_lookup (const struct net *net,const struct nft_set *set, -const u32 *key,const struct nft_set_ext **ext, -unsigned int seq) +static const struct nft_set_ext * +__nft_rbtree_lookup (const struct net *net,const struct nft_set *set, +const u32 *key,unsigned int seq) {struct nft_rbtree *priv =nft_set_priv (set);const struct nft_rbtree_elem *rbe, *interval =NULL ;
@@ -65,7 +65,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set parent =rcu_dereference_raw (priv->root.rb_node);while (parent !=NULL ) {if (read_seqcount_retry (&priv->count, seq)) -return false; +return NULL ; rbe = rb_entry(parent, struct nft_rbtree_elem, node);
@@ -87,50 +87,48 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set }if (nft_rbtree_elem_expired (rbe)) -return false; +return NULL ;if (nft_rbtree_interval_end (rbe)) {if (nft_set_is_anonymous (set)) -return false; +return NULL ; parent =rcu_dereference_raw (parent->rb_left); interval =NULL ;continue ; } - *ext = &rbe->ext; -return true; +return &rbe->ext; } }if (set->flags &NFT_SET_INTERVAL && interval !=NULL &&nft_set_elem_active (&interval->ext, genmask) && !nft_rbtree_elem_expired (interval) && -nft_rbtree_interval_start (interval)) { - *ext = &interval->ext; -return true; - } +nft_rbtree_interval_start (interval)) +return &interval->ext; -return false; +return NULL ; }INDIRECT_CALLABLE_SCOPE -bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set, -const u32 *key,const struct nft_set_ext **ext) +const struct nft_set_ext * +nft_rbtree_lookup (const struct net *net,const struct nft_set *set, +const u32 *key) {struct nft_rbtree *priv =nft_set_priv (set);unsigned int seq =read_seqcount_begin (&priv->count); -bool ret; +const struct nft_set_ext *ext; - ret =__nft_rbtree_lookup (net, set, key, ext, seq); -if (ret || !read_seqcount_retry (&priv->count, seq)) -return ret; + ext =__nft_rbtree_lookup (net, set, key, seq); +if (ext || !read_seqcount_retry (&priv->count, seq)) +return ext;read_lock_bh (&priv->lock); seq =read_seqcount_begin (&priv->count); - ret =__nft_rbtree_lookup (net, set, key, ext, seq); + ext =__nft_rbtree_lookup (net, set, key, seq);read_unlock_bh (&priv->lock); -return ret; +return ext; } static bool __nft_rbtree_get(const struct net *net, const struct nft_set *set,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 155/189 netfilter: nft_set_pipapo: merge pipapo_get/lookup
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit d8d871a35ca9ee4881d34995444ed1cb826d01db ]
The matching algorithm has implemented thrice:
1. data path lookup, generic version
2. data path lookup, avx2 version
3. control plane lookup
Merge 1 and 3 by refactoring pipapo_get as a common helper, then make nft_pipapo_lookup and nft_pipapo_get both call the common helper.
Aside from the code savings this has the benefit that we no longer allocate temporary scratch maps for each control plane get and insertion operation.
Stable-dep-of: c4eaca2e1052 ("netfilter: nft_set_pipapo: don't check genbit from packetpath lookups")
--- net/netfilter/nft_set_pipapo.c | 188 ++++++++++----------------------- 1 file changed, 58 insertions(+), 130 deletions(-)
net/netfilter/nft_set_pipapo.c +58 -130
@@ -397,35 +397,36 @@ int pipapo_refill(unsigned long *map, unsigned int len, unsigned int rules, }/** -* nft_pipapo_lookup() - Lookup function -* @net: Network namespace -* @set: nftables API set representation -* @key: nftables API element representation containing key data -* @ext: nftables API extension pointer, filled with matching reference +* pipapo_get() - Get matching element reference given key data +* @m: storage containing the set elements +* @data: Key data to be matched against existing elements +* @genmask: If set, check that element is active in given genmask +* @tstamp: timestamp to check for expired elements * * For more details, see DOC: Theory of Operation. * -* Return: true on match, false otherwise. +* This is the main lookup function. It matches key data against either +* the working match set or the uncommitted copy, depending on what the +* caller passed to us. +* nft_pipapo_get (lookup from userspace/control plane) and nft_pipapo_lookup +* (datapath lookup) pass the active copy. +* The insertion path will pass the uncommitted working copy. +* +* Return: pointer to &struct nft_pipapo_elem on match, NULL otherwise. */ -const struct nft_set_ext * -nft_pipapo_lookup (const struct net *net,const struct nft_set *set, -const u32 *key) +static struct nft_pipapo_elem *pipapo_get (const struct nft_pipapo_match *m, +const u8 *data,u8 genmask, +u64 tstamp) { -struct nft_pipapo *priv =nft_set_priv (set);struct nft_pipapo_scratch *scratch;unsigned long *res_map, *fill_map; -u8 genmask =nft_genmask_cur (net); -const struct nft_pipapo_match *m;const struct nft_pipapo_field *f; -const u8 *rp = (const u8 *)key;bool map_index;int i;local_bh_disable (); - m =rcu_dereference (priv->match); - -if (unlikely (!m || !*raw_cpu_ptr (m->scratch))) +if (unlikely (!raw_cpu_ptr (m->scratch))) goto out; scratch = *raw_cpu_ptr (m->scratch);
@@ -445,12 +446,12 @@ nft_pipapo_lookup(const struct net *net, const struct nft_set *set,* packet bytes value, then AND bucket value */ if (likely (f->bb ==8 )) -pipapo_and_field_buckets_8bit (f, res_map, rp); +pipapo_and_field_buckets_8bit (f, res_map, data);else -pipapo_and_field_buckets_4bit (f, res_map, rp); +pipapo_and_field_buckets_4bit (f, res_map, data);NFT_PIPAPO_GROUP_BITS_ARE_8_OR_4 ; - rp += f->groups /NFT_PIPAPO_GROUPS_PER_BYTE (f); + data += f->groups /NFT_PIPAPO_GROUPS_PER_BYTE (f);/* Now populate the bitmap for the next field, unless this is * the last field, in which case return the matched 'ext'
@@ -470,11 +471,11 @@ nft_pipapo_lookup(const struct net *net, const struct nft_set *set, }if (last) { -const struct nft_set_ext *ext; +struct nft_pipapo_elem *e; - ext = &f->mt[b].e->ext; -if (unlikely (nft_set_elem_expired (ext) || - !nft_set_elem_active (ext, genmask))) + e = f->mt[b].e; +if (unlikely (__nft_set_elem_expired (&e->ext, tstamp) || + !nft_set_elem_active (&e->ext, genmask))) goto next_match;/* Last field: we're just returning the key without
@@ -484,8 +485,7 @@ nft_pipapo_lookup(const struct net *net, const struct nft_set *set,*/ scratch->map_index = map_index;local_bh_enable (); - -return ext; +return e; }/* Swap bitmap indices: res_map is the initial bitmap for the
@@ -495,7 +495,7 @@ nft_pipapo_lookup(const struct net *net, const struct nft_set *set, map_index = !map_index;swap (res_map, fill_map); - rp +=NFT_PIPAPO_GROUPS_PADDING (f); + data +=NFT_PIPAPO_GROUPS_PADDING (f); } out:
@@ -504,99 +504,29 @@ nft_pipapo_lookup(const struct net *net, const struct nft_set *set, }/** -* pipapo_get() - Get matching element reference given key data -* @m: storage containing active/existing elements -* @data: Key data to be matched against existing elements -* @genmask: If set, check that element is active in given genmask -* @tstamp: timestamp to check for expired elements -* @gfp: the type of memory to allocate (see kmalloc). +* nft_pipapo_lookup() - Dataplane fronted for main lookup function +* @net: Network namespace +* @set: nftables API set representation +* @key: pointer to nft registers containing key data * -* This is essentially the same as the lookup function, except that it matches -* key data against the uncommitted copy and doesn't use preallocated maps for -* bitmap results. +* This function is called from the data path. It will search for +* an element matching the given key in the current active copy. * -* Return: pointer to &struct nft_pipapo_elem on match, error pointer otherwise. +* Return: ntables API extension pointer or NULL if no match. */ -static struct nft_pipapo_elem *pipapo_get (const struct nft_pipapo_match *m, -const u8 *data,u8 genmask, -u64 tstamp,gfp_t gfp) +const struct nft_set_ext * +nft_pipapo_lookup (const struct net *net,const struct nft_set *set, +const u32 *key) { -struct nft_pipapo_elem *ret =ERR_PTR (-ENOENT ); -unsigned long *res_map, *fill_map =NULL ; -const struct nft_pipapo_field *f; -int i; - -if (m->bsize_max ==0 ) -return ret; - - res_map =kmalloc_array (m->bsize_max,sizeof (*res_map), gfp); -if (!res_map) { - ret =ERR_PTR (-ENOMEM ); - goto out; - } - - fill_map =kcalloc (m->bsize_max,sizeof (*res_map), gfp); -if (!fill_map) { - ret =ERR_PTR (-ENOMEM ); - goto out; - } - -pipapo_resmap_init (m, res_map); - -nft_pipapo_for_each_field (f, i, m) { -bool last = i == m->field_count -1 ; -int b; - -/* For each bit group: select lookup table bucket depending on -* packet bytes value, then AND bucket value -*/ -if (f->bb ==8 ) -pipapo_and_field_buckets_8bit (f, res_map, data); -else if (f->bb ==4 ) -pipapo_and_field_buckets_4bit (f, res_map, data); -else -BUG (); - - data += f->groups /NFT_PIPAPO_GROUPS_PER_BYTE (f); - -/* Now populate the bitmap for the next field, unless this is -* the last field, in which case return the matched 'ext' -* pointer if any. -* -* Now res_map contains the matching bitmap, and fill_map is the -* bitmap for the next field. -*/ -next_match: - b =pipapo_refill (res_map, f->bsize, f->rules, fill_map, f->mt, - last); -if (b <0 ) - goto out; - -if (last) { -if (__nft_set_elem_expired (&f->mt[b].e->ext, tstamp)) - goto next_match; -if ((genmask && - !nft_set_elem_active (&f->mt[b].e->ext, genmask))) - goto next_match; - - ret = f->mt[b].e; - goto out; - } - - data +=NFT_PIPAPO_GROUPS_PADDING (f); +struct nft_pipapo *priv =nft_set_priv (set); +u8 genmask =nft_genmask_cur (net); +const struct nft_pipapo_match *m; +const struct nft_pipapo_elem *e; -/* Swap bitmap indices: fill_map will be the initial bitmap for -* the next field (i.e. the new res_map), and res_map is -* guaranteed to be all-zeroes at this point, ready to be filled -* according to the next mapping table. -*/ -swap (res_map, fill_map); - } + m =rcu_dereference (priv->match); + e =pipapo_get (m, (const u8 *)key, genmask,get_jiffies_64 ()); -out: -kfree (fill_map); -kfree (res_map); -return ret; +return e ? &e->ext :NULL ; }/**
@@ -605,6 +535,11 @@ static struct nft_pipapo_elem *pipapo_get(const struct nft_pipapo_match *m,* @set: nftables API set representation * @elem: nftables API element representation containing key data * @flags: Unused +* +* This function is called from the control plane path under +* RCU read lock. +* +* Return: set element private pointer or ERR_PTR(-ENOENT). */ static struct nft_elem_priv * nft_pipapo_get(const struct net *net, const struct nft_set *set,
@@ -615,10 +550,9 @@ nft_pipapo_get(const struct net *net, const struct nft_set *set,struct nft_pipapo_elem *e; e =pipapo_get (m, (const u8 *)elem->key.val.data, -nft_genmask_cur (net),get_jiffies_64 (), -GFP_ATOMIC ); -if (IS_ERR (e)) -return ERR_CAST (e); +nft_genmask_cur (net),get_jiffies_64 ()); +if (!e) +return ERR_PTR (-ENOENT );return &e->priv; }
@@ -1343,8 +1277,8 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,else end = start; - dup =pipapo_get (m, start, genmask, tstamp,GFP_KERNEL ); -if (!IS_ERR (dup)) { + dup =pipapo_get (m, start, genmask, tstamp); +if (dup) {/* Check if we already have the same exact entry */ const struct nft_data *dup_key, *dup_end;
@@ -1363,15 +1297,9 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,return -ENOTEMPTY ; } -if (PTR_ERR (dup) == -ENOENT ) { -/* Look for partially overlapping entries */ - dup =pipapo_get (m, end,nft_genmask_next (net), tstamp, -GFP_KERNEL ); - } - -if (PTR_ERR (dup) != -ENOENT ) { -if (IS_ERR (dup)) -return PTR_ERR (dup); +/* Look for partially overlapping entries */ + dup =pipapo_get (m, end,nft_genmask_next (net), tstamp); +if (dup) { *elem_priv = &dup->priv;return -ENOTEMPTY ; }
@@ -1913,8 +1841,8 @@ nft_pipapo_deactivate(const struct net *net, const struct nft_set *set,return NULL ; e =pipapo_get (m, (const u8 *)elem->key.val.data, -nft_genmask_next (net),nft_net_tstamp (net),GFP_KERNEL ); -if (IS_ERR (e)) +nft_genmask_next (net),nft_net_tstamp (net)); +if (!e)return NULL ;nft_set_elem_change_active (net, set, &e->ext);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 156/189 netfilter: nft_set_pipapo: dont return bogus extension pointer
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit c8a7c2c608180f3b4e51dc958b3861242dcdd76d ]
Dan Carpenter says:
Commit 17a20e09f086 ("netfilter: nft_set: remove one argument from lookup and update functions") [..] leads to the following Smatch static checker warning:
net/netfilter/nft_set_pipapo_avx2.c:1269 nft_pipapo_avx2_lookup()
error: uninitialized symbol 'ext'.
Fix this by initing ext to NULL and set it only once we've found a match.
Stable-dep-of: c4eaca2e1052 ("netfilter: nft_set_pipapo: don't check genbit from packetpath lookups")
--- net/netfilter/nft_set_pipapo_avx2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
net/netfilter/nft_set_pipapo_avx2.c +6 -6
@@ -1151,12 +1151,12 @@ nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, const u32 *key) {struct nft_pipapo *priv =nft_set_priv (set); +const struct nft_set_ext *ext =NULL ;struct nft_pipapo_scratch *scratch;u8 genmask =nft_genmask_cur (net);const struct nft_pipapo_match *m;const struct nft_pipapo_field *f;const u8 *rp = (const u8 *)key; -const struct nft_set_ext *ext;unsigned long *res, *fill;bool map_index;int i;
@@ -1247,13 +1247,13 @@ nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, goto out;if (last) { - ext = &f->mt[ret].e->ext; -if (unlikely (nft_set_elem_expired (ext) || - !nft_set_elem_active (ext, genmask))) { - ext =NULL ; +const struct nft_set_ext *e = &f->mt[ret].e->ext; + +if (unlikely (nft_set_elem_expired (e) || + !nft_set_elem_active (e, genmask))) goto next_match; - } + ext = e; goto out; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 157/189 netfilter: nft_set_pipapo: dont check genbit from packetpath lookups
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit c4eaca2e1052adfd67bed0a36a9d4b8e515666e4 ]
The pipapo set type is special in that it has two copies of its
datastructure: one live copy containing only valid elements and one on-demand clone used during transaction where adds/deletes happen.
This clone is not visible to the datapath.
This is unlike all other set types in nftables, those all link new elements into their live hlist/tree.
For those sets, the lookup functions must skip the new elements while the transaction is ongoing to ensure consistency.
As the clone is shallow, removal does have an effect on the packet path:
once the transaction enters the commit phase the 'gencursor' bit that determines which elements are active and which elements should be ignored (because they are no longer valid) is flipped.
This causes the datapath lookup to ignore these elements if they are found during lookup.
This opens up a small race window where pipapo has an inconsistent view of the dataset from when the transaction-cpu flipped the genbit until the transaction-cpu calls nft_pipapo_commit() to swap live/clone pointers:
cpu0 cpu1
has added new elements to clone
has marked elements as being
inactive in new generation
perform lookup in the set
enters commit phase:
I) increments the genbit
A) observes new genbit
removes elements from the clone so
they won't be found anymore
B) lookup in datastructure can't see new elements yet, but old elements are ignored -> Only matches elements that were not changed in the transaction
II) calls nft_pipapo_commit(), clone
and live pointers are swapped.
C New nft_lookup happening now
will find matching elements.
Consider a packet matching range r1-r2:
cpu0 processes following transaction:
1. remove r1-r2
2. add r1-r3
P is contained in both ranges. Therefore, cpu1 should always find a match for P. Due to above race, this is not the case:
cpu1 does find r1-r2, but then ignores it due to the genbit indicating the range has been removed.
At the same time, r1-r3 is not visible yet, because it can only be found in the clone.
The situation persists for all lookups until after cpu0 hits II).
The fix is easy: Don't check the genbit from pipapo lookup functions. This is possible because unlike the other set types, the new elements are not reachable from the live copy of the dataset.
The clone/live pointer swap is enough to avoid matching on old elements while at the same time all new elements are exposed in one go.
After this change, step B above returns a match in r1-r2. This is fine: r1-r2 only becomes truly invalid the moment they get freed. This happens after a synchronize_rcu() call and rcu read lock is held via netfilter hook traversal (nf_hook_slow()).
--- net/netfilter/nft_set_pipapo.c | 20 ++++++++++++++++++-- net/netfilter/nft_set_pipapo_avx2.c | 4 +--- 2 files changed, 19 insertions(+), 5 deletions(-)
net/netfilter/nft_set_pipapo.c +18 -2
@@ -511,6 +511,23 @@ static struct nft_pipapo_elem *pipapo_get(const struct nft_pipapo_match *m,* * This function is called from the data path. It will search for * an element matching the given key in the current active copy. +* Unlike other set types, this uses NFT_GENMASK_ANY instead of +* nft_genmask_cur(). +* +* This is because new (future) elements are not reachable from +* priv->match, they get added to priv->clone instead. +* When the commit phase flips the generation bitmask, the +* 'now old' entries are skipped but without the 'now current' +* elements becoming visible. Using nft_genmask_cur() thus creates +* inconsistent state: matching old entries get skipped but thew +* newly matching entries are unreachable. +* +* GENMASK will still find the 'now old' entries which ensures consistent +* priv->match view. +* +* nft_pipapo_commit swaps ->clone and ->match shortly after the +* genbit flip. As ->clone doesn't contain the old entries in the first +* place, lookup will only find the now-current ones. * * Return: ntables API extension pointer or NULL if no match. */
@@ -519,12 +536,11 @@ nft_pipapo_lookup(const struct net *net, const struct nft_set *set, const u32 *key) {struct nft_pipapo *priv =nft_set_priv (set); -u8 genmask =nft_genmask_cur (net);const struct nft_pipapo_match *m;const struct nft_pipapo_elem *e; m =rcu_dereference (priv->match); - e =pipapo_get (m, (const u8 *)key, genmask,get_jiffies_64 ()); + e =pipapo_get (m, (const u8 *)key,NFT_GENMASK_ANY ,get_jiffies_64 ());return e ? &e->ext :NULL ; }
net/netfilter/nft_set_pipapo_avx2.c +1 -3
@@ -1153,7 +1153,6 @@ nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,struct nft_pipapo *priv =nft_set_priv (set);const struct nft_set_ext *ext =NULL ;struct nft_pipapo_scratch *scratch; -u8 genmask =nft_genmask_cur (net);const struct nft_pipapo_match *m;const struct nft_pipapo_field *f;const u8 *rp = (const u8 *)key;
@@ -1249,8 +1248,7 @@ nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,if (last) {const struct nft_set_ext *e = &f->mt[ret].e->ext; -if (unlikely (nft_set_elem_expired (e) || - !nft_set_elem_active (e, genmask))) +if (unlikely (nft_set_elem_expired (e))) goto next_match; ext = e;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 158/189 netfilter: nft_set_rbtree: continue traversal if element is inactive
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit a60f7bf4a1524d8896b76ba89623080aebf44272 ]
When the rbtree lookup function finds a match in the rbtree, it sets the range start interval to a potentially inactive element.
Then, after tree lookup, if the matching element is inactive, it returns NULL and suppresses a matching result.
This is wrong and leads to false negative matches when a transaction has already entered the commit phase.
cpu0 cpu1
has added new elements to clone
has marked elements as being
inactive in new generation
perform lookup in the set
enters commit phase:
I) increments the genbit
A) observes new genbit
B) finds matching range
C) returns no match: found range invalid in new generation
II) removes old elements from the tree
C New nft_lookup happening now
will find matching element, because it is no longer obscured by old, inactive one.
Consider a packet matching range r1-r2:
cpu0 processes following transaction:
1. remove r1-r2
2. add r1-r3
P is contained in both ranges. Therefore, cpu1 should always find a match for P. Due to above race, this is not the case:
cpu1 does find r1-r2, but then ignores it due to the genbit indicating the range has been removed. It does NOT test for further matches.
The situation persists for all lookups until after cpu0 hits II) after which r1-r3 range start node is tested for the first time.
Move the "interval start is valid" check ahead so that tree traversal continues if the starting interval is not valid in this generation.
Thanks to Stefan Hanreich for providing an initial reproducer for this bug.
--- net/netfilter/nft_set_rbtree.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/netfilter/nft_set_rbtree.c +3 -3
@@ -77,7 +77,9 @@ __nft_rbtree_lookup(const struct net *net, const struct nft_set *set,nft_rbtree_interval_end (rbe) && nft_rbtree_interval_start(interval)) continue; - interval = rbe; +if (nft_set_elem_active (&rbe->ext, genmask) && + !nft_rbtree_elem_expired (rbe)) + interval = rbe; }else if (d >0 ) parent =rcu_dereference_raw (parent->rb_right);else {
@@ -102,8 +104,6 @@ __nft_rbtree_lookup(const struct net *net, const struct nft_set *set, }if (set->flags &NFT_SET_INTERVAL && interval !=NULL && -nft_set_elem_active (&interval->ext, genmask) && - !nft_rbtree_elem_expired (interval) &&nft_rbtree_interval_start (interval))return &interval->ext;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 159/189 netfilter: nf_tables: Reintroduce shortened deletion notifications
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phil Sutter <[email protected]>
[ Upstream commit a1050dd071682d2c9d8d6d5c96119f8f401b62f0 ]
Restore commit 28339b21a365 ("netfilter: nf_tables: do not send complete notification of deletions") and fix it:
- Avoid upfront modification of 'event' variable so the conditionals become effective.
- Always include NFTA_OBJ_TYPE attribute in object notifications, user space requires it for proper deserialisation.
- Catch DESTROY events, too.
Stable-dep-of: b2f742c846ca ("netfilter: nf_tables: restart set lookup on base_seq change")
--- net/netfilter/nf_tables_api.c | 67 ++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 17 deletions(-)
net/netfilter/nf_tables_api.c +50 -17
@@ -1153,9 +1153,9 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, {struct nlmsghdr *nlh; - event =nfnl_msg_type (NFNL_SUBSYS_NFTABLES , event); - nlh =nfnl_msg_put (skb, portid, seq, event, flags, family, -NFNETLINK_V0 ,nft_base_seq (net)); + nlh =nfnl_msg_put (skb, portid, seq, +nfnl_msg_type (NFNL_SUBSYS_NFTABLES , event), + flags, family,NFNETLINK_V0 ,nft_base_seq (net));if (!nlh) goto nla_put_failure;
@@ -1165,6 +1165,12 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, NFTA_TABLE_PAD)) goto nla_put_failure; +if (event ==NFT_MSG_DELTABLE || + event ==NFT_MSG_DESTROYTABLE ) { +nlmsg_end (skb, nlh); +return 0 ; + } +if (nla_put_be32 (skb,NFTA_TABLE_FLAGS ,htonl (table->flags &NFT_TABLE_F_MASK ))) goto nla_put_failure;
@@ -2022,9 +2028,9 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net, {struct nlmsghdr *nlh; - event =nfnl_msg_type (NFNL_SUBSYS_NFTABLES , event); - nlh =nfnl_msg_put (skb, portid, seq, event, flags, family, -NFNETLINK_V0 ,nft_base_seq (net)); + nlh =nfnl_msg_put (skb, portid, seq, +nfnl_msg_type (NFNL_SUBSYS_NFTABLES , event), + flags, family,NFNETLINK_V0 ,nft_base_seq (net));if (!nlh) goto nla_put_failure;
@@ -2034,6 +2040,13 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net, NFTA_CHAIN_PAD)) goto nla_put_failure; +if (!hook_list && + (event ==NFT_MSG_DELCHAIN || + event ==NFT_MSG_DESTROYCHAIN )) { +nlmsg_end (skb, nlh); +return 0 ; + } +if (nft_is_base_chain (chain)) {const struct nft_base_chain *basechain =nft_base_chain (chain);struct nft_stats __percpu *stats;
@@ -4871,9 +4884,10 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,u32 seq = ctx->seq;int i; - event =nfnl_msg_type (NFNL_SUBSYS_NFTABLES , event); - nlh =nfnl_msg_put (skb, portid, seq, event, flags, ctx->family, -NFNETLINK_V0 ,nft_base_seq (ctx->net)); + nlh =nfnl_msg_put (skb, portid, seq, +nfnl_msg_type (NFNL_SUBSYS_NFTABLES , event), + flags, ctx->family,NFNETLINK_V0 , +nft_base_seq (ctx->net));if (!nlh) goto nla_put_failure;
@@ -4885,6 +4899,12 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx, NFTA_SET_PAD)) goto nla_put_failure; +if (event ==NFT_MSG_DELSET || + event ==NFT_MSG_DESTROYSET ) { +nlmsg_end (skb, nlh); +return 0 ; + } +if (set->flags !=0 )if (nla_put_be32 (skb,NFTA_SET_FLAGS ,htonl (set->flags))) goto nla_put_failure;
@@ -8359,20 +8379,26 @@ static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net, {struct nlmsghdr *nlh; - event =nfnl_msg_type (NFNL_SUBSYS_NFTABLES , event); - nlh =nfnl_msg_put (skb, portid, seq, event, flags, family, -NFNETLINK_V0 ,nft_base_seq (net)); + nlh =nfnl_msg_put (skb, portid, seq, +nfnl_msg_type (NFNL_SUBSYS_NFTABLES , event), + flags, family,NFNETLINK_V0 ,nft_base_seq (net));if (!nlh) goto nla_put_failure;if (nla_put_string (skb,NFTA_OBJ_TABLE , table->name) ||nla_put_string (skb,NFTA_OBJ_NAME , obj->key.name) || +nla_put_be32 (skb,NFTA_OBJ_TYPE ,htonl (obj->ops->type->type)) ||nla_put_be64 (skb,NFTA_OBJ_HANDLE ,cpu_to_be64 (obj->handle),NFTA_OBJ_PAD )) goto nla_put_failure; -if (nla_put_be32 (skb,NFTA_OBJ_TYPE ,htonl (obj->ops->type->type)) || -nla_put_be32 (skb,NFTA_OBJ_USE ,htonl (obj->use)) || +if (event ==NFT_MSG_DELOBJ || + event ==NFT_MSG_DESTROYOBJ ) { +nlmsg_end (skb, nlh); +return 0 ; + } + +if (nla_put_be32 (skb,NFTA_OBJ_USE ,htonl (obj->use)) ||nft_object_dump (skb,NFTA_OBJ_DATA , obj, reset)) goto nla_put_failure;
@@ -9413,9 +9439,9 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net,struct nft_hook *hook;struct nlmsghdr *nlh; - event =nfnl_msg_type (NFNL_SUBSYS_NFTABLES , event); - nlh =nfnl_msg_put (skb, portid, seq, event, flags, family, -NFNETLINK_V0 ,nft_base_seq (net)); + nlh =nfnl_msg_put (skb, portid, seq, +nfnl_msg_type (NFNL_SUBSYS_NFTABLES , event), + flags, family,NFNETLINK_V0 ,nft_base_seq (net));if (!nlh) goto nla_put_failure;
@@ -9425,6 +9451,13 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net, NFTA_FLOWTABLE_PAD)) goto nla_put_failure; +if (!hook_list && + (event ==NFT_MSG_DELFLOWTABLE || + event ==NFT_MSG_DESTROYFLOWTABLE )) { +nlmsg_end (skb, nlh); +return 0 ; + } +if (nla_put_be32 (skb,NFTA_FLOWTABLE_USE ,htonl (flowtable->use)) ||nla_put_be32 (skb,NFTA_FLOWTABLE_FLAGS ,htonl (flowtable->data.flags))) goto nla_put_failure;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 160/189 netfilter: nf_tables: place base_seq in struct net
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 64102d9bbc3d41dac5188b8fba75b1344c438970 ]
This will soon be read from packet path around same time as the gencursor.
Both gencursor and base_seq get incremented almost at the same time, so it makes sense to place them in the same structure.
This doesn't increase struct net size on 64bit due to padding.
Stable-dep-of: b2f742c846ca ("netfilter: nf_tables: restart set lookup on base_seq change")
--- include/net/netfilter/nf_tables.h | 1 - include/net/netns/nftables.h | 1 + net/netfilter/nf_tables_api.c | 65 ++++++++++++++++--------------- 3 files changed, 34 insertions(+), 33 deletions(-)
include/net/netfilter/nf_tables.h +0 -1
@@ -1916,7 +1916,6 @@ struct nftables_pernet {struct mutex commit_mutex;u64 table_handle;u64 tstamp; -unsigned int base_seq;unsigned int gc_seq;u8 validate_state;struct work_struct destroy_work;
include/net/netns/nftables.h +1 -0
@@ -3,6 +3,7 @@#define _NETNS_NFTABLES_H_struct netns_nftables { +unsigned int base_seq;u8 gencursor; };
net/netfilter/nf_tables_api.c +33 -32
235 lines not on this page · raw message
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 161/189 netfilter: nf_tables: make nft_set_do_lookup available unconditionally
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 11fe5a82e53ac3581a80c88e0e35fb8a80e15f48 ]
This function was added for retpoline mitigation and is replaced by a static inline helper if mitigations are not enabled.
Enable this helper function unconditionally so next patch can add a lookup restart mechanism to fix possible false negatives while transactions are in progress.
Adding lookup restarts in nft_lookup_eval doesn't work as nft_objref would then need the same copypaste loop.
This patch is separate to ease review of the actual bug fix.
Stable-dep-of: b2f742c846ca ("netfilter: nf_tables: restart set lookup on base_seq change")
--- include/net/netfilter/nf_tables_core.h | 10 ++-------- net/netfilter/nft_lookup.c | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 13 deletions(-)
include/net/netfilter/nf_tables_core.h +2 -8
@@ -109,17 +109,11 @@ nft_hash_lookup_fast(const struct net *net, const struct nft_set *set,const struct nft_set_ext *nft_hash_lookup (const struct net *net,const struct nft_set *set,const u32 *key); +#endif +const struct nft_set_ext *nft_set_do_lookup (const struct net *net,const struct nft_set *set,const u32 *key); -#else -static inline const struct nft_set_ext * -nft_set_do_lookup (const struct net *net,const struct nft_set *set, -const u32 *key) -{ -return set->ops->lookup (net, set, key); -} -#endif /* called from nft_pipapo_avx2.c */ const struct nft_set_ext *
net/netfilter/nft_lookup.c +12 -5
@@ -24,11 +24,11 @@ struct nft_lookup {struct nft_set_binding binding; }; -#ifdef CONFIG_MITIGATION_RETPOLINE -const struct nft_set_ext * -nft_set_do_lookup (const struct net *net,const struct nft_set *set, -const u32 *key) +static const struct nft_set_ext * +__nft_set_do_lookup (const struct net *net,const struct nft_set *set, +const u32 *key) { +#ifdef CONFIG_MITIGATION_RETPOLINE if (set->ops == &nft_set_hash_fast_type.ops)return nft_hash_lookup_fast (net, set, key);if (set->ops == &nft_set_hash_type.ops)
@@ -51,10 +51,17 @@ nft_set_do_lookup(const struct net *net, const struct nft_set *set,return nft_rbtree_lookup (net, set, key);WARN_ON_ONCE (1 ); +#endif return set->ops->lookup (net, set, key); } + +const struct nft_set_ext * +nft_set_do_lookup (const struct net *net,const struct nft_set *set, +const u32 *key) +{ +return __nft_set_do_lookup (net, set, key); +}EXPORT_SYMBOL_GPL (nft_set_do_lookup); -#endif void nft_lookup_eval(const struct nft_expr *expr, struct nft_regs *regs,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 162/189 netfilter: nf_tables: restart set lookup on base_seq change
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit b2f742c846cab9afc5953a5d8f17b54922dcc723 ]
The hash, hash_fast, rhash and bitwise sets may indicate no result even though a matching element exists during a short time window while other cpu is finalizing the transaction.
This happens when the hash lookup/bitwise lookup function has picked up the old genbit, right before it was toggled by nf_tables_commit(), but then the same cpu managed to unlink the matching old element from the hash table:
cpu0 cpu1
has added new elements to clone
has marked elements as being
inactive in new generation
perform lookup in the set
enters commit phase:
A) observes old genbit
increments base_seq
I) increments the genbit
II) removes old element from the set
B) finds matching element
C) returns no match: found element is not valid in old generation
Next lookup observes new genbit and finds matching e2.
Consider a packet matching element e1, e2.
cpu0 processes following transaction:
1. remove e1
2. adds e2, which has same key as e1.
P matches both e1 and e2. Therefore, cpu1 should always find a match for P. Due to above race, this is not the case:
cpu1 observed the old genbit. e2 will not be considered once it is found. The element e1 is not found anymore if cpu0 managed to unlink it from the hlist before cpu1 found it during list traversal.
The situation only occurs for a brief time period, lookups happening after I) observe new genbit and return e2.
This problem exists in all set types except nft_set_pipapo, so fix it once in nft_lookup rather than each set ops individually.
Sample the base sequence counter, which gets incremented right before the genbit is changed.
Then, if no match is found, retry the lookup if the base sequence was altered in between.
If the base sequence hasn't changed:
- No update took place: no-match result is expected.
This is the common case. or:
- nf_tables_commit() hasn't progressed to genbit update yet. Old elements were still visible and nomatch result is expected, or:
- nf_tables_commit updated the genbit:
We picked up the new base_seq, so the lookup function also picked up the new genbit, no-match result is expected.
If the old genbit was observed, then nft_lookup also picked up the oldbase_seq: nft_lookup_should_retry() returns true and relookup is performed in the new generation.
This problem was added when the unconditional synchronize_rcu() call that followed the current/next generation bit toggle was removed.
Thanks to Pablo Neira Ayuso for reviewing an earlier version of this patchset, for suggesting re-use of existing base_seq and placement of the restart loop in nft_set_do_lookup().
--- net/netfilter/nf_tables_api.c | 3 ++- net/netfilter/nft_lookup.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-)
net/netfilter/nf_tables_api.c +2 -1
@@ -10971,7 +10971,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)while (++base_seq ==0 ) ; -WRITE_ONCE (net->nft.base_seq, base_seq); +/* pairs with smp_load_acquire in nft_lookup_eval */ +smp_store_release (&net->nft.base_seq, base_seq); gc_seq =nft_gc_seq_begin (nft_net);
net/netfilter/nft_lookup.c +30 -1
@@ -55,11 +55,40 @@ __nft_set_do_lookup(const struct net *net, const struct nft_set *set,return set->ops->lookup (net, set, key); } +static unsigned int nft_base_seq (const struct net *net) +{ +/* pairs with smp_store_release() in nf_tables_commit() */ +return smp_load_acquire (&net->nft.base_seq); +} + +static bool nft_lookup_should_retry (const struct net *net,unsigned int seq) +{ +return unlikely (seq !=nft_base_seq (net)); +} +const struct nft_set_ext *nft_set_do_lookup (const struct net *net,const struct nft_set *set,const u32 *key) { -return __nft_set_do_lookup (net, set, key); +const struct nft_set_ext *ext; +unsigned int base_seq; + +do { + base_seq =nft_base_seq (net); + + ext =__nft_set_do_lookup (net, set, key); +if (ext) +break ; +/* No match? There is a small chance that lookup was +* performed in the old generation, but nf_tables_commit() +* already unlinked a (matching) element. +* +* We need to repeat the lookup to make sure that we didn't +* miss a matching element in the new generation. +*/ + }while (nft_lookup_should_retry (net, base_seq)); + +return ext; }EXPORT_SYMBOL_GPL (nft_set_do_lookup);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 163/189 hsr: use rtnl lock when iterating over ports
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
[ Upstream commit 8884c693991333ae065830554b9b0c96590b1bb2 ]
hsr_for_each_port is called in many places without holding the RCU read lock, this may trigger warnings on debug kernels. Most of the callers are actually hold rtnl lock. So add a new helper hsr_for_each_port_rtnl to allow callers in suitable contexts to iterate ports safely without explicit RCU locking.
This patch only fixed the callers that is hold rtnl lock. Other caller issues will be fixed in later patches.
--- net/hsr/hsr_device.c | 18 +++++++++--------- net/hsr/hsr_main.c | 2 +- net/hsr/hsr_main.h | 3 +++ 3 files changed, 13 insertions(+), 10 deletions(-)
net/hsr/hsr_device.c +9 -9
@@ -49,7 +49,7 @@ static bool hsr_check_carrier(struct hsr_port *master)ASSERT_RTNL (); -hsr_for_each_port (master->hsr, port) { +hsr_for_each_port_rtnl (master->hsr, port) {if (port->type !=HSR_PT_MASTER &&is_slave_up (port->dev)) {netif_carrier_on (master->dev);return true;
@@ -105,7 +105,7 @@ int hsr_get_max_mtu(struct hsr_priv *hsr)struct hsr_port *port; mtu_max =ETH_DATA_LEN ; -hsr_for_each_port (hsr, port) +hsr_for_each_port_rtnl (hsr, port)if (port->type !=HSR_PT_MASTER ) mtu_max =min (port->dev->mtu, mtu_max);
@@ -139,7 +139,7 @@ static int hsr_dev_open(struct net_device *dev) hsr =netdev_priv (dev); -hsr_for_each_port (hsr, port) { +hsr_for_each_port_rtnl (hsr, port) {if (port->type ==HSR_PT_MASTER )continue ;switch (port->type) {
@@ -172,7 +172,7 @@ static int hsr_dev_close(struct net_device *dev)struct hsr_priv *hsr; hsr =netdev_priv (dev); -hsr_for_each_port (hsr, port) { +hsr_for_each_port_rtnl (hsr, port) {if (port->type ==HSR_PT_MASTER )continue ;switch (port->type) {
@@ -205,7 +205,7 @@ static netdev_features_t hsr_features_recompute(struct hsr_priv *hsr,* may become enabled. */ features &= ~NETIF_F_ONE_FOR_ALL ; -hsr_for_each_port (hsr, port) +hsr_for_each_port_rtnl (hsr, port) features =netdev_increment_features (features, port->dev->features, mask);
@@ -484,7 +484,7 @@ static void hsr_set_rx_mode(struct net_device *dev) hsr =netdev_priv (dev); -hsr_for_each_port (hsr, port) { +hsr_for_each_port_rtnl (hsr, port) {if (port->type ==HSR_PT_MASTER )continue ;switch (port->type) {
@@ -506,7 +506,7 @@ static void hsr_change_rx_flags(struct net_device *dev, int change) hsr =netdev_priv (dev); -hsr_for_each_port (hsr, port) { +hsr_for_each_port_rtnl (hsr, port) {if (port->type ==HSR_PT_MASTER )continue ;switch (port->type) {
@@ -534,7 +534,7 @@ static int hsr_ndo_vlan_rx_add_vid(struct net_device *dev, hsr =netdev_priv (dev); -hsr_for_each_port (hsr, port) { +hsr_for_each_port_rtnl (hsr, port) {if (port->type ==HSR_PT_MASTER || port->type ==HSR_PT_INTERLINK )continue ;
@@ -580,7 +580,7 @@ static int hsr_ndo_vlan_rx_kill_vid(struct net_device *dev, hsr =netdev_priv (dev); -hsr_for_each_port (hsr, port) { +hsr_for_each_port_rtnl (hsr, port) {switch (port->type) {case HSR_PT_SLAVE_A :case HSR_PT_SLAVE_B :
net/hsr/hsr_main.c +1 -1
@@ -22,7 +22,7 @@ static bool hsr_slave_empty(struct hsr_priv *hsr) {struct hsr_port *port; -hsr_for_each_port (hsr, port) +hsr_for_each_port_rtnl (hsr, port)if (port->type !=HSR_PT_MASTER )return false;return true;
net/hsr/hsr_main.h +3 -0
@@ -224,6 +224,9 @@ struct hsr_priv {#define hsr_for_each_port (hsr, port) \ list_for_each_entry_rcu((port), &(hsr)->ports, port_list) +#define hsr_for_each_port_rtnl (hsr, port) \ + list_for_each_entry_rcu((port), &(hsr)->ports, port_list, lockdep_rtnl_is_held()) +struct hsr_port *hsr_port_get_hsr (struct hsr_priv *hsr,enum hsr_port_type pt);/* Caller must ensure skb is a valid HSR frame */
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 164/189 hsr: use hsr_for_each_port_rtnl in hsr_port_get_hsr
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
[ Upstream commit 393c841fe4333cdd856d0ca37b066d72746cfaa6 ]
hsr_port_get_hsr() iterates over ports using hsr_for_each_port(), but many of its callers do not hold the required RCU lock.
Switch to hsr_for_each_port_rtnl(), since most callers already hold the rtnl lock. After review, all callers are covered by either the rtnl lock or the RCU lock, except hsr_dev_xmit(). Fix this by adding an RCU read lock there.
--- net/hsr/hsr_device.c | 3 +++ net/hsr/hsr_main.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-)
net/hsr/hsr_device.c +3 -0
@@ -226,6 +226,7 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)struct hsr_priv *hsr =netdev_priv (dev);struct hsr_port *master; +rcu_read_lock (); master =hsr_port_get_hsr (hsr,HSR_PT_MASTER );if (master) { skb->dev = master->dev;
@@ -238,6 +239,8 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)dev_core_stats_tx_dropped_inc (dev);dev_kfree_skb_any (skb); } +rcu_read_unlock (); +return NETDEV_TX_OK ; }
net/hsr/hsr_main.c +1 -1
@@ -134,7 +134,7 @@ struct hsr_port *hsr_port_get_hsr(struct hsr_priv *hsr, enum hsr_port_type pt) {struct hsr_port *port; -hsr_for_each_port (hsr, port) +hsr_for_each_port_rtnl (hsr, port)if (port->type == pt)return port;return NULL ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 165/189 hsr: hold rcu and dev lock for hsr_get_port_ndev
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
[ Upstream commit 847748fc66d08a89135a74e29362a66ba4e3ab15 ]
hsr_get_port_ndev calls hsr_for_each_port, which need to hold rcu lock. On the other hand, before return the port device, we need to hold the device reference to avoid UaF in the caller function.
--- drivers/net/ethernet/ti/icssg/icssg_prueth.c | 20 ++++++++++++++------ net/hsr/hsr_device.c | 7 ++++++- 2 files changed, 20 insertions(+), 7 deletions(-)
drivers/net/ethernet/ti/icssg/icssg_prueth.c +14 -6
@@ -691,7 +691,7 @@ static void icssg_prueth_hsr_fdb_add_del(struct prueth_emac *emac,static int icssg_prueth_hsr_add_mcast (struct net_device *ndev,const u8 *addr) { -struct net_device *real_dev; +struct net_device *real_dev, *port_dev;struct prueth_emac *emac;u8 vlan_id, i;
@@ -700,11 +700,15 @@ static int icssg_prueth_hsr_add_mcast(struct net_device *ndev, const u8 *addr)if (is_hsr_master (real_dev)) {for (i =HSR_PT_SLAVE_A ; i <HSR_PT_INTERLINK ; i++) { - emac =netdev_priv (hsr_get_port_ndev (real_dev, i)); -if (!emac) + port_dev =hsr_get_port_ndev (real_dev, i); + emac =netdev_priv (port_dev); +if (!emac) { +dev_put (port_dev);return -EINVAL ; + }icssg_prueth_hsr_fdb_add_del (emac, addr, vlan_id, true); +dev_put (port_dev); } }else { emac =netdev_priv (real_dev);
@@ -716,7 +720,7 @@ static int icssg_prueth_hsr_add_mcast(struct net_device *ndev, const u8 *addr)static int icssg_prueth_hsr_del_mcast (struct net_device *ndev,const u8 *addr) { -struct net_device *real_dev; +struct net_device *real_dev, *port_dev;struct prueth_emac *emac;u8 vlan_id, i;
@@ -725,11 +729,15 @@ static int icssg_prueth_hsr_del_mcast(struct net_device *ndev, const u8 *addr)if (is_hsr_master (real_dev)) {for (i =HSR_PT_SLAVE_A ; i <HSR_PT_INTERLINK ; i++) { - emac =netdev_priv (hsr_get_port_ndev (real_dev, i)); -if (!emac) + port_dev =hsr_get_port_ndev (real_dev, i); + emac =netdev_priv (port_dev); +if (!emac) { +dev_put (port_dev);return -EINVAL ; + }icssg_prueth_hsr_fdb_add_del (emac, addr, vlan_id, false); +dev_put (port_dev); } }else { emac =netdev_priv (real_dev);
net/hsr/hsr_device.c +6 -1
@@ -675,9 +675,14 @@ struct net_device *hsr_get_port_ndev(struct net_device *ndev,struct hsr_priv *hsr =netdev_priv (ndev);struct hsr_port *port; +rcu_read_lock ();hsr_for_each_port (hsr, port) -if (port->type == pt) +if (port->type == pt) { +dev_hold (port->dev); +rcu_read_unlock ();return port->dev; + } +rcu_read_unlock ();return NULL ; }EXPORT_SYMBOL (hsr_get_port_ndev);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 166/189 phy: qualcomm: phy-qcom-eusb2-repeater: fix override properties
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengyu Luo <[email protected]>
[ Upstream commit 942e47ab228c7dd27c2ae043c17e7aab2028082c ]
property "qcom,tune-usb2-preem" is for EUSB2_TUNE_USB2_PREEM property "qcom,tune-usb2-amplitude" is for EUSB2_TUNE_IUSB2
The downstream correspondence is as follows:EUSB2_TUNE_USB2_PREEM: Tx pre-emphasis tuningEUSB2_TUNE_IUSB2: HS trasmit amplitudeEUSB2_TUNE_SQUELCH_U: Squelch detection thresholdEUSB2_TUNE_HSDISC: HS disconnect thresholdEUSB2_TUNE_EUSB_SLEW: slew rate
--- drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c +2 -2
@@ -127,13 +127,13 @@ static int eusb2_repeater_init(struct phy *phy) rptr->cfg->init_tbl[i].value);/* Override registers from devicetree values */ -if (!of_property_read_u8 (np,"qcom,tune-usb2-amplitude" , &val)) +if (!of_property_read_u8 (np,"qcom,tune-usb2-preem" , &val))regmap_write (regmap, base +EUSB2_TUNE_USB2_PREEM , val);if (!of_property_read_u8 (np,"qcom,tune-usb2-disc-thres" , &val))regmap_write (regmap, base +EUSB2_TUNE_HSDISC , val); -if (!of_property_read_u8 (np,"qcom,tune-usb2-preem" , &val)) +if (!of_property_read_u8 (np,"qcom,tune-usb2-amplitude" , &val))regmap_write (regmap, base +EUSB2_TUNE_IUSB2 , val);/* Wait for status OK */
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 167/189 dmaengine: idxd: Remove improper idxd_free
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yi Sun <[email protected]>
[ Upstream commit f41c538881eec4dcf5961a242097d447f848cda6 ]
The call to idxd_free() introduces a duplicate put_device() leading to a reference count underflow:refcount_t: underflow; use-after-free.
WARNING: CPU: 15 PID: 4428 at lib/refcount.c:28 refcount_warn_saturate+0xbe/0x110 ... Call Trace: <TASK> idxd_remove+0xe4/0x120 [idxd] pci_device_remove+0x3f/0xb0 device_release_driver_internal+0x197/0x200 driver_detach+0x48/0x90 bus_remove_driver+0x74/0xf0 pci_unregister_driver+0x2e/0xb0 idxd_exit_module+0x34/0x7a0 [idxd] __do_sys_delete_module.constprop.0+0x183/0x280 do_syscall_64+0x54/0xd70 entry_SYSCALL_64_after_hwframe+0x76/0x7e
The idxd_unregister_devices() which is invoked at the very beginning of idxd_remove(), already takes care of the necessary put_device() through the following call path:idxd_unregister_devices() -> device_unregister() -> put_device()
In addition, when CONFIG_DEBUG_KOBJECT_RELEASE is enabled, put_device() may trigger asynchronous cleanup via schedule_delayed_work(). If idxd_free() is called immediately after, it can result in a use-after-free.
Remove the improper idxd_free() to avoid both the refcount underflow and potential memory corruption during module unload.
--- drivers/dma/idxd/init.c | 1 - 1 file changed, 1 deletion(-)
drivers/dma/idxd/init.c +0 -1
@@ -1295,7 +1295,6 @@ static void idxd_remove(struct pci_dev *pdev)idxd_cleanup (idxd);pci_iounmap (pdev, idxd->reg_base);put_device (idxd_confdev (idxd)); -idxd_free (idxd);pci_disable_device (pdev); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 168/189 dmaengine: idxd: Fix refcount underflow on module unload
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yi Sun <[email protected]>
[ Upstream commit b7cb9a034305d52222433fad10c3de10204f29e7 ]
A recent refactor introduced a misplaced put_device() call, resulting in a reference count underflow during module unload.
There is no need to add additional put_device() calls for idxd groups, engines, or workqueues. Although the commit claims: "Note, this also fixes the missing put_device() for idxd groups, engines, and wqs."
It appears no such omission actually existed. The required cleanup is already handled by the call chain:idxd_unregister_devices() -> device_unregister() -> put_device()
Extend idxd_cleanup() to handle the remaining necessary cleanup and remove idxd_cleanup_internals(), which duplicates deallocation logic for idxd, engines, groups, and workqueues. Memory management is also properly handled through the Linux device model.
--- drivers/dma/idxd/init.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/dma/idxd/init.c +4 -1
@@ -1292,7 +1292,10 @@ static void idxd_remove(struct pci_dev *pdev)device_unregister (idxd_confdev (idxd));idxd_shutdown (pdev);idxd_device_remove_debugfs (idxd); -idxd_cleanup (idxd); +perfmon_pmu_remove (idxd); +idxd_cleanup_interrupts (idxd); +if (device_pasid_enabled (idxd)) +idxd_disable_system_pasid (idxd);pci_iounmap (pdev, idxd->reg_base);put_device (idxd_confdev (idxd));pci_disable_device (pdev);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 169/189 dmaengine: idxd: Fix double free in idxd_setup_wqs()
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 39aaa337449e71a41d4813be0226a722827ba606 ]
The clean up in idxd_setup_wqs() has had a couple bugs because the error handling is a bit subtle. It's simpler to just re-write it in a cleaner way. The issues here are:
1) If "idxd->max_wqs" is <= 0 then we call put_device(conf_dev) when "conf_dev" hasn't been initialized.
2) If kzalloc_node() fails then again "conf_dev" is invalid. It's either uninitialized or it points to the "conf_dev" from the previous iteration so it leads to a double free.
It's better to free partial loop iterations within the loop and then the unwinding at the end can handle whole loop iterations. I also renamed the labels to describe what the goto does and not where the goto was located.
--- drivers/dma/idxd/init.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-)
drivers/dma/idxd/init.c +17 -16
@@ -189,27 +189,30 @@ static int idxd_setup_wqs(struct idxd_device *idxd) idxd->wq_enable_map =bitmap_zalloc_node (idxd->max_wqs,GFP_KERNEL ,dev_to_node (dev));if (!idxd->wq_enable_map) { rc = -ENOMEM ; - goto err_bitmap; + goto err_free_wqs; }for (i =0 ; i < idxd->max_wqs; i++) { wq =kzalloc_node (sizeof (*wq),GFP_KERNEL ,dev_to_node (dev));if (!wq) { rc = -ENOMEM ; - goto err; + goto err_unwind; }idxd_dev_set_type (&wq->idxd_dev,IDXD_DEV_WQ ); conf_dev =wq_confdev (wq); wq->id = i; wq->idxd = idxd; -device_initialize (wq_confdev (wq)); +device_initialize (conf_dev); conf_dev->parent =idxd_confdev (idxd); conf_dev->bus = &dsa_bus_type; conf_dev->type = &idxd_wq_device_type; rc =dev_set_name (conf_dev,"wq%d.%d" , idxd->id, wq->id); -if (rc <0 ) - goto err; +if (rc <0 ) { +put_device (conf_dev); +kfree (wq); + goto err_unwind; + }mutex_init (&wq->wq_lock);init_waitqueue_head (&wq->err_queue);
@@ -220,15 +223,20 @@ static int idxd_setup_wqs(struct idxd_device *idxd) wq->enqcmds_retries =IDXD_ENQCMDS_RETRIES ; wq->wqcfg =kzalloc_node (idxd->wqcfg_size,GFP_KERNEL ,dev_to_node (dev));if (!wq->wqcfg) { +put_device (conf_dev); +kfree (wq); rc = -ENOMEM ; - goto err; + goto err_unwind; }if (idxd->hw.wq_cap.op_config) { wq->opcap_bmap =bitmap_zalloc (IDXD_MAX_OPCAP_BITS ,GFP_KERNEL );if (!wq->opcap_bmap) { +kfree (wq->wqcfg); +put_device (conf_dev); +kfree (wq); rc = -ENOMEM ; - goto err_opcap_bmap; + goto err_unwind; }bitmap_copy (wq->opcap_bmap, idxd->opcap_bmap,IDXD_MAX_OPCAP_BITS ); }
@@ -239,13 +247,7 @@ static int idxd_setup_wqs(struct idxd_device *idxd)return 0 ; -err_opcap_bmap: -kfree (wq->wqcfg); - -err: -put_device (conf_dev); -kfree (wq); - +err_unwind:while (--i >=0 ) { wq = idxd->wqs[i];if (idxd->hw.wq_cap.op_config)
@@ -254,11 +256,10 @@ static int idxd_setup_wqs(struct idxd_device *idxd) conf_dev =wq_confdev (wq);put_device (conf_dev);kfree (wq); - }bitmap_free (idxd->wq_enable_map); -err_bitmap: +err_free_wqs:kfree (idxd->wqs);return rc;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 170/189 erofs: get rid of {get,put}_page() for ztailpacking data
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gao Xiang <[email protected]>
[ Upstream commit 96debe8c27ee2494bbd78abf3744745a84a745f1 ]
The compressed data for the ztailpacking feature is fetched from the metadata inode (e.g., bd_inode), which is folio-based.
Therefore, the folio interface should be used instead.
Stable-dep-of: 131897c65e2b ("erofs: fix invalid algorithm for encoded extents")
--- fs/erofs/zdata.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
fs/erofs/zdata.c +6 -8
@@ -805,6 +805,7 @@ static int z_erofs_pcluster_begin(struct z_erofs_frontend *fe)struct erofs_map_blocks *map = &fe->map;struct super_block *sb = fe->inode->i_sb;struct z_erofs_pcluster *pcl =NULL ; +void *ptr;int ret;DBG_BUGON (fe->pcl);
@@ -854,15 +855,13 @@ static int z_erofs_pcluster_begin(struct z_erofs_frontend *fe)/* bind cache first when cached decompression is preferred */ z_erofs_bind_cache (fe); }else { -void *mptr; - - mptr =erofs_read_metabuf (&map->buf, sb, map->m_pa, false); -if (IS_ERR (mptr)) { - ret =PTR_ERR (mptr); + ptr =erofs_read_metabuf (&map->buf, sb, map->m_pa, false); +if (IS_ERR (ptr)) { + ret =PTR_ERR (ptr);erofs_err (sb,"failed to get inline data %d" , ret);return ret; } -get_page (map->buf.page); +folio_get (page_folio (map->buf.page));WRITE_ONCE (fe->pcl->compressed_bvecs[0 ].page, map->buf.page); fe->pcl->pageofs_in = map->m_pa & ~PAGE_MASK ; fe->mode =Z_EROFS_PCLUSTER_FOLLOWED_NOINPLACE ;
@@ -1325,9 +1324,8 @@ static int z_erofs_decompress_pcluster(struct z_erofs_backend *be, int err)/* must handle all compressed pages before actual file pages */ if (pcl->from_meta) { - page = pcl->compressed_bvecs[0 ].page; +folio_put (page_folio (pcl->compressed_bvecs[0 ].page));WRITE_ONCE (pcl->compressed_bvecs[0 ].page,NULL ); -put_page (page); }else {/* managed folios are still left in compressed_bvecs[] */ for (i =0 ; i < pclusterpages; ++i) {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 171/189 erofs: remove need_kmap in erofs_read_metabuf()
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gao Xiang <[email protected]>
[ Upstream commit 5e744cb61536bb4e37caca9c5e84feef638782be ]
- need_kmap is always true except for a ztailpacking case; thus, just open-code that one;
- The upcoming metadata compression will add a new boolean, so simplify this first.
Stable-dep-of: 131897c65e2b ("erofs: fix invalid algorithm for encoded extents")
--- fs/erofs/data.c | 8 ++++---- fs/erofs/fileio.c | 2 +- fs/erofs/fscache.c | 2 +- fs/erofs/inode.c | 8 ++++---- fs/erofs/internal.h | 2 +- fs/erofs/super.c | 4 ++-- fs/erofs/zdata.c | 5 +++-- fs/erofs/zmap.c | 12 ++++++------ 8 files changed, 22 insertions(+), 21 deletions(-)
fs/erofs/data.c +4 -4
@@ -65,10 +65,10 @@ void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb) }void *erofs_read_metabuf (struct erofs_buf *buf,struct super_block *sb, -erofs_off_t offset,bool need_kmap) +erofs_off_t offset) {erofs_init_metabuf (buf, sb); -return erofs_bread (buf, offset, need_kmap); +return erofs_bread (buf, offset, true); }int erofs_map_blocks (struct inode *inode,struct erofs_map_blocks *map)
@@ -118,7 +118,7 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map) pos =ALIGN (erofs_iloc (inode) + vi->inode_isize + vi->xattr_isize, unit) + unit * chunknr; - idx =erofs_read_metabuf (&buf, sb, pos, true); + idx =erofs_read_metabuf (&buf, sb, pos);if (IS_ERR (idx)) { err =PTR_ERR (idx); goto out;
@@ -299,7 +299,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,struct erofs_buf buf = __EROFS_BUF_INITIALIZER; iomap->type =IOMAP_INLINE ; - ptr =erofs_read_metabuf (&buf, sb, mdev.m_pa, true); + ptr =erofs_read_metabuf (&buf, sb, mdev.m_pa);if (IS_ERR (ptr))return PTR_ERR (ptr); iomap->inline_data = ptr;
fs/erofs/fileio.c +1 -1
@@ -115,7 +115,7 @@ static int erofs_fileio_scan_folio(struct erofs_fileio *io, struct folio *folio)void *src; src =erofs_read_metabuf (&buf, inode->i_sb, - map->m_pa + ofs, true); + map->m_pa + ofs);if (IS_ERR (src)) { err =PTR_ERR (src);break ;
fs/erofs/fscache.c +1 -1
@@ -274,7 +274,7 @@ static int erofs_fscache_data_read_slice(struct erofs_fscache_rq *req)size_t size = map.m_llen;void *src; - src =erofs_read_metabuf (&buf, sb, map.m_pa, true); + src =erofs_read_metabuf (&buf, sb, map.m_pa);if (IS_ERR (src))return PTR_ERR (src);
fs/erofs/inode.c +4 -4
@@ -39,10 +39,10 @@ static int erofs_read_inode(struct inode *inode)void *ptr;int err =0 ; - ptr =erofs_read_metabuf (&buf, sb,erofs_pos (sb, blkaddr), true); + ptr =erofs_read_metabuf (&buf, sb,erofs_pos (sb, blkaddr));if (IS_ERR (ptr)) { err =PTR_ERR (ptr); -erofs_err (sb,"failed to get inode (nid: %llu) page, err %d" , +erofs_err (sb,"failed to read inode meta block (nid: %llu): %d" , vi->nid, err); goto err_out; }
@@ -78,10 +78,10 @@ static int erofs_read_inode(struct inode *inode)memcpy (&copied, dic, gotten); ptr =erofs_read_metabuf (&buf, sb, -erofs_pos (sb, blkaddr +1 ), true); +erofs_pos (sb, blkaddr +1 ));if (IS_ERR (ptr)) { err =PTR_ERR (ptr); -erofs_err (sb,"failed to get inode payload block (nid: %llu), err %d" , +erofs_err (sb,"failed to read inode payload block (nid: %llu): %d" , vi->nid, err); goto err_out; }
fs/erofs/internal.h +1 -1
@@ -385,7 +385,7 @@ void erofs_put_metabuf(struct erofs_buf *buf);void *erofs_bread (struct erofs_buf *buf,erofs_off_t offset,bool need_kmap);void erofs_init_metabuf (struct erofs_buf *buf,struct super_block *sb);void *erofs_read_metabuf (struct erofs_buf *buf,struct super_block *sb, -erofs_off_t offset,bool need_kmap); +erofs_off_t offset);int erofs_map_dev (struct super_block *sb,struct erofs_map_dev *dev);int erofs_fiemap (struct inode *inode,struct fiemap_extent_info *fieinfo,u64 start,u64 len);
fs/erofs/super.c +2 -2
@@ -141,7 +141,7 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb,struct erofs_deviceslot *dis;struct file *file; - dis =erofs_read_metabuf (buf, sb, *pos, true); + dis =erofs_read_metabuf (buf, sb, *pos);if (IS_ERR (dis))return PTR_ERR (dis);
@@ -268,7 +268,7 @@ static int erofs_read_superblock(struct super_block *sb)void *data;int ret; - data =erofs_read_metabuf (&buf, sb,0 , true); + data =erofs_read_metabuf (&buf, sb,0 );if (IS_ERR (data)) {erofs_err (sb,"cannot read erofs superblock" );return PTR_ERR (data);
fs/erofs/zdata.c +3 -2
@@ -855,10 +855,11 @@ static int z_erofs_pcluster_begin(struct z_erofs_frontend *fe)/* bind cache first when cached decompression is preferred */ z_erofs_bind_cache (fe); }else { - ptr =erofs_read_metabuf (&map->buf, sb, map->m_pa, false); +erofs_init_metabuf (&map->buf, sb); + ptr =erofs_bread (&map->buf, map->m_pa, false);if (IS_ERR (ptr)) { ret =PTR_ERR (ptr); -erofs_err (sb,"failed to get inline data %d" , ret); +erofs_err (sb,"failed to get inline folio %d" , ret);return ret; }folio_get (page_folio (map->buf.page));
fs/erofs/zmap.c +6 -6
@@ -31,7 +31,7 @@ static int z_erofs_load_full_lcluster(struct z_erofs_maprecorder *m,struct z_erofs_lcluster_index *di;unsigned int advise; - di =erofs_read_metabuf (&m->map->buf, inode->i_sb, pos, true); + di =erofs_read_metabuf (&m->map->buf, inode->i_sb, pos);if (IS_ERR (di))return PTR_ERR (di); m->lcn = lcn;
@@ -146,7 +146,7 @@ static int z_erofs_load_compact_lcluster(struct z_erofs_maprecorder *m,else return -EOPNOTSUPP ; - in =erofs_read_metabuf (&m->map->buf, m->inode->i_sb, pos, true); + in =erofs_read_metabuf (&m->map->buf, m->inode->i_sb, pos);if (IS_ERR (in))return PTR_ERR (in);
@@ -551,7 +551,7 @@ static int z_erofs_map_blocks_ext(struct inode *inode, map->m_flags =0 ;if (recsz <= offsetof(struct z_erofs_extent , pstart_hi)) {if (recsz <= offsetof(struct z_erofs_extent , pstart_lo)) { - ext =erofs_read_metabuf (&map->buf, sb, pos, true); + ext =erofs_read_metabuf (&map->buf, sb, pos);if (IS_ERR (ext))return PTR_ERR (ext); pa =le64_to_cpu (*(__le64 *)ext);
@@ -564,7 +564,7 @@ static int z_erofs_map_blocks_ext(struct inode *inode, }for (; lstart <= map->m_la; lstart +=1 << vi->z_lclusterbits) { - ext =erofs_read_metabuf (&map->buf, sb, pos, true); + ext =erofs_read_metabuf (&map->buf, sb, pos);if (IS_ERR (ext))return PTR_ERR (ext); map->m_plen =le32_to_cpu (ext->plen);
@@ -584,7 +584,7 @@ static int z_erofs_map_blocks_ext(struct inode *inode,for (l =0 , r = vi->z_extents; l < r; ) { mid = l + (r - l) /2 ; ext =erofs_read_metabuf (&map->buf, sb, - pos + mid * recsz, true); + pos + mid * recsz);if (IS_ERR (ext))return PTR_ERR (ext);
@@ -667,7 +667,7 @@ static int z_erofs_fill_inode_lazy(struct inode *inode) goto out_unlock; pos =ALIGN (erofs_iloc (inode) + vi->inode_isize + vi->xattr_isize,8 ); - h =erofs_read_metabuf (&buf, sb, pos, true); + h =erofs_read_metabuf (&buf, sb, pos);if (IS_ERR (h)) { err =PTR_ERR (h); goto out_unlock;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 172/189 erofs: unify meta buffers in z_erofs_fill_inode()
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gao Xiang <[email protected]>
[ Upstream commit df50848bcd9f17e4e60e6d5823d0e8fe8982bbab ]
There is no need to keep additional local metabufs since we already have one in struct erofs_map_blocks.
This was actually a leftover when applying meta buffers to zmap operations, see commit 09c543798c3c ("erofs: use meta buffers for zmap operations").
Stable-dep-of: 131897c65e2b ("erofs: fix invalid algorithm for encoded extents")
--- fs/erofs/zmap.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-)
fs/erofs/zmap.c +10 -13
@@ -641,13 +641,12 @@ static int z_erofs_map_blocks_ext(struct inode *inode,return 0 ; } -static int z_erofs_fill_inode_lazy (struct inode *inode) +static int z_erofs_fill_inode (struct inode *inode,struct erofs_map_blocks *map) {struct erofs_inode *const vi =EROFS_I (inode);struct super_block *const sb = inode->i_sb;int err, headnr;erofs_off_t pos; -struct erofs_buf buf = __EROFS_BUF_INITIALIZER;struct z_erofs_map_header *h;if (test_bit (EROFS_I_Z_INITED_BIT , &vi->flags)) {
@@ -667,7 +666,7 @@ static int z_erofs_fill_inode_lazy(struct inode *inode) goto out_unlock; pos =ALIGN (erofs_iloc (inode) + vi->inode_isize + vi->xattr_isize,8 ); - h =erofs_read_metabuf (&buf, sb, pos); + h =erofs_read_metabuf (&map->buf, sb, pos);if (IS_ERR (h)) { err =PTR_ERR (h); goto out_unlock;
@@ -705,7 +704,7 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)erofs_err (sb,"unknown HEAD%u format %u for nid %llu, please upgrade kernel" , headnr +1 , vi->z_algorithmtype[headnr], vi->nid); err = -EOPNOTSUPP ; - goto out_put_metabuf; + goto out_unlock; } if (!erofs_sb_has_big_pcluster(EROFS_SB(sb)) &&
@@ -714,7 +713,7 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)erofs_err (sb,"per-inode big pcluster without sb feature for nid %llu" , vi->nid); err = -EFSCORRUPTED ; - goto out_put_metabuf; + goto out_unlock; }if (vi->datalayout ==EROFS_INODE_COMPRESSED_COMPACT && !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1) ^
@@ -722,27 +721,25 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)erofs_err (sb,"big pcluster head1/2 of compact indexes should be consistent for nid %llu" , vi->nid); err = -EFSCORRUPTED ; - goto out_put_metabuf; + goto out_unlock; }if (vi->z_idata_size || (vi->z_advise &Z_EROFS_ADVISE_FRAGMENT_PCLUSTER )) { -struct erofs_map_blocks map = { +struct erofs_map_blocks tm = { .buf = __EROFS_BUF_INITIALIZER }; - err =z_erofs_map_blocks_fo (inode, &map, + err =z_erofs_map_blocks_fo (inode, &tm,EROFS_GET_BLOCKS_FINDTAIL ); -erofs_put_metabuf (&map.buf); +erofs_put_metabuf (&tm.buf);if (err <0 ) - goto out_put_metabuf; + goto out_unlock; } done:/* paired with smp_mb() at the beginning of the function */ smp_mb ();set_bit (EROFS_I_Z_INITED_BIT , &vi->flags); -out_put_metabuf: -erofs_put_metabuf (&buf); out_unlock:clear_and_wake_up_bit (EROFS_I_BL_Z_BIT , &vi->flags);return err;
@@ -760,7 +757,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, map->m_la = inode->i_size; map->m_flags =0 ; }else { - err =z_erofs_fill_inode_lazy (inode); + err =z_erofs_fill_inode (inode, map);if (!err) {if (vi->datalayout ==EROFS_INODE_COMPRESSED_FULL && (vi->z_advise &Z_EROFS_ADVISE_EXTENTS ))
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 173/189 erofs: fix invalid algorithm for encoded extents
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gao Xiang <[email protected]>
[ Upstream commit 131897c65e2b86cf14bec7379f44aa8fbb407526 ]
The current algorithm sanity checks do not properly apply to new encoded extents.
Unify the algorithm check with Z_EROFS_COMPRESSION(_RUNTIME)_MAX and ensure consistency with sbi->available_compr_algs.
Thanks-to: Edward Adam Davis <[email protected]>
--- fs/erofs/zmap.c | 67 +++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 30 deletions(-)
fs/erofs/zmap.c +37 -30
@@ -403,10 +403,10 @@ static int z_erofs_map_blocks_fo(struct inode *inode, .inode = inode, .map = map, }; -int err =0 ; -unsigned int endoff, afmt; +unsigned int endoff;unsigned long initial_lcn;unsigned long long ofs, end; +int err; ofs = flags &EROFS_GET_BLOCKS_FINDTAIL ? inode->i_size -1 : map->m_la; if (fragment && !(flags & EROFS_GET_BLOCKS_FINDTAIL) &&
@@ -502,20 +502,15 @@ static int z_erofs_map_blocks_fo(struct inode *inode, err = -EFSCORRUPTED ; goto unmap_out; } - afmt = vi->z_advise &Z_EROFS_ADVISE_INTERLACED_PCLUSTER ? -Z_EROFS_COMPRESSION_INTERLACED : -Z_EROFS_COMPRESSION_SHIFTED ; +if (vi->z_advise &Z_EROFS_ADVISE_INTERLACED_PCLUSTER ) + map->m_algorithmformat =Z_EROFS_COMPRESSION_INTERLACED ; +else + map->m_algorithmformat =Z_EROFS_COMPRESSION_SHIFTED ; + }else if (m.headtype ==Z_EROFS_LCLUSTER_TYPE_HEAD2 ) { + map->m_algorithmformat = vi->z_algorithmtype[1 ]; }else { - afmt = m.headtype ==Z_EROFS_LCLUSTER_TYPE_HEAD2 ? - vi->z_algorithmtype[1 ] : vi->z_algorithmtype[0 ]; -if (!(EROFS_I_SB (inode)->available_compr_algs & (1 << afmt))) { -erofs_err (sb,"inconsistent algorithmtype %u for nid %llu" , - afmt, vi->nid); - err = -EFSCORRUPTED ; - goto unmap_out; - } + map->m_algorithmformat = vi->z_algorithmtype[0 ]; } - map->m_algorithmformat = afmt; if ((flags & EROFS_GET_BLOCKS_FIEMAP) || ((flags & EROFS_GET_BLOCKS_READMORE) &&
@@ -645,9 +640,9 @@ static int z_erofs_fill_inode(struct inode *inode, struct erofs_map_blocks *map) {struct erofs_inode *const vi =EROFS_I (inode);struct super_block *const sb = inode->i_sb; -int err, headnr; -erofs_off_t pos;struct z_erofs_map_header *h; +erofs_off_t pos; +int err =0 ;if (test_bit (EROFS_I_Z_INITED_BIT , &vi->flags)) {/*
@@ -661,7 +656,6 @@ static int z_erofs_fill_inode(struct inode *inode, struct erofs_map_blocks *map)if (wait_on_bit_lock (&vi->flags,EROFS_I_BL_Z_BIT ,TASK_KILLABLE ))return -ERESTARTSYS ; - err =0 ;if (test_bit (EROFS_I_Z_INITED_BIT , &vi->flags)) goto out_unlock;
@@ -698,15 +692,6 @@ static int z_erofs_fill_inode(struct inode *inode, struct erofs_map_blocks *map)else if (vi->z_advise &Z_EROFS_ADVISE_INLINE_PCLUSTER ) vi->z_idata_size =le16_to_cpu (h->h_idata_size); - headnr =0 ; -if (vi->z_algorithmtype[0 ] >=Z_EROFS_COMPRESSION_MAX || - vi->z_algorithmtype[++headnr] >=Z_EROFS_COMPRESSION_MAX ) { -erofs_err (sb,"unknown HEAD%u format %u for nid %llu, please upgrade kernel" , - headnr +1 , vi->z_algorithmtype[headnr], vi->nid); - err = -EOPNOTSUPP ; - goto out_unlock; - } -if (!erofs_sb_has_big_pcluster (EROFS_SB (sb)) && vi->z_advise & (Z_EROFS_ADVISE_BIG_PCLUSTER_1 |Z_EROFS_ADVISE_BIG_PCLUSTER_2 )) {
@@ -745,6 +730,30 @@ static int z_erofs_fill_inode(struct inode *inode, struct erofs_map_blocks *map)return err; } +static int z_erofs_map_sanity_check (struct inode *inode, +struct erofs_map_blocks *map) +{ +struct erofs_sb_info *sbi =EROFS_I_SB (inode); + +if (!(map->m_flags &EROFS_MAP_ENCODED )) +return 0 ; +if (unlikely (map->m_algorithmformat >=Z_EROFS_COMPRESSION_RUNTIME_MAX )) { +erofs_err (inode->i_sb,"unknown algorithm %d @ pos %llu for nid %llu, please upgrade kernel" , + map->m_algorithmformat, map->m_la,EROFS_I (inode)->nid); +return -EOPNOTSUPP ; + } +if (unlikely (map->m_algorithmformat <Z_EROFS_COMPRESSION_MAX && + !(sbi->available_compr_algs & (1 << map->m_algorithmformat)))) { +erofs_err (inode->i_sb,"inconsistent algorithmtype %u for nid %llu" , + map->m_algorithmformat,EROFS_I (inode)->nid); +return -EFSCORRUPTED ; + } +if (unlikely (map->m_plen >Z_EROFS_PCLUSTER_MAX_SIZE || + map->m_llen >Z_EROFS_PCLUSTER_MAX_DSIZE )) +return -EOPNOTSUPP ; +return 0 ; +} +int z_erofs_map_blocks_iter (struct inode *inode,struct erofs_map_blocks *map,int flags) {
@@ -765,10 +774,8 @@ int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map,else err =z_erofs_map_blocks_fo (inode, map, flags); } -if (!err && (map->m_flags &EROFS_MAP_ENCODED ) && -unlikely (map->m_plen >Z_EROFS_PCLUSTER_MAX_SIZE || - map->m_llen >Z_EROFS_PCLUSTER_MAX_DSIZE )) - err = -EOPNOTSUPP ; +if (!err) + err =z_erofs_map_sanity_check (inode, map);if (err) map->m_llen =0 ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 174/189 dmaengine: ti: edma: Fix memory allocation size for queue_priority_map
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anders Roxell <[email protected]>
[ Upstream commit e63419dbf2ceb083c1651852209c7f048089ac0f ]
Fix a critical memory allocation bug in edma_setup_from_hw() where queue_priority_map was allocated with insufficient memory. The code declared queue_priority_map as s8 (*)[2] (pointer to array of 2 s8), but allocated memory using sizeof(s8) instead of the correct size.
This caused out-of-bounds memory writes when accessing:
queue_priority_map[i][0] = i; queue_priority_map[i][1] = i;
The bug manifested as kernel crashes with "Oops - undefined instruction" on ARM platforms (BeagleBoard-X15) during EDMA driver probe, as the memory corruption triggered kernel hardening features on Clang.
Change the allocation to use sizeof(*queue_priority_map) which automatically gets the correct size for the 2D array structure.
--- drivers/dma/ti/edma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/dma/ti/edma.c +2 -2
@@ -2064,8 +2064,8 @@ static int edma_setup_from_hw(struct device *dev, struct edma_soc_info *pdata,* priority. So Q0 is the highest priority queue and the last queue has * the lowest priority. */ - queue_priority_map =devm_kcalloc (dev, ecc->num_tc +1 ,sizeof (s8), -GFP_KERNEL ); + queue_priority_map =devm_kcalloc (dev, ecc->num_tc +1 , +sizeof (*queue_priority_map),GFP_KERNEL );if (!queue_priority_map)return -ENOMEM ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 175/189 regulator: sy7636a: fix lifecycle of power good gpio
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Kemnade <[email protected]>
[ Upstream commit c05d0b32eebadc8be6e53196e99c64cf2bed1d99 ]
Attach the power good gpio to the regulator device devres instead of the parent device to fix problems if probe is run multiple times (rmmod/insmod or some deferral).
Message-ID: <[email protected]>
--- drivers/regulator/sy7636a-regulator.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/regulator/sy7636a-regulator.c +4 -3
@@ -83,9 +83,11 @@ static int sy7636a_regulator_probe(struct platform_device *pdev)if (!regmap)return -EPROBE_DEFER ; - gdp =devm_gpiod_get (pdev->dev.parent,"epd-pwr-good" ,GPIOD_IN ); +device_set_of_node_from_dev (&pdev->dev, pdev->dev.parent); + + gdp =devm_gpiod_get (&pdev->dev,"epd-pwr-good" ,GPIOD_IN );if (IS_ERR (gdp)) { -dev_err (pdev->dev.parent,"Power good GPIO fault %ld\n" ,PTR_ERR (gdp)); +dev_err (&pdev->dev,"Power good GPIO fault %ld\n" ,PTR_ERR (gdp));return PTR_ERR (gdp); }
@@ -105,7 +107,6 @@ static int sy7636a_regulator_probe(struct platform_device *pdev) } config.dev = &pdev->dev; - config.dev->of_node = pdev->dev.parent->of_node; config.regmap = regmap; rdev =devm_regulator_register (&pdev->dev, &desc, &config);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 176/189 erofs: fix runtime warning on truncate_folio_batch_exceptionals()
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuezhang Mo <[email protected]>
[ Upstream commit 181993bb0d626cf88cc803f4356ce5c5abe86278 ]
Commit 0e2f80afcfa6("fs/dax: ensure all pages are idle prior to filesystem unmount") introduced the WARN_ON_ONCE to capture whether the filesystem has removed all DAX entries or not and applied the fix to xfs and ext4.
Apply the missed fix on erofs to fix the runtime warning:
[ 5.266254] ------------[ cut here ]------------ [ 5.266274] WARNING: CPU: 6 PID: 3109 at mm/truncate.c:89 truncate_folio_batch_exceptionals+0xff/0x260 [ 5.266294] Modules linked in: [ 5.266999] CPU: 6 UID: 0 PID: 3109 Comm: umount Tainted: G S 6.16.0+ #6 PREEMPT(voluntary) [ 5.267012] Tainted: [S]=CPU_OUT_OF_SPEC [ 5.267017] Hardware name: Dell Inc. OptiPlex 5000/05WXFV, BIOS 1.5.1 08/24/2022 [ 5.267024] RIP: 0010:truncate_folio_batch_exceptionals+0xff/0x260 [ 5.267076] Code: 00 00 41 39 df 7f 11 eb 78 83 c3 01 49 83 c4 08 41 39 df 74 6c 48 63 f3 48 83 fe 1f 0f 83 3c 01 00 00 43 f6 44 26 08 01 74 df <0f> 0b 4a 8b 34 22 4c 89 ef 48 89 55 90 e8 ff 54 1f 00 48 8b 55 90 [ 5.267083] RSP: 0018:ffffc900013f36c8 EFLAGS: 00010202 [ 5.267095] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 [ 5.267101] RDX: ffffc900013f3790 RSI: 0000000000000000 RDI: ffff8882a1407898 [ 5.267108] RBP: ffffc900013f3740 R08: 0000000000000000 R09: 0000000000000000 [ 5.267113] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 [ 5.267119] R13: ffff8882a1407ab8 R14: ffffc900013f3888 R15: 0000000000000001 [ 5.267125] FS: 00007aaa8b437800(0000) GS:ffff88850025b000(0000) knlGS:0000000000000000 [ 5.267132] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 5.267138] CR2: 00007aaa8b3aac10 CR3: 000000024f764000 CR4: 0000000000f52ef0 [ 5.267144] PKRU: 55555554 [ 5.267150] Call Trace: [ 5.267154] <TASK> [ 5.267181] truncate_inode_pages_range+0x118/0x5e0 [ 5.267193] ? save_trace+0x54/0x390 [ 5.267296] truncate_inode_pages_final+0x43/0x60 [ 5.267309] evict+0x2a4/0x2c0 [ 5.267339] dispose_list+0x39/0x80 [ 5.267352] evict_inodes+0x150/0x1b0 [ 5.267376] generic_shutdown_super+0x41/0x180 [ 5.267390] kill_block_super+0x1b/0x50 [ 5.267402] erofs_kill_sb+0x81/0x90 [erofs] [ 5.267436] deactivate_locked_super+0x32/0xb0 [ 5.267450] deactivate_super+0x46/0x60 [ 5.267460] cleanup_mnt+0xc3/0x170 [ 5.267475] __cleanup_mnt+0x12/0x20 [ 5.267485] task_work_run+0x5d/0xb0 [ 5.267499] exit_to_user_mode_loop+0x144/0x170 [ 5.267512] do_syscall_64+0x2b9/0x7c0 [ 5.267523] ? __lock_acquire+0x665/0x2ce0 [ 5.267535] ? __lock_acquire+0x665/0x2ce0 [ 5.267560] ? lock_acquire+0xcd/0x300 [ 5.267573] ? find_held_lock+0x31/0x90 [ 5.267582] ? mntput_no_expire+0x97/0x4e0 [ 5.267606] ? mntput_no_expire+0xa1/0x4e0 [ 5.267625] ? mntput+0x24/0x50 [ 5.267634] ? path_put+0x1e/0x30 [ 5.267647] ? do_faccessat+0x120/0x2f0 [ 5.267677] ? do_syscall_64+0x1a2/0x7c0 [ 5.267686] ? from_kgid_munged+0x17/0x30 [ 5.267703] ? from_kuid_munged+0x13/0x30 [ 5.267711] ? __do_sys_getuid+0x3d/0x50 [ 5.267724] ? do_syscall_64+0x1a2/0x7c0 [ 5.267732] ? irqentry_exit+0x77/0xb0 [ 5.267743] ? clear_bhb_loop+0x30/0x80 [ 5.267752] ? clear_bhb_loop+0x30/0x80 [ 5.267765] entry_SYSCALL_64_after_hwframe+0x76/0x7e [ 5.267772] RIP: 0033:0x7aaa8b32a9fb [ 5.267781] Code: c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 f3 0f 1e fa 31 f6 e9 05 00 00 00 0f 1f 44 00 00 f3 0f 1e fa b8 a6 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 05 c3 0f 1f 40 00 48 8b 15 e9 83 0d 00 f7 d8 [ 5.267787] RSP: 002b:00007ffd7c4c9468 EFLAGS: 00000246 ORIG_RAX: 00000000000000a6 [ 5.267796] RAX: 0000000000000000 RBX: 00005a61592a8b00 RCX: 00007aaa8b32a9fb [ 5.267802] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00005a61592b2080 [ 5.267806] RBP: 00007ffd7c4c9540 R08: 00007aaa8b403b20 R09: 0000000000000020 [ 5.267812] R10: 0000000000000001 R11: 0000000000000246 R12: 00005a61592a8c00 [ 5.267817] R13: 0000000000000000 R14: 00005a61592b2080 R15: 00005a61592a8f10 [ 5.267849] </TASK> [ 5.267854] irq event stamp: 4721 [ 5.267859] hardirqs last enabled at (4727): [<ffffffff814abf50>] __up_console_sem+0x90/0xa0 [ 5.267873] hardirqs last disabled at (4732): [<ffffffff814abf35>] __up_console_sem+0x75/0xa0 [ 5.267884] softirqs last enabled at (3044): [<ffffffff8132adb3>] kernel_fpu_end+0x53/0x70 [ 5.267895] softirqs last disabled at (3042): [<ffffffff8132b5f4>] kernel_fpu_begin_mask+0xc4/0x120 [ 5.267905] ---[ end trace 0000000000000000 ]---
--- fs/erofs/super.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
fs/erofs/super.c +12 -0
@@ -999,10 +999,22 @@ static int erofs_show_options(struct seq_file *seq, struct dentry *root)return 0 ; } +static void erofs_evict_inode (struct inode *inode) +{ +#ifdef CONFIG_FS_DAX +if (IS_DAX (inode)) +dax_break_layout_final (inode); +#endif + +truncate_inode_pages_final (&inode->i_data); +clear_inode (inode); +} +const struct super_operations erofs_sops = { .put_super = erofs_put_super, .alloc_inode = erofs_alloc_inode, .free_inode = erofs_free_inode, + .evict_inode = erofs_evict_inode, .statfs = erofs_statfs, .show_options = erofs_show_options, };
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 177/189 xhci: dbc: decouple endpoint allocation from initialization
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mathias Nyman <[email protected]>
commit 220a0ffde02f962c13bc752b01aa570b8c65a37b upstream.
Decouple allocation of endpoint ring buffer from initialization of the buffer, and initialization of endpoint context parts from from the rest of the contexts.
It allows driver to clear up and reinitialize endpoint rings after disconnect without reallocating everything.
This is a prerequisite for the next patch that prevents the transfer ring from filling up with cancelled (no-op) TRBs if a debug cable is reconnected several times without transferring anything.
--- drivers/usb/host/xhci-dbgcap.c | 71 ++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 25 deletions(-)
drivers/usb/host/xhci-dbgcap.c +46 -25
@@ -101,13 +101,34 @@ static u32 xhci_dbc_populate_strings(strreturn string_length; } +static void xhci_dbc_init_ep_contexts (struct xhci_dbc *dbc) +{ +struct xhci_ep_ctx *ep_ctx; +unsigned int max_burst; +dma_addr_t deq; + + max_burst =DBC_CTRL_MAXBURST (readl (&dbc->regs->control)); + +/* Populate bulk out endpoint context: */ + ep_ctx =dbc_bulkout_ctx (dbc); + deq =dbc_bulkout_enq (dbc); + ep_ctx->ep_info =0 ; + ep_ctx->ep_info2 =dbc_epctx_info2 (BULK_OUT_EP ,1024 , max_burst); + ep_ctx->deq =cpu_to_le64 (deq | dbc->ring_out->cycle_state); + +/* Populate bulk in endpoint context: */ + ep_ctx =dbc_bulkin_ctx (dbc); + deq =dbc_bulkin_enq (dbc); + ep_ctx->ep_info =0 ; + ep_ctx->ep_info2 =dbc_epctx_info2 (BULK_IN_EP ,1024 , max_burst); + ep_ctx->deq =cpu_to_le64 (deq | dbc->ring_in->cycle_state); +} +static void xhci_dbc_init_contexts (struct xhci_dbc *dbc,u32 string_length) {struct dbc_info_context *info; -struct xhci_ep_ctx *ep_ctx;u32 dev_info; -dma_addr_t deq, dma; -unsigned int max_burst; +dma_addr_t dma;if (!dbc)return ;
@@ -121,20 +142,8 @@ static void xhci_dbc_init_contexts(struc info->serial =cpu_to_le64 (dma +DBC_MAX_STRING_LENGTH *3 ); info->length =cpu_to_le32 (string_length); -/* Populate bulk out endpoint context: */ - ep_ctx =dbc_bulkout_ctx (dbc); - max_burst =DBC_CTRL_MAXBURST (readl (&dbc->regs->control)); - deq =dbc_bulkout_enq (dbc); - ep_ctx->ep_info =0 ; - ep_ctx->ep_info2 =dbc_epctx_info2 (BULK_OUT_EP ,1024 , max_burst); - ep_ctx->deq =cpu_to_le64 (deq | dbc->ring_out->cycle_state); - -/* Populate bulk in endpoint context: */ - ep_ctx =dbc_bulkin_ctx (dbc); - deq =dbc_bulkin_enq (dbc); - ep_ctx->ep_info =0 ; - ep_ctx->ep_info2 =dbc_epctx_info2 (BULK_IN_EP ,1024 , max_burst); - ep_ctx->deq =cpu_to_le64 (deq | dbc->ring_in->cycle_state); +/* Populate bulk in and out endpoint contexts: */ +xhci_dbc_init_ep_contexts (dbc);/* Set DbC context and info registers: */ lo_hi_writeq (dbc->ctx->dma, &dbc->regs->dccp);
@@ -436,6 +445,23 @@ dbc_alloc_ctx(struct device *dev, gfp_treturn ctx; } +static void xhci_dbc_ring_init (struct xhci_ring *ring) +{ +struct xhci_segment *seg = ring->first_seg; + +/* clear all trbs on ring in case of old ring */ +memset (seg->trbs,0 ,TRB_SEGMENT_SIZE ); + +/* Only event ring does not use link TRB */ +if (ring->type !=TYPE_EVENT ) { +union xhci_trb *trb = &seg->trbs[TRBS_PER_SEGMENT -1 ]; + + trb->link.segment_ptr =cpu_to_le64 (ring->first_seg->dma); + trb->link.control =cpu_to_le32 (LINK_TOGGLE |TRB_TYPE (TRB_LINK )); + } +xhci_initialize_ring_info (ring); +} +static struct xhci_ring *xhci_dbc_ring_alloc (struct device *dev,enum xhci_ring_type type,gfp_t flags) {
@@ -464,15 +490,10 @@ xhci_dbc_ring_alloc(struct device *dev, seg->dma = dma; -/* Only event ring does not use link TRB */ -if (type !=TYPE_EVENT ) { -union xhci_trb *trb = &seg->trbs[TRBS_PER_SEGMENT -1 ]; - - trb->link.segment_ptr =cpu_to_le64 (dma); - trb->link.control =cpu_to_le32 (LINK_TOGGLE |TRB_TYPE (TRB_LINK )); - }INIT_LIST_HEAD (&ring->td_list); -xhci_initialize_ring_info (ring); + +xhci_dbc_ring_init (ring); +return ring; dma_fail:kfree (seg);
Greg Kroah-Hartman
maintainerPATCH 178/189 xhci: dbc: Fix full DbC transfer ring after several reconnects
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mathias Nyman <[email protected]>
commit a5c98e8b1398534ae1feb6e95e2d3ee5215538ed upstream.
Pending requests will be flushed on disconnect, and the corresponding TRBs will be turned into No-op TRBs, which are ignored by the xHC controller once it starts processing the ring.
If the USB debug cable repeatedly disconnects before ring is started then the ring will eventually be filled with No-op TRBs. No new transfers can be queued when the ring is full, and driver will print the following error message:
"xhci_hcd 0000:00:14.0: failed to queue trbs"
This is a normal case for 'in' transfers where TRBs are always enqueued in advance, ready to take on incoming data. If no data arrives, and device is disconnected, then ring dequeue will remain at beginning of the ring while enqueue points to first free TRB after last cancelled No-op TRB.
s
Solve this by reinitializing the rings when the debug cable disconnects and DbC is leaving the configured state.
Clear the whole ring buffer and set enqueue and dequeue to the beginning of ring, and set cycle bit to its initial state.
--- drivers/usb/host/xhci-dbgcap.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
drivers/usb/host/xhci-dbgcap.c +21 -2
@@ -462,6 +462,25 @@ static void xhci_dbc_ring_init(struct xhxhci_initialize_ring_info (ring); } +static int xhci_dbc_reinit_ep_rings (struct xhci_dbc *dbc) +{ +struct xhci_ring *in_ring = dbc->eps[BULK_IN ].ring; +struct xhci_ring *out_ring = dbc->eps[BULK_OUT ].ring; + +if (!in_ring || !out_ring || !dbc->ctx) { +dev_warn (dbc->dev,"Can't re-init unallocated endpoints\n" ); +return -ENODEV ; + } + +xhci_dbc_ring_init (in_ring); +xhci_dbc_ring_init (out_ring); + +/* set ep context enqueue, dequeue, and cycle to initial values */ +xhci_dbc_init_ep_contexts (dbc); + +return 0 ; +} +static struct xhci_ring *xhci_dbc_ring_alloc (struct device *dev,enum xhci_ring_type type,gfp_t flags) {
@@ -885,7 +904,7 @@ static enum evtreturn xhci_dbc_do_handledev_info (dbc->dev,"DbC cable unplugged\n" ); dbc->state =DS_ENABLED ;xhci_dbc_flush_requests (dbc); - +xhci_dbc_reinit_ep_rings (dbc);return EVT_DISC ; }
@@ -895,7 +914,7 @@ static enum evtreturn xhci_dbc_do_handlewritel (portsc, &dbc->regs->portsc); dbc->state =DS_ENABLED ;xhci_dbc_flush_requests (dbc); - +xhci_dbc_reinit_ep_rings (dbc);return EVT_DISC ; }
Greg Kroah-Hartman
maintainerPATCH 179/189 xhci: fix memory leak regression when freeing xhci vdev devices depth first
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mathias Nyman <[email protected]>
commit edcbe06453ddfde21f6aa763f7cab655f26133cc upstream.
Suspend-resume cycle test revealed a memory leak in 6.17-rc3
Turns out the slot_id race fix changes accidentally ends up calling xhci_free_virt_device() with an incorrect vdev parameter. The vdev variable was reused for temporary purposes right before calling xhci_free_virt_device().
Fix this by passing the correct vdev parameter.
The slot_id race fix that caused this regression was targeted for stable, so this needs to be applied there as well.
--- drivers/usb/host/xhci-mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/host/xhci-mem.c +1 -1
@@ -962,7 +962,7 @@ static void xhci_free_virt_devices_depth out:/* we are now at a leaf device */ xhci_debugfs_remove_slot (xhci, slot_id); -xhci_free_virt_device (xhci, vdev, slot_id); +xhci_free_virt_device (xhci, xhci->devs[slot_id], slot_id); } int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
Greg Kroah-Hartman
maintainerPATCH 180/189 USB: gadget: dummy-hcd: Fix locking bug in RT-enabled kernels
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alan Stern <[email protected]>
commit 8d63c83d8eb922f6c316320f50c82fa88d099bea upstream.
Yunseong Kim and the syzbot fuzzer both reported a problem in RT-enabled kernels caused by the way dummy-hcd mixes interrupt management and spin-locking. The pattern was:
local_irq_save(flags); spin_lock(&dum->lock); ... spin_unlock(&dum->lock); ... // calls usb_gadget_giveback_request() local_irq_restore(flags);
The code was written this way because usb_gadget_giveback_request() needs to be called with interrupts disabled and the private lock not held.
While this pattern works fine in non-RT kernels, it's not good when RT is enabled. RT kernels handle spinlocks much like mutexes; in particular, spin_lock() may sleep. But sleeping is not allowed while local interrupts are disabled.
To fix the problem, rewrite the code to conform to the pattern used elsewhere in dummy-hcd and other UDC drivers:
spin_lock_irqsave(&dum->lock, flags); ... spin_unlock(&dum->lock); usb_gadget_giveback_request(...); spin_lock(&dum->lock); ... spin_unlock_irqrestore(&dum->lock, flags);
This approach satisfies the RT requirements.
--- drivers/usb/gadget/udc/dummy_hcd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/usb/gadget/udc/dummy_hcd.c +4 -4
@@ -765,8 +765,7 @@ static int dummy_dequeue(struct usb_ep *if (!dum->driver)return -ESHUTDOWN ; -local_irq_save (flags); -spin_lock (&dum->lock); +spin_lock_irqsave (&dum->lock, flags);list_for_each_entry (iter, &ep->queue, queue) {if (&iter->req != _req)continue ;
@@ -776,15 +775,16 @@ static int dummy_dequeue(struct usb_ep * retval =0 ;break ; } -spin_unlock (&dum->lock);if (retval ==0 ) {dev_dbg (udc_dev (dum),"dequeued req %p from %s, len %d buf %p\n" , req, _ep->name, _req->length, _req->buf); +spin_unlock (&dum->lock);usb_gadget_giveback_request (_ep, _req); +spin_lock (&dum->lock); } -local_irq_restore (flags); +spin_unlock_irqrestore (&dum->lock, flags);return retval; }
Greg Kroah-Hartman
maintainerPATCH 181/189 usb: typec: tcpm: properly deliver cable vdms to altmode drivers
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: RD Babiera <[email protected]>
commit f34bfcc77b18375a87091c289c2eb53c249787b4 upstream.
tcpm_handle_vdm_request delivers messages to the partner altmode or the cable altmode depending on the SVDM response type, which is incorrect. The partner or cable should be chosen based on the received message type instead.
Also add this filter to ADEV_NOTIFY_USB_AND_QUEUE_VDM, which is used when the Enter Mode command is responded to by a NAK on SOP or SOP' and when the Exit Mode command is responded to by an ACK on SOP.
--- drivers/usb/typec/tcpm/tcpm.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/usb/typec/tcpm/tcpm.c +8 -4
@@ -2426,17 +2426,21 @@ static void tcpm_handle_vdm_request(strucase ADEV_NONE :break ;case ADEV_NOTIFY_USB_AND_QUEUE_VDM : -WARN_ON (typec_altmode_notify (adev,TYPEC_STATE_USB ,NULL )); -typec_altmode_vdm (adev, p[0 ], &p[1 ], cnt); +if (rx_sop_type ==TCPC_TX_SOP_PRIME ) { +typec_cable_altmode_vdm (adev,TYPEC_PLUG_SOP_P , p[0 ], &p[1 ], cnt); + }else { +WARN_ON (typec_altmode_notify (adev,TYPEC_STATE_USB ,NULL )); +typec_altmode_vdm (adev, p[0 ], &p[1 ], cnt); + }break ;case ADEV_QUEUE_VDM : -if (response_tx_sop_type ==TCPC_TX_SOP_PRIME ) +if (rx_sop_type ==TCPC_TX_SOP_PRIME )typec_cable_altmode_vdm (adev,TYPEC_PLUG_SOP_P , p[0 ], &p[1 ], cnt);else typec_altmode_vdm (adev, p[0 ], &p[1 ], cnt);break ;case ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL : -if (response_tx_sop_type ==TCPC_TX_SOP_PRIME ) { +if (rx_sop_type ==TCPC_TX_SOP_PRIME ) {if (typec_cable_altmode_vdm (adev,TYPEC_PLUG_SOP_P , p[0 ], &p[1 ], cnt)) { int svdm_version = typec_get_cable_svdm_version(
Greg Kroah-Hartman
maintainerPATCH 182/189 usb: gadget: midi2: Fix missing UMP group attributes initialization
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit 21d8525d2e061cde034277d518411b02eac764e2 upstream.
The gadget card driver forgot to call snd_ump_update_group_attrs() after adding FBs, and this leaves the UMP group attributes uninitialized. As a result, -ENODEV error is returned at opening a legacy rawmidi device as an inactive group.
This patch adds the missing call to address the behavior above.
--- drivers/usb/gadget/function/f_midi2.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/gadget/function/f_midi2.c +1 -0
@@ -1599,6 +1599,7 @@ static int f_midi2_create_card(struct f_strscpy (fb->info.name,ump_fb_name (b),sizeof (fb->info.name)); } +snd_ump_update_group_attrs (ump); }for (i =0 ; i < midi2->num_eps; i++) {
Greg Kroah-Hartman
maintainerPATCH 183/189 usb: gadget: midi2: Fix MIDI2 IN EP max packet size
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit 116e79c679a1530cf833d0ff3007061d7a716bd9 upstream.
The EP-IN of MIDI2 (altset 1) wasn't initialized in f_midi2_create_usb_configs() as it's an INT EP unlike others BULK EPs. But this leaves rather the max packet size unchanged no matter which speed is used, resulting in the very slow access. And the wMaxPacketSize values set there look legit for INT EPs, so let's initialize the MIDI2 EP-IN there for achieving the equivalent speed as well.
--- drivers/usb/gadget/function/f_midi2.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/usb/gadget/function/f_midi2.c +8 -2
@@ -1737,9 +1737,12 @@ static int f_midi2_create_usb_configs(stcase USB_SPEED_HIGH : midi2_midi1_ep_out_desc.wMaxPacketSize =cpu_to_le16 (512 ); midi2_midi1_ep_in_desc.wMaxPacketSize =cpu_to_le16 (512 ); -for (i =0 ; i < midi2->num_eps; i++) +for (i =0 ; i < midi2->num_eps; i++) { midi2_midi2_ep_out_desc[i].wMaxPacketSize =cpu_to_le16 (512 ); + midi2_midi2_ep_in_desc[i].wMaxPacketSize = +cpu_to_le16 (512 ); + } fallthrough;case USB_SPEED_FULL : midi1_in_eps = midi2_midi1_ep_in_descs;
@@ -1748,9 +1751,12 @@ static int f_midi2_create_usb_configs(stcase USB_SPEED_SUPER : midi2_midi1_ep_out_desc.wMaxPacketSize =cpu_to_le16 (1024 ); midi2_midi1_ep_in_desc.wMaxPacketSize =cpu_to_le16 (1024 ); -for (i =0 ; i < midi2->num_eps; i++) +for (i =0 ; i < midi2->num_eps; i++) { midi2_midi2_ep_out_desc[i].wMaxPacketSize =cpu_to_le16 (1024 ); + midi2_midi2_ep_in_desc[i].wMaxPacketSize = +cpu_to_le16 (1024 ); + } midi1_in_eps = midi2_midi1_ep_in_ss_descs; midi1_out_eps = midi2_midi1_ep_out_ss_descs;break ;
Greg Kroah-Hartman
maintainerPATCH 184/189 dmaengine: qcom: bam_dma: Fix DT error handling for num-channels/ees
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephan Gerhold <[email protected]>
commit 5068b5254812433e841a40886e695633148d362d upstream.
When we don't have a clock specified in the device tree, we have no way to ensure the BAM is on. This is often the case for remotely-controlled or remotely-powered BAM instances. In this case, we need to read num-channels from the DT to have all the necessary information to complete probing.
However, at the moment invalid device trees without clock and without num-channels still continue probing, because the error handling is missing return statements. The driver will then later try to read the number of channels from the registers. This is unsafe, because it relies on boot firmware and lucky timing to succeed. Unfortunately, the lack of proper error handling here has been abused for several Qualcomm SoCs upstream, causing early boot crashes in several situations [1, 2].
Avoid these early crashes by erroring out when any of the required DT properties are missing. Note that this will break some of the existing DTs upstream (mainly BAM instances related to the crypto engine). However, clearly these DTs have never been tested properly, since the error in the kernel log was just ignored. It's safer to disable the crypto engine for these broken DTBs.
[1]: https://lore.kernel.org/r/[email protected]/
[2]: https://lore.kernel.org/r/[email protected]/
--- drivers/dma/qcom/bam_dma.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/dma/qcom/bam_dma.c +6 -2
@@ -1283,13 +1283,17 @@ static int bam_dma_probe(struct platformif (!bdev->bamclk) { ret =of_property_read_u32 (pdev->dev.of_node,"num-channels" , &bdev->num_channels); -if (ret) +if (ret) {dev_err (bdev->dev,"num-channels unspecified in dt\n" ); +return ret; + } ret =of_property_read_u32 (pdev->dev.of_node,"qcom,num-ees" , &bdev->num_ees); -if (ret) +if (ret) {dev_err (bdev->dev,"num-ees unspecified in dt\n" ); +return ret; + } } ret =clk_prepare_enable (bdev->bamclk);
Greg Kroah-Hartman
maintainerPATCH 185/189 dmaengine: dw: dmamux: Fix device reference leak in rzn1_dmamux_route_allocate
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miaoqian Lin <[email protected]>
commit aa2e1e4563d3ab689ffa86ca1412ecbf9fd3b308 upstream.
The reference taken by of_find_device_by_node() must be released when not needed anymore.
Add missing put_device() call to fix device reference leaks.
--- drivers/dma/dw/rzn1-dmamux.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
drivers/dma/dw/rzn1-dmamux.c +11 -4
@@ -48,12 +48,16 @@ static void *rzn1_dmamux_route_allocate(u32 mask;int ret; -if (dma_spec->args_count !=RNZ1_DMAMUX_NCELLS ) -return ERR_PTR (-EINVAL ); +if (dma_spec->args_count !=RNZ1_DMAMUX_NCELLS ) { + ret = -EINVAL ; + goto put_device; + } map =kzalloc (sizeof (*map),GFP_KERNEL ); -if (!map) -return ERR_PTR (-ENOMEM ); +if (!map) { + ret = -ENOMEM ; + goto put_device; + } chan = dma_spec->args[0 ]; map->req_idx = dma_spec->args[4 ];
@@ -94,12 +98,15 @@ static void *rzn1_dmamux_route_allocate(if (ret) goto clear_bitmap; +put_device (&pdev->dev);return map; clear_bitmap:clear_bit (map->req_idx, dmamux->used_chans); free_map:kfree (map); +put_device: +put_device (&pdev->dev);return ERR_PTR (ret); }
Greg Kroah-Hartman
maintainerPATCH 186/189 phy: qcom: qmp-pcie: Fix PHY initialization when powered down by firmware
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephan Gerhold <[email protected]>
commit 6cb8c1f957f674ca20b7d7c96b1f1bb11b83b679 upstream.
Commit 0cc22f5a861c ("phy: qcom: qmp-pcie: Add PHY register retention support") added support for using the "no_csr" reset to skip configuration of the PHY if the init sequence was already applied by the boot firmware. The expectation is that the PHY is only turned on/off by using the "no_csr" reset, instead of powering it down and re-programming it after a full reset.
The boot firmware on X1E does not fully conform to this expectation: If the PCIe3 link fails to come up (e.g. because no PCIe card is inserted), the firmware powers down the PHY using the QPHY_PCS_POWER_DOWN_CONTROL register. The QPHY_START_CTRL register is kept as-is, so the driver assumes the PHY is already initialized and skips the configuration/power up sequence. The PHY won't come up again without clearing the QPHY_PCS_POWER_DOWN_CONTROL, so eventually initialization fails:
qcom-qmp-pcie-phy 1be0000.phy: phy initialization timed-out phy phy-1be0000.phy.0: phy poweron failed --> -110
qcom-pcie 1bd0000.pcie: cannot initialize host
qcom-pcie 1bd0000.pcie: probe with driver qcom-pcie failed with error -110
This can be reliably reproduced on the X1E CRD, QCP and Devkit when no card is inserted for PCIe3.
Fix this by checking the QPHY_PCS_POWER_DOWN_CONTROL register in addition to QPHY_START_CTRL. If the PHY is powered down with the register, it doesn't conform to the expectations for using the "no_csr" reset, so we fully re-initialize with the normal reset sequence.
Also check the register more carefully to ensure all of the bits we expect are actually set. A simple !!(readl()) is not enough, because the PHY might be only partially set up with some of the expected bits set.
--- drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-)
drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +19 -6
@@ -3064,6 +3064,14 @@ struct qmp_pcie {struct clk_fixed_rate aux_clk_fixed; }; +static bool qphy_checkbits (const void __iomem *base,u32 offset,u32 val) +{ +u32 reg; + + reg =readl (base + offset); +return (reg & val) == val; +} +static inline void qphy_setbits (void __iomem *base,u32 offset,u32 val) {u32 reg;
@@ -4332,16 +4340,21 @@ static int qmp_pcie_init(struct phy *phystruct qmp_pcie *qmp =phy_get_drvdata (phy);const struct qmp_phy_cfg *cfg = qmp->cfg;void __iomem *pcs = qmp->pcs; -bool phy_initialized = !!(readl (pcs + cfg->regs[QPHY_START_CTRL ]));int ret; - qmp->skip_init = qmp->nocsr_reset && phy_initialized;/* -* We need to check the existence of init sequences in two cases: -* 1. The PHY doesn't support no_csr reset. -* 2. The PHY supports no_csr reset but isn't initialized by bootloader. -* As we can't skip init in these two cases. +* We can skip PHY initialization if all of the following conditions +* are met: +* 1. The PHY supports the nocsr_reset that preserves the PHY config. +* 2. The PHY was started (and not powered down again) by the +* bootloader, with all of the expected bits set correctly. +* In this case, we can continue without having the init sequence +* defined in the driver. */ + qmp->skip_init = qmp->nocsr_reset && +qphy_checkbits (pcs, cfg->regs[QPHY_START_CTRL ],SERDES_START |PCS_START ) && +qphy_checkbits (pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL ], cfg->pwrdn_ctrl); +if (!qmp->skip_init && !cfg->tbls.serdes_num) {dev_err (qmp->dev,"Init sequence not available\n" );return -ENODATA ;
Greg Kroah-Hartman
maintainerPATCH 187/189 phy: tegra: xusb: fix device and OF node leak at probe
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit bca065733afd1e3a89a02f05ffe14e966cd5f78e upstream.
Make sure to drop the references taken to the PMC OF node and device by of_parse_phandle() and of_find_device_by_node() during probe.
Note the holding a reference to the PMC device does not prevent the PMC regmap from going away (e.g. if the PMC driver is unbound) so there is no need to keep the reference.
--- drivers/phy/tegra/xusb-tegra210.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/phy/tegra/xusb-tegra210.c +5 -1
@@ -3164,18 +3164,22 @@ tegra210_xusb_padctl_probe(struct device } pdev =of_find_device_by_node (np); +of_node_put (np);if (!pdev) {dev_warn (dev,"PMC device is not available\n" ); goto out; } -if (!platform_get_drvdata (pdev)) +if (!platform_get_drvdata (pdev)) { +put_device (&pdev->dev);return ERR_PTR (-EPROBE_DEFER ); + } padctl->regmap =dev_get_regmap (&pdev->dev,"usb_sleepwalk" );if (!padctl->regmap)dev_info (dev,"failed to find PMC regmap\n" ); +put_device (&pdev->dev); out:return &padctl->base; }
Greg Kroah-Hartman
maintainerPATCH 188/189 phy: ti: omap-usb2: fix device leak at unbind
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 64961557efa1b98f375c0579779e7eeda1a02c42 upstream.
Make sure to drop the reference to the control device taken by of_find_device_by_node() during probe when the driver is unbound.
--- drivers/phy/ti/phy-omap-usb2.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/phy/ti/phy-omap-usb2.c +13 -0
@@ -363,6 +363,13 @@ static void omap_usb2_init_errata(struct phy->flags |=OMAP_USB2_DISABLE_CHRG_DET ; } +static void omap_usb2_put_device (void *_dev) +{ +struct device *dev = _dev; + +put_device (dev); +} +static int omap_usb2_probe (struct platform_device *pdev) {struct omap_usb *phy;
@@ -373,6 +380,7 @@ static int omap_usb2_probe(struct platfostruct device_node *control_node;struct platform_device *control_pdev;const struct usb_phy_data *phy_data; +int ret; phy_data =device_get_match_data (&pdev->dev);if (!phy_data)
@@ -423,6 +431,11 @@ static int omap_usb2_probe(struct platforeturn -EINVAL ; } phy->control_dev = &control_pdev->dev; + + ret =devm_add_action_or_reset (&pdev->dev, omap_usb2_put_device, + phy->control_dev); +if (ret) +return ret; }else { if (of_property_read_u32_index(node, "syscon-phy-power", 1,
Greg Kroah-Hartman
maintainerPATCH 189/189 phy: ti-pipe3: fix device leak at unbind
In reply to Greg Kroah-Hartman6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit e19bcea99749ce8e8f1d359f68ae03210694ad56 upstream.
Make sure to drop the reference to the control device taken by of_find_device_by_node() during probe when the driver is unbound.
--- drivers/phy/ti/phy-ti-pipe3.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/phy/ti/phy-ti-pipe3.c +13 -0
@@ -667,12 +667,20 @@ static int ti_pipe3_get_clk(struct ti_pireturn 0 ; } +static void ti_pipe3_put_device (void *_dev) +{ +struct device *dev = _dev; + +put_device (dev); +} +static int ti_pipe3_get_sysctrl (struct ti_pipe3 *phy) {struct device *dev = phy->dev;struct device_node *node = dev->of_node;struct device_node *control_node;struct platform_device *control_pdev; +int ret; phy->phy_power_syscon =syscon_regmap_lookup_by_phandle (node,"syscon-phy-power" );
@@ -704,6 +712,11 @@ static int ti_pipe3_get_sysctrl(struct t } phy->control_dev = &control_pdev->dev; + + ret =devm_add_action_or_reset (dev, ti_pipe3_put_device, + phy->control_dev); +if (ret) +return ret; }if (phy->mode ==PIPE3_MODE_PCIE ) {
The kernel, bpf tool, perf tool, and kselftest builds fine for v6.16.8-rc1 on x86 and arm64 Azure VM.
Thanks,
Hardik
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.16.8 release. There are 189 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, 19 Sep 2025 12:32:53 +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.16.8-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.16.y
and the diffstat can be found below.thanks,
greg k-h
Thanks! Builded on all Alpine architectures & booted on x86_64.
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.16.8 release. There are 189 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, 19 Sep 2025 12:32:53 +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.16.8-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.16.y
and the diffstat can be found below.thanks,
greg k-h
All tests passing for Tegra ...
Test results for stable-v6.16:
10 builds: 10 pass, 0 fail
28 boots: 28 pass, 0 fail
120 tests: 120 pass, 0 failLinux version: 6.16.8-rc1-gfb25a6be32b3
Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000,
tegra186-p3509-0000+p3636-0001, tegra194-p2972-0000,
tegra194-p3509-0000+p3668-0000, tegra20-ventana,
tegra210-p2371-2180, tegra210-p3450-0000,
tegra30-cardhu-a04Jon
[2025-09-17 14:31] Greg Kroah-Hartman:
Quoted 5 lines
This is the start of the stable review cycle for the 6.16.8 release. There are 189 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.
Quoted 8 lines
Responses should be made by Fri, 19 Sep 2025 12:32:53 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.16.8-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.16.y
and the diffstat can be found below.
Hi Greg,
both vanilla 6.16.8-rc1 and 6.16.8-rc1 with the additional patch "netfilter: nft_set_pipapo: fix null deref for empty set" from the stable queue (https://git.kernel.org/pub/scm/linux/kernel/git/stable/stable-queue.git/tree/queue-6.16/netfilter-nft_set_pipapo-fix-null-deref-for-empty-set.patch?id=0c6237e517860496c3dece455ec705bbcc9a0d79) compile fine for x86_64 using GCC 15.2.1+r22+gc4e96a094636 and binutils 2.45+r29+g2b2e51a31ec7, and the resulting kernels booted and ran/runs without any discernible issues on various physical machines of mine (Ivy Bridge, Haswell, Kaby Lake, Coffee Lake) and on a Zen 2 VM and a bunch of Kaby Lake VMs.
Regards
Pascal
Pascal Ernster
Tested-by[2025-09-17 22:51] Pascal Ernster:
Quoted 3 lines
Hi Greg,
both vanilla 6.16.8-rc1 and 6.16.8-rc1 with the additional patch "netfilter:
nft_set_pipapo: fix null deref for empty set" from the stable queue (https://git.kernel.org/pub/scm/linux/kernel/git/stable/stable-queue.git/tree/queue-6.16/netfilter-nft_set_pipapo-fix-null-deref-for-empty-set.patch?id=0c6237e517860496c3dece455ec705bbcc9a0d79) compile fine forx86_64using GCC 15.2.1+r22+gc4e96a094636 and binutils 2.45+r29+g2b2e51a31ec7, and the resulting kernels booted and ran/runs without any discernible issues on various physical machines of mine (Ivy Bridge, Haswell, Kaby Lake, Coffee Lake) and on a Zen 2 VM and a bunch of Kaby Lake VMs.
Am 17.09.2025 um 14:31 schrieb Greg Kroah-Hartman:
Quoted 4 lines
This is the start of the stable review cycle for the 6.16.8 release. There are 189 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.
Builds, boots and works on my 2-socket Ivy Bridge Xeon E5-2697 v2 server. No dmesg oddities or regressions found.
Beste Grüße,
Peter Schneider
Signature · 8 lines
Climb the mountain not to plant your flag, but to embrace the challenge, enjoy the air and behold the view. Climb it so you can see the world, not so the world can see you. -- David McCullough Jr. OpenPGP: 0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244 Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc https://keys.mailvelope.com/pks/lookup?op=get&[email protected] https://keys.mailvelope.com/pks/lookup?op=get&[email protected]
Hi Greg
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.16.8 release. There are 189 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, 19 Sep 2025 12:32:53 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.16.8-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.16.y
and the diffstat can be found below.thanks,
greg k-h
6.16.8-rc1 tested.
Build successfully completed.
Boot successfully completed.
No dmesg regressions.
Video output normal.
Sound output normal.
Lenovo ThinkPad X1 Carbon Gen10(Intel i7-1260P(x86_64) arch linux)
[ 0.000000] Linux version 6.16.8-rc1rv-gfb25a6be32b3
(takeshi@ThinkPadX1Gen10J0764) (gcc (GCC) 15.2.1 20250813, GNU ld (GNU Binutils) 2.45.0) #1 SMP PREEMPT_DYNAMIC Thu Sep 18 11:43:14 JST 2025
Thanks
# Librecast Test Results
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 6.16.8-rc1-gfb25a6be32b3 #80 SMP PREEMPT_DYNAMIC Wed Sep 17 13:17:09 -00 2025 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.16.8 release. There are 189 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, 19 Sep 2025 12:32:53 +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.16.8-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.16.y
and the diffstat can be found below.thanks,
greg k-h
Results from Linaro's test farm.
No regressions on arm64, arm, x86_64, and i386.
## Build
* kernel: 6.16.8-rc1
* git: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
* git commit: fb25a6be32b38a3267e8037fc4bf1a559316360a
* git describe: v6.16.6-198-gfb25a6be32b3
* test details:
https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-6.16.y/build/v6.16.6-198-gfb25a6be32b3
## Test Regressions (compared to v6.16.4-327-g665877a17a1b)
## Metric Regressions (compared to v6.16.4-327-g665877a17a1b)
## Test Fixes (compared to v6.16.4-327-g665877a17a1b)
## Metric Fixes (compared to v6.16.4-327-g665877a17a1b)
## Test result summary
total: 338478, pass: 312378, fail: 6637, skip: 19463, xfail: 0
## Build Summary
* arc: 5 total, 5 passed, 0 failed
* arm: 139 total, 138 passed, 1 failed
* arm64: 57 total, 56 passed, 1 failed
* i386: 18 total, 18 passed, 0 failed
* mips: 34 total, 27 passed, 7 failed
* parisc: 4 total, 4 passed, 0 failed
* powerpc: 40 total, 38 passed, 2 failed
* riscv: 25 total, 25 passed, 0 failed
* s390: 22 total, 22 passed, 0 failed
* sh: 5 total, 5 passed, 0 failed
* sparc: 4 total, 3 passed, 1 failed
* x86_64: 49 total, 47 passed, 2 failed
## Test suites summary
* boot
* commands
* kselftest-arm64
* kselftest-breakpoints
* kselftest-capabilities
* kselftest-cgroup
* kselftest-clone3
* kselftest-core
* kselftest-cpu-hotplug
* kselftest-cpufreq
* kselftest-efivarfs
* kselftest-exec
* kselftest-fpu
* kselftest-ftrace
* kselftest-futex
* kselftest-gpio
* kselftest-intel_pstate
* kselftest-ipc
* kselftest-kcmp
* kselftest-kvm
* kselftest-livepatch
* kselftest-membarrier
* kselftest-memfd
* kselftest-mincore
* kselftest-mm
* kselftest-mqueue
* kselftest-net
* kselftest-net-mptcp
* kselftest-openat2
* kselftest-ptrace
* kselftest-rseq
* kselftest-rtc
* kselftest-rust
* kselftest-seccomp
* kselftest-sigaltstack
* kselftest-size
* kselftest-tc-testing
* kselftest-timers
* kselftest-tmpfs
* kselftest-tpm2
* kselftest-user_events
* kselftest-vDSO
* kselftest-x86
* kunit
* kvm-unit-tests
* lava
* libgpiod
* libhugetlbfs
* log-parser-boot
* log-parser-build-clang
* log-parser-build-gcc
* log-parser-test
* ltp-capability
* ltp-commands
* ltp-containers
* ltp-controllers
* ltp-cpuhotplug
* ltp-crypto
* ltp-cve
* ltp-dio
* ltp-fcntl-locktests
* ltp-fs
* ltp-fs_bind
* ltp-fs_perms_simple
* ltp-hugetlb
* ltp-math
* ltp-mm
* ltp-nptl
* ltp-pty
* ltp-sched
* ltp-smoke
* ltp-syscalls
* ltp-tracing
* modules
* perf
* rcutorture
* rt-tests-cyclicdeadline
* rt-tests-pi-stress
* rt-tests-pmqtest
* rt-tests-rt-migrate-test
* rt-tests-signaltest
--
Linaro LKFT
https://lkft.linaro.org
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.16.8 release. There are 189 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, 19 Sep 2025 12:32:53 +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.16.8-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.16.y
and the diffstat can be found below.thanks,
greg k-h
Build and boot tested 6.16.8-rc1 using qemu-x86_64. The kernel was successfully built and booted in a virtualized environment without issues.
Build
kernel: 6.16.8-rc1
git: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
git commit: fb25a6be32b38a3267e8037fc4bf1a559316360a
Best regards
Dileep M
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.16.8 release. There are 189 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, 19 Sep 2025 12:32:53 +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.16.8-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.16.y
and the diffstat can be found below.thanks,
greg k-h
Built and booted successfully on RISC-V RV64 (HiFive Unmatched).
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.16.8 release. There are 189 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.
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.16.8 release. There are 189 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, 19 Sep 2025 12:32:53 +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.16.8-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.16.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMST using 32-bit and 64-bit ARM kernels, build tested on BMIPS_GENERIC:
Signature · 1 line
Florian
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 6.16.8 release. There are 189 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.
CIP testing did not find any problems here:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-6.16.y
6.6 passes our testing, too.
Best regards,
Pavel
Signature · 2 lines
In cooperation with DENX Software Engineering GmbH, HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.16.8 release. There are 189 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, 19 Sep 2025 12:32:53 +0000. Anything received after that time might be too late.
Tested on the following hardware:
* a ThinkPad E14 Gen 3 with a AMD Ryzen 5 5500U CPU
* a Framework Laptop with a Ryzen AI 5 340
* a Framework Desktop
* a Steam Deck (LCD Edition)