]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Fri, 12 Mar 2021 23:04:40 +0000 (18:04 -0500)
committerSasha Levin <sashal@kernel.org>
Fri, 12 Mar 2021 23:04:40 +0000 (18:04 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
25 files changed:
queue-5.10/ath11k-fix-ap-mode-for-qca6390.patch [new file with mode: 0644]
queue-5.10/ath11k-peer-delete-synchronization-with-firmware.patch [new file with mode: 0644]
queue-5.10/ath11k-start-vdev-if-a-bss-peer-is-already-created.patch [new file with mode: 0644]
queue-5.10/enetc-fix-unused-var-build-warning-for-config_of.patch [new file with mode: 0644]
queue-5.10/mips-kernel-reserve-exception-base-early-to-prevent-.patch [new file with mode: 0644]
queue-5.10/net-dsa-implement-a-central-tx-reallocation-procedur.patch [new file with mode: 0644]
queue-5.10/net-dsa-tag_ar9331-let-dsa-core-deal-with-tx-realloc.patch [new file with mode: 0644]
queue-5.10/net-dsa-tag_brcm-let-dsa-core-deal-with-tx-reallocat.patch [new file with mode: 0644]
queue-5.10/net-dsa-tag_dsa-let-dsa-core-deal-with-tx-reallocati.patch [new file with mode: 0644]
queue-5.10/net-dsa-tag_edsa-let-dsa-core-deal-with-tx-reallocat.patch [new file with mode: 0644]
queue-5.10/net-dsa-tag_gswip-let-dsa-core-deal-with-tx-realloca.patch [new file with mode: 0644]
queue-5.10/net-dsa-tag_ksz-don-t-allocate-additional-memory-for.patch [new file with mode: 0644]
queue-5.10/net-dsa-tag_lan9303-let-dsa-core-deal-with-tx-reallo.patch [new file with mode: 0644]
queue-5.10/net-dsa-tag_mtk-fix-802.1ad-vlan-egress.patch [new file with mode: 0644]
queue-5.10/net-dsa-tag_mtk-let-dsa-core-deal-with-tx-reallocati.patch [new file with mode: 0644]
queue-5.10/net-dsa-tag_ocelot-let-dsa-core-deal-with-tx-realloc.patch [new file with mode: 0644]
queue-5.10/net-dsa-tag_qca-let-dsa-core-deal-with-tx-reallocati.patch [new file with mode: 0644]
queue-5.10/net-dsa-trailer-don-t-allocate-additional-memory-for.patch [new file with mode: 0644]
queue-5.10/net-enetc-initialize-rfs-rss-memories-for-unused-por.patch [new file with mode: 0644]
queue-5.10/net-hns3-fix-error-mask-definition-of-flow-director.patch [new file with mode: 0644]
queue-5.10/s390-qeth-don-t-replace-a-fully-completed-async-tx-b.patch [new file with mode: 0644]
queue-5.10/s390-qeth-fix-notification-for-pending-buffers-durin.patch [new file with mode: 0644]
queue-5.10/s390-qeth-improve-completion-of-pending-tx-buffers.patch [new file with mode: 0644]
queue-5.10/s390-qeth-remove-qeth_qdio_buf_handled_delayed-state.patch [new file with mode: 0644]
queue-5.10/series

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 (file)
index 0000000..e21ebc1
--- /dev/null
@@ -0,0 +1,60 @@
+From b1670b113b0c23315d3fc95af7f119378084459d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Feb 2021 17:14:09 +0200
+Subject: ath11k: fix AP mode for QCA6390
+
+From: Kalle Valo <kvalo@codeaurora.org>
+
+[ 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 <kvalo@codeaurora.org>
+Link: https://lore.kernel.org/r/1614006849-25764-1-git-send-email-kvalo@codeaurora.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..1267694
--- /dev/null
@@ -0,0 +1,212 @@
+From 0f24b33cc67c55b0f1bc65b8c35475ac6c4e7eb6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Nov 2020 17:59:14 +0200
+Subject: ath11k: peer delete synchronization with firmware
+
+From: Ritesh Singh <ritesi@codeaurora.org>
+
+[ 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 <ritesi@codeaurora.org>
+Signed-off-by: Maharaja Kennadyrajan <mkenna@codeaurora.org>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Link: https://lore.kernel.org/r/1605514143-17652-3-git-send-email-mkenna@codeaurora.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..33cbb92
--- /dev/null
@@ -0,0 +1,105 @@
+From fa7bf57f7938aea2770df6d7b069b36da3cce238 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Dec 2020 00:13:58 -0500
+Subject: ath11k: start vdev if a bss peer is already created
+
+From: Carl Huang <cjhuang@codeaurora.org>
+
+[ 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 <cjhuang@codeaurora.org>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Link: https://lore.kernel.org/r/20201211051358.9191-1-cjhuang@codeaurora.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..e431657
--- /dev/null
@@ -0,0 +1,106 @@
+From 46e5105d05a088a29ea70d9ecb80904fdb711c4b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Dec 2020 14:08:00 +0200
+Subject: enetc: Fix unused var build warning for CONFIG_OF
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ 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 <arnd@arndb.de>
+Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
+Link: https://lore.kernel.org/r/20201204120800.17193-1-claudiu.manoil@nxp.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..8c9f8e7
--- /dev/null
@@ -0,0 +1,163 @@
+From 50eae04e8a832e98e0f281eedc80769c52c8475f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Mar 2021 10:24:47 +0100
+Subject: MIPS: kernel: Reserve exception base early to prevent corruption
+
+From: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+
+[ 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 <kdasu.kdev@gmail.com>
+Debugged-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
+Acked-by: Mike Rapoport <rppt@linux.ibm.com>
+Tested-by: Florian Fainelli <f.fainelli@gmail.com>
+Reviewed-by: Serge Semin <fancer.lancer@gmail.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <asm/elf.h>
+ #include <asm/pgtable-bits.h>
+ #include <asm/spram.h>
++#include <asm/traps.h>
+ #include <linux/uaccess.h>
+ #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 <asm/fpu.h>
+ #include <asm/mipsregs.h>
+ #include <asm/elf.h>
++#include <asm/traps.h>
+ #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 (file)
index 0000000..15c0ba3
--- /dev/null
@@ -0,0 +1,114 @@
+From 7f0929f5432f121f49716d56319a9cc7465269ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 1 Nov 2020 21:16:09 +0200
+Subject: net: dsa: implement a central TX reallocation procedure
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ 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 <vladimir.oltean@nxp.com>
+Tested-by: Christian Eggers <ceggers@arri.de> # For tail taggers only
+Tested-by: Kurt Kanzenbach <kurt@linutronix.de>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..28f6ab8
--- /dev/null
@@ -0,0 +1,41 @@
+From 1cf4673ba62477fd972a8369f7b126c735916840 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 1 Nov 2020 21:16:20 +0200
+Subject: net: dsa: tag_ar9331: let DSA core deal with TX reallocation
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ 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 <per.forlin@axis.com>
+Cc: Oleksij Rempel <linux@rempel-privat.de>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Tested-by: Oleksij Rempel <linux@rempel-privat.de>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..cb4d19c
--- /dev/null
@@ -0,0 +1,39 @@
+From d48532018497a8df115f2537952b25cb6a8defd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 1 Nov 2020 21:16:17 +0200
+Subject: net: dsa: tag_brcm: let DSA core deal with TX reallocation
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ 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 <f.fainelli@gmail.com>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..543755d
--- /dev/null
@@ -0,0 +1,53 @@
+From 3559a2edd20071b42af22d3cda506372e4bfa7c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 1 Nov 2020 21:16:18 +0200
+Subject: net: dsa: tag_dsa: let DSA core deal with TX reallocation
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ 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 <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..e5dadaa
--- /dev/null
@@ -0,0 +1,52 @@
+From d4c3878b0c48f4aa059c239b02198848bf3faa7b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 1 Nov 2020 21:16:16 +0200
+Subject: net: dsa: tag_edsa: let DSA core deal with TX reallocation
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ 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 <andrew@lunn.ch>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..5598382
--- /dev/null
@@ -0,0 +1,50 @@
+From f5e9219ce4606a568cf76d4650aed661d642288a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 1 Nov 2020 21:16:19 +0200
+Subject: net: dsa: tag_gswip: let DSA core deal with TX reallocation
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ 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 <hauke@hauke-m.de>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..fcdab09
--- /dev/null
@@ -0,0 +1,161 @@
+From d67d109966037a86ca61265d35db182148b43165 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <ceggers@arri.de>
+
+[ 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 <ceggers@arri.de>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..6b2e899
--- /dev/null
@@ -0,0 +1,44 @@
+From 144ccb61f5c40c1854bb165a16a2d2b3fa47abe8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 1 Nov 2020 21:16:15 +0200
+Subject: net: dsa: tag_lan9303: let DSA core deal with TX reallocation
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ 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 <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..210e95c
--- /dev/null
@@ -0,0 +1,84 @@
+From 431ef53c835c33faa35fb2792fa5d549b986bb58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Mar 2021 00:01:59 +0800
+Subject: net: dsa: tag_mtk: fix 802.1ad VLAN egress
+
+From: DENG Qingfang <dqfext@gmail.com>
+
+[ Upstream commit 9200f515c41f4cbaeffd8fdd1d8b6373a18b1b67 ]
+
+A different TPID bit is used for 802.1ad VLAN frames.
+
+Reported-by: Ilario Gelmetti <iochesonome@gmail.com>
+Fixes: f0af34317f4b ("net: dsa: mediatek: combine MediaTek tag with VLAN tag")
+Signed-off-by: DENG Qingfang <dqfext@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..21172c2
--- /dev/null
@@ -0,0 +1,41 @@
+From ea0f236c1714f4d948851c74cc13bf211359efe2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 1 Nov 2020 21:16:14 +0200
+Subject: net: dsa: tag_mtk: let DSA core deal with TX reallocation
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ 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 <dqfext@gmail.com>
+Cc: Sean Wang <sean.wang@mediatek.com>
+Cc: John Crispin <john@phrozen.org>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..c45329e
--- /dev/null
@@ -0,0 +1,42 @@
+From 2407ba787b21c6f9d4e1a2de75d10acab9bd8f27 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 1 Nov 2020 21:16:13 +0200
+Subject: net: dsa: tag_ocelot: let DSA core deal with TX reallocation
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ 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 <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..ef37139
--- /dev/null
@@ -0,0 +1,40 @@
+From 711716fcbb18a3f427fc231d0fc983343d289714 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 1 Nov 2020 21:16:12 +0200
+Subject: net: dsa: tag_qca: let DSA core deal with TX reallocation
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ 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 <john@phrozen.org>
+Cc: Alexander Lobakin <alobakin@pm.me>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..afbbfc5
--- /dev/null
@@ -0,0 +1,74 @@
+From 42a1837d79bf5111efe55272f483d29bd6bcabca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 1 Nov 2020 21:16:11 +0200
+Subject: net: dsa: trailer: don't allocate additional memory for
+ padding/tagging
+
+From: Christian Eggers <ceggers@arri.de>
+
+[ 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 <ceggers@arri.de>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..2b5bec0
--- /dev/null
@@ -0,0 +1,174 @@
+From d2765886e4ca05d12d0de35ce5a45ce1f6ae9736 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Mar 2021 13:18:12 +0200
+Subject: net: enetc: initialize RFS/RSS memories for unused ports too
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ 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 <michael@walle.cc>
+Cc: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Tested-by: Michael Walle <michael@walle.cc>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..bba492e
--- /dev/null
@@ -0,0 +1,51 @@
+From c8605d62188d979dc64a3be89e479dcdfde25815 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 27 Feb 2021 15:24:51 +0800
+Subject: net: hns3: fix error mask definition of flow director
+
+From: Jian Shen <shenjian15@huawei.com>
+
+[ 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 <shenjian15@huawei.com>
+Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..50ead2d
--- /dev/null
@@ -0,0 +1,183 @@
+From db57241ae94eceea3692871b5f238dd09606dea1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Dec 2020 14:12:31 +0100
+Subject: s390/qeth: don't replace a fully completed async TX buffer
+
+From: Julian Wiedmann <jwi@linux.ibm.com>
+
+[ 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 <jwi@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..22572f4
--- /dev/null
@@ -0,0 +1,57 @@
+From b693b65fee8137c86b32714fc19e6e28c1831c2f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Mar 2021 17:52:21 +0100
+Subject: s390/qeth: fix notification for pending buffers during teardown
+
+From: Julian Wiedmann <jwi@linux.ibm.com>
+
+[ 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 <jwi@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..20fbf64
--- /dev/null
@@ -0,0 +1,198 @@
+From 4478aa7a048a6bb0371c9155a0d081c8c741008b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Mar 2021 17:52:19 +0100
+Subject: s390/qeth: improve completion of pending TX buffers
+
+From: Julian Wiedmann <jwi@linux.ibm.com>
+
+[ 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 <jwi@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..73a6db8
--- /dev/null
@@ -0,0 +1,60 @@
+From 384fee83b72b583c52a8f9235694c0338c5a72a2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Dec 2020 14:12:32 +0100
+Subject: s390/qeth: remove QETH_QDIO_BUF_HANDLED_DELAYED state
+
+From: Julian Wiedmann <jwi@linux.ibm.com>
+
+[ 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 <jwi@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
index ffc149c04bf24ee15b8313fd71158ef27968f702..afacaa0037370e914f9cb41799192900c62e0a8e 100644 (file)
@@ -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