From: Sasha Levin Date: Fri, 12 Mar 2021 23:04:40 +0000 (-0500) Subject: Fixes for 5.10 X-Git-Tag: v4.4.262~74 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=167f39cf87bf58497e8ee731b055bce0edd69514;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.10 Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/ath11k-fix-ap-mode-for-qca6390.patch b/queue-5.10/ath11k-fix-ap-mode-for-qca6390.patch new file mode 100644 index 00000000000..e21ebc1a0dc --- /dev/null +++ b/queue-5.10/ath11k-fix-ap-mode-for-qca6390.patch @@ -0,0 +1,60 @@ +From b1670b113b0c23315d3fc95af7f119378084459d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Feb 2021 17:14:09 +0200 +Subject: ath11k: fix AP mode for QCA6390 + +From: Kalle Valo + +[ Upstream commit 77d7e87128d4dfb400df4208b2812160e999c165 ] + +Commit c134d1f8c436 ("ath11k: Handle errors if peer creation fails") completely +broke AP mode on QCA6390: + +kernel: [ 151.230734] ath11k_pci 0000:06:00.0: failed to create peer after vdev start delay: -22 +wpa_supplicant[2307]: Failed to set beacon parameters +wpa_supplicant[2307]: Interface initialization failed +wpa_supplicant[2307]: wlan0: interface state UNINITIALIZED->DISABLED +wpa_supplicant[2307]: wlan0: AP-DISABLED +wpa_supplicant[2307]: wlan0: Unable to setup interface. +wpa_supplicant[2307]: Failed to initialize AP interface + +This was because commit c134d1f8c436 ("ath11k: Handle errors if peer creation +fails") added error handling for ath11k_peer_create(), which had been failing +all along but was unnoticed due to the missing error handling. The actual bug +was introduced already in commit aa44b2f3ecd4 ("ath11k: start vdev if a bss peer is +already created"). + +ath11k_peer_create() was failing because for AP mode the peer is created +already earlier op_add_interface() and we should skip creation here, but the +check for modes was wrong. Fixing that makes AP mode work again. + +This shouldn't affect IPQ8074 nor QCN9074 as they have hw_params.vdev_start_delay disabled. + +Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 + +Fixes: c134d1f8c436 ("ath11k: Handle errors if peer creation fails") +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/1614006849-25764-1-git-send-email-kvalo@codeaurora.org +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/mac.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index f3c5023f8a45..ee0edd918560 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -5262,8 +5262,8 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, + } + + if (ab->hw_params.vdev_start_delay && +- (arvif->vdev_type == WMI_VDEV_TYPE_AP || +- arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)) { ++ arvif->vdev_type != WMI_VDEV_TYPE_AP && ++ arvif->vdev_type != WMI_VDEV_TYPE_MONITOR) { + param.vdev_id = arvif->vdev_id; + param.peer_type = WMI_PEER_TYPE_DEFAULT; + param.peer_addr = ar->mac_addr; +-- +2.30.1 + diff --git a/queue-5.10/ath11k-peer-delete-synchronization-with-firmware.patch b/queue-5.10/ath11k-peer-delete-synchronization-with-firmware.patch new file mode 100644 index 00000000000..1267694c48b --- /dev/null +++ b/queue-5.10/ath11k-peer-delete-synchronization-with-firmware.patch @@ -0,0 +1,212 @@ +From 0f24b33cc67c55b0f1bc65b8c35475ac6c4e7eb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Nov 2020 17:59:14 +0200 +Subject: ath11k: peer delete synchronization with firmware + +From: Ritesh Singh + +[ Upstream commit 690ace20ff790f443c3cbaf12e1769e4eb0072db ] + +Peer creation in firmware fails, if last peer deletion +is still in progress. +Hence, add wait for the event after deleting every peer +from host driver to synchronize with firmware. + +Signed-off-by: Ritesh Singh +Signed-off-by: Maharaja Kennadyrajan +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/1605514143-17652-3-git-send-email-mkenna@codeaurora.org +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/core.c | 1 + + drivers/net/wireless/ath/ath11k/core.h | 1 + + drivers/net/wireless/ath/ath11k/mac.c | 17 +++++++++- + drivers/net/wireless/ath/ath11k/peer.c | 44 ++++++++++++++++++++++++-- + drivers/net/wireless/ath/ath11k/peer.h | 2 ++ + drivers/net/wireless/ath/ath11k/wmi.c | 17 ++++++++-- + 6 files changed, 75 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c +index ebd6886a8c18..a68fe3a45a74 100644 +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -774,6 +774,7 @@ static void ath11k_core_restart(struct work_struct *work) + complete(&ar->scan.started); + complete(&ar->scan.completed); + complete(&ar->peer_assoc_done); ++ complete(&ar->peer_delete_done); + complete(&ar->install_key_done); + complete(&ar->vdev_setup_done); + complete(&ar->bss_survey_done); +diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h +index 5a7915f75e1e..c8e36251068c 100644 +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -502,6 +502,7 @@ struct ath11k { + u8 lmac_id; + + struct completion peer_assoc_done; ++ struct completion peer_delete_done; + + int install_key_status; + struct completion install_key_done; +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index b5bd9b06da89..c8f1b786e746 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -4589,8 +4589,22 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, + + err_peer_del: + if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { ++ reinit_completion(&ar->peer_delete_done); ++ ++ ret = ath11k_wmi_send_peer_delete_cmd(ar, vif->addr, ++ arvif->vdev_id); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n", ++ arvif->vdev_id, vif->addr); ++ return ret; ++ } ++ ++ ret = ath11k_wait_for_peer_delete_done(ar, arvif->vdev_id, ++ vif->addr); ++ if (ret) ++ return ret; ++ + ar->num_peers--; +- ath11k_wmi_send_peer_delete_cmd(ar, vif->addr, arvif->vdev_id); + } + + err_vdev_del: +@@ -6413,6 +6427,7 @@ int ath11k_mac_allocate(struct ath11k_base *ab) + mutex_init(&ar->conf_mutex); + init_completion(&ar->vdev_setup_done); + init_completion(&ar->peer_assoc_done); ++ init_completion(&ar->peer_delete_done); + init_completion(&ar->install_key_done); + init_completion(&ar->bss_survey_done); + init_completion(&ar->scan.started); +diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c +index 61ad9300eafb..1866d82678fa 100644 +--- a/drivers/net/wireless/ath/ath11k/peer.c ++++ b/drivers/net/wireless/ath/ath11k/peer.c +@@ -177,12 +177,36 @@ static int ath11k_wait_for_peer_deleted(struct ath11k *ar, int vdev_id, const u8 + return ath11k_wait_for_peer_common(ar->ab, vdev_id, addr, false); + } + ++int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id, ++ const u8 *addr) ++{ ++ int ret; ++ unsigned long time_left; ++ ++ ret = ath11k_wait_for_peer_deleted(ar, vdev_id, addr); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed wait for peer deleted"); ++ return ret; ++ } ++ ++ time_left = wait_for_completion_timeout(&ar->peer_delete_done, ++ 3 * HZ); ++ if (time_left == 0) { ++ ath11k_warn(ar->ab, "Timeout in receiving peer delete response\n"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ + int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr) + { + int ret; + + lockdep_assert_held(&ar->conf_mutex); + ++ reinit_completion(&ar->peer_delete_done); ++ + ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id); + if (ret) { + ath11k_warn(ar->ab, +@@ -191,7 +215,7 @@ int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr) + return ret; + } + +- ret = ath11k_wait_for_peer_deleted(ar, vdev_id, addr); ++ ret = ath11k_wait_for_peer_delete_done(ar, vdev_id, addr); + if (ret) + return ret; + +@@ -247,8 +271,22 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, + spin_unlock_bh(&ar->ab->base_lock); + ath11k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n", + param->peer_addr, param->vdev_id); +- ath11k_wmi_send_peer_delete_cmd(ar, param->peer_addr, +- param->vdev_id); ++ ++ reinit_completion(&ar->peer_delete_done); ++ ++ ret = ath11k_wmi_send_peer_delete_cmd(ar, param->peer_addr, ++ param->vdev_id); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n", ++ param->vdev_id, param->peer_addr); ++ return ret; ++ } ++ ++ ret = ath11k_wait_for_peer_delete_done(ar, param->vdev_id, ++ param->peer_addr); ++ if (ret) ++ return ret; ++ + return -ENOENT; + } + +diff --git a/drivers/net/wireless/ath/ath11k/peer.h b/drivers/net/wireless/ath/ath11k/peer.h +index 5d125ce8984e..bba2e00b6944 100644 +--- a/drivers/net/wireless/ath/ath11k/peer.h ++++ b/drivers/net/wireless/ath/ath11k/peer.h +@@ -41,5 +41,7 @@ void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id); + int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr); + int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, + struct ieee80211_sta *sta, struct peer_create_params *param); ++int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id, ++ const u8 *addr); + + #endif /* _PEER_H_ */ +diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c +index 04b8b002edfe..173ab6ceed1f 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -5532,15 +5532,26 @@ static int ath11k_ready_event(struct ath11k_base *ab, struct sk_buff *skb) + static void ath11k_peer_delete_resp_event(struct ath11k_base *ab, struct sk_buff *skb) + { + struct wmi_peer_delete_resp_event peer_del_resp; ++ struct ath11k *ar; + + if (ath11k_pull_peer_del_resp_ev(ab, skb, &peer_del_resp) != 0) { + ath11k_warn(ab, "failed to extract peer delete resp"); + return; + } + +- /* TODO: Do we need to validate whether ath11k_peer_find() return NULL +- * Why this is needed when there is HTT event for peer delete +- */ ++ rcu_read_lock(); ++ ar = ath11k_mac_get_ar_by_vdev_id(ab, peer_del_resp.vdev_id); ++ if (!ar) { ++ ath11k_warn(ab, "invalid vdev id in peer delete resp ev %d", ++ peer_del_resp.vdev_id); ++ rcu_read_unlock(); ++ return; ++ } ++ ++ complete(&ar->peer_delete_done); ++ rcu_read_unlock(); ++ ath11k_dbg(ab, ATH11K_DBG_WMI, "peer delete resp for vdev id %d addr %pM\n", ++ peer_del_resp.vdev_id, peer_del_resp.peer_macaddr.addr); + } + + static inline const char *ath11k_wmi_vdev_resp_print(u32 vdev_resp_status) +-- +2.30.1 + diff --git a/queue-5.10/ath11k-start-vdev-if-a-bss-peer-is-already-created.patch b/queue-5.10/ath11k-start-vdev-if-a-bss-peer-is-already-created.patch new file mode 100644 index 00000000000..33cbb923f9e --- /dev/null +++ b/queue-5.10/ath11k-start-vdev-if-a-bss-peer-is-already-created.patch @@ -0,0 +1,105 @@ +From fa7bf57f7938aea2770df6d7b069b36da3cce238 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Dec 2020 00:13:58 -0500 +Subject: ath11k: start vdev if a bss peer is already created + +From: Carl Huang + +[ Upstream commit aa44b2f3ecd41f90b7e477158036648a49d21a32 ] + +For QCA6390, bss peer must be created before vdev is to start. This +change is to start vdev if a bss peer is created. Otherwise, ath11k +delays to start vdev. + +This fixes an issue in a case where HT/VHT/HE settings change between +authentication and association, e.g., due to the user space request +to disable HT. + +Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 + +Signed-off-by: Carl Huang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20201211051358.9191-1-cjhuang@codeaurora.org +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/mac.c | 8 ++++++-- + drivers/net/wireless/ath/ath11k/peer.c | 17 +++++++++++++++++ + drivers/net/wireless/ath/ath11k/peer.h | 2 ++ + 3 files changed, 25 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index c8f1b786e746..f3c5023f8a45 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -2986,6 +2986,7 @@ static int ath11k_mac_station_add(struct ath11k *ar, + } + + if (ab->hw_params.vdev_start_delay && ++ !arvif->is_started && + arvif->vdev_type != WMI_VDEV_TYPE_AP) { + ret = ath11k_start_vdev_delay(ar->hw, vif); + if (ret) { +@@ -5248,7 +5249,8 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, + /* for QCA6390 bss peer must be created before vdev_start */ + if (ab->hw_params.vdev_start_delay && + arvif->vdev_type != WMI_VDEV_TYPE_AP && +- arvif->vdev_type != WMI_VDEV_TYPE_MONITOR) { ++ arvif->vdev_type != WMI_VDEV_TYPE_MONITOR && ++ !ath11k_peer_find_by_vdev_id(ab, arvif->vdev_id)) { + memcpy(&arvif->chanctx, ctx, sizeof(*ctx)); + ret = 0; + goto out; +@@ -5259,7 +5261,9 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, + goto out; + } + +- if (ab->hw_params.vdev_start_delay) { ++ if (ab->hw_params.vdev_start_delay && ++ (arvif->vdev_type == WMI_VDEV_TYPE_AP || ++ arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)) { + param.vdev_id = arvif->vdev_id; + param.peer_type = WMI_PEER_TYPE_DEFAULT; + param.peer_addr = ar->mac_addr; +diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c +index 1866d82678fa..b69e7ebfa930 100644 +--- a/drivers/net/wireless/ath/ath11k/peer.c ++++ b/drivers/net/wireless/ath/ath11k/peer.c +@@ -76,6 +76,23 @@ struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab, + return NULL; + } + ++struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab, ++ int vdev_id) ++{ ++ struct ath11k_peer *peer; ++ ++ spin_lock_bh(&ab->base_lock); ++ ++ list_for_each_entry(peer, &ab->peers, list) { ++ if (vdev_id == peer->vdev_id) { ++ spin_unlock_bh(&ab->base_lock); ++ return peer; ++ } ++ } ++ spin_unlock_bh(&ab->base_lock); ++ return NULL; ++} ++ + void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id) + { + struct ath11k_peer *peer; +diff --git a/drivers/net/wireless/ath/ath11k/peer.h b/drivers/net/wireless/ath/ath11k/peer.h +index bba2e00b6944..8553ed061aea 100644 +--- a/drivers/net/wireless/ath/ath11k/peer.h ++++ b/drivers/net/wireless/ath/ath11k/peer.h +@@ -43,5 +43,7 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, + struct ieee80211_sta *sta, struct peer_create_params *param); + int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id, + const u8 *addr); ++struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab, ++ int vdev_id); + + #endif /* _PEER_H_ */ +-- +2.30.1 + diff --git a/queue-5.10/enetc-fix-unused-var-build-warning-for-config_of.patch b/queue-5.10/enetc-fix-unused-var-build-warning-for-config_of.patch new file mode 100644 index 00000000000..e4316575799 --- /dev/null +++ b/queue-5.10/enetc-fix-unused-var-build-warning-for-config_of.patch @@ -0,0 +1,106 @@ +From 46e5105d05a088a29ea70d9ecb80904fdb711c4b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Dec 2020 14:08:00 +0200 +Subject: enetc: Fix unused var build warning for CONFIG_OF + +From: Arnd Bergmann + +[ Upstream commit 4560b2a3ecdd5d587c4c6eea4339899f173a559a ] + +When CONFIG_OF is disabled, there is a harmless warning about +an unused variable: + +enetc_pf.c: In function 'enetc_phylink_create': +enetc_pf.c:981:17: error: unused variable 'dev' [-Werror=unused-variable] + +Slightly rearrange the code to pass around the of_node as a +function argument, which avoids the problem without hurting +readability. + +Fixes: 71b77a7a27a3 ("enetc: Migrate to PHYLINK and PCS_LYNX") +Signed-off-by: Arnd Bergmann +Signed-off-by: Claudiu Manoil +Link: https://lore.kernel.org/r/20201204120800.17193-1-claudiu.manoil@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/freescale/enetc/enetc_pf.c | 21 +++++++++---------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c +index b35096455293..f29058dddb36 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c +@@ -859,13 +859,12 @@ static bool enetc_port_has_pcs(struct enetc_pf *pf) + pf->if_mode == PHY_INTERFACE_MODE_USXGMII); + } + +-static int enetc_mdiobus_create(struct enetc_pf *pf) ++static int enetc_mdiobus_create(struct enetc_pf *pf, struct device_node *node) + { +- struct device *dev = &pf->si->pdev->dev; + struct device_node *mdio_np; + int err; + +- mdio_np = of_get_child_by_name(dev->of_node, "mdio"); ++ mdio_np = of_get_child_by_name(node, "mdio"); + if (mdio_np) { + err = enetc_mdio_probe(pf, mdio_np); + +@@ -1009,18 +1008,17 @@ static const struct phylink_mac_ops enetc_mac_phylink_ops = { + .mac_link_down = enetc_pl_mac_link_down, + }; + +-static int enetc_phylink_create(struct enetc_ndev_priv *priv) ++static int enetc_phylink_create(struct enetc_ndev_priv *priv, ++ struct device_node *node) + { + struct enetc_pf *pf = enetc_si_priv(priv->si); +- struct device *dev = &pf->si->pdev->dev; + struct phylink *phylink; + int err; + + pf->phylink_config.dev = &priv->ndev->dev; + pf->phylink_config.type = PHYLINK_NETDEV; + +- phylink = phylink_create(&pf->phylink_config, +- of_fwnode_handle(dev->of_node), ++ phylink = phylink_create(&pf->phylink_config, of_fwnode_handle(node), + pf->if_mode, &enetc_mac_phylink_ops); + if (IS_ERR(phylink)) { + err = PTR_ERR(phylink); +@@ -1086,13 +1084,14 @@ static int enetc_init_port_rss_memory(struct enetc_si *si) + static int enetc_pf_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) + { ++ struct device_node *node = pdev->dev.of_node; + struct enetc_ndev_priv *priv; + struct net_device *ndev; + struct enetc_si *si; + struct enetc_pf *pf; + int err; + +- if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) { ++ if (node && !of_device_is_available(node)) { + dev_info(&pdev->dev, "device is disabled, skipping\n"); + return -ENODEV; + } +@@ -1161,12 +1160,12 @@ static int enetc_pf_probe(struct pci_dev *pdev, + goto err_alloc_msix; + } + +- if (!of_get_phy_mode(pdev->dev.of_node, &pf->if_mode)) { +- err = enetc_mdiobus_create(pf); ++ if (!of_get_phy_mode(node, &pf->if_mode)) { ++ err = enetc_mdiobus_create(pf, node); + if (err) + goto err_mdiobus_create; + +- err = enetc_phylink_create(priv); ++ err = enetc_phylink_create(priv, node); + if (err) + goto err_phylink_create; + } +-- +2.30.1 + diff --git a/queue-5.10/mips-kernel-reserve-exception-base-early-to-prevent-.patch b/queue-5.10/mips-kernel-reserve-exception-base-early-to-prevent-.patch new file mode 100644 index 00000000000..8c9f8e77f3b --- /dev/null +++ b/queue-5.10/mips-kernel-reserve-exception-base-early-to-prevent-.patch @@ -0,0 +1,163 @@ +From 50eae04e8a832e98e0f281eedc80769c52c8475f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Mar 2021 10:24:47 +0100 +Subject: MIPS: kernel: Reserve exception base early to prevent corruption + +From: Thomas Bogendoerfer + +[ Upstream commit bd67b711bfaa02cf19e88aa2d9edae5c1c1d2739 ] + +BMIPS is one of the few platforms that do change the exception base. +After commit 2dcb39645441 ("memblock: do not start bottom-up allocations +with kernel_end") we started seeing BMIPS boards fail to boot with the +built-in FDT being corrupted. + +Before the cited commit, early allocations would be in the [kernel_end, +RAM_END] range, but after commit they would be within [RAM_START + +PAGE_SIZE, RAM_END]. + +The custom exception base handler that is installed by +bmips_ebase_setup() done for BMIPS5000 CPUs ends-up trampling on the +memory region allocated by unflatten_and_copy_device_tree() thus +corrupting the FDT used by the kernel. + +To fix this, we need to perform an early reservation of the custom +exception space. Additional we reserve the first 4k (1k for R3k) for +either normal exception vector space (legacy CPUs) or special vectors +like cache exceptions. + +Huge thanks to Serge for analysing and proposing a solution to this +issue. + +Fixes: 2dcb39645441 ("memblock: do not start bottom-up allocations with kernel_end") +Reported-by: Kamal Dasu +Debugged-by: Serge Semin +Acked-by: Mike Rapoport +Tested-by: Florian Fainelli +Reviewed-by: Serge Semin +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/include/asm/traps.h | 3 +++ + arch/mips/kernel/cpu-probe.c | 6 ++++++ + arch/mips/kernel/cpu-r3k-probe.c | 3 +++ + arch/mips/kernel/traps.c | 10 +++++----- + 4 files changed, 17 insertions(+), 5 deletions(-) + +diff --git a/arch/mips/include/asm/traps.h b/arch/mips/include/asm/traps.h +index 6a0864bb604d..9038b91e2d8c 100644 +--- a/arch/mips/include/asm/traps.h ++++ b/arch/mips/include/asm/traps.h +@@ -24,6 +24,9 @@ extern void (*board_ebase_setup)(void); + extern void (*board_cache_error_setup)(void); + + extern int register_nmi_notifier(struct notifier_block *nb); ++extern void reserve_exception_space(phys_addr_t addr, unsigned long size); ++ ++#define VECTORSPACING 0x100 /* for EI/VI mode */ + + #define nmi_notifier(fn, pri) \ + ({ \ +diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c +index 31cb9199197c..21794db53c05 100644 +--- a/arch/mips/kernel/cpu-probe.c ++++ b/arch/mips/kernel/cpu-probe.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + + #include "fpu-probe.h" +@@ -1619,6 +1620,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) + c->cputype = CPU_BMIPS3300; + __cpu_name[cpu] = "Broadcom BMIPS3300"; + set_elf_platform(cpu, "bmips3300"); ++ reserve_exception_space(0x400, VECTORSPACING * 64); + break; + case PRID_IMP_BMIPS43XX: { + int rev = c->processor_id & PRID_REV_MASK; +@@ -1629,6 +1631,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) + __cpu_name[cpu] = "Broadcom BMIPS4380"; + set_elf_platform(cpu, "bmips4380"); + c->options |= MIPS_CPU_RIXI; ++ reserve_exception_space(0x400, VECTORSPACING * 64); + } else { + c->cputype = CPU_BMIPS4350; + __cpu_name[cpu] = "Broadcom BMIPS4350"; +@@ -1645,6 +1648,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) + __cpu_name[cpu] = "Broadcom BMIPS5000"; + set_elf_platform(cpu, "bmips5000"); + c->options |= MIPS_CPU_ULRI | MIPS_CPU_RIXI; ++ reserve_exception_space(0x1000, VECTORSPACING * 64); + break; + } + } +@@ -2124,6 +2128,8 @@ void cpu_probe(void) + if (cpu == 0) + __ua_limit = ~((1ull << cpu_vmbits) - 1); + #endif ++ ++ reserve_exception_space(0, 0x1000); + } + + void cpu_report(void) +diff --git a/arch/mips/kernel/cpu-r3k-probe.c b/arch/mips/kernel/cpu-r3k-probe.c +index abdbbe8c5a43..af654771918c 100644 +--- a/arch/mips/kernel/cpu-r3k-probe.c ++++ b/arch/mips/kernel/cpu-r3k-probe.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #include "fpu-probe.h" + +@@ -158,6 +159,8 @@ void cpu_probe(void) + cpu_set_fpu_opts(c); + else + cpu_set_nofpu_opts(c); ++ ++ reserve_exception_space(0, 0x400); + } + + void cpu_report(void) +diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c +index e0352958e2f7..808b8b61ded1 100644 +--- a/arch/mips/kernel/traps.c ++++ b/arch/mips/kernel/traps.c +@@ -2009,13 +2009,16 @@ void __noreturn nmi_exception_handler(struct pt_regs *regs) + nmi_exit(); + } + +-#define VECTORSPACING 0x100 /* for EI/VI mode */ +- + unsigned long ebase; + EXPORT_SYMBOL_GPL(ebase); + unsigned long exception_handlers[32]; + unsigned long vi_handlers[64]; + ++void reserve_exception_space(phys_addr_t addr, unsigned long size) ++{ ++ memblock_reserve(addr, size); ++} ++ + void __init *set_except_vector(int n, void *addr) + { + unsigned long handler = (unsigned long) addr; +@@ -2367,10 +2370,7 @@ void __init trap_init(void) + + if (!cpu_has_mips_r2_r6) { + ebase = CAC_BASE; +- ebase_pa = virt_to_phys((void *)ebase); + vec_size = 0x400; +- +- memblock_reserve(ebase_pa, vec_size); + } else { + if (cpu_has_veic || cpu_has_vint) + vec_size = 0x200 + VECTORSPACING*64; +-- +2.30.1 + diff --git a/queue-5.10/net-dsa-implement-a-central-tx-reallocation-procedur.patch b/queue-5.10/net-dsa-implement-a-central-tx-reallocation-procedur.patch new file mode 100644 index 00000000000..15c0ba3759b --- /dev/null +++ b/queue-5.10/net-dsa-implement-a-central-tx-reallocation-procedur.patch @@ -0,0 +1,114 @@ +From 7f0929f5432f121f49716d56319a9cc7465269ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Nov 2020 21:16:09 +0200 +Subject: net: dsa: implement a central TX reallocation procedure + +From: Vladimir Oltean + +[ Upstream commit a3b0b6479700a5b0af2c631cb2ec0fb7a0d978f2 ] + +At the moment, taggers are left with the task of ensuring that the skb +headers are writable (which they aren't, if the frames were cloned for +TX timestamping, for flooding by the bridge, etc), and that there is +enough space in the skb data area for the DSA tag to be pushed. + +Moreover, the life of tail taggers is even harder, because they need to +ensure that short frames have enough padding, a problem that normal +taggers don't have. + +The principle of the DSA framework is that everything except for the +most intimate hardware specifics (like in this case, the actual packing +of the DSA tag bits) should be done inside the core, to avoid having +code paths that are very rarely tested. + +So provide a TX reallocation procedure that should cover the known needs +of DSA today. + +Note that this patch also gives the network stack a good hint about the +headroom/tailroom it's going to need. Up till now it wasn't doing that. +So the reallocation procedure should really be there only for the +exceptional cases, and for cloned packets which need to be unshared. + +Signed-off-by: Vladimir Oltean +Tested-by: Christian Eggers # For tail taggers only +Tested-by: Kurt Kanzenbach +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/slave.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + +diff --git a/net/dsa/slave.c b/net/dsa/slave.c +index 3bc5ca40c9fb..c6806eef906f 100644 +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -548,6 +548,30 @@ netdev_tx_t dsa_enqueue_skb(struct sk_buff *skb, struct net_device *dev) + } + EXPORT_SYMBOL_GPL(dsa_enqueue_skb); + ++static int dsa_realloc_skb(struct sk_buff *skb, struct net_device *dev) ++{ ++ int needed_headroom = dev->needed_headroom; ++ int needed_tailroom = dev->needed_tailroom; ++ ++ /* For tail taggers, we need to pad short frames ourselves, to ensure ++ * that the tail tag does not fail at its role of being at the end of ++ * the packet, once the master interface pads the frame. Account for ++ * that pad length here, and pad later. ++ */ ++ if (unlikely(needed_tailroom && skb->len < ETH_ZLEN)) ++ needed_tailroom += ETH_ZLEN - skb->len; ++ /* skb_headroom() returns unsigned int... */ ++ needed_headroom = max_t(int, needed_headroom - skb_headroom(skb), 0); ++ needed_tailroom = max_t(int, needed_tailroom - skb_tailroom(skb), 0); ++ ++ if (likely(!needed_headroom && !needed_tailroom && !skb_cloned(skb))) ++ /* No reallocation needed, yay! */ ++ return 0; ++ ++ return pskb_expand_head(skb, needed_headroom, needed_tailroom, ++ GFP_ATOMIC); ++} ++ + static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct dsa_slave_priv *p = netdev_priv(dev); +@@ -567,6 +591,17 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev) + */ + dsa_skb_tx_timestamp(p, skb); + ++ if (dsa_realloc_skb(skb, dev)) { ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } ++ ++ /* needed_tailroom should still be 'warm' in the cache line from ++ * dsa_realloc_skb(), which has also ensured that padding is safe. ++ */ ++ if (dev->needed_tailroom) ++ eth_skb_pad(skb); ++ + /* Transmit function may have to reallocate the original SKB, + * in which case it must have freed it. Only free it here on error. + */ +@@ -1791,6 +1826,16 @@ int dsa_slave_create(struct dsa_port *port) + slave_dev->netdev_ops = &dsa_slave_netdev_ops; + if (ds->ops->port_max_mtu) + slave_dev->max_mtu = ds->ops->port_max_mtu(ds, port->index); ++ if (cpu_dp->tag_ops->tail_tag) ++ slave_dev->needed_tailroom = cpu_dp->tag_ops->overhead; ++ else ++ slave_dev->needed_headroom = cpu_dp->tag_ops->overhead; ++ /* Try to save one extra realloc later in the TX path (in the master) ++ * by also inheriting the master's needed headroom and tailroom. ++ * The 8021q driver also does this. ++ */ ++ slave_dev->needed_headroom += master->needed_headroom; ++ slave_dev->needed_tailroom += master->needed_tailroom; + SET_NETDEV_DEVTYPE(slave_dev, &dsa_type); + + netdev_for_each_tx_queue(slave_dev, dsa_slave_set_lockdep_class_one, +-- +2.30.1 + diff --git a/queue-5.10/net-dsa-tag_ar9331-let-dsa-core-deal-with-tx-realloc.patch b/queue-5.10/net-dsa-tag_ar9331-let-dsa-core-deal-with-tx-realloc.patch new file mode 100644 index 00000000000..28f6ab87d12 --- /dev/null +++ b/queue-5.10/net-dsa-tag_ar9331-let-dsa-core-deal-with-tx-realloc.patch @@ -0,0 +1,41 @@ +From 1cf4673ba62477fd972a8369f7b126c735916840 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Nov 2020 21:16:20 +0200 +Subject: net: dsa: tag_ar9331: let DSA core deal with TX reallocation + +From: Vladimir Oltean + +[ Upstream commit 86c4ad9a7876777c12fd5a7010152e4141fcb94d ] + +Now that we have a central TX reallocation procedure that accounts for +the tagger's needed headroom in a generic way, we can remove the +skb_cow_head call. + +Cc: Per Forlin +Cc: Oleksij Rempel +Signed-off-by: Vladimir Oltean +Tested-by: Oleksij Rempel +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/tag_ar9331.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/net/dsa/tag_ar9331.c b/net/dsa/tag_ar9331.c +index 55b00694cdba..002cf7f952e2 100644 +--- a/net/dsa/tag_ar9331.c ++++ b/net/dsa/tag_ar9331.c +@@ -31,9 +31,6 @@ static struct sk_buff *ar9331_tag_xmit(struct sk_buff *skb, + __le16 *phdr; + u16 hdr; + +- if (skb_cow_head(skb, AR9331_HDR_LEN) < 0) +- return NULL; +- + phdr = skb_push(skb, AR9331_HDR_LEN); + + hdr = FIELD_PREP(AR9331_HDR_VERSION_MASK, AR9331_HDR_VERSION); +-- +2.30.1 + diff --git a/queue-5.10/net-dsa-tag_brcm-let-dsa-core-deal-with-tx-reallocat.patch b/queue-5.10/net-dsa-tag_brcm-let-dsa-core-deal-with-tx-reallocat.patch new file mode 100644 index 00000000000..cb4d19c791a --- /dev/null +++ b/queue-5.10/net-dsa-tag_brcm-let-dsa-core-deal-with-tx-reallocat.patch @@ -0,0 +1,39 @@ +From d48532018497a8df115f2537952b25cb6a8defd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Nov 2020 21:16:17 +0200 +Subject: net: dsa: tag_brcm: let DSA core deal with TX reallocation + +From: Vladimir Oltean + +[ Upstream commit 2f0d030c5ffec6660f79a32b4f522155f75a9d71 ] + +Now that we have a central TX reallocation procedure that accounts for +the tagger's needed headroom in a generic way, we can remove the +skb_cow_head call. + +Cc: Florian Fainelli +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/tag_brcm.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c +index ad72dff8d524..e934dace3922 100644 +--- a/net/dsa/tag_brcm.c ++++ b/net/dsa/tag_brcm.c +@@ -66,9 +66,6 @@ static struct sk_buff *brcm_tag_xmit_ll(struct sk_buff *skb, + u16 queue = skb_get_queue_mapping(skb); + u8 *brcm_tag; + +- if (skb_cow_head(skb, BRCM_TAG_LEN) < 0) +- return NULL; +- + /* The Ethernet switch we are interfaced with needs packets to be at + * least 64 bytes (including FCS) otherwise they will be discarded when + * they enter the switch port logic. When Broadcom tags are enabled, we +-- +2.30.1 + diff --git a/queue-5.10/net-dsa-tag_dsa-let-dsa-core-deal-with-tx-reallocati.patch b/queue-5.10/net-dsa-tag_dsa-let-dsa-core-deal-with-tx-reallocati.patch new file mode 100644 index 00000000000..543755d99d5 --- /dev/null +++ b/queue-5.10/net-dsa-tag_dsa-let-dsa-core-deal-with-tx-reallocati.patch @@ -0,0 +1,53 @@ +From 3559a2edd20071b42af22d3cda506372e4bfa7c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Nov 2020 21:16:18 +0200 +Subject: net: dsa: tag_dsa: let DSA core deal with TX reallocation + +From: Vladimir Oltean + +[ Upstream commit 952a06345015867e3bd37f8d9045fc1429637d43 ] + +Now that we have a central TX reallocation procedure that accounts for +the tagger's needed headroom in a generic way, we can remove the +skb_cow_head call. + +Similar to the EtherType DSA tagger, the old Marvell tagger can +transform an 802.1Q header if present into a DSA tag, so there is no +headroom required in that case. But we are ensuring that it exists, +regardless (practically speaking, the headroom must be 4 bytes larger +than it needs to be). + +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/tag_dsa.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c +index 0b756fae68a5..63d690a0fca6 100644 +--- a/net/dsa/tag_dsa.c ++++ b/net/dsa/tag_dsa.c +@@ -23,9 +23,6 @@ static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev) + * the ethertype field for untagged packets. + */ + if (skb->protocol == htons(ETH_P_8021Q)) { +- if (skb_cow_head(skb, 0) < 0) +- return NULL; +- + /* + * Construct tagged FROM_CPU DSA tag from 802.1q tag. + */ +@@ -41,8 +38,6 @@ static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev) + dsa_header[2] &= ~0x10; + } + } else { +- if (skb_cow_head(skb, DSA_HLEN) < 0) +- return NULL; + skb_push(skb, DSA_HLEN); + + memmove(skb->data, skb->data + DSA_HLEN, 2 * ETH_ALEN); +-- +2.30.1 + diff --git a/queue-5.10/net-dsa-tag_edsa-let-dsa-core-deal-with-tx-reallocat.patch b/queue-5.10/net-dsa-tag_edsa-let-dsa-core-deal-with-tx-reallocat.patch new file mode 100644 index 00000000000..e5dadaa20be --- /dev/null +++ b/queue-5.10/net-dsa-tag_edsa-let-dsa-core-deal-with-tx-reallocat.patch @@ -0,0 +1,52 @@ +From d4c3878b0c48f4aa059c239b02198848bf3faa7b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Nov 2020 21:16:16 +0200 +Subject: net: dsa: tag_edsa: let DSA core deal with TX reallocation + +From: Vladimir Oltean + +[ Upstream commit c6c4e1237dfe731644e79fa06d073625f28cd945 ] + +Now that we have a central TX reallocation procedure that accounts for +the tagger's needed headroom in a generic way, we can remove the +skb_cow_head call. + +Note that the VLAN code path needs a smaller extra headroom than the +regular EtherType DSA path. That isn't a problem, because this tagger +declares the larger tag length (8 bytes vs 4) as the protocol overhead, +so we are covered in both cases. + +Cc: Andrew Lunn +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/tag_edsa.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c +index 120614240319..abf70a29deb4 100644 +--- a/net/dsa/tag_edsa.c ++++ b/net/dsa/tag_edsa.c +@@ -35,8 +35,6 @@ static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev) + * current ethertype field if the packet is untagged. + */ + if (skb->protocol == htons(ETH_P_8021Q)) { +- if (skb_cow_head(skb, DSA_HLEN) < 0) +- return NULL; + skb_push(skb, DSA_HLEN); + + memmove(skb->data, skb->data + DSA_HLEN, 2 * ETH_ALEN); +@@ -60,8 +58,6 @@ static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev) + edsa_header[6] &= ~0x10; + } + } else { +- if (skb_cow_head(skb, EDSA_HLEN) < 0) +- return NULL; + skb_push(skb, EDSA_HLEN); + + memmove(skb->data, skb->data + EDSA_HLEN, 2 * ETH_ALEN); +-- +2.30.1 + diff --git a/queue-5.10/net-dsa-tag_gswip-let-dsa-core-deal-with-tx-realloca.patch b/queue-5.10/net-dsa-tag_gswip-let-dsa-core-deal-with-tx-realloca.patch new file mode 100644 index 00000000000..5598382e0d9 --- /dev/null +++ b/queue-5.10/net-dsa-tag_gswip-let-dsa-core-deal-with-tx-realloca.patch @@ -0,0 +1,50 @@ +From f5e9219ce4606a568cf76d4650aed661d642288a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Nov 2020 21:16:19 +0200 +Subject: net: dsa: tag_gswip: let DSA core deal with TX reallocation + +From: Vladimir Oltean + +[ Upstream commit 9b9826ae117f211bcbdc75db844d5fd8b159fc59 ] + +Now that we have a central TX reallocation procedure that accounts for +the tagger's needed headroom in a generic way, we can remove the +skb_cow_head call. + +This one is interesting, the DSA tag is 8 bytes on RX and 4 bytes on TX. +Because DSA is unaware of asymmetrical tag lengths, the overhead/needed +headroom is declared as 8 bytes and therefore 4 bytes larger than it +needs to be. If this becomes a problem, and the GSWIP driver can't be +converted to a uniform header length, we might need to make DSA aware of +separate RX/TX overhead values. + +Cc: Hauke Mehrtens +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/tag_gswip.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/net/dsa/tag_gswip.c b/net/dsa/tag_gswip.c +index 408d4af390a0..2f5bd5e338ab 100644 +--- a/net/dsa/tag_gswip.c ++++ b/net/dsa/tag_gswip.c +@@ -60,13 +60,8 @@ static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb, + struct net_device *dev) + { + struct dsa_port *dp = dsa_slave_to_port(dev); +- int err; + u8 *gswip_tag; + +- err = skb_cow_head(skb, GSWIP_TX_HEADER_LEN); +- if (err) +- return NULL; +- + skb_push(skb, GSWIP_TX_HEADER_LEN); + + gswip_tag = skb->data; +-- +2.30.1 + diff --git a/queue-5.10/net-dsa-tag_ksz-don-t-allocate-additional-memory-for.patch b/queue-5.10/net-dsa-tag_ksz-don-t-allocate-additional-memory-for.patch new file mode 100644 index 00000000000..fcdab095f4e --- /dev/null +++ b/queue-5.10/net-dsa-tag_ksz-don-t-allocate-additional-memory-for.patch @@ -0,0 +1,161 @@ +From d67d109966037a86ca61265d35db182148b43165 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Nov 2020 21:16:10 +0200 +Subject: net: dsa: tag_ksz: don't allocate additional memory for + padding/tagging + +From: Christian Eggers + +[ Upstream commit 88fda8eefd9a7a7175bf4dad1d02cc0840581111 ] + +The caller (dsa_slave_xmit) guarantees that the frame length is at least +ETH_ZLEN and that enough memory for tail tagging is available. + +Signed-off-by: Christian Eggers +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/tag_ksz.c | 73 ++++++----------------------------------------- + 1 file changed, 9 insertions(+), 64 deletions(-) + +diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c +index 0a5aa982c60d..4820dbcedfa2 100644 +--- a/net/dsa/tag_ksz.c ++++ b/net/dsa/tag_ksz.c +@@ -14,46 +14,6 @@ + #define KSZ_EGRESS_TAG_LEN 1 + #define KSZ_INGRESS_TAG_LEN 1 + +-static struct sk_buff *ksz_common_xmit(struct sk_buff *skb, +- struct net_device *dev, int len) +-{ +- struct sk_buff *nskb; +- int padlen; +- +- padlen = (skb->len >= ETH_ZLEN) ? 0 : ETH_ZLEN - skb->len; +- +- if (skb_tailroom(skb) >= padlen + len) { +- /* Let dsa_slave_xmit() free skb */ +- if (__skb_put_padto(skb, skb->len + padlen, false)) +- return NULL; +- +- nskb = skb; +- } else { +- nskb = alloc_skb(NET_IP_ALIGN + skb->len + +- padlen + len, GFP_ATOMIC); +- if (!nskb) +- return NULL; +- skb_reserve(nskb, NET_IP_ALIGN); +- +- skb_reset_mac_header(nskb); +- skb_set_network_header(nskb, +- skb_network_header(skb) - skb->head); +- skb_set_transport_header(nskb, +- skb_transport_header(skb) - skb->head); +- skb_copy_and_csum_dev(skb, skb_put(nskb, skb->len)); +- +- /* Let skb_put_padto() free nskb, and let dsa_slave_xmit() free +- * skb +- */ +- if (skb_put_padto(nskb, nskb->len + padlen)) +- return NULL; +- +- consume_skb(skb); +- } +- +- return nskb; +-} +- + static struct sk_buff *ksz_common_rcv(struct sk_buff *skb, + struct net_device *dev, + unsigned int port, unsigned int len) +@@ -90,23 +50,18 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb, + static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct dsa_port *dp = dsa_slave_to_port(dev); +- struct sk_buff *nskb; + u8 *tag; + u8 *addr; + +- nskb = ksz_common_xmit(skb, dev, KSZ_INGRESS_TAG_LEN); +- if (!nskb) +- return NULL; +- + /* Tag encoding */ +- tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN); +- addr = skb_mac_header(nskb); ++ tag = skb_put(skb, KSZ_INGRESS_TAG_LEN); ++ addr = skb_mac_header(skb); + + *tag = 1 << dp->index; + if (is_link_local_ether_addr(addr)) + *tag |= KSZ8795_TAIL_TAG_OVERRIDE; + +- return nskb; ++ return skb; + } + + static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev, +@@ -156,18 +111,13 @@ static struct sk_buff *ksz9477_xmit(struct sk_buff *skb, + struct net_device *dev) + { + struct dsa_port *dp = dsa_slave_to_port(dev); +- struct sk_buff *nskb; + __be16 *tag; + u8 *addr; + u16 val; + +- nskb = ksz_common_xmit(skb, dev, KSZ9477_INGRESS_TAG_LEN); +- if (!nskb) +- return NULL; +- + /* Tag encoding */ +- tag = skb_put(nskb, KSZ9477_INGRESS_TAG_LEN); +- addr = skb_mac_header(nskb); ++ tag = skb_put(skb, KSZ9477_INGRESS_TAG_LEN); ++ addr = skb_mac_header(skb); + + val = BIT(dp->index); + +@@ -176,7 +126,7 @@ static struct sk_buff *ksz9477_xmit(struct sk_buff *skb, + + *tag = cpu_to_be16(val); + +- return nskb; ++ return skb; + } + + static struct sk_buff *ksz9477_rcv(struct sk_buff *skb, struct net_device *dev, +@@ -213,24 +163,19 @@ static struct sk_buff *ksz9893_xmit(struct sk_buff *skb, + struct net_device *dev) + { + struct dsa_port *dp = dsa_slave_to_port(dev); +- struct sk_buff *nskb; + u8 *addr; + u8 *tag; + +- nskb = ksz_common_xmit(skb, dev, KSZ_INGRESS_TAG_LEN); +- if (!nskb) +- return NULL; +- + /* Tag encoding */ +- tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN); +- addr = skb_mac_header(nskb); ++ tag = skb_put(skb, KSZ_INGRESS_TAG_LEN); ++ addr = skb_mac_header(skb); + + *tag = BIT(dp->index); + + if (is_link_local_ether_addr(addr)) + *tag |= KSZ9893_TAIL_TAG_OVERRIDE; + +- return nskb; ++ return skb; + } + + static const struct dsa_device_ops ksz9893_netdev_ops = { +-- +2.30.1 + diff --git a/queue-5.10/net-dsa-tag_lan9303-let-dsa-core-deal-with-tx-reallo.patch b/queue-5.10/net-dsa-tag_lan9303-let-dsa-core-deal-with-tx-reallo.patch new file mode 100644 index 00000000000..6b2e8996237 --- /dev/null +++ b/queue-5.10/net-dsa-tag_lan9303-let-dsa-core-deal-with-tx-reallo.patch @@ -0,0 +1,44 @@ +From 144ccb61f5c40c1854bb165a16a2d2b3fa47abe8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Nov 2020 21:16:15 +0200 +Subject: net: dsa: tag_lan9303: let DSA core deal with TX reallocation + +From: Vladimir Oltean + +[ Upstream commit 6ed94135f58372cdec34cafb60f7596893b0b371 ] + +Now that we have a central TX reallocation procedure that accounts for +the tagger's needed headroom in a generic way, we can remove the +skb_cow_head call. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/tag_lan9303.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/net/dsa/tag_lan9303.c b/net/dsa/tag_lan9303.c +index ccfb6f641bbf..aa1318dccaf0 100644 +--- a/net/dsa/tag_lan9303.c ++++ b/net/dsa/tag_lan9303.c +@@ -58,15 +58,6 @@ static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev) + __be16 *lan9303_tag; + u16 tag; + +- /* insert a special VLAN tag between the MAC addresses +- * and the current ethertype field. +- */ +- if (skb_cow_head(skb, LAN9303_TAG_LEN) < 0) { +- dev_dbg(&dev->dev, +- "Cannot make room for the special tag. Dropping packet\n"); +- return NULL; +- } +- + /* provide 'LAN9303_TAG_LEN' bytes additional space */ + skb_push(skb, LAN9303_TAG_LEN); + +-- +2.30.1 + diff --git a/queue-5.10/net-dsa-tag_mtk-fix-802.1ad-vlan-egress.patch b/queue-5.10/net-dsa-tag_mtk-fix-802.1ad-vlan-egress.patch new file mode 100644 index 00000000000..210e95cef47 --- /dev/null +++ b/queue-5.10/net-dsa-tag_mtk-fix-802.1ad-vlan-egress.patch @@ -0,0 +1,84 @@ +From 431ef53c835c33faa35fb2792fa5d549b986bb58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Mar 2021 00:01:59 +0800 +Subject: net: dsa: tag_mtk: fix 802.1ad VLAN egress + +From: DENG Qingfang + +[ Upstream commit 9200f515c41f4cbaeffd8fdd1d8b6373a18b1b67 ] + +A different TPID bit is used for 802.1ad VLAN frames. + +Reported-by: Ilario Gelmetti +Fixes: f0af34317f4b ("net: dsa: mediatek: combine MediaTek tag with VLAN tag") +Signed-off-by: DENG Qingfang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/dsa/tag_mtk.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c +index 38dcdded74c0..59748487664f 100644 +--- a/net/dsa/tag_mtk.c ++++ b/net/dsa/tag_mtk.c +@@ -13,6 +13,7 @@ + #define MTK_HDR_LEN 4 + #define MTK_HDR_XMIT_UNTAGGED 0 + #define MTK_HDR_XMIT_TAGGED_TPID_8100 1 ++#define MTK_HDR_XMIT_TAGGED_TPID_88A8 2 + #define MTK_HDR_RECV_SOURCE_PORT_MASK GENMASK(2, 0) + #define MTK_HDR_XMIT_DP_BIT_MASK GENMASK(5, 0) + #define MTK_HDR_XMIT_SA_DIS BIT(6) +@@ -21,8 +22,8 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb, + struct net_device *dev) + { + struct dsa_port *dp = dsa_slave_to_port(dev); ++ u8 xmit_tpid; + u8 *mtk_tag; +- bool is_vlan_skb = true; + unsigned char *dest = eth_hdr(skb)->h_dest; + bool is_multicast_skb = is_multicast_ether_addr(dest) && + !is_broadcast_ether_addr(dest); +@@ -33,10 +34,17 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb, + * the both special and VLAN tag at the same time and then look up VLAN + * table with VID. + */ +- if (!skb_vlan_tagged(skb)) { ++ switch (skb->protocol) { ++ case htons(ETH_P_8021Q): ++ xmit_tpid = MTK_HDR_XMIT_TAGGED_TPID_8100; ++ break; ++ case htons(ETH_P_8021AD): ++ xmit_tpid = MTK_HDR_XMIT_TAGGED_TPID_88A8; ++ break; ++ default: ++ xmit_tpid = MTK_HDR_XMIT_UNTAGGED; + skb_push(skb, MTK_HDR_LEN); + memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN); +- is_vlan_skb = false; + } + + mtk_tag = skb->data + 2 * ETH_ALEN; +@@ -44,8 +52,7 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb, + /* Mark tag attribute on special tag insertion to notify hardware + * whether that's a combined special tag with 802.1Q header. + */ +- mtk_tag[0] = is_vlan_skb ? MTK_HDR_XMIT_TAGGED_TPID_8100 : +- MTK_HDR_XMIT_UNTAGGED; ++ mtk_tag[0] = xmit_tpid; + mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK; + + /* Disable SA learning for multicast frames */ +@@ -53,7 +60,7 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb, + mtk_tag[1] |= MTK_HDR_XMIT_SA_DIS; + + /* Tag control information is kept for 802.1Q */ +- if (!is_vlan_skb) { ++ if (xmit_tpid == MTK_HDR_XMIT_UNTAGGED) { + mtk_tag[2] = 0; + mtk_tag[3] = 0; + } +-- +2.30.1 + diff --git a/queue-5.10/net-dsa-tag_mtk-let-dsa-core-deal-with-tx-reallocati.patch b/queue-5.10/net-dsa-tag_mtk-let-dsa-core-deal-with-tx-reallocati.patch new file mode 100644 index 00000000000..21172c2c46c --- /dev/null +++ b/queue-5.10/net-dsa-tag_mtk-let-dsa-core-deal-with-tx-reallocati.patch @@ -0,0 +1,41 @@ +From ea0f236c1714f4d948851c74cc13bf211359efe2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Nov 2020 21:16:14 +0200 +Subject: net: dsa: tag_mtk: let DSA core deal with TX reallocation + +From: Vladimir Oltean + +[ Upstream commit 941f66beb7bb4e0e4726aa31336d9ccc1c3a3dc2 ] + +Now that we have a central TX reallocation procedure that accounts for +the tagger's needed headroom in a generic way, we can remove the +skb_cow_head call. + +Cc: DENG Qingfang +Cc: Sean Wang +Cc: John Crispin +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/tag_mtk.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c +index 4cdd9cf428fb..38dcdded74c0 100644 +--- a/net/dsa/tag_mtk.c ++++ b/net/dsa/tag_mtk.c +@@ -34,9 +34,6 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb, + * table with VID. + */ + if (!skb_vlan_tagged(skb)) { +- if (skb_cow_head(skb, MTK_HDR_LEN) < 0) +- return NULL; +- + skb_push(skb, MTK_HDR_LEN); + memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN); + is_vlan_skb = false; +-- +2.30.1 + diff --git a/queue-5.10/net-dsa-tag_ocelot-let-dsa-core-deal-with-tx-realloc.patch b/queue-5.10/net-dsa-tag_ocelot-let-dsa-core-deal-with-tx-realloc.patch new file mode 100644 index 00000000000..c45329ed4cc --- /dev/null +++ b/queue-5.10/net-dsa-tag_ocelot-let-dsa-core-deal-with-tx-realloc.patch @@ -0,0 +1,42 @@ +From 2407ba787b21c6f9d4e1a2de75d10acab9bd8f27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Nov 2020 21:16:13 +0200 +Subject: net: dsa: tag_ocelot: let DSA core deal with TX reallocation + +From: Vladimir Oltean + +[ Upstream commit 9c5c3bd00557e57c1049f7861f11e5e39f0fb42d ] + +Now that we have a central TX reallocation procedure that accounts for +the tagger's needed headroom in a generic way, we can remove the +skb_cow_head call. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/tag_ocelot.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/net/dsa/tag_ocelot.c b/net/dsa/tag_ocelot.c +index 3b468aca5c53..16a1afd5b8e1 100644 +--- a/net/dsa/tag_ocelot.c ++++ b/net/dsa/tag_ocelot.c +@@ -143,13 +143,6 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb, + struct ocelot_port *ocelot_port; + u8 *prefix, *injection; + u64 qos_class, rew_op; +- int err; +- +- err = skb_cow_head(skb, OCELOT_TOTAL_TAG_LEN); +- if (unlikely(err < 0)) { +- netdev_err(netdev, "Cannot make room for tag.\n"); +- return NULL; +- } + + ocelot_port = ocelot->ports[dp->index]; + +-- +2.30.1 + diff --git a/queue-5.10/net-dsa-tag_qca-let-dsa-core-deal-with-tx-reallocati.patch b/queue-5.10/net-dsa-tag_qca-let-dsa-core-deal-with-tx-reallocati.patch new file mode 100644 index 00000000000..ef371395d98 --- /dev/null +++ b/queue-5.10/net-dsa-tag_qca-let-dsa-core-deal-with-tx-reallocati.patch @@ -0,0 +1,40 @@ +From 711716fcbb18a3f427fc231d0fc983343d289714 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Nov 2020 21:16:12 +0200 +Subject: net: dsa: tag_qca: let DSA core deal with TX reallocation + +From: Vladimir Oltean + +[ Upstream commit 9bbda29ae1044bc4c1c01a5b7c44688c4765785f ] + +Now that we have a central TX reallocation procedure that accounts for +the tagger's needed headroom in a generic way, we can remove the +skb_cow_head call. + +Cc: John Crispin +Cc: Alexander Lobakin +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/tag_qca.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/net/dsa/tag_qca.c b/net/dsa/tag_qca.c +index 1b9e8507112b..88181b52f480 100644 +--- a/net/dsa/tag_qca.c ++++ b/net/dsa/tag_qca.c +@@ -34,9 +34,6 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev) + __be16 *phdr; + u16 hdr; + +- if (skb_cow_head(skb, QCA_HDR_LEN) < 0) +- return NULL; +- + skb_push(skb, QCA_HDR_LEN); + + memmove(skb->data, skb->data + QCA_HDR_LEN, 2 * ETH_ALEN); +-- +2.30.1 + diff --git a/queue-5.10/net-dsa-trailer-don-t-allocate-additional-memory-for.patch b/queue-5.10/net-dsa-trailer-don-t-allocate-additional-memory-for.patch new file mode 100644 index 00000000000..afbbfc51c78 --- /dev/null +++ b/queue-5.10/net-dsa-trailer-don-t-allocate-additional-memory-for.patch @@ -0,0 +1,74 @@ +From 42a1837d79bf5111efe55272f483d29bd6bcabca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Nov 2020 21:16:11 +0200 +Subject: net: dsa: trailer: don't allocate additional memory for + padding/tagging + +From: Christian Eggers + +[ Upstream commit ef3f72fee286bd270453ce2344feb7295a798508 ] + +The caller (dsa_slave_xmit) guarantees that the frame length is at least +ETH_ZLEN and that enough memory for tail tagging is available. + +Signed-off-by: Christian Eggers +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/tag_trailer.c | 31 ++----------------------------- + 1 file changed, 2 insertions(+), 29 deletions(-) + +diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c +index 3a1cc24a4f0a..5b97ede56a0f 100644 +--- a/net/dsa/tag_trailer.c ++++ b/net/dsa/tag_trailer.c +@@ -13,42 +13,15 @@ + static struct sk_buff *trailer_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct dsa_port *dp = dsa_slave_to_port(dev); +- struct sk_buff *nskb; +- int padlen; + u8 *trailer; + +- /* +- * We have to make sure that the trailer ends up as the very +- * last 4 bytes of the packet. This means that we have to pad +- * the packet to the minimum ethernet frame size, if necessary, +- * before adding the trailer. +- */ +- padlen = 0; +- if (skb->len < 60) +- padlen = 60 - skb->len; +- +- nskb = alloc_skb(NET_IP_ALIGN + skb->len + padlen + 4, GFP_ATOMIC); +- if (!nskb) +- return NULL; +- skb_reserve(nskb, NET_IP_ALIGN); +- +- skb_reset_mac_header(nskb); +- skb_set_network_header(nskb, skb_network_header(skb) - skb->head); +- skb_set_transport_header(nskb, skb_transport_header(skb) - skb->head); +- skb_copy_and_csum_dev(skb, skb_put(nskb, skb->len)); +- consume_skb(skb); +- +- if (padlen) { +- skb_put_zero(nskb, padlen); +- } +- +- trailer = skb_put(nskb, 4); ++ trailer = skb_put(skb, 4); + trailer[0] = 0x80; + trailer[1] = 1 << dp->index; + trailer[2] = 0x10; + trailer[3] = 0x00; + +- return nskb; ++ return skb; + } + + static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev, +-- +2.30.1 + diff --git a/queue-5.10/net-enetc-initialize-rfs-rss-memories-for-unused-por.patch b/queue-5.10/net-enetc-initialize-rfs-rss-memories-for-unused-por.patch new file mode 100644 index 00000000000..2b5bec0a291 --- /dev/null +++ b/queue-5.10/net-enetc-initialize-rfs-rss-memories-for-unused-por.patch @@ -0,0 +1,174 @@ +From d2765886e4ca05d12d0de35ce5a45ce1f6ae9736 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Mar 2021 13:18:12 +0200 +Subject: net: enetc: initialize RFS/RSS memories for unused ports too + +From: Vladimir Oltean + +[ Upstream commit 3222b5b613db558e9a494bbf53f3c984d90f71ea ] + +Michael reports that since linux-next-20210211, the AER messages for ECC +errors have started reappearing, and this time they can be reliably +reproduced with the first ping on one of his LS1028A boards. + +$ ping 1[ 33.258069] pcieport 0000:00:1f.0: AER: Multiple Corrected error received: 0000:00:00.0 +72.16.0.1 +PING [ 33.267050] pcieport 0000:00:1f.0: AER: can't find device of ID0000 +172.16.0.1 (172.16.0.1): 56 data bytes +64 bytes from 172.16.0.1: seq=0 ttl=64 time=17.124 ms +64 bytes from 172.16.0.1: seq=1 ttl=64 time=0.273 ms + +$ devmem 0x1f8010e10 32 +0xC0000006 + +It isn't clear why this is necessary, but it seems that for the errors +to go away, we must clear the entire RFS and RSS memory, not just for +the ports in use. + +Sadly the code is structured in such a way that we can't have unified +logic for the used and unused ports. For the minimal initialization of +an unused port, we need just to enable and ioremap the PF memory space, +and a control buffer descriptor ring. Unused ports must then free the +CBDR because the driver will exit, but used ports can not pick up from +where that code path left, since the CBDR API does not reinitialize a +ring when setting it up, so its producer and consumer indices are out of +sync between the software and hardware state. So a separate +enetc_init_unused_port function was created, and it gets called right +after the PF memory space is enabled. + +Fixes: 07bf34a50e32 ("net: enetc: initialize the RFS and RSS memories") +Reported-by: Michael Walle +Cc: Jesse Brandeburg +Signed-off-by: Vladimir Oltean +Tested-by: Michael Walle +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc.c | 8 ++--- + drivers/net/ethernet/freescale/enetc/enetc.h | 4 +++ + .../net/ethernet/freescale/enetc/enetc_pf.c | 33 ++++++++++++++++--- + 3 files changed, 36 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c +index 019a0fa3d9a5..df4a858c8001 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc.c +@@ -1035,7 +1035,7 @@ static void enetc_free_rxtx_rings(struct enetc_ndev_priv *priv) + enetc_free_tx_ring(priv->tx_ring[i]); + } + +-static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr) ++int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr) + { + int size = cbdr->bd_count * sizeof(struct enetc_cbd); + +@@ -1056,7 +1056,7 @@ static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr) + return 0; + } + +-static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr) ++void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr) + { + int size = cbdr->bd_count * sizeof(struct enetc_cbd); + +@@ -1064,7 +1064,7 @@ static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr) + cbdr->bd_base = NULL; + } + +-static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr) ++void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr) + { + /* set CBDR cache attributes */ + enetc_wr(hw, ENETC_SICAR2, +@@ -1084,7 +1084,7 @@ static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr) + cbdr->cir = hw->reg + ENETC_SICBDRCIR; + } + +-static void enetc_clear_cbdr(struct enetc_hw *hw) ++void enetc_clear_cbdr(struct enetc_hw *hw) + { + enetc_wr(hw, ENETC_SICBDRMR, 0); + } +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h +index 6bc23f9b53fa..15d19cbd5a95 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.h ++++ b/drivers/net/ethernet/freescale/enetc/enetc.h +@@ -311,6 +311,10 @@ int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type, + void enetc_set_ethtool_ops(struct net_device *ndev); + + /* control buffer descriptor ring (CBDR) */ ++int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr); ++void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr); ++void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr); ++void enetc_clear_cbdr(struct enetc_hw *hw); + int enetc_set_mac_flt_entry(struct enetc_si *si, int index, + char *mac_addr, int si_map); + int enetc_clear_mac_flt_entry(struct enetc_si *si, int index); +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c +index f29058dddb36..83187cd59fdd 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c +@@ -1081,6 +1081,26 @@ static int enetc_init_port_rss_memory(struct enetc_si *si) + return err; + } + ++static void enetc_init_unused_port(struct enetc_si *si) ++{ ++ struct device *dev = &si->pdev->dev; ++ struct enetc_hw *hw = &si->hw; ++ int err; ++ ++ si->cbd_ring.bd_count = ENETC_CBDR_DEFAULT_SIZE; ++ err = enetc_alloc_cbdr(dev, &si->cbd_ring); ++ if (err) ++ return; ++ ++ enetc_setup_cbdr(hw, &si->cbd_ring); ++ ++ enetc_init_port_rfs_memory(si); ++ enetc_init_port_rss_memory(si); ++ ++ enetc_clear_cbdr(hw); ++ enetc_free_cbdr(dev, &si->cbd_ring); ++} ++ + static int enetc_pf_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) + { +@@ -1091,11 +1111,6 @@ static int enetc_pf_probe(struct pci_dev *pdev, + struct enetc_pf *pf; + int err; + +- if (node && !of_device_is_available(node)) { +- dev_info(&pdev->dev, "device is disabled, skipping\n"); +- return -ENODEV; +- } +- + err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf)); + if (err) { + dev_err(&pdev->dev, "PCI probing failed\n"); +@@ -1109,6 +1124,13 @@ static int enetc_pf_probe(struct pci_dev *pdev, + goto err_map_pf_space; + } + ++ if (node && !of_device_is_available(node)) { ++ enetc_init_unused_port(si); ++ dev_info(&pdev->dev, "device is disabled, skipping\n"); ++ err = -ENODEV; ++ goto err_device_disabled; ++ } ++ + pf = enetc_si_priv(si); + pf->si = si; + pf->total_vfs = pci_sriov_get_totalvfs(pdev); +@@ -1191,6 +1213,7 @@ err_alloc_si_res: + si->ndev = NULL; + free_netdev(ndev); + err_alloc_netdev: ++err_device_disabled: + err_map_pf_space: + enetc_pci_remove(pdev); + +-- +2.30.1 + diff --git a/queue-5.10/net-hns3-fix-error-mask-definition-of-flow-director.patch b/queue-5.10/net-hns3-fix-error-mask-definition-of-flow-director.patch new file mode 100644 index 00000000000..bba492eff05 --- /dev/null +++ b/queue-5.10/net-hns3-fix-error-mask-definition-of-flow-director.patch @@ -0,0 +1,51 @@ +From c8605d62188d979dc64a3be89e479dcdfde25815 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Feb 2021 15:24:51 +0800 +Subject: net: hns3: fix error mask definition of flow director + +From: Jian Shen + +[ Upstream commit ae85ddda0f1b341b2d25f5a5e0eff1d42b6ef3df ] + +Currently, some bit filed definitions of flow director TCAM +configuration command are incorrect. Since the wrong MSB is +always 0, and these fields are assgined in order, so it still works. + +Fix it by redefine them. + +Fixes: 117328680288 ("net: hns3: Add input key and action config support for flow director") +Signed-off-by: Jian Shen +Signed-off-by: Huazhong Tan +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +index 096e26a2e16b..36690fc5c1af 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +@@ -1031,16 +1031,16 @@ struct hclge_fd_tcam_config_3_cmd { + #define HCLGE_FD_AD_DROP_B 0 + #define HCLGE_FD_AD_DIRECT_QID_B 1 + #define HCLGE_FD_AD_QID_S 2 +-#define HCLGE_FD_AD_QID_M GENMASK(12, 2) ++#define HCLGE_FD_AD_QID_M GENMASK(11, 2) + #define HCLGE_FD_AD_USE_COUNTER_B 12 + #define HCLGE_FD_AD_COUNTER_NUM_S 13 + #define HCLGE_FD_AD_COUNTER_NUM_M GENMASK(20, 13) + #define HCLGE_FD_AD_NXT_STEP_B 20 + #define HCLGE_FD_AD_NXT_KEY_S 21 +-#define HCLGE_FD_AD_NXT_KEY_M GENMASK(26, 21) ++#define HCLGE_FD_AD_NXT_KEY_M GENMASK(25, 21) + #define HCLGE_FD_AD_WR_RULE_ID_B 0 + #define HCLGE_FD_AD_RULE_ID_S 1 +-#define HCLGE_FD_AD_RULE_ID_M GENMASK(13, 1) ++#define HCLGE_FD_AD_RULE_ID_M GENMASK(12, 1) + + struct hclge_fd_ad_config_cmd { + u8 stage; +-- +2.30.1 + diff --git a/queue-5.10/s390-qeth-don-t-replace-a-fully-completed-async-tx-b.patch b/queue-5.10/s390-qeth-don-t-replace-a-fully-completed-async-tx-b.patch new file mode 100644 index 00000000000..50ead2d8868 --- /dev/null +++ b/queue-5.10/s390-qeth-don-t-replace-a-fully-completed-async-tx-b.patch @@ -0,0 +1,183 @@ +From db57241ae94eceea3692871b5f238dd09606dea1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Dec 2020 14:12:31 +0100 +Subject: s390/qeth: don't replace a fully completed async TX buffer + +From: Julian Wiedmann + +[ Upstream commit db4ffdcef7c9a842e55228c9faef7abf8b72382f ] + +For TX buffers that require an additional async notification via QAOB, the +TX completion code can now manage all the necessary processing if the +notification has already occurred (or is occurring concurrently). + +In such cases we can avoid replacing the metadata that is associated +with the buffer's slot on the ring, and just keep using the current one. + +As qeth_clear_output_buffer() will also handle any kmem cache-allocated +memory that was mapped into the TX buffer, qeth_qdio_handle_aob() +doesn't need to worry about it. + +While at it, also remove the unneeded forward declaration for +qeth_init_qdio_out_buf(). + +Signed-off-by: Julian Wiedmann +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/s390/net/qeth_core_main.c | 89 ++++++++++++++++++------------- + 1 file changed, 51 insertions(+), 38 deletions(-) + +diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c +index 77cd714978bd..78a866424022 100644 +--- a/drivers/s390/net/qeth_core_main.c ++++ b/drivers/s390/net/qeth_core_main.c +@@ -75,7 +75,6 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue, + enum iucv_tx_notify notification); + static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error, + int budget); +-static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int); + + static void qeth_close_dev_handler(struct work_struct *work) + { +@@ -517,18 +516,6 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, + buffer = (struct qeth_qdio_out_buffer *) aob->user1; + QETH_CARD_TEXT_(card, 5, "%lx", aob->user1); + +- /* Free dangling allocations. The attached skbs are handled by +- * qeth_cleanup_handled_pending(). +- */ +- for (i = 0; +- i < aob->sb_count && i < QETH_MAX_BUFFER_ELEMENTS(card); +- i++) { +- void *data = phys_to_virt(aob->sba[i]); +- +- if (data && buffer->is_header[i]) +- kmem_cache_free(qeth_core_header_cache, data); +- } +- + if (aob->aorc) { + QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc); + new_state = QETH_QDIO_BUF_QAOB_ERROR; +@@ -536,10 +523,9 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, + + switch (atomic_xchg(&buffer->state, new_state)) { + case QETH_QDIO_BUF_PRIMED: +- /* Faster than TX completion code. */ +- notification = qeth_compute_cq_notification(aob->aorc, 0); +- qeth_notify_skbs(buffer->q, buffer, notification); +- atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED); ++ /* Faster than TX completion code, let it handle the async ++ * completion for us. ++ */ + break; + case QETH_QDIO_BUF_PENDING: + /* TX completion code is active and will handle the async +@@ -550,6 +536,19 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, + /* TX completion code is already finished. */ + notification = qeth_compute_cq_notification(aob->aorc, 1); + qeth_notify_skbs(buffer->q, buffer, notification); ++ ++ /* Free dangling allocations. The attached skbs are handled by ++ * qeth_cleanup_handled_pending(). ++ */ ++ for (i = 0; ++ i < aob->sb_count && i < QETH_MAX_BUFFER_ELEMENTS(card); ++ i++) { ++ void *data = phys_to_virt(aob->sba[i]); ++ ++ if (data && buffer->is_header[i]) ++ kmem_cache_free(qeth_core_header_cache, data); ++ } ++ + atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED); + break; + default: +@@ -5870,9 +5869,13 @@ static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue, + QDIO_OUTBUF_STATE_FLAG_PENDING)) { + WARN_ON_ONCE(card->options.cq != QETH_CQ_ENABLED); + +- if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED, +- QETH_QDIO_BUF_PENDING) == +- QETH_QDIO_BUF_PRIMED) { ++ QETH_CARD_TEXT_(card, 5, "pel%u", bidx); ++ ++ switch (atomic_cmpxchg(&buffer->state, ++ QETH_QDIO_BUF_PRIMED, ++ QETH_QDIO_BUF_PENDING)) { ++ case QETH_QDIO_BUF_PRIMED: ++ /* We have initial ownership, no QAOB (yet): */ + qeth_notify_skbs(queue, buffer, TX_NOTIFY_PENDING); + + /* Handle race with qeth_qdio_handle_aob(): */ +@@ -5880,39 +5883,49 @@ static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue, + QETH_QDIO_BUF_NEED_QAOB)) { + case QETH_QDIO_BUF_PENDING: + /* No concurrent QAOB notification. */ +- break; ++ ++ /* Prepare the queue slot for immediate re-use: */ ++ qeth_scrub_qdio_buffer(buffer->buffer, queue->max_elements); ++ if (qeth_init_qdio_out_buf(queue, bidx)) { ++ QETH_CARD_TEXT(card, 2, "outofbuf"); ++ qeth_schedule_recovery(card); ++ } ++ ++ /* Skip clearing the buffer: */ ++ return; + case QETH_QDIO_BUF_QAOB_OK: + qeth_notify_skbs(queue, buffer, + TX_NOTIFY_DELAYED_OK); +- atomic_set(&buffer->state, +- QETH_QDIO_BUF_HANDLED_DELAYED); ++ error = false; + break; + case QETH_QDIO_BUF_QAOB_ERROR: + qeth_notify_skbs(queue, buffer, + TX_NOTIFY_DELAYED_GENERALERROR); +- atomic_set(&buffer->state, +- QETH_QDIO_BUF_HANDLED_DELAYED); ++ error = true; + break; + default: + WARN_ON_ONCE(1); + } +- } +- +- QETH_CARD_TEXT_(card, 5, "pel%u", bidx); + +- /* prepare the queue slot for re-use: */ +- qeth_scrub_qdio_buffer(buffer->buffer, queue->max_elements); +- if (qeth_init_qdio_out_buf(queue, bidx)) { +- QETH_CARD_TEXT(card, 2, "outofbuf"); +- qeth_schedule_recovery(card); ++ break; ++ case QETH_QDIO_BUF_QAOB_OK: ++ /* qeth_qdio_handle_aob() already received a QAOB: */ ++ qeth_notify_skbs(queue, buffer, TX_NOTIFY_OK); ++ error = false; ++ break; ++ case QETH_QDIO_BUF_QAOB_ERROR: ++ /* qeth_qdio_handle_aob() already received a QAOB: */ ++ qeth_notify_skbs(queue, buffer, TX_NOTIFY_GENERALERROR); ++ error = true; ++ break; ++ default: ++ WARN_ON_ONCE(1); + } +- +- return; +- } +- +- if (card->options.cq == QETH_CQ_ENABLED) ++ } else if (card->options.cq == QETH_CQ_ENABLED) { + qeth_notify_skbs(queue, buffer, + qeth_compute_cq_notification(sflags, 0)); ++ } ++ + qeth_clear_output_buffer(queue, buffer, error, budget); + } + +-- +2.30.1 + diff --git a/queue-5.10/s390-qeth-fix-notification-for-pending-buffers-durin.patch b/queue-5.10/s390-qeth-fix-notification-for-pending-buffers-durin.patch new file mode 100644 index 00000000000..22572f400ec --- /dev/null +++ b/queue-5.10/s390-qeth-fix-notification-for-pending-buffers-durin.patch @@ -0,0 +1,57 @@ +From b693b65fee8137c86b32714fc19e6e28c1831c2f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Mar 2021 17:52:21 +0100 +Subject: s390/qeth: fix notification for pending buffers during teardown + +From: Julian Wiedmann + +[ Upstream commit 7eefda7f353ef86ad82a2dc8329e8a3538c08ab6 ] + +The cited commit reworked the state machine for pending TX buffers. +In qeth_iqd_tx_complete() it turned PENDING into a transient state, and +uses NEED_QAOB for buffers that get parked while waiting for their QAOB +completion. + +But it missed to adjust the check in qeth_tx_complete_buf(). So if +qeth_tx_complete_pending_bufs() is called during teardown to drain +the parked TX buffers, we no longer raise a notification for af_iucv. + +Instead of updating the checked state, just move this code into +qeth_tx_complete_pending_bufs() itself. This also gets rid of the +special-case in the common TX completion path. + +Fixes: 8908f36d20d8 ("s390/qeth: fix af_iucv notification race") +Signed-off-by: Julian Wiedmann +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/s390/net/qeth_core_main.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c +index db785030293b..03f96177e58e 100644 +--- a/drivers/s390/net/qeth_core_main.c ++++ b/drivers/s390/net/qeth_core_main.c +@@ -1383,9 +1383,6 @@ static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error, + struct qeth_qdio_out_q *queue = buf->q; + struct sk_buff *skb; + +- if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING) +- qeth_notify_skbs(queue, buf, TX_NOTIFY_GENERALERROR); +- + /* Empty buffer? */ + if (buf->next_element_to_fill == 0) + return; +@@ -1458,6 +1455,9 @@ static void qeth_tx_complete_pending_bufs(struct qeth_card *card, + QETH_CARD_TEXT(card, 5, "fp"); + QETH_CARD_TEXT_(card, 5, "%lx", (long) buf); + ++ if (drain) ++ qeth_notify_skbs(queue, buf, ++ TX_NOTIFY_GENERALERROR); + qeth_tx_complete_buf(buf, drain, 0); + + list_del(&buf->list_entry); +-- +2.30.1 + diff --git a/queue-5.10/s390-qeth-improve-completion-of-pending-tx-buffers.patch b/queue-5.10/s390-qeth-improve-completion-of-pending-tx-buffers.patch new file mode 100644 index 00000000000..20fbf645d14 --- /dev/null +++ b/queue-5.10/s390-qeth-improve-completion-of-pending-tx-buffers.patch @@ -0,0 +1,198 @@ +From 4478aa7a048a6bb0371c9155a0d081c8c741008b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Mar 2021 17:52:19 +0100 +Subject: s390/qeth: improve completion of pending TX buffers + +From: Julian Wiedmann + +[ Upstream commit c20383ad1656b0f6354dd50e4acd894f9d94090d ] + +The current design attaches a pending TX buffer to a custom +single-linked list, which is anchored at the buffer's slot on the +TX ring. The buffer is then checked for final completion whenever +this slot is processed during a subsequent TX NAPI poll cycle. + +But if there's insufficient traffic on the ring, we might never make +enough progress to get back to this ring slot and discover the pending +buffer's final TX completion. In particular if this missing TX +completion blocks the application from sending further traffic. + +So convert the custom single-linked list code to a per-queue list_head, +and scan this list on every TX NAPI cycle. + +Fixes: 0da9581ddb0f ("qeth: exploit asynchronous delivery of storage blocks") +Signed-off-by: Julian Wiedmann +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/s390/net/qeth_core.h | 3 +- + drivers/s390/net/qeth_core_main.c | 69 +++++++++++++------------------ + 2 files changed, 30 insertions(+), 42 deletions(-) + +diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h +index ea969b8fe687..bf8404b0e74f 100644 +--- a/drivers/s390/net/qeth_core.h ++++ b/drivers/s390/net/qeth_core.h +@@ -436,7 +436,7 @@ struct qeth_qdio_out_buffer { + int is_header[QDIO_MAX_ELEMENTS_PER_BUFFER]; + + struct qeth_qdio_out_q *q; +- struct qeth_qdio_out_buffer *next_pending; ++ struct list_head list_entry; + }; + + struct qeth_card; +@@ -500,6 +500,7 @@ struct qeth_qdio_out_q { + struct qdio_buffer *qdio_bufs[QDIO_MAX_BUFFERS_PER_Q]; + struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q]; + struct qdio_outbuf_state *bufstates; /* convenience pointer */ ++ struct list_head pending_bufs; + struct qeth_out_q_stats stats; + spinlock_t lock; + unsigned int priority; +diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c +index e2cdb5c2fc66..db785030293b 100644 +--- a/drivers/s390/net/qeth_core_main.c ++++ b/drivers/s390/net/qeth_core_main.c +@@ -73,8 +73,6 @@ static void qeth_free_qdio_queues(struct qeth_card *card); + static void qeth_notify_skbs(struct qeth_qdio_out_q *queue, + struct qeth_qdio_out_buffer *buf, + enum iucv_tx_notify notification); +-static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error, +- int budget); + + static void qeth_close_dev_handler(struct work_struct *work) + { +@@ -465,41 +463,6 @@ static enum iucv_tx_notify qeth_compute_cq_notification(int sbalf15, + return n; + } + +-static void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, int bidx, +- int forced_cleanup) +-{ +- if (q->card->options.cq != QETH_CQ_ENABLED) +- return; +- +- if (q->bufs[bidx]->next_pending != NULL) { +- struct qeth_qdio_out_buffer *head = q->bufs[bidx]; +- struct qeth_qdio_out_buffer *c = q->bufs[bidx]->next_pending; +- +- while (c) { +- if (forced_cleanup || +- atomic_read(&c->state) == QETH_QDIO_BUF_EMPTY) { +- struct qeth_qdio_out_buffer *f = c; +- +- QETH_CARD_TEXT(f->q->card, 5, "fp"); +- QETH_CARD_TEXT_(f->q->card, 5, "%lx", (long) f); +- /* release here to avoid interleaving between +- outbound tasklet and inbound tasklet +- regarding notifications and lifecycle */ +- qeth_tx_complete_buf(c, forced_cleanup, 0); +- +- c = f->next_pending; +- WARN_ON_ONCE(head->next_pending != f); +- head->next_pending = c; +- kmem_cache_free(qeth_qdio_outbuf_cache, f); +- } else { +- head = c; +- c = c->next_pending; +- } +- +- } +- } +-} +- + static void qeth_qdio_handle_aob(struct qeth_card *card, + unsigned long phys_aob_addr) + { +@@ -537,7 +500,7 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, + qeth_notify_skbs(buffer->q, buffer, notification); + + /* Free dangling allocations. The attached skbs are handled by +- * qeth_cleanup_handled_pending(). ++ * qeth_tx_complete_pending_bufs(). + */ + for (i = 0; + i < aob->sb_count && i < QETH_MAX_BUFFER_ELEMENTS(card); +@@ -1484,14 +1447,35 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, + atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY); + } + ++static void qeth_tx_complete_pending_bufs(struct qeth_card *card, ++ struct qeth_qdio_out_q *queue, ++ bool drain) ++{ ++ struct qeth_qdio_out_buffer *buf, *tmp; ++ ++ list_for_each_entry_safe(buf, tmp, &queue->pending_bufs, list_entry) { ++ if (drain || atomic_read(&buf->state) == QETH_QDIO_BUF_EMPTY) { ++ QETH_CARD_TEXT(card, 5, "fp"); ++ QETH_CARD_TEXT_(card, 5, "%lx", (long) buf); ++ ++ qeth_tx_complete_buf(buf, drain, 0); ++ ++ list_del(&buf->list_entry); ++ kmem_cache_free(qeth_qdio_outbuf_cache, buf); ++ } ++ } ++} ++ + static void qeth_drain_output_queue(struct qeth_qdio_out_q *q, bool free) + { + int j; + ++ qeth_tx_complete_pending_bufs(q->card, q, true); ++ + for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { + if (!q->bufs[j]) + continue; +- qeth_cleanup_handled_pending(q, j, 1); ++ + qeth_clear_output_buffer(q, q->bufs[j], true, 0); + if (free) { + kmem_cache_free(qeth_qdio_outbuf_cache, q->bufs[j]); +@@ -2611,7 +2595,6 @@ static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx) + skb_queue_head_init(&newbuf->skb_list); + lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key); + newbuf->q = q; +- newbuf->next_pending = q->bufs[bidx]; + atomic_set(&newbuf->state, QETH_QDIO_BUF_EMPTY); + q->bufs[bidx] = newbuf; + return 0; +@@ -2693,6 +2676,7 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card) + card->qdio.out_qs[i] = queue; + queue->card = card; + queue->queue_no = i; ++ INIT_LIST_HEAD(&queue->pending_bufs); + spin_lock_init(&queue->lock); + timer_setup(&queue->timer, qeth_tx_completion_timer, 0); + queue->coalesce_usecs = QETH_TX_COALESCE_USECS; +@@ -5890,6 +5874,8 @@ static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue, + qeth_schedule_recovery(card); + } + ++ list_add(&buffer->list_entry, ++ &queue->pending_bufs); + /* Skip clearing the buffer: */ + return; + case QETH_QDIO_BUF_QAOB_OK: +@@ -5945,6 +5931,8 @@ static int qeth_tx_poll(struct napi_struct *napi, int budget) + unsigned int bytes = 0; + int completed; + ++ qeth_tx_complete_pending_bufs(card, queue, false); ++ + if (qeth_out_queue_is_empty(queue)) { + napi_complete(napi); + return 0; +@@ -5977,7 +5965,6 @@ static int qeth_tx_poll(struct napi_struct *napi, int budget) + + qeth_handle_send_error(card, buffer, error); + qeth_iqd_tx_complete(queue, bidx, error, budget); +- qeth_cleanup_handled_pending(queue, bidx, false); + } + + netdev_tx_completed_queue(txq, packets, bytes); +-- +2.30.1 + diff --git a/queue-5.10/s390-qeth-remove-qeth_qdio_buf_handled_delayed-state.patch b/queue-5.10/s390-qeth-remove-qeth_qdio_buf_handled_delayed-state.patch new file mode 100644 index 00000000000..73a6db8bf92 --- /dev/null +++ b/queue-5.10/s390-qeth-remove-qeth_qdio_buf_handled_delayed-state.patch @@ -0,0 +1,60 @@ +From 384fee83b72b583c52a8f9235694c0338c5a72a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Dec 2020 14:12:32 +0100 +Subject: s390/qeth: remove QETH_QDIO_BUF_HANDLED_DELAYED state + +From: Julian Wiedmann + +[ Upstream commit 75cf3854dcdf7b5c583538cae12ffa054d237d93 ] + +Reuse the QETH_QDIO_BUF_EMPTY state to indicate that a TX buffer has +been completed with a QAOB notification, and may be cleaned up by +qeth_cleanup_handled_pending(). + +Signed-off-by: Julian Wiedmann +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/s390/net/qeth_core.h | 2 -- + drivers/s390/net/qeth_core_main.c | 5 ++--- + 2 files changed, 2 insertions(+), 5 deletions(-) + +diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h +index 2f7e06ec9a30..ea969b8fe687 100644 +--- a/drivers/s390/net/qeth_core.h ++++ b/drivers/s390/net/qeth_core.h +@@ -424,8 +424,6 @@ enum qeth_qdio_out_buffer_state { + /* Received QAOB notification on CQ: */ + QETH_QDIO_BUF_QAOB_OK, + QETH_QDIO_BUF_QAOB_ERROR, +- /* Handled via transfer pending / completion queue. */ +- QETH_QDIO_BUF_HANDLED_DELAYED, + }; + + struct qeth_qdio_out_buffer { +diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c +index 78a866424022..e2cdb5c2fc66 100644 +--- a/drivers/s390/net/qeth_core_main.c ++++ b/drivers/s390/net/qeth_core_main.c +@@ -477,8 +477,7 @@ static void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, int bidx, + + while (c) { + if (forced_cleanup || +- atomic_read(&c->state) == +- QETH_QDIO_BUF_HANDLED_DELAYED) { ++ atomic_read(&c->state) == QETH_QDIO_BUF_EMPTY) { + struct qeth_qdio_out_buffer *f = c; + + QETH_CARD_TEXT(f->q->card, 5, "fp"); +@@ -549,7 +548,7 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, + kmem_cache_free(qeth_core_header_cache, data); + } + +- atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED); ++ atomic_set(&buffer->state, QETH_QDIO_BUF_EMPTY); + break; + default: + WARN_ON_ONCE(1); +-- +2.30.1 + diff --git a/queue-5.10/series b/queue-5.10/series index ffc149c04bf..afacaa00373 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -106,3 +106,27 @@ media-v4l-vsp1-fix-uif-null-pointer-access.patch media-v4l-vsp1-fix-bru-null-pointer-access.patch media-rc-compile-rc-cec.c-into-rc-core.patch cifs-fix-credit-accounting-for-extra-channel.patch +net-hns3-fix-error-mask-definition-of-flow-director.patch +mips-kernel-reserve-exception-base-early-to-prevent-.patch +s390-qeth-don-t-replace-a-fully-completed-async-tx-b.patch +s390-qeth-remove-qeth_qdio_buf_handled_delayed-state.patch +s390-qeth-improve-completion-of-pending-tx-buffers.patch +s390-qeth-fix-notification-for-pending-buffers-durin.patch +net-dsa-implement-a-central-tx-reallocation-procedur.patch +net-dsa-tag_ksz-don-t-allocate-additional-memory-for.patch +net-dsa-trailer-don-t-allocate-additional-memory-for.patch +net-dsa-tag_qca-let-dsa-core-deal-with-tx-reallocati.patch +net-dsa-tag_ocelot-let-dsa-core-deal-with-tx-realloc.patch +net-dsa-tag_mtk-let-dsa-core-deal-with-tx-reallocati.patch +net-dsa-tag_lan9303-let-dsa-core-deal-with-tx-reallo.patch +net-dsa-tag_edsa-let-dsa-core-deal-with-tx-reallocat.patch +net-dsa-tag_brcm-let-dsa-core-deal-with-tx-reallocat.patch +net-dsa-tag_dsa-let-dsa-core-deal-with-tx-reallocati.patch +net-dsa-tag_gswip-let-dsa-core-deal-with-tx-realloca.patch +net-dsa-tag_ar9331-let-dsa-core-deal-with-tx-realloc.patch +net-dsa-tag_mtk-fix-802.1ad-vlan-egress.patch +enetc-fix-unused-var-build-warning-for-config_of.patch +net-enetc-initialize-rfs-rss-memories-for-unused-por.patch +ath11k-peer-delete-synchronization-with-firmware.patch +ath11k-start-vdev-if-a-bss-peer-is-already-created.patch +ath11k-fix-ap-mode-for-qca6390.patch