commit 821560c32c3e311d32b1125a19a0d19f55e062ae Author: CentOS Sources Date: Mon Apr 12 05:00:56 2021 -0400 import kmod-redhat-atlantic-4.18.0_255.el8_dup8.3-1.el8_3 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1cd28ad --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/atlantic-redhat-4.18.0_255.el8_dup8.3.tar.bz2 diff --git a/.kmod-redhat-atlantic.metadata b/.kmod-redhat-atlantic.metadata new file mode 100644 index 0000000..7fbac58 --- /dev/null +++ b/.kmod-redhat-atlantic.metadata @@ -0,0 +1 @@ +5ece7ad494005356ea006e000eeaafdf78a9fea5 SOURCES/atlantic-redhat-4.18.0_255.el8_dup8.3.tar.bz2 diff --git a/SOURCES/0001-netdrv-treewide-Replace-GPLv2-boilerplate-reference-.patch b/SOURCES/0001-netdrv-treewide-Replace-GPLv2-boilerplate-reference-.patch new file mode 100644 index 0000000..9deca5c --- /dev/null +++ b/SOURCES/0001-netdrv-treewide-Replace-GPLv2-boilerplate-reference-.patch @@ -0,0 +1,92 @@ +From b90c68b784b589dd31510770959da82bcf983a74 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:18 -0500 +Subject: [PATCH 001/139] [netdrv] treewide: Replace GPLv2 + boilerplate/reference with SPDX - rule 308 + +Message-id: <1604687916-15087-2-git-send-email-irusskik@redhat.com> +Patchwork-id: 338430 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 001/139] treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 308 +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 +Conflicts: Limit the scope of upstream commit to atlantic driver + +commit dcc4086d9e1abaf0c5477eaf14fec5ca903eb57d +Author: Thomas Gleixner +Date: Wed May 29 16:57:23 2019 -0700 + + treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 308 + + Based on 1 normalized pattern(s): + + this program is free software you can redistribute it and or modify + it under the terms and conditions of the gnu general public license + version 2 as published by the free software foundation this program + is distributed in the hope it will be useful but without any + warranty without even the implied warranty of merchantability or + fitness for a particular purpose see the gnu general public license + for more details you should have received a copy of the gnu general + public license along with this program if not see http www gnu org + licenses the full gnu general public license is included in this + distribution in the file called copying + + extracted by the scancode license scanner the SPDX license identifier + + GPL-2.0-only + + has been chosen to replace the boilerplate/reference in 12 file(s). + + Signed-off-by: Thomas Gleixner + Reviewed-by: Alexios Zavras + Reviewed-by: Allison Randal + Reviewed-by: Kate Stewart + Cc: linux-spdx@vger.kernel.org + Link: https://lkml.kernel.org/r/20190530000434.160381502@linutronix.de + Signed-off-by: Greg Kroah-Hartman + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/Makefile | 16 +--------------- + 1 file changed, 1 insertion(+), 15 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile +index 1f99cf832476..131cab855be7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/Makefile ++++ b/drivers/net/ethernet/aquantia/atlantic/Makefile +@@ -1,23 +1,9 @@ ++# SPDX-License-Identifier: GPL-2.0-only + ################################################################################ + # + # aQuantia Ethernet Controller AQtion Linux Driver + # Copyright(c) 2014-2017 aQuantia Corporation. + # +-# This program is free software; you can redistribute it and/or modify it +-# under the terms and conditions of the GNU General Public License, +-# version 2, as published by the Free Software Foundation. +-# +-# This program is distributed in the hope it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +-# more details. +-# +-# You should have received a copy of the GNU General Public License along +-# with this program. If not, see . +-# +-# The full GNU General Public License is included in this distribution in +-# the file called "COPYING". +-# + # Contact Information: + # aQuantia Corporation, 105 E. Tasman Dr. San Jose, CA 95134, USA + # +-- +2.13.6 + diff --git a/SOURCES/0002-netdrv-treewide-Replace-GPLv2-boilerplate-reference-.patch b/SOURCES/0002-netdrv-treewide-Replace-GPLv2-boilerplate-reference-.patch new file mode 100644 index 0000000..83fff8a --- /dev/null +++ b/SOURCES/0002-netdrv-treewide-Replace-GPLv2-boilerplate-reference-.patch @@ -0,0 +1,597 @@ +From a71019cedb1848a347b0d3437d85c0b4c65d90d2 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:19 -0500 +Subject: [PATCH 002/139] [netdrv] treewide: Replace GPLv2 + boilerplate/reference with SPDX - rule 422 + +Message-id: <1604687916-15087-3-git-send-email-irusskik@redhat.com> +Patchwork-id: 338429 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 002/139] treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 422 +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 +Conflicts: Limit the scope of upstream commit to atlantic driver + +commit 75a6faf617d107bdbc74d36ccf89f2280b96ac26 +Author: Thomas Gleixner +Date: Sat Jun 1 10:08:37 2019 +0200 + + treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 422 + + Based on 1 normalized pattern(s): + + this program is free software you can redistribute it and or modify + it under the terms and conditions of the gnu general public license + version 2 as published by the free software foundation + + extracted by the scancode license scanner the SPDX license identifier + + GPL-2.0-only + + has been chosen to replace the boilerplate/reference in 101 file(s). + + Signed-off-by: Thomas Gleixner + Reviewed-by: Allison Randal + Cc: linux-spdx@vger.kernel.org + Link: https://lkml.kernel.org/r/20190531190113.822954939@linutronix.de + Signed-off-by: Greg Kroah-Hartman + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_cfg.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_common.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_main.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_rss.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_utils.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 5 +---- + drivers/net/ethernet/aquantia/atlantic/aq_vec.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 5 +---- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 5 +---- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 5 +---- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c | 5 +---- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h | 5 +---- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 5 +---- + drivers/net/ethernet/aquantia/atlantic/ver.h | 5 +---- + 32 files changed, 32 insertions(+), 128 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +index 8f35c3f883f0..173be45463ee 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_cfg.h: Definition of configuration parameters and constants. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +index 235bb3a72d66..42ea8d8daa46 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_common.h: Basic includes for all files in project. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 79da48094770..24df132384fb 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -1,10 +1,7 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_ethtool.c: Definition of ethertool related functions. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h +index 21c126eeb5eb..632b5531db4a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_ethtool.h: Declaration of ethertool related functions. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index 5c8995ae94b5..1ee717b0e67c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_hw.h: Declaration of abstract interface for NIC hardware specific +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +index 22a1c784dc9c..9c7a226d81b6 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +@@ -1,10 +1,7 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_hw_utils.c: Definitions of helper functions used across +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +index bf73428ed689..9ef82d487e01 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_hw_utils.h: Declaration of helper functions used across hardware +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index ab83b5aac0be..4ebf083c51c5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -1,10 +1,7 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_main.c: Main file for aQuantia Linux driver. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.h b/drivers/net/ethernet/aquantia/atlantic/aq_main.h +index 5448b82fb7ea..a5a624b9ce73 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_main.h: Main file for aQuantia Linux driver. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 919d23727702..41172fbebddd 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -1,10 +1,7 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_nic.c: Definition of common code for NIC. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index c80d38f5e889..0f22f5d5691b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_nic.h: Declaration of common code for NIC. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +index 9cb0864d6d8d..74b9f3f1da81 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +@@ -1,10 +1,7 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_pci_func.c: Definition of PCI functions. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h +index 670f9a940d65..77be7ee0d7b3 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_pci_func.h: Declaration of PCI functions. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index 941b0beb87ef..2a7b91ed17c5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -1,10 +1,7 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_ring.c: Definition of functions for Rx/Tx rings. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +index cfffc301e746..6bd67210d0b7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_ring.h: Declaration of functions for Rx/Tx rings. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_rss.h b/drivers/net/ethernet/aquantia/atlantic/aq_rss.h +index 1db6eb20a8f2..39b1f43c8ad7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_rss.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_rss.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_rss.h: Receive Side Scaling definitions. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_utils.h +index 786ea8187c69..d3a0b2ec0279 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_utils.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_utils.h: Useful macro and structures used in all layers of driver. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +index a2e4ca1782ae..715685aa48c3 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +@@ -1,10 +1,7 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_vec.c: Definition of common structure for vector of Rx and Tx rings. +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.h b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h +index 8bdf60bb3f63..0fe8e0904c7f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File aq_vec.h: Definition of common structures for vector of Rx and Tx rings. +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index 9fe507fe2d7f..0f140a9fe404 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -1,10 +1,7 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File hw_atl_a0.c: Definition of Atlantic hardware specific functions. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.h +index 25fe954def03..1a294ad4d17d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File hw_atl_a0.h: Declaration of abstract interface for Atlantic hardware +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h +index a021dc431ef7..1b9b2e5601ed 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File hw_atl_a0_internal.h: Definition of Atlantic A0 chip specific +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 1cb5db0fc951..13ac2661a473 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1,10 +1,7 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File hw_atl_b0.c: Definition of Atlantic hardware specific functions. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +index b1c0b6850e60..09af1683034b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File hw_atl_b0.h: Declaration of abstract interface for Atlantic hardware +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +index ea98a08d7820..e4ba2ccf9830 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File hw_atl_b0_internal.h: Definition of Atlantic B0 chip specific +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index eaab25cd08b3..451529069f28 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -1,10 +1,7 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File hw_atl_llh.c: Definitions of bitfield and register access functions for +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index 2eb44e1cff70..34b42ce43512 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File hw_atl_llh.h: Declarations of bitfield and register access functions for +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +index b64140924a02..fc1446f737bb 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File hw_atl_llh_internal.h: Preprocessor definitions +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 3fc41da39a0a..52646855495e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -1,10 +1,7 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File hw_atl_utils.c: Definition of common functions for Atlantic hardware +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index 48278e333462..692bed70e104 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File hw_atl_utils.h: Declaration of common functions for Atlantic hardware +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index 9c16d85fb104..da726489e3c8 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -1,10 +1,7 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + /* File hw_atl_utils_fw2x.c: Definition of firmware 2.x functions for +diff --git a/drivers/net/ethernet/aquantia/atlantic/ver.h b/drivers/net/ethernet/aquantia/atlantic/ver.h +index b48260114da3..23374bffa92b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/ver.h ++++ b/drivers/net/ethernet/aquantia/atlantic/ver.h +@@ -1,10 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. + */ + + #ifndef VER_H +-- +2.13.6 + diff --git a/SOURCES/0003-netdrv-net-aquantia-replace-internal-driver-version-.patch b/SOURCES/0003-netdrv-net-aquantia-replace-internal-driver-version-.patch new file mode 100644 index 0000000..dd475d1 --- /dev/null +++ b/SOURCES/0003-netdrv-net-aquantia-replace-internal-driver-version-.patch @@ -0,0 +1,85 @@ +From e30f48604e751c828d74ae23e4696c245c65411b Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:20 -0500 +Subject: [PATCH 003/139] [netdrv] net: aquantia: replace internal driver + version code with uts + +Message-id: <1604687916-15087-4-git-send-email-irusskik@redhat.com> +Patchwork-id: 338482 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 003/139] net: aquantia: replace internal driver version code with uts +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 2d3910c4dc37813fedab8f056a62451eaf202c3a +Author: Igor Russkikh +Date: Wed Jun 26 12:35:33 2019 +0000 + + net: aquantia: replace internal driver version code with uts + + As it was discussed some time previously, driver is better to + report kernel version string, as it in a best way identifies + the codebase. + + Signed-off-by: Igor Russkikh + Reviewed-by: Andrew Lunn + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_cfg.h | 7 +++---- + drivers/net/ethernet/aquantia/atlantic/ver.h | 5 ----- + 2 files changed, 3 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +index 173be45463ee..02f1b70c4e25 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +@@ -9,6 +9,8 @@ + #ifndef AQ_CFG_H + #define AQ_CFG_H + ++#include ++ + #define AQ_CFG_VECS_DEF 8U + #define AQ_CFG_TCS_DEF 1U + +@@ -86,10 +88,7 @@ + #define AQ_CFG_DRV_AUTHOR "aQuantia" + #define AQ_CFG_DRV_DESC "aQuantia Corporation(R) Network Driver" + #define AQ_CFG_DRV_NAME "atlantic" +-#define AQ_CFG_DRV_VERSION __stringify(NIC_MAJOR_DRIVER_VERSION)"."\ +- __stringify(NIC_MINOR_DRIVER_VERSION)"."\ +- __stringify(NIC_BUILD_DRIVER_VERSION)"."\ +- __stringify(NIC_REVISION_DRIVER_VERSION) \ ++#define AQ_CFG_DRV_VERSION UTS_RELEASE \ + AQ_CFG_DRV_VERSION_SUFFIX + + #endif /* AQ_CFG_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/ver.h b/drivers/net/ethernet/aquantia/atlantic/ver.h +index 23374bffa92b..597654b51e01 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/ver.h ++++ b/drivers/net/ethernet/aquantia/atlantic/ver.h +@@ -7,11 +7,6 @@ + #ifndef VER_H + #define VER_H + +-#define NIC_MAJOR_DRIVER_VERSION 2 +-#define NIC_MINOR_DRIVER_VERSION 0 +-#define NIC_BUILD_DRIVER_VERSION 4 +-#define NIC_REVISION_DRIVER_VERSION 0 +- + #define AQ_CFG_DRV_VERSION_SUFFIX "-kern" + + #endif /* VER_H */ +-- +2.13.6 + diff --git a/SOURCES/0004-netdrv-net-aquantia-make-all-files-GPL-2.0-only.patch b/SOURCES/0004-netdrv-net-aquantia-make-all-files-GPL-2.0-only.patch new file mode 100644 index 0000000..5e8b823 --- /dev/null +++ b/SOURCES/0004-netdrv-net-aquantia-make-all-files-GPL-2.0-only.patch @@ -0,0 +1,84 @@ +From 3f74c7e0d6347662397788ab7c28f228bfb3598d Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:21 -0500 +Subject: [PATCH 004/139] [netdrv] net: aquantia: make all files GPL-2.0-only + +Message-id: <1604687916-15087-5-git-send-email-irusskik@redhat.com> +Patchwork-id: 338460 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 004/139] net: aquantia: make all files GPL-2.0-only +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 17f54a3bf540690ac4b6f9e9e6d69fc9baf465d9 +Author: Igor Russkikh +Date: Wed Jun 26 12:35:40 2019 +0000 + + net: aquantia: make all files GPL-2.0-only + + It was noticed some files had -or-later, however overall driver has + -only license. Clean this up. + + Signed-off-by: Igor Russkikh + Reviewed-by: Andrew Lunn + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c | 2 +- + drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.h | 2 +- + drivers/net/ethernet/aquantia/atlantic/aq_filters.c | 2 +- + drivers/net/ethernet/aquantia/atlantic/aq_filters.h | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c +index adad6a7acabe..6da65099047d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later ++// SPDX-License-Identifier: GPL-2.0-only + /* Copyright (C) 2014-2019 aQuantia Corporation. */ + + /* File aq_drvinfo.c: Definition of common code for firmware info in sys.*/ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.h b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.h +index 41fbb1358068..23a0487893a7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* Copyright (C) 2014-2017 aQuantia Corporation. */ + + /* File aq_drvinfo.h: Declaration of common code for firmware info in sys.*/ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c +index 1fff462a4175..440690b18734 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c +@@ -1,4 +1,4 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later ++// SPDX-License-Identifier: GPL-2.0-only + /* Copyright (C) 2014-2017 aQuantia Corporation. */ + + /* File aq_filters.c: RX filters related functions. */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_filters.h b/drivers/net/ethernet/aquantia/atlantic/aq_filters.h +index c6a08c6585d5..122e06c88a33 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_filters.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_filters.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* Copyright (C) 2014-2017 aQuantia Corporation. */ + + /* File aq_filters.h: RX filters related functions. */ +-- +2.13.6 + diff --git a/SOURCES/0005-netdrv-net-aquantia-added-vlan-offload-related-macro.patch b/SOURCES/0005-netdrv-net-aquantia-added-vlan-offload-related-macro.patch new file mode 100644 index 0000000..f9b3d9d --- /dev/null +++ b/SOURCES/0005-netdrv-net-aquantia-added-vlan-offload-related-macro.patch @@ -0,0 +1,138 @@ +From 1f902bdd64264c973b08200d6156e0ac63bcfe8b Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:22 -0500 +Subject: [PATCH 005/139] [netdrv] net: aquantia: added vlan offload related + macros and functions + +Message-id: <1604687916-15087-6-git-send-email-irusskik@redhat.com> +Patchwork-id: 338431 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 005/139] net: aquantia: added vlan offload related macros and functions +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 161dea83f1c7304403ceb66645f3acda47f997da +Author: Igor Russkikh +Date: Wed Jun 26 12:35:42 2019 +0000 + + net: aquantia: added vlan offload related macros and functions + + Register declaration macros required to work with vlan offload mode. + + Tested-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../aquantia/atlantic/hw_atl/hw_atl_b0_internal.h | 7 +++++++ + .../net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 16 ++++++++++++++++ + .../net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 5 +++++ + .../aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 18 ++++++++++++++++++ + 4 files changed, 46 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +index e4ba2ccf9830..808d8cd4252a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +@@ -107,10 +107,17 @@ + #define HW_ATL_B0_RXD_NCEA0 (0x1) + + #define HW_ATL_B0_RXD_WB_STAT_RSSTYPE (0x0000000F) ++#define HW_ATL_B0_RXD_WB_STAT_RSSTYPE_SHIFT (0x0) + #define HW_ATL_B0_RXD_WB_STAT_PKTTYPE (0x00000FF0) ++#define HW_ATL_B0_RXD_WB_STAT_PKTTYPE_SHIFT (0x4) + #define HW_ATL_B0_RXD_WB_STAT_RXCTRL (0x00180000) ++#define HW_ATL_B0_RXD_WB_STAT_RXCTRL_SHIFT (0x13) + #define HW_ATL_B0_RXD_WB_STAT_SPLHDR (0x00200000) + #define HW_ATL_B0_RXD_WB_STAT_HDRLEN (0xFFC00000) ++#define HW_ATL_B0_RXD_WB_STAT_HDRLEN_SHIFT (0x16) ++ ++#define HW_ATL_B0_RXD_WB_PKTTYPE_VLAN BIT(5) ++#define HW_ATL_B0_RXD_WB_PKTTYPE_VLAN_DOUBLE BIT(6) + + #define HW_ATL_B0_RXD_WB_STAT2_DD (0x0001) + #define HW_ATL_B0_RXD_WB_STAT2_EOP (0x0002) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index 451529069f28..1149812ae463 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -1004,6 +1004,22 @@ void hw_atl_rpo_rx_desc_vlan_stripping_set(struct aq_hw_s *aq_hw, + rx_desc_vlan_stripping); + } + ++void hw_atl_rpo_outer_vlan_tag_mode_set(void *context, ++ u32 outervlantagmode) ++{ ++ aq_hw_write_reg_bit(context, HW_ATL_RPO_OUTER_VL_INS_MODE_ADR, ++ HW_ATL_RPO_OUTER_VL_INS_MODE_MSK, ++ HW_ATL_RPO_OUTER_VL_INS_MODE_SHIFT, ++ outervlantagmode); ++} ++ ++u32 hw_atl_rpo_outer_vlan_tag_mode_get(void *context) ++{ ++ return aq_hw_read_reg_bit(context, HW_ATL_RPO_OUTER_VL_INS_MODE_ADR, ++ HW_ATL_RPO_OUTER_VL_INS_MODE_MSK, ++ HW_ATL_RPO_OUTER_VL_INS_MODE_SHIFT); ++} ++ + void hw_atl_rpo_tcp_udp_crc_offload_en_set(struct aq_hw_s *aq_hw, + u32 tcp_udp_crc_offload_en) + { +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index 34b42ce43512..0c37abbabca5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -488,6 +488,11 @@ void hw_atl_rpo_rx_desc_vlan_stripping_set(struct aq_hw_s *aq_hw, + u32 rx_desc_vlan_stripping, + u32 descriptor); + ++void hw_atl_rpo_outer_vlan_tag_mode_set(void *context, ++ u32 outervlantagmode); ++ ++u32 hw_atl_rpo_outer_vlan_tag_mode_get(void *context); ++ + /* set tcp/udp checksum offload enable */ + void hw_atl_rpo_tcp_udp_crc_offload_en_set(struct aq_hw_s *aq_hw, + u32 tcp_udp_crc_offload_en); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +index fc1446f737bb..c3febcdfa92e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +@@ -1383,6 +1383,24 @@ + /* default value of bitfield l4_chk_en */ + #define HW_ATL_RPOL4CHK_EN_DEFAULT 0x0 + ++/* RX outer_vl_ins_mode Bitfield Definitions ++ * Preprocessor definitions for the bitfield "outer_vl_ins_mode". ++ * PORT="pif_rpo_outer_vl_mode_i" ++ */ ++ ++/* Register address for bitfield outer_vl_ins_mode */ ++#define HW_ATL_RPO_OUTER_VL_INS_MODE_ADR 0x00005580 ++/* Bitmask for bitfield outer_vl_ins_mode */ ++#define HW_ATL_RPO_OUTER_VL_INS_MODE_MSK 0x00000004 ++/* Inverted bitmask for bitfield outer_vl_ins_mode */ ++#define HW_ATL_RPO_OUTER_VL_INS_MODE_MSKN 0xFFFFFFFB ++/* Lower bit position of bitfield outer_vl_ins_mode */ ++#define HW_ATL_RPO_OUTER_VL_INS_MODE_SHIFT 2 ++/* Width of bitfield outer_vl_ins_mode */ ++#define HW_ATL_RPO_OUTER_VL_INS_MODE_WIDTH 1 ++/* Default value of bitfield outer_vl_ins_mode */ ++#define HW_ATL_RPO_OUTER_VL_INS_MODE_DEFAULT 0x0 ++ + /* rx reg_res_dsbl bitfield definitions + * preprocessor definitions for the bitfield "reg_res_dsbl". + * port="pif_rx_reg_res_dsbl_i" +-- +2.13.6 + diff --git a/SOURCES/0006-netdrv-net-aquantia-adding-fields-and-device-feature.patch b/SOURCES/0006-netdrv-net-aquantia-adding-fields-and-device-feature.patch new file mode 100644 index 0000000..4edfbb7 --- /dev/null +++ b/SOURCES/0006-netdrv-net-aquantia-adding-fields-and-device-feature.patch @@ -0,0 +1,199 @@ +From 8d5054035ac45d4710a9b0495caa1cf99577f76c Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:23 -0500 +Subject: [PATCH 006/139] [netdrv] net: aquantia: adding fields and device + features for vlan offload + +Message-id: <1604687916-15087-7-git-send-email-irusskik@redhat.com> +Patchwork-id: 338436 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 006/139] net: aquantia: adding fields and device features for vlan offload +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit d3ed7c5cf79bb9099c9a3fc5c1d90b51d13a4453 +Author: Igor Russkikh +Date: Wed Jun 26 12:35:44 2019 +0000 + + net: aquantia: adding fields and device features for vlan offload + + Updating features and vlan_features with vlan HW offload. + Added vlan_tag fields to rx/tx ring_buff to track vlan related data. + + Tested-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 9 ++++++--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 2 ++ + drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 9 ++++++--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 2 +- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 10 +++++++--- + 5 files changed, 22 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 41172fbebddd..d2d23491d0b1 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -126,6 +126,8 @@ void aq_nic_cfg_start(struct aq_nic_s *self) + + cfg->link_speed_msk &= cfg->aq_hw_caps->link_speed_msk; + cfg->features = cfg->aq_hw_caps->hw_features; ++ cfg->is_vlan_rx_strip = !!(cfg->features & NETIF_F_HW_VLAN_CTAG_RX); ++ cfg->is_vlan_tx_insert = !!(cfg->features & NETIF_F_HW_VLAN_CTAG_TX); + cfg->is_vlan_force_promisc = true; + } + +@@ -286,7 +288,8 @@ void aq_nic_ndev_init(struct aq_nic_s *self) + self->ndev->hw_features |= aq_hw_caps->hw_features; + self->ndev->features = aq_hw_caps->hw_features; + self->ndev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM | +- NETIF_F_RXHASH | NETIF_F_SG | NETIF_F_LRO; ++ NETIF_F_RXHASH | NETIF_F_SG | ++ NETIF_F_LRO | NETIF_F_TSO; + self->ndev->priv_flags = aq_hw_caps->hw_priv_flags; + self->ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + +@@ -435,7 +438,7 @@ static unsigned int aq_nic_map_skb(struct aq_nic_s *self, + dx_buff->len_l3 = ip_hdrlen(skb); + dx_buff->len_l4 = tcp_hdrlen(skb); + dx_buff->mss = skb_shinfo(skb)->gso_size; +- dx_buff->is_txc = 1U; ++ dx_buff->is_gso = 1U; + dx_buff->eop_index = 0xffffU; + + dx_buff->is_ipv6 = +@@ -535,7 +538,7 @@ static unsigned int aq_nic_map_skb(struct aq_nic_s *self, + --ret, dx = aq_ring_next_dx(ring, dx)) { + dx_buff = &ring->buff_ring[dx]; + +- if (!dx_buff->is_txc && dx_buff->pa) { ++ if (!dx_buff->is_gso && dx_buff->pa) { + if (unlikely(dx_buff->is_sop)) { + dma_unmap_single(aq_nic_get_dev(self), + dx_buff->pa, +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index 0f22f5d5691b..255b54a6ae07 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -35,6 +35,8 @@ struct aq_nic_cfg_s { + u32 flow_control; + u32 link_speed_msk; + u32 wol; ++ u8 is_vlan_rx_strip; ++ u8 is_vlan_tx_insert; + bool is_vlan_force_promisc; + u16 is_mc_list_enabled; + u16 mc_list_count; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +index 6bd67210d0b7..47abd09d06c2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +@@ -27,7 +27,7 @@ struct aq_rxpage { + * +----------+----------+----------+----------- + * 4/8bytes|len pkt |len pkt | | skb + * +----------+----------+----------+----------- +- * 4/8bytes|is_txc |len,flags |len |len,is_eop ++ * 4/8bytes|is_gso |len,flags |len |len,is_eop + * +----------+----------+----------+----------- + * + * This aq_ring_buff_s doesn't have endianness dependency. +@@ -44,6 +44,7 @@ struct __packed aq_ring_buff_s { + u8 is_hash_l4; + u8 rsvd1; + struct aq_rxpage rxdata; ++ u16 vlan_rx_tag; + }; + /* EOP */ + struct { +@@ -59,6 +60,7 @@ struct __packed aq_ring_buff_s { + u8 is_ipv6:1; + u8 rsvd2:7; + u32 len_pkt; ++ u16 vlan_tx_tag; + }; + }; + union { +@@ -70,11 +72,12 @@ struct __packed aq_ring_buff_s { + u32 is_cso_err:1; + u32 is_sop:1; + u32 is_eop:1; +- u32 is_txc:1; ++ u32 is_gso:1; + u32 is_mapped:1; + u32 is_cleaned:1; + u32 is_error:1; +- u32 rsvd3:6; ++ u32 is_vlan:1; ++ u32 rsvd3:5; + u16 eop_index; + u16 rsvd4; + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index 0f140a9fe404..359a4d387185 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -451,7 +451,7 @@ static int hw_atl_a0_hw_ring_tx_xmit(struct aq_hw_s *self, + + buff = &ring->buff_ring[ring->sw_tail]; + +- if (buff->is_txc) { ++ if (buff->is_gso) { + txd->ctl |= (buff->len_l3 << 31) | + (buff->len_l2 << 24) | + HW_ATL_A0_TXD_CTL_CMD_TCP | +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 13ac2661a473..8ead2a8d2893 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -40,7 +40,9 @@ + NETIF_F_TSO | \ + NETIF_F_LRO | \ + NETIF_F_NTUPLE | \ +- NETIF_F_HW_VLAN_CTAG_FILTER, \ ++ NETIF_F_HW_VLAN_CTAG_FILTER | \ ++ NETIF_F_HW_VLAN_CTAG_RX | \ ++ NETIF_F_HW_VLAN_CTAG_TX, \ + .hw_priv_flags = IFF_UNICAST_FLT, \ + .flow_control = true, \ + .mtu = HW_ATL_B0_MTU_JUMBO, \ +@@ -501,7 +503,7 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, + + buff = &ring->buff_ring[ring->sw_tail]; + +- if (buff->is_txc) { ++ if (buff->is_gso) { + txd->ctl |= (buff->len_l3 << 31) | + (buff->len_l2 << 24) | + HW_ATL_B0_TXD_CTL_CMD_TCP | +@@ -559,6 +561,7 @@ static int hw_atl_b0_hw_ring_rx_init(struct aq_hw_s *self, + { + u32 dma_desc_addr_lsw = (u32)aq_ring->dx_ring_pa; + u32 dma_desc_addr_msw = (u32)(((u64)aq_ring->dx_ring_pa) >> 32); ++ u32 vlan_rx_stripping = self->aq_nic_cfg->is_vlan_rx_strip; + + hw_atl_rdm_rx_desc_en_set(self, false, aq_ring->idx); + +@@ -578,7 +581,8 @@ static int hw_atl_b0_hw_ring_rx_init(struct aq_hw_s *self, + + hw_atl_rdm_rx_desc_head_buff_size_set(self, 0U, aq_ring->idx); + hw_atl_rdm_rx_desc_head_splitting_set(self, 0U, aq_ring->idx); +- hw_atl_rpo_rx_desc_vlan_stripping_set(self, 0U, aq_ring->idx); ++ hw_atl_rpo_rx_desc_vlan_stripping_set(self, !!vlan_rx_stripping, ++ aq_ring->idx); + + /* Rx ring set mode */ + +-- +2.13.6 + diff --git a/SOURCES/0007-netdrv-net-aquantia-vlan-offloads-logic-in-datapath.patch b/SOURCES/0007-netdrv-net-aquantia-vlan-offloads-logic-in-datapath.patch new file mode 100644 index 0000000..a382a84 --- /dev/null +++ b/SOURCES/0007-netdrv-net-aquantia-vlan-offloads-logic-in-datapath.patch @@ -0,0 +1,241 @@ +From e9f9048e434b2dc20965537e7bc51c65951301bd Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:24 -0500 +Subject: [PATCH 007/139] [netdrv] net: aquantia: vlan offloads logic in + datapath + +Message-id: <1604687916-15087-8-git-send-email-irusskik@redhat.com> +Patchwork-id: 338432 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 007/139] net: aquantia: vlan offloads logic in datapath +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 880b3ca5043d16c887cc8ad22eb6831cace048b9 +Author: Igor Russkikh +Date: Wed Jun 26 12:35:46 2019 +0000 + + net: aquantia: vlan offloads logic in datapath + + Update datapath by adding logic related to hardware assisted + vlan strip/insert behaviour. + + Tested-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 23 +++++++--- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 4 ++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 52 ++++++++++++++++------ + 3 files changed, 60 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index d2d23491d0b1..e1392766e21e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -430,26 +430,37 @@ static unsigned int aq_nic_map_skb(struct aq_nic_s *self, + unsigned int dx = ring->sw_tail; + struct aq_ring_buff_s *first = NULL; + struct aq_ring_buff_s *dx_buff = &ring->buff_ring[dx]; ++ bool need_context_tag = false; ++ ++ dx_buff->flags = 0U; + + if (unlikely(skb_is_gso(skb))) { +- dx_buff->flags = 0U; ++ dx_buff->mss = skb_shinfo(skb)->gso_size; ++ dx_buff->is_gso = 1U; + dx_buff->len_pkt = skb->len; + dx_buff->len_l2 = ETH_HLEN; + dx_buff->len_l3 = ip_hdrlen(skb); + dx_buff->len_l4 = tcp_hdrlen(skb); +- dx_buff->mss = skb_shinfo(skb)->gso_size; +- dx_buff->is_gso = 1U; + dx_buff->eop_index = 0xffffU; +- + dx_buff->is_ipv6 = + (ip_hdr(skb)->version == 6) ? 1U : 0U; ++ need_context_tag = true; ++ } + ++ if (self->aq_nic_cfg.is_vlan_tx_insert && skb_vlan_tag_present(skb)) { ++ dx_buff->vlan_tx_tag = skb_vlan_tag_get(skb); ++ dx_buff->len_pkt = skb->len; ++ dx_buff->is_vlan = 1U; ++ need_context_tag = true; ++ } ++ ++ if (need_context_tag) { + dx = aq_ring_next_dx(ring, dx); + dx_buff = &ring->buff_ring[dx]; ++ dx_buff->flags = 0U; + ++ret; + } + +- dx_buff->flags = 0U; + dx_buff->len = skb_headlen(skb); + dx_buff->pa = dma_map_single(aq_nic_get_dev(self), + skb->data, +@@ -538,7 +549,7 @@ static unsigned int aq_nic_map_skb(struct aq_nic_s *self, + --ret, dx = aq_ring_next_dx(ring, dx)) { + dx_buff = &ring->buff_ring[dx]; + +- if (!dx_buff->is_gso && dx_buff->pa) { ++ if (!dx_buff->is_gso && !dx_buff->is_vlan && dx_buff->pa) { + if (unlikely(dx_buff->is_sop)) { + dma_unmap_single(aq_nic_get_dev(self), + dx_buff->pa, +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index 2a7b91ed17c5..3901d7994ca1 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -409,6 +409,10 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + } + } + ++ if (buff->is_vlan) ++ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ++ buff->vlan_rx_tag); ++ + skb->protocol = eth_type_trans(skb, ndev); + + aq_rx_checksum(self, buff, skb); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 8ead2a8d2893..30f7fc4c97ff 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -247,6 +247,9 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, + /* LSO offloads*/ + hw_atl_tdm_large_send_offload_en_set(self, 0xFFFFFFFFU); + ++ /* Outer VLAN tag offload */ ++ hw_atl_rpo_outer_vlan_tag_mode_set(self, 1U); ++ + /* LRO offloads */ + { + unsigned int val = (8U < HW_ATL_B0_LRO_RXD_MAX) ? 0x3U : +@@ -489,6 +492,7 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, + unsigned int buff_pa_len = 0U; + unsigned int pkt_len = 0U; + unsigned int frag_count = 0U; ++ bool is_vlan = false; + bool is_gso = false; + + buff = &ring->buff_ring[ring->sw_tail]; +@@ -504,35 +508,43 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, + buff = &ring->buff_ring[ring->sw_tail]; + + if (buff->is_gso) { ++ txd->ctl |= HW_ATL_B0_TXD_CTL_CMD_TCP; ++ txd->ctl |= HW_ATL_B0_TXD_CTL_DESC_TYPE_TXC; + txd->ctl |= (buff->len_l3 << 31) | +- (buff->len_l2 << 24) | +- HW_ATL_B0_TXD_CTL_CMD_TCP | +- HW_ATL_B0_TXD_CTL_DESC_TYPE_TXC; +- txd->ctl2 |= (buff->mss << 16) | +- (buff->len_l4 << 8) | +- (buff->len_l3 >> 1); ++ (buff->len_l2 << 24); ++ txd->ctl2 |= (buff->mss << 16); ++ is_gso = true; + + pkt_len -= (buff->len_l4 + + buff->len_l3 + + buff->len_l2); +- is_gso = true; +- + if (buff->is_ipv6) + txd->ctl |= HW_ATL_B0_TXD_CTL_CMD_IPV6; +- } else { ++ txd->ctl2 |= (buff->len_l4 << 8) | ++ (buff->len_l3 >> 1); ++ } ++ if (buff->is_vlan) { ++ txd->ctl |= HW_ATL_B0_TXD_CTL_DESC_TYPE_TXC; ++ txd->ctl |= buff->vlan_tx_tag << 4; ++ is_vlan = true; ++ } ++ if (!buff->is_gso && !buff->is_vlan) { + buff_pa_len = buff->len; + + txd->buf_addr = buff->pa; + txd->ctl |= (HW_ATL_B0_TXD_CTL_BLEN & + ((u32)buff_pa_len << 4)); + txd->ctl |= HW_ATL_B0_TXD_CTL_DESC_TYPE_TXD; ++ + /* PAY_LEN */ + txd->ctl2 |= HW_ATL_B0_TXD_CTL2_LEN & (pkt_len << 14); + +- if (is_gso) { +- txd->ctl |= HW_ATL_B0_TXD_CTL_CMD_LSO; ++ if (is_gso || is_vlan) { ++ /* enable tx context */ + txd->ctl2 |= HW_ATL_B0_TXD_CTL2_CTX_EN; + } ++ if (is_gso) ++ txd->ctl |= HW_ATL_B0_TXD_CTL_CMD_LSO; + + /* Tx checksum offloads */ + if (buff->is_ip_cso) +@@ -541,13 +553,16 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, + if (buff->is_udp_cso || buff->is_tcp_cso) + txd->ctl |= HW_ATL_B0_TXD_CTL_CMD_TUCSO; + ++ if (is_vlan) ++ txd->ctl |= HW_ATL_B0_TXD_CTL_CMD_VLAN; ++ + if (unlikely(buff->is_eop)) { + txd->ctl |= HW_ATL_B0_TXD_CTL_EOP; + txd->ctl |= HW_ATL_B0_TXD_CTL_CMD_WB; + is_gso = false; ++ is_vlan = false; + } + } +- + ring->sw_tail = aq_ring_next_dx(ring, ring->sw_tail); + } + +@@ -685,11 +700,15 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self, + + buff = &ring->buff_ring[ring->hw_head]; + ++ buff->flags = 0U; ++ buff->is_hash_l4 = 0U; ++ + rx_stat = (0x0000003CU & rxd_wb->status) >> 2; + + is_rx_check_sum_enabled = (rxd_wb->type >> 19) & 0x3U; + +- pkt_type = 0xFFU & (rxd_wb->type >> 4); ++ pkt_type = (rxd_wb->type & HW_ATL_B0_RXD_WB_STAT_PKTTYPE) >> ++ HW_ATL_B0_RXD_WB_STAT_PKTTYPE_SHIFT; + + if (is_rx_check_sum_enabled & BIT(0) && + (0x0U == (pkt_type & 0x3U))) +@@ -710,6 +729,13 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self, + buff->is_cso_err = 0U; + } + ++ if (self->aq_nic_cfg->is_vlan_rx_strip && ++ ((pkt_type & HW_ATL_B0_RXD_WB_PKTTYPE_VLAN) || ++ (pkt_type & HW_ATL_B0_RXD_WB_PKTTYPE_VLAN_DOUBLE))) { ++ buff->is_vlan = 1; ++ buff->vlan_rx_tag = le16_to_cpu(rxd_wb->vlan); ++ } ++ + if ((rx_stat & BIT(0)) || rxd_wb->type & 0x1000U) { + /* MAC error or DMA error */ + buff->is_error = 1U; +-- +2.13.6 + diff --git a/SOURCES/0008-netdrv-net-aquantia-implement-vlan-offload-configura.patch b/SOURCES/0008-netdrv-net-aquantia-implement-vlan-offload-configura.patch new file mode 100644 index 0000000..a354cf5 --- /dev/null +++ b/SOURCES/0008-netdrv-net-aquantia-implement-vlan-offload-configura.patch @@ -0,0 +1,103 @@ +From 765e85481b20c58eae36f9911ad6289ece7d618b Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:25 -0500 +Subject: [PATCH 008/139] [netdrv] net: aquantia: implement vlan offload + configuration + +Message-id: <1604687916-15087-9-git-send-email-irusskik@redhat.com> +Patchwork-id: 338434 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 008/139] net: aquantia: implement vlan offload configuration +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 04f207fb0c2fa768da1fd30642bb83554c46847f +Author: Igor Russkikh +Date: Wed Jun 26 12:35:49 2019 +0000 + + net: aquantia: implement vlan offload configuration + + set_features should update flags and reinit hardware if + vlan offload settings were changed. + + Signed-off-by: Igor Russkikh + Tested-by: Nikita Danilov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 34 +++++++++++++++++++----- + 1 file changed, 27 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index 4ebf083c51c5..b4a0fb281e69 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -112,11 +112,16 @@ static int aq_ndev_change_mtu(struct net_device *ndev, int new_mtu) + static int aq_ndev_set_features(struct net_device *ndev, + netdev_features_t features) + { ++ bool is_vlan_rx_strip = !!(features & NETIF_F_HW_VLAN_CTAG_RX); ++ bool is_vlan_tx_insert = !!(features & NETIF_F_HW_VLAN_CTAG_TX); + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *aq_cfg = aq_nic_get_cfg(aq_nic); ++ bool need_ndev_restart = false; ++ struct aq_nic_cfg_s *aq_cfg; + bool is_lro = false; + int err = 0; + ++ aq_cfg = aq_nic_get_cfg(aq_nic); ++ + if (!(features & NETIF_F_NTUPLE)) { + if (aq_nic->ndev->features & NETIF_F_NTUPLE) { + err = aq_clear_rxnfc_all_rules(aq_nic); +@@ -139,17 +144,32 @@ static int aq_ndev_set_features(struct net_device *ndev, + + if (aq_cfg->is_lro != is_lro) { + aq_cfg->is_lro = is_lro; +- +- if (netif_running(ndev)) { +- aq_ndev_close(ndev); +- aq_ndev_open(ndev); +- } ++ need_ndev_restart = true; + } + } +- if ((aq_nic->ndev->features ^ features) & NETIF_F_RXCSUM) ++ ++ if ((aq_nic->ndev->features ^ features) & NETIF_F_RXCSUM) { + err = aq_nic->aq_hw_ops->hw_set_offload(aq_nic->aq_hw, + aq_cfg); + ++ if (unlikely(err)) ++ goto err_exit; ++ } ++ ++ if (aq_cfg->is_vlan_rx_strip != is_vlan_rx_strip) { ++ aq_cfg->is_vlan_rx_strip = is_vlan_rx_strip; ++ need_ndev_restart = true; ++ } ++ if (aq_cfg->is_vlan_tx_insert != is_vlan_tx_insert) { ++ aq_cfg->is_vlan_tx_insert = is_vlan_tx_insert; ++ need_ndev_restart = true; ++ } ++ ++ if (need_ndev_restart && netif_running(ndev)) { ++ aq_ndev_close(ndev); ++ aq_ndev_open(ndev); ++ } ++ + err_exit: + return err; + } +-- +2.13.6 + diff --git a/SOURCES/0009-netdrv-net-aquantia-fix-removal-of-vlan-0.patch b/SOURCES/0009-netdrv-net-aquantia-fix-removal-of-vlan-0.patch new file mode 100644 index 0000000..ff66654 --- /dev/null +++ b/SOURCES/0009-netdrv-net-aquantia-fix-removal-of-vlan-0.patch @@ -0,0 +1,56 @@ +From fc8d11f19c19a9b47cf8d253a6f163a163511e66 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:26 -0500 +Subject: [PATCH 009/139] [netdrv] net: aquantia: fix removal of vlan 0 + +Message-id: <1604687916-15087-10-git-send-email-irusskik@redhat.com> +Patchwork-id: 338433 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 009/139] net: aquantia: fix removal of vlan 0 +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 6fdc060d7476ef73c8029b652d252c1a7b4de948 +Author: Dmitry Bogdanov +Date: Fri Aug 30 12:08:30 2019 +0000 + + net: aquantia: fix removal of vlan 0 + + Due to absence of checking against the rx flow rule when vlan 0 is being + removed, the other rule could be removed instead of the rule with vlan 0 + + Fixes: 7975d2aff5afb ("net: aquantia: add support of rx-vlan-filter offload") + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_filters.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c +index 440690b18734..b13704544a23 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c +@@ -431,7 +431,8 @@ int aq_del_fvlan_by_vlan(struct aq_nic_s *aq_nic, u16 vlan_id) + if (be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id) + break; + } +- if (rule && be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id) { ++ if (rule && rule->type == aq_rx_filter_vlan && ++ be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id) { + struct ethtool_rxnfc cmd; + + cmd.fs.location = rule->aq_fsp.location; +-- +2.13.6 + diff --git a/SOURCES/0010-netdrv-net-aquantia-fix-limit-of-vlan-filters.patch b/SOURCES/0010-netdrv-net-aquantia-fix-limit-of-vlan-filters.patch new file mode 100644 index 0000000..c98de0a --- /dev/null +++ b/SOURCES/0010-netdrv-net-aquantia-fix-limit-of-vlan-filters.patch @@ -0,0 +1,55 @@ +From dd499904538592d7ca8d7764b02b12bc0b098f2a Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:27 -0500 +Subject: [PATCH 010/139] [netdrv] net: aquantia: fix limit of vlan filters + +Message-id: <1604687916-15087-11-git-send-email-irusskik@redhat.com> +Patchwork-id: 338437 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 010/139] net: aquantia: fix limit of vlan filters +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 392349f60110dc2c3daf86464fd926afc53d6143 +Author: Dmitry Bogdanov +Date: Fri Aug 30 12:08:33 2019 +0000 + + net: aquantia: fix limit of vlan filters + + Fix a limit condition of vlans on the interface before setting vlan + promiscuous mode + + Fixes: 48dd73d08d4dd ("net: aquantia: fix vlans not working over bridged network") + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_filters.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c +index b13704544a23..aee827f07c16 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c +@@ -844,7 +844,7 @@ int aq_filters_vlans_update(struct aq_nic_s *aq_nic) + return err; + + if (aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) { +- if (hweight < AQ_VLAN_MAX_FILTERS && hweight > 0) { ++ if (hweight <= AQ_VLAN_MAX_FILTERS && hweight > 0) { + err = aq_hw_ops->hw_filter_vlan_ctrl(aq_hw, + !(aq_nic->packet_filter & IFF_PROMISC)); + aq_nic->aq_nic_cfg.is_vlan_force_promisc = false; +-- +2.13.6 + diff --git a/SOURCES/0011-netdrv-net-aquantia-linkstate-irq-should-be-oneshot.patch b/SOURCES/0011-netdrv-net-aquantia-linkstate-irq-should-be-oneshot.patch new file mode 100644 index 0000000..3a32cc2 --- /dev/null +++ b/SOURCES/0011-netdrv-net-aquantia-linkstate-irq-should-be-oneshot.patch @@ -0,0 +1,66 @@ +From f30e80d55daf9076a95b661bb1ea9d9a00d8b8fb Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:28 -0500 +Subject: [PATCH 011/139] [netdrv] net: aquantia: linkstate irq should be + oneshot + +Message-id: <1604687916-15087-12-git-send-email-irusskik@redhat.com> +Patchwork-id: 338435 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 011/139] net: aquantia: linkstate irq should be oneshot +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 5c47e3ba6fe52465603cf9d816b3371e6881d649 +Author: Igor Russkikh +Date: Fri Aug 30 12:08:36 2019 +0000 + + net: aquantia: linkstate irq should be oneshot + + Declaring threaded irq handler should also indicate the irq is + oneshot. It is oneshot indeed, because HW implements irq automasking + on trigger. + + Not declaring this causes some kernel configurations to fail + on interface up, because request_threaded_irq returned an err code. + + The issue was originally hidden on normal x86_64 configuration with + latest kernel, because depending on interrupt controller, irq driver + added ONESHOT flag on its own. + + Issue was observed on older kernels (4.14) where no such logic exists. + + Fixes: 4c83f170b3ac ("net: aquantia: link status irq handling") + Signed-off-by: Igor Russkikh + Reported-by: Michael Symolkin + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index e1392766e21e..8f66e7817811 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -393,7 +393,7 @@ int aq_nic_start(struct aq_nic_s *self) + self->aq_nic_cfg.link_irq_vec); + err = request_threaded_irq(irqvec, NULL, + aq_linkstate_threaded_isr, +- IRQF_SHARED, ++ IRQF_SHARED | IRQF_ONESHOT, + self->ndev->name, self); + if (err < 0) + goto err_exit; +-- +2.13.6 + diff --git a/SOURCES/0012-netdrv-net-aquantia-fix-out-of-memory-condition-on-r.patch b/SOURCES/0012-netdrv-net-aquantia-fix-out-of-memory-condition-on-r.patch new file mode 100644 index 0000000..80fc21a --- /dev/null +++ b/SOURCES/0012-netdrv-net-aquantia-fix-out-of-memory-condition-on-r.patch @@ -0,0 +1,78 @@ +From 932ad5d965a7ed50fd53f7869ad72e695b6c9906 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:29 -0500 +Subject: [PATCH 012/139] [netdrv] net: aquantia: fix out of memory condition + on rx side + +Message-id: <1604687916-15087-13-git-send-email-irusskik@redhat.com> +Patchwork-id: 338438 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 012/139] net: aquantia: fix out of memory condition on rx side +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit be6cef69ba570ebb327eba1ef6438f7af49aaf86 +Author: Dmitry Bogdanov +Date: Fri Aug 30 12:08:38 2019 +0000 + + net: aquantia: fix out of memory condition on rx side + + On embedded environments with hard memory limits it is a normal although + rare case when skb can't be allocated on rx part under high traffic. + + In such OOM cases napi_complete_done() was not called. + So the napi object became in an invalid state like it is "scheduled". + Kernel do not re-schedules the poll of that napi object. + + Consequently, kernel can not remove that object the system hangs on + `ifconfig down` waiting for a poll. + + We are fixing this by gracefully closing napi poll routine with correct + invocation of napi_complete_done. + + This was reproduced with artificially failing the allocation of skb to + simulate an "out of memory" error case and check that traffic does + not get stuck. + + Fixes: 970a2e9864b0 ("net: ethernet: aquantia: Vector operations") + Signed-off-by: Igor Russkikh + Signed-off-by: Dmitry Bogdanov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +index 715685aa48c3..28892b8acd0e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +@@ -86,6 +86,7 @@ static int aq_vec_poll(struct napi_struct *napi, int budget) + } + } + ++err_exit: + if (!was_tx_cleaned) + work_done = budget; + +@@ -95,7 +96,7 @@ static int aq_vec_poll(struct napi_struct *napi, int budget) + 1U << self->aq_ring_param.vec_idx); + } + } +-err_exit: ++ + return work_done; + } + +-- +2.13.6 + diff --git a/SOURCES/0013-netdrv-net-aquantia-Fix-aq_vec_isr_legacy-return-val.patch b/SOURCES/0013-netdrv-net-aquantia-Fix-aq_vec_isr_legacy-return-val.patch new file mode 100644 index 0000000..5a01720 --- /dev/null +++ b/SOURCES/0013-netdrv-net-aquantia-Fix-aq_vec_isr_legacy-return-val.patch @@ -0,0 +1,86 @@ +From 1efbf20806c2b42accd54637cf66159e32e7df42 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:30 -0500 +Subject: [PATCH 013/139] [netdrv] net: aquantia: Fix aq_vec_isr_legacy() + return value + +Message-id: <1604687916-15087-14-git-send-email-irusskik@redhat.com> +Patchwork-id: 338440 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 013/139] net: aquantia: Fix aq_vec_isr_legacy() return value +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 31aefe14bc9f56566041303d733fda511d3a1c3e +Author: Dan Carpenter +Date: Wed Sep 25 13:54:30 2019 +0300 + + net: aquantia: Fix aq_vec_isr_legacy() return value + + The irqreturn_t type is an enum or an unsigned int in GCC. That + creates to problems because it can't detect if the + self->aq_hw_ops->hw_irq_read() call fails and at the end the function + always returns IRQ_HANDLED. + + drivers/net/ethernet/aquantia/atlantic/aq_vec.c:316 aq_vec_isr_legacy() warn: unsigned 'err' is never less than zero. + drivers/net/ethernet/aquantia/atlantic/aq_vec.c:329 aq_vec_isr_legacy() warn: always true condition '(err >= 0) => (0-u32max >= 0)' + + Fixes: 970a2e9864b0 ("net: ethernet: aquantia: Vector operations") + Signed-off-by: Dan Carpenter + Reviewed-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +index 28892b8acd0e..a95c263a45aa 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +@@ -306,15 +306,13 @@ irqreturn_t aq_vec_isr_legacy(int irq, void *private) + { + struct aq_vec_s *self = private; + u64 irq_mask = 0U; +- irqreturn_t err = 0; ++ int err; + +- if (!self) { +- err = -EINVAL; +- goto err_exit; +- } ++ if (!self) ++ return IRQ_NONE; + err = self->aq_hw_ops->hw_irq_read(self->aq_hw, &irq_mask); + if (err < 0) +- goto err_exit; ++ return IRQ_NONE; + + if (irq_mask) { + self->aq_hw_ops->hw_irq_disable(self->aq_hw, +@@ -322,11 +320,10 @@ irqreturn_t aq_vec_isr_legacy(int irq, void *private) + napi_schedule(&self->napi); + } else { + self->aq_hw_ops->hw_irq_enable(self->aq_hw, 1U); +- err = IRQ_NONE; ++ return IRQ_NONE; + } + +-err_exit: +- return err >= 0 ? IRQ_HANDLED : IRQ_NONE; ++ return IRQ_HANDLED; + } + + cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self) +-- +2.13.6 + diff --git a/SOURCES/0014-netdrv-net-aquantia-temperature-retrieval-fix.patch b/SOURCES/0014-netdrv-net-aquantia-temperature-retrieval-fix.patch new file mode 100644 index 0000000..d5d2458 --- /dev/null +++ b/SOURCES/0014-netdrv-net-aquantia-temperature-retrieval-fix.patch @@ -0,0 +1,60 @@ +From 395e73945b1175ddcc414d092a049d9bf7ef5691 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:31 -0500 +Subject: [PATCH 014/139] [netdrv] net: aquantia: temperature retrieval fix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Message-id: <1604687916-15087-15-git-send-email-irusskik@redhat.com> +Patchwork-id: 338441 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 014/139] net: aquantia: temperature retrieval fix +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 06b0d7fe7e5ff3ba4c7e265ef41135e8bcc232bb +Author: Igor Russkikh +Date: Fri Oct 11 13:45:19 2019 +0000 + + net: aquantia: temperature retrieval fix + + Chip temperature is a two byte word, colocated internally with cable + length data. We do all readouts from HW memory by dwords, thus + we should clear extra high bytes, otherwise temperature output + gets weird as soon as we attach a cable to the NIC. + + Fixes: 8f8940118654 ("net: aquantia: add infrastructure to readout chip temperature") + Tested-by: Holger Hoffstätte + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index da726489e3c8..7bc51f8d6f2f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -337,7 +337,7 @@ static int aq_fw2x_get_phy_temp(struct aq_hw_s *self, int *temp) + /* Convert PHY temperature from 1/256 degree Celsius + * to 1/1000 degree Celsius. + */ +- *temp = temp_res * 1000 / 256; ++ *temp = (temp_res & 0xFFFF) * 1000 / 256; + + return 0; + } +-- +2.13.6 + diff --git a/SOURCES/0015-netdrv-net-aquantia-when-cleaning-hw-cache-it-should.patch b/SOURCES/0015-netdrv-net-aquantia-when-cleaning-hw-cache-it-should.patch new file mode 100644 index 0000000..6b7b7ac --- /dev/null +++ b/SOURCES/0015-netdrv-net-aquantia-when-cleaning-hw-cache-it-should.patch @@ -0,0 +1,162 @@ +From 3ecdc313cb9b8b33d30b5ea6803de0debbffaf5f Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:32 -0500 +Subject: [PATCH 015/139] [netdrv] net: aquantia: when cleaning hw cache it + should be toggled + +Message-id: <1604687916-15087-16-git-send-email-irusskik@redhat.com> +Patchwork-id: 338439 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 015/139] net: aquantia: when cleaning hw cache it should be toggled +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit ed4d81c4b3f28ccf624f11fd66f67aec5b58859c +Author: Igor Russkikh +Date: Fri Oct 11 13:45:20 2019 +0000 + + net: aquantia: when cleaning hw cache it should be toggled + + >From HW specification to correctly reset HW caches (this is a required + workaround when stopping the device), register bit should actually + be toggled. + + It was previosly always just set. Due to the way driver stops HW this + never actually caused any issues, but it still may, so cleaning this up. + + Fixes: 7a1bb49461b1 ("net: aquantia: fix potential IOMMU fault after driver unbind") + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 16 ++++++++++++++-- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 17 +++++++++++++++-- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 7 +++++-- + .../aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 19 +++++++++++++++++++ + 4 files changed, 53 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 30f7fc4c97ff..3459fadb7ddd 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -968,14 +968,26 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self) + + static int hw_atl_b0_hw_stop(struct aq_hw_s *self) + { ++ int err; ++ u32 val; ++ + hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK); + + /* Invalidate Descriptor Cache to prevent writing to the cached + * descriptors and to the data pointer of those descriptors + */ +- hw_atl_rdm_rx_dma_desc_cache_init_set(self, 1); ++ hw_atl_rdm_rx_dma_desc_cache_init_tgl(self); + +- return aq_hw_err_from_flags(self); ++ err = aq_hw_err_from_flags(self); ++ ++ if (err) ++ goto err_exit; ++ ++ readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, ++ self, val, val == 1, 1000U, 10000U); ++ ++err_exit: ++ return err; + } + + static int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index 1149812ae463..6f340695e6bd 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -606,12 +606,25 @@ void hw_atl_rpb_rx_flow_ctl_mode_set(struct aq_hw_s *aq_hw, u32 rx_flow_ctl_mode + HW_ATL_RPB_RX_FC_MODE_SHIFT, rx_flow_ctl_mode); + } + +-void hw_atl_rdm_rx_dma_desc_cache_init_set(struct aq_hw_s *aq_hw, u32 init) ++void hw_atl_rdm_rx_dma_desc_cache_init_tgl(struct aq_hw_s *aq_hw) + { ++ u32 val; ++ ++ val = aq_hw_read_reg_bit(aq_hw, HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_ADR, ++ HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSK, ++ HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_SHIFT); ++ + aq_hw_write_reg_bit(aq_hw, HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_ADR, + HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSK, + HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_SHIFT, +- init); ++ val ^ 1); ++} ++ ++u32 hw_atl_rdm_rx_dma_desc_cache_init_done_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg_bit(aq_hw, RDM_RX_DMA_DESC_CACHE_INIT_DONE_ADR, ++ RDM_RX_DMA_DESC_CACHE_INIT_DONE_MSK, ++ RDM_RX_DMA_DESC_CACHE_INIT_DONE_SHIFT); + } + + void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index 0c37abbabca5..c3ee278c3747 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -313,8 +313,11 @@ void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, + u32 rx_pkt_buff_size_per_tc, + u32 buffer); + +-/* set rdm rx dma descriptor cache init */ +-void hw_atl_rdm_rx_dma_desc_cache_init_set(struct aq_hw_s *aq_hw, u32 init); ++/* toggle rdm rx dma descriptor cache init */ ++void hw_atl_rdm_rx_dma_desc_cache_init_tgl(struct aq_hw_s *aq_hw); ++ ++/* get rdm rx dma descriptor cache init done */ ++u32 hw_atl_rdm_rx_dma_desc_cache_init_done_get(struct aq_hw_s *aq_hw); + + /* set rx xoff enable (per tc) */ + void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, u32 rx_xoff_en_per_tc, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +index c3febcdfa92e..35887ad89025 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +@@ -318,6 +318,25 @@ + /* default value of bitfield rdm_desc_init_i */ + #define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_DEFAULT 0x0 + ++/* rdm_desc_init_done_i bitfield definitions ++ * preprocessor definitions for the bitfield rdm_desc_init_done_i. ++ * port="pif_rdm_desc_init_done_i" ++ */ ++ ++/* register address for bitfield rdm_desc_init_done_i */ ++#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_ADR 0x00005a10 ++/* bitmask for bitfield rdm_desc_init_done_i */ ++#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_MSK 0x00000001U ++/* inverted bitmask for bitfield rdm_desc_init_done_i */ ++#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_MSKN 0xfffffffe ++/* lower bit position of bitfield rdm_desc_init_done_i */ ++#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_SHIFT 0U ++/* width of bitfield rdm_desc_init_done_i */ ++#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_WIDTH 1 ++/* default value of bitfield rdm_desc_init_done_i */ ++#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_DEFAULT 0x0 ++ ++ + /* rx int_desc_wrb_en bitfield definitions + * preprocessor definitions for the bitfield "int_desc_wrb_en". + * port="pif_rdm_int_desc_wrb_en_i" +-- +2.13.6 + diff --git a/SOURCES/0016-netdrv-net-aquantia-do-not-pass-lro-session-with-inv.patch b/SOURCES/0016-netdrv-net-aquantia-do-not-pass-lro-session-with-inv.patch new file mode 100644 index 0000000..936c363 --- /dev/null +++ b/SOURCES/0016-netdrv-net-aquantia-do-not-pass-lro-session-with-inv.patch @@ -0,0 +1,70 @@ +From ddccc2338e49e1880ea9664420c494b9254fb497 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:33 -0500 +Subject: [PATCH 016/139] [netdrv] net: aquantia: do not pass lro session with + invalid tcp checksum + +Message-id: <1604687916-15087-17-git-send-email-irusskik@redhat.com> +Patchwork-id: 338443 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 016/139] net: aquantia: do not pass lro session with invalid tcp checksum +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit d08b9a0a3ebdf71b0aabe576c7dd48e57e80e0f0 +Author: Dmitry Bogdanov +Date: Fri Oct 11 13:45:22 2019 +0000 + + net: aquantia: do not pass lro session with invalid tcp checksum + + Individual descriptors on LRO TCP session should be checked + for CRC errors. It was discovered that HW recalculates + L4 checksums on LRO session and does not break it up on bad L4 + csum. + + Thus, driver should aggregate HW LRO L4 statuses from all individual + buffers of LRO session and drop packet if one of the buffers has bad + L4 checksum. + + Fixes: f38f1ee8aeb2 ("net: aquantia: check rx csum for all packets in LRO session") + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index 3901d7994ca1..76bdbe1596d6 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -313,6 +313,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + break; + + buff->is_error |= buff_->is_error; ++ buff->is_cso_err |= buff_->is_cso_err; + + } while (!buff_->is_eop); + +@@ -320,7 +321,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + err = 0; + goto err_exit; + } +- if (buff->is_error) { ++ if (buff->is_error || buff->is_cso_err) { + buff_ = buff; + do { + next_ = buff_->next, +-- +2.13.6 + diff --git a/SOURCES/0017-netdrv-net-aquantia-correctly-handle-macvlan-and-mul.patch b/SOURCES/0017-netdrv-net-aquantia-correctly-handle-macvlan-and-mul.patch new file mode 100644 index 0000000..ec0a843 --- /dev/null +++ b/SOURCES/0017-netdrv-net-aquantia-correctly-handle-macvlan-and-mul.patch @@ -0,0 +1,147 @@ +From af62980c29f1c626dd6b1c9869333c7a0ed21cb4 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:34 -0500 +Subject: [PATCH 017/139] [netdrv] net: aquantia: correctly handle macvlan and + multicast coexistence + +Message-id: <1604687916-15087-18-git-send-email-irusskik@redhat.com> +Patchwork-id: 338442 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 017/139] net: aquantia: correctly handle macvlan and multicast coexistence +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 9f051db566da1e8110659ab4ab188af1c2510bb4 +Author: Dmitry Bogdanov +Date: Fri Oct 11 13:45:23 2019 +0000 + + net: aquantia: correctly handle macvlan and multicast coexistence + + macvlan and multicast handling is now mixed up. + The explicit issue is that macvlan interface gets broken (no traffic) + after clearing MULTICAST flag on the real interface. + + We now do separate logic and consider both ALLMULTI and MULTICAST + flags on the device. + + Fixes: 11ba961c9161 ("net: aquantia: Fix IFF_ALLMULTI flag functionality") + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 4 +-- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 32 +++++++++++----------- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 7 +++-- + 3 files changed, 21 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index b4a0fb281e69..bb65dd39f847 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -194,9 +194,7 @@ static void aq_ndev_set_multicast_settings(struct net_device *ndev) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); + +- aq_nic_set_packet_filter(aq_nic, ndev->flags); +- +- aq_nic_set_multicast_list(aq_nic, ndev); ++ (void)aq_nic_set_multicast_list(aq_nic, ndev); + } + + static int aq_ndo_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 8f66e7817811..2a18439b36fb 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -631,9 +631,12 @@ int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags) + + int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev) + { +- unsigned int packet_filter = self->packet_filter; ++ const struct aq_hw_ops *hw_ops = self->aq_hw_ops; ++ struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; ++ unsigned int packet_filter = ndev->flags; + struct netdev_hw_addr *ha = NULL; + unsigned int i = 0U; ++ int err = 0; + + self->mc_list.count = 0; + if (netdev_uc_count(ndev) > AQ_HW_MULTICAST_ADDRESS_MAX) { +@@ -641,29 +644,26 @@ int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev) + } else { + netdev_for_each_uc_addr(ha, ndev) { + ether_addr_copy(self->mc_list.ar[i++], ha->addr); +- +- if (i >= AQ_HW_MULTICAST_ADDRESS_MAX) +- break; + } + } + +- if (i + netdev_mc_count(ndev) > AQ_HW_MULTICAST_ADDRESS_MAX) { +- packet_filter |= IFF_ALLMULTI; +- } else { +- netdev_for_each_mc_addr(ha, ndev) { +- ether_addr_copy(self->mc_list.ar[i++], ha->addr); +- +- if (i >= AQ_HW_MULTICAST_ADDRESS_MAX) +- break; ++ cfg->is_mc_list_enabled = !!(packet_filter & IFF_MULTICAST); ++ if (cfg->is_mc_list_enabled) { ++ if (i + netdev_mc_count(ndev) > AQ_HW_MULTICAST_ADDRESS_MAX) { ++ packet_filter |= IFF_ALLMULTI; ++ } else { ++ netdev_for_each_mc_addr(ha, ndev) { ++ ether_addr_copy(self->mc_list.ar[i++], ++ ha->addr); ++ } + } + } + + if (i > 0 && i <= AQ_HW_MULTICAST_ADDRESS_MAX) { +- packet_filter |= IFF_MULTICAST; + self->mc_list.count = i; +- self->aq_hw_ops->hw_multicast_list_set(self->aq_hw, +- self->mc_list.ar, +- self->mc_list.count); ++ err = hw_ops->hw_multicast_list_set(self->aq_hw, ++ self->mc_list.ar, ++ self->mc_list.count); + } + return aq_nic_set_packet_filter(self, packet_filter); + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 3459fadb7ddd..2ad3fa6316ce 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -818,14 +818,15 @@ static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self, + cfg->is_vlan_force_promisc); + + hw_atl_rpfl2multicast_flr_en_set(self, +- IS_FILTER_ENABLED(IFF_ALLMULTI), 0); ++ IS_FILTER_ENABLED(IFF_ALLMULTI) && ++ IS_FILTER_ENABLED(IFF_MULTICAST), 0); + + hw_atl_rpfl2_accept_all_mc_packets_set(self, +- IS_FILTER_ENABLED(IFF_ALLMULTI)); ++ IS_FILTER_ENABLED(IFF_ALLMULTI) && ++ IS_FILTER_ENABLED(IFF_MULTICAST)); + + hw_atl_rpfl2broadcast_en_set(self, IS_FILTER_ENABLED(IFF_BROADCAST)); + +- cfg->is_mc_list_enabled = IS_FILTER_ENABLED(IFF_MULTICAST); + + for (i = HW_ATL_B0_MAC_MIN; i < HW_ATL_B0_MAC_MAX; ++i) + hw_atl_rpfl2_uc_flr_en_set(self, +-- +2.13.6 + diff --git a/SOURCES/0018-netdrv-net-aquantia-add-an-error-handling-in-aq_nic_.patch b/SOURCES/0018-netdrv-net-aquantia-add-an-error-handling-in-aq_nic_.patch new file mode 100644 index 0000000..683ef87 --- /dev/null +++ b/SOURCES/0018-netdrv-net-aquantia-add-an-error-handling-in-aq_nic_.patch @@ -0,0 +1,57 @@ +From 14dcc60332a3d782f23e72672fa012865e86e629 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:35 -0500 +Subject: [PATCH 018/139] [netdrv] net: aquantia: add an error handling in + aq_nic_set_multicast_list + +Message-id: <1604687916-15087-19-git-send-email-irusskik@redhat.com> +Patchwork-id: 338444 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 018/139] net: aquantia: add an error handling in aq_nic_set_multicast_list +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 3d00cf2fbb61212f47a3cf838be51c921366c937 +Author: Chenwandun +Date: Fri Oct 18 18:20:37 2019 +0800 + + net: aquantia: add an error handling in aq_nic_set_multicast_list + + add an error handling in aq_nic_set_multicast_list, it may not + work when hw_multicast_list_set error; and at the same time + it will remove gcc Wunused-but-set-variable warning. + + Signed-off-by: Chenwandun + Reviewed-by: Igor Russkikh + Reviewed-by: Andrew Lunn + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 2a18439b36fb..137c1de4c6ec 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -664,6 +664,8 @@ int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev) + err = hw_ops->hw_multicast_list_set(self->aq_hw, + self->mc_list.ar, + self->mc_list.count); ++ if (err < 0) ++ return err; + } + return aq_nic_set_packet_filter(self, packet_filter); + } +-- +2.13.6 + diff --git a/SOURCES/0019-netdrv-net-aquantia-PTP-skeleton-declarations-and-ca.patch b/SOURCES/0019-netdrv-net-aquantia-PTP-skeleton-declarations-and-ca.patch new file mode 100644 index 0000000..eeddf71 --- /dev/null +++ b/SOURCES/0019-netdrv-net-aquantia-PTP-skeleton-declarations-and-ca.patch @@ -0,0 +1,395 @@ +From 0f6d832a6ed8f70ddf6e2217037a640f40e0874e Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:36 -0500 +Subject: [PATCH 019/139] [netdrv] net: aquantia: PTP skeleton declarations and + callbacks + +Message-id: <1604687916-15087-20-git-send-email-irusskik@redhat.com> +Patchwork-id: 338445 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 019/139] net: aquantia: PTP skeleton declarations and callbacks +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 1a64f8dc82b1a96baae3dc7eecbbbb6a315f1512 +Author: Egor Pomozov +Date: Tue Oct 22 09:53:22 2019 +0000 + + net: aquantia: PTP skeleton declarations and callbacks + + Here we add basic function for PTP clock register/unregister. + We also declare FW/HW capability bits used to control PTP feature on device. + + PTP device is created if network card has appropriate FW that has PTP + enabled in config. HW supports timestamping for PTPv2 802.AS1 and + PTPv2 IPv4 UDP packets. + + It also supports basic PTP callbacks for getting/setting time, adjusting + frequency and time as well. + + Signed-off-by: Egor Pomozov + Co-developed-by: Sergey Samoilenko + Signed-off-by: Sergey Samoilenko + Co-developed-by: Dmitry Bezrukov + Signed-off-by: Dmitry Bezrukov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/Makefile | 1 + + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 10 ++- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 5 +- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 84 +++++++++++++++++++++ + drivers/net/ethernet/aquantia/atlantic/aq_ptp.h | 22 ++++++ + .../aquantia/atlantic/hw_atl/hw_atl_utils.h | 85 +++++++++++++++++++++- + 6 files changed, 201 insertions(+), 6 deletions(-) + create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_ptp.c + create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_ptp.h + +diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile +index 131cab855be7..cd12d9d824ec 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/Makefile ++++ b/drivers/net/ethernet/aquantia/atlantic/Makefile +@@ -24,6 +24,7 @@ atlantic-objs := aq_main.o \ + aq_ethtool.o \ + aq_drvinfo.o \ + aq_filters.o \ ++ aq_ptp.o \ + hw_atl/hw_atl_a0.o \ + hw_atl/hw_atl_b0.o \ + hw_atl/hw_atl_utils.o \ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 137c1de4c6ec..d283d0bc75a3 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File aq_nic.c: Definition of common code for NIC. */ +@@ -12,6 +12,7 @@ + #include "aq_hw.h" + #include "aq_pci_func.h" + #include "aq_main.h" ++#include "aq_ptp.h" + + #include + #include +@@ -331,6 +332,10 @@ int aq_nic_init(struct aq_nic_s *self) + self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) + aq_vec_init(aq_vec, self->aq_hw_ops, self->aq_hw); + ++ err = aq_ptp_init(self, self->irqvecs - 1); ++ if (err < 0) ++ goto err_exit; ++ + netif_carrier_off(self->ndev); + + err_exit: +@@ -972,6 +977,9 @@ void aq_nic_deinit(struct aq_nic_s *self) + self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) + aq_vec_deinit(aq_vec); + ++ aq_ptp_unregister(self); ++ aq_ptp_free(self); ++ + if (likely(self->aq_fw_ops->deinit)) { + mutex_lock(&self->fwreq_mutex); + self->aq_fw_ops->deinit(self->aq_hw); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index 255b54a6ae07..d0979bba7ed3 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File aq_nic.h: Declaration of common code for NIC. */ +@@ -17,6 +17,7 @@ struct aq_ring_s; + struct aq_hw_ops; + struct aq_fw_s; + struct aq_vec_s; ++struct aq_ptp_s; + + struct aq_nic_cfg_s { + const struct aq_hw_caps_s *aq_hw_caps; +@@ -108,6 +109,8 @@ struct aq_nic_s { + u32 irqvecs; + /* mutex to serialize FW interface access operations */ + struct mutex fwreq_mutex; ++ /* PTP support */ ++ struct aq_ptp_s *aq_ptp; + struct aq_hw_rx_fltrs_s aq_hw_rx_fltrs; + }; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +new file mode 100644 +index 000000000000..a320916cced3 +--- /dev/null ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -0,0 +1,84 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Aquantia Corporation Network Driver ++ * Copyright (C) 2014-2019 Aquantia Corporation. All rights reserved ++ */ ++ ++/* File aq_ptp.c: ++ * Definition of functions for Linux PTP support. ++ */ ++ ++#include ++#include ++ ++#include "aq_nic.h" ++#include "aq_ptp.h" ++ ++struct aq_ptp_s { ++ struct aq_nic_s *aq_nic; ++ struct ptp_clock *ptp_clock; ++ struct ptp_clock_info ptp_info; ++}; ++ ++static struct ptp_clock_info aq_ptp_clock = { ++ .owner = THIS_MODULE, ++ .name = "atlantic ptp", ++ .n_ext_ts = 0, ++ .pps = 0, ++ .n_per_out = 0, ++ .n_pins = 0, ++ .pin_config = NULL, ++}; ++ ++int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) ++{ ++ struct hw_atl_utils_mbox mbox; ++ struct aq_ptp_s *aq_ptp; ++ int err = 0; ++ ++ hw_atl_utils_mpi_read_stats(aq_nic->aq_hw, &mbox); ++ ++ if (!(mbox.info.caps_ex & BIT(CAPS_EX_PHY_PTP_EN))) { ++ aq_nic->aq_ptp = NULL; ++ return 0; ++ } ++ ++ aq_ptp = kzalloc(sizeof(*aq_ptp), GFP_KERNEL); ++ if (!aq_ptp) { ++ err = -ENOMEM; ++ goto err_exit; ++ } ++ ++ aq_ptp->aq_nic = aq_nic; ++ ++ aq_ptp->ptp_info = aq_ptp_clock; ++ ++ aq_nic->aq_ptp = aq_ptp; ++ ++ return 0; ++ ++err_exit: ++ kfree(aq_ptp); ++ aq_nic->aq_ptp = NULL; ++ return err; ++} ++ ++void aq_ptp_unregister(struct aq_nic_s *aq_nic) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ ++ if (!aq_ptp) ++ return; ++ ++ ptp_clock_unregister(aq_ptp->ptp_clock); ++} ++ ++void aq_ptp_free(struct aq_nic_s *aq_nic) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ ++ if (!aq_ptp) ++ return; ++ ++ kfree(aq_ptp); ++ aq_nic->aq_ptp = NULL; ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +new file mode 100644 +index 000000000000..cea238959b20 +--- /dev/null ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +@@ -0,0 +1,22 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* Aquantia Corporation Network Driver ++ * Copyright (C) 2014-2019 Aquantia Corporation. All rights reserved ++ */ ++ ++/* File aq_ptp.h: Declaration of PTP functions. ++ */ ++#ifndef AQ_PTP_H ++#define AQ_PTP_H ++ ++#include ++#include ++ ++/* Common functions */ ++int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec); ++ ++void aq_ptp_unregister(struct aq_nic_s *aq_nic); ++void aq_ptp_free(struct aq_nic_s *aq_nic); ++ ++void aq_ptp_clock_init(struct aq_nic_s *aq_nic); ++ ++#endif /* AQ_PTP_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index 692bed70e104..7121248954df 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File hw_atl_utils.h: Declaration of common functions for Atlantic hardware +@@ -168,6 +168,34 @@ struct __packed hw_atl_utils_mbox_header { + u32 error; + }; + ++struct __packed hw_aq_ptp_offset { ++ u16 ingress_100; ++ u16 egress_100; ++ u16 ingress_1000; ++ u16 egress_1000; ++ u16 ingress_2500; ++ u16 egress_2500; ++ u16 ingress_5000; ++ u16 egress_5000; ++ u16 ingress_10000; ++ u16 egress_10000; ++}; ++ ++enum gpio_pin_function { ++ GPIO_PIN_FUNCTION_NC, ++ GPIO_PIN_FUNCTION_VAUX_ENABLE, ++ GPIO_PIN_FUNCTION_EFUSE_BURN_ENABLE, ++ GPIO_PIN_FUNCTION_SFP_PLUS_DETECT, ++ GPIO_PIN_FUNCTION_TX_DISABLE, ++ GPIO_PIN_FUNCTION_RATE_SEL_0, ++ GPIO_PIN_FUNCTION_RATE_SEL_1, ++ GPIO_PIN_FUNCTION_TX_FAULT, ++ GPIO_PIN_FUNCTION_PTP0, ++ GPIO_PIN_FUNCTION_PTP1, ++ GPIO_PIN_FUNCTION_PTP2, ++ GPIO_PIN_FUNCTION_SIZE ++}; ++ + struct __packed hw_aq_info { + u8 reserved[6]; + u16 phy_fault_code; +@@ -175,9 +203,23 @@ struct __packed hw_aq_info { + u8 cable_len; + u8 reserved1; + u32 cable_diag_data[4]; +- u8 reserved2[32]; ++ struct hw_aq_ptp_offset ptp_offset; ++ u8 reserved2[12]; + u32 caps_lo; + u32 caps_hi; ++ u32 reserved_datapath; ++ u32 reserved3[7]; ++ u32 reserved_simpleresp[3]; ++ u32 reserved_linkstat[7]; ++ u32 reserved_wakes_count; ++ u32 reserved_eee_stat[12]; ++ u32 tx_stuck_cnt; ++ u32 setting_address; ++ u32 setting_length; ++ u32 caps_ex; ++ enum gpio_pin_function gpio_pin[3]; ++ u32 pcie_aer_dump[18]; ++ u16 snr_margin[4]; + }; + + struct __packed hw_atl_utils_mbox { +@@ -372,7 +414,7 @@ enum hw_atl_fw2x_caps_hi { + CAPS_HI_2P5GBASET_FD_EEE, + CAPS_HI_5GBASET_FD_EEE, + CAPS_HI_10GBASET_FD_EEE, +- CAPS_HI_RESERVED5, ++ CAPS_HI_FW_REQUEST, + CAPS_HI_RESERVED6, + CAPS_HI_RESERVED7, + CAPS_HI_RESERVED8, +@@ -380,7 +422,7 @@ enum hw_atl_fw2x_caps_hi { + CAPS_HI_CABLE_DIAG, + CAPS_HI_TEMPERATURE, + CAPS_HI_DOWNSHIFT, +- CAPS_HI_PTP_AVB_EN, ++ CAPS_HI_PTP_AVB_EN_FW2X = 20, + CAPS_HI_MEDIA_DETECT, + CAPS_HI_LINK_DROP, + CAPS_HI_SLEEP_PROXY, +@@ -429,6 +471,41 @@ enum hw_atl_fw2x_ctrl { + CTRL_FORCE_RECONNECT, + }; + ++enum hw_atl_caps_ex { ++ CAPS_EX_LED_CONTROL = 0, ++ CAPS_EX_LED0_MODE_LO, ++ CAPS_EX_LED0_MODE_HI, ++ CAPS_EX_LED1_MODE_LO, ++ CAPS_EX_LED1_MODE_HI, ++ CAPS_EX_LED2_MODE_LO = 5, ++ CAPS_EX_LED2_MODE_HI, ++ CAPS_EX_RESERVED07, ++ CAPS_EX_RESERVED08, ++ CAPS_EX_RESERVED09, ++ CAPS_EX_RESERVED10 = 10, ++ CAPS_EX_RESERVED11, ++ CAPS_EX_RESERVED12, ++ CAPS_EX_RESERVED13, ++ CAPS_EX_RESERVED14, ++ CAPS_EX_RESERVED15 = 15, ++ CAPS_EX_PHY_PTP_EN, ++ CAPS_EX_MAC_PTP_EN, ++ CAPS_EX_EXT_CLK_EN, ++ CAPS_EX_SCHED_DMA_EN, ++ CAPS_EX_PTP_GPIO_EN = 20, ++ CAPS_EX_UPDATE_SETTINGS, ++ CAPS_EX_PHY_CTRL_TS_PIN, ++ CAPS_EX_SNR_OPERATING_MARGIN, ++ CAPS_EX_RESERVED24, ++ CAPS_EX_RESERVED25 = 25, ++ CAPS_EX_RESERVED26, ++ CAPS_EX_RESERVED27, ++ CAPS_EX_RESERVED28, ++ CAPS_EX_RESERVED29, ++ CAPS_EX_RESERVED30 = 30, ++ CAPS_EX_RESERVED31 ++}; ++ + struct aq_hw_s; + struct aq_fw_ops; + struct aq_hw_caps_s; +-- +2.13.6 + diff --git a/SOURCES/0020-netdrv-net-aquantia-unify-styling-of-bit-enums.patch b/SOURCES/0020-netdrv-net-aquantia-unify-styling-of-bit-enums.patch new file mode 100644 index 0000000..22cf659 --- /dev/null +++ b/SOURCES/0020-netdrv-net-aquantia-unify-styling-of-bit-enums.patch @@ -0,0 +1,172 @@ +From 4d66d2cfd4a303b6aac8ea803e45573be8488e59 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:37 -0500 +Subject: [PATCH 020/139] [netdrv] net: aquantia: unify styling of bit enums + +Message-id: <1604687916-15087-21-git-send-email-irusskik@redhat.com> +Patchwork-id: 338452 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 020/139] net: aquantia: unify styling of bit enums +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 593f7b43bd78c10f636088d3a067683e3ac376b1 +Author: Dmitry Bezrukov +Date: Tue Oct 22 09:53:25 2019 +0000 + + net: aquantia: unify styling of bit enums + + Make some other bit-enums more clear about positioning, + this helps on debugging and development + + Signed-off-by: Dmitry Bezrukov + Signed-off-by: Igor Russkikh + Reviewed-by: Andrew Lunn + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 2 +- + .../aquantia/atlantic/hw_atl/hw_atl_utils.h | 41 +++++++++++++--------- + 2 files changed, 26 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 52646855495e..32512539ae86 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File hw_atl_utils.c: Definition of common functions for Atlantic hardware +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index 7121248954df..766e02c7fd4e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -386,38 +386,44 @@ enum hw_atl_fw2x_rate { + FW2X_RATE_10G = 0x800, + }; + ++/* 0x370 ++ * Link capabilities resolution register ++ */ + enum hw_atl_fw2x_caps_lo { +- CAPS_LO_10BASET_HD = 0x00, ++ CAPS_LO_10BASET_HD = 0, + CAPS_LO_10BASET_FD, + CAPS_LO_100BASETX_HD, + CAPS_LO_100BASET4_HD, + CAPS_LO_100BASET2_HD, +- CAPS_LO_100BASETX_FD, ++ CAPS_LO_100BASETX_FD = 5, + CAPS_LO_100BASET2_FD, + CAPS_LO_1000BASET_HD, + CAPS_LO_1000BASET_FD, + CAPS_LO_2P5GBASET_FD, +- CAPS_LO_5GBASET_FD, ++ CAPS_LO_5GBASET_FD = 10, + CAPS_LO_10GBASET_FD, + }; + ++/* 0x374 ++ * Status register ++ */ + enum hw_atl_fw2x_caps_hi { +- CAPS_HI_RESERVED1 = 0x00, ++ CAPS_HI_RESERVED1 = 0, + CAPS_HI_10BASET_EEE, + CAPS_HI_RESERVED2, + CAPS_HI_PAUSE, + CAPS_HI_ASYMMETRIC_PAUSE, +- CAPS_HI_100BASETX_EEE, ++ CAPS_HI_100BASETX_EEE = 5, + CAPS_HI_RESERVED3, + CAPS_HI_RESERVED4, + CAPS_HI_1000BASET_FD_EEE, + CAPS_HI_2P5GBASET_FD_EEE, +- CAPS_HI_5GBASET_FD_EEE, ++ CAPS_HI_5GBASET_FD_EEE = 10, + CAPS_HI_10GBASET_FD_EEE, + CAPS_HI_FW_REQUEST, + CAPS_HI_RESERVED6, + CAPS_HI_RESERVED7, +- CAPS_HI_RESERVED8, ++ CAPS_HI_RESERVED8 = 15, + CAPS_HI_RESERVED9, + CAPS_HI_CABLE_DIAG, + CAPS_HI_TEMPERATURE, +@@ -427,47 +433,50 @@ enum hw_atl_fw2x_caps_hi { + CAPS_HI_LINK_DROP, + CAPS_HI_SLEEP_PROXY, + CAPS_HI_WOL, +- CAPS_HI_MAC_STOP, ++ CAPS_HI_MAC_STOP = 25, + CAPS_HI_EXT_LOOPBACK, + CAPS_HI_INT_LOOPBACK, + CAPS_HI_EFUSE_AGENT, + CAPS_HI_WOL_TIMER, +- CAPS_HI_STATISTICS, ++ CAPS_HI_STATISTICS = 30, + CAPS_HI_TRANSACTION_ID, + }; + ++/* 0x36C ++ * Control register ++ */ + enum hw_atl_fw2x_ctrl { +- CTRL_RESERVED1 = 0x00, ++ CTRL_RESERVED1 = 0, + CTRL_RESERVED2, + CTRL_RESERVED3, + CTRL_PAUSE, + CTRL_ASYMMETRIC_PAUSE, +- CTRL_RESERVED4, ++ CTRL_RESERVED4 = 5, + CTRL_RESERVED5, + CTRL_RESERVED6, + CTRL_1GBASET_FD_EEE, + CTRL_2P5GBASET_FD_EEE, +- CTRL_5GBASET_FD_EEE, ++ CTRL_5GBASET_FD_EEE = 10, + CTRL_10GBASET_FD_EEE, + CTRL_THERMAL_SHUTDOWN, + CTRL_PHY_LOGS, + CTRL_EEE_AUTO_DISABLE, +- CTRL_PFC, ++ CTRL_PFC = 15, + CTRL_WAKE_ON_LINK, + CTRL_CABLE_DIAG, + CTRL_TEMPERATURE, + CTRL_DOWNSHIFT, +- CTRL_PTP_AVB, ++ CTRL_PTP_AVB = 20, + CTRL_RESERVED7, + CTRL_LINK_DROP, + CTRL_SLEEP_PROXY, + CTRL_WOL, +- CTRL_MAC_STOP, ++ CTRL_MAC_STOP = 25, + CTRL_EXT_LOOPBACK, + CTRL_INT_LOOPBACK, + CTRL_RESERVED8, + CTRL_WOL_TIMER, +- CTRL_STATISTICS, ++ CTRL_STATISTICS = 30, + CTRL_FORCE_RECONNECT, + }; + +-- +2.13.6 + diff --git a/SOURCES/0021-netdrv-net-aquantia-add-basic-ptp_clock-callbacks.patch b/SOURCES/0021-netdrv-net-aquantia-add-basic-ptp_clock-callbacks.patch new file mode 100644 index 0000000..3923f72 --- /dev/null +++ b/SOURCES/0021-netdrv-net-aquantia-add-basic-ptp_clock-callbacks.patch @@ -0,0 +1,747 @@ +From 0a9e8b98ea2f8d557afcd3a09fb7b0eea8da0c3f Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:38 -0500 +Subject: [PATCH 021/139] [netdrv] net: aquantia: add basic ptp_clock callbacks + +Message-id: <1604687916-15087-22-git-send-email-irusskik@redhat.com> +Patchwork-id: 338450 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 021/139] net: aquantia: add basic ptp_clock callbacks +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 910479a9f793f47b21a01564bf9f1672029cbdfe +Author: Egor Pomozov +Date: Tue Oct 22 09:53:27 2019 +0000 + + net: aquantia: add basic ptp_clock callbacks + + Basic HW functions implemented for adjusting frequency, + adjusting time, getting and setting time. + With these callbacks we now do register ptp clock in the system. + + Firmware interface parts are defined for PTP requests and interactions. + Enable/disable PTP counters in HW on clock register/unregister. + + Signed-off-by: Egor Pomozov + Co-developed-by: Sergey Samoilenko + Signed-off-by: Sergey Samoilenko + Co-developed-by: Dmitry Bezrukov + Signed-off-by: Dmitry Bezrukov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 21 +++- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 3 + + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 125 +++++++++++++++++++++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 110 +++++++++++++++++- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 16 ++- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 8 +- + .../aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 18 ++- + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 5 +- + .../aquantia/atlantic/hw_atl/hw_atl_utils.h | 30 +++++ + .../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 97 ++++++++++++---- + 10 files changed, 403 insertions(+), 30 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index 1ee717b0e67c..cd6fc075bb2c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File aq_hw.h: Declaration of abstract interface for NIC hardware specific +@@ -15,6 +15,9 @@ + #include "aq_rss.h" + #include "hw_atl/hw_atl_utils.h" + ++#define AQ_HW_MAC_COUNTER_HZ 312500000ll ++#define AQ_HW_PHY_COUNTER_HZ 160000000ll ++ + #define AQ_RX_FIRST_LOC_FVLANID 0U + #define AQ_RX_LAST_LOC_FVLANID 15U + #define AQ_RX_FIRST_LOC_FETHERT 16U +@@ -94,6 +97,7 @@ struct aq_stats_s { + #define AQ_HW_FLAG_STOPPING 0x00000008U + #define AQ_HW_FLAG_RESETTING 0x00000010U + #define AQ_HW_FLAG_CLOSING 0x00000020U ++#define AQ_HW_PTP_AVAILABLE 0x01000000U + #define AQ_HW_LINK_DOWN 0x04000000U + #define AQ_HW_FLAG_ERR_UNPLUG 0x40000000U + #define AQ_HW_FLAG_ERR_HW 0x80000000U +@@ -135,6 +139,7 @@ struct aq_hw_s { + u32 rpc_addr; + u32 rpc_tid; + struct hw_atl_utils_fw_rpc rpc; ++ s64 ptp_clk_offset; + }; + + struct aq_ring_s; +@@ -235,6 +240,14 @@ struct aq_hw_ops { + int (*hw_set_offload)(struct aq_hw_s *self, + struct aq_nic_cfg_s *aq_nic_cfg); + ++ void (*hw_get_ptp_ts)(struct aq_hw_s *self, u64 *stamp); ++ ++ int (*hw_adj_clock_freq)(struct aq_hw_s *self, s32 delta); ++ ++ int (*hw_adj_sys_clock)(struct aq_hw_s *self, s64 delta); ++ ++ int (*hw_set_sys_clock)(struct aq_hw_s *self, u64 time, u64 ts); ++ + int (*hw_set_fc)(struct aq_hw_s *self, u32 fc, u32 tc); + }; + +@@ -267,6 +280,12 @@ struct aq_fw_ops { + int (*set_power)(struct aq_hw_s *self, unsigned int power_state, + u8 *mac); + ++ int (*send_fw_request)(struct aq_hw_s *self, ++ const struct hw_fw_request_iface *fw_req, ++ size_t size); ++ ++ void (*enable_ptp)(struct aq_hw_s *self, int enable); ++ + int (*set_eee_rate)(struct aq_hw_s *self, u32 speed); + + int (*get_eee_rate)(struct aq_hw_s *self, u32 *rate, +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index d283d0bc75a3..dc9769fe762b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -146,6 +146,9 @@ static int aq_nic_update_link_status(struct aq_nic_s *self) + self->aq_hw->aq_link_status.mbps); + aq_nic_update_interrupt_moderation_settings(self); + ++ if (self->aq_ptp) ++ aq_ptp_clock_init(self); ++ + /* Driver has to update flow control settings on RX block + * on any link event. + * We should query FW whether it negotiated FC. +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index a320916cced3..02c2a8cd1219 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -15,15 +15,108 @@ + + struct aq_ptp_s { + struct aq_nic_s *aq_nic; ++ spinlock_t ptp_lock; + struct ptp_clock *ptp_clock; + struct ptp_clock_info ptp_info; + }; + ++/* aq_ptp_adjfine ++ * @ptp: the ptp clock structure ++ * @ppb: parts per billion adjustment from base ++ * ++ * adjust the frequency of the ptp cycle counter by the ++ * indicated ppb from the base frequency. ++ */ ++static int aq_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) ++{ ++ struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info); ++ struct aq_nic_s *aq_nic = aq_ptp->aq_nic; ++ ++ mutex_lock(&aq_nic->fwreq_mutex); ++ aq_nic->aq_hw_ops->hw_adj_clock_freq(aq_nic->aq_hw, ++ scaled_ppm_to_ppb(scaled_ppm)); ++ mutex_unlock(&aq_nic->fwreq_mutex); ++ ++ return 0; ++} ++ ++/* aq_ptp_adjtime ++ * @ptp: the ptp clock structure ++ * @delta: offset to adjust the cycle counter by ++ * ++ * adjust the timer by resetting the timecounter structure. ++ */ ++static int aq_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) ++{ ++ struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info); ++ struct aq_nic_s *aq_nic = aq_ptp->aq_nic; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&aq_ptp->ptp_lock, flags); ++ aq_nic->aq_hw_ops->hw_adj_sys_clock(aq_nic->aq_hw, delta); ++ spin_unlock_irqrestore(&aq_ptp->ptp_lock, flags); ++ ++ return 0; ++} ++ ++/* aq_ptp_gettime ++ * @ptp: the ptp clock structure ++ * @ts: timespec structure to hold the current time value ++ * ++ * read the timecounter and return the correct value on ns, ++ * after converting it into a struct timespec. ++ */ ++static int aq_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) ++{ ++ struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info); ++ struct aq_nic_s *aq_nic = aq_ptp->aq_nic; ++ unsigned long flags; ++ u64 ns; ++ ++ spin_lock_irqsave(&aq_ptp->ptp_lock, flags); ++ aq_nic->aq_hw_ops->hw_get_ptp_ts(aq_nic->aq_hw, &ns); ++ spin_unlock_irqrestore(&aq_ptp->ptp_lock, flags); ++ ++ *ts = ns_to_timespec64(ns); ++ ++ return 0; ++} ++ ++/* aq_ptp_settime ++ * @ptp: the ptp clock structure ++ * @ts: the timespec containing the new time for the cycle counter ++ * ++ * reset the timecounter to use a new base value instead of the kernel ++ * wall timer value. ++ */ ++static int aq_ptp_settime(struct ptp_clock_info *ptp, ++ const struct timespec64 *ts) ++{ ++ struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info); ++ struct aq_nic_s *aq_nic = aq_ptp->aq_nic; ++ unsigned long flags; ++ u64 ns = timespec64_to_ns(ts); ++ u64 now; ++ ++ spin_lock_irqsave(&aq_ptp->ptp_lock, flags); ++ aq_nic->aq_hw_ops->hw_get_ptp_ts(aq_nic->aq_hw, &now); ++ aq_nic->aq_hw_ops->hw_adj_sys_clock(aq_nic->aq_hw, (s64)ns - (s64)now); ++ ++ spin_unlock_irqrestore(&aq_ptp->ptp_lock, flags); ++ ++ return 0; ++} ++ + static struct ptp_clock_info aq_ptp_clock = { + .owner = THIS_MODULE, + .name = "atlantic ptp", ++ .max_adj = 999999999, + .n_ext_ts = 0, + .pps = 0, ++ .adjfine = aq_ptp_adjfine, ++ .adjtime = aq_ptp_adjtime, ++ .gettime64 = aq_ptp_gettime, ++ .settime64 = aq_ptp_settime, + .n_per_out = 0, + .n_pins = 0, + .pin_config = NULL, +@@ -32,9 +125,20 @@ static struct ptp_clock_info aq_ptp_clock = { + int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + { + struct hw_atl_utils_mbox mbox; ++ struct ptp_clock *clock; + struct aq_ptp_s *aq_ptp; + int err = 0; + ++ if (!aq_nic->aq_hw_ops->hw_get_ptp_ts) { ++ aq_nic->aq_ptp = NULL; ++ return 0; ++ } ++ ++ if (!aq_nic->aq_fw_ops->enable_ptp) { ++ aq_nic->aq_ptp = NULL; ++ return 0; ++ } ++ + hw_atl_utils_mpi_read_stats(aq_nic->aq_hw, &mbox); + + if (!(mbox.info.caps_ex & BIT(CAPS_EX_PHY_PTP_EN))) { +@@ -50,10 +154,26 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + + aq_ptp->aq_nic = aq_nic; + ++ spin_lock_init(&aq_ptp->ptp_lock); ++ + aq_ptp->ptp_info = aq_ptp_clock; ++ clock = ptp_clock_register(&aq_ptp->ptp_info, &aq_nic->ndev->dev); ++ if (!clock || IS_ERR(clock)) { ++ netdev_err(aq_nic->ndev, "ptp_clock_register failed\n"); ++ err = PTR_ERR(clock); ++ goto err_exit; ++ } ++ aq_ptp->ptp_clock = clock; + + aq_nic->aq_ptp = aq_ptp; + ++ /* enable ptp counter */ ++ aq_utils_obj_set(&aq_nic->aq_hw->flags, AQ_HW_PTP_AVAILABLE); ++ mutex_lock(&aq_nic->fwreq_mutex); ++ aq_nic->aq_fw_ops->enable_ptp(aq_nic->aq_hw, 1); ++ aq_ptp_clock_init(aq_nic); ++ mutex_unlock(&aq_nic->fwreq_mutex); ++ + return 0; + + err_exit: +@@ -79,6 +199,11 @@ void aq_ptp_free(struct aq_nic_s *aq_nic) + if (!aq_ptp) + return; + ++ /* disable ptp */ ++ mutex_lock(&aq_nic->fwreq_mutex); ++ aq_nic->aq_fw_ops->enable_ptp(aq_nic->aq_hw, 0); ++ mutex_unlock(&aq_nic->fwreq_mutex); ++ + kfree(aq_ptp); + aq_nic->aq_ptp = NULL; + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 2ad3fa6316ce..881caa8ee319 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File hw_atl_b0.c: Definition of Atlantic hardware specific functions. */ +@@ -49,6 +49,8 @@ + .mac_regs_count = 88, \ + .hw_alive_check_addr = 0x10U + ++#define FRAC_PER_NS 0x100000000LL ++ + const struct aq_hw_caps_s hw_atl_b0_caps_aqc100 = { + DEFAULT_B0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_FIBRE, +@@ -1005,6 +1007,104 @@ static int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, + return aq_hw_err_from_flags(self); + } + ++#define get_ptp_ts_val_u64(self, indx) \ ++ ((u64)(hw_atl_pcs_ptp_clock_get(self, indx) & 0xffff)) ++ ++static void hw_atl_b0_get_ptp_ts(struct aq_hw_s *self, u64 *stamp) ++{ ++ u64 ns; ++ ++ hw_atl_pcs_ptp_clock_read_enable(self, 1); ++ hw_atl_pcs_ptp_clock_read_enable(self, 0); ++ ns = (get_ptp_ts_val_u64(self, 0) + ++ (get_ptp_ts_val_u64(self, 1) << 16)) * NSEC_PER_SEC + ++ (get_ptp_ts_val_u64(self, 3) + ++ (get_ptp_ts_val_u64(self, 4) << 16)); ++ ++ *stamp = ns + self->ptp_clk_offset; ++} ++ ++static void hw_atl_b0_adj_params_get(u64 freq, s64 adj, u32 *ns, u32 *fns) ++{ ++ /* For accuracy, the digit is extended */ ++ s64 base_ns = ((adj + NSEC_PER_SEC) * NSEC_PER_SEC); ++ u64 nsi_frac = 0; ++ u64 nsi; ++ ++ base_ns = div64_s64(base_ns, freq); ++ nsi = div64_u64(base_ns, NSEC_PER_SEC); ++ ++ if (base_ns != nsi * NSEC_PER_SEC) { ++ s64 divisor = div64_s64((s64)NSEC_PER_SEC * NSEC_PER_SEC, ++ base_ns - nsi * NSEC_PER_SEC); ++ nsi_frac = div64_s64(FRAC_PER_NS * NSEC_PER_SEC, divisor); ++ } ++ ++ *ns = (u32)nsi; ++ *fns = (u32)nsi_frac; ++} ++ ++static void ++hw_atl_b0_mac_adj_param_calc(struct hw_fw_request_ptp_adj_freq *ptp_adj_freq, ++ u64 phyfreq, u64 macfreq) ++{ ++ s64 adj_fns_val; ++ s64 fns_in_sec_phy = phyfreq * (ptp_adj_freq->fns_phy + ++ FRAC_PER_NS * ptp_adj_freq->ns_phy); ++ s64 fns_in_sec_mac = macfreq * (ptp_adj_freq->fns_mac + ++ FRAC_PER_NS * ptp_adj_freq->ns_mac); ++ s64 fault_in_sec_phy = FRAC_PER_NS * NSEC_PER_SEC - fns_in_sec_phy; ++ s64 fault_in_sec_mac = FRAC_PER_NS * NSEC_PER_SEC - fns_in_sec_mac; ++ /* MAC MCP counter freq is macfreq / 4 */ ++ s64 diff_in_mcp_overflow = (fault_in_sec_mac - fault_in_sec_phy) * ++ 4 * FRAC_PER_NS; ++ ++ diff_in_mcp_overflow = div64_s64(diff_in_mcp_overflow, ++ AQ_HW_MAC_COUNTER_HZ); ++ adj_fns_val = (ptp_adj_freq->fns_mac + FRAC_PER_NS * ++ ptp_adj_freq->ns_mac) + diff_in_mcp_overflow; ++ ++ ptp_adj_freq->mac_ns_adj = div64_s64(adj_fns_val, FRAC_PER_NS); ++ ptp_adj_freq->mac_fns_adj = adj_fns_val - ptp_adj_freq->mac_ns_adj * ++ FRAC_PER_NS; ++} ++ ++static int hw_atl_b0_adj_sys_clock(struct aq_hw_s *self, s64 delta) ++{ ++ self->ptp_clk_offset += delta; ++ ++ return 0; ++} ++ ++static int hw_atl_b0_set_sys_clock(struct aq_hw_s *self, u64 time, u64 ts) ++{ ++ s64 delta = time - (self->ptp_clk_offset + ts); ++ ++ return hw_atl_b0_adj_sys_clock(self, delta); ++} ++ ++static int hw_atl_b0_adj_clock_freq(struct aq_hw_s *self, s32 ppb) ++{ ++ struct hw_fw_request_iface fwreq; ++ size_t size; ++ ++ memset(&fwreq, 0, sizeof(fwreq)); ++ ++ fwreq.msg_id = HW_AQ_FW_REQUEST_PTP_ADJ_FREQ; ++ hw_atl_b0_adj_params_get(AQ_HW_MAC_COUNTER_HZ, ppb, ++ &fwreq.ptp_adj_freq.ns_mac, ++ &fwreq.ptp_adj_freq.fns_mac); ++ hw_atl_b0_adj_params_get(AQ_HW_PHY_COUNTER_HZ, ppb, ++ &fwreq.ptp_adj_freq.ns_phy, ++ &fwreq.ptp_adj_freq.fns_phy); ++ hw_atl_b0_mac_adj_param_calc(&fwreq.ptp_adj_freq, ++ AQ_HW_PHY_COUNTER_HZ, ++ AQ_HW_MAC_COUNTER_HZ); ++ ++ size = sizeof(fwreq.msg_id) + sizeof(fwreq.ptp_adj_freq); ++ return self->aq_fw_ops->send_fw_request(self, &fwreq, size); ++} ++ + static int hw_atl_b0_hw_fl3l4_clear(struct aq_hw_s *self, + struct aq_rx_filter_l3l4 *data) + { +@@ -1177,6 +1277,12 @@ const struct aq_hw_ops hw_atl_ops_b0 = { + .hw_get_regs = hw_atl_utils_hw_get_regs, + .hw_get_hw_stats = hw_atl_utils_get_hw_stats, + .hw_get_fw_version = hw_atl_utils_get_fw_version, +- .hw_set_offload = hw_atl_b0_hw_offload_set, ++ ++ .hw_get_ptp_ts = hw_atl_b0_get_ptp_ts, ++ .hw_adj_sys_clock = hw_atl_b0_adj_sys_clock, ++ .hw_set_sys_clock = hw_atl_b0_set_sys_clock, ++ .hw_adj_clock_freq = hw_atl_b0_adj_clock_freq, ++ ++ .hw_set_offload = hw_atl_b0_hw_offload_set, + .hw_set_fc = hw_atl_b0_set_fc, + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index 6f340695e6bd..eb982288fc52 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File hw_atl_llh.c: Definitions of bitfield and register access functions for +@@ -1526,6 +1526,20 @@ void hw_atl_reg_glb_cpu_scratch_scp_set(struct aq_hw_s *aq_hw, + glb_cpu_scratch_scp); + } + ++void hw_atl_pcs_ptp_clock_read_enable(struct aq_hw_s *aq_hw, ++ u32 ptp_clock_read_enable) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_ADR, ++ HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_MSK, ++ HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_SHIFT, ++ ptp_clock_read_enable); ++} ++ ++u32 hw_atl_pcs_ptp_clock_get(struct aq_hw_s *aq_hw, u32 index) ++{ ++ return aq_hw_read_reg(aq_hw, HW_ATL_PCS_PTP_TS_VAL_ADDR(index)); ++} ++ + void hw_atl_mcp_up_force_intr_set(struct aq_hw_s *aq_hw, u32 up_force_intr) + { + aq_hw_write_reg_bit(aq_hw, HW_ATL_MCP_UP_FORCE_INTERRUPT_ADR, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index c3ee278c3747..7753ab860c95 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File hw_atl_llh.h: Declarations of bitfield and register access functions for +@@ -715,6 +715,12 @@ void hw_atl_msm_reg_wr_strobe_set(struct aq_hw_s *aq_hw, u32 reg_wr_strobe); + /* set pci register reset disable */ + void hw_atl_pci_pci_reg_res_dis_set(struct aq_hw_s *aq_hw, u32 pci_reg_res_dis); + ++/* pcs */ ++void hw_atl_pcs_ptp_clock_read_enable(struct aq_hw_s *aq_hw, ++ u32 ptp_clock_read_enable); ++ ++u32 hw_atl_pcs_ptp_clock_get(struct aq_hw_s *aq_hw, u32 index); ++ + /* set uP Force Interrupt */ + void hw_atl_mcp_up_force_intr_set(struct aq_hw_s *aq_hw, u32 up_force_intr); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +index 35887ad89025..65fb74a4d5ea 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File hw_atl_llh_internal.h: Preprocessor definitions +@@ -2440,6 +2440,22 @@ + /* default value of bitfield register write strobe */ + #define HW_ATL_MSM_REG_WR_STROBE_DEFAULT 0x0 + ++/* register address for bitfield PTP Digital Clock Read Enable */ ++#define HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_ADR 0x00004628 ++/* bitmask for bitfield PTP Digital Clock Read Enable */ ++#define HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_MSK 0x00000010 ++/* inverted bitmask for bitfield PTP Digital Clock Read Enable */ ++#define HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_MSKN 0xFFFFFFEF ++/* lower bit position of bitfield PTP Digital Clock Read Enable */ ++#define HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_SHIFT 4 ++/* width of bitfield PTP Digital Clock Read Enable */ ++#define HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_WIDTH 1 ++/* default value of bitfield PTP Digital Clock Read Enable */ ++#define HW_ATL_PCS_PTP_CLOCK_READ_ENABLE_DEFAULT 0x0 ++ ++/* register address for ptp counter reading */ ++#define HW_ATL_PCS_PTP_TS_VAL_ADDR(index) (0x00004900 + (index) * 0x4) ++ + /* mif soft reset bitfield definitions + * preprocessor definitions for the bitfield "soft reset". + * port="pif_glb_res_i" +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 32512539ae86..6fc5640065bd 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -327,8 +327,7 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, + return err; + } + +-static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, +- u32 cnt) ++int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt) + { + u32 val; + int err = 0; +@@ -964,4 +963,6 @@ const struct aq_fw_ops aq_fw_1x_ops = { + .set_eee_rate = NULL, + .get_eee_rate = NULL, + .set_flow_control = NULL, ++ .send_fw_request = NULL, ++ .enable_ptp = NULL, + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index 766e02c7fd4e..f2eb94f298e2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -279,6 +279,34 @@ struct __packed offload_info { + u8 buf[0]; + }; + ++/* Mailbox FW Request interface */ ++struct __packed hw_fw_request_ptp_adj_freq { ++ u32 ns_mac; ++ u32 fns_mac; ++ u32 ns_phy; ++ u32 fns_phy; ++ u32 mac_ns_adj; ++ u32 mac_fns_adj; ++}; ++ ++struct __packed hw_fw_request_ptp_adj_clock { ++ u32 ns; ++ u32 sec; ++ int sign; ++}; ++ ++#define HW_AQ_FW_REQUEST_PTP_ADJ_FREQ 0x12 ++#define HW_AQ_FW_REQUEST_PTP_ADJ_CLOCK 0x13 ++ ++struct __packed hw_fw_request_iface { ++ u32 msg_id; ++ union { ++ /* PTP FW Request */ ++ struct hw_fw_request_ptp_adj_freq ptp_adj_freq; ++ struct hw_fw_request_ptp_adj_clock ptp_adj_clock; ++ }; ++}; ++ + enum hw_atl_rx_action_with_traffic { + HW_ATL_RX_DISCARD, + HW_ATL_RX_HOST, +@@ -561,6 +589,8 @@ struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self); + int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, + u32 *p, u32 cnt); + ++int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt); ++ + int hw_atl_utils_fw_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac); + + int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index 7bc51f8d6f2f..f649ac949d06 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File hw_atl_utils_fw2x.c: Definition of firmware 2.x functions for +@@ -17,14 +17,17 @@ + #include "hw_atl_utils.h" + #include "hw_atl_llh.h" + +-#define HW_ATL_FW2X_MPI_RPC_ADDR 0x334 ++#define HW_ATL_FW2X_MPI_RPC_ADDR 0x334 + +-#define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360 +-#define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364 +-#define HW_ATL_FW2X_MPI_CONTROL_ADDR 0x368 +-#define HW_ATL_FW2X_MPI_CONTROL2_ADDR 0x36C +-#define HW_ATL_FW2X_MPI_STATE_ADDR 0x370 +-#define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374 ++#define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360 ++#define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364 ++#define HW_ATL_FW2X_MPI_CONTROL_ADDR 0x368 ++#define HW_ATL_FW2X_MPI_CONTROL2_ADDR 0x36C ++#define HW_ATL_FW2X_MPI_STATE_ADDR 0x370 ++#define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374 ++ ++#define HW_ATL_FW3X_EXT_CONTROL_ADDR 0x378 ++#define HW_ATL_FW3X_EXT_STATE_ADDR 0x37c + + #define HW_ATL_FW2X_CAP_PAUSE BIT(CAPS_HI_PAUSE) + #define HW_ATL_FW2X_CAP_ASYM_PAUSE BIT(CAPS_HI_ASYMMETRIC_PAUSE) +@@ -444,6 +447,54 @@ static int aq_fw2x_set_power(struct aq_hw_s *self, unsigned int power_state, + return err; + } + ++static int aq_fw2x_send_fw_request(struct aq_hw_s *self, ++ const struct hw_fw_request_iface *fw_req, ++ size_t size) ++{ ++ u32 ctrl2, orig_ctrl2; ++ u32 dword_cnt; ++ int err = 0; ++ u32 val; ++ ++ /* Write data to drvIface Mailbox */ ++ dword_cnt = size / sizeof(u32); ++ if (size % sizeof(u32)) ++ dword_cnt++; ++ err = hw_atl_utils_fw_upload_dwords(self, aq_fw2x_rpc_get(self), ++ (void *)fw_req, dword_cnt); ++ if (err < 0) ++ goto err_exit; ++ ++ /* Toggle statistics bit for FW to update */ ++ ctrl2 = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); ++ orig_ctrl2 = ctrl2 & BIT(CAPS_HI_FW_REQUEST); ++ ctrl2 = ctrl2 ^ BIT(CAPS_HI_FW_REQUEST); ++ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, ctrl2); ++ ++ /* Wait FW to report back */ ++ err = readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val, ++ orig_ctrl2 != (val & ++ BIT(CAPS_HI_FW_REQUEST)), ++ 1U, 10000U); ++ ++err_exit: ++ return err; ++} ++ ++static void aq_fw3x_enable_ptp(struct aq_hw_s *self, int enable) ++{ ++ u32 ptp_opts = aq_hw_read_reg(self, HW_ATL_FW3X_EXT_STATE_ADDR); ++ u32 all_ptp_features = BIT(CAPS_EX_PHY_PTP_EN) | ++ BIT(CAPS_EX_PTP_GPIO_EN); ++ ++ if (enable) ++ ptp_opts |= all_ptp_features; ++ else ++ ptp_opts &= ~all_ptp_features; ++ ++ aq_hw_write_reg(self, HW_ATL_FW3X_EXT_CONTROL_ADDR, ptp_opts); ++} ++ + static int aq_fw2x_set_eee_rate(struct aq_hw_s *self, u32 speed) + { + u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); +@@ -534,19 +585,21 @@ static u32 aq_fw2x_state2_get(struct aq_hw_s *self) + } + + const struct aq_fw_ops aq_fw_2x_ops = { +- .init = aq_fw2x_init, +- .deinit = aq_fw2x_deinit, +- .reset = NULL, +- .renegotiate = aq_fw2x_renegotiate, +- .get_mac_permanent = aq_fw2x_get_mac_permanent, +- .set_link_speed = aq_fw2x_set_link_speed, +- .set_state = aq_fw2x_set_state, ++ .init = aq_fw2x_init, ++ .deinit = aq_fw2x_deinit, ++ .reset = NULL, ++ .renegotiate = aq_fw2x_renegotiate, ++ .get_mac_permanent = aq_fw2x_get_mac_permanent, ++ .set_link_speed = aq_fw2x_set_link_speed, ++ .set_state = aq_fw2x_set_state, + .update_link_status = aq_fw2x_update_link_status, +- .update_stats = aq_fw2x_update_stats, +- .get_phy_temp = aq_fw2x_get_phy_temp, +- .set_power = aq_fw2x_set_power, +- .set_eee_rate = aq_fw2x_set_eee_rate, +- .get_eee_rate = aq_fw2x_get_eee_rate, +- .set_flow_control = aq_fw2x_set_flow_control, +- .get_flow_control = aq_fw2x_get_flow_control ++ .update_stats = aq_fw2x_update_stats, ++ .get_phy_temp = aq_fw2x_get_phy_temp, ++ .set_power = aq_fw2x_set_power, ++ .set_eee_rate = aq_fw2x_set_eee_rate, ++ .get_eee_rate = aq_fw2x_get_eee_rate, ++ .set_flow_control = aq_fw2x_set_flow_control, ++ .get_flow_control = aq_fw2x_get_flow_control, ++ .send_fw_request = aq_fw2x_send_fw_request, ++ .enable_ptp = aq_fw3x_enable_ptp, + }; +-- +2.13.6 + diff --git a/SOURCES/0022-netdrv-net-aquantia-add-PTP-rings-infrastructure.patch b/SOURCES/0022-netdrv-net-aquantia-add-PTP-rings-infrastructure.patch new file mode 100644 index 0000000..c4fb58c --- /dev/null +++ b/SOURCES/0022-netdrv-net-aquantia-add-PTP-rings-infrastructure.patch @@ -0,0 +1,673 @@ +From b7d9cef8662d722c6256955eaa85d0ef25cfbe1e Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:39 -0500 +Subject: [PATCH 022/139] [netdrv] net: aquantia: add PTP rings infrastructure + +Message-id: <1604687916-15087-23-git-send-email-irusskik@redhat.com> +Patchwork-id: 338454 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 022/139] net: aquantia: add PTP rings infrastructure +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 94ad94558b0fbf18dd6fb0987540af1693157556 +Author: Egor Pomozov +Date: Tue Oct 22 09:53:29 2019 +0000 + + net: aquantia: add PTP rings infrastructure + + Add implementations of PTP rings alloc/free. + + PTP desing on this device uses two separate rings on a separate traffic + class for traffic rx/tx. + + Third ring (hwts) is not a traffic ring, but is used only to receive timestamps + of the transmitted packets. + + Signed-off-by: Egor Pomozov + Co-developed-by: Sergey Samoilenko + Signed-off-by: Sergey Samoilenko + Co-developed-by: Dmitry Bezrukov + Signed-off-by: Dmitry Bezrukov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 4 + + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 16 ++ + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 235 +++++++++++++++++++++ + drivers/net/ethernet/aquantia/atlantic/aq_ptp.h | 8 + + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 26 ++- + drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 6 +- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 45 +++- + .../aquantia/atlantic/hw_atl/hw_atl_b0_internal.h | 9 +- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 14 ++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 6 + + .../aquantia/atlantic/hw_atl/hw_atl_utils.h | 8 + + 11 files changed, 365 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index cd6fc075bb2c..fa943852757e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -240,6 +240,10 @@ struct aq_hw_ops { + int (*hw_set_offload)(struct aq_hw_s *self, + struct aq_nic_cfg_s *aq_nic_cfg); + ++ int (*hw_tx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode); ++ ++ int (*hw_rx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode); ++ + void (*hw_get_ptp_ts)(struct aq_hw_s *self, u64 *stamp); + + int (*hw_adj_clock_freq)(struct aq_hw_s *self, s32 delta); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index dc9769fe762b..ecca2c4cf140 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -339,6 +339,14 @@ int aq_nic_init(struct aq_nic_s *self) + if (err < 0) + goto err_exit; + ++ err = aq_ptp_ring_alloc(self); ++ if (err < 0) ++ goto err_exit; ++ ++ err = aq_ptp_ring_init(self); ++ if (err < 0) ++ goto err_exit; ++ + netif_carrier_off(self->ndev); + + err_exit: +@@ -369,6 +377,10 @@ int aq_nic_start(struct aq_nic_s *self) + goto err_exit; + } + ++ err = aq_ptp_ring_start(self); ++ if (err < 0) ++ goto err_exit; ++ + err = self->aq_hw_ops->hw_start(self->aq_hw); + if (err < 0) + goto err_exit; +@@ -965,6 +977,8 @@ int aq_nic_stop(struct aq_nic_s *self) + self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) + aq_vec_stop(aq_vec); + ++ aq_ptp_ring_stop(self); ++ + return self->aq_hw_ops->hw_stop(self->aq_hw); + } + +@@ -981,6 +995,8 @@ void aq_nic_deinit(struct aq_nic_s *self) + aq_vec_deinit(aq_vec); + + aq_ptp_unregister(self); ++ aq_ptp_ring_deinit(self); ++ aq_ptp_ring_free(self); + aq_ptp_free(self); + + if (likely(self->aq_fw_ops->deinit)) { +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index 02c2a8cd1219..f2fd0ca14a49 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -12,14 +12,55 @@ + + #include "aq_nic.h" + #include "aq_ptp.h" ++#include "aq_ring.h" ++ ++struct ptp_skb_ring { ++ struct sk_buff **buff; ++ spinlock_t lock; ++ unsigned int size; ++ unsigned int head; ++ unsigned int tail; ++}; + + struct aq_ptp_s { + struct aq_nic_s *aq_nic; + spinlock_t ptp_lock; ++ spinlock_t ptp_ring_lock; + struct ptp_clock *ptp_clock; + struct ptp_clock_info ptp_info; ++ ++ struct aq_ring_param_s ptp_ring_param; ++ ++ struct aq_ring_s ptp_tx; ++ struct aq_ring_s ptp_rx; ++ struct aq_ring_s hwts_rx; ++ ++ struct ptp_skb_ring skb_ring; + }; + ++static int aq_ptp_skb_ring_init(struct ptp_skb_ring *ring, unsigned int size) ++{ ++ struct sk_buff **buff = kmalloc(sizeof(*buff) * size, GFP_KERNEL); ++ ++ if (!buff) ++ return -ENOMEM; ++ ++ spin_lock_init(&ring->lock); ++ ++ ring->buff = buff; ++ ring->size = size; ++ ring->head = 0; ++ ring->tail = 0; ++ ++ return 0; ++} ++ ++static void aq_ptp_skb_ring_release(struct ptp_skb_ring *ring) ++{ ++ kfree(ring->buff); ++ ring->buff = NULL; ++} ++ + /* aq_ptp_adjfine + * @ptp: the ptp clock structure + * @ppb: parts per billion adjustment from base +@@ -107,6 +148,190 @@ static int aq_ptp_settime(struct ptp_clock_info *ptp, + return 0; + } + ++int aq_ptp_ring_init(struct aq_nic_s *aq_nic) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ int err = 0; ++ ++ if (!aq_ptp) ++ return 0; ++ ++ err = aq_ring_init(&aq_ptp->ptp_tx); ++ if (err < 0) ++ goto err_exit; ++ err = aq_nic->aq_hw_ops->hw_ring_tx_init(aq_nic->aq_hw, ++ &aq_ptp->ptp_tx, ++ &aq_ptp->ptp_ring_param); ++ if (err < 0) ++ goto err_exit; ++ ++ err = aq_ring_init(&aq_ptp->ptp_rx); ++ if (err < 0) ++ goto err_exit; ++ err = aq_nic->aq_hw_ops->hw_ring_rx_init(aq_nic->aq_hw, ++ &aq_ptp->ptp_rx, ++ &aq_ptp->ptp_ring_param); ++ if (err < 0) ++ goto err_exit; ++ ++ err = aq_ring_rx_fill(&aq_ptp->ptp_rx); ++ if (err < 0) ++ goto err_rx_free; ++ err = aq_nic->aq_hw_ops->hw_ring_rx_fill(aq_nic->aq_hw, ++ &aq_ptp->ptp_rx, ++ 0U); ++ if (err < 0) ++ goto err_rx_free; ++ ++ err = aq_ring_init(&aq_ptp->hwts_rx); ++ if (err < 0) ++ goto err_rx_free; ++ err = aq_nic->aq_hw_ops->hw_ring_rx_init(aq_nic->aq_hw, ++ &aq_ptp->hwts_rx, ++ &aq_ptp->ptp_ring_param); ++ ++ return err; ++ ++err_rx_free: ++ aq_ring_rx_deinit(&aq_ptp->ptp_rx); ++err_exit: ++ return err; ++} ++ ++int aq_ptp_ring_start(struct aq_nic_s *aq_nic) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ int err = 0; ++ ++ if (!aq_ptp) ++ return 0; ++ ++ err = aq_nic->aq_hw_ops->hw_ring_tx_start(aq_nic->aq_hw, &aq_ptp->ptp_tx); ++ if (err < 0) ++ goto err_exit; ++ ++ err = aq_nic->aq_hw_ops->hw_ring_rx_start(aq_nic->aq_hw, &aq_ptp->ptp_rx); ++ if (err < 0) ++ goto err_exit; ++ ++ err = aq_nic->aq_hw_ops->hw_ring_rx_start(aq_nic->aq_hw, ++ &aq_ptp->hwts_rx); ++ if (err < 0) ++ goto err_exit; ++ ++err_exit: ++ return err; ++} ++ ++void aq_ptp_ring_stop(struct aq_nic_s *aq_nic) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ ++ if (!aq_ptp) ++ return; ++ ++ aq_nic->aq_hw_ops->hw_ring_tx_stop(aq_nic->aq_hw, &aq_ptp->ptp_tx); ++ aq_nic->aq_hw_ops->hw_ring_rx_stop(aq_nic->aq_hw, &aq_ptp->ptp_rx); ++ ++ aq_nic->aq_hw_ops->hw_ring_rx_stop(aq_nic->aq_hw, &aq_ptp->hwts_rx); ++} ++ ++void aq_ptp_ring_deinit(struct aq_nic_s *aq_nic) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ ++ if (!aq_ptp || !aq_ptp->ptp_tx.aq_nic || !aq_ptp->ptp_rx.aq_nic) ++ return; ++ ++ aq_ring_tx_clean(&aq_ptp->ptp_tx); ++ aq_ring_rx_deinit(&aq_ptp->ptp_rx); ++} ++ ++#define PTP_8TC_RING_IDX 8 ++#define PTP_4TC_RING_IDX 16 ++#define PTP_HWST_RING_IDX 31 ++ ++int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ unsigned int tx_ring_idx, rx_ring_idx; ++ struct aq_ring_s *hwts = 0; ++ u32 tx_tc_mode, rx_tc_mode; ++ struct aq_ring_s *ring; ++ int err; ++ ++ if (!aq_ptp) ++ return 0; ++ ++ /* Index must to be 8 (8 TCs) or 16 (4 TCs). ++ * It depends from Traffic Class mode. ++ */ ++ aq_nic->aq_hw_ops->hw_tx_tc_mode_get(aq_nic->aq_hw, &tx_tc_mode); ++ if (tx_tc_mode == 0) ++ tx_ring_idx = PTP_8TC_RING_IDX; ++ else ++ tx_ring_idx = PTP_4TC_RING_IDX; ++ ++ ring = aq_ring_tx_alloc(&aq_ptp->ptp_tx, aq_nic, ++ tx_ring_idx, &aq_nic->aq_nic_cfg); ++ if (!ring) { ++ err = -ENOMEM; ++ goto err_exit; ++ } ++ ++ aq_nic->aq_hw_ops->hw_rx_tc_mode_get(aq_nic->aq_hw, &rx_tc_mode); ++ if (rx_tc_mode == 0) ++ rx_ring_idx = PTP_8TC_RING_IDX; ++ else ++ rx_ring_idx = PTP_4TC_RING_IDX; ++ ++ ring = aq_ring_rx_alloc(&aq_ptp->ptp_rx, aq_nic, ++ rx_ring_idx, &aq_nic->aq_nic_cfg); ++ if (!ring) { ++ err = -ENOMEM; ++ goto err_exit_ptp_tx; ++ } ++ ++ hwts = aq_ring_hwts_rx_alloc(&aq_ptp->hwts_rx, aq_nic, PTP_HWST_RING_IDX, ++ aq_nic->aq_nic_cfg.rxds, ++ aq_nic->aq_nic_cfg.aq_hw_caps->rxd_size); ++ if (!hwts) { ++ err = -ENOMEM; ++ goto err_exit_ptp_rx; ++ } ++ ++ err = aq_ptp_skb_ring_init(&aq_ptp->skb_ring, aq_nic->aq_nic_cfg.rxds); ++ if (err != 0) { ++ err = -ENOMEM; ++ goto err_exit_hwts_rx; ++ } ++ ++ return 0; ++ ++err_exit_hwts_rx: ++ aq_ring_free(&aq_ptp->hwts_rx); ++err_exit_ptp_rx: ++ aq_ring_free(&aq_ptp->ptp_rx); ++err_exit_ptp_tx: ++ aq_ring_free(&aq_ptp->ptp_tx); ++err_exit: ++ return err; ++} ++ ++void aq_ptp_ring_free(struct aq_nic_s *aq_nic) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ ++ if (!aq_ptp) ++ return; ++ ++ aq_ring_free(&aq_ptp->ptp_tx); ++ aq_ring_free(&aq_ptp->ptp_rx); ++ aq_ring_free(&aq_ptp->hwts_rx); ++ ++ aq_ptp_skb_ring_release(&aq_ptp->skb_ring); ++} ++ + static struct ptp_clock_info aq_ptp_clock = { + .owner = THIS_MODULE, + .name = "atlantic ptp", +@@ -122,6 +347,15 @@ static struct ptp_clock_info aq_ptp_clock = { + .pin_config = NULL, + }; + ++void aq_ptp_clock_init(struct aq_nic_s *aq_nic) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ struct timespec64 ts; ++ ++ ktime_get_real_ts64(&ts); ++ aq_ptp_settime(&aq_ptp->ptp_info, &ts); ++} ++ + int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + { + struct hw_atl_utils_mbox mbox; +@@ -155,6 +389,7 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + aq_ptp->aq_nic = aq_nic; + + spin_lock_init(&aq_ptp->ptp_lock); ++ spin_lock_init(&aq_ptp->ptp_ring_lock); + + aq_ptp->ptp_info = aq_ptp_clock; + clock = ptp_clock_register(&aq_ptp->ptp_info, &aq_nic->ndev->dev); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +index cea238959b20..32350f75e138 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +@@ -17,6 +17,14 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec); + void aq_ptp_unregister(struct aq_nic_s *aq_nic); + void aq_ptp_free(struct aq_nic_s *aq_nic); + ++int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic); ++void aq_ptp_ring_free(struct aq_nic_s *aq_nic); ++ ++int aq_ptp_ring_init(struct aq_nic_s *aq_nic); ++int aq_ptp_ring_start(struct aq_nic_s *aq_nic); ++void aq_ptp_ring_stop(struct aq_nic_s *aq_nic); ++void aq_ptp_ring_deinit(struct aq_nic_s *aq_nic); ++ + void aq_ptp_clock_init(struct aq_nic_s *aq_nic); + + #endif /* AQ_PTP_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index 76bdbe1596d6..8e84ff6eefe3 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File aq_ring.c: Definition of functions for Rx/Tx rings. */ +@@ -177,6 +177,30 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self, + return self; + } + ++struct aq_ring_s * ++aq_ring_hwts_rx_alloc(struct aq_ring_s *self, struct aq_nic_s *aq_nic, ++ unsigned int idx, unsigned int size, unsigned int dx_size) ++{ ++ struct device *dev = aq_nic_get_dev(aq_nic); ++ size_t sz = size * dx_size + AQ_CFG_RXDS_DEF; ++ ++ memset(self, 0, sizeof(*self)); ++ ++ self->aq_nic = aq_nic; ++ self->idx = idx; ++ self->size = size; ++ self->dx_size = dx_size; ++ ++ self->dx_ring = dma_alloc_coherent(dev, sz, &self->dx_ring_pa, ++ GFP_KERNEL); ++ if (!self->dx_ring) { ++ aq_ring_free(self); ++ return NULL; ++ } ++ ++ return self; ++} ++ + int aq_ring_init(struct aq_ring_s *self) + { + self->hw_head = 0; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +index 47abd09d06c2..068689f44bc9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File aq_ring.h: Declaration of functions for Rx/Tx rings. */ +@@ -174,4 +174,8 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + int budget); + int aq_ring_rx_fill(struct aq_ring_s *self); + ++struct aq_ring_s *aq_ring_hwts_rx_alloc(struct aq_ring_s *self, ++ struct aq_nic_s *aq_nic, unsigned int idx, ++ unsigned int size, unsigned int dx_size); ++ + #endif /* AQ_RING_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 881caa8ee319..55c7f9985692 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -126,13 +126,16 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U); + hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U); + +- hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF, 0U); +- hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0x64, 0U); +- hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, 0U); +- hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, 0U); ++ tc = 0; ++ ++ /* TX Packet Scheduler Data TC0 */ ++ hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF, tc); ++ hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0x64, tc); ++ hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, tc); ++ hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc); + +- /* Tx buf size */ +- buff_size = HW_ATL_B0_TXBUF_MAX; ++ /* Tx buf size TC0 */ ++ buff_size = HW_ATL_B0_TXBUF_MAX - HW_ATL_B0_PTP_TXBUF_SIZE; + + hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, buff_size, tc); + hw_atl_tpb_tx_buff_hi_threshold_per_tc_set(self, +@@ -143,10 +146,15 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + (buff_size * + (1024 / 32U) * 50U) / + 100U, tc); ++ /* Init TC2 for PTP_TX */ ++ tc = 2; ++ ++ hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, HW_ATL_B0_PTP_TXBUF_SIZE, ++ tc); + + /* QoS Rx buf size per TC */ + tc = 0; +- buff_size = HW_ATL_B0_RXBUF_MAX; ++ buff_size = HW_ATL_B0_RXBUF_MAX - HW_ATL_B0_PTP_RXBUF_SIZE; + + hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, buff_size, tc); + hw_atl_rpb_rx_buff_hi_threshold_per_tc_set(self, +@@ -160,6 +168,14 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + + hw_atl_b0_set_fc(self, self->aq_nic_cfg->flow_control, tc); + ++ /* Init TC2 for PTP_RX */ ++ tc = 2; ++ ++ hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, HW_ATL_B0_PTP_RXBUF_SIZE, ++ tc); ++ /* No flow control for PTP */ ++ hw_atl_rpb_rx_xoff_en_per_tc_set(self, 0U, tc); ++ + /* QoS 802.1p priority -> TC mapping */ + for (i_priority = 8U; i_priority--;) + hw_atl_rpf_rpb_user_priority_tc_map_set(self, i_priority, 0U); +@@ -1007,6 +1023,18 @@ static int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, + return aq_hw_err_from_flags(self); + } + ++static int hw_atl_b0_tx_tc_mode_get(struct aq_hw_s *self, u32 *tc_mode) ++{ ++ *tc_mode = hw_atl_rpb_tps_tx_tc_mode_get(self); ++ return aq_hw_err_from_flags(self); ++} ++ ++static int hw_atl_b0_rx_tc_mode_get(struct aq_hw_s *self, u32 *tc_mode) ++{ ++ *tc_mode = hw_atl_rpb_rpf_rx_traf_class_mode_get(self); ++ return aq_hw_err_from_flags(self); ++} ++ + #define get_ptp_ts_val_u64(self, indx) \ + ((u64)(hw_atl_pcs_ptp_clock_get(self, indx) & 0xffff)) + +@@ -1278,6 +1306,9 @@ const struct aq_hw_ops hw_atl_ops_b0 = { + .hw_get_hw_stats = hw_atl_utils_get_hw_stats, + .hw_get_fw_version = hw_atl_utils_get_fw_version, + ++ .hw_tx_tc_mode_get = hw_atl_b0_tx_tc_mode_get, ++ .hw_rx_tc_mode_get = hw_atl_b0_rx_tc_mode_get, ++ + .hw_get_ptp_ts = hw_atl_b0_get_ptp_ts, + .hw_adj_sys_clock = hw_atl_b0_adj_sys_clock, + .hw_set_sys_clock = hw_atl_b0_set_sys_clock, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +index 808d8cd4252a..7ab23a1751d3 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File hw_atl_b0_internal.h: Definition of Atlantic B0 chip specific +@@ -64,8 +64,11 @@ + #define HW_ATL_B0_MPI_SPEED_MSK 0xFFFFU + #define HW_ATL_B0_MPI_SPEED_SHIFT 16U + +-#define HW_ATL_B0_TXBUF_MAX 160U +-#define HW_ATL_B0_RXBUF_MAX 320U ++#define HW_ATL_B0_TXBUF_MAX 160U ++#define HW_ATL_B0_PTP_TXBUF_SIZE 8U ++ ++#define HW_ATL_B0_RXBUF_MAX 320U ++#define HW_ATL_B0_PTP_RXBUF_SIZE 16U + + #define HW_ATL_B0_RSS_REDIRECTION_MAX 64U + #define HW_ATL_B0_RSS_REDIRECTION_BITS 3U +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index eb982288fc52..368b5caf3c49 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -572,6 +572,13 @@ void hw_atl_rpb_rpf_rx_traf_class_mode_set(struct aq_hw_s *aq_hw, + rx_traf_class_mode); + } + ++u32 hw_atl_rpb_rpf_rx_traf_class_mode_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg_bit(aq_hw, HW_ATL_RPB_RPF_RX_TC_MODE_ADR, ++ HW_ATL_RPB_RPF_RX_TC_MODE_MSK, ++ HW_ATL_RPB_RPF_RX_TC_MODE_SHIFT); ++} ++ + void hw_atl_rpb_rx_buff_en_set(struct aq_hw_s *aq_hw, u32 rx_buff_en) + { + aq_hw_write_reg_bit(aq_hw, HW_ATL_RPB_RX_BUF_EN_ADR, +@@ -1290,6 +1297,13 @@ void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en) + HW_ATL_TPB_TX_BUF_EN_SHIFT, tx_buff_en); + } + ++u32 hw_atl_rpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg_bit(aq_hw, HW_ATL_TPB_TX_TC_MODE_ADDR, ++ HW_ATL_TPB_TX_TC_MODE_MSK, ++ HW_ATL_TPB_TX_TC_MODE_SHIFT); ++} ++ + void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw, + u32 tx_traf_class_mode) + { +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index 7753ab860c95..a579864b6ba1 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -292,6 +292,9 @@ void hw_atl_rpb_dma_sys_lbk_set(struct aq_hw_s *aq_hw, u32 dma_sys_lbk); + void hw_atl_rpb_rpf_rx_traf_class_mode_set(struct aq_hw_s *aq_hw, + u32 rx_traf_class_mode); + ++/* get rx traffic class mode */ ++u32 hw_atl_rpb_rpf_rx_traf_class_mode_get(struct aq_hw_s *aq_hw); ++ + /* set rx buffer enable */ + void hw_atl_rpb_rx_buff_en_set(struct aq_hw_s *aq_hw, u32 rx_buff_en); + +@@ -605,6 +608,9 @@ void hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(struct aq_hw_s *aq_hw, + void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw, + u32 tx_traf_class_mode); + ++/* get TX Traffic Class Mode */ ++u32 hw_atl_rpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw); ++ + /* set tx buffer enable */ + void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index f2eb94f298e2..77132bda4696 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -44,6 +44,14 @@ struct __packed hw_atl_rxd_wb_s { + u16 vlan; + }; + ++/* Hardware rx HW TIMESTAMP writeback */ ++struct __packed hw_atl_rxd_hwts_wb_s { ++ u32 sec_hw; ++ u32 ns; ++ u32 sec_lw0; ++ u32 sec_lw1; ++}; ++ + struct __packed hw_atl_stats_s { + u32 uprc; + u32 mprc; +-- +2.13.6 + diff --git a/SOURCES/0023-netdrv-net-aquantia-styling-fixes-on-ptp-related-fun.patch b/SOURCES/0023-netdrv-net-aquantia-styling-fixes-on-ptp-related-fun.patch new file mode 100644 index 0000000..b3d3dee --- /dev/null +++ b/SOURCES/0023-netdrv-net-aquantia-styling-fixes-on-ptp-related-fun.patch @@ -0,0 +1,92 @@ +From 05ef343aaccc3260bd10f1915e2f77c2a4ec0bc7 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:40 -0500 +Subject: [PATCH 023/139] [netdrv] net: aquantia: styling fixes on ptp related + functions + +Message-id: <1604687916-15087-24-git-send-email-irusskik@redhat.com> +Patchwork-id: 338458 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 023/139] net: aquantia: styling fixes on ptp related functions +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 61cc502ef428d104f4c35baa3ea099ae80318275 +Author: Dmitry Bezrukov +Date: Tue Oct 22 09:53:32 2019 +0000 + + net: aquantia: styling fixes on ptp related functions + + Checkpatch and styling fixes on parts of code touched by ptp + + Signed-off-by: Dmitry Bezrukov + Signed-off-by: Igor Russkikh + Reviewed-by: Andrew Lunn + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 4 ++-- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 9 ++++++--- + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index 368b5caf3c49..d83f1a34a537 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -643,8 +643,8 @@ void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, + rx_pkt_buff_size_per_tc); + } + +-void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, u32 rx_xoff_en_per_tc, +- u32 buffer) ++void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, ++ u32 rx_xoff_en_per_tc, u32 buffer) + { + aq_hw_write_reg_bit(aq_hw, HW_ATL_RPB_RXBXOFF_EN_ADR(buffer), + HW_ATL_RPB_RXBXOFF_EN_MSK, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index a579864b6ba1..b192702a7b8b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -309,7 +309,8 @@ void hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(struct aq_hw_s *aq_hw, + u32 buffer); + + /* set rx flow control mode */ +-void hw_atl_rpb_rx_flow_ctl_mode_set(struct aq_hw_s *aq_hw, u32 rx_flow_ctl_mode); ++void hw_atl_rpb_rx_flow_ctl_mode_set(struct aq_hw_s *aq_hw, ++ u32 rx_flow_ctl_mode); + + /* set rx packet buffer size (per tc) */ + void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, +@@ -323,7 +324,8 @@ void hw_atl_rdm_rx_dma_desc_cache_init_tgl(struct aq_hw_s *aq_hw); + u32 hw_atl_rdm_rx_dma_desc_cache_init_done_get(struct aq_hw_s *aq_hw); + + /* set rx xoff enable (per tc) */ +-void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, u32 rx_xoff_en_per_tc, ++void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, ++ u32 rx_xoff_en_per_tc, + u32 buffer); + + /* rpf */ +@@ -629,7 +631,8 @@ void hw_atl_tpb_tx_dma_sys_lbk_en_set(struct aq_hw_s *aq_hw, u32 tx_dma_sys_lbk_ + + /* set tx packet buffer size (per tc) */ + void hw_atl_tpb_tx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, +- u32 tx_pkt_buff_size_per_tc, u32 buffer); ++ u32 tx_pkt_buff_size_per_tc, ++ u32 buffer); + + /* set tx path pad insert enable */ + void hw_atl_tpb_tx_path_scp_ins_en_set(struct aq_hw_s *aq_hw, u32 tx_path_scp_ins_en); +-- +2.13.6 + diff --git a/SOURCES/0024-netdrv-net-aquantia-implement-data-PTP-datapath.patch b/SOURCES/0024-netdrv-net-aquantia-implement-data-PTP-datapath.patch new file mode 100644 index 0000000..e5913b1 --- /dev/null +++ b/SOURCES/0024-netdrv-net-aquantia-implement-data-PTP-datapath.patch @@ -0,0 +1,1162 @@ +From 1da5e0bee9685a47f5f7fdb550728baecc84d92f Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:41 -0500 +Subject: [PATCH 024/139] [netdrv] net: aquantia: implement data PTP datapath + +Message-id: <1604687916-15087-25-git-send-email-irusskik@redhat.com> +Patchwork-id: 338453 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 024/139] net: aquantia: implement data PTP datapath +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 04a1839950d92ab6519479bc95710e89ae6cbc77 +Author: Egor Pomozov +Date: Tue Oct 22 09:53:35 2019 +0000 + + net: aquantia: implement data PTP datapath + + Here we do alloc/free IRQs for PTP rings. + We also implement processing of PTP packets on TX and RX sides. + + Signed-off-by: Egor Pomozov + Co-developed-by: Sergey Samoilenko + Signed-off-by: Sergey Samoilenko + Co-developed-by: Dmitry Bezrukov + Signed-off-by: Dmitry Bezrukov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_cfg.h | 4 +- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 12 + + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 23 +- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 18 +- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 3 + + .../net/ethernet/aquantia/atlantic/aq_pci_func.c | 5 +- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 534 ++++++++++++++++++++- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.h | 19 + + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 31 +- + drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 1 + + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 100 ++++ + 11 files changed, 738 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +index 02f1b70c4e25..8c633caf79d2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File aq_cfg.h: Definition of configuration parameters and constants. */ +@@ -27,7 +27,7 @@ + + #define AQ_CFG_INTERRUPT_MODERATION_USEC_MAX (0x1FF * 2) + +-#define AQ_CFG_IRQ_MASK 0x1FFU ++#define AQ_CFG_IRQ_MASK 0x3FFU + + #define AQ_CFG_VECS_MAX 8U + #define AQ_CFG_TCS_MAX 8U +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index fa943852757e..a9880c7be60f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -244,6 +244,12 @@ struct aq_hw_ops { + + int (*hw_rx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode); + ++ int (*hw_ring_hwts_rx_fill)(struct aq_hw_s *self, ++ struct aq_ring_s *aq_ring); ++ ++ int (*hw_ring_hwts_rx_receive)(struct aq_hw_s *self, ++ struct aq_ring_s *ring); ++ + void (*hw_get_ptp_ts)(struct aq_hw_s *self, u64 *stamp); + + int (*hw_adj_clock_freq)(struct aq_hw_s *self, s32 delta); +@@ -252,6 +258,12 @@ struct aq_hw_ops { + + int (*hw_set_sys_clock)(struct aq_hw_s *self, u64 time, u64 ts); + ++ u16 (*rx_extract_ts)(struct aq_hw_s *self, u8 *p, unsigned int len, ++ u64 *timestamp); ++ ++ int (*extract_hwts)(struct aq_hw_s *self, u8 *p, unsigned int len, ++ u64 *timestamp); ++ + int (*hw_set_fc)(struct aq_hw_s *self, u32 fc, u32 tc); + }; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index bb65dd39f847..f630032af8e1 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File aq_main.c: Main file for aQuantia Linux driver. */ +@@ -10,10 +10,13 @@ + #include "aq_nic.h" + #include "aq_pci_func.h" + #include "aq_ethtool.h" ++#include "aq_ptp.h" + #include "aq_filters.h" + + #include + #include ++#include ++#include + + MODULE_LICENSE("GPL v2"); + MODULE_VERSION(AQ_CFG_DRV_VERSION); +@@ -93,6 +96,24 @@ static int aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); + ++ if (unlikely(aq_utils_obj_test(&aq_nic->flags, AQ_NIC_PTP_DPATH_UP))) { ++ /* Hardware adds the Timestamp for PTPv2 802.AS1 ++ * and PTPv2 IPv4 UDP. ++ * We have to push even general 320 port messages to the ptp ++ * queue explicitly. This is a limitation of current firmware ++ * and hardware PTP design of the chip. Otherwise ptp stream ++ * will fail to sync ++ */ ++ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) || ++ unlikely((ip_hdr(skb)->version == 4) && ++ (ip_hdr(skb)->protocol == IPPROTO_UDP) && ++ ((udp_hdr(skb)->dest == htons(319)) || ++ (udp_hdr(skb)->dest == htons(320)))) || ++ unlikely(eth_hdr(skb)->h_proto == htons(ETH_P_1588))) ++ return aq_ptp_xmit(aq_nic, skb); ++ } ++ ++ skb_tx_timestamp(skb); + return aq_nic_xmit(aq_nic, skb); + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index ecca2c4cf140..65384f45805f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -146,8 +146,11 @@ static int aq_nic_update_link_status(struct aq_nic_s *self) + self->aq_hw->aq_link_status.mbps); + aq_nic_update_interrupt_moderation_settings(self); + +- if (self->aq_ptp) ++ if (self->aq_ptp) { + aq_ptp_clock_init(self); ++ aq_ptp_tm_offset_set(self, ++ self->aq_hw->aq_link_status.mbps); ++ } + + /* Driver has to update flow control settings on RX block + * on any link event. +@@ -196,6 +199,8 @@ static void aq_nic_service_task(struct work_struct *work) + service_task); + int err; + ++ aq_ptp_service_task(self); ++ + if (aq_utils_obj_test(&self->flags, AQ_NIC_FLAGS_IS_NOT_READY)) + return; + +@@ -408,6 +413,10 @@ int aq_nic_start(struct aq_nic_s *self) + goto err_exit; + } + ++ err = aq_ptp_irq_alloc(self); ++ if (err < 0) ++ goto err_exit; ++ + if (self->aq_nic_cfg.link_irq_vec) { + int irqvec = pci_irq_vector(self->pdev, + self->aq_nic_cfg.link_irq_vec); +@@ -440,9 +449,8 @@ int aq_nic_start(struct aq_nic_s *self) + return err; + } + +-static unsigned int aq_nic_map_skb(struct aq_nic_s *self, +- struct sk_buff *skb, +- struct aq_ring_s *ring) ++unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, ++ struct aq_ring_s *ring) + { + unsigned int ret = 0U; + unsigned int nr_frags = skb_shinfo(skb)->nr_frags; +@@ -973,6 +981,8 @@ int aq_nic_stop(struct aq_nic_s *self) + else + aq_pci_func_free_irqs(self); + ++ aq_ptp_irq_free(self); ++ + for (i = 0U, aq_vec = self->aq_vec[0]; + self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) + aq_vec_stop(aq_vec); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index d0979bba7ed3..576432adda4c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -54,6 +54,7 @@ struct aq_nic_cfg_s { + #define AQ_NIC_FLAG_STOPPING 0x00000008U + #define AQ_NIC_FLAG_RESETTING 0x00000010U + #define AQ_NIC_FLAG_CLOSING 0x00000020U ++#define AQ_NIC_PTP_DPATH_UP 0x02000000U + #define AQ_NIC_LINK_DOWN 0x04000000U + #define AQ_NIC_FLAG_ERR_UNPLUG 0x40000000U + #define AQ_NIC_FLAG_ERR_HW 0x80000000U +@@ -129,6 +130,8 @@ void aq_nic_cfg_start(struct aq_nic_s *self); + int aq_nic_ndev_register(struct aq_nic_s *self); + void aq_nic_ndev_free(struct aq_nic_s *self); + int aq_nic_start(struct aq_nic_s *self); ++unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, ++ struct aq_ring_s *ring); + int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb); + int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p); + int aq_nic_get_regs_count(struct aq_nic_s *self); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +index 74b9f3f1da81..e82c96b50373 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File aq_pci_func.c: Definition of PCI functions. */ +@@ -269,6 +269,9 @@ static int aq_pci_probe(struct pci_dev *pdev, + numvecs = min((u8)AQ_CFG_VECS_DEF, + aq_nic_get_cfg(self)->aq_hw_caps->msix_irqs); + numvecs = min(numvecs, num_online_cpus()); ++ /* Request IRQ vector for PTP */ ++ numvecs += 1; ++ + numvecs += AQ_HW_SERVICE_IRQS; + /*enable interrupts */ + #if !AQ_CFG_FORCE_LEGACY_INT +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index f2fd0ca14a49..fbb1912a34d7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -8,12 +8,24 @@ + */ + + #include ++#include + #include + + #include "aq_nic.h" + #include "aq_ptp.h" + #include "aq_ring.h" + ++#define AQ_PTP_TX_TIMEOUT (HZ * 10) ++ ++enum ptp_speed_offsets { ++ ptp_offset_idx_10 = 0, ++ ptp_offset_idx_100, ++ ptp_offset_idx_1000, ++ ptp_offset_idx_2500, ++ ptp_offset_idx_5000, ++ ptp_offset_idx_10000, ++}; ++ + struct ptp_skb_ring { + struct sk_buff **buff; + spinlock_t lock; +@@ -22,6 +34,12 @@ struct ptp_skb_ring { + unsigned int tail; + }; + ++struct ptp_tx_timeout { ++ spinlock_t lock; ++ bool active; ++ unsigned long tx_start; ++}; ++ + struct aq_ptp_s { + struct aq_nic_s *aq_nic; + spinlock_t ptp_lock; +@@ -29,8 +47,16 @@ struct aq_ptp_s { + struct ptp_clock *ptp_clock; + struct ptp_clock_info ptp_info; + ++ atomic_t offset_egress; ++ atomic_t offset_ingress; ++ + struct aq_ring_param_s ptp_ring_param; + ++ struct ptp_tx_timeout ptp_tx_timeout; ++ ++ unsigned int idx_vector; ++ struct napi_struct napi; ++ + struct aq_ring_s ptp_tx; + struct aq_ring_s ptp_rx; + struct aq_ring_s hwts_rx; +@@ -38,6 +64,101 @@ struct aq_ptp_s { + struct ptp_skb_ring skb_ring; + }; + ++struct ptp_tm_offset { ++ unsigned int mbps; ++ int egress; ++ int ingress; ++}; ++ ++static struct ptp_tm_offset ptp_offset[6]; ++ ++void aq_ptp_tm_offset_set(struct aq_nic_s *aq_nic, unsigned int mbps) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ int i, egress, ingress; ++ ++ if (!aq_ptp) ++ return; ++ ++ egress = 0; ++ ingress = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(ptp_offset); i++) { ++ if (mbps == ptp_offset[i].mbps) { ++ egress = ptp_offset[i].egress; ++ ingress = ptp_offset[i].ingress; ++ break; ++ } ++ } ++ ++ atomic_set(&aq_ptp->offset_egress, egress); ++ atomic_set(&aq_ptp->offset_ingress, ingress); ++} ++ ++static int __aq_ptp_skb_put(struct ptp_skb_ring *ring, struct sk_buff *skb) ++{ ++ unsigned int next_head = (ring->head + 1) % ring->size; ++ ++ if (next_head == ring->tail) ++ return -ENOMEM; ++ ++ ring->buff[ring->head] = skb_get(skb); ++ ring->head = next_head; ++ ++ return 0; ++} ++ ++static int aq_ptp_skb_put(struct ptp_skb_ring *ring, struct sk_buff *skb) ++{ ++ unsigned long flags; ++ int ret; ++ ++ spin_lock_irqsave(&ring->lock, flags); ++ ret = __aq_ptp_skb_put(ring, skb); ++ spin_unlock_irqrestore(&ring->lock, flags); ++ ++ return ret; ++} ++ ++static struct sk_buff *__aq_ptp_skb_get(struct ptp_skb_ring *ring) ++{ ++ struct sk_buff *skb; ++ ++ if (ring->tail == ring->head) ++ return NULL; ++ ++ skb = ring->buff[ring->tail]; ++ ring->tail = (ring->tail + 1) % ring->size; ++ ++ return skb; ++} ++ ++static struct sk_buff *aq_ptp_skb_get(struct ptp_skb_ring *ring) ++{ ++ unsigned long flags; ++ struct sk_buff *skb; ++ ++ spin_lock_irqsave(&ring->lock, flags); ++ skb = __aq_ptp_skb_get(ring); ++ spin_unlock_irqrestore(&ring->lock, flags); ++ ++ return skb; ++} ++ ++static unsigned int aq_ptp_skb_buf_len(struct ptp_skb_ring *ring) ++{ ++ unsigned long flags; ++ unsigned int len; ++ ++ spin_lock_irqsave(&ring->lock, flags); ++ len = (ring->head >= ring->tail) ? ++ ring->head - ring->tail : ++ ring->size - ring->tail + ring->head; ++ spin_unlock_irqrestore(&ring->lock, flags); ++ ++ return len; ++} ++ + static int aq_ptp_skb_ring_init(struct ptp_skb_ring *ring, unsigned int size) + { + struct sk_buff **buff = kmalloc(sizeof(*buff) * size, GFP_KERNEL); +@@ -55,10 +176,75 @@ static int aq_ptp_skb_ring_init(struct ptp_skb_ring *ring, unsigned int size) + return 0; + } + ++static void aq_ptp_skb_ring_clean(struct ptp_skb_ring *ring) ++{ ++ struct sk_buff *skb; ++ ++ while ((skb = aq_ptp_skb_get(ring)) != NULL) ++ dev_kfree_skb_any(skb); ++} ++ + static void aq_ptp_skb_ring_release(struct ptp_skb_ring *ring) + { +- kfree(ring->buff); +- ring->buff = NULL; ++ if (ring->buff) { ++ aq_ptp_skb_ring_clean(ring); ++ kfree(ring->buff); ++ ring->buff = NULL; ++ } ++} ++ ++static void aq_ptp_tx_timeout_init(struct ptp_tx_timeout *timeout) ++{ ++ spin_lock_init(&timeout->lock); ++ timeout->active = false; ++} ++ ++static void aq_ptp_tx_timeout_start(struct aq_ptp_s *aq_ptp) ++{ ++ struct ptp_tx_timeout *timeout = &aq_ptp->ptp_tx_timeout; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&timeout->lock, flags); ++ timeout->active = true; ++ timeout->tx_start = jiffies; ++ spin_unlock_irqrestore(&timeout->lock, flags); ++} ++ ++static void aq_ptp_tx_timeout_update(struct aq_ptp_s *aq_ptp) ++{ ++ if (!aq_ptp_skb_buf_len(&aq_ptp->skb_ring)) { ++ struct ptp_tx_timeout *timeout = &aq_ptp->ptp_tx_timeout; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&timeout->lock, flags); ++ timeout->active = false; ++ spin_unlock_irqrestore(&timeout->lock, flags); ++ } ++} ++ ++static void aq_ptp_tx_timeout_check(struct aq_ptp_s *aq_ptp) ++{ ++ struct ptp_tx_timeout *timeout = &aq_ptp->ptp_tx_timeout; ++ unsigned long flags; ++ bool timeout_flag; ++ ++ timeout_flag = false; ++ ++ spin_lock_irqsave(&timeout->lock, flags); ++ if (timeout->active) { ++ timeout_flag = time_is_before_jiffies(timeout->tx_start + ++ AQ_PTP_TX_TIMEOUT); ++ /* reset active flag if timeout detected */ ++ if (timeout_flag) ++ timeout->active = false; ++ } ++ spin_unlock_irqrestore(&timeout->lock, flags); ++ ++ if (timeout_flag) { ++ aq_ptp_skb_ring_clean(&aq_ptp->skb_ring); ++ netdev_err(aq_ptp->aq_nic->ndev, ++ "PTP Timeout. Clearing Tx Timestamp SKBs\n"); ++ } + } + + /* aq_ptp_adjfine +@@ -148,6 +334,263 @@ static int aq_ptp_settime(struct ptp_clock_info *ptp, + return 0; + } + ++static void aq_ptp_convert_to_hwtstamp(struct aq_ptp_s *aq_ptp, ++ struct skb_shared_hwtstamps *hwtstamp, ++ u64 timestamp) ++{ ++ memset(hwtstamp, 0, sizeof(*hwtstamp)); ++ hwtstamp->hwtstamp = ns_to_ktime(timestamp); ++} ++ ++/* aq_ptp_tx_hwtstamp - utility function which checks for TX time stamp ++ * @adapter: the private adapter struct ++ * ++ * if the timestamp is valid, we convert it into the timecounter ns ++ * value, then store that result into the hwtstamps structure which ++ * is passed up the network stack ++ */ ++void aq_ptp_tx_hwtstamp(struct aq_nic_s *aq_nic, u64 timestamp) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ struct sk_buff *skb = aq_ptp_skb_get(&aq_ptp->skb_ring); ++ struct skb_shared_hwtstamps hwtstamp; ++ ++ if (!skb) { ++ netdev_err(aq_nic->ndev, "have timestamp but tx_queus empty\n"); ++ return; ++ } ++ ++ timestamp += atomic_read(&aq_ptp->offset_egress); ++ aq_ptp_convert_to_hwtstamp(aq_ptp, &hwtstamp, timestamp); ++ skb_tstamp_tx(skb, &hwtstamp); ++ dev_kfree_skb_any(skb); ++ ++ aq_ptp_tx_timeout_update(aq_ptp); ++} ++ ++/* aq_ptp_rx_hwtstamp - utility function which checks for RX time stamp ++ * @adapter: pointer to adapter struct ++ * @skb: particular skb to send timestamp with ++ * ++ * if the timestamp is valid, we convert it into the timecounter ns ++ * value, then store that result into the hwtstamps structure which ++ * is passed up the network stack ++ */ ++static void aq_ptp_rx_hwtstamp(struct aq_ptp_s *aq_ptp, struct sk_buff *skb, ++ u64 timestamp) ++{ ++ timestamp -= atomic_read(&aq_ptp->offset_ingress); ++ aq_ptp_convert_to_hwtstamp(aq_ptp, skb_hwtstamps(skb), timestamp); ++} ++ ++bool aq_ptp_ring(struct aq_nic_s *aq_nic, struct aq_ring_s *ring) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ ++ if (!aq_ptp) ++ return false; ++ ++ return &aq_ptp->ptp_tx == ring || ++ &aq_ptp->ptp_rx == ring || &aq_ptp->hwts_rx == ring; ++} ++ ++u16 aq_ptp_extract_ts(struct aq_nic_s *aq_nic, struct sk_buff *skb, u8 *p, ++ unsigned int len) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ u64 timestamp = 0; ++ u16 ret = aq_nic->aq_hw_ops->rx_extract_ts(aq_nic->aq_hw, ++ p, len, ×tamp); ++ ++ if (ret > 0) ++ aq_ptp_rx_hwtstamp(aq_ptp, skb, timestamp); ++ ++ return ret; ++} ++ ++static int aq_ptp_poll(struct napi_struct *napi, int budget) ++{ ++ struct aq_ptp_s *aq_ptp = container_of(napi, struct aq_ptp_s, napi); ++ struct aq_nic_s *aq_nic = aq_ptp->aq_nic; ++ bool was_cleaned = false; ++ int work_done = 0; ++ int err; ++ ++ /* Processing PTP TX traffic */ ++ err = aq_nic->aq_hw_ops->hw_ring_tx_head_update(aq_nic->aq_hw, ++ &aq_ptp->ptp_tx); ++ if (err < 0) ++ goto err_exit; ++ ++ if (aq_ptp->ptp_tx.sw_head != aq_ptp->ptp_tx.hw_head) { ++ aq_ring_tx_clean(&aq_ptp->ptp_tx); ++ ++ was_cleaned = true; ++ } ++ ++ /* Processing HW_TIMESTAMP RX traffic */ ++ err = aq_nic->aq_hw_ops->hw_ring_hwts_rx_receive(aq_nic->aq_hw, ++ &aq_ptp->hwts_rx); ++ if (err < 0) ++ goto err_exit; ++ ++ if (aq_ptp->hwts_rx.sw_head != aq_ptp->hwts_rx.hw_head) { ++ aq_ring_hwts_rx_clean(&aq_ptp->hwts_rx, aq_nic); ++ ++ err = aq_nic->aq_hw_ops->hw_ring_hwts_rx_fill(aq_nic->aq_hw, ++ &aq_ptp->hwts_rx); ++ ++ was_cleaned = true; ++ } ++ ++ /* Processing PTP RX traffic */ ++ err = aq_nic->aq_hw_ops->hw_ring_rx_receive(aq_nic->aq_hw, ++ &aq_ptp->ptp_rx); ++ if (err < 0) ++ goto err_exit; ++ ++ if (aq_ptp->ptp_rx.sw_head != aq_ptp->ptp_rx.hw_head) { ++ unsigned int sw_tail_old; ++ ++ err = aq_ring_rx_clean(&aq_ptp->ptp_rx, napi, &work_done, budget); ++ if (err < 0) ++ goto err_exit; ++ ++ sw_tail_old = aq_ptp->ptp_rx.sw_tail; ++ err = aq_ring_rx_fill(&aq_ptp->ptp_rx); ++ if (err < 0) ++ goto err_exit; ++ ++ err = aq_nic->aq_hw_ops->hw_ring_rx_fill(aq_nic->aq_hw, ++ &aq_ptp->ptp_rx, ++ sw_tail_old); ++ if (err < 0) ++ goto err_exit; ++ } ++ ++ if (was_cleaned) ++ work_done = budget; ++ ++ if (work_done < budget) { ++ napi_complete_done(napi, work_done); ++ aq_nic->aq_hw_ops->hw_irq_enable(aq_nic->aq_hw, ++ 1 << aq_ptp->ptp_ring_param.vec_idx); ++ } ++ ++err_exit: ++ return work_done; ++} ++ ++static irqreturn_t aq_ptp_isr(int irq, void *private) ++{ ++ struct aq_ptp_s *aq_ptp = private; ++ int err = 0; ++ ++ if (!aq_ptp) { ++ err = -EINVAL; ++ goto err_exit; ++ } ++ napi_schedule(&aq_ptp->napi); ++ ++err_exit: ++ return err >= 0 ? IRQ_HANDLED : IRQ_NONE; ++} ++ ++int aq_ptp_xmit(struct aq_nic_s *aq_nic, struct sk_buff *skb) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ struct aq_ring_s *ring = &aq_ptp->ptp_tx; ++ unsigned long irq_flags; ++ int err = NETDEV_TX_OK; ++ unsigned int frags; ++ ++ if (skb->len <= 0) { ++ dev_kfree_skb_any(skb); ++ goto err_exit; ++ } ++ ++ frags = skb_shinfo(skb)->nr_frags + 1; ++ /* Frags cannot be bigger 16KB ++ * because PTP usually works ++ * without Jumbo even in a background ++ */ ++ if (frags > AQ_CFG_SKB_FRAGS_MAX || frags > aq_ring_avail_dx(ring)) { ++ /* Drop packet because it doesn't make sence to delay it */ ++ dev_kfree_skb_any(skb); ++ goto err_exit; ++ } ++ ++ err = aq_ptp_skb_put(&aq_ptp->skb_ring, skb); ++ if (err) { ++ netdev_err(aq_nic->ndev, "SKB Ring is overflow (%u)!\n", ++ ring->size); ++ return NETDEV_TX_BUSY; ++ } ++ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; ++ aq_ptp_tx_timeout_start(aq_ptp); ++ skb_tx_timestamp(skb); ++ ++ spin_lock_irqsave(&aq_nic->aq_ptp->ptp_ring_lock, irq_flags); ++ frags = aq_nic_map_skb(aq_nic, skb, ring); ++ ++ if (likely(frags)) { ++ err = aq_nic->aq_hw_ops->hw_ring_tx_xmit(aq_nic->aq_hw, ++ ring, frags); ++ if (err >= 0) { ++ ++ring->stats.tx.packets; ++ ring->stats.tx.bytes += skb->len; ++ } ++ } else { ++ err = NETDEV_TX_BUSY; ++ } ++ spin_unlock_irqrestore(&aq_nic->aq_ptp->ptp_ring_lock, irq_flags); ++ ++err_exit: ++ return err; ++} ++ ++void aq_ptp_service_task(struct aq_nic_s *aq_nic) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ ++ if (!aq_ptp) ++ return; ++ ++ aq_ptp_tx_timeout_check(aq_ptp); ++} ++ ++int aq_ptp_irq_alloc(struct aq_nic_s *aq_nic) ++{ ++ struct pci_dev *pdev = aq_nic->pdev; ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ int err = 0; ++ ++ if (!aq_ptp) ++ return 0; ++ ++ if (pdev->msix_enabled || pdev->msi_enabled) { ++ err = request_irq(pci_irq_vector(pdev, aq_ptp->idx_vector), ++ aq_ptp_isr, 0, aq_nic->ndev->name, aq_ptp); ++ } else { ++ err = -EINVAL; ++ goto err_exit; ++ } ++ ++err_exit: ++ return err; ++} ++ ++void aq_ptp_irq_free(struct aq_nic_s *aq_nic) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ struct pci_dev *pdev = aq_nic->pdev; ++ ++ if (!aq_ptp) ++ return; ++ ++ free_irq(pci_irq_vector(pdev, aq_ptp->idx_vector), aq_ptp); ++} ++ + int aq_ptp_ring_init(struct aq_nic_s *aq_nic) + { + struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; +@@ -189,6 +632,12 @@ int aq_ptp_ring_init(struct aq_nic_s *aq_nic) + err = aq_nic->aq_hw_ops->hw_ring_rx_init(aq_nic->aq_hw, + &aq_ptp->hwts_rx, + &aq_ptp->ptp_ring_param); ++ if (err < 0) ++ goto err_exit; ++ err = aq_nic->aq_hw_ops->hw_ring_hwts_rx_fill(aq_nic->aq_hw, ++ &aq_ptp->hwts_rx); ++ if (err < 0) ++ goto err_exit; + + return err; + +@@ -219,6 +668,8 @@ int aq_ptp_ring_start(struct aq_nic_s *aq_nic) + if (err < 0) + goto err_exit; + ++ napi_enable(&aq_ptp->napi); ++ + err_exit: + return err; + } +@@ -234,6 +685,8 @@ void aq_ptp_ring_stop(struct aq_nic_s *aq_nic) + aq_nic->aq_hw_ops->hw_ring_rx_stop(aq_nic->aq_hw, &aq_ptp->ptp_rx); + + aq_nic->aq_hw_ops->hw_ring_rx_stop(aq_nic->aq_hw, &aq_ptp->hwts_rx); ++ ++ napi_disable(&aq_ptp->napi); + } + + void aq_ptp_ring_deinit(struct aq_nic_s *aq_nic) +@@ -306,6 +759,12 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic) + goto err_exit_hwts_rx; + } + ++ aq_ptp->ptp_ring_param.vec_idx = aq_ptp->idx_vector; ++ aq_ptp->ptp_ring_param.cpu = aq_ptp->ptp_ring_param.vec_idx + ++ aq_nic_get_cfg(aq_nic)->aq_rss.base_cpu_number; ++ cpumask_set_cpu(aq_ptp->ptp_ring_param.cpu, ++ &aq_ptp->ptp_ring_param.affinity_mask); ++ + return 0; + + err_exit_hwts_rx: +@@ -347,6 +806,60 @@ static struct ptp_clock_info aq_ptp_clock = { + .pin_config = NULL, + }; + ++#define ptp_offset_init(__idx, __mbps, __egress, __ingress) do { \ ++ ptp_offset[__idx].mbps = (__mbps); \ ++ ptp_offset[__idx].egress = (__egress); \ ++ ptp_offset[__idx].ingress = (__ingress); } \ ++ while (0) ++ ++static void aq_ptp_offset_init_from_fw(const struct hw_aq_ptp_offset *offsets) ++{ ++ int i; ++ ++ /* Load offsets for PTP */ ++ for (i = 0; i < ARRAY_SIZE(ptp_offset); i++) { ++ switch (i) { ++ /* 100M */ ++ case ptp_offset_idx_100: ++ ptp_offset_init(i, 100, ++ offsets->egress_100, ++ offsets->ingress_100); ++ break; ++ /* 1G */ ++ case ptp_offset_idx_1000: ++ ptp_offset_init(i, 1000, ++ offsets->egress_1000, ++ offsets->ingress_1000); ++ break; ++ /* 2.5G */ ++ case ptp_offset_idx_2500: ++ ptp_offset_init(i, 2500, ++ offsets->egress_2500, ++ offsets->ingress_2500); ++ break; ++ /* 5G */ ++ case ptp_offset_idx_5000: ++ ptp_offset_init(i, 5000, ++ offsets->egress_5000, ++ offsets->ingress_5000); ++ break; ++ /* 10G */ ++ case ptp_offset_idx_10000: ++ ptp_offset_init(i, 10000, ++ offsets->egress_10000, ++ offsets->ingress_10000); ++ break; ++ } ++ } ++} ++ ++static void aq_ptp_offset_init(const struct hw_aq_ptp_offset *offsets) ++{ ++ memset(ptp_offset, 0, sizeof(ptp_offset)); ++ ++ aq_ptp_offset_init_from_fw(offsets); ++} ++ + void aq_ptp_clock_init(struct aq_nic_s *aq_nic) + { + struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; +@@ -380,6 +893,8 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + return 0; + } + ++ aq_ptp_offset_init(&mbox.info.ptp_offset); ++ + aq_ptp = kzalloc(sizeof(*aq_ptp), GFP_KERNEL); + if (!aq_ptp) { + err = -ENOMEM; +@@ -399,6 +914,15 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + goto err_exit; + } + aq_ptp->ptp_clock = clock; ++ aq_ptp_tx_timeout_init(&aq_ptp->ptp_tx_timeout); ++ ++ atomic_set(&aq_ptp->offset_egress, 0); ++ atomic_set(&aq_ptp->offset_ingress, 0); ++ ++ netif_napi_add(aq_nic_get_ndev(aq_nic), &aq_ptp->napi, ++ aq_ptp_poll, AQ_CFG_NAPI_WEIGHT); ++ ++ aq_ptp->idx_vector = idx_vec; + + aq_nic->aq_ptp = aq_ptp; + +@@ -439,6 +963,12 @@ void aq_ptp_free(struct aq_nic_s *aq_nic) + aq_nic->aq_fw_ops->enable_ptp(aq_nic->aq_hw, 0); + mutex_unlock(&aq_nic->fwreq_mutex); + ++ netif_napi_del(&aq_ptp->napi); + kfree(aq_ptp); + aq_nic->aq_ptp = NULL; + } ++ ++struct ptp_clock *aq_ptp_get_ptp_clock(struct aq_ptp_s *aq_ptp) ++{ ++ return aq_ptp->ptp_clock; ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +index 32350f75e138..2c84483fcac1 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +@@ -17,6 +17,9 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec); + void aq_ptp_unregister(struct aq_nic_s *aq_nic); + void aq_ptp_free(struct aq_nic_s *aq_nic); + ++int aq_ptp_irq_alloc(struct aq_nic_s *aq_nic); ++void aq_ptp_irq_free(struct aq_nic_s *aq_nic); ++ + int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic); + void aq_ptp_ring_free(struct aq_nic_s *aq_nic); + +@@ -25,6 +28,22 @@ int aq_ptp_ring_start(struct aq_nic_s *aq_nic); + void aq_ptp_ring_stop(struct aq_nic_s *aq_nic); + void aq_ptp_ring_deinit(struct aq_nic_s *aq_nic); + ++void aq_ptp_service_task(struct aq_nic_s *aq_nic); ++ ++void aq_ptp_tm_offset_set(struct aq_nic_s *aq_nic, unsigned int mbps); ++ + void aq_ptp_clock_init(struct aq_nic_s *aq_nic); + ++/* Traffic processing functions */ ++int aq_ptp_xmit(struct aq_nic_s *aq_nic, struct sk_buff *skb); ++void aq_ptp_tx_hwtstamp(struct aq_nic_s *aq_nic, u64 timestamp); ++ ++/* Return either ring is belong to PTP or not*/ ++bool aq_ptp_ring(struct aq_nic_s *aq_nic, struct aq_ring_s *ring); ++ ++u16 aq_ptp_extract_ts(struct aq_nic_s *aq_nic, struct sk_buff *skb, u8 *p, ++ unsigned int len); ++ ++struct ptp_clock *aq_ptp_get_ptp_clock(struct aq_ptp_s *aq_ptp); ++ + #endif /* AQ_PTP_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index 8e84ff6eefe3..f756cc0bbdf0 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -10,6 +10,7 @@ + #include "aq_nic.h" + #include "aq_hw.h" + #include "aq_hw_utils.h" ++#include "aq_ptp.h" + + #include + #include +@@ -314,6 +315,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + self->sw_head = aq_ring_next_dx(self, self->sw_head), + --budget, ++(*work_done)) { + struct aq_ring_buff_s *buff = &self->buff_ring[self->sw_head]; ++ bool is_ptp_ring = aq_ptp_ring(self->aq_nic, self); + struct aq_ring_buff_s *buff_ = NULL; + struct sk_buff *skb = NULL; + unsigned int next_ = 0U; +@@ -378,6 +380,11 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + err = -ENOMEM; + goto err_exit; + } ++ if (is_ptp_ring) ++ buff->len -= ++ aq_ptp_extract_ts(self->aq_nic, skb, ++ aq_buf_vaddr(&buff->rxdata), ++ buff->len); + skb_put(skb, buff->len); + page_ref_inc(buff->rxdata.page); + } else { +@@ -386,6 +393,11 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + err = -ENOMEM; + goto err_exit; + } ++ if (is_ptp_ring) ++ buff->len -= ++ aq_ptp_extract_ts(self->aq_nic, skb, ++ aq_buf_vaddr(&buff->rxdata), ++ buff->len); + + hdr_len = buff->len; + if (hdr_len > AQ_CFG_RX_HDR_SIZE) +@@ -445,8 +457,8 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + skb_set_hash(skb, buff->rss_hash, + buff->is_hash_l4 ? PKT_HASH_TYPE_L4 : + PKT_HASH_TYPE_NONE); +- +- skb_record_rx_queue(skb, self->idx); ++ /* Send all PTP traffic to 0 queue */ ++ skb_record_rx_queue(skb, is_ptp_ring ? 0 : self->idx); + + ++self->stats.rx.packets; + self->stats.rx.bytes += skb->len; +@@ -458,6 +470,21 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + return err; + } + ++void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic) ++{ ++ while (self->sw_head != self->hw_head) { ++ u64 ns; ++ ++ aq_nic->aq_hw_ops->extract_hwts(aq_nic->aq_hw, ++ self->dx_ring + ++ (self->sw_head * self->dx_size), ++ self->dx_size, &ns); ++ aq_ptp_tx_hwtstamp(aq_nic, ns); ++ ++ self->sw_head = aq_ring_next_dx(self, self->sw_head); ++ } ++} ++ + int aq_ring_rx_fill(struct aq_ring_s *self) + { + unsigned int page_order = self->page_order; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +index 068689f44bc9..be3702a4dcc9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +@@ -177,5 +177,6 @@ int aq_ring_rx_fill(struct aq_ring_s *self); + struct aq_ring_s *aq_ring_hwts_rx_alloc(struct aq_ring_s *self, + struct aq_nic_s *aq_nic, unsigned int idx, + unsigned int size, unsigned int dx_size); ++void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic); + + #endif /* AQ_RING_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 55c7f9985692..bd9e5a598657 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -682,6 +682,46 @@ static int hw_atl_b0_hw_ring_rx_fill(struct aq_hw_s *self, + return aq_hw_err_from_flags(self); + } + ++static int hw_atl_b0_hw_ring_hwts_rx_fill(struct aq_hw_s *self, ++ struct aq_ring_s *ring) ++{ ++ unsigned int i; ++ ++ for (i = aq_ring_avail_dx(ring); i--; ++ ring->sw_tail = aq_ring_next_dx(ring, ring->sw_tail)) { ++ struct hw_atl_rxd_s *rxd = ++ (struct hw_atl_rxd_s *) ++ &ring->dx_ring[ring->sw_tail * HW_ATL_B0_RXD_SIZE]; ++ ++ rxd->buf_addr = ring->dx_ring_pa + ring->size * ring->dx_size; ++ rxd->hdr_addr = 0U; ++ } ++ /* Make sure descriptors are updated before bump tail*/ ++ wmb(); ++ ++ hw_atl_reg_rx_dma_desc_tail_ptr_set(self, ring->sw_tail, ring->idx); ++ ++ return aq_hw_err_from_flags(self); ++} ++ ++static int hw_atl_b0_hw_ring_hwts_rx_receive(struct aq_hw_s *self, ++ struct aq_ring_s *ring) ++{ ++ while (ring->hw_head != ring->sw_tail) { ++ struct hw_atl_rxd_hwts_wb_s *hwts_wb = ++ (struct hw_atl_rxd_hwts_wb_s *) ++ (ring->dx_ring + (ring->hw_head * HW_ATL_B0_RXD_SIZE)); ++ ++ /* RxD is not done */ ++ if (!(hwts_wb->sec_lw0 & 0x1U)) ++ break; ++ ++ ring->hw_head = aq_ring_next_dx(ring, ring->hw_head); ++ } ++ ++ return aq_hw_err_from_flags(self); ++} ++ + static int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self, + struct aq_ring_s *ring) + { +@@ -1133,6 +1173,61 @@ static int hw_atl_b0_adj_clock_freq(struct aq_hw_s *self, s32 ppb) + return self->aq_fw_ops->send_fw_request(self, &fwreq, size); + } + ++static u16 hw_atl_b0_rx_extract_ts(struct aq_hw_s *self, u8 *p, ++ unsigned int len, u64 *timestamp) ++{ ++ unsigned int offset = 14; ++ struct ethhdr *eth; ++ u64 sec; ++ u8 *ptr; ++ u32 ns; ++ ++ if (len <= offset || !timestamp) ++ return 0; ++ ++ /* The TIMESTAMP in the end of package has following format: ++ * (big-endian) ++ * struct { ++ * uint64_t sec; ++ * uint32_t ns; ++ * uint16_t stream_id; ++ * }; ++ */ ++ ptr = p + (len - offset); ++ memcpy(&sec, ptr, sizeof(sec)); ++ ptr += sizeof(sec); ++ memcpy(&ns, ptr, sizeof(ns)); ++ ++ sec = be64_to_cpu(sec) & 0xffffffffffffllu; ++ ns = be32_to_cpu(ns); ++ *timestamp = sec * NSEC_PER_SEC + ns + self->ptp_clk_offset; ++ ++ eth = (struct ethhdr *)p; ++ ++ return (eth->h_proto == htons(ETH_P_1588)) ? 12 : 14; ++} ++ ++static int hw_atl_b0_extract_hwts(struct aq_hw_s *self, u8 *p, unsigned int len, ++ u64 *timestamp) ++{ ++ struct hw_atl_rxd_hwts_wb_s *hwts_wb = (struct hw_atl_rxd_hwts_wb_s *)p; ++ u64 tmp, sec, ns; ++ ++ sec = 0; ++ tmp = (hwts_wb->sec_lw0 >> 2) & 0x3ff; ++ sec += tmp; ++ tmp = (u64)((hwts_wb->sec_lw1 >> 16) & 0xffff) << 10; ++ sec += tmp; ++ tmp = (u64)(hwts_wb->sec_hw & 0xfff) << 26; ++ sec += tmp; ++ tmp = (u64)((hwts_wb->sec_hw >> 22) & 0x3ff) << 38; ++ sec += tmp; ++ ns = sec * NSEC_PER_SEC + hwts_wb->ns; ++ if (timestamp) ++ *timestamp = ns + self->ptp_clk_offset; ++ return 0; ++} ++ + static int hw_atl_b0_hw_fl3l4_clear(struct aq_hw_s *self, + struct aq_rx_filter_l3l4 *data) + { +@@ -1309,11 +1404,16 @@ const struct aq_hw_ops hw_atl_ops_b0 = { + .hw_tx_tc_mode_get = hw_atl_b0_tx_tc_mode_get, + .hw_rx_tc_mode_get = hw_atl_b0_rx_tc_mode_get, + ++ .hw_ring_hwts_rx_fill = hw_atl_b0_hw_ring_hwts_rx_fill, ++ .hw_ring_hwts_rx_receive = hw_atl_b0_hw_ring_hwts_rx_receive, ++ + .hw_get_ptp_ts = hw_atl_b0_get_ptp_ts, + .hw_adj_sys_clock = hw_atl_b0_adj_sys_clock, + .hw_set_sys_clock = hw_atl_b0_set_sys_clock, + .hw_adj_clock_freq = hw_atl_b0_adj_clock_freq, + ++ .rx_extract_ts = hw_atl_b0_rx_extract_ts, ++ .extract_hwts = hw_atl_b0_extract_hwts, + .hw_set_offload = hw_atl_b0_hw_offload_set, + .hw_set_fc = hw_atl_b0_set_fc, + }; +-- +2.13.6 + diff --git a/SOURCES/0025-netdrv-net-aquantia-rx-filters-for-ptp.patch b/SOURCES/0025-netdrv-net-aquantia-rx-filters-for-ptp.patch new file mode 100644 index 0000000..35eb85b --- /dev/null +++ b/SOURCES/0025-netdrv-net-aquantia-rx-filters-for-ptp.patch @@ -0,0 +1,386 @@ +From 15dae649ec3e0bbdb786037f50425d7f58ec8631 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:42 -0500 +Subject: [PATCH 025/139] [netdrv] net: aquantia: rx filters for ptp + +Message-id: <1604687916-15087-26-git-send-email-irusskik@redhat.com> +Patchwork-id: 338446 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 025/139] net: aquantia: rx filters for ptp +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 5a1bf9ef51cfd9bbe12a5a03a12a47eeacc0ef64 +Author: Dmitry Bezrukov +Date: Tue Oct 22 09:53:38 2019 +0000 + + net: aquantia: rx filters for ptp + + We implement HW filter reservation for PTP traffic. Special location + in filters table is marked as reserved, because incoming ptp traffic + should be directed only to PTP designated queue. This way HW will do PTP + timestamping and proper processing. + + Co-developed-by: Egor Pomozov + Signed-off-by: Egor Pomozov + Co-developed-by: Sergey Samoilenko + Signed-off-by: Sergey Samoilenko + Signed-off-by: Dmitry Bezrukov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/aq_filters.c | 17 ++-- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 44 +++++++++++ + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 8 +- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 14 ++++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 12 ++- + .../aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 90 +++++++++++----------- + 6 files changed, 131 insertions(+), 54 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c +index aee827f07c16..6102251bb909 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c +@@ -1,5 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* Copyright (C) 2014-2017 aQuantia Corporation. */ ++/* Copyright (C) 2014-2019 aQuantia Corporation. */ + + /* File aq_filters.c: RX filters related functions. */ + +@@ -89,12 +89,14 @@ static int aq_check_approve_fl3l4(struct aq_nic_s *aq_nic, + struct aq_hw_rx_fltrs_s *rx_fltrs, + struct ethtool_rx_flow_spec *fsp) + { ++ u32 last_location = AQ_RX_LAST_LOC_FL3L4 - ++ aq_nic->aq_hw_rx_fltrs.fl3l4.reserved_count; ++ + if (fsp->location < AQ_RX_FIRST_LOC_FL3L4 || +- fsp->location > AQ_RX_LAST_LOC_FL3L4) { ++ fsp->location > last_location) { + netdev_err(aq_nic->ndev, + "ethtool: location must be in range [%d, %d]", +- AQ_RX_FIRST_LOC_FL3L4, +- AQ_RX_LAST_LOC_FL3L4); ++ AQ_RX_FIRST_LOC_FL3L4, last_location); + return -EINVAL; + } + if (rx_fltrs->fl3l4.is_ipv6 && rx_fltrs->fl3l4.active_ipv4) { +@@ -124,12 +126,15 @@ aq_check_approve_fl2(struct aq_nic_s *aq_nic, + struct aq_hw_rx_fltrs_s *rx_fltrs, + struct ethtool_rx_flow_spec *fsp) + { ++ u32 last_location = AQ_RX_LAST_LOC_FETHERT - ++ aq_nic->aq_hw_rx_fltrs.fet_reserved_count; ++ + if (fsp->location < AQ_RX_FIRST_LOC_FETHERT || +- fsp->location > AQ_RX_LAST_LOC_FETHERT) { ++ fsp->location > last_location) { + netdev_err(aq_nic->ndev, + "ethtool: location must be in range [%d, %d]", + AQ_RX_FIRST_LOC_FETHERT, +- AQ_RX_LAST_LOC_FETHERT); ++ last_location); + return -EINVAL; + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 65384f45805f..22e4a5587c15 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -13,6 +13,7 @@ + #include "aq_pci_func.h" + #include "aq_main.h" + #include "aq_ptp.h" ++#include "aq_filters.h" + + #include + #include +@@ -1105,3 +1106,46 @@ void aq_nic_shutdown(struct aq_nic_s *self) + err_exit: + rtnl_unlock(); + } ++ ++u8 aq_nic_reserve_filter(struct aq_nic_s *self, enum aq_rx_filter_type type) ++{ ++ u8 location = 0xFF; ++ u32 fltr_cnt; ++ u32 n_bit; ++ ++ switch (type) { ++ case aq_rx_filter_ethertype: ++ location = AQ_RX_LAST_LOC_FETHERT - AQ_RX_FIRST_LOC_FETHERT - ++ self->aq_hw_rx_fltrs.fet_reserved_count; ++ self->aq_hw_rx_fltrs.fet_reserved_count++; ++ break; ++ case aq_rx_filter_l3l4: ++ fltr_cnt = AQ_RX_LAST_LOC_FL3L4 - AQ_RX_FIRST_LOC_FL3L4; ++ n_bit = fltr_cnt - self->aq_hw_rx_fltrs.fl3l4.reserved_count; ++ ++ self->aq_hw_rx_fltrs.fl3l4.active_ipv4 |= BIT(n_bit); ++ self->aq_hw_rx_fltrs.fl3l4.reserved_count++; ++ location = n_bit; ++ break; ++ default: ++ break; ++ } ++ ++ return location; ++} ++ ++void aq_nic_release_filter(struct aq_nic_s *self, enum aq_rx_filter_type type, ++ u32 location) ++{ ++ switch (type) { ++ case aq_rx_filter_ethertype: ++ self->aq_hw_rx_fltrs.fet_reserved_count--; ++ break; ++ case aq_rx_filter_l3l4: ++ self->aq_hw_rx_fltrs.fl3l4.reserved_count--; ++ self->aq_hw_rx_fltrs.fl3l4.active_ipv4 &= ~BIT(location); ++ break; ++ default: ++ break; ++ } ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index 576432adda4c..c2513b79b9e9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -18,6 +18,7 @@ struct aq_hw_ops; + struct aq_fw_s; + struct aq_vec_s; + struct aq_ptp_s; ++enum aq_rx_filter_type; + + struct aq_nic_cfg_s { + const struct aq_hw_caps_s *aq_hw_caps; +@@ -72,6 +73,7 @@ struct aq_hw_rx_fl3l4 { + u8 active_ipv4; + u8 active_ipv6:2; + u8 is_ipv6; ++ u8 reserved_count; + }; + + struct aq_hw_rx_fltrs_s { +@@ -79,6 +81,8 @@ struct aq_hw_rx_fltrs_s { + u16 active_filters; + struct aq_hw_rx_fl2 fl2; + struct aq_hw_rx_fl3l4 fl3l4; ++ /*filter ether type */ ++ u8 fet_reserved_count; + }; + + struct aq_nic_s { +@@ -154,5 +158,7 @@ u32 aq_nic_get_fw_version(struct aq_nic_s *self); + int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg); + int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self); + void aq_nic_shutdown(struct aq_nic_s *self); +- ++u8 aq_nic_reserve_filter(struct aq_nic_s *self, enum aq_rx_filter_type type); ++void aq_nic_release_filter(struct aq_nic_s *self, enum aq_rx_filter_type type, ++ u32 location); + #endif /* AQ_NIC_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index fbb1912a34d7..82409cb1f815 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -8,12 +8,14 @@ + */ + + #include ++#include + #include + #include + + #include "aq_nic.h" + #include "aq_ptp.h" + #include "aq_ring.h" ++#include "aq_filters.h" + + #define AQ_PTP_TX_TIMEOUT (HZ * 10) + +@@ -62,6 +64,9 @@ struct aq_ptp_s { + struct aq_ring_s hwts_rx; + + struct ptp_skb_ring skb_ring; ++ ++ struct aq_rx_filter_l3l4 udp_filter; ++ struct aq_rx_filter_l2 eth_type_filter; + }; + + struct ptp_tm_offset { +@@ -933,6 +938,11 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + aq_ptp_clock_init(aq_nic); + mutex_unlock(&aq_nic->fwreq_mutex); + ++ aq_ptp->eth_type_filter.location = ++ aq_nic_reserve_filter(aq_nic, aq_rx_filter_ethertype); ++ aq_ptp->udp_filter.location = ++ aq_nic_reserve_filter(aq_nic, aq_rx_filter_l3l4); ++ + return 0; + + err_exit: +@@ -958,6 +968,10 @@ void aq_ptp_free(struct aq_nic_s *aq_nic) + if (!aq_ptp) + return; + ++ aq_nic_release_filter(aq_nic, aq_rx_filter_ethertype, ++ aq_ptp->eth_type_filter.location); ++ aq_nic_release_filter(aq_nic, aq_rx_filter_l3l4, ++ aq_ptp->udp_filter.location); + /* disable ptp */ + mutex_lock(&aq_nic->fwreq_mutex); + aq_nic->aq_fw_ops->enable_ptp(aq_nic->aq_hw, 0); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index bd9e5a598657..56cec2ea0af0 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1261,7 +1261,8 @@ static int hw_atl_b0_hw_fl3l4_set(struct aq_hw_s *self, + + hw_atl_b0_hw_fl3l4_clear(self, data); + +- if (data->cmd) { ++ if (data->cmd & (HW_ATL_RX_ENABLE_CMP_DEST_ADDR_L3 | ++ HW_ATL_RX_ENABLE_CMP_SRC_ADDR_L3)) { + if (!data->is_ipv6) { + hw_atl_rpfl3l4_ipv4_dest_addr_set(self, + location, +@@ -1278,8 +1279,13 @@ static int hw_atl_b0_hw_fl3l4_set(struct aq_hw_s *self, + data->ip_src); + } + } +- hw_atl_rpf_l4_dpd_set(self, data->p_dst, location); +- hw_atl_rpf_l4_spd_set(self, data->p_src, location); ++ ++ if (data->cmd & (HW_ATL_RX_ENABLE_CMP_DEST_PORT_L4 | ++ HW_ATL_RX_ENABLE_CMP_SRC_PORT_L4)) { ++ hw_atl_rpf_l4_dpd_set(self, data->p_dst, location); ++ hw_atl_rpf_l4_spd_set(self, data->p_src, location); ++ } ++ + hw_atl_rpfl3l4_cmd_set(self, location, data->cmd); + + return aq_hw_err_from_flags(self); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +index 65fb74a4d5ea..86c2d12b0dcd 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +@@ -1308,6 +1308,52 @@ + /* default value of bitfield et_val{f}[f:0] */ + #define HW_ATL_RPF_ET_VALF_DEFAULT 0x0 + ++/* RX l3_l4_en{F} Bitfield Definitions ++ * Preprocessor definitions for the bitfield "l3_l4_en{F}". ++ * Parameter: filter {F} | stride size 0x4 | range [0, 7] ++ * PORT="pif_rpf_l3_l4_en_i[0]" ++ */ ++ ++#define HW_ATL_RPF_L3_REG_CTRL_ADR(filter) (0x00005380 + (filter) * 0x4) ++ ++/* RX rpf_l3_sa{D}[1F:0] Bitfield Definitions ++ * Preprocessor definitions for the bitfield "l3_sa{D}[1F:0]". ++ * Parameter: location {D} | stride size 0x4 | range [0, 7] ++ * PORT="pif_rpf_l3_sa0_i[31:0]" ++ */ ++ ++/* Register address for bitfield pif_rpf_l3_sa0_i[31:0] */ ++#define HW_ATL_RPF_L3_SRCA_ADR(filter) (0x000053B0 + (filter) * 0x4) ++/* Bitmask for bitfield l3_sa0[1F:0] */ ++#define HW_ATL_RPF_L3_SRCA_MSK 0xFFFFFFFFu ++/* Inverted bitmask for bitfield l3_sa0[1F:0] */ ++#define HW_ATL_RPF_L3_SRCA_MSKN 0xFFFFFFFFu ++/* Lower bit position of bitfield l3_sa0[1F:0] */ ++#define HW_ATL_RPF_L3_SRCA_SHIFT 0 ++/* Width of bitfield l3_sa0[1F:0] */ ++#define HW_ATL_RPF_L3_SRCA_WIDTH 32 ++/* Default value of bitfield l3_sa0[1F:0] */ ++#define HW_ATL_RPF_L3_SRCA_DEFAULT 0x0 ++ ++/* RX rpf_l3_da{D}[1F:0] Bitfield Definitions ++ * Preprocessor definitions for the bitfield "l3_da{D}[1F:0]". ++ * Parameter: location {D} | stride size 0x4 | range [0, 7] ++ * PORT="pif_rpf_l3_da0_i[31:0]" ++ */ ++ ++ /* Register address for bitfield pif_rpf_l3_da0_i[31:0] */ ++#define HW_ATL_RPF_L3_DSTA_ADR(filter) (0x000053B0 + (filter) * 0x4) ++/* Bitmask for bitfield l3_da0[1F:0] */ ++#define HW_ATL_RPF_L3_DSTA_MSK 0xFFFFFFFFu ++/* Inverted bitmask for bitfield l3_da0[1F:0] */ ++#define HW_ATL_RPF_L3_DSTA_MSKN 0xFFFFFFFFu ++/* Lower bit position of bitfield l3_da0[1F:0] */ ++#define HW_ATL_RPF_L3_DSTA_SHIFT 0 ++/* Width of bitfield l3_da0[1F:0] */ ++#define HW_ATL_RPF_L3_DSTA_WIDTH 32 ++/* Default value of bitfield l3_da0[1F:0] */ ++#define HW_ATL_RPF_L3_DSTA_DEFAULT 0x0 ++ + /* RX l4_sp{D}[F:0] Bitfield Definitions + * Preprocessor definitions for the bitfield "l4_sp{D}[F:0]". + * Parameter: srcport {D} | stride size 0x4 | range [0, 7] +@@ -2548,50 +2594,6 @@ + /* default value of bitfield uP Force Interrupt */ + #define HW_ATL_MCP_UP_FORCE_INTERRUPT_DEFAULT 0x0 + +-#define HW_ATL_RX_CTRL_ADDR_BEGIN_FL3L4 0x00005380 +-#define HW_ATL_RX_SRCA_ADDR_BEGIN_FL3L4 0x000053B0 +-#define HW_ATL_RX_DESTA_ADDR_BEGIN_FL3L4 0x000053D0 +- +-#define HW_ATL_RPF_L3_REG_CTRL_ADR(location) (0x00005380 + (location) * 0x4) +- +-/* RX rpf_l3_sa{D}[1F:0] Bitfield Definitions +- * Preprocessor definitions for the bitfield "l3_sa{D}[1F:0]". +- * Parameter: location {D} | stride size 0x4 | range [0, 7] +- * PORT="pif_rpf_l3_sa0_i[31:0]" +- */ +- +-/* Register address for bitfield pif_rpf_l3_sa0_i[31:0] */ +-#define HW_ATL_RPF_L3_SRCA_ADR(location) (0x000053B0 + (location) * 0x4) +-/* Bitmask for bitfield l3_sa0[1F:0] */ +-#define HW_ATL_RPF_L3_SRCA_MSK 0xFFFFFFFFu +-/* Inverted bitmask for bitfield l3_sa0[1F:0] */ +-#define HW_ATL_RPF_L3_SRCA_MSKN 0xFFFFFFFFu +-/* Lower bit position of bitfield l3_sa0[1F:0] */ +-#define HW_ATL_RPF_L3_SRCA_SHIFT 0 +-/* Width of bitfield l3_sa0[1F:0] */ +-#define HW_ATL_RPF_L3_SRCA_WIDTH 32 +-/* Default value of bitfield l3_sa0[1F:0] */ +-#define HW_ATL_RPF_L3_SRCA_DEFAULT 0x0 +- +-/* RX rpf_l3_da{D}[1F:0] Bitfield Definitions +- * Preprocessor definitions for the bitfield "l3_da{D}[1F:0]". +- * Parameter: location {D} | stride size 0x4 | range [0, 7] +- * PORT="pif_rpf_l3_da0_i[31:0]" +- */ +- +- /* Register address for bitfield pif_rpf_l3_da0_i[31:0] */ +-#define HW_ATL_RPF_L3_DSTA_ADR(location) (0x000053B0 + (location) * 0x4) +-/* Bitmask for bitfield l3_da0[1F:0] */ +-#define HW_ATL_RPF_L3_DSTA_MSK 0xFFFFFFFFu +-/* Inverted bitmask for bitfield l3_da0[1F:0] */ +-#define HW_ATL_RPF_L3_DSTA_MSKN 0xFFFFFFFFu +-/* Lower bit position of bitfield l3_da0[1F:0] */ +-#define HW_ATL_RPF_L3_DSTA_SHIFT 0 +-/* Width of bitfield l3_da0[1F:0] */ +-#define HW_ATL_RPF_L3_DSTA_WIDTH 32 +-/* Default value of bitfield l3_da0[1F:0] */ +-#define HW_ATL_RPF_L3_DSTA_DEFAULT 0x0 +- + #define HW_ATL_FW_SM_RAM 0x2U + + #endif /* HW_ATL_LLH_INTERNAL_H */ +-- +2.13.6 + diff --git a/SOURCES/0026-netdrv-net-aquantia-add-support-for-ptp-ioctls.patch b/SOURCES/0026-netdrv-net-aquantia-add-support-for-ptp-ioctls.patch new file mode 100644 index 0000000..27fa740 --- /dev/null +++ b/SOURCES/0026-netdrv-net-aquantia-add-support-for-ptp-ioctls.patch @@ -0,0 +1,244 @@ +From 5128a58c099254c3e3786eb10373833eabc6cf71 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:43 -0500 +Subject: [PATCH 026/139] [netdrv] net: aquantia: add support for ptp ioctls + +Message-id: <1604687916-15087-27-git-send-email-irusskik@redhat.com> +Patchwork-id: 338447 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 026/139] net: aquantia: add support for ptp ioctls +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 7db3d07afd2c1337f784ba9d528c10e225f91aa8 +Author: Egor Pomozov +Date: Tue Oct 22 09:53:40 2019 +0000 + + net: aquantia: add support for ptp ioctls + + Here we add support for PTP specific IOCTLs of HW timestamp get/set. + + These will use filters to configure flows onto the required queue ids. + + Co-developed-by: Sergey Samoilenko + Signed-off-by: Sergey Samoilenko + Signed-off-by: Egor Pomozov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 82 ++++++++++++++++++++++++ + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 63 ++++++++++++++++++ + drivers/net/ethernet/aquantia/atlantic/aq_ptp.h | 6 ++ + 3 files changed, 151 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index f630032af8e1..a26d4a69efad 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -218,6 +218,87 @@ static void aq_ndev_set_multicast_settings(struct net_device *ndev) + (void)aq_nic_set_multicast_list(aq_nic, ndev); + } + ++static int aq_ndev_config_hwtstamp(struct aq_nic_s *aq_nic, ++ struct hwtstamp_config *config) ++{ ++ if (config->flags) ++ return -EINVAL; ++ ++ switch (config->tx_type) { ++ case HWTSTAMP_TX_OFF: ++ case HWTSTAMP_TX_ON: ++ break; ++ default: ++ return -ERANGE; ++ } ++ ++ switch (config->rx_filter) { ++ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: ++ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: ++ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: ++ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: ++ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: ++ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: ++ case HWTSTAMP_FILTER_PTP_V2_SYNC: ++ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: ++ config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; ++ break; ++ case HWTSTAMP_FILTER_PTP_V2_EVENT: ++ case HWTSTAMP_FILTER_NONE: ++ break; ++ default: ++ return -ERANGE; ++ } ++ ++ return aq_ptp_hwtstamp_config_set(aq_nic->aq_ptp, config); ++} ++ ++static int aq_ndev_hwtstamp_set(struct aq_nic_s *aq_nic, struct ifreq *ifr) ++{ ++ struct hwtstamp_config config; ++ int ret_val; ++ ++ if (!aq_nic->aq_ptp) ++ return -EOPNOTSUPP; ++ ++ if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) ++ return -EFAULT; ++ ++ ret_val = aq_ndev_config_hwtstamp(aq_nic, &config); ++ if (ret_val) ++ return ret_val; ++ ++ return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? ++ -EFAULT : 0; ++} ++ ++static int aq_ndev_hwtstamp_get(struct aq_nic_s *aq_nic, struct ifreq *ifr) ++{ ++ struct hwtstamp_config config; ++ ++ if (!aq_nic->aq_ptp) ++ return -EOPNOTSUPP; ++ ++ aq_ptp_hwtstamp_config_get(aq_nic->aq_ptp, &config); ++ return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? ++ -EFAULT : 0; ++} ++ ++static int aq_ndev_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) ++{ ++ struct aq_nic_s *aq_nic = netdev_priv(netdev); ++ ++ switch (cmd) { ++ case SIOCSHWTSTAMP: ++ return aq_ndev_hwtstamp_set(aq_nic, ifr); ++ ++ case SIOCGHWTSTAMP: ++ return aq_ndev_hwtstamp_get(aq_nic, ifr); ++ } ++ ++ return -EOPNOTSUPP; ++} ++ + static int aq_ndo_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, + u16 vid) + { +@@ -255,6 +336,7 @@ static const struct net_device_ops aq_ndev_ops = { + .ndo_change_mtu = aq_ndev_change_mtu, + .ndo_set_mac_address = aq_ndev_set_mac_address, + .ndo_set_features = aq_ndev_set_features, ++ .ndo_do_ioctl = aq_ndev_ioctl, + .ndo_vlan_rx_add_vid = aq_ndo_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = aq_ndo_vlan_rx_kill_vid, + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index 82409cb1f815..56613792abc8 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -44,6 +44,7 @@ struct ptp_tx_timeout { + + struct aq_ptp_s { + struct aq_nic_s *aq_nic; ++ struct hwtstamp_config hwtstamp_config; + spinlock_t ptp_lock; + spinlock_t ptp_ring_lock; + struct ptp_clock *ptp_clock; +@@ -388,6 +389,68 @@ static void aq_ptp_rx_hwtstamp(struct aq_ptp_s *aq_ptp, struct sk_buff *skb, + aq_ptp_convert_to_hwtstamp(aq_ptp, skb_hwtstamps(skb), timestamp); + } + ++void aq_ptp_hwtstamp_config_get(struct aq_ptp_s *aq_ptp, ++ struct hwtstamp_config *config) ++{ ++ *config = aq_ptp->hwtstamp_config; ++} ++ ++static void aq_ptp_prepare_filters(struct aq_ptp_s *aq_ptp) ++{ ++ aq_ptp->udp_filter.cmd = HW_ATL_RX_ENABLE_FLTR_L3L4 | ++ HW_ATL_RX_ENABLE_CMP_PROT_L4 | ++ HW_ATL_RX_UDP | ++ HW_ATL_RX_ENABLE_CMP_DEST_PORT_L4 | ++ HW_ATL_RX_HOST << HW_ATL_RX_ACTION_FL3F4_SHIFT | ++ HW_ATL_RX_ENABLE_QUEUE_L3L4 | ++ aq_ptp->ptp_rx.idx << HW_ATL_RX_QUEUE_FL3L4_SHIFT; ++ aq_ptp->udp_filter.p_dst = PTP_EV_PORT; ++ ++ aq_ptp->eth_type_filter.ethertype = ETH_P_1588; ++ aq_ptp->eth_type_filter.queue = aq_ptp->ptp_rx.idx; ++} ++ ++int aq_ptp_hwtstamp_config_set(struct aq_ptp_s *aq_ptp, ++ struct hwtstamp_config *config) ++{ ++ struct aq_nic_s *aq_nic = aq_ptp->aq_nic; ++ const struct aq_hw_ops *hw_ops; ++ int err = 0; ++ ++ hw_ops = aq_nic->aq_hw_ops; ++ if (config->tx_type == HWTSTAMP_TX_ON || ++ config->rx_filter == HWTSTAMP_FILTER_PTP_V2_EVENT) { ++ aq_ptp_prepare_filters(aq_ptp); ++ if (hw_ops->hw_filter_l3l4_set) { ++ err = hw_ops->hw_filter_l3l4_set(aq_nic->aq_hw, ++ &aq_ptp->udp_filter); ++ } ++ if (!err && hw_ops->hw_filter_l2_set) { ++ err = hw_ops->hw_filter_l2_set(aq_nic->aq_hw, ++ &aq_ptp->eth_type_filter); ++ } ++ aq_utils_obj_set(&aq_nic->flags, AQ_NIC_PTP_DPATH_UP); ++ } else { ++ aq_ptp->udp_filter.cmd &= ~HW_ATL_RX_ENABLE_FLTR_L3L4; ++ if (hw_ops->hw_filter_l3l4_set) { ++ err = hw_ops->hw_filter_l3l4_set(aq_nic->aq_hw, ++ &aq_ptp->udp_filter); ++ } ++ if (!err && hw_ops->hw_filter_l2_clear) { ++ err = hw_ops->hw_filter_l2_clear(aq_nic->aq_hw, ++ &aq_ptp->eth_type_filter); ++ } ++ aq_utils_obj_clear(&aq_nic->flags, AQ_NIC_PTP_DPATH_UP); ++ } ++ ++ if (err) ++ return -EREMOTEIO; ++ ++ aq_ptp->hwtstamp_config = *config; ++ ++ return 0; ++} ++ + bool aq_ptp_ring(struct aq_nic_s *aq_nic, struct aq_ring_s *ring) + { + struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +index 2c84483fcac1..7a7f36f43ce0 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +@@ -38,6 +38,12 @@ void aq_ptp_clock_init(struct aq_nic_s *aq_nic); + int aq_ptp_xmit(struct aq_nic_s *aq_nic, struct sk_buff *skb); + void aq_ptp_tx_hwtstamp(struct aq_nic_s *aq_nic, u64 timestamp); + ++/* Must be to check available of PTP before call */ ++void aq_ptp_hwtstamp_config_get(struct aq_ptp_s *aq_ptp, ++ struct hwtstamp_config *config); ++int aq_ptp_hwtstamp_config_set(struct aq_ptp_s *aq_ptp, ++ struct hwtstamp_config *config); ++ + /* Return either ring is belong to PTP or not*/ + bool aq_ptp_ring(struct aq_nic_s *aq_nic, struct aq_ring_s *ring); + +-- +2.13.6 + diff --git a/SOURCES/0027-netdrv-net-aquantia-implement-get_ts_info-ethtool.patch b/SOURCES/0027-netdrv-net-aquantia-implement-get_ts_info-ethtool.patch new file mode 100644 index 0000000..2d73ed6 --- /dev/null +++ b/SOURCES/0027-netdrv-net-aquantia-implement-get_ts_info-ethtool.patch @@ -0,0 +1,112 @@ +From 5eb5efc51761e5fedf4325ee2645e12922ee2fe4 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:44 -0500 +Subject: [PATCH 027/139] [netdrv] net: aquantia: implement get_ts_info ethtool + +Message-id: <1604687916-15087-28-git-send-email-irusskik@redhat.com> +Patchwork-id: 338455 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 027/139] net: aquantia: implement get_ts_info ethtool +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 84989af0465b4a7898eb3a2392ea382cc219cb1d +Author: Egor Pomozov +Date: Tue Oct 22 09:53:42 2019 +0000 + + net: aquantia: implement get_ts_info ethtool + + Ethtool callback with basic information on what PTP features are supported + by the device. + + Signed-off-by: Egor Pomozov + Co-developed-by: Sergey Samoilenko + Signed-off-by: Sergey Samoilenko + Co-developed-by: Dmitry Bezrukov + Signed-off-by: Dmitry Bezrukov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 35 +++++++++++++++++++++- + 1 file changed, 34 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 24df132384fb..1ae8aabcc41a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++ * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved + */ + + /* File aq_ethtool.c: Definition of ethertool related functions. */ +@@ -9,8 +9,11 @@ + #include "aq_ethtool.h" + #include "aq_nic.h" + #include "aq_vec.h" ++#include "aq_ptp.h" + #include "aq_filters.h" + ++#include ++ + static void aq_ethtool_get_regs(struct net_device *ndev, + struct ethtool_regs *regs, void *p) + { +@@ -377,6 +380,35 @@ static int aq_ethtool_set_wol(struct net_device *ndev, + return err; + } + ++static int aq_ethtool_get_ts_info(struct net_device *ndev, ++ struct ethtool_ts_info *info) ++{ ++ struct aq_nic_s *aq_nic = netdev_priv(ndev); ++ ++ ethtool_op_get_ts_info(ndev, info); ++ ++ if (!aq_nic->aq_ptp) ++ return 0; ++ ++ info->so_timestamping |= ++ SOF_TIMESTAMPING_TX_HARDWARE | ++ SOF_TIMESTAMPING_RX_HARDWARE | ++ SOF_TIMESTAMPING_RAW_HARDWARE; ++ ++ info->tx_types = BIT(HWTSTAMP_TX_OFF) | ++ BIT(HWTSTAMP_TX_ON); ++ ++ info->rx_filters = BIT(HWTSTAMP_FILTER_NONE); ++ ++ info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | ++ BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | ++ BIT(HWTSTAMP_FILTER_PTP_V2_EVENT); ++ ++ info->phc_index = ptp_clock_index(aq_ptp_get_ptp_clock(aq_nic->aq_ptp)); ++ ++ return 0; ++} ++ + static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed) + { + u32 rate = 0; +@@ -604,4 +636,5 @@ const struct ethtool_ops aq_ethtool_ops = { + .set_link_ksettings = aq_ethtool_set_link_ksettings, + .get_coalesce = aq_ethtool_get_coalesce, + .set_coalesce = aq_ethtool_set_coalesce, ++ .get_ts_info = aq_ethtool_get_ts_info, + }; +-- +2.13.6 + diff --git a/SOURCES/0028-netdrv-net-aquantia-add-support-for-Phy-access.patch b/SOURCES/0028-netdrv-net-aquantia-add-support-for-Phy-access.patch new file mode 100644 index 0000000..ad8fe84 --- /dev/null +++ b/SOURCES/0028-netdrv-net-aquantia-add-support-for-Phy-access.patch @@ -0,0 +1,547 @@ +From 0ddb29355ee9799bf2db3dc13079eda848a67837 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:45 -0500 +Subject: [PATCH 028/139] [netdrv] net: aquantia: add support for Phy access + +Message-id: <1604687916-15087-29-git-send-email-irusskik@redhat.com> +Patchwork-id: 338448 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 028/139] net: aquantia: add support for Phy access +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit dbcd6806af4200c830869fb5ccd1f193361c136f +Author: Dmitry Bezrukov +Date: Tue Oct 22 09:53:45 2019 +0000 + + net: aquantia: add support for Phy access + + GPIO PIN control and access is done by direct phy manipulation. + Here we add an aq_phy module which is able to access phy registers + via MDIO access mailbox. + + Access is controlled via HW semaphore. + + Co-developed-by: Nikita Danilov + Signed-off-by: Nikita Danilov + Signed-off-by: Dmitry Bezrukov + Signed-off-by: Igor Russkikh + Reviewed-by: Andrew Lunn + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/Makefile | 1 + + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 1 + + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 6 + + drivers/net/ethernet/aquantia/atlantic/aq_phy.c | 147 +++++++++++++++++++++ + drivers/net/ethernet/aquantia/atlantic/aq_phy.h | 32 +++++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 62 +++++++++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 35 +++++ + .../aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 115 ++++++++++++++++ + 8 files changed, 399 insertions(+) + create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_phy.c + create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_phy.h + +diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile +index cd12d9d824ec..68c41141ede2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/Makefile ++++ b/drivers/net/ethernet/aquantia/atlantic/Makefile +@@ -25,6 +25,7 @@ atlantic-objs := aq_main.o \ + aq_drvinfo.o \ + aq_filters.o \ + aq_ptp.o \ ++ aq_phy.o \ + hw_atl/hw_atl_a0.o \ + hw_atl/hw_atl_b0.o \ + hw_atl/hw_atl_utils.o \ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index a9880c7be60f..596ede85f81e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -140,6 +140,7 @@ struct aq_hw_s { + u32 rpc_tid; + struct hw_atl_utils_fw_rpc rpc; + s64 ptp_clk_offset; ++ u16 phy_id; + }; + + struct aq_ring_s; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 22e4a5587c15..1e12cedee11e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -12,6 +12,7 @@ + #include "aq_hw.h" + #include "aq_pci_func.h" + #include "aq_main.h" ++#include "aq_phy.h" + #include "aq_ptp.h" + #include "aq_filters.h" + +@@ -337,6 +338,11 @@ int aq_nic_init(struct aq_nic_s *self) + if (err < 0) + goto err_exit; + ++ if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_TP) { ++ self->aq_hw->phy_id = HW_ATL_PHY_ID_MAX; ++ err = aq_phy_init(self->aq_hw); ++ } ++ + for (i = 0U, aq_vec = self->aq_vec[0]; + self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) + aq_vec_init(aq_vec, self->aq_hw_ops, self->aq_hw); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_phy.c b/drivers/net/ethernet/aquantia/atlantic/aq_phy.c +new file mode 100644 +index 000000000000..51ae921e3e1f +--- /dev/null ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_phy.c +@@ -0,0 +1,147 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* aQuantia Corporation Network Driver ++ * Copyright (C) 2018-2019 aQuantia Corporation. All rights reserved ++ */ ++ ++#include "aq_phy.h" ++ ++bool aq_mdio_busy_wait(struct aq_hw_s *aq_hw) ++{ ++ int err = 0; ++ u32 val; ++ ++ err = readx_poll_timeout_atomic(hw_atl_mdio_busy_get, aq_hw, ++ val, val == 0U, 10U, 100000U); ++ ++ if (err < 0) ++ return false; ++ ++ return true; ++} ++ ++u16 aq_mdio_read_word(struct aq_hw_s *aq_hw, u16 mmd, u16 addr) ++{ ++ u16 phy_addr = aq_hw->phy_id << 5 | mmd; ++ ++ /* Set Address register. */ ++ hw_atl_glb_mdio_iface4_set(aq_hw, (addr & HW_ATL_MDIO_ADDRESS_MSK) << ++ HW_ATL_MDIO_ADDRESS_SHIFT); ++ /* Send Address command. */ ++ hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK | ++ (3 << HW_ATL_MDIO_OP_MODE_SHIFT) | ++ ((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) << ++ HW_ATL_MDIO_PHY_ADDRESS_SHIFT)); ++ ++ aq_mdio_busy_wait(aq_hw); ++ ++ /* Send Read command. */ ++ hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK | ++ (1 << HW_ATL_MDIO_OP_MODE_SHIFT) | ++ ((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) << ++ HW_ATL_MDIO_PHY_ADDRESS_SHIFT)); ++ /* Read result. */ ++ aq_mdio_busy_wait(aq_hw); ++ ++ return (u16)hw_atl_glb_mdio_iface5_get(aq_hw); ++} ++ ++void aq_mdio_write_word(struct aq_hw_s *aq_hw, u16 mmd, u16 addr, u16 data) ++{ ++ u16 phy_addr = aq_hw->phy_id << 5 | mmd; ++ ++ /* Set Address register. */ ++ hw_atl_glb_mdio_iface4_set(aq_hw, (addr & HW_ATL_MDIO_ADDRESS_MSK) << ++ HW_ATL_MDIO_ADDRESS_SHIFT); ++ /* Send Address command. */ ++ hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK | ++ (3 << HW_ATL_MDIO_OP_MODE_SHIFT) | ++ ((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) << ++ HW_ATL_MDIO_PHY_ADDRESS_SHIFT)); ++ ++ aq_mdio_busy_wait(aq_hw); ++ ++ hw_atl_glb_mdio_iface3_set(aq_hw, (data & HW_ATL_MDIO_WRITE_DATA_MSK) << ++ HW_ATL_MDIO_WRITE_DATA_SHIFT); ++ /* Send Write command. */ ++ hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK | ++ (2 << HW_ATL_MDIO_OP_MODE_SHIFT) | ++ ((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) << ++ HW_ATL_MDIO_PHY_ADDRESS_SHIFT)); ++ ++ aq_mdio_busy_wait(aq_hw); ++} ++ ++u16 aq_phy_read_reg(struct aq_hw_s *aq_hw, u16 mmd, u16 address) ++{ ++ int err = 0; ++ u32 val; ++ ++ err = readx_poll_timeout_atomic(hw_atl_sem_mdio_get, aq_hw, ++ val, val == 1U, 10U, 100000U); ++ ++ if (err < 0) { ++ err = 0xffff; ++ goto err_exit; ++ } ++ ++ err = aq_mdio_read_word(aq_hw, mmd, address); ++ ++ hw_atl_reg_glb_cpu_sem_set(aq_hw, 1U, HW_ATL_FW_SM_MDIO); ++ ++err_exit: ++ return err; ++} ++ ++void aq_phy_write_reg(struct aq_hw_s *aq_hw, u16 mmd, u16 address, u16 data) ++{ ++ int err = 0; ++ u32 val; ++ ++ err = readx_poll_timeout_atomic(hw_atl_sem_mdio_get, aq_hw, ++ val, val == 1U, 10U, 100000U); ++ if (err < 0) ++ return; ++ ++ aq_mdio_write_word(aq_hw, mmd, address, data); ++ hw_atl_reg_glb_cpu_sem_set(aq_hw, 1U, HW_ATL_FW_SM_MDIO); ++} ++ ++bool aq_phy_init_phy_id(struct aq_hw_s *aq_hw) ++{ ++ u16 val; ++ ++ for (aq_hw->phy_id = 0; aq_hw->phy_id < HW_ATL_PHY_ID_MAX; ++ ++aq_hw->phy_id) { ++ /* PMA Standard Device Identifier 2: Address 1.3 */ ++ val = aq_phy_read_reg(aq_hw, MDIO_MMD_PMAPMD, 3); ++ ++ if (val != 0xffff) ++ return true; ++ } ++ ++ return false; ++} ++ ++bool aq_phy_init(struct aq_hw_s *aq_hw) ++{ ++ u32 dev_id; ++ ++ if (aq_hw->phy_id == HW_ATL_PHY_ID_MAX) ++ if (!aq_phy_init_phy_id(aq_hw)) ++ return false; ++ ++ /* PMA Standard Device Identifier: ++ * Address 1.2 = MSW, ++ * Address 1.3 = LSW ++ */ ++ dev_id = aq_phy_read_reg(aq_hw, MDIO_MMD_PMAPMD, 2); ++ dev_id <<= 16; ++ dev_id |= aq_phy_read_reg(aq_hw, MDIO_MMD_PMAPMD, 3); ++ ++ if (dev_id == 0xffffffff) { ++ aq_hw->phy_id = HW_ATL_PHY_ID_MAX; ++ return false; ++ } ++ ++ return true; ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_phy.h b/drivers/net/ethernet/aquantia/atlantic/aq_phy.h +new file mode 100644 +index 000000000000..84b72ad04a4a +--- /dev/null ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_phy.h +@@ -0,0 +1,32 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* aQuantia Corporation Network Driver ++ * Copyright (C) 2018-2019 aQuantia Corporation. All rights reserved ++ */ ++ ++#ifndef AQ_PHY_H ++#define AQ_PHY_H ++ ++#include ++ ++#include "hw_atl/hw_atl_llh.h" ++#include "hw_atl/hw_atl_llh_internal.h" ++#include "aq_hw_utils.h" ++#include "aq_hw.h" ++ ++#define HW_ATL_PHY_ID_MAX 32U ++ ++bool aq_mdio_busy_wait(struct aq_hw_s *aq_hw); ++ ++u16 aq_mdio_read_word(struct aq_hw_s *aq_hw, u16 mmd, u16 addr); ++ ++void aq_mdio_write_word(struct aq_hw_s *aq_hw, u16 mmd, u16 addr, u16 data); ++ ++u16 aq_phy_read_reg(struct aq_hw_s *aq_hw, u16 mmd, u16 address); ++ ++void aq_phy_write_reg(struct aq_hw_s *aq_hw, u16 mmd, u16 address, u16 data); ++ ++bool aq_phy_init_phy_id(struct aq_hw_s *aq_hw); ++ ++bool aq_phy_init(struct aq_hw_s *aq_hw); ++ ++#endif /* AQ_PHY_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index d83f1a34a537..6cadc9054544 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -1644,6 +1644,11 @@ u32 hw_atl_sem_ram_get(struct aq_hw_s *self) + return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM); + } + ++u32 hw_atl_sem_mdio_get(struct aq_hw_s *self) ++{ ++ return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_MDIO); ++} ++ + u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp) + { + return aq_hw_read_reg(aq_hw, +@@ -1659,3 +1664,60 @@ u32 hw_atl_scrpad25_get(struct aq_hw_s *self) + { + return hw_atl_scrpad_get(self, 0x18); + } ++ ++void hw_atl_glb_mdio_iface1_set(struct aq_hw_s *aq_hw, u32 value) ++{ ++ aq_hw_write_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(1), value); ++} ++ ++u32 hw_atl_glb_mdio_iface1_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(1)); ++} ++ ++void hw_atl_glb_mdio_iface2_set(struct aq_hw_s *aq_hw, u32 value) ++{ ++ aq_hw_write_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(2), value); ++} ++ ++u32 hw_atl_glb_mdio_iface2_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(2)); ++} ++ ++void hw_atl_glb_mdio_iface3_set(struct aq_hw_s *aq_hw, u32 value) ++{ ++ aq_hw_write_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(3), value); ++} ++ ++u32 hw_atl_glb_mdio_iface3_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(3)); ++} ++ ++void hw_atl_glb_mdio_iface4_set(struct aq_hw_s *aq_hw, u32 value) ++{ ++ aq_hw_write_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(4), value); ++} ++ ++u32 hw_atl_glb_mdio_iface4_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(4)); ++} ++ ++void hw_atl_glb_mdio_iface5_set(struct aq_hw_s *aq_hw, u32 value) ++{ ++ aq_hw_write_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(5), value); ++} ++ ++u32 hw_atl_glb_mdio_iface5_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg(aq_hw, HW_ATL_GLB_MDIO_IFACE_N_ADR(5)); ++} ++ ++u32 hw_atl_mdio_busy_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg_bit(aq_hw, HW_ATL_MDIO_BUSY_ADR, ++ HW_ATL_MDIO_BUSY_MSK, ++ HW_ATL_MDIO_BUSY_SHIFT); ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index b192702a7b8b..5750b0c9cae7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -767,9 +767,44 @@ void hw_atl_rpfl3l4_ipv6_src_addr_set(struct aq_hw_s *aq_hw, u8 location, + void hw_atl_rpfl3l4_ipv6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location, + u32 *ipv6_dest); + ++/* set Global MDIO Interface 1 */ ++void hw_atl_glb_mdio_iface1_set(struct aq_hw_s *hw, u32 value); ++ ++/* get Global MDIO Interface 1 */ ++u32 hw_atl_glb_mdio_iface1_get(struct aq_hw_s *hw); ++ ++/* set Global MDIO Interface 2 */ ++void hw_atl_glb_mdio_iface2_set(struct aq_hw_s *hw, u32 value); ++ ++/* get Global MDIO Interface 2 */ ++u32 hw_atl_glb_mdio_iface2_get(struct aq_hw_s *hw); ++ ++/* set Global MDIO Interface 3 */ ++void hw_atl_glb_mdio_iface3_set(struct aq_hw_s *hw, u32 value); ++ ++/* get Global MDIO Interface 3 */ ++u32 hw_atl_glb_mdio_iface3_get(struct aq_hw_s *hw); ++ ++/* set Global MDIO Interface 4 */ ++void hw_atl_glb_mdio_iface4_set(struct aq_hw_s *hw, u32 value); ++ ++/* get Global MDIO Interface 4 */ ++u32 hw_atl_glb_mdio_iface4_get(struct aq_hw_s *hw); ++ ++/* set Global MDIO Interface 5 */ ++void hw_atl_glb_mdio_iface5_set(struct aq_hw_s *hw, u32 value); ++ ++/* get Global MDIO Interface 5 */ ++u32 hw_atl_glb_mdio_iface5_get(struct aq_hw_s *hw); ++ ++u32 hw_atl_mdio_busy_get(struct aq_hw_s *aq_hw); ++ + /* get global microprocessor ram semaphore */ + u32 hw_atl_sem_ram_get(struct aq_hw_s *self); + ++/* get global microprocessor mdio semaphore */ ++u32 hw_atl_sem_mdio_get(struct aq_hw_s *self); ++ + /* get global microprocessor scratch pad register */ + u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +index 86c2d12b0dcd..ec3bcdcefc4d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +@@ -2594,6 +2594,121 @@ + /* default value of bitfield uP Force Interrupt */ + #define HW_ATL_MCP_UP_FORCE_INTERRUPT_DEFAULT 0x0 + ++/* Preprocessor definitions for Global MDIO Interfaces ++ * Address: 0x00000280 + 0x4 * Number of interface ++ */ ++#define HW_ATL_GLB_MDIO_IFACE_ADDR_BEGIN 0x00000280u ++ ++#define HW_ATL_GLB_MDIO_IFACE_N_ADR(number) \ ++ (HW_ATL_GLB_MDIO_IFACE_ADDR_BEGIN + (((number) - 1) * 0x4)) ++ ++/* MIF MDIO Busy Bitfield Definitions ++ * Preprocessor definitions for the bitfield "MDIO Busy". ++ * PORT="mdio_pif_busy_o" ++ */ ++ ++/* Register address for bitfield MDIO Busy */ ++#define HW_ATL_MDIO_BUSY_ADR 0x00000284 ++/* Bitmask for bitfield MDIO Busy */ ++#define HW_ATL_MDIO_BUSY_MSK 0x80000000 ++/* Inverted bitmask for bitfield MDIO Busy */ ++#define HW_ATL_MDIO_BUSY_MSKN 0x7FFFFFFF ++/* Lower bit position of bitfield MDIO Busy */ ++#define HW_ATL_MDIO_BUSY_SHIFT 31 ++/* Width of bitfield MDIO Busy */ ++#define HW_ATL_MDIO_BUSY_WIDTH 1 ++ ++/* MIF MDIO Execute Operation Bitfield Definitions ++ * Preprocessor definitions for the bitfield "MDIO Execute Operation". ++ * PORT="pif_mdio_op_start_i" ++ */ ++ ++/* Register address for bitfield MDIO Execute Operation */ ++#define HW_ATL_MDIO_EXECUTE_OPERATION_ADR 0x00000284 ++/* Bitmask for bitfield MDIO Execute Operation */ ++#define HW_ATL_MDIO_EXECUTE_OPERATION_MSK 0x00008000 ++/* Inverted bitmask for bitfield MDIO Execute Operation */ ++#define HW_ATL_MDIO_EXECUTE_OPERATION_MSKN 0xFFFF7FFF ++/* Lower bit position of bitfield MDIO Execute Operation */ ++#define HW_ATL_MDIO_EXECUTE_OPERATION_SHIFT 15 ++/* Width of bitfield MDIO Execute Operation */ ++#define HW_ATL_MDIO_EXECUTE_OPERATION_WIDTH 1 ++/* Default value of bitfield MDIO Execute Operation */ ++#define HW_ATL_MDIO_EXECUTE_OPERATION_DEFAULT 0x0 ++ ++/* MIF Op Mode [1:0] Bitfield Definitions ++ * Preprocessor definitions for the bitfield "Op Mode [1:0]". ++ * PORT="pif_mdio_mode_i[1:0]" ++ */ ++ ++/* Register address for bitfield Op Mode [1:0] */ ++#define HW_ATL_MDIO_OP_MODE_ADR 0x00000284 ++/* Bitmask for bitfield Op Mode [1:0] */ ++#define HW_ATL_MDIO_OP_MODE_MSK 0x00003000 ++/* Inverted bitmask for bitfield Op Mode [1:0] */ ++#define HW_ATL_MDIO_OP_MODE_MSKN 0xFFFFCFFF ++/* Lower bit position of bitfield Op Mode [1:0] */ ++#define HW_ATL_MDIO_OP_MODE_SHIFT 12 ++/* Width of bitfield Op Mode [1:0] */ ++#define HW_ATL_MDIO_OP_MODE_WIDTH 2 ++/* Default value of bitfield Op Mode [1:0] */ ++#define HW_ATL_MDIO_OP_MODE_DEFAULT 0x0 ++ ++/* MIF PHY address Bitfield Definitions ++ * Preprocessor definitions for the bitfield "PHY address". ++ * PORT="pif_mdio_phy_addr_i[9:0]" ++ */ ++ ++/* Register address for bitfield PHY address */ ++#define HW_ATL_MDIO_PHY_ADDRESS_ADR 0x00000284 ++/* Bitmask for bitfield PHY address */ ++#define HW_ATL_MDIO_PHY_ADDRESS_MSK 0x000003FF ++/* Inverted bitmask for bitfield PHY address */ ++#define HW_ATL_MDIO_PHY_ADDRESS_MSKN 0xFFFFFC00 ++/* Lower bit position of bitfield PHY address */ ++#define HW_ATL_MDIO_PHY_ADDRESS_SHIFT 0 ++/* Width of bitfield PHY address */ ++#define HW_ATL_MDIO_PHY_ADDRESS_WIDTH 10 ++/* Default value of bitfield PHY address */ ++#define HW_ATL_MDIO_PHY_ADDRESS_DEFAULT 0x0 ++ ++/* MIF MDIO WriteData [F:0] Bitfield Definitions ++ * Preprocessor definitions for the bitfield "MDIO WriteData [F:0]". ++ * PORT="pif_mdio_wdata_i[15:0]" ++ */ ++ ++/* Register address for bitfield MDIO WriteData [F:0] */ ++#define HW_ATL_MDIO_WRITE_DATA_ADR 0x00000288 ++/* Bitmask for bitfield MDIO WriteData [F:0] */ ++#define HW_ATL_MDIO_WRITE_DATA_MSK 0x0000FFFF ++/* Inverted bitmask for bitfield MDIO WriteData [F:0] */ ++#define HW_ATL_MDIO_WRITE_DATA_MSKN 0xFFFF0000 ++/* Lower bit position of bitfield MDIO WriteData [F:0] */ ++#define HW_ATL_MDIO_WRITE_DATA_SHIFT 0 ++/* Width of bitfield MDIO WriteData [F:0] */ ++#define HW_ATL_MDIO_WRITE_DATA_WIDTH 16 ++/* Default value of bitfield MDIO WriteData [F:0] */ ++#define HW_ATL_MDIO_WRITE_DATA_DEFAULT 0x0 ++ ++/* MIF MDIO Address [F:0] Bitfield Definitions ++ * Preprocessor definitions for the bitfield "MDIO Address [F:0]". ++ * PORT="pif_mdio_addr_i[15:0]" ++ */ ++ ++/* Register address for bitfield MDIO Address [F:0] */ ++#define HW_ATL_MDIO_ADDRESS_ADR 0x0000028C ++/* Bitmask for bitfield MDIO Address [F:0] */ ++#define HW_ATL_MDIO_ADDRESS_MSK 0x0000FFFF ++/* Inverted bitmask for bitfield MDIO Address [F:0] */ ++#define HW_ATL_MDIO_ADDRESS_MSKN 0xFFFF0000 ++/* Lower bit position of bitfield MDIO Address [F:0] */ ++#define HW_ATL_MDIO_ADDRESS_SHIFT 0 ++/* Width of bitfield MDIO Address [F:0] */ ++#define HW_ATL_MDIO_ADDRESS_WIDTH 16 ++/* Default value of bitfield MDIO Address [F:0] */ ++#define HW_ATL_MDIO_ADDRESS_DEFAULT 0x0 ++ ++#define HW_ATL_FW_SM_MDIO 0x0U + #define HW_ATL_FW_SM_RAM 0x2U + + #endif /* HW_ATL_LLH_INTERNAL_H */ +-- +2.13.6 + diff --git a/SOURCES/0029-netdrv-net-aquantia-add-support-for-PIN-funcs.patch b/SOURCES/0029-netdrv-net-aquantia-add-support-for-PIN-funcs.patch new file mode 100644 index 0000000..cb289ed --- /dev/null +++ b/SOURCES/0029-netdrv-net-aquantia-add-support-for-PIN-funcs.patch @@ -0,0 +1,663 @@ +From 83e7602f8870827a811276a007f5ed2a608284c9 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:46 -0500 +Subject: [PATCH 029/139] [netdrv] net: aquantia: add support for PIN funcs + +Message-id: <1604687916-15087-30-git-send-email-irusskik@redhat.com> +Patchwork-id: 338451 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 029/139] net: aquantia: add support for PIN funcs +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 9c477032f7d0beafe592e65238d8fb79341e91dc +Author: Dmitry Bezrukov +Date: Tue Oct 22 09:53:47 2019 +0000 + + net: aquantia: add support for PIN funcs + + Depending on FW configuration we can manage from 0 to 3 PINs for periodic output + and from 0 to 1 ext ts PIN for getting TS for external event. + + Ext TS PIN functionality is implemented via periodic timestamps polling + directly from PHY, because right now there is now way to receive the + PIN trigger interrupt from phy. + + The polling interval is 15 milliseconds. + + Co-developed-by: Egor Pomozov + Signed-off-by: Egor Pomozov + Co-developed-by: Pavel Belous + Signed-off-by: Pavel Belous + Signed-off-by: Dmitry Bezrukov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 10 + + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 1 + + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 339 +++++++++++++++++++++ + drivers/net/ethernet/aquantia/atlantic/aq_ptp.h | 2 + + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 63 +++- + .../aquantia/atlantic/hw_atl/hw_atl_utils.h | 8 + + 6 files changed, 422 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index 596ede85f81e..a5cf6e02d4f6 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -259,6 +259,16 @@ struct aq_hw_ops { + + int (*hw_set_sys_clock)(struct aq_hw_s *self, u64 time, u64 ts); + ++ int (*hw_ts_to_sys_clock)(struct aq_hw_s *self, u64 ts, u64 *time); ++ ++ int (*hw_gpio_pulse)(struct aq_hw_s *self, u32 index, u64 start, ++ u32 period); ++ ++ int (*hw_extts_gpio_enable)(struct aq_hw_s *self, u32 index, ++ u32 enable); ++ ++ int (*hw_get_sync_ts)(struct aq_hw_s *self, u64 *ts); ++ + u16 (*rx_extract_ts)(struct aq_hw_s *self, u8 *p, unsigned int len, + u64 *timestamp); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 1e12cedee11e..433adc099e44 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -152,6 +152,7 @@ static int aq_nic_update_link_status(struct aq_nic_s *self) + aq_ptp_clock_init(self); + aq_ptp_tm_offset_set(self, + self->aq_hw->aq_link_status.mbps); ++ aq_ptp_link_change(self); + } + + /* Driver has to update flow control settings on RX block +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index 56613792abc8..3ec08415e53e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -15,10 +15,13 @@ + #include "aq_nic.h" + #include "aq_ptp.h" + #include "aq_ring.h" ++#include "aq_phy.h" + #include "aq_filters.h" + + #define AQ_PTP_TX_TIMEOUT (HZ * 10) + ++#define POLL_SYNC_TIMER_MS 15 ++ + enum ptp_speed_offsets { + ptp_offset_idx_10 = 0, + ptp_offset_idx_100, +@@ -68,6 +71,12 @@ struct aq_ptp_s { + + struct aq_rx_filter_l3l4 udp_filter; + struct aq_rx_filter_l2 eth_type_filter; ++ ++ struct delayed_work poll_sync; ++ u32 poll_timeout_ms; ++ ++ bool extts_pin_enabled; ++ u64 last_sync1588_ts; + }; + + struct ptp_tm_offset { +@@ -348,6 +357,168 @@ static void aq_ptp_convert_to_hwtstamp(struct aq_ptp_s *aq_ptp, + hwtstamp->hwtstamp = ns_to_ktime(timestamp); + } + ++static int aq_ptp_hw_pin_conf(struct aq_nic_s *aq_nic, u32 pin_index, u64 start, ++ u64 period) ++{ ++ if (period) ++ netdev_dbg(aq_nic->ndev, ++ "Enable GPIO %d pulsing, start time %llu, period %u\n", ++ pin_index, start, (u32)period); ++ else ++ netdev_dbg(aq_nic->ndev, ++ "Disable GPIO %d pulsing, start time %llu, period %u\n", ++ pin_index, start, (u32)period); ++ ++ /* Notify hardware of request to being sending pulses. ++ * If period is ZERO then pulsen is disabled. ++ */ ++ mutex_lock(&aq_nic->fwreq_mutex); ++ aq_nic->aq_hw_ops->hw_gpio_pulse(aq_nic->aq_hw, pin_index, ++ start, (u32)period); ++ mutex_unlock(&aq_nic->fwreq_mutex); ++ ++ return 0; ++} ++ ++static int aq_ptp_perout_pin_configure(struct ptp_clock_info *ptp, ++ struct ptp_clock_request *rq, int on) ++{ ++ struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info); ++ struct ptp_clock_time *t = &rq->perout.period; ++ struct ptp_clock_time *s = &rq->perout.start; ++ struct aq_nic_s *aq_nic = aq_ptp->aq_nic; ++ u64 start, period; ++ u32 pin_index = rq->perout.index; ++ ++ /* verify the request channel is there */ ++ if (pin_index >= ptp->n_per_out) ++ return -EINVAL; ++ ++ /* we cannot support periods greater ++ * than 4 seconds due to reg limit ++ */ ++ if (t->sec > 4 || t->sec < 0) ++ return -ERANGE; ++ ++ /* convert to unsigned 64b ns, ++ * verify we can put it in a 32b register ++ */ ++ period = on ? t->sec * NSEC_PER_SEC + t->nsec : 0; ++ ++ /* verify the value is in range supported by hardware */ ++ if (period > U32_MAX) ++ return -ERANGE; ++ /* convert to unsigned 64b ns */ ++ /* TODO convert to AQ time */ ++ start = on ? s->sec * NSEC_PER_SEC + s->nsec : 0; ++ ++ aq_ptp_hw_pin_conf(aq_nic, pin_index, start, period); ++ ++ return 0; ++} ++ ++static int aq_ptp_pps_pin_configure(struct ptp_clock_info *ptp, ++ struct ptp_clock_request *rq, int on) ++{ ++ struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info); ++ struct aq_nic_s *aq_nic = aq_ptp->aq_nic; ++ u64 start, period; ++ u32 pin_index = 0; ++ u32 rest = 0; ++ ++ /* verify the request channel is there */ ++ if (pin_index >= ptp->n_per_out) ++ return -EINVAL; ++ ++ aq_nic->aq_hw_ops->hw_get_ptp_ts(aq_nic->aq_hw, &start); ++ div_u64_rem(start, NSEC_PER_SEC, &rest); ++ period = on ? NSEC_PER_SEC : 0; /* PPS - pulse per second */ ++ start = on ? start - rest + NSEC_PER_SEC * ++ (rest > 990000000LL ? 2 : 1) : 0; ++ ++ aq_ptp_hw_pin_conf(aq_nic, pin_index, start, period); ++ ++ return 0; ++} ++ ++static void aq_ptp_extts_pin_ctrl(struct aq_ptp_s *aq_ptp) ++{ ++ struct aq_nic_s *aq_nic = aq_ptp->aq_nic; ++ u32 enable = aq_ptp->extts_pin_enabled; ++ ++ if (aq_nic->aq_hw_ops->hw_extts_gpio_enable) ++ aq_nic->aq_hw_ops->hw_extts_gpio_enable(aq_nic->aq_hw, 0, ++ enable); ++} ++ ++static int aq_ptp_extts_pin_configure(struct ptp_clock_info *ptp, ++ struct ptp_clock_request *rq, int on) ++{ ++ struct aq_ptp_s *aq_ptp = container_of(ptp, struct aq_ptp_s, ptp_info); ++ ++ u32 pin_index = rq->extts.index; ++ ++ if (pin_index >= ptp->n_ext_ts) ++ return -EINVAL; ++ ++ aq_ptp->extts_pin_enabled = !!on; ++ if (on) { ++ aq_ptp->poll_timeout_ms = POLL_SYNC_TIMER_MS; ++ cancel_delayed_work_sync(&aq_ptp->poll_sync); ++ schedule_delayed_work(&aq_ptp->poll_sync, ++ msecs_to_jiffies(aq_ptp->poll_timeout_ms)); ++ } ++ ++ aq_ptp_extts_pin_ctrl(aq_ptp); ++ return 0; ++} ++ ++/* aq_ptp_gpio_feature_enable ++ * @ptp: the ptp clock structure ++ * @rq: the requested feature to change ++ * @on: whether to enable or disable the feature ++ */ ++static int aq_ptp_gpio_feature_enable(struct ptp_clock_info *ptp, ++ struct ptp_clock_request *rq, int on) ++{ ++ switch (rq->type) { ++ case PTP_CLK_REQ_EXTTS: ++ return aq_ptp_extts_pin_configure(ptp, rq, on); ++ case PTP_CLK_REQ_PEROUT: ++ return aq_ptp_perout_pin_configure(ptp, rq, on); ++ case PTP_CLK_REQ_PPS: ++ return aq_ptp_pps_pin_configure(ptp, rq, on); ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++/* aq_ptp_verify ++ * @ptp: the ptp clock structure ++ * @pin: index of the pin in question ++ * @func: the desired function to use ++ * @chan: the function channel index to use ++ */ ++static int aq_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin, ++ enum ptp_pin_function func, unsigned int chan) ++{ ++ /* verify the requested pin is there */ ++ if (!ptp->pin_config || pin >= ptp->n_pins) ++ return -EINVAL; ++ ++ /* enforce locked channels, no changing them */ ++ if (chan != ptp->pin_config[pin].chan) ++ return -EINVAL; ++ ++ /* we want to keep the functions locked as well */ ++ if (func != ptp->pin_config[pin].func) ++ return -EINVAL; ++ ++ return 0; ++} ++ + /* aq_ptp_tx_hwtstamp - utility function which checks for TX time stamp + * @adapter: the private adapter struct + * +@@ -859,6 +1030,8 @@ void aq_ptp_ring_free(struct aq_nic_s *aq_nic) + aq_ptp_skb_ring_release(&aq_ptp->skb_ring); + } + ++#define MAX_PTP_GPIO_COUNT 4 ++ + static struct ptp_clock_info aq_ptp_clock = { + .owner = THIS_MODULE, + .name = "atlantic ptp", +@@ -870,7 +1043,9 @@ static struct ptp_clock_info aq_ptp_clock = { + .gettime64 = aq_ptp_gettime, + .settime64 = aq_ptp_settime, + .n_per_out = 0, ++ .enable = aq_ptp_gpio_feature_enable, + .n_pins = 0, ++ .verify = aq_ptp_verify, + .pin_config = NULL, + }; + +@@ -928,6 +1103,57 @@ static void aq_ptp_offset_init(const struct hw_aq_ptp_offset *offsets) + aq_ptp_offset_init_from_fw(offsets); + } + ++static void aq_ptp_gpio_init(struct ptp_clock_info *info, ++ struct hw_aq_info *hw_info) ++{ ++ struct ptp_pin_desc pin_desc[MAX_PTP_GPIO_COUNT]; ++ u32 extts_pin_cnt = 0; ++ u32 out_pin_cnt = 0; ++ u32 i; ++ ++ memset(pin_desc, 0, sizeof(pin_desc)); ++ ++ for (i = 0; i < MAX_PTP_GPIO_COUNT - 1; i++) { ++ if (hw_info->gpio_pin[i] == ++ (GPIO_PIN_FUNCTION_PTP0 + out_pin_cnt)) { ++ snprintf(pin_desc[out_pin_cnt].name, ++ sizeof(pin_desc[out_pin_cnt].name), ++ "AQ_GPIO%d", i); ++ pin_desc[out_pin_cnt].index = out_pin_cnt; ++ pin_desc[out_pin_cnt].chan = out_pin_cnt; ++ pin_desc[out_pin_cnt++].func = PTP_PF_PEROUT; ++ } ++ } ++ ++ info->n_per_out = out_pin_cnt; ++ ++ if (hw_info->caps_ex & BIT(CAPS_EX_PHY_CTRL_TS_PIN)) { ++ extts_pin_cnt += 1; ++ ++ snprintf(pin_desc[out_pin_cnt].name, ++ sizeof(pin_desc[out_pin_cnt].name), ++ "AQ_GPIO%d", out_pin_cnt); ++ pin_desc[out_pin_cnt].index = out_pin_cnt; ++ pin_desc[out_pin_cnt].chan = 0; ++ pin_desc[out_pin_cnt].func = PTP_PF_EXTTS; ++ } ++ ++ info->n_pins = out_pin_cnt + extts_pin_cnt; ++ info->n_ext_ts = extts_pin_cnt; ++ ++ if (!info->n_pins) ++ return; ++ ++ info->pin_config = kcalloc(info->n_pins, sizeof(struct ptp_pin_desc), ++ GFP_KERNEL); ++ ++ if (!info->pin_config) ++ return; ++ ++ memcpy(info->pin_config, &pin_desc, ++ sizeof(struct ptp_pin_desc) * info->n_pins); ++} ++ + void aq_ptp_clock_init(struct aq_nic_s *aq_nic) + { + struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; +@@ -937,6 +1163,8 @@ void aq_ptp_clock_init(struct aq_nic_s *aq_nic) + aq_ptp_settime(&aq_ptp->ptp_info, &ts); + } + ++static void aq_ptp_poll_sync_work_cb(struct work_struct *w); ++ + int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + { + struct hw_atl_utils_mbox mbox; +@@ -975,6 +1203,7 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + spin_lock_init(&aq_ptp->ptp_ring_lock); + + aq_ptp->ptp_info = aq_ptp_clock; ++ aq_ptp_gpio_init(&aq_ptp->ptp_info, &mbox.info); + clock = ptp_clock_register(&aq_ptp->ptp_info, &aq_nic->ndev->dev); + if (!clock || IS_ERR(clock)) { + netdev_err(aq_nic->ndev, "ptp_clock_register failed\n"); +@@ -1001,6 +1230,7 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + aq_ptp_clock_init(aq_nic); + mutex_unlock(&aq_nic->fwreq_mutex); + ++ INIT_DELAYED_WORK(&aq_ptp->poll_sync, &aq_ptp_poll_sync_work_cb); + aq_ptp->eth_type_filter.location = + aq_nic_reserve_filter(aq_nic, aq_rx_filter_ethertype); + aq_ptp->udp_filter.location = +@@ -1009,6 +1239,8 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + return 0; + + err_exit: ++ if (aq_ptp) ++ kfree(aq_ptp->ptp_info.pin_config); + kfree(aq_ptp); + aq_nic->aq_ptp = NULL; + return err; +@@ -1035,11 +1267,14 @@ void aq_ptp_free(struct aq_nic_s *aq_nic) + aq_ptp->eth_type_filter.location); + aq_nic_release_filter(aq_nic, aq_rx_filter_l3l4, + aq_ptp->udp_filter.location); ++ cancel_delayed_work_sync(&aq_ptp->poll_sync); + /* disable ptp */ + mutex_lock(&aq_nic->fwreq_mutex); + aq_nic->aq_fw_ops->enable_ptp(aq_nic->aq_hw, 0); + mutex_unlock(&aq_nic->fwreq_mutex); + ++ kfree(aq_ptp->ptp_info.pin_config); ++ + netif_napi_del(&aq_ptp->napi); + kfree(aq_ptp); + aq_nic->aq_ptp = NULL; +@@ -1049,3 +1284,107 @@ struct ptp_clock *aq_ptp_get_ptp_clock(struct aq_ptp_s *aq_ptp) + { + return aq_ptp->ptp_clock; + } ++ ++/* PTP external GPIO nanoseconds count */ ++static uint64_t aq_ptp_get_sync1588_ts(struct aq_nic_s *aq_nic) ++{ ++ u64 ts = 0; ++ ++ if (aq_nic->aq_hw_ops->hw_get_sync_ts) ++ aq_nic->aq_hw_ops->hw_get_sync_ts(aq_nic->aq_hw, &ts); ++ ++ return ts; ++} ++ ++static void aq_ptp_start_work(struct aq_ptp_s *aq_ptp) ++{ ++ if (aq_ptp->extts_pin_enabled) { ++ aq_ptp->poll_timeout_ms = POLL_SYNC_TIMER_MS; ++ aq_ptp->last_sync1588_ts = ++ aq_ptp_get_sync1588_ts(aq_ptp->aq_nic); ++ schedule_delayed_work(&aq_ptp->poll_sync, ++ msecs_to_jiffies(aq_ptp->poll_timeout_ms)); ++ } ++} ++ ++int aq_ptp_link_change(struct aq_nic_s *aq_nic) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ ++ if (!aq_ptp) ++ return 0; ++ ++ if (aq_nic->aq_hw->aq_link_status.mbps) ++ aq_ptp_start_work(aq_ptp); ++ else ++ cancel_delayed_work_sync(&aq_ptp->poll_sync); ++ ++ return 0; ++} ++ ++static bool aq_ptp_sync_ts_updated(struct aq_ptp_s *aq_ptp, u64 *new_ts) ++{ ++ struct aq_nic_s *aq_nic = aq_ptp->aq_nic; ++ u64 sync_ts2; ++ u64 sync_ts; ++ ++ sync_ts = aq_ptp_get_sync1588_ts(aq_nic); ++ ++ if (sync_ts != aq_ptp->last_sync1588_ts) { ++ sync_ts2 = aq_ptp_get_sync1588_ts(aq_nic); ++ if (sync_ts != sync_ts2) { ++ sync_ts = sync_ts2; ++ sync_ts2 = aq_ptp_get_sync1588_ts(aq_nic); ++ if (sync_ts != sync_ts2) { ++ netdev_err(aq_nic->ndev, ++ "%s: Unable to get correct GPIO TS", ++ __func__); ++ sync_ts = 0; ++ } ++ } ++ ++ *new_ts = sync_ts; ++ return true; ++ } ++ return false; ++} ++ ++static int aq_ptp_check_sync1588(struct aq_ptp_s *aq_ptp) ++{ ++ struct aq_nic_s *aq_nic = aq_ptp->aq_nic; ++ u64 sync_ts; ++ ++ /* Sync1588 pin was triggered */ ++ if (aq_ptp_sync_ts_updated(aq_ptp, &sync_ts)) { ++ if (aq_ptp->extts_pin_enabled) { ++ struct ptp_clock_event ptp_event; ++ u64 time = 0; ++ ++ aq_nic->aq_hw_ops->hw_ts_to_sys_clock(aq_nic->aq_hw, ++ sync_ts, &time); ++ ptp_event.index = aq_ptp->ptp_info.n_pins - 1; ++ ptp_event.timestamp = time; ++ ++ ptp_event.type = PTP_CLOCK_EXTTS; ++ ptp_clock_event(aq_ptp->ptp_clock, &ptp_event); ++ } ++ ++ aq_ptp->last_sync1588_ts = sync_ts; ++ } ++ ++ return 0; ++} ++ ++void aq_ptp_poll_sync_work_cb(struct work_struct *w) ++{ ++ struct delayed_work *dw = to_delayed_work(w); ++ struct aq_ptp_s *aq_ptp = container_of(dw, struct aq_ptp_s, poll_sync); ++ ++ aq_ptp_check_sync1588(aq_ptp); ++ ++ if (aq_ptp->extts_pin_enabled) { ++ unsigned long timeout = msecs_to_jiffies(aq_ptp->poll_timeout_ms); ++ ++ schedule_delayed_work(&aq_ptp->poll_sync, timeout); ++ } ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +index 7a7f36f43ce0..3de4682f7c06 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +@@ -52,4 +52,6 @@ u16 aq_ptp_extract_ts(struct aq_nic_s *aq_nic, struct sk_buff *skb, u8 *p, + + struct ptp_clock *aq_ptp_get_ptp_clock(struct aq_ptp_s *aq_ptp); + ++int aq_ptp_link_change(struct aq_nic_s *aq_nic); ++ + #endif /* AQ_PTP_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 56cec2ea0af0..51ecf87e0198 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -10,6 +10,7 @@ + #include "../aq_hw_utils.h" + #include "../aq_ring.h" + #include "../aq_nic.h" ++#include "../aq_phy.h" + #include "hw_atl_b0.h" + #include "hw_atl_utils.h" + #include "hw_atl_llh.h" +@@ -1151,6 +1152,12 @@ static int hw_atl_b0_set_sys_clock(struct aq_hw_s *self, u64 time, u64 ts) + return hw_atl_b0_adj_sys_clock(self, delta); + } + ++int hw_atl_b0_ts_to_sys_clock(struct aq_hw_s *self, u64 ts, u64 *time) ++{ ++ *time = self->ptp_clk_offset + ts; ++ return 0; ++} ++ + static int hw_atl_b0_adj_clock_freq(struct aq_hw_s *self, s32 ppb) + { + struct hw_fw_request_iface fwreq; +@@ -1173,6 +1180,57 @@ static int hw_atl_b0_adj_clock_freq(struct aq_hw_s *self, s32 ppb) + return self->aq_fw_ops->send_fw_request(self, &fwreq, size); + } + ++static int hw_atl_b0_gpio_pulse(struct aq_hw_s *self, u32 index, ++ u64 start, u32 period) ++{ ++ struct hw_fw_request_iface fwreq; ++ size_t size; ++ ++ memset(&fwreq, 0, sizeof(fwreq)); ++ ++ fwreq.msg_id = HW_AQ_FW_REQUEST_PTP_GPIO_CTRL; ++ fwreq.ptp_gpio_ctrl.index = index; ++ fwreq.ptp_gpio_ctrl.period = period; ++ /* Apply time offset */ ++ fwreq.ptp_gpio_ctrl.start = start - self->ptp_clk_offset; ++ ++ size = sizeof(fwreq.msg_id) + sizeof(fwreq.ptp_gpio_ctrl); ++ return self->aq_fw_ops->send_fw_request(self, &fwreq, size); ++} ++ ++static int hw_atl_b0_extts_gpio_enable(struct aq_hw_s *self, u32 index, ++ u32 enable) ++{ ++ /* Enable/disable Sync1588 GPIO Timestamping */ ++ aq_phy_write_reg(self, MDIO_MMD_PCS, 0xc611, enable ? 0x71 : 0); ++ ++ return 0; ++} ++ ++static int hw_atl_b0_get_sync_ts(struct aq_hw_s *self, u64 *ts) ++{ ++ u64 sec_l; ++ u64 sec_h; ++ u64 nsec_l; ++ u64 nsec_h; ++ ++ if (!ts) ++ return -1; ++ ++ /* PTP external GPIO clock seconds count 15:0 */ ++ sec_l = aq_phy_read_reg(self, MDIO_MMD_PCS, 0xc914); ++ /* PTP external GPIO clock seconds count 31:16 */ ++ sec_h = aq_phy_read_reg(self, MDIO_MMD_PCS, 0xc915); ++ /* PTP external GPIO clock nanoseconds count 15:0 */ ++ nsec_l = aq_phy_read_reg(self, MDIO_MMD_PCS, 0xc916); ++ /* PTP external GPIO clock nanoseconds count 31:16 */ ++ nsec_h = aq_phy_read_reg(self, MDIO_MMD_PCS, 0xc917); ++ ++ *ts = (nsec_h << 16) + nsec_l + ((sec_h << 16) + sec_l) * NSEC_PER_SEC; ++ ++ return 0; ++} ++ + static u16 hw_atl_b0_rx_extract_ts(struct aq_hw_s *self, u8 *p, + unsigned int len, u64 *timestamp) + { +@@ -1416,8 +1474,11 @@ const struct aq_hw_ops hw_atl_ops_b0 = { + .hw_get_ptp_ts = hw_atl_b0_get_ptp_ts, + .hw_adj_sys_clock = hw_atl_b0_adj_sys_clock, + .hw_set_sys_clock = hw_atl_b0_set_sys_clock, ++ .hw_ts_to_sys_clock = hw_atl_b0_ts_to_sys_clock, + .hw_adj_clock_freq = hw_atl_b0_adj_clock_freq, +- ++ .hw_gpio_pulse = hw_atl_b0_gpio_pulse, ++ .hw_extts_gpio_enable = hw_atl_b0_extts_gpio_enable, ++ .hw_get_sync_ts = hw_atl_b0_get_sync_ts, + .rx_extract_ts = hw_atl_b0_rx_extract_ts, + .extract_hwts = hw_atl_b0_extract_hwts, + .hw_set_offload = hw_atl_b0_hw_offload_set, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index 77132bda4696..37e6b696009d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -288,6 +288,12 @@ struct __packed offload_info { + }; + + /* Mailbox FW Request interface */ ++struct __packed hw_fw_request_ptp_gpio_ctrl { ++ u32 index; ++ u32 period; ++ u64 start; ++}; ++ + struct __packed hw_fw_request_ptp_adj_freq { + u32 ns_mac; + u32 fns_mac; +@@ -303,6 +309,7 @@ struct __packed hw_fw_request_ptp_adj_clock { + int sign; + }; + ++#define HW_AQ_FW_REQUEST_PTP_GPIO_CTRL 0x11 + #define HW_AQ_FW_REQUEST_PTP_ADJ_FREQ 0x12 + #define HW_AQ_FW_REQUEST_PTP_ADJ_CLOCK 0x13 + +@@ -310,6 +317,7 @@ struct __packed hw_fw_request_iface { + u32 msg_id; + union { + /* PTP FW Request */ ++ struct hw_fw_request_ptp_gpio_ctrl ptp_gpio_ctrl; + struct hw_fw_request_ptp_adj_freq ptp_adj_freq; + struct hw_fw_request_ptp_adj_clock ptp_adj_clock; + }; +-- +2.13.6 + diff --git a/SOURCES/0030-netdrv-net-aquantia-fix-var-initialization-warning.patch b/SOURCES/0030-netdrv-net-aquantia-fix-var-initialization-warning.patch new file mode 100644 index 0000000..bea67f5 --- /dev/null +++ b/SOURCES/0030-netdrv-net-aquantia-fix-var-initialization-warning.patch @@ -0,0 +1,55 @@ +From 539be87d83e96b3624d80bcee8d3bd5996a1ce87 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:47 -0500 +Subject: [PATCH 030/139] [netdrv] net: aquantia: fix var initialization + warning + +Message-id: <1604687916-15087-31-git-send-email-irusskik@redhat.com> +Patchwork-id: 338449 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 030/139] net: aquantia: fix var initialization warning +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit bb1eded18d139c815f39abb77390a7040fb24b04 +Author: Igor Russkikh +Date: Sat Oct 26 11:05:31 2019 +0000 + + net: aquantia: fix var initialization warning + + found by sparse, simply useless local initialization with zero. + + Fixes: 94ad94558b0f ("net: aquantia: add PTP rings infrastructure") + Reported-by: kbuild test robot + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index 3ec08415e53e..bb6fbbadfd47 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -947,7 +947,7 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic) + { + struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; + unsigned int tx_ring_idx, rx_ring_idx; +- struct aq_ring_s *hwts = 0; ++ struct aq_ring_s *hwts; + u32 tx_tc_mode, rx_tc_mode; + struct aq_ring_s *ring; + int err; +-- +2.13.6 + diff --git a/SOURCES/0031-netdrv-net-aquantia-fix-warnings-on-endianness.patch b/SOURCES/0031-netdrv-net-aquantia-fix-warnings-on-endianness.patch new file mode 100644 index 0000000..be5c7ef --- /dev/null +++ b/SOURCES/0031-netdrv-net-aquantia-fix-warnings-on-endianness.patch @@ -0,0 +1,84 @@ +From 9a6e98753774849b077307443c22abb146451f85 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:48 -0500 +Subject: [PATCH 031/139] [netdrv] net: aquantia: fix warnings on endianness + +Message-id: <1604687916-15087-32-git-send-email-irusskik@redhat.com> +Patchwork-id: 338456 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 031/139] net: aquantia: fix warnings on endianness +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 5eeb6c3cf26eac522df07bee1a58573804179126 +Author: Igor Russkikh +Date: Sat Oct 26 11:05:33 2019 +0000 + + net: aquantia: fix warnings on endianness + + fixes to remove sparse warnings: + sparse: sparse: cast to restricted __be64 + + Fixes: 04a1839950d9 ("net: aquantia: implement data PTP datapath") + Reported-by: kbuild test robot + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 9 ++++----- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h | 2 +- + 2 files changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 51ecf87e0198..abee561ea54e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1236,9 +1236,9 @@ static u16 hw_atl_b0_rx_extract_ts(struct aq_hw_s *self, u8 *p, + { + unsigned int offset = 14; + struct ethhdr *eth; +- u64 sec; ++ __be64 sec; ++ __be32 ns; + u8 *ptr; +- u32 ns; + + if (len <= offset || !timestamp) + return 0; +@@ -1256,9 +1256,8 @@ static u16 hw_atl_b0_rx_extract_ts(struct aq_hw_s *self, u8 *p, + ptr += sizeof(sec); + memcpy(&ns, ptr, sizeof(ns)); + +- sec = be64_to_cpu(sec) & 0xffffffffffffllu; +- ns = be32_to_cpu(ns); +- *timestamp = sec * NSEC_PER_SEC + ns + self->ptp_clk_offset; ++ *timestamp = (be64_to_cpu(sec) & 0xffffffffffffllu) * NSEC_PER_SEC + ++ be32_to_cpu(ns) + self->ptp_clk_offset; + + eth = (struct ethhdr *)p; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index 37e6b696009d..ee11b107f0a5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -41,7 +41,7 @@ struct __packed hw_atl_rxd_wb_s { + u16 status; + u16 pkt_len; + u16 next_desc_ptr; +- u16 vlan; ++ __le16 vlan; + }; + + /* Hardware rx HW TIMESTAMP writeback */ +-- +2.13.6 + diff --git a/SOURCES/0032-netdrv-net-aquantia-disable-ptp-object-build-if-no-c.patch b/SOURCES/0032-netdrv-net-aquantia-disable-ptp-object-build-if-no-c.patch new file mode 100644 index 0000000..4d2db21 --- /dev/null +++ b/SOURCES/0032-netdrv-net-aquantia-disable-ptp-object-build-if-no-c.patch @@ -0,0 +1,164 @@ +From c197a8c38b4b4cd9d2fb973ffb04de19a5ae83e8 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:49 -0500 +Subject: [PATCH 032/139] [netdrv] net: aquantia: disable ptp object build if + no config + +Message-id: <1604687916-15087-33-git-send-email-irusskik@redhat.com> +Patchwork-id: 338457 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 032/139] net: aquantia: disable ptp object build if no config +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 7873ee26b10bcb03553b6a26ec16b9a937a5b916 +Author: Igor Russkikh +Date: Sat Oct 26 11:05:34 2019 +0000 + + net: aquantia: disable ptp object build if no config + + We do disable aq_ptp module build using inline + stubs when CONFIG_PTP_1588_CLOCK is not declared. + + This reduces module size and removes unnecessary code. + + Reported-by: YueHaibing + Signed-off-by: Igor Russkikh + Acked-by: Richard Cochran + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/Makefile | 3 +- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.h | 84 +++++++++++++++++++++++++ + 2 files changed, 86 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile +index 68c41141ede2..0020726db204 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/Makefile ++++ b/drivers/net/ethernet/aquantia/atlantic/Makefile +@@ -24,10 +24,11 @@ atlantic-objs := aq_main.o \ + aq_ethtool.o \ + aq_drvinfo.o \ + aq_filters.o \ +- aq_ptp.o \ + aq_phy.o \ + hw_atl/hw_atl_a0.o \ + hw_atl/hw_atl_b0.o \ + hw_atl/hw_atl_utils.o \ + hw_atl/hw_atl_utils_fw2x.o \ + hw_atl/hw_atl_llh.o ++ ++atlantic-$(CONFIG_PTP_1588_CLOCK) += aq_ptp.o +\ No newline at end of file +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +index 3de4682f7c06..bf503a40b6a4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +@@ -11,6 +11,8 @@ + #include + #include + ++#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) ++ + /* Common functions */ + int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec); + +@@ -54,4 +56,86 @@ struct ptp_clock *aq_ptp_get_ptp_clock(struct aq_ptp_s *aq_ptp); + + int aq_ptp_link_change(struct aq_nic_s *aq_nic); + ++#else ++ ++static inline int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) ++{ ++ return 0; ++} ++ ++static inline void aq_ptp_unregister(struct aq_nic_s *aq_nic) {} ++ ++static inline void aq_ptp_free(struct aq_nic_s *aq_nic) ++{ ++} ++ ++static inline int aq_ptp_irq_alloc(struct aq_nic_s *aq_nic) ++{ ++ return 0; ++} ++ ++static inline void aq_ptp_irq_free(struct aq_nic_s *aq_nic) ++{ ++} ++ ++static inline int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic) ++{ ++ return 0; ++} ++ ++static inline void aq_ptp_ring_free(struct aq_nic_s *aq_nic) {} ++ ++static inline int aq_ptp_ring_init(struct aq_nic_s *aq_nic) ++{ ++ return 0; ++} ++ ++static inline int aq_ptp_ring_start(struct aq_nic_s *aq_nic) ++{ ++ return 0; ++} ++ ++static inline void aq_ptp_ring_stop(struct aq_nic_s *aq_nic) {} ++static inline void aq_ptp_ring_deinit(struct aq_nic_s *aq_nic) {} ++static inline void aq_ptp_service_task(struct aq_nic_s *aq_nic) {} ++static inline void aq_ptp_tm_offset_set(struct aq_nic_s *aq_nic, ++ unsigned int mbps) {} ++static inline void aq_ptp_clock_init(struct aq_nic_s *aq_nic) {} ++static inline int aq_ptp_xmit(struct aq_nic_s *aq_nic, struct sk_buff *skb) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline void aq_ptp_tx_hwtstamp(struct aq_nic_s *aq_nic, u64 timestamp) {} ++static inline void aq_ptp_hwtstamp_config_get(struct aq_ptp_s *aq_ptp, ++ struct hwtstamp_config *config) {} ++static inline int aq_ptp_hwtstamp_config_set(struct aq_ptp_s *aq_ptp, ++ struct hwtstamp_config *config) ++{ ++ return 0; ++} ++ ++static inline bool aq_ptp_ring(struct aq_nic_s *aq_nic, struct aq_ring_s *ring) ++{ ++ return false; ++} ++ ++static inline u16 aq_ptp_extract_ts(struct aq_nic_s *aq_nic, ++ struct sk_buff *skb, u8 *p, ++ unsigned int len) ++{ ++ return 0; ++} ++ ++static inline struct ptp_clock *aq_ptp_get_ptp_clock(struct aq_ptp_s *aq_ptp) ++{ ++ return NULL; ++} ++ ++static inline int aq_ptp_link_change(struct aq_nic_s *aq_nic) ++{ ++ return 0; ++} ++#endif ++ + #endif /* AQ_PTP_H */ +-- +2.13.6 + diff --git a/SOURCES/0033-netdrv-net-aquantia-fix-spelling-mistake-tx_queus-tx.patch b/SOURCES/0033-netdrv-net-aquantia-fix-spelling-mistake-tx_queus-tx.patch new file mode 100644 index 0000000..bec19f5 --- /dev/null +++ b/SOURCES/0033-netdrv-net-aquantia-fix-spelling-mistake-tx_queus-tx.patch @@ -0,0 +1,54 @@ +From 4aac272db692d044aa87f843eef1772af4f97a18 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:50 -0500 +Subject: [PATCH 033/139] [netdrv] net: aquantia: fix spelling mistake: + tx_queus -> tx_queues + +Message-id: <1604687916-15087-34-git-send-email-irusskik@redhat.com> +Patchwork-id: 338459 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 033/139] net: aquantia: fix spelling mistake: tx_queus -> tx_queues +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 69977901867aefbdda5f5f75af067fff08650af2 +Author: Colin Ian King +Date: Fri Oct 25 12:38:28 2019 +0100 + + net: aquantia: fix spelling mistake: tx_queus -> tx_queues + + There is a spelling mistake in a netdev_err error message. Fix it. + + Signed-off-by: Colin Ian King + Reviewed-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index bb6fbbadfd47..1b3be0553e31 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -533,7 +533,7 @@ void aq_ptp_tx_hwtstamp(struct aq_nic_s *aq_nic, u64 timestamp) + struct skb_shared_hwtstamps hwtstamp; + + if (!skb) { +- netdev_err(aq_nic->ndev, "have timestamp but tx_queus empty\n"); ++ netdev_err(aq_nic->ndev, "have timestamp but tx_queues empty\n"); + return; + } + +-- +2.13.6 + diff --git a/SOURCES/0034-netdrv-net-aquantia-fix-unintention-integer-overflow.patch b/SOURCES/0034-netdrv-net-aquantia-fix-unintention-integer-overflow.patch new file mode 100644 index 0000000..6903414 --- /dev/null +++ b/SOURCES/0034-netdrv-net-aquantia-fix-unintention-integer-overflow.patch @@ -0,0 +1,60 @@ +From cc5ba2a52846c54f6be4668a790d82ea260b51a1 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:51 -0500 +Subject: [PATCH 034/139] [netdrv] net: aquantia: fix unintention integer + overflow on left shift + +Message-id: <1604687916-15087-35-git-send-email-irusskik@redhat.com> +Patchwork-id: 338462 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 034/139] net: aquantia: fix unintention integer overflow on left shift +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 92d72f1b8bbbd87220daa49cd1253ce72bb7553c +Author: Colin Ian King +Date: Fri Oct 25 12:58:11 2019 +0100 + + net: aquantia: fix unintention integer overflow on left shift + + Shifting the integer value 1 is evaluated using 32-bit + arithmetic and then used in an expression that expects a 64-bit + value, so there is potentially an integer overflow. Fix this + by using the BIT_ULL macro to perform the shift and avoid the + overflow. + + Addresses-Coverity: ("Unintentional integer overflow") + Fixes: 04a1839950d9 ("net: aquantia: implement data PTP datapath") + Signed-off-by: Colin Ian King + Reviewed-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index 1b3be0553e31..dca092f454b4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -713,7 +713,7 @@ static int aq_ptp_poll(struct napi_struct *napi, int budget) + if (work_done < budget) { + napi_complete_done(napi, work_done); + aq_nic->aq_hw_ops->hw_irq_enable(aq_nic->aq_hw, +- 1 << aq_ptp->ptp_ring_param.vec_idx); ++ BIT_ULL(aq_ptp->ptp_ring_param.vec_idx)); + } + + err_exit: +-- +2.13.6 + diff --git a/SOURCES/0035-netdrv-net-aquantia-make-two-symbols-be-static.patch b/SOURCES/0035-netdrv-net-aquantia-make-two-symbols-be-static.patch new file mode 100644 index 0000000..3954eca --- /dev/null +++ b/SOURCES/0035-netdrv-net-aquantia-make-two-symbols-be-static.patch @@ -0,0 +1,80 @@ +From a011ce039a9c68edeefa0a5d664d9802d9c9a747 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:52 -0500 +Subject: [PATCH 035/139] [netdrv] net: aquantia: make two symbols be static + +Message-id: <1604687916-15087-36-git-send-email-irusskik@redhat.com> +Patchwork-id: 338463 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 035/139] net: aquantia: make two symbols be static +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 11dbb632a45a120ceb64f9f2a733992f947278c8 +Author: Mao Wenan +Date: Sat Oct 26 10:07:38 2019 +0800 + + net: aquantia: make two symbols be static + + When using ARCH=mips CROSS_COMPILE=mips-linux-gnu- + to build drivers/net/ethernet/aquantia/atlantic/aq_ptp.o + and drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.o, + below errors can be seen: + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c:1378:6: + warning: symbol 'aq_ptp_poll_sync_work_cb' was not declared. + Should it be static? + + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c:1155:5: + warning: symbol 'hw_atl_b0_ts_to_sys_clock' was not declared. + Should it be static? + + This patch to make aq_ptp_poll_sync_work_cb and hw_atl_b0_ts_to_sys_clock + be static to fix these warnings. + + Fixes: 9c477032f7d0 ("net: aquantia: add support for PIN funcs") + Signed-off-by: Mao Wenan + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 2 +- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index dca092f454b4..4ca36003c6ca 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -1375,7 +1375,7 @@ static int aq_ptp_check_sync1588(struct aq_ptp_s *aq_ptp) + return 0; + } + +-void aq_ptp_poll_sync_work_cb(struct work_struct *w) ++static void aq_ptp_poll_sync_work_cb(struct work_struct *w) + { + struct delayed_work *dw = to_delayed_work(w); + struct aq_ptp_s *aq_ptp = container_of(dw, struct aq_ptp_s, poll_sync); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index abee561ea54e..c7297ca03624 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1152,7 +1152,7 @@ static int hw_atl_b0_set_sys_clock(struct aq_hw_s *self, u64 time, u64 ts) + return hw_atl_b0_adj_sys_clock(self, delta); + } + +-int hw_atl_b0_ts_to_sys_clock(struct aq_hw_s *self, u64 ts, u64 *time) ++static int hw_atl_b0_ts_to_sys_clock(struct aq_hw_s *self, u64 ts, u64 *time) + { + *time = self->ptp_clk_offset + ts; + return 0; +-- +2.13.6 + diff --git a/SOURCES/0036-netdrv-net-aquantia-remove-unused-including-linux-ve.patch b/SOURCES/0036-netdrv-net-aquantia-remove-unused-including-linux-ve.patch new file mode 100644 index 0000000..fd256f2 --- /dev/null +++ b/SOURCES/0036-netdrv-net-aquantia-remove-unused-including-linux-ve.patch @@ -0,0 +1,52 @@ +From 9c6017427a003727312b3a7608cf850202ca1f85 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:53 -0500 +Subject: [PATCH 036/139] [netdrv] net: aquantia: remove unused including + + +Message-id: <1604687916-15087-37-git-send-email-irusskik@redhat.com> +Patchwork-id: 338467 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 036/139] net: aquantia: remove unused including +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 207136dfeb3b2cde873b48d745100fa688c83f06 +Author: YueHaibing +Date: Sat Oct 26 02:51:09 2019 +0000 + + net: aquantia: remove unused including + + Remove including that don't need it. + + Signed-off-by: YueHaibing + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +index bf503a40b6a4..231906431a48 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +@@ -9,7 +9,6 @@ + #define AQ_PTP_H + + #include +-#include + + #if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) + +-- +2.13.6 + diff --git a/SOURCES/0037-netdrv-net-aquantia-fix-error-handling-in-aq_ptp_pol.patch b/SOURCES/0037-netdrv-net-aquantia-fix-error-handling-in-aq_ptp_pol.patch new file mode 100644 index 0000000..79a0a8f --- /dev/null +++ b/SOURCES/0037-netdrv-net-aquantia-fix-error-handling-in-aq_ptp_pol.patch @@ -0,0 +1,57 @@ +From 082524971f8bf307d604eba664777098c912392a Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:54 -0500 +Subject: [PATCH 037/139] [netdrv] net: aquantia: fix error handling in + aq_ptp_poll + +Message-id: <1604687916-15087-38-git-send-email-irusskik@redhat.com> +Patchwork-id: 338461 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 037/139] net: aquantia: fix error handling in aq_ptp_poll +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 76d7774e203d422edb6b8c6db800478ca029fde5 +Author: Gustavo A. R. Silva +Date: Mon Oct 28 02:04:47 2019 -0500 + + net: aquantia: fix error handling in aq_ptp_poll + + Fix currenty ignored returned error by properly checking *err* after + calling aq_nic->aq_hw_ops->hw_ring_hwts_rx_fill(). + + Addresses-Coverity-ID: 1487357 ("Unused value") + Fixes: 04a1839950d9 ("net: aquantia: implement data PTP datapath") + Signed-off-by: Gustavo A. R. Silva + Reviewed-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index 4ca36003c6ca..8175513e48c9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -678,6 +678,8 @@ static int aq_ptp_poll(struct napi_struct *napi, int budget) + + err = aq_nic->aq_hw_ops->hw_ring_hwts_rx_fill(aq_nic->aq_hw, + &aq_ptp->hwts_rx); ++ if (err < 0) ++ goto err_exit; + + was_cleaned = true; + } +-- +2.13.6 + diff --git a/SOURCES/0038-netdrv-net-aquantia-fix-return-value-check-in-aq_ptp.patch b/SOURCES/0038-netdrv-net-aquantia-fix-return-value-check-in-aq_ptp.patch new file mode 100644 index 0000000..c019207 --- /dev/null +++ b/SOURCES/0038-netdrv-net-aquantia-fix-return-value-check-in-aq_ptp.patch @@ -0,0 +1,55 @@ +From 1d5de9236ce4575b6b00d35eccd40cb4219cf6be Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:55 -0500 +Subject: [PATCH 038/139] [netdrv] net: aquantia: fix return value check in + aq_ptp_init() + +Message-id: <1604687916-15087-39-git-send-email-irusskik@redhat.com> +Patchwork-id: 338465 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 038/139] net: aquantia: fix return value check in aq_ptp_init() +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 1dcff44a9d2b74b3de2c854bbf11a5f765e7ba77 +Author: Wei Yongjun +Date: Wed Nov 6 14:59:21 2019 +0000 + + net: aquantia: fix return value check in aq_ptp_init() + + Function ptp_clock_register() returns ERR_PTR() and never returns + NULL. The NULL test should be removed. + + Signed-off-by: Wei Yongjun + Acked-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index 8175513e48c9..1f9eab74453e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -1207,7 +1207,7 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + aq_ptp->ptp_info = aq_ptp_clock; + aq_ptp_gpio_init(&aq_ptp->ptp_info, &mbox.info); + clock = ptp_clock_register(&aq_ptp->ptp_info, &aq_nic->ndev->dev); +- if (!clock || IS_ERR(clock)) { ++ if (IS_ERR(clock)) { + netdev_err(aq_nic->ndev, "ptp_clock_register failed\n"); + err = PTR_ERR(clock); + goto err_exit; +-- +2.13.6 + diff --git a/SOURCES/0039-netdrv-net-atlantic-update-firmware-interface.patch b/SOURCES/0039-netdrv-net-atlantic-update-firmware-interface.patch new file mode 100644 index 0000000..4105f9b --- /dev/null +++ b/SOURCES/0039-netdrv-net-atlantic-update-firmware-interface.patch @@ -0,0 +1,342 @@ +From 58fd0b97bf29a158260f77695d7a0065fd315e5f Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:56 -0500 +Subject: [PATCH 039/139] [netdrv] net: atlantic: update firmware interface + +Message-id: <1604687916-15087-40-git-send-email-irusskik@redhat.com> +Patchwork-id: 338469 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 039/139] net: atlantic: update firmware interface +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit d993e14bd872e1e30e2028cbaa0302acf2661579 +Author: Nikita Danilov +Date: Thu Nov 7 22:41:49 2019 +0000 + + net: atlantic: update firmware interface + + Here we improve FW interface structures layout + and prepare these for the wake phy feature implementation. + + Signed-off-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 18 ++- + .../aquantia/atlantic/hw_atl/hw_atl_utils.h | 173 ++++++++------------- + 2 files changed, 72 insertions(+), 119 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 6fc5640065bd..6c7caff9a96b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -858,22 +858,26 @@ static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac) + memset(prpc, 0, sizeof(*prpc)); + + if (wol_enabled) { +- rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_wol); ++ rpc_size = offsetof(struct hw_atl_utils_fw_rpc, msg_wol_add) + ++ sizeof(prpc->msg_wol_add); ++ + + prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD; +- prpc->msg_wol.priority = ++ prpc->msg_wol_add.priority = + HAL_ATLANTIC_UTILS_FW_MSG_WOL_PRIOR; +- prpc->msg_wol.pattern_id = ++ prpc->msg_wol_add.pattern_id = + HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN; +- prpc->msg_wol.wol_packet_type = ++ prpc->msg_wol_add.packet_type = + HAL_ATLANTIC_UTILS_FW_MSG_WOL_MAG_PKT; + +- ether_addr_copy((u8 *)&prpc->msg_wol.wol_pattern, mac); ++ ether_addr_copy((u8 *)&prpc->msg_wol_add.magic_packet_pattern, ++ mac); + } else { +- rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_del_id); ++ rpc_size = sizeof(prpc->msg_wol_remove) + ++ offsetof(struct hw_atl_utils_fw_rpc, msg_wol_remove); + + prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL; +- prpc->msg_wol.pattern_id = ++ prpc->msg_wol_add.pattern_id = + HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN; + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index ee11b107f0a5..c6708f0d5d3e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -70,104 +70,41 @@ struct __packed hw_atl_stats_s { + u32 dpc; + }; + +-union __packed ip_addr { +- struct { +- u8 addr[16]; +- } v6; +- struct { +- u8 padding[12]; +- u8 addr[4]; +- } v4; +-}; +- +-struct __packed hw_atl_utils_fw_rpc { +- u32 msg_id; +- ++struct __packed drv_msg_enable_wakeup { + union { +- struct { +- u32 pong; +- } msg_ping; ++ u32 pattern_mask; + + struct { +- u8 mac_addr[6]; +- u32 ip_addr_cnt; ++ u32 reason_arp_v4_pkt : 1; ++ u32 reason_ipv4_ping_pkt : 1; ++ u32 reason_ipv6_ns_pkt : 1; ++ u32 reason_ipv6_ping_pkt : 1; ++ u32 reason_link_up : 1; ++ u32 reason_link_down : 1; ++ u32 reason_maximum : 1; ++ }; ++ }; + +- struct { +- union ip_addr addr; +- union ip_addr mask; +- } ip[1]; +- } msg_arp; ++ union { ++ u32 offload_mask; ++ }; ++}; + +- struct { +- u32 len; +- u8 packet[1514U]; +- } msg_inject; ++struct __packed magic_packet_pattern_s { ++ u8 mac_addr[ETH_ALEN]; ++}; + +- struct { +- u32 priority; +- u32 wol_packet_type; +- u32 pattern_id; +- u32 next_wol_pattern_offset; +- +- union { +- struct { +- u32 flags; +- u8 ipv4_source_address[4]; +- u8 ipv4_dest_address[4]; +- u16 tcp_source_port_number; +- u16 tcp_dest_port_number; +- } ipv4_tcp_syn_parameters; +- +- struct { +- u32 flags; +- u8 ipv6_source_address[16]; +- u8 ipv6_dest_address[16]; +- u16 tcp_source_port_number; +- u16 tcp_dest_port_number; +- } ipv6_tcp_syn_parameters; +- +- struct { +- u32 flags; +- } eapol_request_id_message_parameters; +- +- struct { +- u32 flags; +- u32 mask_offset; +- u32 mask_size; +- u32 pattern_offset; +- u32 pattern_size; +- } wol_bit_map_pattern; +- +- struct { +- u8 mac_addr[ETH_ALEN]; +- } wol_magic_packet_patter; +- } wol_pattern; +- } msg_wol; ++struct __packed drv_msg_wol_add { ++ u32 priority; ++ u32 packet_type; ++ u32 pattern_id; ++ u32 next_pattern_offset; + +- struct { +- union { +- u32 pattern_mask; +- +- struct { +- u32 reason_arp_v4_pkt : 1; +- u32 reason_ipv4_ping_pkt : 1; +- u32 reason_ipv6_ns_pkt : 1; +- u32 reason_ipv6_ping_pkt : 1; +- u32 reason_link_up : 1; +- u32 reason_link_down : 1; +- u32 reason_maximum : 1; +- }; +- }; +- +- union { +- u32 offload_mask; +- }; +- } msg_enable_wakeup; ++ struct magic_packet_pattern_s magic_packet_pattern; ++}; + +- struct { +- u32 id; +- } msg_del_id; +- }; ++struct __packed drv_msg_wol_remove { ++ u32 id; + }; + + struct __packed hw_atl_utils_mbox_header { +@@ -189,6 +126,13 @@ struct __packed hw_aq_ptp_offset { + u16 egress_10000; + }; + ++struct __packed hw_atl_cable_diag { ++ u8 fault; ++ u8 distance; ++ u8 far_distance; ++ u8 reserved; ++}; ++ + enum gpio_pin_function { + GPIO_PIN_FUNCTION_NC, + GPIO_PIN_FUNCTION_VAUX_ENABLE, +@@ -210,7 +154,7 @@ struct __packed hw_aq_info { + u16 phy_temperature; + u8 cable_len; + u8 reserved1; +- u32 cable_diag_data[4]; ++ struct hw_atl_cable_diag cable_diag_data[4]; + struct hw_aq_ptp_offset ptp_offset; + u8 reserved2[12]; + u32 caps_lo; +@@ -236,25 +180,22 @@ struct __packed hw_atl_utils_mbox { + struct hw_aq_info info; + }; + +-/* fw2x */ +-typedef u32 fw_offset_t; +- + struct __packed offload_ip_info { + u8 v4_local_addr_count; + u8 v4_addr_count; + u8 v6_local_addr_count; + u8 v6_addr_count; +- fw_offset_t v4_addr; +- fw_offset_t v4_prefix; +- fw_offset_t v6_addr; +- fw_offset_t v6_prefix; ++ u32 v4_addr; ++ u32 v4_prefix; ++ u32 v6_addr; ++ u32 v6_prefix; + }; + + struct __packed offload_port_info { + u16 udp_port_count; + u16 tcp_port_count; +- fw_offset_t udp_port; +- fw_offset_t tcp_port; ++ u32 udp_port; ++ u32 tcp_port; + }; + + struct __packed offload_ka_info { +@@ -262,15 +203,15 @@ struct __packed offload_ka_info { + u16 v6_ka_count; + u32 retry_count; + u32 retry_interval; +- fw_offset_t v4_ka; +- fw_offset_t v6_ka; ++ u32 v4_ka; ++ u32 v6_ka; + }; + + struct __packed offload_rr_info { + u32 rr_count; + u32 rr_buf_len; +- fw_offset_t rr_id_x; +- fw_offset_t rr_buf; ++ u32 rr_id_x; ++ u32 rr_buf; + }; + + struct __packed offload_info { +@@ -287,6 +228,19 @@ struct __packed offload_info { + u8 buf[0]; + }; + ++struct __packed hw_atl_utils_fw_rpc { ++ u32 msg_id; ++ ++ union { ++ /* fw1x structures */ ++ struct drv_msg_wol_add msg_wol_add; ++ struct drv_msg_wol_remove msg_wol_remove; ++ struct drv_msg_enable_wakeup msg_enable_wakeup; ++ /* fw2x structures */ ++ struct offload_info fw2x_offloads; ++ }; ++}; ++ + /* Mailbox FW Request interface */ + struct __packed hw_fw_request_ptp_gpio_ctrl { + u32 index; +@@ -326,6 +280,9 @@ struct __packed hw_fw_request_iface { + enum hw_atl_rx_action_with_traffic { + HW_ATL_RX_DISCARD, + HW_ATL_RX_HOST, ++ HW_ATL_RX_MNGMNT, ++ HW_ATL_RX_HOST_AND_MNGMNT, ++ HW_ATL_RX_WOL + }; + + struct aq_rx_filter_vlan { +@@ -407,20 +364,12 @@ enum hal_atl_utils_fw_state_e { + #define HAL_ATLANTIC_RATE_100M BIT(5) + #define HAL_ATLANTIC_RATE_INVALID BIT(6) + +-#define HAL_ATLANTIC_UTILS_FW_MSG_PING 0x1U +-#define HAL_ATLANTIC_UTILS_FW_MSG_ARP 0x2U +-#define HAL_ATLANTIC_UTILS_FW_MSG_INJECT 0x3U + #define HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD 0x4U + #define HAL_ATLANTIC_UTILS_FW_MSG_WOL_PRIOR 0x10000000U + #define HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN 0x1U + #define HAL_ATLANTIC_UTILS_FW_MSG_WOL_MAG_PKT 0x2U + #define HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL 0x5U + #define HAL_ATLANTIC_UTILS_FW_MSG_ENABLE_WAKEUP 0x6U +-#define HAL_ATLANTIC_UTILS_FW_MSG_MSM_PFC 0x7U +-#define HAL_ATLANTIC_UTILS_FW_MSG_PROVISIONING 0x8U +-#define HAL_ATLANTIC_UTILS_FW_MSG_OFFLOAD_ADD 0x9U +-#define HAL_ATLANTIC_UTILS_FW_MSG_OFFLOAD_DEL 0xAU +-#define HAL_ATLANTIC_UTILS_FW_MSG_CABLE_DIAG 0xDU + + enum hw_atl_fw2x_rate { + FW2X_RATE_100M = 0x20, +-- +2.13.6 + diff --git a/SOURCES/0040-netdrv-net-atlantic-implement-wake_phy-feature.patch b/SOURCES/0040-netdrv-net-atlantic-implement-wake_phy-feature.patch new file mode 100644 index 0000000..796b5fe --- /dev/null +++ b/SOURCES/0040-netdrv-net-atlantic-implement-wake_phy-feature.patch @@ -0,0 +1,393 @@ +From a18a11bc895f73004972b2db47c4d029ba3b4856 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:57 -0500 +Subject: [PATCH 040/139] [netdrv] net: atlantic: implement wake_phy feature + +Message-id: <1604687916-15087-41-git-send-email-irusskik@redhat.com> +Patchwork-id: 338464 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 040/139] net: atlantic: implement wake_phy feature +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 837c637869bef28b06653462cd010ccc0c2ce984 +Author: Nikita Danilov +Date: Thu Nov 7 22:41:50 2019 +0000 + + net: atlantic: implement wake_phy feature + + Wake on PHY allows to configure device to wakeup host + as soon as PHY link status is changed to active. + + Signed-off-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_cfg.h | 3 + + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 18 ++-- + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 4 +- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 34 ++++--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 6 +- + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 7 +- + .../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 111 ++++++--------------- + 7 files changed, 73 insertions(+), 110 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +index 8c633caf79d2..d02b0d79f68a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +@@ -78,6 +78,9 @@ + + #define AQ_CFG_FC_MODE AQ_NIC_FC_FULL + ++/* Default WOL modes used on initialization */ ++#define AQ_CFG_WOL_MODES WAKE_MAGIC ++ + #define AQ_CFG_SPEED_MSK 0xFFFFU /* 0xFFFFU==auto_neg */ + + #define AQ_CFG_IS_AUTONEG_DEF 1U +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 1ae8aabcc41a..3c55cf13cf14 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -356,11 +356,8 @@ static void aq_ethtool_get_wol(struct net_device *ndev, + struct aq_nic_s *aq_nic = netdev_priv(ndev); + struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); + +- wol->supported = WAKE_MAGIC; +- wol->wolopts = 0; +- +- if (cfg->wol) +- wol->wolopts |= WAKE_MAGIC; ++ wol->supported = AQ_NIC_WOL_MODES; ++ wol->wolopts = cfg->wol; + } + + static int aq_ethtool_set_wol(struct net_device *ndev, +@@ -371,11 +368,12 @@ static int aq_ethtool_set_wol(struct net_device *ndev, + struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); + int err = 0; + +- if (wol->wolopts & WAKE_MAGIC) +- cfg->wol |= AQ_NIC_WOL_ENABLED; +- else +- cfg->wol &= ~AQ_NIC_WOL_ENABLED; +- err = device_set_wakeup_enable(&pdev->dev, wol->wolopts); ++ if (wol->wolopts & ~AQ_NIC_WOL_MODES) ++ return -EOPNOTSUPP; ++ ++ cfg->wol = wol->wolopts; ++ ++ err = device_set_wakeup_enable(&pdev->dev, !!cfg->wol); + + return err; + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index a26d4a69efad..2c1096561614 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -74,7 +74,7 @@ static int aq_ndev_open(struct net_device *ndev) + + err_exit: + if (err < 0) +- aq_nic_deinit(aq_nic); ++ aq_nic_deinit(aq_nic, true); + return err; + } + +@@ -86,7 +86,7 @@ static int aq_ndev_close(struct net_device *ndev) + err = aq_nic_stop(aq_nic); + if (err < 0) + goto err_exit; +- aq_nic_deinit(aq_nic); ++ aq_nic_deinit(aq_nic, true); + + err_exit: + return err; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 433adc099e44..75faf288a2fc 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -79,6 +79,7 @@ void aq_nic_cfg_start(struct aq_nic_s *self) + cfg->num_rss_queues = AQ_CFG_NUM_RSS_QUEUES_DEF; + cfg->aq_rss.base_cpu_number = AQ_CFG_RSS_BASE_CPU_NUM_DEF; + cfg->flow_control = AQ_CFG_FC_MODE; ++ cfg->wol = AQ_CFG_WOL_MODES; + + cfg->mtu = AQ_CFG_MTU_DEF; + cfg->link_speed_msk = AQ_CFG_SPEED_MSK; +@@ -1000,7 +1001,20 @@ int aq_nic_stop(struct aq_nic_s *self) + return self->aq_hw_ops->hw_stop(self->aq_hw); + } + +-void aq_nic_deinit(struct aq_nic_s *self) ++void aq_nic_set_power(struct aq_nic_s *self) ++{ ++ if (self->power_state != AQ_HW_POWER_STATE_D0 || ++ self->aq_hw->aq_nic_cfg->wol) ++ if (likely(self->aq_fw_ops->set_power)) { ++ mutex_lock(&self->fwreq_mutex); ++ self->aq_fw_ops->set_power(self->aq_hw, ++ self->power_state, ++ self->ndev->dev_addr); ++ mutex_unlock(&self->fwreq_mutex); ++ } ++} ++ ++void aq_nic_deinit(struct aq_nic_s *self, bool link_down) + { + struct aq_vec_s *aq_vec = NULL; + unsigned int i = 0U; +@@ -1017,23 +1031,12 @@ void aq_nic_deinit(struct aq_nic_s *self) + aq_ptp_ring_free(self); + aq_ptp_free(self); + +- if (likely(self->aq_fw_ops->deinit)) { ++ if (likely(self->aq_fw_ops->deinit) && link_down) { + mutex_lock(&self->fwreq_mutex); + self->aq_fw_ops->deinit(self->aq_hw); + mutex_unlock(&self->fwreq_mutex); + } + +- if (self->power_state != AQ_HW_POWER_STATE_D0 || +- self->aq_hw->aq_nic_cfg->wol) +- if (likely(self->aq_fw_ops->set_power)) { +- mutex_lock(&self->fwreq_mutex); +- self->aq_fw_ops->set_power(self->aq_hw, +- self->power_state, +- self->ndev->dev_addr); +- mutex_unlock(&self->fwreq_mutex); +- } +- +- + err_exit:; + } + +@@ -1072,7 +1075,7 @@ int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg) + if (err < 0) + goto err_exit; + +- aq_nic_deinit(self); ++ aq_nic_deinit(self, !self->aq_hw->aq_nic_cfg->wol); + } else { + err = aq_nic_init(self); + if (err < 0) +@@ -1108,7 +1111,8 @@ void aq_nic_shutdown(struct aq_nic_s *self) + if (err < 0) + goto err_exit; + } +- aq_nic_deinit(self); ++ aq_nic_deinit(self, !self->aq_hw->aq_nic_cfg->wol); ++ aq_nic_set_power(self); + + err_exit: + rtnl_unlock(); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index c2513b79b9e9..8c23ad4ddf38 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -60,7 +60,8 @@ struct aq_nic_cfg_s { + #define AQ_NIC_FLAG_ERR_UNPLUG 0x40000000U + #define AQ_NIC_FLAG_ERR_HW 0x80000000U + +-#define AQ_NIC_WOL_ENABLED BIT(0) ++#define AQ_NIC_WOL_MODES (WAKE_MAGIC |\ ++ WAKE_PHY) + + #define AQ_NIC_TCVEC2RING(_NIC_, _TC_, _VEC_) \ + ((_TC_) * AQ_CFG_TCS_MAX + (_VEC_)) +@@ -141,7 +142,8 @@ int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p); + int aq_nic_get_regs_count(struct aq_nic_s *self); + void aq_nic_get_stats(struct aq_nic_s *self, u64 *data); + int aq_nic_stop(struct aq_nic_s *self); +-void aq_nic_deinit(struct aq_nic_s *self); ++void aq_nic_deinit(struct aq_nic_s *self, bool link_down); ++void aq_nic_set_power(struct aq_nic_s *self); + void aq_nic_free_hot_resources(struct aq_nic_s *self); + void aq_nic_free_vectors(struct aq_nic_s *self); + int aq_nic_set_mtu(struct aq_nic_s *self, int new_mtu); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 6c7caff9a96b..fd2c6be4e22e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -845,7 +845,8 @@ int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version) + return 0; + } + +-static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac) ++static int aq_fw1x_set_wake_magic(struct aq_hw_s *self, bool wol_enabled, ++ u8 *mac) + { + struct hw_atl_utils_fw_rpc *prpc = NULL; + unsigned int rpc_size = 0U; +@@ -894,8 +895,8 @@ static int aq_fw1x_set_power(struct aq_hw_s *self, unsigned int power_state, + unsigned int rpc_size = 0U; + int err = 0; + +- if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) { +- err = aq_fw1x_set_wol(self, 1, mac); ++ if (self->aq_nic_cfg->wol & WAKE_MAGIC) { ++ err = aq_fw1x_set_wake_magic(self, 1, mac); + + if (err < 0) + goto err_exit; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index f649ac949d06..9b89622fa5d4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -34,6 +34,7 @@ + #define HW_ATL_FW2X_CAP_SLEEP_PROXY BIT(CAPS_HI_SLEEP_PROXY) + #define HW_ATL_FW2X_CAP_WOL BIT(CAPS_HI_WOL) + ++#define HW_ATL_FW2X_CTRL_WAKE_ON_LINK BIT(CTRL_WAKE_ON_LINK) + #define HW_ATL_FW2X_CTRL_SLEEP_PROXY BIT(CTRL_SLEEP_PROXY) + #define HW_ATL_FW2X_CTRL_WOL BIT(CTRL_WOL) + #define HW_ATL_FW2X_CTRL_LINK_DROP BIT(CTRL_LINK_DROP) +@@ -345,87 +346,46 @@ static int aq_fw2x_get_phy_temp(struct aq_hw_s *self, int *temp) + return 0; + } + +-static int aq_fw2x_set_sleep_proxy(struct aq_hw_s *self, u8 *mac) ++static int aq_fw2x_set_wol(struct aq_hw_s *self, u8 *mac) + { + struct hw_atl_utils_fw_rpc *rpc = NULL; +- struct offload_info *cfg = NULL; +- unsigned int rpc_size = 0U; +- u32 mpi_opts; ++ struct offload_info *info = NULL; ++ u32 wol_bits = 0; ++ u32 rpc_size; + int err = 0; + u32 val; + +- rpc_size = sizeof(rpc->msg_id) + sizeof(*cfg); +- +- err = hw_atl_utils_fw_rpc_wait(self, &rpc); +- if (err < 0) +- goto err_exit; +- +- memset(rpc, 0, rpc_size); +- cfg = (struct offload_info *)(&rpc->msg_id + 1); +- +- memcpy(cfg->mac_addr, mac, ETH_ALEN); +- cfg->len = sizeof(*cfg); +- +- /* Clear bit 0x36C.23 and 0x36C.22 */ +- mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); +- mpi_opts &= ~HW_ATL_FW2X_CTRL_SLEEP_PROXY; +- mpi_opts &= ~HW_ATL_FW2X_CTRL_LINK_DROP; +- +- aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); +- +- err = hw_atl_utils_fw_rpc_call(self, rpc_size); +- if (err < 0) +- goto err_exit; +- +- /* Set bit 0x36C.23 */ +- mpi_opts |= HW_ATL_FW2X_CTRL_SLEEP_PROXY; +- aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); +- +- err = readx_poll_timeout_atomic(aq_fw2x_state2_get, +- self, val, +- val & HW_ATL_FW2X_CTRL_SLEEP_PROXY, +- 1U, 100000U); +- +-err_exit: +- return err; +-} +- +-static int aq_fw2x_set_wol_params(struct aq_hw_s *self, u8 *mac) +-{ +- struct hw_atl_utils_fw_rpc *rpc = NULL; +- struct fw2x_msg_wol *msg = NULL; +- u32 mpi_opts; +- int err = 0; +- u32 val; +- +- err = hw_atl_utils_fw_rpc_wait(self, &rpc); +- if (err < 0) +- goto err_exit; +- +- msg = (struct fw2x_msg_wol *)rpc; +- +- memset(msg, 0, sizeof(*msg)); ++ if (self->aq_nic_cfg->wol & WAKE_PHY) { ++ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, ++ HW_ATL_FW2X_CTRL_LINK_DROP); ++ readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val, ++ (val & ++ HW_ATL_FW2X_CTRL_LINK_DROP) != 0, ++ 1000, 100000); ++ wol_bits |= HW_ATL_FW2X_CTRL_WAKE_ON_LINK; ++ } + +- msg->msg_id = HAL_ATLANTIC_UTILS_FW2X_MSG_WOL; +- msg->magic_packet_enabled = true; +- memcpy(msg->hw_addr, mac, ETH_ALEN); ++ if (self->aq_nic_cfg->wol & WAKE_MAGIC) { ++ wol_bits |= HW_ATL_FW2X_CTRL_SLEEP_PROXY | ++ HW_ATL_FW2X_CTRL_WOL; + +- mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); +- mpi_opts &= ~(HW_ATL_FW2X_CTRL_SLEEP_PROXY | HW_ATL_FW2X_CTRL_WOL); ++ err = hw_atl_utils_fw_rpc_wait(self, &rpc); ++ if (err < 0) ++ goto err_exit; + +- aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); ++ rpc_size = sizeof(*info) + ++ offsetof(struct hw_atl_utils_fw_rpc, fw2x_offloads); ++ memset(rpc, 0, rpc_size); ++ info = &rpc->fw2x_offloads; ++ memcpy(info->mac_addr, mac, ETH_ALEN); ++ info->len = sizeof(*info); + +- err = hw_atl_utils_fw_rpc_call(self, sizeof(*msg)); +- if (err < 0) +- goto err_exit; ++ err = hw_atl_utils_fw_rpc_call(self, rpc_size); ++ if (err < 0) ++ goto err_exit; ++ } + +- /* Set bit 0x36C.24 */ +- mpi_opts |= HW_ATL_FW2X_CTRL_WOL; +- aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); +- +- err = readx_poll_timeout_atomic(aq_fw2x_state2_get, +- self, val, val & HW_ATL_FW2X_CTRL_WOL, +- 1U, 10000U); ++ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, wol_bits); + + err_exit: + return err; +@@ -436,14 +396,9 @@ static int aq_fw2x_set_power(struct aq_hw_s *self, unsigned int power_state, + { + int err = 0; + +- if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) { +- err = aq_fw2x_set_sleep_proxy(self, mac); +- if (err < 0) +- goto err_exit; +- err = aq_fw2x_set_wol_params(self, mac); +- } ++ if (self->aq_nic_cfg->wol) ++ err = aq_fw2x_set_wol(self, mac); + +-err_exit: + return err; + } + +-- +2.13.6 + diff --git a/SOURCES/0041-netdrv-net-atlantic-refactoring-pm-logic.patch b/SOURCES/0041-netdrv-net-atlantic-refactoring-pm-logic.patch new file mode 100644 index 0000000..d894280 --- /dev/null +++ b/SOURCES/0041-netdrv-net-atlantic-refactoring-pm-logic.patch @@ -0,0 +1,221 @@ +From 2e1781ef47a927e6cdce729f70b3a5732eaedf32 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:58 -0500 +Subject: [PATCH 041/139] [netdrv] net: atlantic: refactoring pm logic + +Message-id: <1604687916-15087-42-git-send-email-irusskik@redhat.com> +Patchwork-id: 338466 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 041/139] net: atlantic: refactoring pm logic +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 8aaa112a57c1d725c92dfad32c0694bd21b374d0 +Author: Nikita Danilov +Date: Thu Nov 7 22:41:52 2019 +0000 + + net: atlantic: refactoring pm logic + + We now implement .driver.pm callbacks, these + allows driver to work correctly in hibernate + usecases, especially when used in conjunction with + WOL feature. + + Before that driver only reacted to legacy .suspend/.resume + callbacks, that was a limitation in some cases. + + Signed-off-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 38 ---------- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 1 - + .../net/ethernet/aquantia/atlantic/aq_pci_func.c | 87 +++++++++++++++++++--- + 3 files changed, 78 insertions(+), 48 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 75faf288a2fc..d5764228cea5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -1057,44 +1057,6 @@ void aq_nic_free_vectors(struct aq_nic_s *self) + err_exit:; + } + +-int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg) +-{ +- int err = 0; +- +- if (!netif_running(self->ndev)) { +- err = 0; +- goto out; +- } +- rtnl_lock(); +- if (pm_msg->event & PM_EVENT_SLEEP || pm_msg->event & PM_EVENT_FREEZE) { +- self->power_state = AQ_HW_POWER_STATE_D3; +- netif_device_detach(self->ndev); +- netif_tx_stop_all_queues(self->ndev); +- +- err = aq_nic_stop(self); +- if (err < 0) +- goto err_exit; +- +- aq_nic_deinit(self, !self->aq_hw->aq_nic_cfg->wol); +- } else { +- err = aq_nic_init(self); +- if (err < 0) +- goto err_exit; +- +- err = aq_nic_start(self); +- if (err < 0) +- goto err_exit; +- +- netif_device_attach(self->ndev); +- netif_tx_start_all_queues(self->ndev); +- } +- +-err_exit: +- rtnl_unlock(); +-out: +- return err; +-} +- + void aq_nic_shutdown(struct aq_nic_s *self) + { + int err = 0; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index 8c23ad4ddf38..ab3176dfc209 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -157,7 +157,6 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self, + const struct ethtool_link_ksettings *cmd); + struct aq_nic_cfg_s *aq_nic_get_cfg(struct aq_nic_s *self); + u32 aq_nic_get_fw_version(struct aq_nic_s *self); +-int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg); + int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self); + void aq_nic_shutdown(struct aq_nic_s *self); + u8 aq_nic_reserve_filter(struct aq_nic_s *self, enum aq_rx_filter_type type); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +index e82c96b50373..3169951fe6ab 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +@@ -347,29 +347,98 @@ static void aq_pci_shutdown(struct pci_dev *pdev) + } + } + +-static int aq_pci_suspend(struct pci_dev *pdev, pm_message_t pm_msg) ++static int aq_suspend_common(struct device *dev, bool deep) + { +- struct aq_nic_s *self = pci_get_drvdata(pdev); ++ struct aq_nic_s *nic = pci_get_drvdata(to_pci_dev(dev)); ++ ++ rtnl_lock(); ++ ++ nic->power_state = AQ_HW_POWER_STATE_D3; ++ netif_device_detach(nic->ndev); ++ netif_tx_stop_all_queues(nic->ndev); + +- return aq_nic_change_pm_state(self, &pm_msg); ++ aq_nic_stop(nic); ++ ++ if (deep) { ++ aq_nic_deinit(nic, !nic->aq_hw->aq_nic_cfg->wol); ++ aq_nic_set_power(nic); ++ } ++ ++ rtnl_unlock(); ++ ++ return 0; + } + +-static int aq_pci_resume(struct pci_dev *pdev) ++static int atl_resume_common(struct device *dev, bool deep) + { +- struct aq_nic_s *self = pci_get_drvdata(pdev); +- pm_message_t pm_msg = PMSG_RESTORE; ++ struct pci_dev *pdev = to_pci_dev(dev); ++ struct aq_nic_s *nic; ++ int ret; ++ ++ nic = pci_get_drvdata(pdev); ++ ++ rtnl_lock(); ++ ++ pci_set_power_state(pdev, PCI_D0); ++ pci_restore_state(pdev); ++ ++ if (deep) { ++ ret = aq_nic_init(nic); ++ if (ret) ++ goto err_exit; ++ } ++ ++ ret = aq_nic_start(nic); ++ if (ret) ++ goto err_exit; ++ ++ netif_device_attach(nic->ndev); ++ netif_tx_start_all_queues(nic->ndev); + +- return aq_nic_change_pm_state(self, &pm_msg); ++err_exit: ++ rtnl_unlock(); ++ ++ return ret; ++} ++ ++static int aq_pm_freeze(struct device *dev) ++{ ++ return aq_suspend_common(dev, false); + } + ++static int aq_pm_suspend_poweroff(struct device *dev) ++{ ++ return aq_suspend_common(dev, true); ++} ++ ++static int aq_pm_thaw(struct device *dev) ++{ ++ return atl_resume_common(dev, false); ++} ++ ++static int aq_pm_resume_restore(struct device *dev) ++{ ++ return atl_resume_common(dev, true); ++} ++ ++const struct dev_pm_ops aq_pm_ops = { ++ .suspend = aq_pm_suspend_poweroff, ++ .poweroff = aq_pm_suspend_poweroff, ++ .freeze = aq_pm_freeze, ++ .resume = aq_pm_resume_restore, ++ .restore = aq_pm_resume_restore, ++ .thaw = aq_pm_thaw, ++}; ++ + static struct pci_driver aq_pci_ops = { + .name = AQ_CFG_DRV_NAME, + .id_table = aq_pci_tbl, + .probe = aq_pci_probe, + .remove = aq_pci_remove, +- .suspend = aq_pci_suspend, +- .resume = aq_pci_resume, + .shutdown = aq_pci_shutdown, ++#ifdef CONFIG_PM ++ .driver.pm = &aq_pm_ops, ++#endif + }; + + int aq_pci_func_register_driver(void) +-- +2.13.6 + diff --git a/SOURCES/0042-netdrv-net-atlantic-add-msglevel-configuration.patch b/SOURCES/0042-netdrv-net-atlantic-add-msglevel-configuration.patch new file mode 100644 index 0000000..feb6d28 --- /dev/null +++ b/SOURCES/0042-netdrv-net-atlantic-add-msglevel-configuration.patch @@ -0,0 +1,114 @@ +From 5e0c058784627f9285b4b45062bfe15a7a381c12 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:36:59 -0500 +Subject: [PATCH 042/139] [netdrv] net: atlantic: add msglevel configuration + +Message-id: <1604687916-15087-43-git-send-email-irusskik@redhat.com> +Patchwork-id: 338470 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 042/139] net: atlantic: add msglevel configuration +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 58128fa0265b75be21ec244680426da50ca72850 +Author: Nikita Danilov +Date: Thu Nov 7 22:41:54 2019 +0000 + + net: atlantic: add msglevel configuration + + We add ethtool msglevel configuration and change some + printouts to use netdev_info set of functions. + + Signed-off-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 16 ++++++++++++++++ + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 7 ++++--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 1 + + 3 files changed, 21 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 3c55cf13cf14..5be273892430 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -607,6 +607,20 @@ static int aq_set_ringparam(struct net_device *ndev, + return err; + } + ++static u32 aq_get_msg_level(struct net_device *ndev) ++{ ++ struct aq_nic_s *aq_nic = netdev_priv(ndev); ++ ++ return aq_nic->msg_enable; ++} ++ ++static void aq_set_msg_level(struct net_device *ndev, u32 data) ++{ ++ struct aq_nic_s *aq_nic = netdev_priv(ndev); ++ ++ aq_nic->msg_enable = data; ++} ++ + const struct ethtool_ops aq_ethtool_ops = { + .get_link = aq_ethtool_get_link, + .get_regs_len = aq_ethtool_get_regs_len, +@@ -628,6 +642,8 @@ const struct ethtool_ops aq_ethtool_ops = { + .set_rxfh = aq_ethtool_set_rss, + .get_rxnfc = aq_ethtool_get_rxnfc, + .set_rxnfc = aq_ethtool_set_rxnfc, ++ .get_msglevel = aq_get_msg_level, ++ .set_msglevel = aq_set_msg_level, + .get_sset_count = aq_ethtool_get_sset_count, + .get_ethtool_stats = aq_ethtool_stats, + .get_link_ksettings = aq_ethtool_get_link_ksettings, +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index d5764228cea5..8f83e91f8146 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -144,9 +144,9 @@ static int aq_nic_update_link_status(struct aq_nic_s *self) + return err; + + if (self->link_status.mbps != self->aq_hw->aq_link_status.mbps) { +- pr_info("%s: link change old %d new %d\n", +- AQ_CFG_DRV_NAME, self->link_status.mbps, +- self->aq_hw->aq_link_status.mbps); ++ netdev_info(self->ndev, "%s: link change old %d new %d\n", ++ AQ_CFG_DRV_NAME, self->link_status.mbps, ++ self->aq_hw->aq_link_status.mbps); + aq_nic_update_interrupt_moderation_settings(self); + + if (self->aq_ptp) { +@@ -306,6 +306,7 @@ void aq_nic_ndev_init(struct aq_nic_s *self) + self->ndev->priv_flags = aq_hw_caps->hw_priv_flags; + self->ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + ++ self->msg_enable = NETIF_MSG_DRV | NETIF_MSG_LINK; + self->ndev->mtu = aq_nic_cfg->mtu - ETH_HLEN; + self->ndev->max_mtu = aq_hw_caps->mtu - ETH_FCS_LEN - ETH_HLEN; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index ab3176dfc209..527273502d54 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -88,6 +88,7 @@ struct aq_hw_rx_fltrs_s { + + struct aq_nic_s { + atomic_t flags; ++ u32 msg_enable; + struct aq_vec_s *aq_vec[AQ_CFG_VECS_MAX]; + struct aq_ring_s *aq_ring_tx[AQ_CFG_VECS_MAX * AQ_CFG_TCS_MAX]; + struct aq_hw_s *aq_hw; +-- +2.13.6 + diff --git a/SOURCES/0043-netdrv-net-atlantic-adding-ethtool-physical-identifi.patch b/SOURCES/0043-netdrv-net-atlantic-adding-ethtool-physical-identifi.patch new file mode 100644 index 0000000..66a6d8c --- /dev/null +++ b/SOURCES/0043-netdrv-net-atlantic-adding-ethtool-physical-identifi.patch @@ -0,0 +1,170 @@ +From 5d842119dc4566fe1d548b21a6a212e33c8eeb01 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:00 -0500 +Subject: [PATCH 043/139] [netdrv] net: atlantic: adding ethtool physical + identification + +Message-id: <1604687916-15087-44-git-send-email-irusskik@redhat.com> +Patchwork-id: 338468 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 043/139] net: atlantic: adding ethtool physical identification +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit d1287ce4ffa1d1f121571ce90ed7ebd410e31a21 +Author: Nikita Danilov +Date: Thu Nov 7 22:41:55 2019 +0000 + + net: atlantic: adding ethtool physical identification + + `ethtool -p eth0` will blink leds helping identify + physical port. + + Signed-off-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 30 ++++++++++++++++++++++ + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 5 ++++ + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 1 + + .../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 14 ++++++++++ + 4 files changed, 50 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 5be273892430..2f877fb46615 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -153,6 +153,35 @@ static void aq_ethtool_get_strings(struct net_device *ndev, + } + } + ++static int aq_ethtool_set_phys_id(struct net_device *ndev, ++ enum ethtool_phys_id_state state) ++{ ++ struct aq_nic_s *aq_nic = netdev_priv(ndev); ++ struct aq_hw_s *hw = aq_nic->aq_hw; ++ int ret = 0; ++ ++ if (!aq_nic->aq_fw_ops->led_control) ++ return -EOPNOTSUPP; ++ ++ mutex_lock(&aq_nic->fwreq_mutex); ++ ++ switch (state) { ++ case ETHTOOL_ID_ACTIVE: ++ ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_BLINK | ++ AQ_HW_LED_BLINK << 2 | AQ_HW_LED_BLINK << 4); ++ break; ++ case ETHTOOL_ID_INACTIVE: ++ ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_DEFAULT); ++ break; ++ default: ++ break; ++ } ++ ++ mutex_unlock(&aq_nic->fwreq_mutex); ++ ++ return ret; ++} ++ + static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset) + { + int ret = 0; +@@ -627,6 +656,7 @@ const struct ethtool_ops aq_ethtool_ops = { + .get_regs = aq_ethtool_get_regs, + .get_drvinfo = aq_ethtool_get_drvinfo, + .get_strings = aq_ethtool_get_strings, ++ .set_phys_id = aq_ethtool_set_phys_id, + .get_rxfh_indir_size = aq_ethtool_get_rss_indir_size, + .get_wol = aq_ethtool_get_wol, + .set_wol = aq_ethtool_set_wol, +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index a5cf6e02d4f6..ce4b8db03882 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -119,6 +119,9 @@ struct aq_stats_s { + #define AQ_HW_TXD_MULTIPLE 8U + #define AQ_HW_RXD_MULTIPLE 8U + ++#define AQ_HW_LED_BLINK 0x2U ++#define AQ_HW_LED_DEFAULT 0x0U ++ + struct aq_hw_s { + atomic_t flags; + u8 rbl_enabled:1; +@@ -304,6 +307,8 @@ struct aq_fw_ops { + + int (*set_flow_control)(struct aq_hw_s *self); + ++ int (*led_control)(struct aq_hw_s *self, u32 mode); ++ + int (*set_power)(struct aq_hw_s *self, unsigned int power_state, + u8 *mac); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index fd2c6be4e22e..fc82ede18b20 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -970,4 +970,5 @@ const struct aq_fw_ops aq_fw_1x_ops = { + .set_flow_control = NULL, + .send_fw_request = NULL, + .enable_ptp = NULL, ++ .led_control = NULL, + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index 9b89622fa5d4..4eab51b5b400 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -17,6 +17,7 @@ + #include "hw_atl_utils.h" + #include "hw_atl_llh.h" + ++#define HW_ATL_FW2X_MPI_LED_ADDR 0x31c + #define HW_ATL_FW2X_MPI_RPC_ADDR 0x334 + + #define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360 +@@ -51,6 +52,8 @@ + #define HAL_ATLANTIC_WOL_FILTERS_COUNT 8 + #define HAL_ATLANTIC_UTILS_FW2X_MSG_WOL 0x0E + ++#define HW_ATL_FW_VER_LED 0x03010026U ++ + struct __packed fw2x_msg_wol_pattern { + u8 mask[16]; + u32 crc; +@@ -450,6 +453,16 @@ static void aq_fw3x_enable_ptp(struct aq_hw_s *self, int enable) + aq_hw_write_reg(self, HW_ATL_FW3X_EXT_CONTROL_ADDR, ptp_opts); + } + ++static int aq_fw2x_led_control(struct aq_hw_s *self, u32 mode) ++{ ++ if (self->fw_ver_actual < HW_ATL_FW_VER_LED) ++ return -EOPNOTSUPP; ++ ++ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_LED_ADDR, mode); ++ ++ return 0; ++} ++ + static int aq_fw2x_set_eee_rate(struct aq_hw_s *self, u32 speed) + { + u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); +@@ -557,4 +570,5 @@ const struct aq_fw_ops aq_fw_2x_ops = { + .get_flow_control = aq_fw2x_get_flow_control, + .send_fw_request = aq_fw2x_send_fw_request, + .enable_ptp = aq_fw3x_enable_ptp, ++ .led_control = aq_fw2x_led_control, + }; +-- +2.13.6 + diff --git a/SOURCES/0044-netdrv-net-atlantic-add-fw-configuration-memory-area.patch b/SOURCES/0044-netdrv-net-atlantic-add-fw-configuration-memory-area.patch new file mode 100644 index 0000000..200ad8a --- /dev/null +++ b/SOURCES/0044-netdrv-net-atlantic-add-fw-configuration-memory-area.patch @@ -0,0 +1,351 @@ +From 3be54b42035cc3b59bf4dc5dbbc0b844308083d3 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:01 -0500 +Subject: [PATCH 044/139] [netdrv] net: atlantic: add fw configuration memory + area + +Message-id: <1604687916-15087-45-git-send-email-irusskik@redhat.com> +Patchwork-id: 338471 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 044/139] net: atlantic: add fw configuration memory area +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit dc12f75afcc677f225e5465b0654c54a14945168 +Author: Nikita Danilov +Date: Thu Nov 7 22:41:57 2019 +0000 + + net: atlantic: add fw configuration memory area + + Device FW has a separate memory area where various + config fields are stored and could be used by the + driver. + + Here we modify download/upload infrastructure to + allow accessing this area. + + Lateron this will be used to configure various behaviours + + Signed-off-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 1 + + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 129 +++++++++++++++------ + .../aquantia/atlantic/hw_atl/hw_atl_utils.h | 47 +++++++- + .../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 19 ++- + 4 files changed, 159 insertions(+), 37 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index ce4b8db03882..b2203f43e00a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -140,6 +140,7 @@ struct aq_hw_s { + atomic_t dpc; + u32 mbox_addr; + u32 rpc_addr; ++ u32 settings_addr; + u32 rpc_tid; + struct hw_atl_utils_fw_rpc rpc; + s64 ptp_clk_offset; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index fc82ede18b20..db8c09c5a768 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -47,6 +47,11 @@ + + #define FORCE_FLASHLESS 0 + ++enum mcp_area { ++ MCP_AREA_CONFIG = 0x80000000, ++ MCP_AREA_SETTINGS = 0x20000000, ++}; ++ + static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); + + static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, +@@ -327,10 +332,75 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, + return err; + } + +-int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt) ++static int hw_atl_utils_write_b1_mbox(struct aq_hw_s *self, u32 addr, ++ u32 *p, u32 cnt, enum mcp_area area) ++{ ++ u32 data_offset = 0; ++ u32 offset = addr; ++ int err = 0; ++ u32 val; ++ ++ switch (area) { ++ case MCP_AREA_CONFIG: ++ offset -= self->rpc_addr; ++ break; ++ ++ case MCP_AREA_SETTINGS: ++ offset -= self->settings_addr; ++ break; ++ } ++ ++ offset = offset / sizeof(u32); ++ ++ for (; data_offset < cnt; ++data_offset, ++offset) { ++ aq_hw_write_reg(self, 0x328, p[data_offset]); ++ aq_hw_write_reg(self, 0x32C, ++ (area | (0xFFFF & (offset * 4)))); ++ hw_atl_mcp_up_force_intr_set(self, 1); ++ /* 1000 times by 10us = 10ms */ ++ err = readx_poll_timeout_atomic(hw_atl_scrpad12_get, ++ self, val, ++ (val & 0xF0000000) != ++ area, ++ 10U, 10000U); ++ ++ if (err < 0) ++ break; ++ } ++ ++ return err; ++} ++ ++static int hw_atl_utils_write_b0_mbox(struct aq_hw_s *self, u32 addr, ++ u32 *p, u32 cnt) + { ++ u32 offset = 0; ++ int err = 0; + u32 val; ++ ++ aq_hw_write_reg(self, 0x208, addr); ++ ++ for (; offset < cnt; ++offset) { ++ aq_hw_write_reg(self, 0x20C, p[offset]); ++ aq_hw_write_reg(self, 0x200, 0xC000); ++ ++ err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get, ++ self, val, ++ (val & 0x100) == 0U, ++ 10U, 10000U); ++ ++ if (err < 0) ++ break; ++ } ++ ++ return err; ++} ++ ++static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 addr, u32 *p, ++ u32 cnt, enum mcp_area area) ++{ + int err = 0; ++ u32 val; + + err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, self, + val, val == 1U, +@@ -338,43 +408,35 @@ int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt) + if (err < 0) + goto err_exit; + +- if (IS_CHIP_FEATURE(REVISION_B1)) { +- u32 offset = 0; +- +- for (; offset < cnt; ++offset) { +- aq_hw_write_reg(self, 0x328, p[offset]); +- aq_hw_write_reg(self, 0x32C, +- (0x80000000 | (0xFFFF & (offset * 4)))); +- hw_atl_mcp_up_force_intr_set(self, 1); +- /* 1000 times by 10us = 10ms */ +- err = readx_poll_timeout_atomic(hw_atl_scrpad12_get, +- self, val, +- (val & 0xF0000000) != +- 0x80000000, +- 10U, 10000U); +- } +- } else { +- u32 offset = 0; +- +- aq_hw_write_reg(self, 0x208, a); ++ if (IS_CHIP_FEATURE(REVISION_B1)) ++ err = hw_atl_utils_write_b1_mbox(self, addr, p, cnt, area); ++ else ++ err = hw_atl_utils_write_b0_mbox(self, addr, p, cnt); + +- for (; offset < cnt; ++offset) { +- aq_hw_write_reg(self, 0x20C, p[offset]); +- aq_hw_write_reg(self, 0x200, 0xC000); ++ hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM); + +- err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get, +- self, val, +- (val & 0x100) == 0, +- 1000U, 10000U); +- } +- } ++ if (err < 0) ++ goto err_exit; + +- hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM); ++ err = aq_hw_err_from_flags(self); + + err_exit: + return err; + } + ++int hw_atl_write_fwcfg_dwords(struct aq_hw_s *self, u32 *p, u32 cnt) ++{ ++ return hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, p, ++ cnt, MCP_AREA_CONFIG); ++} ++ ++int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p, ++ u32 cnt) ++{ ++ return hw_atl_utils_fw_upload_dwords(self, self->settings_addr + offset, ++ p, cnt, MCP_AREA_SETTINGS); ++} ++ + static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual) + { + int err = 0; +@@ -437,10 +499,9 @@ int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size) + err = -1; + goto err_exit; + } +- err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, +- (u32 *)(void *)&self->rpc, +- (rpc_size + sizeof(u32) - +- sizeof(u8)) / sizeof(u32)); ++ err = hw_atl_write_fwcfg_dwords(self, (u32 *)(void *)&self->rpc, ++ (rpc_size + sizeof(u32) - ++ sizeof(u8)) / sizeof(u32)); + if (err < 0) + goto err_exit; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index c6708f0d5d3e..68fe17ec171d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -277,6 +277,48 @@ struct __packed hw_fw_request_iface { + }; + }; + ++struct __packed hw_atl_utils_settings { ++ u32 mtu; ++ u32 downshift_retry_count; ++ u32 link_pause_frame_quanta_100m; ++ u32 link_pause_frame_threshold_100m; ++ u32 link_pause_frame_quanta_1g; ++ u32 link_pause_frame_threshold_1g; ++ u32 link_pause_frame_quanta_2p5g; ++ u32 link_pause_frame_threshold_2p5g; ++ u32 link_pause_frame_quanta_5g; ++ u32 link_pause_frame_threshold_5g; ++ u32 link_pause_frame_quanta_10g; ++ u32 link_pause_frame_threshold_10g; ++ u32 pfc_quanta_class_0; ++ u32 pfc_threshold_class_0; ++ u32 pfc_quanta_class_1; ++ u32 pfc_threshold_class_1; ++ u32 pfc_quanta_class_2; ++ u32 pfc_threshold_class_2; ++ u32 pfc_quanta_class_3; ++ u32 pfc_threshold_class_3; ++ u32 pfc_quanta_class_4; ++ u32 pfc_threshold_class_4; ++ u32 pfc_quanta_class_5; ++ u32 pfc_threshold_class_5; ++ u32 pfc_quanta_class_6; ++ u32 pfc_threshold_class_6; ++ u32 pfc_quanta_class_7; ++ u32 pfc_threshold_class_7; ++ u32 eee_link_down_timeout; ++ u32 eee_link_up_timeout; ++ u32 eee_max_link_drops; ++ u32 eee_rates_mask; ++ u32 wake_timer; ++ u32 thermal_shutdown_off_temp; ++ u32 thermal_shutdown_warning_temp; ++ u32 thermal_shutdown_cold_temp; ++ u32 msm_options; ++ u32 dac_cable_serdes_modes; ++ u32 media_detect; ++}; ++ + enum hw_atl_rx_action_with_traffic { + HW_ATL_RX_DISCARD, + HW_ATL_RX_HOST, +@@ -554,7 +596,10 @@ struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self); + int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, + u32 *p, u32 cnt); + +-int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt); ++int hw_atl_write_fwcfg_dwords(struct aq_hw_s *self, u32 *p, u32 cnt); ++ ++int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p, ++ u32 cnt); + + int hw_atl_utils_fw_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index 4eab51b5b400..3dbce03c5a94 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -78,6 +78,7 @@ static int aq_fw2x_set_state(struct aq_hw_s *self, + + static u32 aq_fw2x_mbox_get(struct aq_hw_s *self); + static u32 aq_fw2x_rpc_get(struct aq_hw_s *self); ++static int aq_fw2x_settings_get(struct aq_hw_s *self, u32 *addr); + static u32 aq_fw2x_state2_get(struct aq_hw_s *self); + + static int aq_fw2x_init(struct aq_hw_s *self) +@@ -95,6 +96,8 @@ static int aq_fw2x_init(struct aq_hw_s *self) + self->rpc_addr != 0U, + 1000U, 100000U); + ++ err = aq_fw2x_settings_get(self, &self->settings_addr); ++ + return err; + } + +@@ -418,8 +421,7 @@ static int aq_fw2x_send_fw_request(struct aq_hw_s *self, + dword_cnt = size / sizeof(u32); + if (size % sizeof(u32)) + dword_cnt++; +- err = hw_atl_utils_fw_upload_dwords(self, aq_fw2x_rpc_get(self), +- (void *)fw_req, dword_cnt); ++ err = hw_atl_write_fwcfg_dwords(self, (void *)fw_req, dword_cnt); + if (err < 0) + goto err_exit; + +@@ -547,6 +549,19 @@ static u32 aq_fw2x_rpc_get(struct aq_hw_s *self) + return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR); + } + ++static int aq_fw2x_settings_get(struct aq_hw_s *self, u32 *addr) ++{ ++ int err = 0; ++ u32 offset; ++ ++ offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox, ++ info.setting_address); ++ ++ err = hw_atl_utils_fw_downld_dwords(self, offset, addr, 1); ++ ++ return err; ++} ++ + static u32 aq_fw2x_state2_get(struct aq_hw_s *self) + { + return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR); +-- +2.13.6 + diff --git a/SOURCES/0045-netdrv-net-atlantic-loopback-tests-via-private-flags.patch b/SOURCES/0045-netdrv-net-atlantic-loopback-tests-via-private-flags.patch new file mode 100644 index 0000000..c7e1d2b --- /dev/null +++ b/SOURCES/0045-netdrv-net-atlantic-loopback-tests-via-private-flags.patch @@ -0,0 +1,558 @@ +From 464e318856bdfae595c18f7ba50968174696a2dc Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:02 -0500 +Subject: [PATCH 045/139] [netdrv] net: atlantic: loopback tests via private + flags + +Message-id: <1604687916-15087-46-git-send-email-irusskik@redhat.com> +Patchwork-id: 338473 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 045/139] net: atlantic: loopback tests via private flags +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit ea4b4d7fc1065165874c27b8add252e04d104137 +Author: Igor Russkikh +Date: Thu Nov 7 22:41:58 2019 +0000 + + net: atlantic: loopback tests via private flags + + Here we add a number of ethtool private flags + to allow enabling various loopbacks on HW. + + Thats useful for verification and bringup works. + + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 55 +++++++++++++++++++++- + .../net/ethernet/aquantia/atlantic/aq_ethtool.h | 1 + + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 18 +++++++ + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 45 ++++++++++++++++++ + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 2 + + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 30 +++++++++++- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 26 ++++++++++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 11 +++++ + .../aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 54 +++++++++++++++++++++ + .../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 32 +++++++++++++ + 10 files changed, 272 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 2f877fb46615..963bf6e67573 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -92,6 +92,14 @@ static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = { + "Queue[%d] InErrors", + }; + ++static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = { ++ "DMASystemLoopback", ++ "PKTSystemLoopback", ++ "DMANetworkLoopback", ++ "PHYInternalLoopback", ++ "PHYExternalLoopback", ++}; ++ + static void aq_ethtool_stats(struct net_device *ndev, + struct ethtool_stats *stats, u64 *data) + { +@@ -137,7 +145,8 @@ static void aq_ethtool_get_strings(struct net_device *ndev, + struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); + u8 *p = data; + +- if (stringset == ETH_SS_STATS) { ++ switch (stringset) { ++ case ETH_SS_STATS: + memcpy(p, aq_ethtool_stat_names, + sizeof(aq_ethtool_stat_names)); + p = p + sizeof(aq_ethtool_stat_names); +@@ -150,6 +159,11 @@ static void aq_ethtool_get_strings(struct net_device *ndev, + p += ETH_GSTRING_LEN; + } + } ++ break; ++ case ETH_SS_PRIV_FLAGS: ++ memcpy(p, aq_ethtool_priv_flag_names, ++ sizeof(aq_ethtool_priv_flag_names)); ++ break; + } + } + +@@ -193,6 +207,9 @@ static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset) + ret = ARRAY_SIZE(aq_ethtool_stat_names) + + cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names); + break; ++ case ETH_SS_PRIV_FLAGS: ++ ret = ARRAY_SIZE(aq_ethtool_priv_flag_names); ++ break; + default: + ret = -EOPNOTSUPP; + } +@@ -650,6 +667,40 @@ static void aq_set_msg_level(struct net_device *ndev, u32 data) + aq_nic->msg_enable = data; + } + ++u32 aq_ethtool_get_priv_flags(struct net_device *ndev) ++{ ++ struct aq_nic_s *aq_nic = netdev_priv(ndev); ++ ++ return aq_nic->aq_nic_cfg.priv_flags; ++} ++ ++int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags) ++{ ++ struct aq_nic_s *aq_nic = netdev_priv(ndev); ++ struct aq_nic_cfg_s *cfg; ++ u32 priv_flags; ++ ++ cfg = aq_nic_get_cfg(aq_nic); ++ priv_flags = cfg->priv_flags; ++ ++ if (flags & ~AQ_PRIV_FLAGS_MASK) ++ return -EOPNOTSUPP; ++ ++ cfg->priv_flags = flags; ++ ++ if ((priv_flags ^ flags) & BIT(AQ_HW_LOOPBACK_DMA_NET)) { ++ if (netif_running(ndev)) { ++ dev_close(ndev); ++ ++ dev_open(ndev, NULL); ++ } ++ } else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) { ++ aq_nic_set_loopback(aq_nic); ++ } ++ ++ return 0; ++} ++ + const struct ethtool_ops aq_ethtool_ops = { + .get_link = aq_ethtool_get_link, + .get_regs_len = aq_ethtool_get_regs_len, +@@ -676,6 +727,8 @@ const struct ethtool_ops aq_ethtool_ops = { + .set_msglevel = aq_set_msg_level, + .get_sset_count = aq_ethtool_get_sset_count, + .get_ethtool_stats = aq_ethtool_stats, ++ .get_priv_flags = aq_ethtool_get_priv_flags, ++ .set_priv_flags = aq_ethtool_set_priv_flags, + .get_link_ksettings = aq_ethtool_get_link_ksettings, + .set_link_ksettings = aq_ethtool_set_link_ksettings, + .get_coalesce = aq_ethtool_get_coalesce, +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h +index 632b5531db4a..6d5be5ebeb13 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h +@@ -12,5 +12,6 @@ + #include "aq_common.h" + + extern const struct ethtool_ops aq_ethtool_ops; ++#define AQ_PRIV_FLAGS_MASK (AQ_HW_LOOPBACK_MASK) + + #endif /* AQ_ETHTOOL_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index b2203f43e00a..e9cf5913b70a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -122,6 +122,20 @@ struct aq_stats_s { + #define AQ_HW_LED_BLINK 0x2U + #define AQ_HW_LED_DEFAULT 0x0U + ++enum aq_priv_flags { ++ AQ_HW_LOOPBACK_DMA_SYS, ++ AQ_HW_LOOPBACK_PKT_SYS, ++ AQ_HW_LOOPBACK_DMA_NET, ++ AQ_HW_LOOPBACK_PHYINT_SYS, ++ AQ_HW_LOOPBACK_PHYEXT_SYS, ++}; ++ ++#define AQ_HW_LOOPBACK_MASK (BIT(AQ_HW_LOOPBACK_DMA_SYS) |\ ++ BIT(AQ_HW_LOOPBACK_PKT_SYS) |\ ++ BIT(AQ_HW_LOOPBACK_DMA_NET) |\ ++ BIT(AQ_HW_LOOPBACK_PHYINT_SYS) |\ ++ BIT(AQ_HW_LOOPBACK_PHYEXT_SYS)) ++ + struct aq_hw_s { + atomic_t flags; + u8 rbl_enabled:1; +@@ -280,6 +294,8 @@ struct aq_hw_ops { + u64 *timestamp); + + int (*hw_set_fc)(struct aq_hw_s *self, u32 fc, u32 tc); ++ ++ int (*hw_set_loopback)(struct aq_hw_s *self, u32 mode, bool enable); + }; + + struct aq_fw_ops { +@@ -310,6 +326,8 @@ struct aq_fw_ops { + + int (*led_control)(struct aq_hw_s *self, u32 mode); + ++ int (*set_phyloopback)(struct aq_hw_s *self, u32 mode, bool enable); ++ + int (*set_power)(struct aq_hw_s *self, unsigned int power_state, + u8 *mac); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 8f83e91f8146..5462b7efcf2f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -406,6 +406,8 @@ int aq_nic_start(struct aq_nic_s *self) + + INIT_WORK(&self->service_task, aq_nic_service_task); + ++ aq_nic_set_loopback(self); ++ + timer_setup(&self->service_timer, aq_nic_service_timer_cb, 0); + aq_nic_service_timer_cb(&self->service_timer); + +@@ -625,6 +627,11 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) + + aq_ring_update_queue_state(ring); + ++ if (self->aq_nic_cfg.priv_flags & BIT(AQ_HW_LOOPBACK_DMA_NET)) { ++ err = NETDEV_TX_BUSY; ++ goto err_exit; ++ } ++ + /* Above status update may stop the queue. Check this. */ + if (__netif_subqueue_stopped(self->ndev, ring->idx)) { + err = NETDEV_TX_BUSY; +@@ -973,6 +980,44 @@ u32 aq_nic_get_fw_version(struct aq_nic_s *self) + return fw_version; + } + ++int aq_nic_set_loopback(struct aq_nic_s *self) ++{ ++ struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; ++ ++ if (!self->aq_hw_ops->hw_set_loopback || ++ !self->aq_fw_ops->set_phyloopback) ++ return -ENOTSUPP; ++ ++ mutex_lock(&self->fwreq_mutex); ++ self->aq_hw_ops->hw_set_loopback(self->aq_hw, ++ AQ_HW_LOOPBACK_DMA_SYS, ++ !!(cfg->priv_flags & ++ BIT(AQ_HW_LOOPBACK_DMA_SYS))); ++ ++ self->aq_hw_ops->hw_set_loopback(self->aq_hw, ++ AQ_HW_LOOPBACK_PKT_SYS, ++ !!(cfg->priv_flags & ++ BIT(AQ_HW_LOOPBACK_PKT_SYS))); ++ ++ self->aq_hw_ops->hw_set_loopback(self->aq_hw, ++ AQ_HW_LOOPBACK_DMA_NET, ++ !!(cfg->priv_flags & ++ BIT(AQ_HW_LOOPBACK_DMA_NET))); ++ ++ self->aq_fw_ops->set_phyloopback(self->aq_hw, ++ AQ_HW_LOOPBACK_PHYINT_SYS, ++ !!(cfg->priv_flags & ++ BIT(AQ_HW_LOOPBACK_PHYINT_SYS))); ++ ++ self->aq_fw_ops->set_phyloopback(self->aq_hw, ++ AQ_HW_LOOPBACK_PHYEXT_SYS, ++ !!(cfg->priv_flags & ++ BIT(AQ_HW_LOOPBACK_PHYEXT_SYS))); ++ mutex_unlock(&self->fwreq_mutex); ++ ++ return 0; ++} ++ + int aq_nic_stop(struct aq_nic_s *self) + { + struct aq_vec_s *aq_vec = NULL; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index 527273502d54..bb4957a31498 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -46,6 +46,7 @@ struct aq_nic_cfg_s { + bool is_polling; + bool is_rss; + bool is_lro; ++ u32 priv_flags; + u8 tcs; + struct aq_rss_parameters aq_rss; + u32 eee_speeds; +@@ -158,6 +159,7 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self, + const struct ethtool_link_ksettings *cmd); + struct aq_nic_cfg_s *aq_nic_get_cfg(struct aq_nic_s *self); + u32 aq_nic_get_fw_version(struct aq_nic_s *self); ++int aq_nic_set_loopback(struct aq_nic_s *self); + int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self); + void aq_nic_shutdown(struct aq_nic_s *self); + u8 aq_nic_reserve_filter(struct aq_nic_s *self, enum aq_rx_filter_type type); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index c7297ca03624..1165689af37d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1427,6 +1427,30 @@ static int hw_atl_b0_hw_vlan_ctrl(struct aq_hw_s *self, bool enable) + return aq_hw_err_from_flags(self); + } + ++static int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable) ++{ ++ switch (mode) { ++ case AQ_HW_LOOPBACK_DMA_SYS: ++ hw_atl_tpb_tx_dma_sys_lbk_en_set(self, enable); ++ hw_atl_rpb_dma_sys_lbk_set(self, enable); ++ break; ++ case AQ_HW_LOOPBACK_PKT_SYS: ++ hw_atl_tpo_tx_pkt_sys_lbk_en_set(self, enable); ++ hw_atl_rpf_tpo_to_rpf_sys_lbk_set(self, enable); ++ break; ++ case AQ_HW_LOOPBACK_DMA_NET: ++ hw_atl_rpf_vlan_prom_mode_en_set(self, enable); ++ hw_atl_rpfl2promiscuous_mode_en_set(self, enable); ++ hw_atl_tpb_tx_tx_clk_gate_en_set(self, !enable); ++ hw_atl_tpb_tx_dma_net_lbk_en_set(self, enable); ++ hw_atl_rpb_dma_net_lbk_set(self, enable); ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ + const struct aq_hw_ops hw_atl_ops_b0 = { + .hw_set_mac_address = hw_atl_b0_hw_mac_addr_set, + .hw_init = hw_atl_b0_hw_init, +@@ -1481,5 +1505,9 @@ const struct aq_hw_ops hw_atl_ops_b0 = { + .rx_extract_ts = hw_atl_b0_rx_extract_ts, + .extract_hwts = hw_atl_b0_extract_hwts, + .hw_set_offload = hw_atl_b0_hw_offload_set, +- .hw_set_fc = hw_atl_b0_set_fc, ++ .hw_get_hw_stats = hw_atl_utils_get_hw_stats, ++ .hw_get_fw_version = hw_atl_utils_get_fw_version, ++ .hw_set_offload = hw_atl_b0_hw_offload_set, ++ .hw_set_loopback = hw_atl_b0_set_loopback, ++ .hw_set_fc = hw_atl_b0_set_fc, + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index 6cadc9054544..d1f68fc16291 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -563,6 +563,13 @@ void hw_atl_rpb_dma_sys_lbk_set(struct aq_hw_s *aq_hw, u32 dma_sys_lbk) + HW_ATL_RPB_DMA_SYS_LBK_SHIFT, dma_sys_lbk); + } + ++void hw_atl_rpb_dma_net_lbk_set(struct aq_hw_s *aq_hw, u32 dma_net_lbk) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL_RPB_DMA_NET_LBK_ADR, ++ HW_ATL_RPB_DMA_NET_LBK_MSK, ++ HW_ATL_RPB_DMA_NET_LBK_SHIFT, dma_net_lbk); ++} ++ + void hw_atl_rpb_rpf_rx_traf_class_mode_set(struct aq_hw_s *aq_hw, + u32 rx_traf_class_mode) + { +@@ -1341,7 +1348,26 @@ void hw_atl_tpb_tx_dma_sys_lbk_en_set(struct aq_hw_s *aq_hw, u32 tx_dma_sys_lbk_ + tx_dma_sys_lbk_en); + } + ++void hw_atl_tpb_tx_dma_net_lbk_en_set(struct aq_hw_s *aq_hw, ++ u32 tx_dma_net_lbk_en) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL_TPB_DMA_NET_LBK_ADR, ++ HW_ATL_TPB_DMA_NET_LBK_MSK, ++ HW_ATL_TPB_DMA_NET_LBK_SHIFT, ++ tx_dma_net_lbk_en); ++} ++ ++void hw_atl_tpb_tx_tx_clk_gate_en_set(struct aq_hw_s *aq_hw, ++ u32 tx_clk_gate_en) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL_TPB_TX_CLK_GATE_EN_ADR, ++ HW_ATL_TPB_TX_CLK_GATE_EN_MSK, ++ HW_ATL_TPB_TX_CLK_GATE_EN_SHIFT, ++ tx_clk_gate_en); ++} ++ + void hw_atl_tpb_tx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, ++ + u32 tx_pkt_buff_size_per_tc, u32 buffer) + { + aq_hw_write_reg_bit(aq_hw, HW_ATL_TPB_TXBBUF_SIZE_ADR(buffer), +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index 5750b0c9cae7..62992b23c0e8 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -288,6 +288,9 @@ void hw_atl_reg_glb_cpu_scratch_scp_set(struct aq_hw_s *aq_hw, + /* set dma system loopback */ + void hw_atl_rpb_dma_sys_lbk_set(struct aq_hw_s *aq_hw, u32 dma_sys_lbk); + ++/* set dma network loopback */ ++void hw_atl_rpb_dma_net_lbk_set(struct aq_hw_s *aq_hw, u32 dma_net_lbk); ++ + /* set rx traffic class mode */ + void hw_atl_rpb_rpf_rx_traf_class_mode_set(struct aq_hw_s *aq_hw, + u32 rx_traf_class_mode); +@@ -629,6 +632,14 @@ void hw_atl_tpb_tx_buff_lo_threshold_per_tc_set(struct aq_hw_s *aq_hw, + /* set tx dma system loopback enable */ + void hw_atl_tpb_tx_dma_sys_lbk_en_set(struct aq_hw_s *aq_hw, u32 tx_dma_sys_lbk_en); + ++/* set tx dma network loopback enable */ ++void hw_atl_tpb_tx_dma_net_lbk_en_set(struct aq_hw_s *aq_hw, ++ u32 tx_dma_net_lbk_en); ++ ++/* set tx clock gating enable */ ++void hw_atl_tpb_tx_tx_clk_gate_en_set(struct aq_hw_s *aq_hw, ++ u32 tx_clk_gate_en); ++ + /* set tx packet buffer size (per tc) */ + void hw_atl_tpb_tx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, + u32 tx_pkt_buff_size_per_tc, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +index ec3bcdcefc4d..18de2f7b8959 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +@@ -554,6 +554,24 @@ + /* default value of bitfield dma_sys_loopback */ + #define HW_ATL_RPB_DMA_SYS_LBK_DEFAULT 0x0 + ++/* rx dma_net_loopback bitfield definitions ++ * preprocessor definitions for the bitfield "dma_net_loopback". ++ * port="pif_rpb_dma_net_lbk_i" ++ */ ++ ++/* register address for bitfield dma_net_loopback */ ++#define HW_ATL_RPB_DMA_NET_LBK_ADR 0x00005000 ++/* bitmask for bitfield dma_net_loopback */ ++#define HW_ATL_RPB_DMA_NET_LBK_MSK 0x00000010 ++/* inverted bitmask for bitfield dma_net_loopback */ ++#define HW_ATL_RPB_DMA_NET_LBK_MSKN 0xffffffef ++/* lower bit position of bitfield dma_net_loopback */ ++#define HW_ATL_RPB_DMA_NET_LBK_SHIFT 4 ++/* width of bitfield dma_net_loopback */ ++#define HW_ATL_RPB_DMA_NET_LBK_WIDTH 1 ++/* default value of bitfield dma_net_loopback */ ++#define HW_ATL_RPB_DMA_NET_LBK_DEFAULT 0x0 ++ + /* rx rx_tc_mode bitfield definitions + * preprocessor definitions for the bitfield "rx_tc_mode". + * port="pif_rpb_rx_tc_mode_i,pif_rpf_rx_tc_mode_i" +@@ -2107,6 +2125,24 @@ + /* default value of bitfield dma_sys_loopback */ + #define HW_ATL_TPB_DMA_SYS_LBK_DEFAULT 0x0 + ++/* tx dma_net_loopback bitfield definitions ++ * preprocessor definitions for the bitfield "dma_net_loopback". ++ * port="pif_tpb_dma_net_lbk_i" ++ */ ++ ++/* register address for bitfield dma_net_loopback */ ++#define HW_ATL_TPB_DMA_NET_LBK_ADR 0x00007000 ++/* bitmask for bitfield dma_net_loopback */ ++#define HW_ATL_TPB_DMA_NET_LBK_MSK 0x00000010 ++/* inverted bitmask for bitfield dma_net_loopback */ ++#define HW_ATL_TPB_DMA_NET_LBK_MSKN 0xffffffef ++/* lower bit position of bitfield dma_net_loopback */ ++#define HW_ATL_TPB_DMA_NET_LBK_SHIFT 4 ++/* width of bitfield dma_net_loopback */ ++#define HW_ATL_TPB_DMA_NET_LBK_WIDTH 1 ++/* default value of bitfield dma_net_loopback */ ++#define HW_ATL_TPB_DMA_NET_LBK_DEFAULT 0x0 ++ + /* tx tx{b}_buf_size[7:0] bitfield definitions + * preprocessor definitions for the bitfield "tx{b}_buf_size[7:0]". + * parameter: buffer {b} | stride size 0x10 | range [0, 7] +@@ -2144,6 +2180,24 @@ + /* default value of bitfield tx_scp_ins_en */ + #define HW_ATL_TPB_TX_SCP_INS_EN_DEFAULT 0x0 + ++/* tx tx_clk_gate_en bitfield definitions ++ * preprocessor definitions for the bitfield "tx_clk_gate_en". ++ * port="pif_tpb_clk_gate_en_i" ++ */ ++ ++/* register address for bitfield tx_clk_gate_en */ ++#define HW_ATL_TPB_TX_CLK_GATE_EN_ADR 0x00007900 ++/* bitmask for bitfield tx_clk_gate_en */ ++#define HW_ATL_TPB_TX_CLK_GATE_EN_MSK 0x00000010 ++/* inverted bitmask for bitfield tx_clk_gate_en */ ++#define HW_ATL_TPB_TX_CLK_GATE_EN_MSKN 0xffffffef ++/* lower bit position of bitfield tx_clk_gate_en */ ++#define HW_ATL_TPB_TX_CLK_GATE_EN_SHIFT 4 ++/* width of bitfield tx_clk_gate_en */ ++#define HW_ATL_TPB_TX_CLK_GATE_EN_WIDTH 1 ++/* default value of bitfield tx_clk_gate_en */ ++#define HW_ATL_TPB_TX_CLK_GATE_EN_DEFAULT 0x1 ++ + /* tx ipv4_chk_en bitfield definitions + * preprocessor definitions for the bitfield "ipv4_chk_en". + * port="pif_tpo_ipv4_chk_en_i" +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index 3dbce03c5a94..feef2b0177b2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -42,6 +42,9 @@ + #define HW_ATL_FW2X_CTRL_PAUSE BIT(CTRL_PAUSE) + #define HW_ATL_FW2X_CTRL_TEMPERATURE BIT(CTRL_TEMPERATURE) + #define HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE BIT(CTRL_ASYMMETRIC_PAUSE) ++#define HW_ATL_FW2X_CTRL_INT_LOOPBACK BIT(CTRL_INT_LOOPBACK) ++#define HW_ATL_FW2X_CTRL_EXT_LOOPBACK BIT(CTRL_EXT_LOOPBACK) ++#define HW_ATL_FW2X_CTRL_DOWNSHIFT BIT(CTRL_DOWNSHIFT) + #define HW_ATL_FW2X_CTRL_FORCE_RECONNECT BIT(CTRL_FORCE_RECONNECT) + + #define HW_ATL_FW2X_CAP_EEE_1G_MASK BIT(CAPS_HI_1000BASET_FD_EEE) +@@ -53,6 +56,7 @@ + #define HAL_ATLANTIC_UTILS_FW2X_MSG_WOL 0x0E + + #define HW_ATL_FW_VER_LED 0x03010026U ++#define HW_ATL_FW_VER_MEDIA_CONTROL 0x0301005aU + + struct __packed fw2x_msg_wol_pattern { + u8 mask[16]; +@@ -539,6 +543,33 @@ static u32 aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fcmode) + return 0; + } + ++static int aq_fw2x_set_phyloopback(struct aq_hw_s *self, u32 mode, bool enable) ++{ ++ u32 mpi_opts; ++ ++ switch (mode) { ++ case AQ_HW_LOOPBACK_PHYINT_SYS: ++ mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); ++ if (enable) ++ mpi_opts |= HW_ATL_FW2X_CTRL_INT_LOOPBACK; ++ else ++ mpi_opts &= ~HW_ATL_FW2X_CTRL_INT_LOOPBACK; ++ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); ++ break; ++ case AQ_HW_LOOPBACK_PHYEXT_SYS: ++ mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); ++ if (enable) ++ mpi_opts |= HW_ATL_FW2X_CTRL_EXT_LOOPBACK; ++ else ++ mpi_opts &= ~HW_ATL_FW2X_CTRL_EXT_LOOPBACK; ++ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ + static u32 aq_fw2x_mbox_get(struct aq_hw_s *self) + { + return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR); +@@ -586,4 +617,5 @@ const struct aq_fw_ops aq_fw_2x_ops = { + .send_fw_request = aq_fw2x_send_fw_request, + .enable_ptp = aq_fw3x_enable_ptp, + .led_control = aq_fw2x_led_control, ++ .set_phyloopback = aq_fw2x_set_phyloopback, + }; +-- +2.13.6 + diff --git a/SOURCES/0046-netdrv-net-atlantic-code-style-cleanup.patch b/SOURCES/0046-netdrv-net-atlantic-code-style-cleanup.patch new file mode 100644 index 0000000..5111e2d --- /dev/null +++ b/SOURCES/0046-netdrv-net-atlantic-code-style-cleanup.patch @@ -0,0 +1,1421 @@ +From 72e3b733c6ef53749387a3efc94569619e3d3bb0 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:03 -0500 +Subject: [PATCH 046/139] [netdrv] net: atlantic: code style cleanup + +Message-id: <1604687916-15087-47-git-send-email-irusskik@redhat.com> +Patchwork-id: 338474 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 046/139] net: atlantic: code style cleanup +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 7b0c342f1f67543f1f16099238d279584d6834e0 +Author: Nikita Danilov +Date: Thu Nov 7 22:42:00 2019 +0000 + + net: atlantic: code style cleanup + + Thats a pure checkpatck walkthrough the code with no functional + changes. Reverse christmas tree, spacing, etc. + + Signed-off-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 108 ++++++++++++++------- + .../net/ethernet/aquantia/atlantic/aq_hw_utils.c | 1 + + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 11 ++- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 39 +++++--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 4 +- + .../net/ethernet/aquantia/atlantic/aq_pci_func.c | 8 +- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 6 +- + drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 8 +- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 39 +++++--- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 69 ++++++++----- + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 52 ++++++---- + .../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 34 ++++--- + 12 files changed, 240 insertions(+), 139 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 963bf6e67573..8286c77d43a5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -18,7 +18,9 @@ static void aq_ethtool_get_regs(struct net_device *ndev, + struct ethtool_regs *regs, void *p) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- u32 regs_count = aq_nic_get_regs_count(aq_nic); ++ u32 regs_count; ++ ++ regs_count = aq_nic_get_regs_count(aq_nic); + + memset(p, 0, regs_count * sizeof(u32)); + aq_nic_get_regs(aq_nic, regs, p); +@@ -27,7 +29,9 @@ static void aq_ethtool_get_regs(struct net_device *ndev, + static int aq_ethtool_get_regs_len(struct net_device *ndev) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- u32 regs_count = aq_nic_get_regs_count(aq_nic); ++ u32 regs_count; ++ ++ regs_count = aq_nic_get_regs_count(aq_nic); + + return regs_count * sizeof(u32); + } +@@ -104,7 +108,9 @@ static void aq_ethtool_stats(struct net_device *ndev, + struct ethtool_stats *stats, u64 *data) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); ++ struct aq_nic_cfg_s *cfg; ++ ++ cfg = aq_nic_get_cfg(aq_nic); + + memset(data, 0, (ARRAY_SIZE(aq_ethtool_stat_names) + + ARRAY_SIZE(aq_ethtool_queue_stat_names) * +@@ -115,11 +121,15 @@ static void aq_ethtool_stats(struct net_device *ndev, + static void aq_ethtool_get_drvinfo(struct net_device *ndev, + struct ethtool_drvinfo *drvinfo) + { +- struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); + struct pci_dev *pdev = to_pci_dev(ndev->dev.parent); +- u32 firmware_version = aq_nic_get_fw_version(aq_nic); +- u32 regs_count = aq_nic_get_regs_count(aq_nic); ++ struct aq_nic_s *aq_nic = netdev_priv(ndev); ++ struct aq_nic_cfg_s *cfg; ++ u32 firmware_version; ++ u32 regs_count; ++ ++ cfg = aq_nic_get_cfg(aq_nic); ++ firmware_version = aq_nic_get_fw_version(aq_nic); ++ regs_count = aq_nic_get_regs_count(aq_nic); + + strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver)); + strlcat(drvinfo->version, AQ_CFG_DRV_VERSION, sizeof(drvinfo->version)); +@@ -140,10 +150,12 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev, + static void aq_ethtool_get_strings(struct net_device *ndev, + u32 stringset, u8 *data) + { +- int i, si; + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); ++ struct aq_nic_cfg_s *cfg; + u8 *p = data; ++ int i, si; ++ ++ cfg = aq_nic_get_cfg(aq_nic); + + switch (stringset) { + case ETH_SS_STATS: +@@ -198,9 +210,11 @@ static int aq_ethtool_set_phys_id(struct net_device *ndev, + + static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset) + { +- int ret = 0; + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); ++ struct aq_nic_cfg_s *cfg; ++ int ret = 0; ++ ++ cfg = aq_nic_get_cfg(aq_nic); + + switch (stringset) { + case ETH_SS_STATS: +@@ -213,6 +227,7 @@ static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset) + default: + ret = -EOPNOTSUPP; + } ++ + return ret; + } + +@@ -224,7 +239,9 @@ static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev) + static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); ++ struct aq_nic_cfg_s *cfg; ++ ++ cfg = aq_nic_get_cfg(aq_nic); + + return sizeof(cfg->aq_rss.hash_secret_key); + } +@@ -233,9 +250,11 @@ static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key, + u8 *hfunc) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); ++ struct aq_nic_cfg_s *cfg; + unsigned int i = 0U; + ++ cfg = aq_nic_get_cfg(aq_nic); ++ + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */ + if (indir) { +@@ -245,6 +264,7 @@ static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key, + if (key) + memcpy(key, cfg->aq_rss.hash_secret_key, + sizeof(cfg->aq_rss.hash_secret_key)); ++ + return 0; + } + +@@ -288,9 +308,11 @@ static int aq_ethtool_get_rxnfc(struct net_device *ndev, + u32 *rule_locs) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); ++ struct aq_nic_cfg_s *cfg; + int err = 0; + ++ cfg = aq_nic_get_cfg(aq_nic); ++ + switch (cmd->cmd) { + case ETHTOOL_GRXRINGS: + cmd->data = cfg->vecs; +@@ -315,8 +337,8 @@ static int aq_ethtool_get_rxnfc(struct net_device *ndev, + static int aq_ethtool_set_rxnfc(struct net_device *ndev, + struct ethtool_rxnfc *cmd) + { +- int err = 0; + struct aq_nic_s *aq_nic = netdev_priv(ndev); ++ int err = 0; + + switch (cmd->cmd) { + case ETHTOOL_SRXCLSRLINS: +@@ -337,7 +359,9 @@ static int aq_ethtool_get_coalesce(struct net_device *ndev, + struct ethtool_coalesce *coal) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); ++ struct aq_nic_cfg_s *cfg; ++ ++ cfg = aq_nic_get_cfg(aq_nic); + + if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON || + cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) { +@@ -351,6 +375,7 @@ static int aq_ethtool_get_coalesce(struct net_device *ndev, + coal->rx_max_coalesced_frames = 1; + coal->tx_max_coalesced_frames = 1; + } ++ + return 0; + } + +@@ -358,7 +383,9 @@ static int aq_ethtool_set_coalesce(struct net_device *ndev, + struct ethtool_coalesce *coal) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); ++ struct aq_nic_cfg_s *cfg; ++ ++ cfg = aq_nic_get_cfg(aq_nic); + + /* This is not yet supported + */ +@@ -400,7 +427,9 @@ static void aq_ethtool_get_wol(struct net_device *ndev, + struct ethtool_wolinfo *wol) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); ++ struct aq_nic_cfg_s *cfg; ++ ++ cfg = aq_nic_get_cfg(aq_nic); + + wol->supported = AQ_NIC_WOL_MODES; + wol->wolopts = cfg->wol; +@@ -411,9 +440,11 @@ static int aq_ethtool_set_wol(struct net_device *ndev, + { + struct pci_dev *pdev = to_pci_dev(ndev->dev.parent); + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); ++ struct aq_nic_cfg_s *cfg; + int err = 0; + ++ cfg = aq_nic_get_cfg(aq_nic); ++ + if (wol->wolopts & ~AQ_NIC_WOL_MODES) + return -EOPNOTSUPP; + +@@ -599,23 +630,28 @@ static void aq_get_ringparam(struct net_device *ndev, + struct ethtool_ringparam *ring) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic); ++ struct aq_nic_cfg_s *cfg; ++ ++ cfg = aq_nic_get_cfg(aq_nic); + +- ring->rx_pending = aq_nic_cfg->rxds; +- ring->tx_pending = aq_nic_cfg->txds; ++ ring->rx_pending = cfg->rxds; ++ ring->tx_pending = cfg->txds; + +- ring->rx_max_pending = aq_nic_cfg->aq_hw_caps->rxds_max; +- ring->tx_max_pending = aq_nic_cfg->aq_hw_caps->txds_max; ++ ring->rx_max_pending = cfg->aq_hw_caps->rxds_max; ++ ring->tx_max_pending = cfg->aq_hw_caps->txds_max; + } + + static int aq_set_ringparam(struct net_device *ndev, + struct ethtool_ringparam *ring) + { +- int err = 0; +- bool ndev_running = false; + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic); +- const struct aq_hw_caps_s *hw_caps = aq_nic_cfg->aq_hw_caps; ++ const struct aq_hw_caps_s *hw_caps; ++ bool ndev_running = false; ++ struct aq_nic_cfg_s *cfg; ++ int err = 0; ++ ++ cfg = aq_nic_get_cfg(aq_nic); ++ hw_caps = cfg->aq_hw_caps; + + if (ring->rx_mini_pending || ring->rx_jumbo_pending) { + err = -EOPNOTSUPP; +@@ -629,18 +665,18 @@ static int aq_set_ringparam(struct net_device *ndev, + + aq_nic_free_vectors(aq_nic); + +- aq_nic_cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min); +- aq_nic_cfg->rxds = min(aq_nic_cfg->rxds, hw_caps->rxds_max); +- aq_nic_cfg->rxds = ALIGN(aq_nic_cfg->rxds, AQ_HW_RXD_MULTIPLE); ++ cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min); ++ cfg->rxds = min(cfg->rxds, hw_caps->rxds_max); ++ cfg->rxds = ALIGN(cfg->rxds, AQ_HW_RXD_MULTIPLE); + +- aq_nic_cfg->txds = max(ring->tx_pending, hw_caps->txds_min); +- aq_nic_cfg->txds = min(aq_nic_cfg->txds, hw_caps->txds_max); +- aq_nic_cfg->txds = ALIGN(aq_nic_cfg->txds, AQ_HW_TXD_MULTIPLE); ++ cfg->txds = max(ring->tx_pending, hw_caps->txds_min); ++ cfg->txds = min(cfg->txds, hw_caps->txds_max); ++ cfg->txds = ALIGN(cfg->txds, AQ_HW_TXD_MULTIPLE); + +- for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < aq_nic_cfg->vecs; ++ for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < cfg->vecs; + aq_nic->aq_vecs++) { + aq_nic->aq_vec[aq_nic->aq_vecs] = +- aq_vec_alloc(aq_nic, aq_nic->aq_vecs, aq_nic_cfg); ++ aq_vec_alloc(aq_nic, aq_nic->aq_vecs, cfg); + if (unlikely(!aq_nic->aq_vec[aq_nic->aq_vecs])) { + err = -ENOMEM; + goto err_exit; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +index 9c7a226d81b6..7dbf49adcea6 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +@@ -59,6 +59,7 @@ u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg) + u64 value = aq_hw_read_reg(hw, reg); + + value |= (u64)aq_hw_read_reg(hw, reg + 4) << 32; ++ + return value; + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index 2c1096561614..538f460a3da7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -53,8 +53,8 @@ struct net_device *aq_ndev_alloc(void) + + static int aq_ndev_open(struct net_device *ndev) + { +- int err = 0; + struct aq_nic_s *aq_nic = netdev_priv(ndev); ++ int err = 0; + + err = aq_nic_init(aq_nic); + if (err < 0) +@@ -75,13 +75,14 @@ static int aq_ndev_open(struct net_device *ndev) + err_exit: + if (err < 0) + aq_nic_deinit(aq_nic, true); ++ + return err; + } + + static int aq_ndev_close(struct net_device *ndev) + { +- int err = 0; + struct aq_nic_s *aq_nic = netdev_priv(ndev); ++ int err = 0; + + err = aq_nic_stop(aq_nic); + if (err < 0) +@@ -120,7 +121,9 @@ static int aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev) + static int aq_ndev_change_mtu(struct net_device *ndev, int new_mtu) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- int err = aq_nic_set_mtu(aq_nic, new_mtu + ETH_HLEN); ++ int err; ++ ++ err = aq_nic_set_mtu(aq_nic, new_mtu + ETH_HLEN); + + if (err < 0) + goto err_exit; +@@ -133,8 +136,8 @@ static int aq_ndev_change_mtu(struct net_device *ndev, int new_mtu) + static int aq_ndev_set_features(struct net_device *ndev, + netdev_features_t features) + { +- bool is_vlan_rx_strip = !!(features & NETIF_F_HW_VLAN_CTAG_RX); + bool is_vlan_tx_insert = !!(features & NETIF_F_HW_VLAN_CTAG_TX); ++ bool is_vlan_rx_strip = !!(features & NETIF_F_HW_VLAN_CTAG_RX); + struct aq_nic_s *aq_nic = netdev_priv(ndev); + bool need_ndev_restart = false; + struct aq_nic_cfg_s *aq_cfg; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 5462b7efcf2f..d3739f21b18e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -41,10 +41,6 @@ static void aq_nic_update_ndev_stats(struct aq_nic_s *self); + + static void aq_nic_rss_init(struct aq_nic_s *self, unsigned int num_rss_queues) + { +- struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; +- struct aq_rss_parameters *rss_params = &cfg->aq_rss; +- int i = 0; +- + static u8 rss_key[AQ_CFG_RSS_HASHKEY_SIZE] = { + 0x1e, 0xad, 0x71, 0x87, 0x65, 0xfc, 0x26, 0x7d, + 0x0d, 0x45, 0x67, 0x74, 0xcd, 0x06, 0x1a, 0x18, +@@ -52,6 +48,11 @@ static void aq_nic_rss_init(struct aq_nic_s *self, unsigned int num_rss_queues) + 0x19, 0x13, 0x4b, 0xa9, 0xd0, 0x3e, 0xfe, 0x70, + 0x25, 0x03, 0xab, 0x50, 0x6a, 0x8b, 0x82, 0x0c + }; ++ struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; ++ struct aq_rss_parameters *rss_params; ++ int i = 0; ++ ++ rss_params = &cfg->aq_rss; + + rss_params->hash_secret_key_size = sizeof(rss_key); + memcpy(rss_params->hash_secret_key, rss_key, sizeof(rss_key)); +@@ -180,6 +181,7 @@ static int aq_nic_update_link_status(struct aq_nic_s *self) + netif_tx_disable(self->ndev); + aq_utils_obj_set(&self->flags, AQ_NIC_LINK_DOWN); + } ++ + return 0; + } + +@@ -194,6 +196,7 @@ static irqreturn_t aq_linkstate_threaded_isr(int irq, void *private) + + self->aq_hw_ops->hw_irq_enable(self->aq_hw, + BIT(self->aq_nic_cfg.link_irq_vec)); ++ + return IRQ_HANDLED; + } + +@@ -224,7 +227,8 @@ static void aq_nic_service_timer_cb(struct timer_list *t) + { + struct aq_nic_s *self = from_timer(self, t, service_timer); + +- mod_timer(&self->service_timer, jiffies + AQ_CFG_SERVICE_TIMER_INTERVAL); ++ mod_timer(&self->service_timer, ++ jiffies + AQ_CFG_SERVICE_TIMER_INTERVAL); + + aq_ndev_schedule_work(&self->service_task); + } +@@ -326,8 +330,8 @@ struct net_device *aq_nic_get_ndev(struct aq_nic_s *self) + int aq_nic_init(struct aq_nic_s *self) + { + struct aq_vec_s *aq_vec = NULL; +- int err = 0; + unsigned int i = 0U; ++ int err = 0; + + self->power_state = AQ_HW_POWER_STATE_D0; + mutex_lock(&self->fwreq_mutex); +@@ -371,8 +375,8 @@ int aq_nic_init(struct aq_nic_s *self) + int aq_nic_start(struct aq_nic_s *self) + { + struct aq_vec_s *aq_vec = NULL; +- int err = 0; + unsigned int i = 0U; ++ int err = 0; + + err = self->aq_hw_ops->hw_multicast_list_set(self->aq_hw, + self->mc_list.ar, +@@ -464,14 +468,16 @@ int aq_nic_start(struct aq_nic_s *self) + unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + struct aq_ring_s *ring) + { +- unsigned int ret = 0U; + unsigned int nr_frags = skb_shinfo(skb)->nr_frags; +- unsigned int frag_count = 0U; +- unsigned int dx = ring->sw_tail; + struct aq_ring_buff_s *first = NULL; +- struct aq_ring_buff_s *dx_buff = &ring->buff_ring[dx]; ++ struct aq_ring_buff_s *dx_buff; + bool need_context_tag = false; ++ unsigned int frag_count = 0U; ++ unsigned int ret = 0U; ++ unsigned int dx; + ++ dx = ring->sw_tail; ++ dx_buff = &ring->buff_ring[dx]; + dx_buff->flags = 0U; + + if (unlikely(skb_is_gso(skb))) { +@@ -610,11 +616,11 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + + int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) + { ++ unsigned int vec = skb->queue_mapping % self->aq_nic_cfg.vecs; + struct aq_ring_s *ring = NULL; + unsigned int frags = 0U; +- unsigned int vec = skb->queue_mapping % self->aq_nic_cfg.vecs; +- unsigned int tc = 0U; + int err = NETDEV_TX_OK; ++ unsigned int tc = 0U; + + frags = skb_shinfo(skb)->nr_frags + 1; + +@@ -712,6 +718,7 @@ int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev) + if (err < 0) + return err; + } ++ + return aq_nic_set_packet_filter(self, packet_filter); + } + +@@ -756,10 +763,10 @@ int aq_nic_get_regs_count(struct aq_nic_s *self) + + void aq_nic_get_stats(struct aq_nic_s *self, u64 *data) + { +- unsigned int i = 0U; +- unsigned int count = 0U; + struct aq_vec_s *aq_vec = NULL; + struct aq_stats_s *stats; ++ unsigned int count = 0U; ++ unsigned int i = 0U; + + if (self->aq_fw_ops->update_stats) { + mutex_lock(&self->fwreq_mutex); +@@ -809,8 +816,8 @@ err_exit:; + + static void aq_nic_update_ndev_stats(struct aq_nic_s *self) + { +- struct net_device *ndev = self->ndev; + struct aq_stats_s *stats = self->aq_hw_ops->hw_get_hw_stats(self->aq_hw); ++ struct net_device *ndev = self->ndev; + + ndev->stats.rx_packets = stats->dma_pkt_rc; + ndev->stats.rx_bytes = stats->dma_oct_rc; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index bb4957a31498..98c3182bf1d0 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -72,8 +72,8 @@ struct aq_hw_rx_fl2 { + }; + + struct aq_hw_rx_fl3l4 { +- u8 active_ipv4; +- u8 active_ipv6:2; ++ u8 active_ipv4; ++ u8 active_ipv6:2; + u8 is_ipv6; + u8 reserved_count; + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +index 3169951fe6ab..a161026cfbfd 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +@@ -185,6 +185,7 @@ unsigned int aq_pci_func_get_irq_type(struct aq_nic_s *self) + return AQ_HW_IRQ_MSIX; + if (self->pdev->msi_enabled) + return AQ_HW_IRQ_MSI; ++ + return AQ_HW_IRQ_LEGACY; + } + +@@ -196,12 +197,12 @@ static void aq_pci_free_irq_vectors(struct aq_nic_s *self) + static int aq_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *pci_id) + { +- struct aq_nic_s *self; +- int err; + struct net_device *ndev; + resource_size_t mmio_pa; +- u32 bar; ++ struct aq_nic_s *self; + u32 numvecs; ++ u32 bar; ++ int err; + + err = pci_enable_device(pdev); + if (err) +@@ -311,6 +312,7 @@ static int aq_pci_probe(struct pci_dev *pdev, + pci_release_regions(pdev); + err_pci_func: + pci_disable_device(pdev); ++ + return err; + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index f756cc0bbdf0..951d86f8b66e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -30,8 +30,8 @@ static int aq_get_rxpage(struct aq_rxpage *rxpage, unsigned int order, + struct device *dev) + { + struct page *page; +- dma_addr_t daddr; + int ret = -ENOMEM; ++ dma_addr_t daddr; + + page = dev_alloc_pages(order); + if (unlikely(!page)) +@@ -118,6 +118,7 @@ static struct aq_ring_s *aq_ring_alloc(struct aq_ring_s *self, + aq_ring_free(self); + self = NULL; + } ++ + return self; + } + +@@ -144,6 +145,7 @@ struct aq_ring_s *aq_ring_tx_alloc(struct aq_ring_s *self, + aq_ring_free(self); + self = NULL; + } ++ + return self; + } + +@@ -175,6 +177,7 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self, + aq_ring_free(self); + self = NULL; + } ++ + return self; + } + +@@ -207,6 +210,7 @@ int aq_ring_init(struct aq_ring_s *self) + self->hw_head = 0; + self->sw_head = 0; + self->sw_tail = 0; ++ + return 0; + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +index a95c263a45aa..6e19e27b6200 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +@@ -103,8 +103,8 @@ static int aq_vec_poll(struct napi_struct *napi, int budget) + struct aq_vec_s *aq_vec_alloc(struct aq_nic_s *aq_nic, unsigned int idx, + struct aq_nic_cfg_s *aq_nic_cfg) + { +- struct aq_vec_s *self = NULL; + struct aq_ring_s *ring = NULL; ++ struct aq_vec_s *self = NULL; + unsigned int i = 0U; + int err = 0; + +@@ -159,6 +159,7 @@ struct aq_vec_s *aq_vec_alloc(struct aq_nic_s *aq_nic, unsigned int idx, + aq_vec_free(self); + self = NULL; + } ++ + return self; + } + +@@ -263,6 +264,7 @@ void aq_vec_deinit(struct aq_vec_s *self) + aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]); + aq_ring_rx_deinit(&ring[AQ_VEC_RX_ID]); + } ++ + err_exit:; + } + +@@ -305,8 +307,8 @@ irqreturn_t aq_vec_isr(int irq, void *private) + irqreturn_t aq_vec_isr_legacy(int irq, void *private) + { + struct aq_vec_s *self = private; ++ irqreturn_t err = 0; + u64 irq_mask = 0U; +- int err; + + if (!self) + return IRQ_NONE; +@@ -361,9 +363,9 @@ void aq_vec_add_stats(struct aq_vec_s *self, + + int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data, unsigned int *p_count) + { +- unsigned int count = 0U; + struct aq_ring_stats_rx_s stats_rx; + struct aq_ring_stats_tx_s stats_tx; ++ unsigned int count = 0U; + + memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s)); + memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s)); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index 359a4d387185..d2fb399f179f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -119,10 +119,10 @@ static int hw_atl_a0_hw_reset(struct aq_hw_s *self) + + static int hw_atl_a0_hw_qos_set(struct aq_hw_s *self) + { +- u32 tc = 0U; +- u32 buff_size = 0U; +- unsigned int i_priority = 0U; + bool is_rx_flow_control = false; ++ unsigned int i_priority = 0U; ++ u32 buff_size = 0U; ++ u32 tc = 0U; + + /* TPS Descriptor rate init */ + hw_atl_tps_tx_pkt_shed_desc_rate_curr_time_res_set(self, 0x0U); +@@ -180,9 +180,9 @@ static int hw_atl_a0_hw_rss_hash_set(struct aq_hw_s *self, + struct aq_rss_parameters *rss_params) + { + struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; +- int err = 0; +- unsigned int i = 0U; + unsigned int addr = 0U; ++ unsigned int i = 0U; ++ int err = 0; + u32 val; + + for (i = 10, addr = 0U; i--; ++addr) { +@@ -207,12 +207,12 @@ static int hw_atl_a0_hw_rss_hash_set(struct aq_hw_s *self, + static int hw_atl_a0_hw_rss_set(struct aq_hw_s *self, + struct aq_rss_parameters *rss_params) + { +- u8 *indirection_table = rss_params->indirection_table; +- u32 i = 0U; + u32 num_rss_queues = max(1U, self->aq_nic_cfg->num_rss_queues); +- int err = 0; ++ u8 *indirection_table = rss_params->indirection_table; + u16 bitary[1 + (HW_ATL_A0_RSS_REDIRECTION_MAX * + HW_ATL_A0_RSS_REDIRECTION_BITS / 16U)]; ++ int err = 0; ++ u32 i = 0U; + u32 val; + + memset(bitary, 0, sizeof(bitary)); +@@ -321,9 +321,9 @@ static int hw_atl_a0_hw_init_rx_path(struct aq_hw_s *self) + + static int hw_atl_a0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) + { +- int err = 0; + unsigned int h = 0U; + unsigned int l = 0U; ++ int err = 0; + + if (!mac_addr) { + err = -EINVAL; +@@ -352,10 +352,9 @@ static int hw_atl_a0_hw_init(struct aq_hw_s *self, u8 *mac_addr) + [AQ_HW_IRQ_MSI] = { 0x20000021U, 0x20000025U }, + [AQ_HW_IRQ_MSIX] = { 0x20000022U, 0x20000026U }, + }; +- ++ struct aq_nic_cfg_s *aq_nic_cfg = self->aq_nic_cfg; + int err = 0; + +- struct aq_nic_cfg_s *aq_nic_cfg = self->aq_nic_cfg; + + hw_atl_a0_hw_init_tx_path(self); + hw_atl_a0_hw_init_rx_path(self); +@@ -404,6 +403,7 @@ static int hw_atl_a0_hw_ring_tx_start(struct aq_hw_s *self, + struct aq_ring_s *ring) + { + hw_atl_tdm_tx_desc_en_set(self, 1, ring->idx); ++ + return aq_hw_err_from_flags(self); + } + +@@ -411,6 +411,7 @@ static int hw_atl_a0_hw_ring_rx_start(struct aq_hw_s *self, + struct aq_ring_s *ring) + { + hw_atl_rdm_rx_desc_en_set(self, 1, ring->idx); ++ + return aq_hw_err_from_flags(self); + } + +@@ -418,6 +419,7 @@ static int hw_atl_a0_hw_start(struct aq_hw_s *self) + { + hw_atl_tpb_tx_buff_en_set(self, 1); + hw_atl_rpb_rx_buff_en_set(self, 1); ++ + return aq_hw_err_from_flags(self); + } + +@@ -425,6 +427,7 @@ static int hw_atl_a0_hw_tx_ring_tail_update(struct aq_hw_s *self, + struct aq_ring_s *ring) + { + hw_atl_reg_tx_dma_desc_tail_ptr_set(self, ring->sw_tail, ring->idx); ++ + return 0; + } + +@@ -435,8 +438,8 @@ static int hw_atl_a0_hw_ring_tx_xmit(struct aq_hw_s *self, + struct aq_ring_buff_s *buff = NULL; + struct hw_atl_txd_s *txd = NULL; + unsigned int buff_pa_len = 0U; +- unsigned int pkt_len = 0U; + unsigned int frag_count = 0U; ++ unsigned int pkt_len = 0U; + bool is_gso = false; + + buff = &ring->buff_ring[ring->sw_tail]; +@@ -500,6 +503,7 @@ static int hw_atl_a0_hw_ring_tx_xmit(struct aq_hw_s *self, + } + + hw_atl_a0_hw_tx_ring_tail_update(self, ring); ++ + return aq_hw_err_from_flags(self); + } + +@@ -507,8 +511,8 @@ static int hw_atl_a0_hw_ring_rx_init(struct aq_hw_s *self, + struct aq_ring_s *aq_ring, + struct aq_ring_param_s *aq_ring_param) + { +- u32 dma_desc_addr_lsw = (u32)aq_ring->dx_ring_pa; + u32 dma_desc_addr_msw = (u32)(((u64)aq_ring->dx_ring_pa) >> 32); ++ u32 dma_desc_addr_lsw = (u32)aq_ring->dx_ring_pa; + + hw_atl_rdm_rx_desc_en_set(self, false, aq_ring->idx); + +@@ -549,8 +553,8 @@ static int hw_atl_a0_hw_ring_tx_init(struct aq_hw_s *self, + struct aq_ring_s *aq_ring, + struct aq_ring_param_s *aq_ring_param) + { +- u32 dma_desc_lsw_addr = (u32)aq_ring->dx_ring_pa; + u32 dma_desc_msw_addr = (u32)(((u64)aq_ring->dx_ring_pa) >> 32); ++ u32 dma_desc_lsw_addr = (u32)aq_ring->dx_ring_pa; + + hw_atl_reg_tx_dma_desc_base_addresslswset(self, dma_desc_lsw_addr, + aq_ring->idx); +@@ -599,8 +603,8 @@ static int hw_atl_a0_hw_ring_rx_fill(struct aq_hw_s *self, + static int hw_atl_a0_hw_ring_tx_head_update(struct aq_hw_s *self, + struct aq_ring_s *ring) + { +- int err = 0; + unsigned int hw_head = hw_atl_tdm_tx_desc_head_ptr_get(self, ring->idx); ++ int err = 0; + + if (aq_utils_obj_test(&self->flags, AQ_HW_FLAG_ERR_UNPLUG)) { + err = -ENXIO; +@@ -720,6 +724,7 @@ static int hw_atl_a0_hw_irq_enable(struct aq_hw_s *self, u64 mask) + { + hw_atl_itr_irq_msk_setlsw_set(self, LODWORD(mask) | + (1U << HW_ATL_A0_ERR_INT)); ++ + return aq_hw_err_from_flags(self); + } + +@@ -737,6 +742,7 @@ static int hw_atl_a0_hw_irq_disable(struct aq_hw_s *self, u64 mask) + static int hw_atl_a0_hw_irq_read(struct aq_hw_s *self, u64 *mask) + { + *mask = hw_atl_itr_irq_statuslsw_get(self); ++ + return aq_hw_err_from_flags(self); + } + +@@ -859,6 +865,7 @@ static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self) + static int hw_atl_a0_hw_stop(struct aq_hw_s *self) + { + hw_atl_a0_hw_irq_disable(self, HW_ATL_A0_INT_MASK); ++ + return aq_hw_err_from_flags(self); + } + +@@ -866,6 +873,7 @@ static int hw_atl_a0_hw_ring_tx_stop(struct aq_hw_s *self, + struct aq_ring_s *ring) + { + hw_atl_tdm_tx_desc_en_set(self, 0U, ring->idx); ++ + return aq_hw_err_from_flags(self); + } + +@@ -873,6 +881,7 @@ static int hw_atl_a0_hw_ring_rx_stop(struct aq_hw_s *self, + struct aq_ring_s *ring) + { + hw_atl_rdm_rx_desc_en_set(self, 0U, ring->idx); ++ + return aq_hw_err_from_flags(self); + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 1165689af37d..8686462b32f9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -107,14 +107,15 @@ static int hw_atl_b0_hw_reset(struct aq_hw_s *self) + static int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc) + { + hw_atl_rpb_rx_xoff_en_per_tc_set(self, !!(fc & AQ_NIC_FC_RX), tc); ++ + return 0; + } + + static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + { +- u32 tc = 0U; +- u32 buff_size = 0U; + unsigned int i_priority = 0U; ++ u32 buff_size = 0U; ++ u32 tc = 0U; + + /* TPS Descriptor rate init */ + hw_atl_tps_tx_pkt_shed_desc_rate_curr_time_res_set(self, 0x0U); +@@ -188,9 +189,9 @@ static int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self, + struct aq_rss_parameters *rss_params) + { + struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; +- int err = 0; +- unsigned int i = 0U; + unsigned int addr = 0U; ++ unsigned int i = 0U; ++ int err = 0; + u32 val; + + for (i = 10, addr = 0U; i--; ++addr) { +@@ -215,12 +216,12 @@ static int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self, + static int hw_atl_b0_hw_rss_set(struct aq_hw_s *self, + struct aq_rss_parameters *rss_params) + { +- u8 *indirection_table = rss_params->indirection_table; +- u32 i = 0U; + u32 num_rss_queues = max(1U, self->aq_nic_cfg->num_rss_queues); +- int err = 0; ++ u8 *indirection_table = rss_params->indirection_table; + u16 bitary[1 + (HW_ATL_B0_RSS_REDIRECTION_MAX * + HW_ATL_B0_RSS_REDIRECTION_BITS / 16U)]; ++ int err = 0; ++ u32 i = 0U; + u32 val; + + memset(bitary, 0, sizeof(bitary)); +@@ -304,6 +305,7 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, + + hw_atl_itr_rsc_delay_set(self, 1U); + } ++ + return aq_hw_err_from_flags(self); + } + +@@ -382,9 +384,9 @@ static int hw_atl_b0_hw_init_rx_path(struct aq_hw_s *self) + + static int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) + { +- int err = 0; + unsigned int h = 0U; + unsigned int l = 0U; ++ int err = 0; + + if (!mac_addr) { + err = -EINVAL; +@@ -413,11 +415,10 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr) + [AQ_HW_IRQ_MSI] = { 0x20000021U, 0x20000025U }, + [AQ_HW_IRQ_MSIX] = { 0x20000022U, 0x20000026U }, + }; +- ++ struct aq_nic_cfg_s *aq_nic_cfg = self->aq_nic_cfg; + int err = 0; + u32 val; + +- struct aq_nic_cfg_s *aq_nic_cfg = self->aq_nic_cfg; + + hw_atl_b0_hw_init_tx_path(self); + hw_atl_b0_hw_init_rx_path(self); +@@ -460,8 +461,10 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr) + + /* Interrupts */ + hw_atl_reg_gen_irq_map_set(self, +- ((HW_ATL_B0_ERR_INT << 0x18) | (1U << 0x1F)) | +- ((HW_ATL_B0_ERR_INT << 0x10) | (1U << 0x17)), 0U); ++ ((HW_ATL_B0_ERR_INT << 0x18) | ++ (1U << 0x1F)) | ++ ((HW_ATL_B0_ERR_INT << 0x10) | ++ (1U << 0x17)), 0U); + + /* Enable link interrupt */ + if (aq_nic_cfg->link_irq_vec) +@@ -478,6 +481,7 @@ static int hw_atl_b0_hw_ring_tx_start(struct aq_hw_s *self, + struct aq_ring_s *ring) + { + hw_atl_tdm_tx_desc_en_set(self, 1, ring->idx); ++ + return aq_hw_err_from_flags(self); + } + +@@ -485,6 +489,7 @@ static int hw_atl_b0_hw_ring_rx_start(struct aq_hw_s *self, + struct aq_ring_s *ring) + { + hw_atl_rdm_rx_desc_en_set(self, 1, ring->idx); ++ + return aq_hw_err_from_flags(self); + } + +@@ -492,6 +497,7 @@ static int hw_atl_b0_hw_start(struct aq_hw_s *self) + { + hw_atl_tpb_tx_buff_en_set(self, 1); + hw_atl_rpb_rx_buff_en_set(self, 1); ++ + return aq_hw_err_from_flags(self); + } + +@@ -499,6 +505,7 @@ static int hw_atl_b0_hw_tx_ring_tail_update(struct aq_hw_s *self, + struct aq_ring_s *ring) + { + hw_atl_reg_tx_dma_desc_tail_ptr_set(self, ring->sw_tail, ring->idx); ++ + return 0; + } + +@@ -509,8 +516,8 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, + struct aq_ring_buff_s *buff = NULL; + struct hw_atl_txd_s *txd = NULL; + unsigned int buff_pa_len = 0U; +- unsigned int pkt_len = 0U; + unsigned int frag_count = 0U; ++ unsigned int pkt_len = 0U; + bool is_vlan = false; + bool is_gso = false; + +@@ -586,6 +593,7 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, + } + + hw_atl_b0_hw_tx_ring_tail_update(self, ring); ++ + return aq_hw_err_from_flags(self); + } + +@@ -593,9 +601,9 @@ static int hw_atl_b0_hw_ring_rx_init(struct aq_hw_s *self, + struct aq_ring_s *aq_ring, + struct aq_ring_param_s *aq_ring_param) + { +- u32 dma_desc_addr_lsw = (u32)aq_ring->dx_ring_pa; + u32 dma_desc_addr_msw = (u32)(((u64)aq_ring->dx_ring_pa) >> 32); + u32 vlan_rx_stripping = self->aq_nic_cfg->is_vlan_rx_strip; ++ u32 dma_desc_addr_lsw = (u32)aq_ring->dx_ring_pa; + + hw_atl_rdm_rx_desc_en_set(self, false, aq_ring->idx); + +@@ -636,8 +644,8 @@ static int hw_atl_b0_hw_ring_tx_init(struct aq_hw_s *self, + struct aq_ring_s *aq_ring, + struct aq_ring_param_s *aq_ring_param) + { +- u32 dma_desc_lsw_addr = (u32)aq_ring->dx_ring_pa; + u32 dma_desc_msw_addr = (u32)(((u64)aq_ring->dx_ring_pa) >> 32); ++ u32 dma_desc_lsw_addr = (u32)aq_ring->dx_ring_pa; + + hw_atl_reg_tx_dma_desc_base_addresslswset(self, dma_desc_lsw_addr, + aq_ring->idx); +@@ -726,8 +734,10 @@ static int hw_atl_b0_hw_ring_hwts_rx_receive(struct aq_hw_s *self, + static int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self, + struct aq_ring_s *ring) + { ++ unsigned int hw_head_; + int err = 0; +- unsigned int hw_head_ = hw_atl_tdm_tx_desc_head_ptr_get(self, ring->idx); ++ ++ hw_head_ = hw_atl_tdm_tx_desc_head_ptr_get(self, ring->idx); + + if (aq_utils_obj_test(&self->flags, AQ_HW_FLAG_ERR_UNPLUG)) { + err = -ENXIO; +@@ -843,6 +853,7 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self, + static int hw_atl_b0_hw_irq_enable(struct aq_hw_s *self, u64 mask) + { + hw_atl_itr_irq_msk_setlsw_set(self, LODWORD(mask)); ++ + return aq_hw_err_from_flags(self); + } + +@@ -852,12 +863,14 @@ static int hw_atl_b0_hw_irq_disable(struct aq_hw_s *self, u64 mask) + hw_atl_itr_irq_status_clearlsw_set(self, LODWORD(mask)); + + atomic_inc(&self->dpc); ++ + return aq_hw_err_from_flags(self); + } + + static int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask) + { + *mask = hw_atl_itr_irq_statuslsw_get(self); ++ + return aq_hw_err_from_flags(self); + } + +@@ -866,8 +879,8 @@ static int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask) + static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self, + unsigned int packet_filter) + { +- unsigned int i = 0U; + struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; ++ unsigned int i = 0U; + + hw_atl_rpfl2promiscuous_mode_en_set(self, + IS_FILTER_ENABLED(IFF_PROMISC)); +@@ -905,29 +918,30 @@ static int hw_atl_b0_hw_multicast_list_set(struct aq_hw_s *self, + u32 count) + { + int err = 0; ++ struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; + + if (count > (HW_ATL_B0_MAC_MAX - HW_ATL_B0_MAC_MIN)) { + err = -EBADRQC; + goto err_exit; + } +- for (self->aq_nic_cfg->mc_list_count = 0U; +- self->aq_nic_cfg->mc_list_count < count; +- ++self->aq_nic_cfg->mc_list_count) { +- u32 i = self->aq_nic_cfg->mc_list_count; ++ for (cfg->mc_list_count = 0U; ++ cfg->mc_list_count < count; ++ ++cfg->mc_list_count) { ++ u32 i = cfg->mc_list_count; + u32 h = (ar_mac[i][0] << 8) | (ar_mac[i][1]); + u32 l = (ar_mac[i][2] << 24) | (ar_mac[i][3] << 16) | + (ar_mac[i][4] << 8) | ar_mac[i][5]; + + hw_atl_rpfl2_uc_flr_en_set(self, 0U, HW_ATL_B0_MAC_MIN + i); + +- hw_atl_rpfl2unicast_dest_addresslsw_set(self, +- l, HW_ATL_B0_MAC_MIN + i); ++ hw_atl_rpfl2unicast_dest_addresslsw_set(self, l, ++ HW_ATL_B0_MAC_MIN + i); + +- hw_atl_rpfl2unicast_dest_addressmsw_set(self, +- h, HW_ATL_B0_MAC_MIN + i); ++ hw_atl_rpfl2unicast_dest_addressmsw_set(self, h, ++ HW_ATL_B0_MAC_MIN + i); + + hw_atl_rpfl2_uc_flr_en_set(self, +- (self->aq_nic_cfg->is_mc_list_enabled), ++ (cfg->is_mc_list_enabled), + HW_ATL_B0_MAC_MIN + i); + } + +@@ -1054,6 +1068,7 @@ static int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, + struct aq_ring_s *ring) + { + hw_atl_tdm_tx_desc_en_set(self, 0U, ring->idx); ++ + return aq_hw_err_from_flags(self); + } + +@@ -1061,6 +1076,7 @@ static int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, + struct aq_ring_s *ring) + { + hw_atl_rdm_rx_desc_en_set(self, 0U, ring->idx); ++ + return aq_hw_err_from_flags(self); + } + +@@ -1448,6 +1464,7 @@ static int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable) + default: + return -EINVAL; + } ++ + return 0; + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index db8c09c5a768..8910b62e67ed 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -92,6 +92,7 @@ int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) + } + self->aq_fw_ops = *fw_ops; + err = self->aq_fw_ops->init(self); ++ + return err; + } + +@@ -242,9 +243,9 @@ static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self) + + int hw_atl_utils_soft_reset(struct aq_hw_s *self) + { +- int k; + u32 boot_exit_code = 0; + u32 val; ++ int k; + + for (k = 0; k < 1000; ++k) { + u32 flb_status = aq_hw_read_reg(self, +@@ -439,15 +440,16 @@ int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p, + + static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual) + { +- int err = 0; + const u32 dw_major_mask = 0xff000000U; + const u32 dw_minor_mask = 0x00ffffffU; ++ int err = 0; + + err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0; + if (err < 0) + goto err_exit; + err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ? + -EOPNOTSUPP : 0; ++ + err_exit: + return err; + } +@@ -492,8 +494,8 @@ struct aq_hw_atl_utils_fw_rpc_tid_s { + + int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size) + { +- int err = 0; + struct aq_hw_atl_utils_fw_rpc_tid_s sw; ++ int err = 0; + + if (!IS_CHIP_FEATURE(MIPS)) { + err = -1; +@@ -516,9 +518,9 @@ int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size) + int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, + struct hw_atl_utils_fw_rpc **rpc) + { +- int err = 0; + struct aq_hw_atl_utils_fw_rpc_tid_s sw; + struct aq_hw_atl_utils_fw_rpc_tid_s fw; ++ int err = 0; + + do { + sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR); +@@ -622,10 +624,10 @@ static int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed) + static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, + enum hal_atl_utils_fw_state_e state) + { +- int err = 0; +- u32 transaction_id = 0; +- struct hw_atl_utils_mbox_header mbox; + u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR); ++ struct hw_atl_utils_mbox_header mbox; ++ u32 transaction_id = 0; ++ int err = 0; + + if (state == MPI_RESET) { + hw_atl_utils_mpi_read_mbox(self, &mbox); +@@ -653,20 +655,26 @@ static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, + val |= state & HW_ATL_MPI_STATE_MSK; + + aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val); ++ + err_exit: + return err; + } + + int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self) + { +- u32 cp0x036C = hw_atl_utils_mpi_get_state(self); +- u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT; + struct aq_hw_link_status_s *link_status = &self->aq_link_status; ++ u32 mpi_state; ++ u32 speed; ++ ++ mpi_state = hw_atl_utils_mpi_get_state(self); ++ speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G | ++ FW2X_RATE_2G5 | FW2X_RATE_5G | ++ FW2X_RATE_10G); + +- if (!link_speed_mask) { ++ if (!speed) { + link_status->mbps = 0U; + } else { +- switch (link_speed_mask) { ++ switch (speed) { + case HAL_ATLANTIC_RATE_10G: + link_status->mbps = 10000U; + break; +@@ -699,14 +707,15 @@ int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self) + int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self, + u8 *mac) + { ++ u32 mac_addr[2]; ++ u32 efuse_addr; + int err = 0; + u32 h = 0U; + u32 l = 0U; +- u32 mac_addr[2]; + + if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) { +- unsigned int rnd = 0; + unsigned int ucp_0x370 = 0; ++ unsigned int rnd = 0; + + get_random_bytes(&rnd, sizeof(unsigned int)); + +@@ -714,11 +723,10 @@ int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self, + aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370); + } + +- err = hw_atl_utils_fw_downld_dwords(self, +- aq_hw_read_reg(self, 0x00000374U) + +- (40U * 4U), +- mac_addr, +- ARRAY_SIZE(mac_addr)); ++ efuse_addr = aq_hw_read_reg(self, 0x00000374U); ++ ++ err = hw_atl_utils_fw_downld_dwords(self, efuse_addr + (40U * 4U), ++ mac_addr, ARRAY_SIZE(mac_addr)); + if (err < 0) { + mac_addr[0] = 0U; + mac_addr[1] = 0U; +@@ -780,14 +788,15 @@ unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps) + default: + break; + } ++ + return ret; + } + + void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p) + { +- u32 chip_features = 0U; + u32 val = hw_atl_reg_glb_mif_id_get(self); + u32 mif_rev = val & 0xFFU; ++ u32 chip_features = 0U; + + if ((0xFU & mif_rev) == 1U) { + chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 | +@@ -814,13 +823,14 @@ static int hw_atl_fw1x_deinit(struct aq_hw_s *self) + { + hw_atl_utils_mpi_set_speed(self, 0); + hw_atl_utils_mpi_set_state(self, MPI_DEINIT); ++ + return 0; + } + + int hw_atl_utils_update_stats(struct aq_hw_s *self) + { +- struct hw_atl_utils_mbox mbox; + struct aq_stats_s *cs = &self->curr_stats; ++ struct hw_atl_utils_mbox mbox; + + hw_atl_utils_mpi_read_stats(self, &mbox); + +@@ -897,12 +907,14 @@ int hw_atl_utils_hw_get_regs(struct aq_hw_s *self, + for (i = 0; i < aq_hw_caps->mac_regs_count; i++) + regs_buff[i] = aq_hw_read_reg(self, + hw_atl_utils_hw_mac_regs[i]); ++ + return 0; + } + + int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version) + { + *fw_version = aq_hw_read_reg(self, 0x18U); ++ + return 0; + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index feef2b0177b2..ce3ed86d8c0e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -226,15 +226,20 @@ static int aq_fw2x_set_state(struct aq_hw_s *self, + break; + } + aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state); ++ + return 0; + } + + static int aq_fw2x_update_link_status(struct aq_hw_s *self) + { +- u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR); +- u32 speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G | +- FW2X_RATE_2G5 | FW2X_RATE_5G | FW2X_RATE_10G); + struct aq_hw_link_status_s *link_status = &self->aq_link_status; ++ u32 mpi_state; ++ u32 speed; ++ ++ mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR); ++ speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G | ++ FW2X_RATE_2G5 | FW2X_RATE_5G | ++ FW2X_RATE_10G); + + if (speed) { + if (speed & FW2X_RATE_10G) +@@ -258,11 +263,11 @@ static int aq_fw2x_update_link_status(struct aq_hw_s *self) + + static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac) + { ++ u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR); ++ u32 mac_addr[2] = { 0 }; + int err = 0; + u32 h = 0U; + u32 l = 0U; +- u32 mac_addr[2] = { 0 }; +- u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR); + + if (efuse_addr != 0) { + err = hw_atl_utils_fw_downld_dwords(self, +@@ -296,15 +301,16 @@ static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac) + h >>= 8; + mac[0] = (u8)(0xFFU & h); + } ++ + return err; + } + + static int aq_fw2x_update_stats(struct aq_hw_s *self) + { +- int err = 0; + u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); + u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS); + u32 stats_val; ++ int err = 0; + + /* Toggle statistics bit for FW to update */ + mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS); +@@ -331,9 +337,9 @@ static int aq_fw2x_get_phy_temp(struct aq_hw_s *self, int *temp) + int err = 0; + u32 val; + +- phy_temp_offset = self->mbox_addr + +- offsetof(struct hw_atl_utils_mbox, info) + +- offsetof(struct hw_aq_info, phy_temperature); ++ phy_temp_offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox, ++ info.phy_temperature); ++ + /* Toggle statistics bit for FW to 0x36C.18 (CTRL_TEMPERATURE) */ + mpi_opts = mpi_opts ^ HW_ATL_FW2X_CTRL_TEMPERATURE; + aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); +@@ -486,11 +492,12 @@ static int aq_fw2x_get_eee_rate(struct aq_hw_s *self, u32 *rate, + u32 mpi_state; + u32 caps_hi; + int err = 0; +- u32 addr = self->mbox_addr + offsetof(struct hw_atl_utils_mbox, info) + +- offsetof(struct hw_aq_info, caps_hi); ++ u32 offset; + +- err = hw_atl_utils_fw_downld_dwords(self, addr, &caps_hi, +- sizeof(caps_hi) / sizeof(u32)); ++ offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox, ++ info.caps_hi); ++ ++ err = hw_atl_utils_fw_downld_dwords(self, offset, &caps_hi, 1); + + if (err) + return err; +@@ -567,6 +574,7 @@ static int aq_fw2x_set_phyloopback(struct aq_hw_s *self, u32 mode, bool enable) + default: + return -EINVAL; + } ++ + return 0; + } + +-- +2.13.6 + diff --git a/SOURCES/0047-netdrv-net-atlantic-stylistic-renames.patch b/SOURCES/0047-netdrv-net-atlantic-stylistic-renames.patch new file mode 100644 index 0000000..b36cb3a --- /dev/null +++ b/SOURCES/0047-netdrv-net-atlantic-stylistic-renames.patch @@ -0,0 +1,112 @@ +From a655a8ee2811ddecdb2097cb9d715107cab560d6 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:04 -0500 +Subject: [PATCH 047/139] [netdrv] net: atlantic: stylistic renames + +Message-id: <1604687916-15087-48-git-send-email-irusskik@redhat.com> +Patchwork-id: 338472 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 047/139] net: atlantic: stylistic renames +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit ddef55263271cd7108db3821c376e7104ba7cc5f +Author: Igor Russkikh +Date: Thu Nov 7 22:42:02 2019 +0000 + + net: atlantic: stylistic renames + + We are trying to follow the naming of the chip (atlantic), not + company. So replace some old namings. + + Signed-off-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 6 +++--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h | 8 ++++---- + 2 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index 1f9eab74453e..58e8c641e8b3 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -1057,7 +1057,7 @@ static struct ptp_clock_info aq_ptp_clock = { + ptp_offset[__idx].ingress = (__ingress); } \ + while (0) + +-static void aq_ptp_offset_init_from_fw(const struct hw_aq_ptp_offset *offsets) ++static void aq_ptp_offset_init_from_fw(const struct hw_atl_ptp_offset *offsets) + { + int i; + +@@ -1098,7 +1098,7 @@ static void aq_ptp_offset_init_from_fw(const struct hw_aq_ptp_offset *offsets) + } + } + +-static void aq_ptp_offset_init(const struct hw_aq_ptp_offset *offsets) ++static void aq_ptp_offset_init(const struct hw_atl_ptp_offset *offsets) + { + memset(ptp_offset, 0, sizeof(ptp_offset)); + +@@ -1106,7 +1106,7 @@ static void aq_ptp_offset_init(const struct hw_aq_ptp_offset *offsets) + } + + static void aq_ptp_gpio_init(struct ptp_clock_info *info, +- struct hw_aq_info *hw_info) ++ struct hw_atl_info *hw_info) + { + struct ptp_pin_desc pin_desc[MAX_PTP_GPIO_COUNT]; + u32 extts_pin_cnt = 0; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index 68fe17ec171d..42f0c5c6ec2d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -113,7 +113,7 @@ struct __packed hw_atl_utils_mbox_header { + u32 error; + }; + +-struct __packed hw_aq_ptp_offset { ++struct __packed hw_atl_ptp_offset { + u16 ingress_100; + u16 egress_100; + u16 ingress_1000; +@@ -148,14 +148,14 @@ enum gpio_pin_function { + GPIO_PIN_FUNCTION_SIZE + }; + +-struct __packed hw_aq_info { ++struct __packed hw_atl_info { + u8 reserved[6]; + u16 phy_fault_code; + u16 phy_temperature; + u8 cable_len; + u8 reserved1; + struct hw_atl_cable_diag cable_diag_data[4]; +- struct hw_aq_ptp_offset ptp_offset; ++ struct hw_atl_ptp_offset ptp_offset; + u8 reserved2[12]; + u32 caps_lo; + u32 caps_hi; +@@ -177,7 +177,7 @@ struct __packed hw_aq_info { + struct __packed hw_atl_utils_mbox { + struct hw_atl_utils_mbox_header header; + struct hw_atl_stats_s stats; +- struct hw_aq_info info; ++ struct hw_atl_info info; + }; + + struct __packed offload_ip_info { +-- +2.13.6 + diff --git a/SOURCES/0048-netdrv-net-atlantic-update-flow-control-logic.patch b/SOURCES/0048-netdrv-net-atlantic-update-flow-control-logic.patch new file mode 100644 index 0000000..6f78179 --- /dev/null +++ b/SOURCES/0048-netdrv-net-atlantic-update-flow-control-logic.patch @@ -0,0 +1,303 @@ +From b45b3f269983806665793a1f482c11ad8ae3cf91 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:05 -0500 +Subject: [PATCH 048/139] [netdrv] net: atlantic: update flow control logic + +Message-id: <1604687916-15087-49-git-send-email-irusskik@redhat.com> +Patchwork-id: 338475 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 048/139] net: atlantic: update flow control logic +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 8009bb1928a6d5b0ce2d8a1dba79972f01e50533 +Author: Nikita Danilov +Date: Thu Nov 7 22:42:04 2019 +0000 + + net: atlantic: update flow control logic + + We now differentiate requested and negotiated flow control + modes. Therefore `ethtool -A` now operates on local requested + FC values, and regular link settings shows the negotiated FC + settings. + + Signed-off-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_cfg.h | 6 --- + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 10 ++--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 19 +++++---- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 14 ++++++- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 2 +- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 2 +- + .../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 47 +++++++++++++--------- + 7 files changed, 59 insertions(+), 41 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +index d02b0d79f68a..f0c41f7408e5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +@@ -70,12 +70,6 @@ + + /*#define AQ_CFG_MAC_ADDR_PERMANENT {0x30, 0x0E, 0xE3, 0x12, 0x34, 0x56}*/ + +-#define AQ_NIC_FC_OFF 0U +-#define AQ_NIC_FC_TX 1U +-#define AQ_NIC_FC_RX 2U +-#define AQ_NIC_FC_FULL 3U +-#define AQ_NIC_FC_AUTO 4U +- + #define AQ_CFG_FC_MODE AQ_NIC_FC_FULL + + /* Default WOL modes used on initialization */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 8286c77d43a5..6353a5c5ed27 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -588,7 +588,7 @@ static void aq_ethtool_get_pauseparam(struct net_device *ndev, + struct ethtool_pauseparam *pause) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- u32 fc = aq_nic->aq_nic_cfg.flow_control; ++ u32 fc = aq_nic->aq_nic_cfg.fc.req; + + pause->autoneg = 0; + +@@ -610,14 +610,14 @@ static int aq_ethtool_set_pauseparam(struct net_device *ndev, + return -EOPNOTSUPP; + + if (pause->rx_pause) +- aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_RX; ++ aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_RX; + else +- aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_RX; ++ aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_RX; + + if (pause->tx_pause) +- aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_TX; ++ aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_TX; + else +- aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_TX; ++ aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_TX; + + mutex_lock(&aq_nic->fwreq_mutex); + err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index d3739f21b18e..7ad8eb535d28 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -79,7 +79,7 @@ void aq_nic_cfg_start(struct aq_nic_s *self) + cfg->is_rss = AQ_CFG_IS_RSS_DEF; + cfg->num_rss_queues = AQ_CFG_NUM_RSS_QUEUES_DEF; + cfg->aq_rss.base_cpu_number = AQ_CFG_RSS_BASE_CPU_NUM_DEF; +- cfg->flow_control = AQ_CFG_FC_MODE; ++ cfg->fc.req = AQ_CFG_FC_MODE; + cfg->wol = AQ_CFG_WOL_MODES; + + cfg->mtu = AQ_CFG_MTU_DEF; +@@ -144,6 +144,10 @@ static int aq_nic_update_link_status(struct aq_nic_s *self) + if (err) + return err; + ++ if (self->aq_fw_ops->get_flow_control) ++ self->aq_fw_ops->get_flow_control(self->aq_hw, &fc); ++ self->aq_nic_cfg.fc.cur = fc; ++ + if (self->link_status.mbps != self->aq_hw->aq_link_status.mbps) { + netdev_info(self->ndev, "%s: link change old %d new %d\n", + AQ_CFG_DRV_NAME, self->link_status.mbps, +@@ -161,8 +165,6 @@ static int aq_nic_update_link_status(struct aq_nic_s *self) + * on any link event. + * We should query FW whether it negotiated FC. + */ +- if (self->aq_fw_ops->get_flow_control) +- self->aq_fw_ops->get_flow_control(self->aq_hw, &fc); + if (self->aq_hw_ops->hw_set_fc) + self->aq_hw_ops->hw_set_fc(self->aq_hw, fc, 0); + } +@@ -862,9 +864,12 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, + ethtool_link_ksettings_add_link_mode(cmd, supported, + 100baseT_Full); + +- if (self->aq_nic_cfg.aq_hw_caps->flow_control) ++ if (self->aq_nic_cfg.aq_hw_caps->flow_control) { + ethtool_link_ksettings_add_link_mode(cmd, supported, + Pause); ++ ethtool_link_ksettings_add_link_mode(cmd, supported, ++ Asym_Pause); ++ } + + ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); + +@@ -898,13 +903,13 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 100baseT_Full); + +- if (self->aq_nic_cfg.flow_control & AQ_NIC_FC_RX) ++ if (self->aq_nic_cfg.fc.cur & AQ_NIC_FC_RX) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + Pause); + + /* Asym is when either RX or TX, but not both */ +- if (!!(self->aq_nic_cfg.flow_control & AQ_NIC_FC_TX) ^ +- !!(self->aq_nic_cfg.flow_control & AQ_NIC_FC_RX)) ++ if (!!(self->aq_nic_cfg.fc.cur & AQ_NIC_FC_TX) ^ ++ !!(self->aq_nic_cfg.fc.cur & AQ_NIC_FC_RX)) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + Asym_Pause); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index 98c3182bf1d0..a752f8bb4b08 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -20,6 +20,18 @@ struct aq_vec_s; + struct aq_ptp_s; + enum aq_rx_filter_type; + ++enum aq_fc_mode { ++ AQ_NIC_FC_OFF = 0, ++ AQ_NIC_FC_TX, ++ AQ_NIC_FC_RX, ++ AQ_NIC_FC_FULL, ++}; ++ ++struct aq_fc_info { ++ enum aq_fc_mode req; ++ enum aq_fc_mode cur; ++}; ++ + struct aq_nic_cfg_s { + const struct aq_hw_caps_s *aq_hw_caps; + u64 features; +@@ -34,7 +46,7 @@ struct aq_nic_cfg_s { + u32 rxpageorder; + u32 num_rss_queues; + u32 mtu; +- u32 flow_control; ++ struct aq_fc_info fc; + u32 link_speed_msk; + u32 wol; + u8 is_vlan_rx_strip; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index d2fb399f179f..03b62d7d9f1a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -155,7 +155,7 @@ static int hw_atl_a0_hw_qos_set(struct aq_hw_s *self) + + /* QoS Rx buf size per TC */ + tc = 0; +- is_rx_flow_control = (AQ_NIC_FC_RX & self->aq_nic_cfg->flow_control); ++ is_rx_flow_control = (AQ_NIC_FC_RX & self->aq_nic_cfg->fc.req); + buff_size = HW_ATL_A0_RXBUF_MAX; + + hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, buff_size, tc); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 8686462b32f9..c5da60c12262 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -168,7 +168,7 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + (1024U / 32U) * 50U) / + 100U, tc); + +- hw_atl_b0_set_fc(self, self->aq_nic_cfg->flow_control, tc); ++ hw_atl_b0_set_fc(self, self->aq_nic_cfg->fc.req, tc); + + /* Init TC2 for PTP_RX */ + tc = 2; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index ce3ed86d8c0e..97ebf849695f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -181,17 +181,26 @@ static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed) + return 0; + } + +-static void aq_fw2x_set_mpi_flow_control(struct aq_hw_s *self, u32 *mpi_state) ++static void aq_fw2x_upd_flow_control_bits(struct aq_hw_s *self, ++ u32 *mpi_state, u32 fc) + { +- if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_RX) +- *mpi_state |= BIT(CAPS_HI_PAUSE); +- else +- *mpi_state &= ~BIT(CAPS_HI_PAUSE); ++ *mpi_state &= ~(HW_ATL_FW2X_CTRL_PAUSE | ++ HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE); + +- if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_TX) +- *mpi_state |= BIT(CAPS_HI_ASYMMETRIC_PAUSE); +- else +- *mpi_state &= ~BIT(CAPS_HI_ASYMMETRIC_PAUSE); ++ switch (fc) { ++ /* There is not explicit mode of RX only pause frames, ++ * thus, we join this mode with FC full. ++ * FC full is either Rx, either Tx, or both. ++ */ ++ case AQ_NIC_FC_FULL: ++ case AQ_NIC_FC_RX: ++ *mpi_state |= HW_ATL_FW2X_CTRL_PAUSE | ++ HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE; ++ break; ++ case AQ_NIC_FC_TX: ++ *mpi_state |= HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE; ++ break; ++ } + } + + static void aq_fw2x_upd_eee_rate_bits(struct aq_hw_s *self, u32 *mpi_opts, +@@ -215,7 +224,8 @@ static int aq_fw2x_set_state(struct aq_hw_s *self, + case MPI_INIT: + mpi_state &= ~BIT(CAPS_HI_LINK_DROP); + aq_fw2x_upd_eee_rate_bits(self, &mpi_state, cfg->eee_speeds); +- aq_fw2x_set_mpi_flow_control(self, &mpi_state); ++ aq_fw2x_upd_flow_control_bits(self, &mpi_state, ++ self->aq_nic_cfg->fc.req); + break; + case MPI_DEINIT: + mpi_state |= BIT(CAPS_HI_LINK_DROP); +@@ -525,7 +535,8 @@ static int aq_fw2x_set_flow_control(struct aq_hw_s *self) + { + u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); + +- aq_fw2x_set_mpi_flow_control(self, &mpi_state); ++ aq_fw2x_upd_flow_control_bits(self, &mpi_state, ++ self->aq_nic_cfg->fc.req); + + aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state); + +@@ -535,17 +546,13 @@ static int aq_fw2x_set_flow_control(struct aq_hw_s *self) + static u32 aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fcmode) + { + u32 mpi_state = aq_fw2x_state2_get(self); ++ *fcmode = 0; + + if (mpi_state & HW_ATL_FW2X_CAP_PAUSE) +- if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE) +- *fcmode = AQ_NIC_FC_RX; +- else +- *fcmode = AQ_NIC_FC_RX | AQ_NIC_FC_TX; +- else +- if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE) +- *fcmode = AQ_NIC_FC_TX; +- else +- *fcmode = 0; ++ *fcmode |= AQ_NIC_FC_RX; ++ ++ if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE) ++ *fcmode |= AQ_NIC_FC_TX; + + return 0; + } +-- +2.13.6 + diff --git a/SOURCES/0049-netdrv-net-atlantic-implement-UDP-GSO-offload.patch b/SOURCES/0049-netdrv-net-atlantic-implement-UDP-GSO-offload.patch new file mode 100644 index 0000000..4507e98 --- /dev/null +++ b/SOURCES/0049-netdrv-net-atlantic-implement-UDP-GSO-offload.patch @@ -0,0 +1,240 @@ +From 9c576296ccdfab0edf2c00a901dcfe0a6f281ee7 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:06 -0500 +Subject: [PATCH 049/139] [netdrv] net: atlantic: implement UDP GSO offload + +Message-id: <1604687916-15087-50-git-send-email-irusskik@redhat.com> +Patchwork-id: 338480 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 049/139] net: atlantic: implement UDP GSO offload +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 822cd114cd05a47b7c272de9b3a4da73114894ca +Author: Igor Russkikh +Date: Thu Nov 7 22:42:06 2019 +0000 + + net: atlantic: implement UDP GSO offload + + atlantic hardware does support UDP hardware segmentation offload. + This allows user to specify one large contiguous buffer with data + which then will be split automagically into multiple UDP packets + of specified size. + + Bulk sending of large UDP streams lowers CPU usage and increases + bandwidth. + + We did estimations both with udpgso_bench_tx test tool and with modified + iperf3 measurement tool (4 streams, multithread, 200b packet size) + over AQC<->AQC 10G link. Flow control is disabled to prevent RX side + impact on measurements. + + No UDP GSO: + iperf3 -c 10.0.1.2 -u -b0 -l 200 -P4 --multithread + UDP GSO: + iperf3 -c 10.0.1.2 -u -b0 -l 12600 --udp-lso 200 -P4 --multithread + + Mode CPU iperf speed Line speed Packets per second + ------------------------------------------------------------- + NO UDP GSO 350% 3.07 Gbps 3.8 Gbps 1,919,419 + SW UDP GSO 200% 5.55 Gbps 6.4 Gbps 3,286,144 + HW UDP GSO 90% 6.80 Gbps 8.4 Gbps 4,273,117 + + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 52 ++++++++++++---------- + drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 7 +-- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 2 +- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 11 +++-- + 4 files changed, 40 insertions(+), 32 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 7ad8eb535d28..a17a4da7bc15 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -309,6 +309,7 @@ void aq_nic_ndev_init(struct aq_nic_s *self) + self->ndev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM | + NETIF_F_RXHASH | NETIF_F_SG | + NETIF_F_LRO | NETIF_F_TSO; ++ self->ndev->gso_partial_features = NETIF_F_GSO_UDP_L4; + self->ndev->priv_flags = aq_hw_caps->hw_priv_flags; + self->ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + +@@ -472,11 +473,18 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + { + unsigned int nr_frags = skb_shinfo(skb)->nr_frags; + struct aq_ring_buff_s *first = NULL; ++ u8 ipver = ip_hdr(skb)->version; + struct aq_ring_buff_s *dx_buff; + bool need_context_tag = false; + unsigned int frag_count = 0U; + unsigned int ret = 0U; + unsigned int dx; ++ u8 l4proto = 0; ++ ++ if (ipver == 4) ++ l4proto = ip_hdr(skb)->protocol; ++ else if (ipver == 6) ++ l4proto = ipv6_hdr(skb)->nexthdr; + + dx = ring->sw_tail; + dx_buff = &ring->buff_ring[dx]; +@@ -484,14 +492,24 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + + if (unlikely(skb_is_gso(skb))) { + dx_buff->mss = skb_shinfo(skb)->gso_size; +- dx_buff->is_gso = 1U; ++ if (l4proto == IPPROTO_TCP) { ++ dx_buff->is_gso_tcp = 1U; ++ dx_buff->len_l4 = tcp_hdrlen(skb); ++ } else if (l4proto == IPPROTO_UDP) { ++ dx_buff->is_gso_udp = 1U; ++ dx_buff->len_l4 = sizeof(struct udphdr); ++ /* UDP GSO Hardware does not replace packet length. */ ++ udp_hdr(skb)->len = htons(dx_buff->mss + ++ dx_buff->len_l4); ++ } else { ++ WARN_ONCE(true, "Bad GSO mode"); ++ goto exit; ++ } + dx_buff->len_pkt = skb->len; + dx_buff->len_l2 = ETH_HLEN; +- dx_buff->len_l3 = ip_hdrlen(skb); +- dx_buff->len_l4 = tcp_hdrlen(skb); ++ dx_buff->len_l3 = skb_network_header_len(skb); + dx_buff->eop_index = 0xffffU; +- dx_buff->is_ipv6 = +- (ip_hdr(skb)->version == 6) ? 1U : 0U; ++ dx_buff->is_ipv6 = (ipver == 6); + need_context_tag = true; + } + +@@ -525,24 +543,9 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + ++ret; + + if (skb->ip_summed == CHECKSUM_PARTIAL) { +- dx_buff->is_ip_cso = (htons(ETH_P_IP) == skb->protocol) ? +- 1U : 0U; +- +- if (ip_hdr(skb)->version == 4) { +- dx_buff->is_tcp_cso = +- (ip_hdr(skb)->protocol == IPPROTO_TCP) ? +- 1U : 0U; +- dx_buff->is_udp_cso = +- (ip_hdr(skb)->protocol == IPPROTO_UDP) ? +- 1U : 0U; +- } else if (ip_hdr(skb)->version == 6) { +- dx_buff->is_tcp_cso = +- (ipv6_hdr(skb)->nexthdr == NEXTHDR_TCP) ? +- 1U : 0U; +- dx_buff->is_udp_cso = +- (ipv6_hdr(skb)->nexthdr == NEXTHDR_UDP) ? +- 1U : 0U; +- } ++ dx_buff->is_ip_cso = (htons(ETH_P_IP) == skb->protocol); ++ dx_buff->is_tcp_cso = (l4proto == IPPROTO_TCP); ++ dx_buff->is_udp_cso = (l4proto == IPPROTO_UDP); + } + + for (; nr_frags--; ++frag_count) { +@@ -597,7 +600,8 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + --ret, dx = aq_ring_next_dx(ring, dx)) { + dx_buff = &ring->buff_ring[dx]; + +- if (!dx_buff->is_gso && !dx_buff->is_vlan && dx_buff->pa) { ++ if (!(dx_buff->is_gso_tcp || dx_buff->is_gso_udp) && ++ !dx_buff->is_vlan && dx_buff->pa) { + if (unlikely(dx_buff->is_sop)) { + dma_unmap_single(aq_nic_get_dev(self), + dx_buff->pa, +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +index be3702a4dcc9..991e4d31b094 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +@@ -65,19 +65,20 @@ struct __packed aq_ring_buff_s { + }; + union { + struct { +- u16 len; ++ u32 len:16; + u32 is_ip_cso:1; + u32 is_udp_cso:1; + u32 is_tcp_cso:1; + u32 is_cso_err:1; + u32 is_sop:1; + u32 is_eop:1; +- u32 is_gso:1; ++ u32 is_gso_tcp:1; ++ u32 is_gso_udp:1; + u32 is_mapped:1; + u32 is_cleaned:1; + u32 is_error:1; + u32 is_vlan:1; +- u32 rsvd3:5; ++ u32 rsvd3:4; + u16 eop_index; + u16 rsvd4; + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index 03b62d7d9f1a..9b1062b8af64 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -454,7 +454,7 @@ static int hw_atl_a0_hw_ring_tx_xmit(struct aq_hw_s *self, + + buff = &ring->buff_ring[ring->sw_tail]; + +- if (buff->is_gso) { ++ if (buff->is_gso_tcp) { + txd->ctl |= (buff->len_l3 << 31) | + (buff->len_l2 << 24) | + HW_ATL_A0_TXD_CTL_CMD_TCP | +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index c5da60c12262..58e891af6e09 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -43,7 +43,9 @@ + NETIF_F_NTUPLE | \ + NETIF_F_HW_VLAN_CTAG_FILTER | \ + NETIF_F_HW_VLAN_CTAG_RX | \ +- NETIF_F_HW_VLAN_CTAG_TX, \ ++ NETIF_F_HW_VLAN_CTAG_TX | \ ++ NETIF_F_GSO_UDP_L4 | \ ++ NETIF_F_GSO_PARTIAL, \ + .hw_priv_flags = IFF_UNICAST_FLT, \ + .flow_control = true, \ + .mtu = HW_ATL_B0_MTU_JUMBO, \ +@@ -533,8 +535,9 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, + + buff = &ring->buff_ring[ring->sw_tail]; + +- if (buff->is_gso) { +- txd->ctl |= HW_ATL_B0_TXD_CTL_CMD_TCP; ++ if (buff->is_gso_tcp || buff->is_gso_udp) { ++ if (buff->is_gso_tcp) ++ txd->ctl |= HW_ATL_B0_TXD_CTL_CMD_TCP; + txd->ctl |= HW_ATL_B0_TXD_CTL_DESC_TYPE_TXC; + txd->ctl |= (buff->len_l3 << 31) | + (buff->len_l2 << 24); +@@ -554,7 +557,7 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, + txd->ctl |= buff->vlan_tx_tag << 4; + is_vlan = true; + } +- if (!buff->is_gso && !buff->is_vlan) { ++ if (!buff->is_gso_tcp && !buff->is_gso_udp && !buff->is_vlan) { + buff_pa_len = buff->len; + + txd->buf_addr = buff->pa; +-- +2.13.6 + diff --git a/SOURCES/0050-netdrv-net-atlantic-change-email-domains-to-Marvell.patch b/SOURCES/0050-netdrv-net-atlantic-change-email-domains-to-Marvell.patch new file mode 100644 index 0000000..174095e --- /dev/null +++ b/SOURCES/0050-netdrv-net-atlantic-change-email-domains-to-Marvell.patch @@ -0,0 +1,62 @@ +From 0a9eaf2afd2d270b088cfaa8b7da2b75bdeaccea Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:07 -0500 +Subject: [PATCH 050/139] [netdrv] net: atlantic: change email domains to + Marvell + +Message-id: <1604687916-15087-51-git-send-email-irusskik@redhat.com> +Patchwork-id: 338476 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 050/139] net: atlantic: change email domains to Marvell +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 362cabda8d4da80152c20e11502ceee6672eb1c1 +Author: Igor Russkikh +Date: Thu Nov 7 22:42:08 2019 +0000 + + net: atlantic: change email domains to Marvell + + Aquantia is now part of Marvell, eventually we'll cease standalone + aquantia.com domain. Thus, change the maintainers file and some other + references to @marvell.com domain + + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/Makefile | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile +index 0020726db204..6e0a6e234483 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/Makefile ++++ b/drivers/net/ethernet/aquantia/atlantic/Makefile +@@ -4,15 +4,8 @@ + # aQuantia Ethernet Controller AQtion Linux Driver + # Copyright(c) 2014-2017 aQuantia Corporation. + # +-# Contact Information: +-# aQuantia Corporation, 105 E. Tasman Dr. San Jose, CA 95134, USA +-# + ################################################################################ + +-# +-# Makefile for the AQtion(tm) Ethernet driver +-# +- + obj-$(CONFIG_AQTION) += atlantic.o + + atlantic-objs := aq_main.o \ +-- +2.13.6 + diff --git a/SOURCES/0051-netdrv-net-atlantic-make-symbol-aq_pm_ops-static.patch b/SOURCES/0051-netdrv-net-atlantic-make-symbol-aq_pm_ops-static.patch new file mode 100644 index 0000000..383a8df --- /dev/null +++ b/SOURCES/0051-netdrv-net-atlantic-make-symbol-aq_pm_ops-static.patch @@ -0,0 +1,57 @@ +From 115e1a8dc328a3c1c4f0b007e1245c62eca3f85d Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:08 -0500 +Subject: [PATCH 051/139] [netdrv] net: atlantic: make symbol 'aq_pm_ops' + static + +Message-id: <1604687916-15087-52-git-send-email-irusskik@redhat.com> +Patchwork-id: 338478 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 051/139] net: atlantic: make symbol 'aq_pm_ops' static +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 0ee0bbb018938addf87b54d447cc5633d2e53490 +Author: zhengbin +Date: Tue Nov 12 14:59:41 2019 +0800 + + net: atlantic: make symbol 'aq_pm_ops' static + + Fix sparse warnings: + + drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c:426:25: warning: symbol 'aq_pm_ops' was not declared. Should it be static? + + Reported-by: Hulk Robot + Fixes: 8aaa112a57c1 ("net: atlantic: refactoring pm logic") + Signed-off-by: zhengbin + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +index a161026cfbfd..2bb329606794 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +@@ -423,7 +423,7 @@ static int aq_pm_resume_restore(struct device *dev) + return atl_resume_common(dev, true); + } + +-const struct dev_pm_ops aq_pm_ops = { ++static const struct dev_pm_ops aq_pm_ops = { + .suspend = aq_pm_suspend_poweroff, + .poweroff = aq_pm_suspend_poweroff, + .freeze = aq_pm_freeze, +-- +2.13.6 + diff --git a/SOURCES/0052-netdrv-net-atlantic-make-function-aq_ethtool_get_pri.patch b/SOURCES/0052-netdrv-net-atlantic-make-function-aq_ethtool_get_pri.patch new file mode 100644 index 0000000..45b3648 --- /dev/null +++ b/SOURCES/0052-netdrv-net-atlantic-make-function-aq_ethtool_get_pri.patch @@ -0,0 +1,66 @@ +From ec26a489ae052876957341c49686c30762e8a532 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:09 -0500 +Subject: [PATCH 052/139] [netdrv] net: atlantic: make function + 'aq_ethtool_get_priv_flags', 'aq_ethtool_set_priv_flags' static + +Message-id: <1604687916-15087-53-git-send-email-irusskik@redhat.com> +Patchwork-id: 338477 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 052/139] net: atlantic: make function 'aq_ethtool_get_priv_flags', 'aq_ethtool_set_priv_flags' static +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 7b094968ccbb55da9e9fa749bdfd9b90b57d64e5 +Author: zhengbin +Date: Tue Nov 12 14:59:42 2019 +0800 + + net: atlantic: make function 'aq_ethtool_get_priv_flags', 'aq_ethtool_set_priv_flags' static + + Fix sparse warnings: + + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c:706:5: warning: symbol 'aq_ethtool_get_priv_flags' was not declared. Should it be static? + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c:713:5: warning: symbol 'aq_ethtool_set_priv_flags' was not declared. Should it be static? + + Reported-by: Hulk Robot + Fixes: ea4b4d7fc106 ("net: atlantic: loopback tests via private flags") + Signed-off-by: zhengbin + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 6353a5c5ed27..a1f99bef4a68 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -703,14 +703,14 @@ static void aq_set_msg_level(struct net_device *ndev, u32 data) + aq_nic->msg_enable = data; + } + +-u32 aq_ethtool_get_priv_flags(struct net_device *ndev) ++static u32 aq_ethtool_get_priv_flags(struct net_device *ndev) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); + + return aq_nic->aq_nic_cfg.priv_flags; + } + +-int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags) ++static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); + struct aq_nic_cfg_s *cfg; +-- +2.13.6 + diff --git a/SOURCES/0053-netdrv-net-atlantic-Signedness-bug-in-aq_vec_isr_leg.patch b/SOURCES/0053-netdrv-net-atlantic-Signedness-bug-in-aq_vec_isr_leg.patch new file mode 100644 index 0000000..b3dcd5c --- /dev/null +++ b/SOURCES/0053-netdrv-net-atlantic-Signedness-bug-in-aq_vec_isr_leg.patch @@ -0,0 +1,64 @@ +From 58eb84b276ca3b724d7a9d25bc52f507c35a3f12 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:10 -0500 +Subject: [PATCH 053/139] [netdrv] net: atlantic: Signedness bug in + aq_vec_isr_legacy() + +Message-id: <1604687916-15087-54-git-send-email-irusskik@redhat.com> +Patchwork-id: 338479 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 053/139] net: atlantic: Signedness bug in aq_vec_isr_legacy() +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit d41378713eef6a7d9d9c30cb9a6181ad72f69596 +Author: Dan Carpenter +Date: Wed Nov 13 21:31:58 2019 +0300 + + net: atlantic: Signedness bug in aq_vec_isr_legacy() + + irqreturn_t type is an enum and in this context it's unsigned, so "err" + can't be irqreturn_t or it breaks the error handling. In fact the "err" + variable is only used to store integers (never irqreturn_t) so it should + be declared as int. + + I removed the initialization because it's not required. Using a bogus + initializer turns off GCC's uninitialized variable warnings. Secondly, + there is a GCC warning about unused assignments and we would like to + enable that feature eventually so we have been trying to remove these + unnecessary initializers. + + Fixes: 7b0c342f1f67 ("net: atlantic: code style cleanup") + Signed-off-by: Dan Carpenter + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +index 6e19e27b6200..f40a427970dc 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +@@ -307,8 +307,8 @@ irqreturn_t aq_vec_isr(int irq, void *private) + irqreturn_t aq_vec_isr_legacy(int irq, void *private) + { + struct aq_vec_s *self = private; +- irqreturn_t err = 0; + u64 irq_mask = 0U; ++ int err; + + if (!self) + return IRQ_NONE; +-- +2.13.6 + diff --git a/SOURCES/0054-netdrv-net-atlantic-broken-link-status-on-old-fw.patch b/SOURCES/0054-netdrv-net-atlantic-broken-link-status-on-old-fw.patch new file mode 100644 index 0000000..51afe1c --- /dev/null +++ b/SOURCES/0054-netdrv-net-atlantic-broken-link-status-on-old-fw.patch @@ -0,0 +1,58 @@ +From 43bf7bf004c384abb26da727b17908407bd09aaa Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:11 -0500 +Subject: [PATCH 054/139] [netdrv] net: atlantic: broken link status on old fw + +Message-id: <1604687916-15087-55-git-send-email-irusskik@redhat.com> +Patchwork-id: 338487 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 054/139] net: atlantic: broken link status on old fw +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit ac70957ee19f198a3884e6f506d75b3f6d8a7dc9 +Author: Igor Russkikh +Date: Mon Jan 6 14:22:28 2020 +0300 + + net: atlantic: broken link status on old fw + + Last code/checkpatch cleanup did a copy paste error where code from + firmware 3 API logic was moved to firmware 1 logic. + + This resulted in FW1.x users would never see the link state as active. + + Fixes: 7b0c342f1f67 ("net: atlantic: code style cleanup") + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 8910b62e67ed..f547baa6c954 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -667,9 +667,7 @@ int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self) + u32 speed; + + mpi_state = hw_atl_utils_mpi_get_state(self); +- speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G | +- FW2X_RATE_2G5 | FW2X_RATE_5G | +- FW2X_RATE_10G); ++ speed = mpi_state >> HW_ATL_MPI_SPEED_SHIFT; + + if (!speed) { + link_status->mbps = 0U; +-- +2.13.6 + diff --git a/SOURCES/0055-netdrv-net-atlantic-loopback-configuration-in-improp.patch b/SOURCES/0055-netdrv-net-atlantic-loopback-configuration-in-improp.patch new file mode 100644 index 0000000..75974f0 --- /dev/null +++ b/SOURCES/0055-netdrv-net-atlantic-loopback-configuration-in-improp.patch @@ -0,0 +1,65 @@ +From 6d9e902625558d33bd9d6b52b53a11793dc14ef8 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:12 -0500 +Subject: [PATCH 055/139] [netdrv] net: atlantic: loopback configuration in + improper place + +Message-id: <1604687916-15087-56-git-send-email-irusskik@redhat.com> +Patchwork-id: 338485 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 055/139] net: atlantic: loopback configuration in improper place +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 883daa1854b61fe3d21d7d9bf2c81d26a07d586b +Author: Igor Russkikh +Date: Mon Jan 6 14:22:29 2020 +0300 + + net: atlantic: loopback configuration in improper place + + Initial loopback configuration should be called earlier, before + starting traffic on HW blocks. Otherwise depending on race conditions + it could be kept disabled. + + Fixes: ea4b4d7fc106 ("net: atlantic: loopback tests via private flags") + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index a17a4da7bc15..c85e3e29012c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -403,6 +403,8 @@ int aq_nic_start(struct aq_nic_s *self) + if (err < 0) + goto err_exit; + ++ aq_nic_set_loopback(self); ++ + err = self->aq_hw_ops->hw_start(self->aq_hw); + if (err < 0) + goto err_exit; +@@ -413,8 +415,6 @@ int aq_nic_start(struct aq_nic_s *self) + + INIT_WORK(&self->service_task, aq_nic_service_task); + +- aq_nic_set_loopback(self); +- + timer_setup(&self->service_timer, aq_nic_service_timer_cb, 0); + aq_nic_service_timer_cb(&self->service_timer); + +-- +2.13.6 + diff --git a/SOURCES/0056-netdrv-net-atlantic-remove-duplicate-entries.patch b/SOURCES/0056-netdrv-net-atlantic-remove-duplicate-entries.patch new file mode 100644 index 0000000..e951cc9 --- /dev/null +++ b/SOURCES/0056-netdrv-net-atlantic-remove-duplicate-entries.patch @@ -0,0 +1,54 @@ +From f7f07fe8710c6c3d67bdfba964466f7ca1deaeec Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:13 -0500 +Subject: [PATCH 056/139] [netdrv] net: atlantic: remove duplicate entries + +Message-id: <1604687916-15087-57-git-send-email-irusskik@redhat.com> +Patchwork-id: 338483 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 056/139] net: atlantic: remove duplicate entries +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit b585f8602acbe2620212cbedc1760906814ff515 +Author: Igor Russkikh +Date: Mon Jan 6 14:22:30 2020 +0300 + + net: atlantic: remove duplicate entries + + Function entries were duplicated accidentally, removing the dups. + + Fixes: ea4b4d7fc106 ("net: atlantic: loopback tests via private flags") + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 58e891af6e09..ec041f78d063 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1525,9 +1525,6 @@ const struct aq_hw_ops hw_atl_ops_b0 = { + .rx_extract_ts = hw_atl_b0_rx_extract_ts, + .extract_hwts = hw_atl_b0_extract_hwts, + .hw_set_offload = hw_atl_b0_hw_offload_set, +- .hw_get_hw_stats = hw_atl_utils_get_hw_stats, +- .hw_get_fw_version = hw_atl_utils_get_fw_version, +- .hw_set_offload = hw_atl_b0_hw_offload_set, + .hw_set_loopback = hw_atl_b0_set_loopback, + .hw_set_fc = hw_atl_b0_set_fc, + }; +-- +2.13.6 + diff --git a/SOURCES/0057-netdrv-net-atlantic-checksum-compat-issue.patch b/SOURCES/0057-netdrv-net-atlantic-checksum-compat-issue.patch new file mode 100644 index 0000000..ec37263 --- /dev/null +++ b/SOURCES/0057-netdrv-net-atlantic-checksum-compat-issue.patch @@ -0,0 +1,118 @@ +From 62d593080703f536164d9840a9fd61fa0d41d607 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:14 -0500 +Subject: [PATCH 057/139] [netdrv] net: atlantic: checksum compat issue + +Message-id: <1604687916-15087-58-git-send-email-irusskik@redhat.com> +Patchwork-id: 338484 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 057/139] net: atlantic: checksum compat issue +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 15beab0a9d797be1b7c67458da007a62269be29a +Author: Dmitry Bezrukov +Date: Fri Feb 14 18:44:51 2020 +0300 + + net: atlantic: checksum compat issue + + Yet another checksum offload compatibility issue was found. + + The known issue is that AQC HW marks tcp packets with 0xFFFF checksum + as invalid (1). This is workarounded in driver, passing all the suspicious + packets up to the stack for further csum validation. + + Another HW problem (2) is that it hides invalid csum of LRO aggregated + packets inside of the individual descriptors. That was workarounded + by forced scan of all LRO descriptors for checksum errors. + + However the scan logic was joint for both LRO and multi-descriptor + packets (jumbos). And this causes the issue. + + We have to drop LRO packets with the detected bad checksum + because of (2), but we have to pass jumbo packets to stack because of (1). + + When using windows tcp partner with jumbo frames but with LSO disabled + driver discards such frames as bad checksummed. But only LRO frames + should be dropped, not jumbos. + + On such a configurations tcp stream have a chance of drops and stucks. + + (1) 76f254d4afe2 ("net: aquantia: tcp checksum 0xffff being handled incorrectly") + (2) d08b9a0a3ebd ("net: aquantia: do not pass lro session with invalid tcp checksum") + + Fixes: d08b9a0a3ebd ("net: aquantia: do not pass lro session with invalid tcp checksum") + Signed-off-by: Dmitry Bezrukov + Signed-off-by: Igor Russkikh + Signed-off-by: Dmitry Bogdanov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 3 ++- + drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 3 ++- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 5 +++-- + 3 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index 951d86f8b66e..6941999ae845 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -351,7 +351,8 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + err = 0; + goto err_exit; + } +- if (buff->is_error || buff->is_cso_err) { ++ if (buff->is_error || ++ (buff->is_lro && buff->is_cso_err)) { + buff_ = buff; + do { + next_ = buff_->next, +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +index 991e4d31b094..2c96f20f6289 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +@@ -78,7 +78,8 @@ struct __packed aq_ring_buff_s { + u32 is_cleaned:1; + u32 is_error:1; + u32 is_vlan:1; +- u32 rsvd3:4; ++ u32 is_lro:1; ++ u32 rsvd3:3; + u16 eop_index; + u16 rsvd4; + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index ec041f78d063..5784da26f868 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -823,6 +823,8 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self, + } + } + ++ buff->is_lro = !!(HW_ATL_B0_RXD_WB_STAT2_RSCCNT & ++ rxd_wb->status); + if (HW_ATL_B0_RXD_WB_STAT2_EOP & rxd_wb->status) { + buff->len = rxd_wb->pkt_len % + AQ_CFG_RX_FRAME_MAX; +@@ -835,8 +837,7 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self, + rxd_wb->pkt_len > AQ_CFG_RX_FRAME_MAX ? + AQ_CFG_RX_FRAME_MAX : rxd_wb->pkt_len; + +- if (HW_ATL_B0_RXD_WB_STAT2_RSCCNT & +- rxd_wb->status) { ++ if (buff->is_lro) { + /* LRO */ + buff->next = rxd_wb->next_desc_ptr; + ++ring->stats.rx.lro_packets; +-- +2.13.6 + diff --git a/SOURCES/0058-netdrv-net-atlantic-check-rpc-result-and-wait-for-rp.patch b/SOURCES/0058-netdrv-net-atlantic-check-rpc-result-and-wait-for-rp.patch new file mode 100644 index 0000000..764d151 --- /dev/null +++ b/SOURCES/0058-netdrv-net-atlantic-check-rpc-result-and-wait-for-rp.patch @@ -0,0 +1,115 @@ +From 593e37a318cc7cb70966663a2840b64429d6da63 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:15 -0500 +Subject: [PATCH 058/139] [netdrv] net: atlantic: check rpc result and wait for + rpc address + +Message-id: <1604687916-15087-59-git-send-email-irusskik@redhat.com> +Patchwork-id: 338481 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 058/139] net: atlantic: check rpc result and wait for rpc address +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit e7b5f97e6574dc4918e375d5f8d24ec31653cd6d +Author: Igor Russkikh +Date: Fri Feb 14 18:44:52 2020 +0300 + + net: atlantic: check rpc result and wait for rpc address + + Artificial HW reliability tests revealed a possible hangup in + the driver. Normally, when device disappears from bus, all + register reads returns 0xFFFFFFFF. + + At remote procedure invocation towards FW there is a logic + where result is compared with -1 in a loop. + That caused an infinite loop if hardware due to some issues + disappears from bus. + + Add extra result checks to prevent this. + + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index f547baa6c954..354705f9bc49 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -22,6 +22,7 @@ + #define HW_ATL_MIF_ADDR 0x0208U + #define HW_ATL_MIF_VAL 0x020CU + ++#define HW_ATL_MPI_RPC_ADDR 0x0334U + #define HW_ATL_RPC_CONTROL_ADR 0x0338U + #define HW_ATL_RPC_STATE_ADR 0x033CU + +@@ -53,15 +54,14 @@ enum mcp_area { + }; + + static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); +- + static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, + enum hal_atl_utils_fw_state_e state); +- + static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self); + static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self); + static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self); + static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self); + static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self); ++static u32 aq_fw1x_rpc_get(struct aq_hw_s *self); + + int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) + { +@@ -476,6 +476,10 @@ static int hw_atl_utils_init_ucp(struct aq_hw_s *self, + self, self->mbox_addr, + self->mbox_addr != 0U, + 1000U, 10000U); ++ err = readx_poll_timeout_atomic(aq_fw1x_rpc_get, self, ++ self->rpc_addr, ++ self->rpc_addr != 0U, ++ 1000U, 100000U); + + return err; + } +@@ -531,6 +535,12 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, + self, fw.val, + sw.tid == fw.tid, + 1000U, 100000U); ++ if (err < 0) ++ goto err_exit; ++ ++ err = aq_hw_err_from_flags(self); ++ if (err < 0) ++ goto err_exit; + + if (fw.len == 0xFFFFU) { + err = hw_atl_utils_fw_rpc_call(self, sw.len); +@@ -1025,6 +1035,11 @@ static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self) + return aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR); + } + ++static u32 aq_fw1x_rpc_get(struct aq_hw_s *self) ++{ ++ return aq_hw_read_reg(self, HW_ATL_MPI_RPC_ADDR); ++} ++ + const struct aq_fw_ops aq_fw_1x_ops = { + .init = hw_atl_utils_mpi_create, + .deinit = hw_atl_fw1x_deinit, +-- +2.13.6 + diff --git a/SOURCES/0059-netdrv-net-atlantic-ptp-gpio-adjustments.patch b/SOURCES/0059-netdrv-net-atlantic-ptp-gpio-adjustments.patch new file mode 100644 index 0000000..e153b57 --- /dev/null +++ b/SOURCES/0059-netdrv-net-atlantic-ptp-gpio-adjustments.patch @@ -0,0 +1,114 @@ +From 8ceaaed2176db0f499c5cddc22181ab081d2568a Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:16 -0500 +Subject: [PATCH 059/139] [netdrv] net: atlantic: ptp gpio adjustments + +Message-id: <1604687916-15087-60-git-send-email-irusskik@redhat.com> +Patchwork-id: 338486 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 059/139] net: atlantic: ptp gpio adjustments +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit f08a464c27ca0a4050333baa271504b27ce834b7 +Author: Egor Pomozov +Date: Fri Feb 14 18:44:53 2020 +0300 + + net: atlantic: ptp gpio adjustments + + Clock adjustment data should be passed to FW as well, otherwise in some + cases a drift was observed when using GPIO features. + + Signed-off-by: Egor Pomozov + Signed-off-by: Igor Russkikh + Signed-off-by: Dmitry Bogdanov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 2 ++ + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 4 +++- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 12 ++++++++++++ + 3 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index e9cf5913b70a..c8d1bb38f746 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -337,6 +337,8 @@ struct aq_fw_ops { + + void (*enable_ptp)(struct aq_hw_s *self, int enable); + ++ void (*adjust_ptp)(struct aq_hw_s *self, uint64_t adj); ++ + int (*set_eee_rate)(struct aq_hw_s *self, u32 speed); + + int (*get_eee_rate)(struct aq_hw_s *self, u32 *rate, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 5784da26f868..9acdb3fbb750 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1162,6 +1162,8 @@ static int hw_atl_b0_adj_sys_clock(struct aq_hw_s *self, s64 delta) + { + self->ptp_clk_offset += delta; + ++ self->aq_fw_ops->adjust_ptp(self, self->ptp_clk_offset); ++ + return 0; + } + +@@ -1212,7 +1214,7 @@ static int hw_atl_b0_gpio_pulse(struct aq_hw_s *self, u32 index, + fwreq.ptp_gpio_ctrl.index = index; + fwreq.ptp_gpio_ctrl.period = period; + /* Apply time offset */ +- fwreq.ptp_gpio_ctrl.start = start - self->ptp_clk_offset; ++ fwreq.ptp_gpio_ctrl.start = start; + + size = sizeof(fwreq.msg_id) + sizeof(fwreq.ptp_gpio_ctrl); + return self->aq_fw_ops->send_fw_request(self, &fwreq, size); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index 97ebf849695f..77a4ed64830f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -30,6 +30,9 @@ + #define HW_ATL_FW3X_EXT_CONTROL_ADDR 0x378 + #define HW_ATL_FW3X_EXT_STATE_ADDR 0x37c + ++#define HW_ATL_FW3X_PTP_ADJ_LSW_ADDR 0x50a0 ++#define HW_ATL_FW3X_PTP_ADJ_MSW_ADDR 0x50a4 ++ + #define HW_ATL_FW2X_CAP_PAUSE BIT(CAPS_HI_PAUSE) + #define HW_ATL_FW2X_CAP_ASYM_PAUSE BIT(CAPS_HI_ASYMMETRIC_PAUSE) + #define HW_ATL_FW2X_CAP_SLEEP_PROXY BIT(CAPS_HI_SLEEP_PROXY) +@@ -475,6 +478,14 @@ static void aq_fw3x_enable_ptp(struct aq_hw_s *self, int enable) + aq_hw_write_reg(self, HW_ATL_FW3X_EXT_CONTROL_ADDR, ptp_opts); + } + ++static void aq_fw3x_adjust_ptp(struct aq_hw_s *self, uint64_t adj) ++{ ++ aq_hw_write_reg(self, HW_ATL_FW3X_PTP_ADJ_LSW_ADDR, ++ (adj >> 0) & 0xffffffff); ++ aq_hw_write_reg(self, HW_ATL_FW3X_PTP_ADJ_MSW_ADDR, ++ (adj >> 32) & 0xffffffff); ++} ++ + static int aq_fw2x_led_control(struct aq_hw_s *self, u32 mode) + { + if (self->fw_ver_actual < HW_ATL_FW_VER_LED) +@@ -633,4 +644,5 @@ const struct aq_fw_ops aq_fw_2x_ops = { + .enable_ptp = aq_fw3x_enable_ptp, + .led_control = aq_fw2x_led_control, + .set_phyloopback = aq_fw2x_set_phyloopback, ++ .adjust_ptp = aq_fw3x_adjust_ptp, + }; +-- +2.13.6 + diff --git a/SOURCES/0060-netdrv-net-atlantic-better-loopback-mode-handling.patch b/SOURCES/0060-netdrv-net-atlantic-better-loopback-mode-handling.patch new file mode 100644 index 0000000..13871af --- /dev/null +++ b/SOURCES/0060-netdrv-net-atlantic-better-loopback-mode-handling.patch @@ -0,0 +1,87 @@ +From a3b77657d4ac7047d28e8fa89375ea4a2d040dc4 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:17 -0500 +Subject: [PATCH 060/139] [netdrv] net: atlantic: better loopback mode handling + +Message-id: <1604687916-15087-61-git-send-email-irusskik@redhat.com> +Patchwork-id: 338488 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 060/139] net: atlantic: better loopback mode handling +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit b42726fcf76e9367e524392e0ead7e672cc0791c +Author: Nikita Danilov +Date: Fri Feb 14 18:44:54 2020 +0300 + + net: atlantic: better loopback mode handling + + Add checks to not enable multiple loopback modes simultaneously, + It was also discovered that for dma loopback to function correctly + promisc mode should be enabled on device. + + Fixes: ea4b4d7fc106 ("net: atlantic: loopback tests via private flags") + Signed-off-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: Dmitry Bogdanov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 5 +++++ + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 13 ++++++++----- + 2 files changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index a1f99bef4a68..7b55633d2cb9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -722,6 +722,11 @@ static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags) + if (flags & ~AQ_PRIV_FLAGS_MASK) + return -EOPNOTSUPP; + ++ if (hweight32((flags | priv_flags) & AQ_HW_LOOPBACK_MASK) > 1) { ++ netdev_info(ndev, "Can't enable more than one loopback simultaneously\n"); ++ return -EINVAL; ++ } ++ + cfg->priv_flags = flags; + + if ((priv_flags ^ flags) & BIT(AQ_HW_LOOPBACK_DMA_NET)) { +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 9acdb3fbb750..d20d91cdece8 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -885,13 +885,16 @@ static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self, + { + struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; + unsigned int i = 0U; ++ u32 vlan_promisc; ++ u32 l2_promisc; + +- hw_atl_rpfl2promiscuous_mode_en_set(self, +- IS_FILTER_ENABLED(IFF_PROMISC)); ++ l2_promisc = IS_FILTER_ENABLED(IFF_PROMISC) || ++ !!(cfg->priv_flags & BIT(AQ_HW_LOOPBACK_DMA_NET)); ++ vlan_promisc = l2_promisc || cfg->is_vlan_force_promisc; + +- hw_atl_rpf_vlan_prom_mode_en_set(self, +- IS_FILTER_ENABLED(IFF_PROMISC) || +- cfg->is_vlan_force_promisc); ++ hw_atl_rpfl2promiscuous_mode_en_set(self, l2_promisc); ++ ++ hw_atl_rpf_vlan_prom_mode_en_set(self, vlan_promisc); + + hw_atl_rpfl2multicast_flr_en_set(self, + IS_FILTER_ENABLED(IFF_ALLMULTI) && +-- +2.13.6 + diff --git a/SOURCES/0061-netdrv-net-atlantic-fix-use-after-free-kasan-warn.patch b/SOURCES/0061-netdrv-net-atlantic-fix-use-after-free-kasan-warn.patch new file mode 100644 index 0000000..a50a5a8 --- /dev/null +++ b/SOURCES/0061-netdrv-net-atlantic-fix-use-after-free-kasan-warn.patch @@ -0,0 +1,86 @@ +From d3f75b38e63b7dc82b0c8befc18dd84665171f8e Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:18 -0500 +Subject: [PATCH 061/139] [netdrv] net: atlantic: fix use after free kasan warn + +Message-id: <1604687916-15087-62-git-send-email-irusskik@redhat.com> +Patchwork-id: 338490 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 061/139] net: atlantic: fix use after free kasan warn +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit a4980919ad6a7be548d499bc5338015e1a9191c6 +Author: Pavel Belous +Date: Fri Feb 14 18:44:55 2020 +0300 + + net: atlantic: fix use after free kasan warn + + skb->len is used to calculate statistics after xmit invocation. + + Under a stress load it may happen that skb will be xmited, + rx interrupt will come and skb will be freed, all before xmit function + is even returned. + + Eventually, skb->len will access unallocated area. + + Moving stats calculation into tx_clean routine. + + Fixes: 018423e90bee ("net: ethernet: aquantia: Add ring support code") + Reported-by: Christophe Vu-Brugier + Signed-off-by: Igor Russkikh + Signed-off-by: Pavel Belous + Signed-off-by: Dmitry Bogdanov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 4 ---- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 7 +++++-- + 2 files changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index c85e3e29012c..263beea1859c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -655,10 +655,6 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) + if (likely(frags)) { + err = self->aq_hw_ops->hw_ring_tx_xmit(self->aq_hw, + ring, frags); +- if (err >= 0) { +- ++ring->stats.tx.packets; +- ring->stats.tx.bytes += skb->len; +- } + } else { + err = NETDEV_TX_BUSY; + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index 6941999ae845..bae95a618560 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -272,9 +272,12 @@ bool aq_ring_tx_clean(struct aq_ring_s *self) + } + } + +- if (unlikely(buff->is_eop)) +- dev_kfree_skb_any(buff->skb); ++ if (unlikely(buff->is_eop)) { ++ ++self->stats.rx.packets; ++ self->stats.tx.bytes += buff->skb->len; + ++ dev_kfree_skb_any(buff->skb); ++ } + buff->pa = 0U; + buff->eop_index = 0xffffU; + self->sw_head = aq_ring_next_dx(self, self->sw_head); +-- +2.13.6 + diff --git a/SOURCES/0062-netdrv-net-atlantic-fix-potential-error-handling.patch b/SOURCES/0062-netdrv-net-atlantic-fix-potential-error-handling.patch new file mode 100644 index 0000000..714be7a --- /dev/null +++ b/SOURCES/0062-netdrv-net-atlantic-fix-potential-error-handling.patch @@ -0,0 +1,62 @@ +From 5877c717b789339f1078213f9b1a4994d5498935 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:19 -0500 +Subject: [PATCH 062/139] [netdrv] net: atlantic: fix potential error handling + +Message-id: <1604687916-15087-63-git-send-email-irusskik@redhat.com> +Patchwork-id: 338505 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 062/139] net: atlantic: fix potential error handling +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 380ec5b9af7f0d57dbf6ac067fd9f33cff2fef71 +Author: Pavel Belous +Date: Fri Feb 14 18:44:56 2020 +0300 + + net: atlantic: fix potential error handling + + Code inspection found that in case of mapping error we do return current + 'ret' value. But beside error, it is used to count number of descriptors + allocated for the packet. In that case map_skb function could return '1'. + + Changing it to return zero (number of mapped descriptors for skb) + + Fixes: 018423e90bee ("net: ethernet: aquantia: Add ring support code") + Signed-off-by: Pavel Belous + Signed-off-by: Igor Russkikh + Signed-off-by: Dmitry Bogdanov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 263beea1859c..e95f6a6bef73 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -533,8 +533,10 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + dx_buff->len, + DMA_TO_DEVICE); + +- if (unlikely(dma_mapping_error(aq_nic_get_dev(self), dx_buff->pa))) ++ if (unlikely(dma_mapping_error(aq_nic_get_dev(self), dx_buff->pa))) { ++ ret = 0; + goto exit; ++ } + + first = dx_buff; + dx_buff->len_pkt = skb->len; +-- +2.13.6 + diff --git a/SOURCES/0063-netdrv-net-atlantic-possible-fault-in-transition-to-.patch b/SOURCES/0063-netdrv-net-atlantic-possible-fault-in-transition-to-.patch new file mode 100644 index 0000000..a500da0 --- /dev/null +++ b/SOURCES/0063-netdrv-net-atlantic-possible-fault-in-transition-to-.patch @@ -0,0 +1,93 @@ +From ef8aa31cd460bd8fa30721b377f2068b03617129 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:20 -0500 +Subject: [PATCH 063/139] [netdrv] net: atlantic: possible fault in transition + to hibernation + +Message-id: <1604687916-15087-64-git-send-email-irusskik@redhat.com> +Patchwork-id: 338489 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 063/139] net: atlantic: possible fault in transition to hibernation +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 52a22f4d6ff95e8bdca557765c04893eb5dd83fd +Author: Pavel Belous +Date: Fri Feb 14 18:44:57 2020 +0300 + + net: atlantic: possible fault in transition to hibernation + + during hibernation freeze, aq_nic_stop could be invoked + on a stopped device. That may cause panic on access to + not yet allocated vector/ring structures. + + Add a check to stop device if it is not yet stopped. + + Similiarly after freeze in hibernation thaw, aq_nic_start + could be invoked on a not initialized net device. + Result will be the same. + + Add a check to start device if it is initialized. + In our case, this is the same as started. + + Fixes: 8aaa112a57c1 ("net: atlantic: refactoring pm logic") + Signed-off-by: Pavel Belous + Signed-off-by: Nikita Danilov + Signed-off-by: Igor Russkikh + Signed-off-by: Dmitry Bogdanov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +index 2bb329606794..f74952674084 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +@@ -359,7 +359,8 @@ static int aq_suspend_common(struct device *dev, bool deep) + netif_device_detach(nic->ndev); + netif_tx_stop_all_queues(nic->ndev); + +- aq_nic_stop(nic); ++ if (netif_running(nic->ndev)) ++ aq_nic_stop(nic); + + if (deep) { + aq_nic_deinit(nic, !nic->aq_hw->aq_nic_cfg->wol); +@@ -375,7 +376,7 @@ static int atl_resume_common(struct device *dev, bool deep) + { + struct pci_dev *pdev = to_pci_dev(dev); + struct aq_nic_s *nic; +- int ret; ++ int ret = 0; + + nic = pci_get_drvdata(pdev); + +@@ -390,9 +391,11 @@ static int atl_resume_common(struct device *dev, bool deep) + goto err_exit; + } + +- ret = aq_nic_start(nic); +- if (ret) +- goto err_exit; ++ if (netif_running(nic->ndev)) { ++ ret = aq_nic_start(nic); ++ if (ret) ++ goto err_exit; ++ } + + netif_device_attach(nic->ndev); + netif_tx_start_all_queues(nic->ndev); +-- +2.13.6 + diff --git a/SOURCES/0064-netdrv-net-atlantic-fix-out-of-range-usage-of-active.patch b/SOURCES/0064-netdrv-net-atlantic-fix-out-of-range-usage-of-active.patch new file mode 100644 index 0000000..77315e0 --- /dev/null +++ b/SOURCES/0064-netdrv-net-atlantic-fix-out-of-range-usage-of-active.patch @@ -0,0 +1,57 @@ +From 8075ce5872ceed25476fbb740b58eb7e25eedb79 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:21 -0500 +Subject: [PATCH 064/139] [netdrv] net: atlantic: fix out of range usage of + active_vlans array + +Message-id: <1604687916-15087-65-git-send-email-irusskik@redhat.com> +Patchwork-id: 338491 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 064/139] net: atlantic: fix out of range usage of active_vlans array +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 5a292c89a84d49b598f8978f154bdda48b1072c0 +Author: Dmitry Bogdanov +Date: Fri Feb 14 18:44:58 2020 +0300 + + net: atlantic: fix out of range usage of active_vlans array + + fix static checker warning: + drivers/net/ethernet/aquantia/atlantic/aq_filters.c:166 aq_check_approve_fvlan() + error: passing untrusted data to 'test_bit()' + + Reported-by: Dan Carpenter + Fixes: 7975d2aff5af: ("net: aquantia: add support of rx-vlan-filter offload") + Signed-off-by: Dmitry Bogdanov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_filters.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c +index 6102251bb909..03ff92bc4a7f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c +@@ -163,7 +163,7 @@ aq_check_approve_fvlan(struct aq_nic_s *aq_nic, + } + + if ((aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) && +- (!test_bit(be16_to_cpu(fsp->h_ext.vlan_tci), ++ (!test_bit(be16_to_cpu(fsp->h_ext.vlan_tci) & VLAN_VID_MASK, + aq_nic->active_vlans))) { + netdev_err(aq_nic->ndev, + "ethtool: unknown vlan-id specified"); +-- +2.13.6 + diff --git a/SOURCES/0065-netdrv-net-aquantia-Delete-module-version.patch b/SOURCES/0065-netdrv-net-aquantia-Delete-module-version.patch new file mode 100644 index 0000000..5f3b89d --- /dev/null +++ b/SOURCES/0065-netdrv-net-aquantia-Delete-module-version.patch @@ -0,0 +1,120 @@ +From 8b5c0190d2a50034acdfc2088998d318470ae7e7 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:22 -0500 +Subject: [PATCH 065/139] [netdrv] net/aquantia: Delete module version + +Message-id: <1604687916-15087-66-git-send-email-irusskik@redhat.com> +Patchwork-id: 338492 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 065/139] net/aquantia: Delete module version +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 0d8c4becb40d78e480b131bca934692196c33542 +Author: Leon Romanovsky +Date: Mon Feb 24 10:53:09 2020 +0200 + + net/aquantia: Delete module version + + There is no need to keep module and driver versions in in-tree + kernel code. + + Signed-off-by: Leon Romanovsky + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_cfg.h | 4 ---- + drivers/net/ethernet/aquantia/atlantic/aq_common.h | 1 - + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 1 - + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 1 - + drivers/net/ethernet/aquantia/atlantic/ver.h | 12 ------------ + 5 files changed, 19 deletions(-) + delete mode 100644 drivers/net/ethernet/aquantia/atlantic/ver.h + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +index f0c41f7408e5..7560f5506e55 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +@@ -9,8 +9,6 @@ + #ifndef AQ_CFG_H + #define AQ_CFG_H + +-#include +- + #define AQ_CFG_VECS_DEF 8U + #define AQ_CFG_TCS_DEF 1U + +@@ -85,7 +83,5 @@ + #define AQ_CFG_DRV_AUTHOR "aQuantia" + #define AQ_CFG_DRV_DESC "aQuantia Corporation(R) Network Driver" + #define AQ_CFG_DRV_NAME "atlantic" +-#define AQ_CFG_DRV_VERSION UTS_RELEASE \ +- AQ_CFG_DRV_VERSION_SUFFIX + + #endif /* AQ_CFG_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +index 42ea8d8daa46..c8c402b013bb 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +@@ -12,7 +12,6 @@ + #include + #include + #include +-#include "ver.h" + #include "aq_cfg.h" + #include "aq_utils.h" + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 7b55633d2cb9..0bdaa0d785b7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -132,7 +132,6 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev, + regs_count = aq_nic_get_regs_count(aq_nic); + + strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver)); +- strlcat(drvinfo->version, AQ_CFG_DRV_VERSION, sizeof(drvinfo->version)); + + snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), + "%u.%u.%u", firmware_version >> 24, +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index 538f460a3da7..9fcab646cbd5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -19,7 +19,6 @@ + #include + + MODULE_LICENSE("GPL v2"); +-MODULE_VERSION(AQ_CFG_DRV_VERSION); + MODULE_AUTHOR(AQ_CFG_DRV_AUTHOR); + MODULE_DESCRIPTION(AQ_CFG_DRV_DESC); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/ver.h b/drivers/net/ethernet/aquantia/atlantic/ver.h +deleted file mode 100644 +index 597654b51e01..000000000000 +--- a/drivers/net/ethernet/aquantia/atlantic/ver.h ++++ /dev/null +@@ -1,12 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved +- */ +- +-#ifndef VER_H +-#define VER_H +- +-#define AQ_CFG_DRV_VERSION_SUFFIX "-kern" +- +-#endif /* VER_H */ +-- +2.13.6 + diff --git a/SOURCES/0066-netdrv-net-atlantic-Replace-zero-length-array-with-f.patch b/SOURCES/0066-netdrv-net-atlantic-Replace-zero-length-array-with-f.patch new file mode 100644 index 0000000..224df86 --- /dev/null +++ b/SOURCES/0066-netdrv-net-atlantic-Replace-zero-length-array-with-f.patch @@ -0,0 +1,79 @@ +From c2bb6fc3b953ff2e6ceb79ef305a5c461e835e82 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:23 -0500 +Subject: [PATCH 066/139] [netdrv] net: atlantic: Replace zero-length array + with flexible-array member + +Message-id: <1604687916-15087-67-git-send-email-irusskik@redhat.com> +Patchwork-id: 338493 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 066/139] net: atlantic: Replace zero-length array with flexible-array member +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 0fcf4666431fcc42e96c48d72a56b284c30d6254 +Author: Gustavo A. R. Silva +Date: Mon Mar 2 06:19:53 2020 -0600 + + net: atlantic: Replace zero-length array with flexible-array member + + The current codebase makes use of the zero-length array language + extension to the C90 standard, but the preferred mechanism to declare + variable-length types such as these ones is a flexible array member[1][2], + introduced in C99: + + struct foo { + int stuff; + struct boo array[]; + }; + + By making use of the mechanism above, we will get a compiler warning + in case the flexible array does not occur last in the structure, which + will help us prevent some kind of undefined behavior bugs from being + inadvertently introduced[3] to the codebase from now on. + + Also, notice that, dynamic memory allocations won't be affected by + this change: + + "Flexible array members have incomplete type, and so the sizeof operator + may not be applied. As a quirk of the original implementation of + zero-length arrays, sizeof evaluates to zero."[1] + + This issue was found with the help of Coccinelle. + + [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html + [2] https://github.com/KSPP/linux/issues/21 + [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") + + Signed-off-by: Gustavo A. R. Silva + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index 42f0c5c6ec2d..6b4f701e7006 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -225,7 +225,7 @@ struct __packed offload_info { + struct offload_port_info ports; + struct offload_ka_info kas; + struct offload_rr_info rrs; +- u8 buf[0]; ++ u8 buf[]; + }; + + struct __packed hw_atl_utils_fw_rpc { +-- +2.13.6 + diff --git a/SOURCES/0067-netdrv-net-aquantia-reject-all-unsupported-coalescin.patch b/SOURCES/0067-netdrv-net-aquantia-reject-all-unsupported-coalescin.patch new file mode 100644 index 0000000..c7bcc84 --- /dev/null +++ b/SOURCES/0067-netdrv-net-aquantia-reject-all-unsupported-coalescin.patch @@ -0,0 +1,79 @@ +From 1349f2eaab8ceb587fa183f9f61ecd7021798ae8 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:24 -0500 +Subject: [PATCH 067/139] [netdrv] net: aquantia: reject all unsupported + coalescing params + +Message-id: <1604687916-15087-68-git-send-email-irusskik@redhat.com> +Patchwork-id: 338494 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 067/139] net: aquantia: reject all unsupported coalescing params +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit fcca747f1800931015d359be48065755ef5c3f25 +Author: Jakub Kicinski +Date: Mon Mar 9 19:14:59 2020 -0700 + + net: aquantia: reject all unsupported coalescing params + + Set ethtool_ops->supported_coalesce_params to let + the core reject unsupported coalescing parameters. + + This driver only rejected some of the unsupported parameters. + + Signed-off-by: Jakub Kicinski + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 15 +++------------ + 1 file changed, 3 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 0bdaa0d785b7..6781256a318a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -386,21 +386,10 @@ static int aq_ethtool_set_coalesce(struct net_device *ndev, + + cfg = aq_nic_get_cfg(aq_nic); + +- /* This is not yet supported +- */ +- if (coal->use_adaptive_rx_coalesce || coal->use_adaptive_tx_coalesce) +- return -EOPNOTSUPP; +- + /* Atlantic only supports timing based coalescing + */ + if (coal->rx_max_coalesced_frames > 1 || +- coal->rx_coalesce_usecs_irq || +- coal->rx_max_coalesced_frames_irq) +- return -EOPNOTSUPP; +- +- if (coal->tx_max_coalesced_frames > 1 || +- coal->tx_coalesce_usecs_irq || +- coal->tx_max_coalesced_frames_irq) ++ coal->tx_max_coalesced_frames > 1) + return -EOPNOTSUPP; + + /* We do not support frame counting. Check this +@@ -742,6 +731,8 @@ static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags) + } + + const struct ethtool_ops aq_ethtool_ops = { ++ .supported_coalesce_params = ETHTOOL_COALESCE_USECS | ++ ETHTOOL_COALESCE_MAX_FRAMES, + .get_link = aq_ethtool_get_link, + .get_regs_len = aq_ethtool_get_regs_len, + .get_regs = aq_ethtool_get_regs, +-- +2.13.6 + diff --git a/SOURCES/0068-netdrv-net-atlantic-MACSec-offload-statistics-implem.patch b/SOURCES/0068-netdrv-net-atlantic-MACSec-offload-statistics-implem.patch new file mode 100644 index 0000000..fac4361 --- /dev/null +++ b/SOURCES/0068-netdrv-net-atlantic-MACSec-offload-statistics-implem.patch @@ -0,0 +1,158 @@ +From 65ee75983ccc5253adadd1b8cc7a16c360a55248 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:25 -0500 +Subject: [PATCH 068/139] [netdrv] net: atlantic: MACSec offload statistics + implementation + +Message-id: <1604687916-15087-69-git-send-email-irusskik@redhat.com> +Patchwork-id: 338495 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 068/139] net: atlantic: MACSec offload statistics implementation +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 +Conflict: merging only refactoring of stats. actual macsec offload code +is skipped + +commit aec0f1aac58e81e88efe381dc5813e2e4d2858f2 +Author: Dmitry Bogdanov +Date: Wed Mar 25 15:52:45 2020 +0300 + + net: atlantic: MACSec offload statistics implementation + + This patch adds support for MACSec statistics on Atlantic network cards. + + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 31 ++++++++++------------ + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 5 +++- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 2 +- + 3 files changed, 19 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 6781256a318a..77a855314b4c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -104,18 +104,23 @@ static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = { + "PHYExternalLoopback", + }; + ++static u32 aq_ethtool_n_stats(struct net_device *ndev) ++{ ++ struct aq_nic_s *nic = netdev_priv(ndev); ++ struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic); ++ u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) + ++ ARRAY_SIZE(aq_ethtool_queue_stat_names) * cfg->vecs; ++ ++ return n_stats; ++} ++ + static void aq_ethtool_stats(struct net_device *ndev, + struct ethtool_stats *stats, u64 *data) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg; +- +- cfg = aq_nic_get_cfg(aq_nic); + +- memset(data, 0, (ARRAY_SIZE(aq_ethtool_stat_names) + +- ARRAY_SIZE(aq_ethtool_queue_stat_names) * +- cfg->vecs) * sizeof(u64)); +- aq_nic_get_stats(aq_nic, data); ++ memset(data, 0, aq_ethtool_n_stats(ndev) * sizeof(u64)); ++ data = aq_nic_get_stats(aq_nic, data); + } + + static void aq_ethtool_get_drvinfo(struct net_device *ndev, +@@ -123,11 +128,9 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev, + { + struct pci_dev *pdev = to_pci_dev(ndev->dev.parent); + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg; + u32 firmware_version; + u32 regs_count; + +- cfg = aq_nic_get_cfg(aq_nic); + firmware_version = aq_nic_get_fw_version(aq_nic); + regs_count = aq_nic_get_regs_count(aq_nic); + +@@ -139,8 +142,7 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev, + + strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "", + sizeof(drvinfo->bus_info)); +- drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) + +- cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names); ++ drvinfo->n_stats = aq_ethtool_n_stats(ndev); + drvinfo->testinfo_len = 0; + drvinfo->regdump_len = regs_count; + drvinfo->eedump_len = 0; +@@ -209,16 +211,11 @@ static int aq_ethtool_set_phys_id(struct net_device *ndev, + + static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset) + { +- struct aq_nic_s *aq_nic = netdev_priv(ndev); +- struct aq_nic_cfg_s *cfg; + int ret = 0; + +- cfg = aq_nic_get_cfg(aq_nic); +- + switch (stringset) { + case ETH_SS_STATS: +- ret = ARRAY_SIZE(aq_ethtool_stat_names) + +- cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names); ++ ret = aq_ethtool_n_stats(ndev); + break; + case ETH_SS_PRIV_FLAGS: + ret = ARRAY_SIZE(aq_ethtool_priv_flag_names); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index e95f6a6bef73..b478becc68b2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -765,7 +765,7 @@ int aq_nic_get_regs_count(struct aq_nic_s *self) + return self->aq_nic_cfg.aq_hw_caps->mac_regs_count; + } + +-void aq_nic_get_stats(struct aq_nic_s *self, u64 *data) ++u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data) + { + struct aq_vec_s *aq_vec = NULL; + struct aq_stats_s *stats; +@@ -815,7 +815,10 @@ void aq_nic_get_stats(struct aq_nic_s *self, u64 *data) + aq_vec_get_sw_stats(aq_vec, data, &count); + } + ++ data += count; ++ + err_exit:; ++ return data; + } + + static void aq_nic_update_ndev_stats(struct aq_nic_s *self) +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index a752f8bb4b08..26436671c474 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -154,7 +154,7 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb); + int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p); + int aq_nic_get_regs_count(struct aq_nic_s *self); +-void aq_nic_get_stats(struct aq_nic_s *self, u64 *data); ++u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data); + int aq_nic_stop(struct aq_nic_s *self); + void aq_nic_deinit(struct aq_nic_s *self, bool link_down); + void aq_nic_set_power(struct aq_nic_s *self); +-- +2.13.6 + diff --git a/SOURCES/0069-netdrv-aquantia-Fix-the-media-type-of-AQC100-etherne.patch b/SOURCES/0069-netdrv-aquantia-Fix-the-media-type-of-AQC100-etherne.patch new file mode 100644 index 0000000..1dfcf49 --- /dev/null +++ b/SOURCES/0069-netdrv-aquantia-Fix-the-media-type-of-AQC100-etherne.patch @@ -0,0 +1,57 @@ +From 175e23f18bc3b0b8e36e0bcca2b9c242224ee37c Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:26 -0500 +Subject: [PATCH 069/139] [netdrv] aquantia: Fix the media type of AQC100 + ethernet controller in the driver + +Message-id: <1604687916-15087-70-git-send-email-irusskik@redhat.com> +Patchwork-id: 338496 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 069/139] aquantia: Fix the media type of AQC100 ethernet controller in the driver +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 6de556c31061e3b9c36546ffaaac5fdb679a2f14 +Author: Richard Clark +Date: Sat Apr 25 08:58:11 2020 +0800 + + aquantia: Fix the media type of AQC100 ethernet controller in the driver + + The Aquantia AQC100 controller enables a SFP+ port, so the driver should + configure the media type as '_TYPE_FIBRE' instead of '_TYPE_TP'. + + Signed-off-by: Richard Clark + Cc: Igor Russkikh + Cc: "David S. Miller" + Acked-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +index f74952674084..83b1b3585d09 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +@@ -56,7 +56,7 @@ static const struct aq_board_revision_s hw_atl_boards[] = { + { AQ_DEVICE_ID_D108, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc108, }, + { AQ_DEVICE_ID_D109, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc109, }, + +- { AQ_DEVICE_ID_AQC100, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, }, ++ { AQ_DEVICE_ID_AQC100, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc100, }, + { AQ_DEVICE_ID_AQC107, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, }, + { AQ_DEVICE_ID_AQC108, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc108, }, + { AQ_DEVICE_ID_AQC109, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109, }, +-- +2.13.6 + diff --git a/SOURCES/0070-netdrv-net-atlantic-update-company-name-in-the-drive.patch b/SOURCES/0070-netdrv-net-atlantic-update-company-name-in-the-drive.patch new file mode 100644 index 0000000..1107c0c --- /dev/null +++ b/SOURCES/0070-netdrv-net-atlantic-update-company-name-in-the-drive.patch @@ -0,0 +1,70 @@ +From 6a4f9fb9f5fedc14d5b85bea0eebf9e36d0305db Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:27 -0500 +Subject: [PATCH 070/139] [netdrv] net: atlantic: update company name in the + driver description + +Message-id: <1604687916-15087-71-git-send-email-irusskik@redhat.com> +Patchwork-id: 338497 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 070/139] net: atlantic: update company name in the driver description +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit fe677b057e33a0345570064c0d82ef6956b005d6 +Author: Igor Russkikh +Date: Thu Apr 30 11:04:29 2020 +0300 + + net: atlantic: update company name in the driver description + + Aquantia is now part of Marvell. Thus, update the driver description. + + Signed-off-by: Igor Russkikh + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_cfg.h | 4 ++-- + drivers/net/ethernet/aquantia/atlantic/aq_common.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +index 7560f5506e55..52b9833fda99 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +@@ -80,8 +80,8 @@ + + #define AQ_CFG_LOCK_TRYS 100U + +-#define AQ_CFG_DRV_AUTHOR "aQuantia" +-#define AQ_CFG_DRV_DESC "aQuantia Corporation(R) Network Driver" ++#define AQ_CFG_DRV_AUTHOR "Marvell" ++#define AQ_CFG_DRV_DESC "Marvell (Aquantia) Corporation(R) Network Driver" + #define AQ_CFG_DRV_NAME "atlantic" + + #endif /* AQ_CFG_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +index c8c402b013bb..d5beb798bab6 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +@@ -37,7 +37,7 @@ + #define AQ_DEVICE_ID_AQC111S 0x91B1 + #define AQ_DEVICE_ID_AQC112S 0x92B1 + +-#define HW_ATL_NIC_NAME "aQuantia AQtion 10Gbit Network Adapter" ++#define HW_ATL_NIC_NAME "Marvell (aQuantia) AQtion 10Gbit Network Adapter" + + #define AQ_HWREV_ANY 0 + #define AQ_HWREV_1 1 +-- +2.13.6 + diff --git a/SOURCES/0071-netdrv-net-atlantic-add-A2-device-IDs.patch b/SOURCES/0071-netdrv-net-atlantic-add-A2-device-IDs.patch new file mode 100644 index 0000000..3bbff0e --- /dev/null +++ b/SOURCES/0071-netdrv-net-atlantic-add-A2-device-IDs.patch @@ -0,0 +1,58 @@ +From 345e431b62606092d9eb6aabe60f8aad16205329 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:28 -0500 +Subject: [PATCH 071/139] [netdrv] net: atlantic: add A2 device IDs + +Message-id: <1604687916-15087-72-git-send-email-irusskik@redhat.com> +Patchwork-id: 338565 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 071/139] net: atlantic: add A2 device IDs +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 98c4353c5add3cb2bbb3c2da1cbd7fd2d09f396b +Author: Igor Russkikh +Date: Thu Apr 30 11:04:30 2020 +0300 + + net: atlantic: add A2 device IDs + + Adding device ids for the new generation of atlantic nic. + + Signed-off-by: Igor Russkikh + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_common.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +index d5beb798bab6..1261e7c7a01e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +@@ -37,6 +37,13 @@ + #define AQ_DEVICE_ID_AQC111S 0x91B1 + #define AQ_DEVICE_ID_AQC112S 0x92B1 + ++#define AQ_DEVICE_ID_AQC113DEV 0x00C0 ++#define AQ_DEVICE_ID_AQC113CS 0x94C0 ++#define AQ_DEVICE_ID_AQC114CS 0x93C0 ++#define AQ_DEVICE_ID_AQC113 0x04C0 ++#define AQ_DEVICE_ID_AQC113C 0x14C0 ++#define AQ_DEVICE_ID_AQC115C 0x12C0 ++ + #define HW_ATL_NIC_NAME "Marvell (aQuantia) AQtion 10Gbit Network Adapter" + + #define AQ_HWREV_ANY 0 +-- +2.13.6 + diff --git a/SOURCES/0072-netdrv-net-atlantic-add-defines-for-10M-and-EEE-100M.patch b/SOURCES/0072-netdrv-net-atlantic-add-defines-for-10M-and-EEE-100M.patch new file mode 100644 index 0000000..ee30300 --- /dev/null +++ b/SOURCES/0072-netdrv-net-atlantic-add-defines-for-10M-and-EEE-100M.patch @@ -0,0 +1,131 @@ +From 789d2f5eb69fede53fd247b3e1c594499603f05e Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:29 -0500 +Subject: [PATCH 072/139] [netdrv] net: atlantic: add defines for 10M and EEE + 100M link mode + +Message-id: <1604687916-15087-73-git-send-email-irusskik@redhat.com> +Patchwork-id: 338500 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 072/139] net: atlantic: add defines for 10M and EEE 100M link mode +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 3d464aadef75415c55a5a4feb611a9bbf034d7d3 +Author: Igor Russkikh +Date: Thu Apr 30 11:04:31 2020 +0300 + + net: atlantic: add defines for 10M and EEE 100M link mode + + This patch adds defines for 10M and EEE 100M link modes, which are + supported by A2. + + 10M support is added in this patch series. + EEE is out of scope, but will be added in a follow-up series. + + Signed-off-by: Igor Russkikh + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_common.h | 22 ++++++++++++---------- + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 3 +++ + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 12 ++++++++++++ + 3 files changed, 27 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +index 1261e7c7a01e..53620ba6d7a6 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +@@ -50,16 +50,18 @@ + #define AQ_HWREV_1 1 + #define AQ_HWREV_2 2 + +-#define AQ_NIC_RATE_10G BIT(0) +-#define AQ_NIC_RATE_5G BIT(1) +-#define AQ_NIC_RATE_5GSR BIT(2) +-#define AQ_NIC_RATE_2GS BIT(3) +-#define AQ_NIC_RATE_1G BIT(4) +-#define AQ_NIC_RATE_100M BIT(5) ++#define AQ_NIC_RATE_10G BIT(0) ++#define AQ_NIC_RATE_5G BIT(1) ++#define AQ_NIC_RATE_5GSR BIT(2) ++#define AQ_NIC_RATE_2GS BIT(3) ++#define AQ_NIC_RATE_1G BIT(4) ++#define AQ_NIC_RATE_100M BIT(5) ++#define AQ_NIC_RATE_10M BIT(6) + +-#define AQ_NIC_RATE_EEE_10G BIT(6) +-#define AQ_NIC_RATE_EEE_5G BIT(7) +-#define AQ_NIC_RATE_EEE_2GS BIT(8) +-#define AQ_NIC_RATE_EEE_1G BIT(9) ++#define AQ_NIC_RATE_EEE_10G BIT(7) ++#define AQ_NIC_RATE_EEE_5G BIT(8) ++#define AQ_NIC_RATE_EEE_2GS BIT(9) ++#define AQ_NIC_RATE_EEE_1G BIT(10) ++#define AQ_NIC_RATE_EEE_100M BIT(11) + + #endif /* AQ_COMMON_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 77a855314b4c..46e8a17e7131 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -482,6 +482,9 @@ static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed) + if (speed & AQ_NIC_RATE_EEE_1G) + rate |= SUPPORTED_1000baseT_Full; + ++ if (speed & AQ_NIC_RATE_EEE_100M) ++ rate |= SUPPORTED_100baseT_Full; ++ + return rate; + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index b478becc68b2..4b8ee15c76f1 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -869,6 +869,10 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, + ethtool_link_ksettings_add_link_mode(cmd, supported, + 100baseT_Full); + ++ if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_10M) ++ ethtool_link_ksettings_add_link_mode(cmd, supported, ++ 10baseT_Full); ++ + if (self->aq_nic_cfg.aq_hw_caps->flow_control) { + ethtool_link_ksettings_add_link_mode(cmd, supported, + Pause); +@@ -908,6 +912,10 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 100baseT_Full); + ++ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10M) ++ ethtool_link_ksettings_add_link_mode(cmd, advertising, ++ 10baseT_Full); ++ + if (self->aq_nic_cfg.fc.cur & AQ_NIC_FC_RX) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + Pause); +@@ -938,6 +946,10 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self, + speed = cmd->base.speed; + + switch (speed) { ++ case SPEED_10: ++ rate = AQ_NIC_RATE_10M; ++ break; ++ + case SPEED_100: + rate = AQ_NIC_RATE_100M; + break; +-- +2.13.6 + diff --git a/SOURCES/0073-netdrv-net-atlantic-add-hw_soft_reset-hw_prepare-to-.patch b/SOURCES/0073-netdrv-net-atlantic-add-hw_soft_reset-hw_prepare-to-.patch new file mode 100644 index 0000000..7983bd8 --- /dev/null +++ b/SOURCES/0073-netdrv-net-atlantic-add-hw_soft_reset-hw_prepare-to-.patch @@ -0,0 +1,138 @@ +From 48661c3c86ef32cdfda6f4dcc878b340afb4fa69 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:30 -0500 +Subject: [PATCH 073/139] [netdrv] net: atlantic: add hw_soft_reset, hw_prepare + to hw_ops + +Message-id: <1604687916-15087-74-git-send-email-irusskik@redhat.com> +Patchwork-id: 338498 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 073/139] net: atlantic: add hw_soft_reset, hw_prepare to hw_ops +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 099d074e3f0cd3f48e57e3349b9f8a25b0e3feb8 +Author: Mark Starovoytov +Date: Thu Apr 30 11:04:32 2020 +0300 + + net: atlantic: add hw_soft_reset, hw_prepare to hw_ops + + A2 will have a different implementation of these 2 APIs, so + this patch moves them to hw_ops in preparation for A2. + + Signed-off-by: Mark Starovoytov + Co-developed-by: Dmitry Bezrukov + Signed-off-by: Dmitry Bezrukov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 5 +++++ + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 16 +++++++++++++++- + .../net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 2 ++ + .../net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 2 ++ + .../net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c | 4 ---- + 5 files changed, 24 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index c8d1bb38f746..fda665280937 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -182,6 +182,11 @@ struct aq_hw_ops { + + int (*hw_set_mac_address)(struct aq_hw_s *self, u8 *mac_addr); + ++ int (*hw_soft_reset)(struct aq_hw_s *self); ++ ++ int (*hw_prepare)(struct aq_hw_s *self, ++ const struct aq_fw_ops **fw_ops); ++ + int (*hw_reset)(struct aq_hw_s *self); + + int (*hw_init)(struct aq_hw_s *self, u8 *mac_addr); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 4b8ee15c76f1..69016ae108b2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -249,6 +249,20 @@ static void aq_nic_polling_timer_cb(struct timer_list *t) + AQ_CFG_POLLING_TIMER_INTERVAL); + } + ++static int aq_nic_hw_prepare(struct aq_nic_s *self) ++{ ++ int err = 0; ++ ++ err = self->aq_hw_ops->hw_soft_reset(self->aq_hw); ++ if (err) ++ goto exit; ++ ++ err = self->aq_hw_ops->hw_prepare(self->aq_hw, &self->aq_fw_ops); ++ ++exit: ++ return err; ++} ++ + int aq_nic_ndev_register(struct aq_nic_s *self) + { + int err = 0; +@@ -258,7 +272,7 @@ int aq_nic_ndev_register(struct aq_nic_s *self) + goto err_exit; + } + +- err = hw_atl_utils_initfw(self->aq_hw, &self->aq_fw_ops); ++ err = aq_nic_hw_prepare(self); + if (err) + goto err_exit; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index 9b1062b8af64..2dba8c277ecb 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -886,6 +886,8 @@ static int hw_atl_a0_hw_ring_rx_stop(struct aq_hw_s *self, + } + + const struct aq_hw_ops hw_atl_ops_a0 = { ++ .hw_soft_reset = hw_atl_utils_soft_reset, ++ .hw_prepare = hw_atl_utils_initfw, + .hw_set_mac_address = hw_atl_a0_hw_mac_addr_set, + .hw_init = hw_atl_a0_hw_init, + .hw_reset = hw_atl_a0_hw_reset, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index d20d91cdece8..4e2e4eef028d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1478,6 +1478,8 @@ static int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable) + } + + const struct aq_hw_ops hw_atl_ops_b0 = { ++ .hw_soft_reset = hw_atl_utils_soft_reset, ++ .hw_prepare = hw_atl_utils_initfw, + .hw_set_mac_address = hw_atl_b0_hw_mac_addr_set, + .hw_init = hw_atl_b0_hw_init, + .hw_reset = hw_atl_b0_hw_reset, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 354705f9bc49..7259bcb81e9b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -67,10 +67,6 @@ int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) + { + int err = 0; + +- err = hw_atl_utils_soft_reset(self); +- if (err) +- return err; +- + hw_atl_utils_hw_chip_features_init(self, + &self->chip_features); + +-- +2.13.6 + diff --git a/SOURCES/0074-netdrv-net-atlantic-simplify-hw_get_fw_version-usage.patch b/SOURCES/0074-netdrv-net-atlantic-simplify-hw_get_fw_version-usage.patch new file mode 100644 index 0000000..4ca49cb --- /dev/null +++ b/SOURCES/0074-netdrv-net-atlantic-simplify-hw_get_fw_version-usage.patch @@ -0,0 +1,115 @@ +From ba4ed1ff3c457654440d3460e3da4fe99d4a775e Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:31 -0500 +Subject: [PATCH 074/139] [netdrv] net: atlantic: simplify hw_get_fw_version() + usage + +Message-id: <1604687916-15087-75-git-send-email-irusskik@redhat.com> +Patchwork-id: 338499 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 074/139] net: atlantic: simplify hw_get_fw_version() usage +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 36e90a5297ea02c67c0f17d8b39eb9ceb93dd6f0 +Author: Nikita Danilov +Date: Thu Apr 30 11:04:33 2020 +0300 + + net: atlantic: simplify hw_get_fw_version() usage + + hw_get_fw_version() never fails, so this patch simplifies its + usage by utilizing return value instead of output argument. + + Signed-off-by: Nikita Danilov + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 2 +- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 6 +----- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c | 8 +++----- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h | 2 +- + 4 files changed, 6 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index fda665280937..e7a253667336 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -259,7 +259,7 @@ struct aq_hw_ops { + + struct aq_stats_s *(*hw_get_hw_stats)(struct aq_hw_s *self); + +- int (*hw_get_fw_version)(struct aq_hw_s *self, u32 *fw_version); ++ u32 (*hw_get_fw_version)(struct aq_hw_s *self); + + int (*hw_set_offload)(struct aq_hw_s *self, + struct aq_nic_cfg_s *aq_nic_cfg); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 69016ae108b2..6d02e40b43a4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -1016,11 +1016,7 @@ struct aq_nic_cfg_s *aq_nic_get_cfg(struct aq_nic_s *self) + + u32 aq_nic_get_fw_version(struct aq_nic_s *self) + { +- u32 fw_version = 0U; +- +- self->aq_hw_ops->hw_get_fw_version(self->aq_hw, &fw_version); +- +- return fw_version; ++ return self->aq_hw_ops->hw_get_fw_version(self->aq_hw); + } + + int aq_nic_set_loopback(struct aq_nic_s *self) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 7259bcb81e9b..bd1712ca9ef2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -70,7 +70,7 @@ int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) + hw_atl_utils_hw_chip_features_init(self, + &self->chip_features); + +- hw_atl_utils_get_fw_version(self, &self->fw_ver_actual); ++ self->fw_ver_actual = hw_atl_utils_get_fw_version(self); + + if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, + self->fw_ver_actual) == 0) { +@@ -915,11 +915,9 @@ int hw_atl_utils_hw_get_regs(struct aq_hw_s *self, + return 0; + } + +-int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version) ++u32 hw_atl_utils_get_fw_version(struct aq_hw_s *self) + { +- *fw_version = aq_hw_read_reg(self, 0x18U); +- +- return 0; ++ return aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION); + } + + static int aq_fw1x_set_wake_magic(struct aq_hw_s *self, bool wol_enabled, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index 6b4f701e7006..ed3f0307652d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -587,7 +587,7 @@ int hw_atl_utils_hw_set_power(struct aq_hw_s *self, + + int hw_atl_utils_hw_deinit(struct aq_hw_s *self); + +-int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version); ++u32 hw_atl_utils_get_fw_version(struct aq_hw_s *self); + + int hw_atl_utils_update_stats(struct aq_hw_s *self); + +-- +2.13.6 + diff --git a/SOURCES/0075-netdrv-net-atlantic-make-hw_get_regs-optional.patch b/SOURCES/0075-netdrv-net-atlantic-make-hw_get_regs-optional.patch new file mode 100644 index 0000000..8238833 --- /dev/null +++ b/SOURCES/0075-netdrv-net-atlantic-make-hw_get_regs-optional.patch @@ -0,0 +1,63 @@ +From 0f412f39e5e9f34f62dbc6bc1477233eb7d45801 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:32 -0500 +Subject: [PATCH 075/139] [netdrv] net: atlantic: make hw_get_regs optional + +Message-id: <1604687916-15087-76-git-send-email-irusskik@redhat.com> +Patchwork-id: 338501 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 075/139] net: atlantic: make hw_get_regs optional +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit d0f23741c202c685447050713907f3be39a985ee +Author: Mark Starovoytov +Date: Thu Apr 30 11:04:34 2020 +0300 + + net: atlantic: make hw_get_regs optional + + This patch fixes potential crash in case if hw_get_regs is NULL. + + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 6d02e40b43a4..e4a33206d365 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -762,6 +762,9 @@ int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p) + u32 *regs_buff = p; + int err = 0; + ++ if (unlikely(!self->aq_hw_ops->hw_get_regs)) ++ return -EOPNOTSUPP; ++ + regs->version = 1; + + err = self->aq_hw_ops->hw_get_regs(self->aq_hw, +@@ -776,6 +779,9 @@ int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p) + + int aq_nic_get_regs_count(struct aq_nic_s *self) + { ++ if (unlikely(!self->aq_hw_ops->hw_get_regs)) ++ return 0; ++ + return self->aq_nic_cfg.aq_hw_caps->mac_regs_count; + } + +-- +2.13.6 + diff --git a/SOURCES/0076-netdrv-net-atlantic-move-IS_CHIP_FEATURE-to-aq_hw.h.patch b/SOURCES/0076-netdrv-net-atlantic-move-IS_CHIP_FEATURE-to-aq_hw.h.patch new file mode 100644 index 0000000..2dc7459 --- /dev/null +++ b/SOURCES/0076-netdrv-net-atlantic-move-IS_CHIP_FEATURE-to-aq_hw.h.patch @@ -0,0 +1,207 @@ +From b3cb0e4c1088d2edecec9171f1377d47f00f7885 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:33 -0500 +Subject: [PATCH 076/139] [netdrv] net: atlantic: move IS_CHIP_FEATURE to + aq_hw.h + +Message-id: <1604687916-15087-77-git-send-email-irusskik@redhat.com> +Patchwork-id: 338508 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 076/139] net: atlantic: move IS_CHIP_FEATURE to aq_hw.h +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit d1ad88fe9fa9f5c3e4ecf509efb579852b44cc79 +Author: Mark Starovoytov +Date: Thu Apr 30 11:04:35 2020 +0300 + + net: atlantic: move IS_CHIP_FEATURE to aq_hw.h + + IS_CHIP feature will be used to differentiate between A1 and A2, + where necessary. Thus, move it to aq_hw.h, rename it and make + it accept the 'hw' pointer. + + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 13 ++++++++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 2 +- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 6 ++-- + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 36 ++++++++++++---------- + .../aquantia/atlantic/hw_atl/hw_atl_utils.h | 11 ------- + 5 files changed, 36 insertions(+), 32 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index e7a253667336..01208e2d2ae4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -136,6 +136,19 @@ enum aq_priv_flags { + BIT(AQ_HW_LOOPBACK_PHYINT_SYS) |\ + BIT(AQ_HW_LOOPBACK_PHYEXT_SYS)) + ++#define ATL_HW_CHIP_MIPS 0x00000001U ++#define ATL_HW_CHIP_TPO2 0x00000002U ++#define ATL_HW_CHIP_RPF2 0x00000004U ++#define ATL_HW_CHIP_MPI_AQ 0x00000010U ++#define ATL_HW_CHIP_ATLANTIC 0x00800000U ++#define ATL_HW_CHIP_REVISION_A0 0x01000000U ++#define ATL_HW_CHIP_REVISION_B0 0x02000000U ++#define ATL_HW_CHIP_REVISION_B1 0x04000000U ++#define ATL_HW_CHIP_ANTIGUA 0x08000000U ++ ++#define ATL_HW_IS_CHIP_FEATURE(_HW_, _F_) (!!(ATL_HW_CHIP_##_F_ & \ ++ (_HW_)->chip_features)) ++ + struct aq_hw_s { + atomic_t flags; + u8 rbl_enabled:1; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index 2dba8c277ecb..eee265b4415a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -267,7 +267,7 @@ static int hw_atl_a0_hw_init_tx_path(struct aq_hw_s *self) + hw_atl_tdm_tx_desc_wr_wb_irq_en_set(self, 1U); + + /* misc */ +- aq_hw_write_reg(self, 0x00007040U, IS_CHIP_FEATURE(TPO2) ? ++ aq_hw_write_reg(self, 0x00007040U, ATL_HW_IS_CHIP_FEATURE(self, TPO2) ? + 0x00010000U : 0x00000000U); + hw_atl_tdm_tx_dca_en_set(self, 0U); + hw_atl_tdm_tx_dca_mode_set(self, 0U); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 4e2e4eef028d..3b42045b9c7d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -324,7 +324,7 @@ static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self) + hw_atl_tdm_tx_desc_wr_wb_irq_en_set(self, 1U); + + /* misc */ +- aq_hw_write_reg(self, 0x00007040U, IS_CHIP_FEATURE(TPO2) ? ++ aq_hw_write_reg(self, 0x00007040U, ATL_HW_IS_CHIP_FEATURE(self, TPO2) ? + 0x00010000U : 0x00000000U); + hw_atl_tdm_tx_dca_en_set(self, 0U); + hw_atl_tdm_tx_dca_mode_set(self, 0U); +@@ -372,8 +372,8 @@ static int hw_atl_b0_hw_init_rx_path(struct aq_hw_s *self) + hw_atl_rdm_rx_desc_wr_wb_irq_en_set(self, 1U); + + /* misc */ +- aq_hw_write_reg(self, 0x00005040U, +- IS_CHIP_FEATURE(RPF2) ? 0x000F0000U : 0x00000000U); ++ aq_hw_write_reg(self, 0x00005040U, ATL_HW_IS_CHIP_FEATURE(self, RPF2) ? ++ 0x000F0000U : 0x00000000U); + + hw_atl_rpfl2broadcast_flr_act_set(self, 1U); + hw_atl_rpfl2broadcast_count_threshold_set(self, 0xFFFFU & (~0U / 256U)); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index bd1712ca9ef2..20655a2170cc 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -309,7 +309,7 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, + for (++cnt; --cnt && !err;) { + aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U); + +- if (IS_CHIP_FEATURE(REVISION_B1)) ++ if (ATL_HW_IS_CHIP_FEATURE(self, REVISION_B1)) + err = readx_poll_timeout_atomic(hw_atl_utils_mif_addr_get, + self, val, val != a, + 1U, 1000U); +@@ -405,7 +405,7 @@ static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 addr, u32 *p, + if (err < 0) + goto err_exit; + +- if (IS_CHIP_FEATURE(REVISION_B1)) ++ if (ATL_HW_IS_CHIP_FEATURE(self, REVISION_B1)) + err = hw_atl_utils_write_b1_mbox(self, addr, p, cnt, area); + else + err = hw_atl_utils_write_b0_mbox(self, addr, p, cnt); +@@ -497,7 +497,7 @@ int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size) + struct aq_hw_atl_utils_fw_rpc_tid_s sw; + int err = 0; + +- if (!IS_CHIP_FEATURE(MIPS)) { ++ if (!ATL_HW_IS_CHIP_FEATURE(self, MIPS)) { + err = -1; + goto err_exit; + } +@@ -603,7 +603,7 @@ void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self, + if (err < 0) + goto err_exit; + +- if (IS_CHIP_FEATURE(REVISION_A0)) { ++ if (ATL_HW_IS_CHIP_FEATURE(self, REVISION_A0)) { + unsigned int mtu = self->aq_nic_cfg ? + self->aq_nic_cfg->mtu : 1514U; + pmbox->stats.ubrc = pmbox->stats.uprc * mtu; +@@ -802,22 +802,24 @@ void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p) + u32 mif_rev = val & 0xFFU; + u32 chip_features = 0U; + ++ chip_features |= ATL_HW_CHIP_ATLANTIC; ++ + if ((0xFU & mif_rev) == 1U) { +- chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 | +- HAL_ATLANTIC_UTILS_CHIP_MPI_AQ | +- HAL_ATLANTIC_UTILS_CHIP_MIPS; ++ chip_features |= ATL_HW_CHIP_REVISION_A0 | ++ ATL_HW_CHIP_MPI_AQ | ++ ATL_HW_CHIP_MIPS; + } else if ((0xFU & mif_rev) == 2U) { +- chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 | +- HAL_ATLANTIC_UTILS_CHIP_MPI_AQ | +- HAL_ATLANTIC_UTILS_CHIP_MIPS | +- HAL_ATLANTIC_UTILS_CHIP_TPO2 | +- HAL_ATLANTIC_UTILS_CHIP_RPF2; ++ chip_features |= ATL_HW_CHIP_REVISION_B0 | ++ ATL_HW_CHIP_MPI_AQ | ++ ATL_HW_CHIP_MIPS | ++ ATL_HW_CHIP_TPO2 | ++ ATL_HW_CHIP_RPF2; + } else if ((0xFU & mif_rev) == 0xAU) { +- chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 | +- HAL_ATLANTIC_UTILS_CHIP_MPI_AQ | +- HAL_ATLANTIC_UTILS_CHIP_MIPS | +- HAL_ATLANTIC_UTILS_CHIP_TPO2 | +- HAL_ATLANTIC_UTILS_CHIP_RPF2; ++ chip_features |= ATL_HW_CHIP_REVISION_B1 | ++ ATL_HW_CHIP_MPI_AQ | ++ ATL_HW_CHIP_MIPS | ++ ATL_HW_CHIP_TPO2 | ++ ATL_HW_CHIP_RPF2; + } + + *p = chip_features; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index ed3f0307652d..36084152c4c3 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -380,17 +380,6 @@ enum hw_atl_rx_ctrl_registers_l3l4 { + #define HW_ATL_GET_REG_LOCATION_FL3L4(location) \ + ((location) - AQ_RX_FIRST_LOC_FL3L4) + +-#define HAL_ATLANTIC_UTILS_CHIP_MIPS 0x00000001U +-#define HAL_ATLANTIC_UTILS_CHIP_TPO2 0x00000002U +-#define HAL_ATLANTIC_UTILS_CHIP_RPF2 0x00000004U +-#define HAL_ATLANTIC_UTILS_CHIP_MPI_AQ 0x00000010U +-#define HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 0x01000000U +-#define HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 0x02000000U +-#define HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 0x04000000U +- +-#define IS_CHIP_FEATURE(_F_) (HAL_ATLANTIC_UTILS_CHIP_##_F_ & \ +- self->chip_features) +- + enum hal_atl_utils_fw_state_e { + MPI_DEINIT = 0, + MPI_RESET = 1, +-- +2.13.6 + diff --git a/SOURCES/0077-netdrv-net-atlantic-A2-driver-firmware-interface.patch b/SOURCES/0077-netdrv-net-atlantic-A2-driver-firmware-interface.patch new file mode 100644 index 0000000..19a0d6c --- /dev/null +++ b/SOURCES/0077-netdrv-net-atlantic-A2-driver-firmware-interface.patch @@ -0,0 +1,640 @@ +From 8e0162b1facc04fed233dfb9fb7d357b95ca4b99 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:34 -0500 +Subject: [PATCH 077/139] [netdrv] net: atlantic: A2 driver-firmware interface + +Message-id: <1604687916-15087-78-git-send-email-irusskik@redhat.com> +Patchwork-id: 338509 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 077/139] net: atlantic: A2 driver-firmware interface +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit f67619611b4ce0e3b2bbc2cd75b9c2ce2035ef1e +Author: Dmitry Bogdanov +Date: Thu Apr 30 11:04:36 2020 +0300 + + net: atlantic: A2 driver-firmware interface + + This patch adds the driver<->firmware interface for A2 + + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../aquantia/atlantic/hw_atl2/hw_atl2_utils.h | 593 +++++++++++++++++++++ + 1 file changed, 593 insertions(+) + create mode 100644 drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h +new file mode 100644 +index 000000000000..7d4ac65440c9 +--- /dev/null ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h +@@ -0,0 +1,593 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* Atlantic Network Driver ++ * Copyright (C) 2020 Marvell International Ltd. ++ */ ++ ++#ifndef HW_ATL2_UTILS_H ++#define HW_ATL2_UTILS_H ++ ++/* F W A P I */ ++ ++struct link_options_s { ++ u8 link_up:1; ++ u8 link_renegotiate:1; ++ u8 minimal_link_speed:1; ++ u8 internal_loopback:1; ++ u8 external_loopback:1; ++ u8 rate_10M_hd:1; ++ u8 rate_100M_hd:1; ++ u8 rate_1G_hd:1; ++ ++ u8 rate_10M:1; ++ u8 rate_100M:1; ++ u8 rate_1G:1; ++ u8 rate_2P5G:1; ++ u8 rate_N2P5G:1; ++ u8 rate_5G:1; ++ u8 rate_N5G:1; ++ u8 rate_10G:1; ++ ++ u8 eee_100M:1; ++ u8 eee_1G:1; ++ u8 eee_2P5G:1; ++ u8 eee_5G:1; ++ u8 eee_10G:1; ++ u8 rsvd3:3; ++ ++ u8 pause_rx:1; ++ u8 pause_tx:1; ++ u8 rsvd4:1; ++ u8 downshift:1; ++ u8 downshift_retry:4; ++}; ++ ++struct link_control_s { ++ u8 mode:4; ++ u8 disable_crc_corruption:1; ++ u8 discard_short_frames:1; ++ u8 flow_control_mode:1; ++ u8 disable_length_check:1; ++ ++ u8 discard_errored_frames:1; ++ u8 control_frame_enable:1; ++ u8 enable_tx_padding:1; ++ u8 enable_crc_forwarding:1; ++ u8 enable_frame_padding_removal_rx: 1; ++ u8 promiscuous_mode: 1; ++ u8 rsvd:2; ++ ++ u16 rsvd2; ++}; ++ ++struct thermal_shutdown_s { ++ u8 enable:1; ++ u8 warning_enable:1; ++ u8 rsvd:6; ++ ++ u8 shutdown_temperature; ++ u8 cold_temperature; ++ u8 warning_temperature; ++}; ++ ++struct mac_address_s { ++ u8 mac_address[6]; ++}; ++ ++struct mac_address_aligned_s { ++ struct mac_address_s aligned; ++ u16 rsvd; ++}; ++ ++struct sleep_proxy_s { ++ struct wake_on_lan_s { ++ u8 wake_on_magic_packet:1; ++ u8 wake_on_pattern:1; ++ u8 wake_on_link_up:1; ++ u8 wake_on_link_down:1; ++ u8 wake_on_ping:1; ++ u8 wake_on_timer:1; ++ u8 rsvd:2; ++ ++ u8 rsvd2; ++ u16 rsvd3; ++ ++ u32 link_up_timeout; ++ u32 link_down_timeout; ++ u32 timer; ++ } wake_on_lan; ++ ++ struct { ++ u32 mask[4]; ++ u32 crc32; ++ } wake_up_pattern[8]; ++ ++ struct __attribute__ ((__packed__)) { ++ u8 arp_responder:1; ++ u8 echo_responder:1; ++ u8 igmp_client:1; ++ u8 echo_truncate:1; ++ u8 address_guard:1; ++ u8 ignore_fragmented:1; ++ u8 rsvd:2; ++ ++ u16 echo_max_len; ++ u8 rsvd2; ++ } ipv4_offload; ++ ++ u32 ipv4_offload_addr[8]; ++ u32 reserved[8]; ++ ++ struct __attribute__ ((__packed__)) { ++ u8 ns_responder:1; ++ u8 echo_responder:1; ++ u8 mld_client:1; ++ u8 echo_truncate:1; ++ u8 address_guard:1; ++ u8 rsvd:3; ++ ++ u16 echo_max_len; ++ u8 rsvd2; ++ } ipv6_offload; ++ ++ u32 ipv6_offload_addr[16][4]; ++ ++ struct { ++ u16 port[16]; ++ } tcp_port_offload; ++ ++ struct { ++ u16 port[16]; ++ } udp_port_offload; ++ ++ struct { ++ u32 retry_count; ++ u32 retry_interval; ++ } ka4_offload; ++ ++ struct { ++ u32 timeout; ++ u16 local_port; ++ u16 remote_port; ++ u8 remote_mac_addr[6]; ++ u16 rsvd; ++ u32 rsvd2; ++ u32 rsvd3; ++ u16 rsvd4; ++ u16 win_size; ++ u32 seq_num; ++ u32 ack_num; ++ u32 local_ip; ++ u32 remote_ip; ++ } ka4_connection[16]; ++ ++ struct { ++ u32 retry_count; ++ u32 retry_interval; ++ } ka6_offload; ++ ++ struct { ++ u32 timeout; ++ u16 local_port; ++ u16 remote_port; ++ u8 remote_mac_addr[6]; ++ u16 rsvd; ++ u32 rsvd2; ++ u32 rsvd3; ++ u16 rsvd4; ++ u16 win_size; ++ u32 seq_num; ++ u32 ack_num; ++ u32 local_ip[4]; ++ u32 remote_ip[4]; ++ } ka6_connection[16]; ++ ++ struct { ++ u32 rr_count; ++ u32 rr_buf_len; ++ u32 idx_offset; ++ u32 rr__offset; ++ } mdns_offload; ++}; ++ ++struct pause_quanta_s { ++ u16 quanta_10M; ++ u16 threshold_10M; ++ u16 quanta_100M; ++ u16 threshold_100M; ++ u16 quanta_1G; ++ u16 threshold_1G; ++ u16 quanta_2P5G; ++ u16 threshold_2P5G; ++ u16 quanta_5G; ++ u16 threshold_5G; ++ u16 quanta_10G; ++ u16 threshold_10G; ++}; ++ ++struct data_buffer_status_s { ++ u32 data_offset; ++ u32 data_length; ++}; ++ ++struct device_caps_s { ++ u8 finite_flashless:1; ++ u8 cable_diag:1; ++ u8 ncsi:1; ++ u8 avb:1; ++ u8 rsvd:4; ++ ++ u8 rsvd2; ++ u16 rsvd3; ++ u32 rsvd4; ++}; ++ ++struct version_s { ++ struct bundle_version_t { ++ u8 major; ++ u8 minor; ++ u16 build; ++ } bundle; ++ struct mac_version_t { ++ u8 major; ++ u8 minor; ++ u16 build; ++ } mac; ++ struct phy_version_t { ++ u8 major; ++ u8 minor; ++ u16 build; ++ } phy; ++ u32 rsvd; ++}; ++ ++struct link_status_s { ++ u8 link_state:4; ++ u8 link_rate:4; ++ ++ u8 pause_tx:1; ++ u8 pause_rx:1; ++ u8 eee:1; ++ u8 duplex:1; ++ u8 rsvd:4; ++ ++ u16 rsvd2; ++}; ++ ++struct wol_status_s { ++ u8 wake_count; ++ u8 wake_reason; ++ ++ u16 wake_up_packet_length :12; ++ u16 wake_up_pattern_number :3; ++ u16 rsvd:1; ++ ++ u32 wake_up_packet[379]; ++}; ++ ++struct mac_health_monitor_s { ++ u8 mac_ready:1; ++ u8 mac_fault:1; ++ u8 mac_flashless_finished:1; ++ u8 rsvd:5; ++ ++ u8 mac_temperature; ++ u16 mac_heart_beat; ++ u16 mac_fault_code; ++ u16 rsvd2; ++}; ++ ++struct phy_health_monitor_s { ++ u8 phy_ready:1; ++ u8 phy_fault:1; ++ u8 phy_hot_warning:1; ++ u8 rsvd:5; ++ ++ u8 phy_temperature; ++ u16 phy_heart_beat; ++ u16 phy_fault_code; ++ u16 rsvd2; ++}; ++ ++struct device_link_caps_s { ++ u8 rsvd:3; ++ u8 internal_loopback:1; ++ u8 external_loopback:1; ++ u8 rate_10M_hd:1; ++ u8 rate_100M_hd:1; ++ u8 rate_1G_hd:1; ++ ++ u8 rate_10M:1; ++ u8 rate_100M:1; ++ u8 rate_1G:1; ++ u8 rate_2P5G:1; ++ u8 rate_N2P5G:1; ++ u8 rate_5G:1; ++ u8 rate_N5G:1; ++ u8 rate_10G:1; ++ ++ u8 rsvd3:1; ++ u8 eee_100M:1; ++ u8 eee_1G:1; ++ u8 eee_2P5G:1; ++ u8 rsvd4:1; ++ u8 eee_5G:1; ++ u8 rsvd5:1; ++ u8 eee_10G:1; ++ ++ u8 pause_rx:1; ++ u8 pause_tx:1; ++ u8 pfc:1; ++ u8 downshift:1; ++ u8 downshift_retry:4; ++}; ++ ++struct sleep_proxy_caps_s { ++ u8 ipv4_offload:1; ++ u8 ipv6_offload:1; ++ u8 tcp_port_offload:1; ++ u8 udp_port_offload:1; ++ u8 ka4_offload:1; ++ u8 ka6_offload:1; ++ u8 mdns_offload:1; ++ u8 wake_on_ping:1; ++ ++ u8 wake_on_magic_packet:1; ++ u8 wake_on_pattern:1; ++ u8 wake_on_timer:1; ++ u8 wake_on_link:1; ++ u8 wake_patterns_count:4; ++ ++ u8 ipv4_count; ++ u8 ipv6_count; ++ ++ u8 tcp_port_offload_count; ++ u8 udp_port_offload_count; ++ ++ u8 tcp4_ka_count; ++ u8 tcp6_ka_count; ++ ++ u8 igmp_offload:1; ++ u8 mld_offload:1; ++ u8 rsvd:6; ++ ++ u8 rsvd2; ++ u16 rsvd3; ++}; ++ ++struct lkp_link_caps_s { ++ u8 rsvd:5; ++ u8 rate_10M_hd:1; ++ u8 rate_100M_hd:1; ++ u8 rate_1G_hd:1; ++ ++ u8 rate_10M:1; ++ u8 rate_100M:1; ++ u8 rate_1G:1; ++ u8 rate_2P5G:1; ++ u8 rate_N2P5G:1; ++ u8 rate_5G:1; ++ u8 rate_N5G:1; ++ u8 rate_10G:1; ++ ++ u8 rsvd2:1; ++ u8 eee_100M:1; ++ u8 eee_1G:1; ++ u8 eee_2P5G:1; ++ u8 rsvd3:1; ++ u8 eee_5G:1; ++ u8 rsvd4:1; ++ u8 eee_10G:1; ++ ++ u8 pause_rx:1; ++ u8 pause_tx:1; ++ u8 rsvd5:6; ++}; ++ ++struct core_dump_s { ++ u32 reg0; ++ u32 reg1; ++ u32 reg2; ++ ++ u32 hi; ++ u32 lo; ++ ++ u32 regs[32]; ++}; ++ ++struct trace_s { ++ u32 sync_counter; ++ u32 mem_buffer[0x1ff]; ++}; ++ ++struct cable_diag_control_s { ++ u8 toggle :1; ++ u8 rsvd:7; ++ ++ u8 wait_timeout_sec; ++ u16 rsvd2; ++}; ++ ++struct cable_diag_lane_data_s { ++ u8 result_code; ++ u8 dist; ++ u8 far_dist; ++ u8 rsvd; ++}; ++ ++struct cable_diag_status_s { ++ struct cable_diag_lane_data_s lane_data[4]; ++ u8 transact_id; ++ u8 status:4; ++ u8 rsvd:4; ++ u16 rsvd2; ++}; ++ ++struct statistics_s { ++ struct { ++ u32 link_up; ++ u32 link_down; ++ } link; ++ ++ struct { ++ u64 tx_unicast_octets; ++ u64 tx_multicast_octets; ++ u64 tx_broadcast_octets; ++ u64 rx_unicast_octets; ++ u64 rx_multicast_octets; ++ u64 rx_broadcast_octets; ++ ++ u32 tx_unicast_frames; ++ u32 tx_multicast_frames; ++ u32 tx_broadcast_frames; ++ u32 tx_errors; ++ ++ u32 rx_unicast_frames; ++ u32 rx_multicast_frames; ++ u32 rx_broadcast_frames; ++ u32 rx_dropped_frames; ++ u32 rx_error_frames; ++ ++ u32 tx_good_frames; ++ u32 rx_good_frames; ++ u32 reserve_fw_gap; ++ } msm; ++ u32 main_loop_cycles; ++ u32 reserve_fw_gap; ++}; ++ ++struct filter_caps_s { ++ u8 l2_filters_base_index:6; ++ u8 flexible_filter_mask:2; ++ u8 l2_filter_count; ++ u8 ethertype_filter_base_index; ++ u8 ethertype_filter_count; ++ ++ u8 vlan_filter_base_index; ++ u8 vlan_filter_count; ++ u8 l3_ip4_filter_base_index:4; ++ u8 l3_ip4_filter_count:4; ++ u8 l3_ip6_filter_base_index:4; ++ u8 l3_ip6_filter_count:4; ++ ++ u8 l4_filter_base_index:4; ++ u8 l4_filter_count:4; ++ u8 l4_flex_filter_base_index:4; ++ u8 l4_flex_filter_count:4; ++ u8 rslv_tbl_base_index; ++ u8 rslv_tbl_count; ++}; ++ ++struct request_policy_s { ++ struct { ++ u8 all:1; ++ u8 mcast:1; ++ u8 rx_queue_tc_index:5; ++ u8 queue_or_tc:1; ++ } promisc; ++ ++ struct { ++ u8 accept:1; ++ u8 rsvd:1; ++ u8 rx_queue_tc_index:5; ++ u8 queue_or_tc:1; ++ } bcast; ++ ++ struct { ++ u8 accept:1; ++ u8 rsvd:1; ++ u8 rx_queue_tc_index:5; ++ u8 queue_or_tc:1; ++ } mcast; ++ ++ u8 rsvd:8; ++}; ++ ++struct fw_interface_in { ++ u32 mtu; ++ u32 rsvd1; ++ struct mac_address_aligned_s mac_address; ++ struct link_control_s link_control; ++ u32 rsvd2; ++ struct link_options_s link_options; ++ u32 rsvd3; ++ struct thermal_shutdown_s thermal_shutdown; ++ u32 rsvd4; ++ struct sleep_proxy_s sleep_proxy; ++ u32 rsvd5; ++ struct pause_quanta_s pause_quanta[8]; ++ struct cable_diag_control_s cable_diag_control; ++ u32 rsvd6; ++ struct data_buffer_status_s data_buffer_status; ++ u32 rsvd7; ++ struct request_policy_s request_policy; ++}; ++ ++struct transaction_counter_s { ++ u16 transaction_cnt_a; ++ u16 transaction_cnt_b; ++}; ++ ++struct management_status_s { ++ struct mac_address_s mac_address; ++ u16 vlan; ++ ++ struct{ ++ u32 enable : 1; ++ u32 rsvd:31; ++ } flags; ++ ++ u32 rsvd1; ++ u32 rsvd2; ++ u32 rsvd3; ++ u32 rsvd4; ++ u32 rsvd5; ++}; ++ ++struct fw_interface_out { ++ struct transaction_counter_s transaction_id; ++ struct version_s version; ++ struct link_status_s link_status; ++ struct wol_status_s wol_status; ++ u32 rsvd; ++ u32 rsvd2; ++ struct mac_health_monitor_s mac_health_monitor; ++ u32 rsvd3; ++ u32 rsvd4; ++ struct phy_health_monitor_s phy_health_monitor; ++ u32 rsvd5; ++ u32 rsvd6; ++ struct cable_diag_status_s cable_diag_status; ++ u32 rsvd7; ++ struct device_link_caps_s device_link_caps; ++ u32 rsvd8; ++ struct sleep_proxy_caps_s sleep_proxy_caps; ++ u32 rsvd9; ++ struct lkp_link_caps_s lkp_link_caps; ++ u32 rsvd10; ++ struct core_dump_s core_dump; ++ u32 rsvd11; ++ struct statistics_s stats; ++ u32 rsvd12; ++ struct filter_caps_s filter_caps; ++ struct device_caps_s device_caps; ++ u32 rsvd13; ++ struct management_status_s management_status; ++ u32 reserve[21]; ++ struct trace_s trace; ++}; ++ ++#define AQ_A2_FW_LINK_RATE_INVALID 0 ++#define AQ_A2_FW_LINK_RATE_10M 1 ++#define AQ_A2_FW_LINK_RATE_100M 2 ++#define AQ_A2_FW_LINK_RATE_1G 3 ++#define AQ_A2_FW_LINK_RATE_2G5 4 ++#define AQ_A2_FW_LINK_RATE_5G 5 ++#define AQ_A2_FW_LINK_RATE_10G 6 ++ ++#define AQ_HOST_MODE_INVALID 0U ++#define AQ_HOST_MODE_ACTIVE 1U ++#define AQ_HOST_MODE_SLEEP_PROXY 2U ++#define AQ_HOST_MODE_LOW_POWER 3U ++#define AQ_HOST_MODE_SHUTDOWN 4U ++ ++#endif /* HW_ATL2_UTILS_H */ +-- +2.13.6 + diff --git a/SOURCES/0078-netdrv-net-atlantic-minimal-A2-HW-bindings-required-.patch b/SOURCES/0078-netdrv-net-atlantic-minimal-A2-HW-bindings-required-.patch new file mode 100644 index 0000000..679124f --- /dev/null +++ b/SOURCES/0078-netdrv-net-atlantic-minimal-A2-HW-bindings-required-.patch @@ -0,0 +1,229 @@ +From 21348f1be3a58a274e864b0b5030474d38b83b2f Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:35 -0500 +Subject: [PATCH 078/139] [netdrv] net: atlantic: minimal A2 HW bindings + required for fw_ops + +Message-id: <1604687916-15087-79-git-send-email-irusskik@redhat.com> +Patchwork-id: 338506 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 078/139] net: atlantic: minimal A2 HW bindings required for fw_ops +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 258ff0cf61d607e17f2e273aae3e50c1dd251dec +Author: Dmitry Bogdanov +Date: Thu Apr 30 11:04:37 2020 +0300 + + net: atlantic: minimal A2 HW bindings required for fw_ops + + This patch adds the bare minimum of A2 HW bindings required to + get fw_ops working. + + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/Makefile | 5 +- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 1 + + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.c | 56 ++++++++++++++++++++++ + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.h | 31 ++++++++++++ + .../atlantic/hw_atl2/hw_atl2_llh_internal.h | 48 +++++++++++++++++++ + 5 files changed, 139 insertions(+), 2 deletions(-) + create mode 100644 drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c + create mode 100644 drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h + create mode 100644 drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h + +diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile +index 6e0a6e234483..7b553460a627 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/Makefile ++++ b/drivers/net/ethernet/aquantia/atlantic/Makefile +@@ -22,6 +22,7 @@ atlantic-objs := aq_main.o \ + hw_atl/hw_atl_b0.o \ + hw_atl/hw_atl_utils.o \ + hw_atl/hw_atl_utils_fw2x.o \ +- hw_atl/hw_atl_llh.o ++ hw_atl/hw_atl_llh.o \ ++ hw_atl2/hw_atl2_llh.o + +-atlantic-$(CONFIG_PTP_1588_CLOCK) += aq_ptp.o +\ No newline at end of file ++atlantic-$(CONFIG_PTP_1588_CLOCK) += aq_ptp.o +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index 01208e2d2ae4..3bce9f8e24d8 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -172,6 +172,7 @@ struct aq_hw_s { + struct hw_atl_utils_fw_rpc rpc; + s64 ptp_clk_offset; + u16 phy_id; ++ void *priv; + }; + + struct aq_ring_s; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +new file mode 100644 +index 000000000000..b6164bc5fffd +--- /dev/null ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +@@ -0,0 +1,56 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Atlantic Network Driver ++ * Copyright (C) 2020 Marvell International Ltd. ++ */ ++ ++#include "hw_atl2_llh.h" ++#include "hw_atl2_llh_internal.h" ++#include "aq_hw_utils.h" ++ ++void hw_atl2_mif_shared_buf_get(struct aq_hw_s *aq_hw, int offset, u32 *data, ++ int len) ++{ ++ int j = 0; ++ int i; ++ ++ for (i = offset; i < offset + len; i++, j++) ++ data[j] = aq_hw_read_reg(aq_hw, ++ HW_ATL2_MIF_SHARED_BUFFER_IN_ADR(i)); ++} ++ ++void hw_atl2_mif_shared_buf_write(struct aq_hw_s *aq_hw, int offset, u32 *data, ++ int len) ++{ ++ int j = 0; ++ int i; ++ ++ for (i = offset; i < offset + len; i++, j++) ++ aq_hw_write_reg(aq_hw, HW_ATL2_MIF_SHARED_BUFFER_IN_ADR(i), ++ data[j]); ++} ++ ++void hw_atl2_mif_shared_buf_read(struct aq_hw_s *aq_hw, int offset, u32 *data, ++ int len) ++{ ++ int j = 0; ++ int i; ++ ++ for (i = offset; i < offset + len; i++, j++) ++ data[j] = aq_hw_read_reg(aq_hw, ++ HW_ATL2_MIF_SHARED_BUFFER_OUT_ADR(i)); ++} ++ ++void hw_atl2_mif_host_finished_write_set(struct aq_hw_s *aq_hw, u32 finish) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_MIF_HOST_FINISHED_WRITE_ADR, ++ HW_ATL2_MIF_HOST_FINISHED_WRITE_MSK, ++ HW_ATL2_MIF_HOST_FINISHED_WRITE_SHIFT, ++ finish); ++} ++ ++u32 hw_atl2_mif_mcp_finished_read_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg_bit(aq_hw, HW_ATL2_MIF_MCP_FINISHED_READ_ADR, ++ HW_ATL2_MIF_MCP_FINISHED_READ_MSK, ++ HW_ATL2_MIF_MCP_FINISHED_READ_SHIFT); ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +new file mode 100644 +index 000000000000..8ef8bd6b2534 +--- /dev/null ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +@@ -0,0 +1,31 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* Atlantic Network Driver ++ * Copyright (C) 2020 Marvell International Ltd. ++ */ ++ ++#ifndef HW_ATL2_LLH_H ++#define HW_ATL2_LLH_H ++ ++#include ++ ++struct aq_hw_s; ++ ++/* get data from firmware shared input buffer */ ++void hw_atl2_mif_shared_buf_get(struct aq_hw_s *aq_hw, int offset, u32 *data, ++ int len); ++ ++/* set data into firmware shared input buffer */ ++void hw_atl2_mif_shared_buf_write(struct aq_hw_s *aq_hw, int offset, u32 *data, ++ int len); ++ ++/* get data from firmware shared output buffer */ ++void hw_atl2_mif_shared_buf_read(struct aq_hw_s *aq_hw, int offset, u32 *data, ++ int len); ++ ++/* set host finished write shared buffer indication */ ++void hw_atl2_mif_host_finished_write_set(struct aq_hw_s *aq_hw, u32 finish); ++ ++/* get mcp finished read shared buffer indication */ ++u32 hw_atl2_mif_mcp_finished_read_get(struct aq_hw_s *aq_hw); ++ ++#endif /* HW_ATL2_LLH_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +new file mode 100644 +index 000000000000..835deb2d1950 +--- /dev/null ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +@@ -0,0 +1,48 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* Atlantic Network Driver ++ * Copyright (C) 2020 Marvell International Ltd. ++ */ ++ ++#ifndef HW_ATL2_LLH_INTERNAL_H ++#define HW_ATL2_LLH_INTERNAL_H ++ ++/* Register address for firmware shared input buffer */ ++#define HW_ATL2_MIF_SHARED_BUFFER_IN_ADR(dword) (0x00012000U + (dword) * 0x4U) ++/* Register address for firmware shared output buffer */ ++#define HW_ATL2_MIF_SHARED_BUFFER_OUT_ADR(dword) (0x00013000U + (dword) * 0x4U) ++ ++/* pif_host_finished_buf_wr_i Bitfield Definitions ++ * Preprocessor definitions for the bitfield "pif_host_finished_buf_wr_i". ++ * PORT="pif_host_finished_buf_wr_i" ++ */ ++/* Register address for bitfield rpif_host_finished_buf_wr_i */ ++#define HW_ATL2_MIF_HOST_FINISHED_WRITE_ADR 0x00000e00u ++/* Bitmask for bitfield pif_host_finished_buf_wr_i */ ++#define HW_ATL2_MIF_HOST_FINISHED_WRITE_MSK 0x00000001u ++/* Inverted bitmask for bitfield pif_host_finished_buf_wr_i */ ++#define HW_ATL2_MIF_HOST_FINISHED_WRITE_MSKN 0xFFFFFFFEu ++/* Lower bit position of bitfield pif_host_finished_buf_wr_i */ ++#define HW_ATL2_MIF_HOST_FINISHED_WRITE_SHIFT 0 ++/* Width of bitfield pif_host_finished_buf_wr_i */ ++#define HW_ATL2_MIF_HOST_FINISHED_WRITE_WIDTH 1 ++/* Default value of bitfield pif_host_finished_buf_wr_i */ ++#define HW_ATL2_MIF_HOST_FINISHED_WRITE_DEFAULT 0x0 ++ ++/* pif_mcp_finished_buf_rd_i Bitfield Definitions ++ * Preprocessor definitions for the bitfield "pif_mcp_finished_buf_rd_i". ++ * PORT="pif_mcp_finished_buf_rd_i" ++ */ ++/* Register address for bitfield pif_mcp_finished_buf_rd_i */ ++#define HW_ATL2_MIF_MCP_FINISHED_READ_ADR 0x00000e04u ++/* Bitmask for bitfield pif_mcp_finished_buf_rd_i */ ++#define HW_ATL2_MIF_MCP_FINISHED_READ_MSK 0x00000001u ++/* Inverted bitmask for bitfield pif_mcp_finished_buf_rd_i */ ++#define HW_ATL2_MIF_MCP_FINISHED_READ_MSKN 0xFFFFFFFEu ++/* Lower bit position of bitfield pif_mcp_finished_buf_rd_i */ ++#define HW_ATL2_MIF_MCP_FINISHED_READ_SHIFT 0 ++/* Width of bitfield pif_mcp_finished_buf_rd_i */ ++#define HW_ATL2_MIF_MCP_FINISHED_READ_WIDTH 1 ++/* Default value of bitfield pif_mcp_finished_buf_rd_i */ ++#define HW_ATL2_MIF_MCP_FINISHED_READ_DEFAULT 0x0 ++ ++#endif /* HW_ATL2_LLH_INTERNAL_H */ +-- +2.13.6 + diff --git a/SOURCES/0079-netdrv-net-atlantic-minimal-A2-fw_ops.patch b/SOURCES/0079-netdrv-net-atlantic-minimal-A2-fw_ops.patch new file mode 100644 index 0000000..5dcac27 --- /dev/null +++ b/SOURCES/0079-netdrv-net-atlantic-minimal-A2-fw_ops.patch @@ -0,0 +1,431 @@ +From 312e017098389fa0648df9d7387d27dc14cf157a Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:36 -0500 +Subject: [PATCH 079/139] [netdrv] net: atlantic: minimal A2 fw_ops + +Message-id: <1604687916-15087-80-git-send-email-irusskik@redhat.com> +Patchwork-id: 338502 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 079/139] net: atlantic: minimal A2 fw_ops +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 5cfd54d7dc186a368af92aba0dcb8b4d4bbe8658 +Author: Dmitry Bogdanov +Date: Thu Apr 30 11:04:38 2020 +0300 + + net: atlantic: minimal A2 fw_ops + + This patch adds the minimum set of FW ops for A2. + + Signed-off-by: Dmitry Bogdanov + Co-developed-by: Igor Russkikh + Signed-off-by: Igor Russkikh + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/Makefile | 1 + + .../aquantia/atlantic/hw_atl2/hw_atl2_internal.h | 17 ++ + .../aquantia/atlantic/hw_atl2/hw_atl2_utils.h | 5 + + .../aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 329 +++++++++++++++++++++ + 4 files changed, 352 insertions(+) + create mode 100644 drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h + create mode 100644 drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c + +diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile +index 7b553460a627..7e58de0d715e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/Makefile ++++ b/drivers/net/ethernet/aquantia/atlantic/Makefile +@@ -23,6 +23,7 @@ atlantic-objs := aq_main.o \ + hw_atl/hw_atl_utils.o \ + hw_atl/hw_atl_utils_fw2x.o \ + hw_atl/hw_atl_llh.o \ ++ hw_atl2/hw_atl2_utils_fw.o \ + hw_atl2/hw_atl2_llh.o + + atlantic-$(CONFIG_PTP_1588_CLOCK) += aq_ptp.o +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +new file mode 100644 +index 000000000000..233db3222bb8 +--- /dev/null ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* Atlantic Network Driver ++ * Copyright (C) 2020 Marvell International Ltd. ++ */ ++ ++#ifndef HW_ATL2_INTERNAL_H ++#define HW_ATL2_INTERNAL_H ++ ++#include "hw_atl2_utils.h" ++ ++#define HW_ATL2_MTU_JUMBO 16352U ++ ++struct hw_atl2_priv { ++ struct statistics_s last_stats; ++}; ++ ++#endif /* HW_ATL2_INTERNAL_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h +index 7d4ac65440c9..5421fbed3db5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h +@@ -590,4 +590,9 @@ struct fw_interface_out { + #define AQ_HOST_MODE_LOW_POWER 3U + #define AQ_HOST_MODE_SHUTDOWN 4U + ++int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self, ++ u8 *base_index, u8 *count); ++ ++extern const struct aq_fw_ops aq_a2_fw_ops; ++ + #endif /* HW_ATL2_UTILS_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +new file mode 100644 +index 000000000000..c3e0e5575810 +--- /dev/null ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +@@ -0,0 +1,329 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Atlantic Network Driver ++ * Copyright (C) 2020 Marvell International Ltd. ++ */ ++ ++#include ++ ++#include "aq_hw.h" ++#include "hw_atl/hw_atl_llh.h" ++#include "hw_atl2_utils.h" ++#include "hw_atl2_llh.h" ++#include "hw_atl2_internal.h" ++ ++#define AQ_A2_FW_READ_TRY_MAX 1000 ++ ++#define hw_atl2_shared_buffer_write(HW, ITEM, VARIABLE) \ ++ hw_atl2_mif_shared_buf_write(HW,\ ++ (offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\ ++ (u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32)) ++ ++#define hw_atl2_shared_buffer_get(HW, ITEM, VARIABLE) \ ++ hw_atl2_mif_shared_buf_get(HW, \ ++ (offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\ ++ (u32 *)&(VARIABLE), \ ++ sizeof(VARIABLE) / sizeof(u32)) ++ ++/* This should never be used on non atomic fields, ++ * treat any > u32 read as non atomic. ++ */ ++#define hw_atl2_shared_buffer_read(HW, ITEM, VARIABLE) \ ++{\ ++ BUILD_BUG_ON_MSG((offsetof(struct fw_interface_out, ITEM) % \ ++ sizeof(u32)) != 0,\ ++ "Non aligned read " # ITEM);\ ++ BUILD_BUG_ON_MSG(sizeof(VARIABLE) > sizeof(u32),\ ++ "Non atomic read " # ITEM);\ ++ hw_atl2_mif_shared_buf_read(HW, \ ++ (offsetof(struct fw_interface_out, ITEM) / sizeof(u32)),\ ++ (u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32));\ ++} ++ ++#define hw_atl2_shared_buffer_read_safe(HW, ITEM, DATA) \ ++ hw_atl2_shared_buffer_read_block((HW), \ ++ (offsetof(struct fw_interface_out, ITEM) / sizeof(u32)),\ ++ sizeof(((struct fw_interface_out *)0)->ITEM) / sizeof(u32),\ ++ (DATA)) ++ ++static int hw_atl2_shared_buffer_read_block(struct aq_hw_s *self, ++ u32 offset, u32 dwords, void *data) ++{ ++ struct transaction_counter_s tid1, tid2; ++ int cnt = 0; ++ ++ do { ++ do { ++ hw_atl2_shared_buffer_read(self, transaction_id, tid1); ++ cnt++; ++ if (cnt > AQ_A2_FW_READ_TRY_MAX) ++ return -ETIME; ++ if (tid1.transaction_cnt_a != tid1.transaction_cnt_b) ++ udelay(1); ++ } while (tid1.transaction_cnt_a != tid1.transaction_cnt_b); ++ ++ hw_atl2_mif_shared_buf_read(self, offset, (u32 *)data, dwords); ++ ++ hw_atl2_shared_buffer_read(self, transaction_id, tid2); ++ ++ cnt++; ++ if (cnt > AQ_A2_FW_READ_TRY_MAX) ++ return -ETIME; ++ } while (tid2.transaction_cnt_a != tid2.transaction_cnt_b || ++ tid1.transaction_cnt_a != tid2.transaction_cnt_a); ++ ++ return 0; ++} ++ ++static inline int hw_atl2_shared_buffer_finish_ack(struct aq_hw_s *self) ++{ ++ u32 val; ++ int err; ++ ++ hw_atl2_mif_host_finished_write_set(self, 1U); ++ err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_finished_read_get, ++ self, val, val == 0U, ++ 100, 100000U); ++ WARN(err, "hw_atl2_shared_buffer_finish_ack"); ++ ++ return err; ++} ++ ++static int aq_a2_fw_init(struct aq_hw_s *self) ++{ ++ struct link_control_s link_control; ++ u32 mtu; ++ u32 val; ++ int err; ++ ++ hw_atl2_shared_buffer_get(self, link_control, link_control); ++ link_control.mode = AQ_HOST_MODE_ACTIVE; ++ hw_atl2_shared_buffer_write(self, link_control, link_control); ++ ++ hw_atl2_shared_buffer_get(self, mtu, mtu); ++ mtu = HW_ATL2_MTU_JUMBO; ++ hw_atl2_shared_buffer_write(self, mtu, mtu); ++ ++ hw_atl2_mif_host_finished_write_set(self, 1U); ++ err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_finished_read_get, ++ self, val, val == 0U, ++ 100, 5000000U); ++ WARN(err, "hw_atl2_shared_buffer_finish_ack"); ++ ++ return err; ++} ++ ++static int aq_a2_fw_deinit(struct aq_hw_s *self) ++{ ++ struct link_control_s link_control; ++ ++ hw_atl2_shared_buffer_get(self, link_control, link_control); ++ link_control.mode = AQ_HOST_MODE_SHUTDOWN; ++ hw_atl2_shared_buffer_write(self, link_control, link_control); ++ ++ return hw_atl2_shared_buffer_finish_ack(self); ++} ++ ++static void a2_link_speed_mask2fw(u32 speed, ++ struct link_options_s *link_options) ++{ ++ link_options->rate_10G = !!(speed & AQ_NIC_RATE_10G); ++ link_options->rate_5G = !!(speed & AQ_NIC_RATE_5G); ++ link_options->rate_N5G = !!(speed & AQ_NIC_RATE_5GSR); ++ link_options->rate_2P5G = !!(speed & AQ_NIC_RATE_2GS); ++ link_options->rate_N2P5G = link_options->rate_2P5G; ++ link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G); ++ link_options->rate_100M = !!(speed & AQ_NIC_RATE_100M); ++ link_options->rate_10M = !!(speed & AQ_NIC_RATE_10M); ++} ++ ++static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed) ++{ ++ struct link_options_s link_options; ++ ++ hw_atl2_shared_buffer_get(self, link_options, link_options); ++ link_options.link_up = 1U; ++ a2_link_speed_mask2fw(speed, &link_options); ++ hw_atl2_shared_buffer_write(self, link_options, link_options); ++ ++ return hw_atl2_shared_buffer_finish_ack(self); ++} ++ ++static int aq_a2_fw_set_state(struct aq_hw_s *self, ++ enum hal_atl_utils_fw_state_e state) ++{ ++ struct link_options_s link_options; ++ ++ hw_atl2_shared_buffer_get(self, link_options, link_options); ++ ++ switch (state) { ++ case MPI_INIT: ++ link_options.link_up = 1U; ++ break; ++ case MPI_DEINIT: ++ link_options.link_up = 0U; ++ break; ++ case MPI_RESET: ++ case MPI_POWER: ++ /* No actions */ ++ break; ++ } ++ ++ hw_atl2_shared_buffer_write(self, link_options, link_options); ++ ++ return hw_atl2_shared_buffer_finish_ack(self); ++} ++ ++static int aq_a2_fw_update_link_status(struct aq_hw_s *self) ++{ ++ struct link_status_s link_status; ++ ++ hw_atl2_shared_buffer_read(self, link_status, link_status); ++ ++ switch (link_status.link_rate) { ++ case AQ_A2_FW_LINK_RATE_10G: ++ self->aq_link_status.mbps = 10000; ++ break; ++ case AQ_A2_FW_LINK_RATE_5G: ++ self->aq_link_status.mbps = 5000; ++ break; ++ case AQ_A2_FW_LINK_RATE_2G5: ++ self->aq_link_status.mbps = 2500; ++ break; ++ case AQ_A2_FW_LINK_RATE_1G: ++ self->aq_link_status.mbps = 1000; ++ break; ++ case AQ_A2_FW_LINK_RATE_100M: ++ self->aq_link_status.mbps = 100; ++ break; ++ case AQ_A2_FW_LINK_RATE_10M: ++ self->aq_link_status.mbps = 10; ++ break; ++ default: ++ self->aq_link_status.mbps = 0; ++ } ++ ++ return 0; ++} ++ ++static int aq_a2_fw_get_mac_permanent(struct aq_hw_s *self, u8 *mac) ++{ ++ struct mac_address_aligned_s mac_address; ++ ++ hw_atl2_shared_buffer_get(self, mac_address, mac_address); ++ ether_addr_copy(mac, (u8 *)mac_address.aligned.mac_address); ++ ++ if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) { ++ unsigned int rnd = 0; ++ u32 h; ++ u32 l; ++ ++ get_random_bytes(&rnd, sizeof(unsigned int)); ++ ++ l = 0xE3000000U | (0xFFFFU & rnd) | (0x00 << 16); ++ h = 0x8001300EU; ++ ++ mac[5] = (u8)(0xFFU & l); ++ l >>= 8; ++ mac[4] = (u8)(0xFFU & l); ++ l >>= 8; ++ mac[3] = (u8)(0xFFU & l); ++ l >>= 8; ++ mac[2] = (u8)(0xFFU & l); ++ mac[1] = (u8)(0xFFU & h); ++ h >>= 8; ++ mac[0] = (u8)(0xFFU & h); ++ } ++ ++ return 0; ++} ++ ++static int aq_a2_fw_update_stats(struct aq_hw_s *self) ++{ ++ struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; ++ struct statistics_s stats; ++ ++ hw_atl2_shared_buffer_read_safe(self, stats, &stats); ++ ++#define AQ_SDELTA(_N_, _F_) (self->curr_stats._N_ += \ ++ stats.msm._F_ - priv->last_stats.msm._F_) ++ ++ if (self->aq_link_status.mbps) { ++ AQ_SDELTA(uprc, rx_unicast_frames); ++ AQ_SDELTA(mprc, rx_multicast_frames); ++ AQ_SDELTA(bprc, rx_broadcast_frames); ++ AQ_SDELTA(erpr, rx_error_frames); ++ ++ AQ_SDELTA(uptc, tx_unicast_frames); ++ AQ_SDELTA(mptc, tx_multicast_frames); ++ AQ_SDELTA(bptc, tx_broadcast_frames); ++ AQ_SDELTA(erpt, tx_errors); ++ ++ AQ_SDELTA(ubrc, rx_unicast_octets); ++ AQ_SDELTA(ubtc, tx_unicast_octets); ++ AQ_SDELTA(mbrc, rx_multicast_octets); ++ AQ_SDELTA(mbtc, tx_multicast_octets); ++ AQ_SDELTA(bbrc, rx_broadcast_octets); ++ AQ_SDELTA(bbtc, tx_broadcast_octets); ++ } ++#undef AQ_SDELTA ++ self->curr_stats.dma_pkt_rc = ++ hw_atl_stats_rx_dma_good_pkt_counter_get(self); ++ self->curr_stats.dma_pkt_tc = ++ hw_atl_stats_tx_dma_good_pkt_counter_get(self); ++ self->curr_stats.dma_oct_rc = ++ hw_atl_stats_rx_dma_good_octet_counter_get(self); ++ self->curr_stats.dma_oct_tc = ++ hw_atl_stats_tx_dma_good_octet_counter_get(self); ++ self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self); ++ ++ memcpy(&priv->last_stats, &stats, sizeof(stats)); ++ ++ return 0; ++} ++ ++static int aq_a2_fw_renegotiate(struct aq_hw_s *self) ++{ ++ struct link_options_s link_options; ++ int err; ++ ++ hw_atl2_shared_buffer_get(self, link_options, link_options); ++ link_options.link_renegotiate = 1U; ++ hw_atl2_shared_buffer_write(self, link_options, link_options); ++ ++ err = hw_atl2_shared_buffer_finish_ack(self); ++ ++ /* We should put renegotiate status back to zero ++ * after command completes ++ */ ++ link_options.link_renegotiate = 0U; ++ hw_atl2_shared_buffer_write(self, link_options, link_options); ++ ++ return err; ++} ++ ++int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self, ++ u8 *base_index, u8 *count) ++{ ++ struct filter_caps_s filter_caps; ++ int err; ++ ++ err = hw_atl2_shared_buffer_read_safe(self, filter_caps, &filter_caps); ++ if (err) ++ return err; ++ ++ *base_index = filter_caps.rslv_tbl_base_index; ++ *count = filter_caps.rslv_tbl_count; ++ return 0; ++} ++ ++const struct aq_fw_ops aq_a2_fw_ops = { ++ .init = aq_a2_fw_init, ++ .deinit = aq_a2_fw_deinit, ++ .reset = NULL, ++ .renegotiate = aq_a2_fw_renegotiate, ++ .get_mac_permanent = aq_a2_fw_get_mac_permanent, ++ .set_link_speed = aq_a2_fw_set_link_speed, ++ .set_state = aq_a2_fw_set_state, ++ .update_link_status = aq_a2_fw_update_link_status, ++ .update_stats = aq_a2_fw_update_stats, ++}; +-- +2.13.6 + diff --git a/SOURCES/0080-netdrv-net-atlantic-A2-hw_ops-skeleton.patch b/SOURCES/0080-netdrv-net-atlantic-A2-hw_ops-skeleton.patch new file mode 100644 index 0000000..0906bb8 --- /dev/null +++ b/SOURCES/0080-netdrv-net-atlantic-A2-hw_ops-skeleton.patch @@ -0,0 +1,476 @@ +From 6618a6c499ff582f2af0a0279905399e0b2f2593 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:37 -0500 +Subject: [PATCH 080/139] [netdrv] net: atlantic: A2 hw_ops skeleton + +Message-id: <1604687916-15087-81-git-send-email-irusskik@redhat.com> +Patchwork-id: 338503 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 080/139] net: atlantic: A2 hw_ops skeleton +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit b3f0c79cba2060c1af37b32d60eff8598391519e +Author: Igor Russkikh +Date: Thu Apr 30 11:04:39 2020 +0300 + + net: atlantic: A2 hw_ops skeleton + + This patch adds basic hw_ops layout for A2. + + Actual implementation will be added in the follow-up patches. + + Signed-off-by: Igor Russkikh + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/Makefile | 1 + + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 1 + + .../net/ethernet/aquantia/atlantic/aq_pci_func.c | 39 +++- + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 226 +++++++++++++++++++++ + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h | 14 ++ + .../aquantia/atlantic/hw_atl2/hw_atl2_internal.h | 20 ++ + 6 files changed, 294 insertions(+), 7 deletions(-) + create mode 100644 drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c + create mode 100644 drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h + +diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile +index 7e58de0d715e..123142c61ab2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/Makefile ++++ b/drivers/net/ethernet/aquantia/atlantic/Makefile +@@ -23,6 +23,7 @@ atlantic-objs := aq_main.o \ + hw_atl/hw_atl_utils.o \ + hw_atl/hw_atl_utils_fw2x.o \ + hw_atl/hw_atl_llh.o \ ++ hw_atl2/hw_atl2.o \ + hw_atl2/hw_atl2_utils_fw.o \ + hw_atl2/hw_atl2_llh.o + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index 3bce9f8e24d8..ccdace2ccad2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -55,6 +55,7 @@ struct aq_hw_caps_s { + u8 rx_rings; + bool flow_control; + bool is_64_dma; ++ u32 priv_data_len; + }; + + struct aq_hw_link_status_s { +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +index 83b1b3585d09..34d5aaf40e19 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +@@ -16,6 +16,7 @@ + #include "aq_pci_func.h" + #include "hw_atl/hw_atl_a0.h" + #include "hw_atl/hw_atl_b0.h" ++#include "hw_atl2/hw_atl2.h" + #include "aq_filters.h" + #include "aq_drvinfo.h" + +@@ -40,6 +41,13 @@ static const struct pci_device_id aq_pci_tbl[] = { + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111S), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112S), }, + ++ { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113DEV), }, ++ { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113CS), }, ++ { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC114CS), }, ++ { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113), }, ++ { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113C), }, ++ { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC115C), }, ++ + {} + }; + +@@ -69,6 +77,13 @@ static const struct aq_board_revision_s hw_atl_boards[] = { + { AQ_DEVICE_ID_AQC109S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109s, }, + { AQ_DEVICE_ID_AQC111S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111s, }, + { AQ_DEVICE_ID_AQC112S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112s, }, ++ ++ { AQ_DEVICE_ID_AQC113DEV, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, ++ { AQ_DEVICE_ID_AQC113, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, ++ { AQ_DEVICE_ID_AQC113CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, ++ { AQ_DEVICE_ID_AQC114CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, ++ { AQ_DEVICE_ID_AQC113C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, ++ { AQ_DEVICE_ID_AQC115C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, + }; + + MODULE_DEVICE_TABLE(pci, aq_pci_tbl); +@@ -103,10 +118,8 @@ int aq_pci_func_init(struct pci_dev *pdev) + int err; + + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); +- if (!err) { ++ if (!err) + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); +- +- } + if (err) { + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (!err) +@@ -236,6 +249,15 @@ static int aq_pci_probe(struct pci_dev *pdev, + goto err_ioremap; + } + self->aq_hw->aq_nic_cfg = aq_nic_get_cfg(self); ++ if (self->aq_hw->aq_nic_cfg->aq_hw_caps->priv_data_len) { ++ int len = self->aq_hw->aq_nic_cfg->aq_hw_caps->priv_data_len; ++ ++ self->aq_hw->priv = kzalloc(len, GFP_KERNEL); ++ if (!self->aq_hw->priv) { ++ err = -ENOMEM; ++ goto err_free_aq_hw; ++ } ++ } + + for (bar = 0; bar < 4; ++bar) { + if (IORESOURCE_MEM & pci_resource_flags(pdev, bar)) { +@@ -244,19 +266,19 @@ static int aq_pci_probe(struct pci_dev *pdev, + mmio_pa = pci_resource_start(pdev, bar); + if (mmio_pa == 0U) { + err = -EIO; +- goto err_free_aq_hw; ++ goto err_free_aq_hw_priv; + } + + reg_sz = pci_resource_len(pdev, bar); + if ((reg_sz <= 24 /*ATL_REGS_SIZE*/)) { + err = -EIO; +- goto err_free_aq_hw; ++ goto err_free_aq_hw_priv; + } + + self->aq_hw->mmio = ioremap_nocache(mmio_pa, reg_sz); + if (!self->aq_hw->mmio) { + err = -EIO; +- goto err_free_aq_hw; ++ goto err_free_aq_hw_priv; + } + break; + } +@@ -264,7 +286,7 @@ static int aq_pci_probe(struct pci_dev *pdev, + + if (bar == 4) { + err = -EIO; +- goto err_free_aq_hw; ++ goto err_free_aq_hw_priv; + } + + numvecs = min((u8)AQ_CFG_VECS_DEF, +@@ -304,6 +326,8 @@ static int aq_pci_probe(struct pci_dev *pdev, + aq_pci_free_irq_vectors(self); + err_hwinit: + iounmap(self->aq_hw->mmio); ++err_free_aq_hw_priv: ++ kfree(self->aq_hw->priv); + err_free_aq_hw: + kfree(self->aq_hw); + err_ioremap: +@@ -327,6 +351,7 @@ static void aq_pci_remove(struct pci_dev *pdev) + aq_nic_free_vectors(self); + aq_pci_free_irq_vectors(self); + iounmap(self->aq_hw->mmio); ++ kfree(self->aq_hw->priv); + kfree(self->aq_hw); + pci_release_regions(pdev); + free_netdev(self->ndev); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +new file mode 100644 +index 000000000000..58c74a73b6cf +--- /dev/null ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -0,0 +1,226 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Atlantic Network Driver ++ * Copyright (C) 2020 Marvell International Ltd. ++ */ ++ ++#include "aq_hw.h" ++#include "hw_atl2_utils.h" ++#include "hw_atl2_internal.h" ++ ++#define DEFAULT_BOARD_BASIC_CAPABILITIES \ ++ .is_64_dma = true, \ ++ .msix_irqs = 8U, \ ++ .irq_mask = ~0U, \ ++ .vecs = HW_ATL2_RSS_MAX, \ ++ .tcs = HW_ATL2_TC_MAX, \ ++ .rxd_alignment = 1U, \ ++ .rxd_size = HW_ATL2_RXD_SIZE, \ ++ .rxds_max = HW_ATL2_MAX_RXD, \ ++ .rxds_min = HW_ATL2_MIN_RXD, \ ++ .txd_alignment = 1U, \ ++ .txd_size = HW_ATL2_TXD_SIZE, \ ++ .txds_max = HW_ATL2_MAX_TXD, \ ++ .txds_min = HW_ATL2_MIN_TXD, \ ++ .txhwb_alignment = 4096U, \ ++ .tx_rings = HW_ATL2_TX_RINGS, \ ++ .rx_rings = HW_ATL2_RX_RINGS, \ ++ .hw_features = NETIF_F_HW_CSUM | \ ++ NETIF_F_RXCSUM | \ ++ NETIF_F_RXHASH | \ ++ NETIF_F_SG | \ ++ NETIF_F_TSO | \ ++ NETIF_F_TSO6 | \ ++ NETIF_F_LRO | \ ++ NETIF_F_NTUPLE | \ ++ NETIF_F_HW_VLAN_CTAG_FILTER | \ ++ NETIF_F_HW_VLAN_CTAG_RX | \ ++ NETIF_F_HW_VLAN_CTAG_TX | \ ++ NETIF_F_GSO_UDP_L4 | \ ++ NETIF_F_GSO_PARTIAL, \ ++ .hw_priv_flags = IFF_UNICAST_FLT, \ ++ .flow_control = true, \ ++ .mtu = HW_ATL2_MTU_JUMBO, \ ++ .mac_regs_count = 72, \ ++ .hw_alive_check_addr = 0x10U, \ ++ .priv_data_len = sizeof(struct hw_atl2_priv) ++ ++const struct aq_hw_caps_s hw_atl2_caps_aqc113 = { ++ DEFAULT_BOARD_BASIC_CAPABILITIES, ++ .media_type = AQ_HW_MEDIA_TYPE_TP, ++ .link_speed_msk = AQ_NIC_RATE_10G | ++ AQ_NIC_RATE_5G | ++ AQ_NIC_RATE_2GS | ++ AQ_NIC_RATE_1G | ++ AQ_NIC_RATE_100M | ++ AQ_NIC_RATE_10M, ++}; ++ ++static int hw_atl2_hw_reset(struct aq_hw_s *self) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_rss_hash_set(struct aq_hw_s *self, ++ struct aq_rss_parameters *rss_params) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_rss_set(struct aq_hw_s *self, ++ struct aq_rss_parameters *rss_params) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_offload_set(struct aq_hw_s *self, ++ struct aq_nic_cfg_s *aq_nic_cfg) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_init(struct aq_hw_s *self, u8 *mac_addr) ++{ ++ struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; ++ u8 base_index, count; ++ int err; ++ ++ err = hw_atl2_utils_get_action_resolve_table_caps(self, &base_index, ++ &count); ++ if (err) ++ return err; ++ ++ priv->art_base_index = 8 * base_index; ++ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_ring_tx_start(struct aq_hw_s *self, ++ struct aq_ring_s *ring) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_ring_rx_start(struct aq_hw_s *self, ++ struct aq_ring_s *ring) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_start(struct aq_hw_s *self) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_ring_tx_xmit(struct aq_hw_s *self, ++ struct aq_ring_s *ring, ++ unsigned int frags) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_ring_rx_init(struct aq_hw_s *self, ++ struct aq_ring_s *aq_ring, ++ struct aq_ring_param_s *aq_ring_param) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_ring_tx_init(struct aq_hw_s *self, ++ struct aq_ring_s *aq_ring, ++ struct aq_ring_param_s *aq_ring_param) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_ring_rx_fill(struct aq_hw_s *self, struct aq_ring_s *ring, ++ unsigned int sw_tail_old) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_ring_tx_head_update(struct aq_hw_s *self, ++ struct aq_ring_s *ring) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_ring_rx_receive(struct aq_hw_s *self, ++ struct aq_ring_s *ring) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_irq_enable(struct aq_hw_s *self, u64 mask) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_irq_disable(struct aq_hw_s *self, u64 mask) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_irq_read(struct aq_hw_s *self, u64 *mask) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_interrupt_moderation_set(struct aq_hw_s *self) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_stop(struct aq_hw_s *self) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int hw_atl2_hw_ring_rx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static struct aq_stats_s *hw_atl2_utils_get_hw_stats(struct aq_hw_s *self) ++{ ++ return &self->curr_stats; ++} ++ ++const struct aq_hw_ops hw_atl2_ops = { ++ .hw_set_mac_address = hw_atl2_hw_mac_addr_set, ++ .hw_init = hw_atl2_hw_init, ++ .hw_reset = hw_atl2_hw_reset, ++ .hw_start = hw_atl2_hw_start, ++ .hw_ring_tx_start = hw_atl2_hw_ring_tx_start, ++ .hw_ring_tx_stop = hw_atl2_hw_ring_tx_stop, ++ .hw_ring_rx_start = hw_atl2_hw_ring_rx_start, ++ .hw_ring_rx_stop = hw_atl2_hw_ring_rx_stop, ++ .hw_stop = hw_atl2_hw_stop, ++ ++ .hw_ring_tx_xmit = hw_atl2_hw_ring_tx_xmit, ++ .hw_ring_tx_head_update = hw_atl2_hw_ring_tx_head_update, ++ ++ .hw_ring_rx_receive = hw_atl2_hw_ring_rx_receive, ++ .hw_ring_rx_fill = hw_atl2_hw_ring_rx_fill, ++ ++ .hw_irq_enable = hw_atl2_hw_irq_enable, ++ .hw_irq_disable = hw_atl2_hw_irq_disable, ++ .hw_irq_read = hw_atl2_hw_irq_read, ++ ++ .hw_ring_rx_init = hw_atl2_hw_ring_rx_init, ++ .hw_ring_tx_init = hw_atl2_hw_ring_tx_init, ++ .hw_interrupt_moderation_set = hw_atl2_hw_interrupt_moderation_set, ++ .hw_rss_set = hw_atl2_hw_rss_set, ++ .hw_rss_hash_set = hw_atl2_hw_rss_hash_set, ++ .hw_get_hw_stats = hw_atl2_utils_get_hw_stats, ++ .hw_set_offload = hw_atl2_hw_offload_set, ++}; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h +new file mode 100644 +index 000000000000..de8723f1c28a +--- /dev/null ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* Atlantic Network Driver ++ * Copyright (C) 2020 Marvell International Ltd. ++ */ ++ ++#ifndef HW_ATL2_H ++#define HW_ATL2_H ++ ++#include "aq_common.h" ++ ++extern const struct aq_hw_caps_s hw_atl2_caps_aqc113; ++extern const struct aq_hw_ops hw_atl2_ops; ++ ++#endif /* HW_ATL2_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +index 233db3222bb8..f82058484332 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +@@ -9,9 +9,29 @@ + #include "hw_atl2_utils.h" + + #define HW_ATL2_MTU_JUMBO 16352U ++#define HW_ATL2_MTU 1514U ++ ++#define HW_ATL2_TX_RINGS 4U ++#define HW_ATL2_RX_RINGS 4U ++ ++#define HW_ATL2_RINGS_MAX 32U ++#define HW_ATL2_TXD_SIZE (16U) ++#define HW_ATL2_RXD_SIZE (16U) ++ ++#define HW_ATL2_TC_MAX 1U ++#define HW_ATL2_RSS_MAX 8U ++ ++#define HW_ATL2_MIN_RXD \ ++ (ALIGN(AQ_CFG_SKB_FRAGS_MAX + 1U, AQ_HW_RXD_MULTIPLE)) ++#define HW_ATL2_MIN_TXD \ ++ (ALIGN(AQ_CFG_SKB_FRAGS_MAX + 1U, AQ_HW_TXD_MULTIPLE)) ++ ++#define HW_ATL2_MAX_RXD 8184U ++#define HW_ATL2_MAX_TXD 8184U + + struct hw_atl2_priv { + struct statistics_s last_stats; ++ unsigned int art_base_index; + }; + + #endif /* HW_ATL2_INTERNAL_H */ +-- +2.13.6 + diff --git a/SOURCES/0081-netdrv-net-atlantic-HW-bindings-for-A2-RFP.patch b/SOURCES/0081-netdrv-net-atlantic-HW-bindings-for-A2-RFP.patch new file mode 100644 index 0000000..c4f4e31 --- /dev/null +++ b/SOURCES/0081-netdrv-net-atlantic-HW-bindings-for-A2-RFP.patch @@ -0,0 +1,403 @@ +From 9e2c87b01c7abf6c5591972450bb4ea05ef9f5cd Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:38 -0500 +Subject: [PATCH 081/139] [netdrv] net: atlantic: HW bindings for A2 RFP + +Message-id: <1604687916-15087-82-git-send-email-irusskik@redhat.com> +Patchwork-id: 338564 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 081/139] net: atlantic: HW bindings for A2 RFP +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 57fe8fd2255cd97d2c2a9b69cb5172c0f15343b8 +Author: Igor Russkikh +Date: Thu Apr 30 11:04:40 2020 +0300 + + net: atlantic: HW bindings for A2 RFP + + RPF is one of the modules which has been significantly + changed/extended on A2. + + This patch adds the necessary A2 register definitions + for RPF, which are used in follow-up patches. + + Signed-off-by: Igor Russkikh + Co-developed-by: Dmitry Bogdanov + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 14 ++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 6 + + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.c | 74 ++++++++++ + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.h | 26 ++++ + .../atlantic/hw_atl2/hw_atl2_llh_internal.h | 164 +++++++++++++++++++++ + 5 files changed, 284 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index d1f68fc16291..8dd3232d72c4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -693,6 +693,13 @@ void hw_atl_rpfl2multicast_flr_en_set(struct aq_hw_s *aq_hw, + HW_ATL_RPFL2MC_ENF_SHIFT, l2multicast_flr_en); + } + ++u32 hw_atl_rpfl2promiscuous_mode_en_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg_bit(aq_hw, HW_ATL_RPFL2PROMIS_MODE_ADR, ++ HW_ATL_RPFL2PROMIS_MODE_MSK, ++ HW_ATL_RPFL2PROMIS_MODE_SHIFT); ++} ++ + void hw_atl_rpfl2promiscuous_mode_en_set(struct aq_hw_s *aq_hw, + u32 l2promiscuous_mode_en) + { +@@ -867,6 +874,13 @@ void hw_atl_rpf_vlan_prom_mode_en_set(struct aq_hw_s *aq_hw, + vlan_prom_mode_en); + } + ++u32 hw_atl_rpf_vlan_prom_mode_en_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg_bit(aq_hw, HW_ATL_RPF_VL_PROMIS_MODE_ADR, ++ HW_ATL_RPF_VL_PROMIS_MODE_MSK, ++ HW_ATL_RPF_VL_PROMIS_MODE_SHIFT); ++} ++ + void hw_atl_rpf_vlan_accept_untagged_packets_set(struct aq_hw_s *aq_hw, + u32 vlan_acc_untagged_packets) + { +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index 62992b23c0e8..a4699a682973 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -349,6 +349,9 @@ void hw_atl_rpfl2multicast_flr_en_set(struct aq_hw_s *aq_hw, + u32 l2multicast_flr_en, + u32 filter); + ++/* get l2 promiscuous mode enable */ ++u32 hw_atl_rpfl2promiscuous_mode_en_get(struct aq_hw_s *aq_hw); ++ + /* set l2 promiscuous mode enable */ + void hw_atl_rpfl2promiscuous_mode_en_set(struct aq_hw_s *aq_hw, + u32 l2promiscuous_mode_en); +@@ -420,6 +423,9 @@ void hw_atl_rpf_vlan_outer_etht_set(struct aq_hw_s *aq_hw, u32 vlan_outer_etht); + void hw_atl_rpf_vlan_prom_mode_en_set(struct aq_hw_s *aq_hw, + u32 vlan_prom_mode_en); + ++/* Get VLAN promiscuous mode enable */ ++u32 hw_atl_rpf_vlan_prom_mode_en_get(struct aq_hw_s *aq_hw); ++ + /* Set VLAN untagged action */ + void hw_atl_rpf_vlan_untagged_act_set(struct aq_hw_s *aq_hw, + u32 vlan_untagged_act); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +index b6164bc5fffd..67f46a7bdcda 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +@@ -7,6 +7,80 @@ + #include "hw_atl2_llh_internal.h" + #include "aq_hw_utils.h" + ++void hw_atl2_rpf_rss_hash_type_set(struct aq_hw_s *aq_hw, u32 rss_hash_type) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_ADR, ++ HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_MSK, ++ HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_SHIFT, ++ rss_hash_type); ++} ++ ++/* rpf */ ++ ++void hw_atl2_rpf_new_enable_set(struct aq_hw_s *aq_hw, u32 enable) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_NEW_EN_ADR, ++ HW_ATL2_RPF_NEW_EN_MSK, ++ HW_ATL2_RPF_NEW_EN_SHIFT, ++ enable); ++} ++ ++void hw_atl2_rpfl2_uc_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPFL2UC_TAG_ADR(filter), ++ HW_ATL2_RPFL2UC_TAG_MSK, ++ HW_ATL2_RPFL2UC_TAG_SHIFT, ++ tag); ++} ++ ++void hw_atl2_rpfl2_bc_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_L2_BC_TAG_ADR, ++ HW_ATL2_RPF_L2_BC_TAG_MSK, ++ HW_ATL2_RPF_L2_BC_TAG_SHIFT, ++ tag); ++} ++ ++void hw_atl2_new_rpf_rss_redir_set(struct aq_hw_s *aq_hw, u32 tc, u32 index, ++ u32 queue) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_RSS_REDIR_ADR(tc, index), ++ HW_ATL2_RPF_RSS_REDIR_MSK(tc), ++ HW_ATL2_RPF_RSS_REDIR_SHIFT(tc), ++ queue); ++} ++ ++void hw_atl2_rpf_vlan_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_VL_TAG_ADR(filter), ++ HW_ATL2_RPF_VL_TAG_MSK, ++ HW_ATL2_RPF_VL_TAG_SHIFT, ++ tag); ++} ++ ++/* set action resolver record */ ++void hw_atl2_rpf_act_rslvr_record_set(struct aq_hw_s *aq_hw, u8 location, ++ u32 tag, u32 mask, u32 action) ++{ ++ aq_hw_write_reg(aq_hw, ++ HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_ADR(location), ++ tag); ++ aq_hw_write_reg(aq_hw, ++ HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_ADR(location), ++ mask); ++ aq_hw_write_reg(aq_hw, ++ HW_ATL2_RPF_ACT_RSLVR_ACTN_ADR(location), ++ action); ++} ++ ++void hw_atl2_rpf_act_rslvr_section_en_set(struct aq_hw_s *aq_hw, u32 sections) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_REC_TAB_EN_ADR, ++ HW_ATL2_RPF_REC_TAB_EN_MSK, ++ HW_ATL2_RPF_REC_TAB_EN_SHIFT, ++ sections); ++} ++ + void hw_atl2_mif_shared_buf_get(struct aq_hw_s *aq_hw, int offset, u32 *data, + int len) + { +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +index 8ef8bd6b2534..bd5b0d5a8084 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +@@ -10,6 +10,32 @@ + + struct aq_hw_s; + ++/** Set RSS HASH type */ ++void hw_atl2_rpf_rss_hash_type_set(struct aq_hw_s *aq_hw, u32 rss_hash_type); ++ ++/* set new RPF enable */ ++void hw_atl2_rpf_new_enable_set(struct aq_hw_s *aq_hw, u32 enable); ++ ++/* set l2 unicast filter tag */ ++void hw_atl2_rpfl2_uc_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter); ++ ++/* set l2 broadcast filter tag */ ++void hw_atl2_rpfl2_bc_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag); ++ ++/* set new rss redirection table */ ++void hw_atl2_new_rpf_rss_redir_set(struct aq_hw_s *aq_hw, u32 tc, u32 index, ++ u32 queue); ++ ++/* Set VLAN filter tag */ ++void hw_atl2_rpf_vlan_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter); ++ ++/* set action resolver record */ ++void hw_atl2_rpf_act_rslvr_record_set(struct aq_hw_s *aq_hw, u8 location, ++ u32 tag, u32 mask, u32 action); ++ ++/* set enable action resolver section */ ++void hw_atl2_rpf_act_rslvr_section_en_set(struct aq_hw_s *aq_hw, u32 sections); ++ + /* get data from firmware shared input buffer */ + void hw_atl2_mif_shared_buf_get(struct aq_hw_s *aq_hw, int offset, u32 *data, + int len); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +index 835deb2d1950..886491b6ab73 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +@@ -6,6 +6,170 @@ + #ifndef HW_ATL2_LLH_INTERNAL_H + #define HW_ATL2_LLH_INTERNAL_H + ++/* RX pif_rpf_rss_hash_type_i Bitfield Definitions ++ */ ++#define HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_ADR 0x000054C8 ++#define HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_MSK 0x000001FF ++#define HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_MSKN 0xFFFFFE00 ++#define HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_SHIFT 0 ++#define HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_WIDTH 9 ++ ++/* rx rpf_new_rpf_en bitfield definitions ++ * preprocessor definitions for the bitfield "rpf_new_rpf_en_i". ++ * port="pif_rpf_new_rpf_en_i ++ */ ++ ++/* register address for bitfield rpf_new_rpf_en */ ++#define HW_ATL2_RPF_NEW_EN_ADR 0x00005104 ++/* bitmask for bitfield rpf_new_rpf_en */ ++#define HW_ATL2_RPF_NEW_EN_MSK 0x00000800 ++/* inverted bitmask for bitfield rpf_new_rpf_en */ ++#define HW_ATL2_RPF_NEW_EN_MSKN 0xfffff7ff ++/* lower bit position of bitfield rpf_new_rpf_en */ ++#define HW_ATL2_RPF_NEW_EN_SHIFT 11 ++/* width of bitfield rpf_new_rpf_en */ ++#define HW_ATL2_RPF_NEW_EN_WIDTH 1 ++/* default value of bitfield rpf_new_rpf_en */ ++#define HW_ATL2_RPF_NEW_EN_DEFAULT 0x0 ++ ++/* rx l2_uc_req_tag0{f}[5:0] bitfield definitions ++ * preprocessor definitions for the bitfield "l2_uc_req_tag0{f}[7:0]". ++ * parameter: filter {f} | stride size 0x8 | range [0, 37] ++ * port="pif_rpf_l2_uc_req_tag0[5:0]" ++ */ ++ ++/* register address for bitfield l2_uc_req_tag0{f}[2:0] */ ++#define HW_ATL2_RPFL2UC_TAG_ADR(filter) (0x00005114 + (filter) * 0x8) ++/* bitmask for bitfield l2_uc_req_tag0{f}[2:0] */ ++#define HW_ATL2_RPFL2UC_TAG_MSK 0x0FC00000 ++/* inverted bitmask for bitfield l2_uc_req_tag0{f}[2:0] */ ++#define HW_ATL2_RPFL2UC_TAG_MSKN 0xF03FFFFF ++/* lower bit position of bitfield l2_uc_req_tag0{f}[2:0] */ ++#define HW_ATL2_RPFL2UC_TAG_SHIFT 22 ++/* width of bitfield l2_uc_req_tag0{f}[2:0] */ ++#define HW_ATL2_RPFL2UC_TAG_WIDTH 6 ++/* default value of bitfield l2_uc_req_tag0{f}[2:0] */ ++#define HW_ATL2_RPFL2UC_TAG_DEFAULT 0x0 ++ ++/* rpf_l2_bc_req_tag[5:0] bitfield definitions ++ * preprocessor definitions for the bitfield "rpf_l2_bc_req_tag[5:0]". ++ * port="pifrpf_l2_bc_req_tag_i[5:0]" ++ */ ++ ++/* register address for bitfield rpf_l2_bc_req_tag */ ++#define HW_ATL2_RPF_L2_BC_TAG_ADR 0x000050F0 ++/* bitmask for bitfield rpf_l2_bc_req_tag */ ++#define HW_ATL2_RPF_L2_BC_TAG_MSK 0x0000003F ++/* inverted bitmask for bitfield rpf_l2_bc_req_tag */ ++#define HW_ATL2_RPF_L2_BC_TAG_MSKN 0xffffffc0 ++/* lower bit position of bitfield rpf_l2_bc_req_tag */ ++#define HW_ATL2_RPF_L2_BC_TAG_SHIFT 0 ++/* width of bitfield rpf_l2_bc_req_tag */ ++#define HW_ATL2_RPF_L2_BC_TAG_WIDTH 6 ++/* default value of bitfield rpf_l2_bc_req_tag */ ++#define HW_ATL2_RPF_L2_BC_TAG_DEFAULT 0x0 ++ ++/* rx rpf_rss_red1_data_[4:0] bitfield definitions ++ * preprocessor definitions for the bitfield "rpf_rss_red1_data[4:0]". ++ * port="pif_rpf_rss_red1_data_i[4:0]" ++ */ ++ ++/* register address for bitfield rpf_rss_red1_data[4:0] */ ++#define HW_ATL2_RPF_RSS_REDIR_ADR(TC, INDEX) (0x00006200 + \ ++ (0x100 * !!((TC) > 3)) + (INDEX) * 4) ++/* bitmask for bitfield rpf_rss_red1_data[4:0] */ ++#define HW_ATL2_RPF_RSS_REDIR_MSK(TC) (0x00000001F << (5 * ((TC) % 4))) ++/* lower bit position of bitfield rpf_rss_red1_data[4:0] */ ++#define HW_ATL2_RPF_RSS_REDIR_SHIFT(TC) (5 * ((TC) % 4)) ++/* width of bitfield rpf_rss_red1_data[4:0] */ ++#define HW_ATL2_RPF_RSS_REDIR_WIDTH 5 ++/* default value of bitfield rpf_rss_red1_data[4:0] */ ++#define HW_ATL2_RPF_RSS_REDIR_DEFAULT 0x0 ++ ++/* rx vlan_req_tag0{f}[3:0] bitfield definitions ++ * preprocessor definitions for the bitfield "vlan_req_tag0{f}[3:0]". ++ * parameter: filter {f} | stride size 0x4 | range [0, 15] ++ * port="pif_rpf_vlan_req_tag0[3:0]" ++ */ ++ ++/* register address for bitfield vlan_req_tag0{f}[3:0] */ ++#define HW_ATL2_RPF_VL_TAG_ADR(filter) (0x00005290 + (filter) * 0x4) ++/* bitmask for bitfield vlan_req_tag0{f}[3:0] */ ++#define HW_ATL2_RPF_VL_TAG_MSK 0x0000F000 ++/* inverted bitmask for bitfield vlan_req_tag0{f}[3:0] */ ++#define HW_ATL2_RPF_VL_TAG_MSKN 0xFFFF0FFF ++/* lower bit position of bitfield vlan_req_tag0{f}[3:0] */ ++#define HW_ATL2_RPF_VL_TAG_SHIFT 12 ++/* width of bitfield vlan_req_tag0{f}[3:0] */ ++#define HW_ATL2_RPF_VL_TAG_WIDTH 4 ++/* default value of bitfield vlan_req_tag0{f}[3:0] */ ++#define HW_ATL2_RPF_VL_TAG_DEFAULT 0x0 ++ ++/* ahb_mem_addr{f}[31:0] Bitfield Definitions ++ * Preprocessor definitions for the bitfield "ahb_mem_addr{f}[31:0]". ++ * Parameter: filter {f} | stride size 0x10 | range [0, 127] ++ * PORT="ahb_mem_addr{f}[31:0]" ++ */ ++ ++/* Register address for bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_ADR(filter) \ ++ (0x00014000u + (filter) * 0x10) ++/* Bitmask for bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_MSK 0xFFFFFFFFu ++/* Inverted bitmask for bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_MSKN 0x00000000u ++/* Lower bit position of bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_SHIFT 0 ++/* Width of bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_WIDTH 31 ++/* Default value of bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_REQ_TAG_DEFAULT 0x0 ++ ++/* Register address for bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_ADR(filter) \ ++ (0x00014004u + (filter) * 0x10) ++/* Bitmask for bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_MSK 0xFFFFFFFFu ++/* Inverted bitmask for bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_MSKN 0x00000000u ++/* Lower bit position of bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_SHIFT 0 ++/* Width of bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_WIDTH 31 ++/* Default value of bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_TAG_MASK_DEFAULT 0x0 ++ ++/* Register address for bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_ACTN_ADR(filter) \ ++ (0x00014008u + (filter) * 0x10) ++/* Bitmask for bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_ACTN_MSK 0x000007FFu ++/* Inverted bitmask for bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_ACTN_MSKN 0xFFFFF800u ++/* Lower bit position of bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_ACTN_SHIFT 0 ++/* Width of bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_ACTN_WIDTH 10 ++/* Default value of bitfield ahb_mem_addr{f}[31:0] */ ++#define HW_ATL2_RPF_ACT_RSLVR_ACTN_DEFAULT 0x0 ++ ++/* rpf_rec_tab_en[15:0] Bitfield Definitions ++ * Preprocessor definitions for the bitfield "rpf_rec_tab_en[15:0]". ++ * PORT="pif_rpf_rec_tab_en[15:0]" ++ */ ++/* Register address for bitfield rpf_rec_tab_en[15:0] */ ++#define HW_ATL2_RPF_REC_TAB_EN_ADR 0x00006ff0u ++/* Bitmask for bitfield rpf_rec_tab_en[15:0] */ ++#define HW_ATL2_RPF_REC_TAB_EN_MSK 0x0000FFFFu ++/* Inverted bitmask for bitfield rpf_rec_tab_en[15:0] */ ++#define HW_ATL2_RPF_REC_TAB_EN_MSKN 0xFFFF0000u ++/* Lower bit position of bitfield rpf_rec_tab_en[15:0] */ ++#define HW_ATL2_RPF_REC_TAB_EN_SHIFT 0 ++/* Width of bitfield rpf_rec_tab_en[15:0] */ ++#define HW_ATL2_RPF_REC_TAB_EN_WIDTH 16 ++/* Default value of bitfield rpf_rec_tab_en[15:0] */ ++#define HW_ATL2_RPF_REC_TAB_EN_DEFAULT 0x0 ++ + /* Register address for firmware shared input buffer */ + #define HW_ATL2_MIF_SHARED_BUFFER_IN_ADR(dword) (0x00012000U + (dword) * 0x4U) + /* Register address for firmware shared output buffer */ +-- +2.13.6 + diff --git a/SOURCES/0082-netdrv-net-atlantic-add-A2-RPF-hw_ops.patch b/SOURCES/0082-netdrv-net-atlantic-add-A2-RPF-hw_ops.patch new file mode 100644 index 0000000..10795d4 --- /dev/null +++ b/SOURCES/0082-netdrv-net-atlantic-add-A2-RPF-hw_ops.patch @@ -0,0 +1,382 @@ +From 2c0c3a7adc16dcbf6f8841f074e2b23f2cb0057c Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:39 -0500 +Subject: [PATCH 082/139] [netdrv] net: atlantic: add A2 RPF hw_ops + +Message-id: <1604687916-15087-83-git-send-email-irusskik@redhat.com> +Patchwork-id: 338504 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 082/139] net: atlantic: add A2 RPF hw_ops +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 3417368494db497c0426d1dcc46c4c459ff43ca7 +Author: Igor Russkikh +Date: Thu Apr 30 11:04:41 2020 +0300 + + net: atlantic: add A2 RPF hw_ops + + This patch adds RPF-related hw_ops, which are needed for basic + functionality. + + Signed-off-by: Igor Russkikh + Co-developed-by: Dmitry Bogdanov + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../aquantia/atlantic/hw_atl/hw_atl_utils.h | 2 + + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 208 +++++++++++++++++++++ + .../aquantia/atlantic/hw_atl2/hw_atl2_internal.h | 49 +++++ + 3 files changed, 259 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index 36084152c4c3..f293c6b9249d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -334,6 +334,8 @@ struct aq_rx_filter_vlan { + u8 queue; + }; + ++#define HW_ATL_VLAN_MAX_FILTERS 16U ++ + struct aq_rx_filter_l2 { + s8 queue; + u8 location; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index 58c74a73b6cf..7dd5f9a1c505 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -4,9 +4,17 @@ + */ + + #include "aq_hw.h" ++#include "aq_hw_utils.h" ++#include "aq_nic.h" ++#include "hw_atl/hw_atl_utils.h" ++#include "hw_atl/hw_atl_llh.h" + #include "hw_atl2_utils.h" ++#include "hw_atl2_llh.h" + #include "hw_atl2_internal.h" + ++static int hw_atl2_act_rslvr_table_set(struct aq_hw_s *self, u8 location, ++ u32 tag, u32 mask, u32 action); ++ + #define DEFAULT_BOARD_BASIC_CAPABILITIES \ + .is_64_dma = true, \ + .msix_irqs = 8U, \ +@@ -55,6 +63,11 @@ const struct aq_hw_caps_s hw_atl2_caps_aqc113 = { + AQ_NIC_RATE_10M, + }; + ++static u32 hw_atl2_sem_act_rslvr_get(struct aq_hw_s *self) ++{ ++ return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL2_FW_SM_ACT_RSLVR); ++} ++ + static int hw_atl2_hw_reset(struct aq_hw_s *self) + { + return -EOPNOTSUPP; +@@ -78,6 +91,60 @@ static int hw_atl2_hw_offload_set(struct aq_hw_s *self, + return -EOPNOTSUPP; + } + ++static void hw_atl2_hw_new_rx_filter_vlan_promisc(struct aq_hw_s *self, ++ bool promisc) ++{ ++ u16 off_action = (!promisc && ++ !hw_atl_rpfl2promiscuous_mode_en_get(self)) ? ++ HW_ATL2_ACTION_DROP : HW_ATL2_ACTION_DISABLE; ++ struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; ++ u8 index; ++ ++ index = priv->art_base_index + HW_ATL2_RPF_VLAN_PROMISC_OFF_INDEX; ++ hw_atl2_act_rslvr_table_set(self, index, 0, ++ HW_ATL2_RPF_TAG_VLAN_MASK | ++ HW_ATL2_RPF_TAG_UNTAG_MASK, off_action); ++} ++ ++static void hw_atl2_hw_new_rx_filter_promisc(struct aq_hw_s *self, bool promisc) ++{ ++ u16 off_action = promisc ? HW_ATL2_ACTION_DISABLE : HW_ATL2_ACTION_DROP; ++ struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; ++ bool vlan_promisc_enable; ++ u8 index; ++ ++ index = priv->art_base_index + HW_ATL2_RPF_L2_PROMISC_OFF_INDEX; ++ hw_atl2_act_rslvr_table_set(self, index, 0, ++ HW_ATL2_RPF_TAG_UC_MASK | ++ HW_ATL2_RPF_TAG_ALLMC_MASK, ++ off_action); ++ ++ /* turn VLAN promisc mode too */ ++ vlan_promisc_enable = hw_atl_rpf_vlan_prom_mode_en_get(self); ++ hw_atl2_hw_new_rx_filter_vlan_promisc(self, promisc | ++ vlan_promisc_enable); ++} ++ ++static int hw_atl2_act_rslvr_table_set(struct aq_hw_s *self, u8 location, ++ u32 tag, u32 mask, u32 action) ++{ ++ u32 val; ++ int err; ++ ++ err = readx_poll_timeout_atomic(hw_atl2_sem_act_rslvr_get, ++ self, val, val == 1, ++ 1, 10000U); ++ if (err) ++ return err; ++ ++ hw_atl2_rpf_act_rslvr_record_set(self, location, tag, mask, ++ action); ++ ++ hw_atl_reg_glb_cpu_sem_set(self, 1, HW_ATL2_FW_SM_ACT_RSLVR); ++ ++ return err; ++} ++ + static int hw_atl2_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) + { + return -EOPNOTSUPP; +@@ -170,6 +237,88 @@ static int hw_atl2_hw_irq_read(struct aq_hw_s *self, u64 *mask) + return -EOPNOTSUPP; + } + ++#define IS_FILTER_ENABLED(_F_) ((packet_filter & (_F_)) ? 1U : 0U) ++ ++static int hw_atl2_hw_packet_filter_set(struct aq_hw_s *self, ++ unsigned int packet_filter) ++{ ++ struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; ++ u32 vlan_promisc; ++ u32 l2_promisc; ++ unsigned int i; ++ ++ l2_promisc = IS_FILTER_ENABLED(IFF_PROMISC) || ++ !!(cfg->priv_flags & BIT(AQ_HW_LOOPBACK_DMA_NET)); ++ vlan_promisc = l2_promisc || cfg->is_vlan_force_promisc; ++ ++ hw_atl_rpfl2promiscuous_mode_en_set(self, l2_promisc); ++ ++ hw_atl_rpf_vlan_prom_mode_en_set(self, vlan_promisc); ++ ++ hw_atl2_hw_new_rx_filter_promisc(self, IS_FILTER_ENABLED(IFF_PROMISC)); ++ ++ hw_atl_rpfl2multicast_flr_en_set(self, ++ IS_FILTER_ENABLED(IFF_ALLMULTI) && ++ IS_FILTER_ENABLED(IFF_MULTICAST), 0); ++ ++ hw_atl_rpfl2_accept_all_mc_packets_set(self, ++ IS_FILTER_ENABLED(IFF_ALLMULTI) && ++ IS_FILTER_ENABLED(IFF_MULTICAST)); ++ ++ hw_atl_rpfl2broadcast_en_set(self, IS_FILTER_ENABLED(IFF_BROADCAST)); ++ ++ for (i = HW_ATL2_MAC_MIN; i < HW_ATL2_MAC_MAX; ++i) ++ hw_atl_rpfl2_uc_flr_en_set(self, ++ (cfg->is_mc_list_enabled && ++ (i <= cfg->mc_list_count)) ? ++ 1U : 0U, i); ++ ++ return aq_hw_err_from_flags(self); ++} ++ ++#undef IS_FILTER_ENABLED ++ ++static int hw_atl2_hw_multicast_list_set(struct aq_hw_s *self, ++ u8 ar_mac ++ [AQ_HW_MULTICAST_ADDRESS_MAX] ++ [ETH_ALEN], ++ u32 count) ++{ ++ struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; ++ int err = 0; ++ ++ if (count > (HW_ATL2_MAC_MAX - HW_ATL2_MAC_MIN)) { ++ err = -EBADRQC; ++ goto err_exit; ++ } ++ for (cfg->mc_list_count = 0U; ++ cfg->mc_list_count < count; ++ ++cfg->mc_list_count) { ++ u32 i = cfg->mc_list_count; ++ u32 h = (ar_mac[i][0] << 8) | (ar_mac[i][1]); ++ u32 l = (ar_mac[i][2] << 24) | (ar_mac[i][3] << 16) | ++ (ar_mac[i][4] << 8) | ar_mac[i][5]; ++ ++ hw_atl_rpfl2_uc_flr_en_set(self, 0U, HW_ATL2_MAC_MIN + i); ++ ++ hw_atl_rpfl2unicast_dest_addresslsw_set(self, l, ++ HW_ATL2_MAC_MIN + i); ++ ++ hw_atl_rpfl2unicast_dest_addressmsw_set(self, h, ++ HW_ATL2_MAC_MIN + i); ++ ++ hw_atl2_rpfl2_uc_flr_tag_set(self, 1, HW_ATL2_MAC_MIN + i); ++ ++ hw_atl_rpfl2_uc_flr_en_set(self, (cfg->is_mc_list_enabled), ++ HW_ATL2_MAC_MIN + i); ++ } ++ ++ err = aq_hw_err_from_flags(self); ++ ++err_exit: ++ return err; ++} ++ + static int hw_atl2_hw_interrupt_moderation_set(struct aq_hw_s *self) + { + return -EOPNOTSUPP; +@@ -195,6 +344,61 @@ static struct aq_stats_s *hw_atl2_utils_get_hw_stats(struct aq_hw_s *self) + return &self->curr_stats; + } + ++static int hw_atl2_hw_vlan_set(struct aq_hw_s *self, ++ struct aq_rx_filter_vlan *aq_vlans) ++{ ++ struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; ++ u32 queue; ++ u8 index; ++ int i; ++ ++ hw_atl_rpf_vlan_prom_mode_en_set(self, 1U); ++ ++ for (i = 0; i < HW_ATL_VLAN_MAX_FILTERS; i++) { ++ queue = HW_ATL2_ACTION_ASSIGN_QUEUE(aq_vlans[i].queue); ++ ++ hw_atl_rpf_vlan_flr_en_set(self, 0U, i); ++ hw_atl_rpf_vlan_rxq_en_flr_set(self, 0U, i); ++ index = priv->art_base_index + HW_ATL2_RPF_VLAN_USER_INDEX + i; ++ hw_atl2_act_rslvr_table_set(self, index, 0, 0, ++ HW_ATL2_ACTION_DISABLE); ++ if (aq_vlans[i].enable) { ++ hw_atl_rpf_vlan_id_flr_set(self, ++ aq_vlans[i].vlan_id, i); ++ hw_atl_rpf_vlan_flr_act_set(self, 1U, i); ++ hw_atl_rpf_vlan_flr_en_set(self, 1U, i); ++ ++ if (aq_vlans[i].queue != 0xFF) { ++ hw_atl_rpf_vlan_rxq_flr_set(self, ++ aq_vlans[i].queue, ++ i); ++ hw_atl_rpf_vlan_rxq_en_flr_set(self, 1U, i); ++ ++ hw_atl2_rpf_vlan_flr_tag_set(self, i + 2, i); ++ ++ index = priv->art_base_index + ++ HW_ATL2_RPF_VLAN_USER_INDEX + i; ++ hw_atl2_act_rslvr_table_set(self, index, ++ (i + 2) << HW_ATL2_RPF_TAG_VLAN_OFFSET, ++ HW_ATL2_RPF_TAG_VLAN_MASK, queue); ++ } else { ++ hw_atl2_rpf_vlan_flr_tag_set(self, 1, i); ++ } ++ } ++ } ++ ++ return aq_hw_err_from_flags(self); ++} ++ ++static int hw_atl2_hw_vlan_ctrl(struct aq_hw_s *self, bool enable) ++{ ++ /* set promisc in case of disabing the vlan filter */ ++ hw_atl_rpf_vlan_prom_mode_en_set(self, !enable); ++ hw_atl2_hw_new_rx_filter_vlan_promisc(self, !enable); ++ ++ return aq_hw_err_from_flags(self); ++} ++ + const struct aq_hw_ops hw_atl2_ops = { + .hw_set_mac_address = hw_atl2_hw_mac_addr_set, + .hw_init = hw_atl2_hw_init, +@@ -218,6 +422,10 @@ const struct aq_hw_ops hw_atl2_ops = { + + .hw_ring_rx_init = hw_atl2_hw_ring_rx_init, + .hw_ring_tx_init = hw_atl2_hw_ring_tx_init, ++ .hw_packet_filter_set = hw_atl2_hw_packet_filter_set, ++ .hw_filter_vlan_set = hw_atl2_hw_vlan_set, ++ .hw_filter_vlan_ctrl = hw_atl2_hw_vlan_ctrl, ++ .hw_multicast_list_set = hw_atl2_hw_multicast_list_set, + .hw_interrupt_moderation_set = hw_atl2_hw_interrupt_moderation_set, + .hw_rss_set = hw_atl2_hw_rss_set, + .hw_rss_hash_set = hw_atl2_hw_rss_hash_set, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +index f82058484332..dccc89df2223 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +@@ -18,6 +18,10 @@ + #define HW_ATL2_TXD_SIZE (16U) + #define HW_ATL2_RXD_SIZE (16U) + ++#define HW_ATL2_MAC_UC 0U ++#define HW_ATL2_MAC_MIN 1U ++#define HW_ATL2_MAC_MAX 38U ++ + #define HW_ATL2_TC_MAX 1U + #define HW_ATL2_RSS_MAX 8U + +@@ -29,6 +33,51 @@ + #define HW_ATL2_MAX_RXD 8184U + #define HW_ATL2_MAX_TXD 8184U + ++#define HW_ATL2_FW_SM_ACT_RSLVR 0x3U ++ ++#define HW_ATL2_RPF_TAG_UC_OFFSET 0x0 ++#define HW_ATL2_RPF_TAG_ALLMC_OFFSET 0x6 ++#define HW_ATL2_RPF_TAG_ET_OFFSET 0x7 ++#define HW_ATL2_RPF_TAG_VLAN_OFFSET 0xA ++#define HW_ATL2_RPF_TAG_UNTAG_OFFSET 0xE ++#define HW_ATL2_RPF_TAG_L3_V4_OFFSET 0xF ++#define HW_ATL2_RPF_TAG_L3_V6_OFFSET 0x12 ++#define HW_ATL2_RPF_TAG_L4_OFFSET 0x15 ++#define HW_ATL2_RPF_TAG_L4_FLEX_OFFSET 0x18 ++#define HW_ATL2_RPF_TAG_FLEX_OFFSET 0x1B ++#define HW_ATL2_RPF_TAG_PCP_OFFSET 0x1D ++ ++#define HW_ATL2_RPF_TAG_UC_MASK (0x0000003F << HW_ATL2_RPF_TAG_UC_OFFSET) ++#define HW_ATL2_RPF_TAG_ALLMC_MASK (0x00000001 << HW_ATL2_RPF_TAG_ALLMC_OFFSET) ++#define HW_ATL2_RPF_TAG_UNTAG_MASK (0x00000001 << HW_ATL2_RPF_TAG_UNTAG_OFFSET) ++#define HW_ATL2_RPF_TAG_VLAN_MASK (0x0000000F << HW_ATL2_RPF_TAG_VLAN_OFFSET) ++#define HW_ATL2_RPF_TAG_ET_MASK (0x00000007 << HW_ATL2_RPF_TAG_ET_OFFSET) ++#define HW_ATL2_RPF_TAG_L3_V4_MASK (0x00000007 << HW_ATL2_RPF_TAG_L3_V4_OFFSET) ++#define HW_ATL2_RPF_TAG_L3_V6_MASK (0x00000007 << HW_ATL2_RPF_TAG_L3_V6_OFFSET) ++#define HW_ATL2_RPF_TAG_L4_MASK (0x00000007 << HW_ATL2_RPF_TAG_L4_OFFSET) ++#define HW_ATL2_RPF_TAG_PCP_MASK (0x00000007 << HW_ATL2_RPF_TAG_PCP_OFFSET) ++ ++enum HW_ATL2_RPF_ART_INDEX { ++ HW_ATL2_RPF_L2_PROMISC_OFF_INDEX, ++ HW_ATL2_RPF_VLAN_PROMISC_OFF_INDEX, ++ HW_ATL2_RPF_L3L4_USER_INDEX = 8, ++ HW_ATL2_RPF_ET_PCP_USER_INDEX = HW_ATL2_RPF_L3L4_USER_INDEX + 16, ++ HW_ATL2_RPF_VLAN_USER_INDEX = HW_ATL2_RPF_ET_PCP_USER_INDEX + 16, ++ HW_ATL2_RPF_PCP_TO_TC_INDEX = HW_ATL2_RPF_VLAN_USER_INDEX + ++ HW_ATL_VLAN_MAX_FILTERS, ++}; ++ ++#define HW_ATL2_ACTION(ACTION, RSS, INDEX, VALID) \ ++ ((((ACTION) & 0x3U) << 8) | \ ++ (((RSS) & 0x1U) << 7) | \ ++ (((INDEX) & 0x3FU) << 2) | \ ++ (((VALID) & 0x1U) << 0)) ++ ++#define HW_ATL2_ACTION_DROP HW_ATL2_ACTION(0, 0, 0, 1) ++#define HW_ATL2_ACTION_DISABLE HW_ATL2_ACTION(0, 0, 0, 0) ++#define HW_ATL2_ACTION_ASSIGN_QUEUE(QUEUE) HW_ATL2_ACTION(1, 0, (QUEUE), 1) ++#define HW_ATL2_ACTION_ASSIGN_TC(TC) HW_ATL2_ACTION(1, 1, (TC), 1) ++ + struct hw_atl2_priv { + struct statistics_s last_stats; + unsigned int art_base_index; +-- +2.13.6 + diff --git a/SOURCES/0083-netdrv-net-atlantic-HW-bindings-for-basic-A2-init-de.patch b/SOURCES/0083-netdrv-net-atlantic-HW-bindings-for-basic-A2-init-de.patch new file mode 100644 index 0000000..64674fb --- /dev/null +++ b/SOURCES/0083-netdrv-net-atlantic-HW-bindings-for-basic-A2-init-de.patch @@ -0,0 +1,304 @@ +From 33d75d80def058590e71d79f0d536e13d48e8306 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:40 -0500 +Subject: [PATCH 083/139] [netdrv] net: atlantic: HW bindings for basic A2 + init/deinit hw_ops + +Message-id: <1604687916-15087-84-git-send-email-irusskik@redhat.com> +Patchwork-id: 338512 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 083/139] net: atlantic: HW bindings for basic A2 init/deinit hw_ops +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit ec7629e0c2217963eedb886026a71040c9d32aa9 +Author: Dmitry Bogdanov +Date: Thu Apr 30 11:04:42 2020 +0300 + + net: atlantic: HW bindings for basic A2 init/deinit hw_ops + + This patch adds A2 register definitions for basic A2 HW + initialization / deinitialization. + + Signed-off-by: Dmitry Bogdanov + Co-developed-by: Egor Pomozov + Signed-off-by: Egor Pomozov + Co-developed-by: Igor Russkikh + Signed-off-by: Igor Russkikh + Co-developed-by: Nikita Danilov + Signed-off-by: Nikita Danilov + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.c | 70 +++++++++++++ + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.h | 29 ++++++ + .../atlantic/hw_atl2/hw_atl2_llh_internal.h | 108 +++++++++++++++++++++ + 3 files changed, 207 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +index 67f46a7bdcda..af176e1e5a18 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +@@ -58,6 +58,55 @@ void hw_atl2_rpf_vlan_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter) + tag); + } + ++/* TX */ ++ ++void hw_atl2_tpb_tx_buf_clk_gate_en_set(struct aq_hw_s *aq_hw, u32 clk_gate_en) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_ADR, ++ HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_MSK, ++ HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_SHIFT, ++ clk_gate_en); ++} ++ ++void hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw, ++ u32 max_credit, ++ u32 tc) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPS_DATA_TCTCREDIT_MAX_ADR(tc), ++ HW_ATL2_TPS_DATA_TCTCREDIT_MAX_MSK, ++ HW_ATL2_TPS_DATA_TCTCREDIT_MAX_SHIFT, ++ max_credit); ++} ++ ++void hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw, ++ u32 tx_pkt_shed_tc_data_weight, ++ u32 tc) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPS_DATA_TCTWEIGHT_ADR(tc), ++ HW_ATL2_TPS_DATA_TCTWEIGHT_MSK, ++ HW_ATL2_TPS_DATA_TCTWEIGHT_SHIFT, ++ tx_pkt_shed_tc_data_weight); ++} ++ ++u32 hw_atl2_get_hw_version(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg(aq_hw, HW_ATL2_FPGA_VER_ADR); ++} ++ ++void hw_atl2_init_launchtime(struct aq_hw_s *aq_hw) ++{ ++ u32 hw_ver = hw_atl2_get_hw_version(aq_hw); ++ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_LT_CTRL_ADR, ++ HW_ATL2_LT_CTRL_CLK_RATIO_MSK, ++ HW_ATL2_LT_CTRL_CLK_RATIO_SHIFT, ++ hw_ver < HW_ATL2_FPGA_VER_U32(1, 0, 0, 0) ? ++ HW_ATL2_LT_CTRL_CLK_RATIO_FULL_SPEED : ++ hw_ver >= HW_ATL2_FPGA_VER_U32(1, 0, 85, 2) ? ++ HW_ATL2_LT_CTRL_CLK_RATIO_HALF_SPEED : ++ HW_ATL2_LT_CTRL_CLK_RATIO_QUATER_SPEED); ++} ++ + /* set action resolver record */ + void hw_atl2_rpf_act_rslvr_record_set(struct aq_hw_s *aq_hw, u8 location, + u32 tag, u32 mask, u32 action) +@@ -128,3 +177,24 @@ u32 hw_atl2_mif_mcp_finished_read_get(struct aq_hw_s *aq_hw) + HW_ATL2_MIF_MCP_FINISHED_READ_MSK, + HW_ATL2_MIF_MCP_FINISHED_READ_SHIFT); + } ++ ++u32 hw_atl2_mif_mcp_boot_reg_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg(aq_hw, HW_ATL2_MIF_BOOT_REG_ADR); ++} ++ ++void hw_atl2_mif_mcp_boot_reg_set(struct aq_hw_s *aq_hw, u32 val) ++{ ++ return aq_hw_write_reg(aq_hw, HW_ATL2_MIF_BOOT_REG_ADR, val); ++} ++ ++u32 hw_atl2_mif_host_req_int_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg(aq_hw, HW_ATL2_MCP_HOST_REQ_INT_ADR); ++} ++ ++void hw_atl2_mif_host_req_int_clr(struct aq_hw_s *aq_hw, u32 val) ++{ ++ return aq_hw_write_reg(aq_hw, HW_ATL2_MCP_HOST_REQ_INT_CLR_ADR, ++ val); ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +index bd5b0d5a8084..4acbbceb623f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +@@ -29,6 +29,23 @@ void hw_atl2_new_rpf_rss_redir_set(struct aq_hw_s *aq_hw, u32 tc, u32 index, + /* Set VLAN filter tag */ + void hw_atl2_rpf_vlan_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter); + ++/* set tx buffer clock gate enable */ ++void hw_atl2_tpb_tx_buf_clk_gate_en_set(struct aq_hw_s *aq_hw, u32 clk_gate_en); ++ ++/* set tx packet scheduler tc data max credit */ ++void hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw, ++ u32 max_credit, ++ u32 tc); ++ ++/* set tx packet scheduler tc data weight */ ++void hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw, ++ u32 tx_pkt_shed_tc_data_weight, ++ u32 tc); ++ ++u32 hw_atl2_get_hw_version(struct aq_hw_s *aq_hw); ++ ++void hw_atl2_init_launchtime(struct aq_hw_s *aq_hw); ++ + /* set action resolver record */ + void hw_atl2_rpf_act_rslvr_record_set(struct aq_hw_s *aq_hw, u8 location, + u32 tag, u32 mask, u32 action); +@@ -54,4 +71,16 @@ void hw_atl2_mif_host_finished_write_set(struct aq_hw_s *aq_hw, u32 finish); + /* get mcp finished read shared buffer indication */ + u32 hw_atl2_mif_mcp_finished_read_get(struct aq_hw_s *aq_hw); + ++/* get mcp boot register */ ++u32 hw_atl2_mif_mcp_boot_reg_get(struct aq_hw_s *aq_hw); ++ ++/* set mcp boot register */ ++void hw_atl2_mif_mcp_boot_reg_set(struct aq_hw_s *aq_hw, u32 val); ++ ++/* get host interrupt request */ ++u32 hw_atl2_mif_host_req_int_get(struct aq_hw_s *aq_hw); ++ ++/* clear host interrupt request */ ++void hw_atl2_mif_host_req_int_clr(struct aq_hw_s *aq_hw, u32 val); ++ + #endif /* HW_ATL2_LLH_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +index 886491b6ab73..14b78e090950 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +@@ -105,6 +105,105 @@ + /* default value of bitfield vlan_req_tag0{f}[3:0] */ + #define HW_ATL2_RPF_VL_TAG_DEFAULT 0x0 + ++/* RX rx_q{Q}_tc_map[2:0] Bitfield Definitions ++ * Preprocessor definitions for the bitfield "rx_q{Q}_tc_map[2:0]". ++ * Parameter: Queue {Q} | bit-level stride | range [0, 31] ++ * PORT="pif_rx_q0_tc_map_i[2:0]" ++ */ ++ ++/* Register address for bitfield rx_q{Q}_tc_map[2:0] */ ++#define HW_ATL2_RX_Q_TC_MAP_ADR(queue) \ ++ (((queue) < 32) ? 0x00005900 + ((queue) / 8) * 4 : 0) ++/* Lower bit position of bitfield rx_q{Q}_tc_map[2:0] */ ++#define HW_ATL2_RX_Q_TC_MAP_SHIFT(queue) \ ++ (((queue) < 32) ? ((queue) * 4) % 32 : 0) ++/* Width of bitfield rx_q{Q}_tc_map[2:0] */ ++#define HW_ATL2_RX_Q_TC_MAP_WIDTH 3 ++/* Default value of bitfield rx_q{Q}_tc_map[2:0] */ ++#define HW_ATL2_RX_Q_TC_MAP_DEFAULT 0x0 ++ ++/* tx tx_buffer_clk_gate_en bitfield definitions ++ * preprocessor definitions for the bitfield "tx_buffer_clk_gate_en". ++ * port="pif_tpb_tx_buffer_clk_gate_en_i" ++ */ ++ ++/* register address for bitfield tx_buffer_clk_gate_en */ ++#define HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_ADR 0x00007900 ++/* bitmask for bitfield tx_buffer_clk_gate_en */ ++#define HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_MSK 0x00000020 ++/* inverted bitmask for bitfield tx_buffer_clk_gate_en */ ++#define HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_MSKN 0xffffffdf ++/* lower bit position of bitfield tx_buffer_clk_gate_en */ ++#define HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_SHIFT 5 ++/* width of bitfield tx_buffer_clk_gate_en */ ++#define HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_WIDTH 1 ++/* default value of bitfield tx_buffer_clk_gate_en */ ++#define HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_DEFAULT 0x0 ++ ++/* tx data_tc{t}_credit_max[b:0] bitfield definitions ++ * preprocessor definitions for the bitfield "data_tc{t}_credit_max[b:0]". ++ * parameter: tc {t} | stride size 0x4 | range [0, 7] ++ * port="pif_tps_data_tc0_credit_max_i[11:0]" ++ */ ++ ++/* register address for bitfield data_tc{t}_credit_max[b:0] */ ++#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_ADR(tc) (0x00007110 + (tc) * 0x4) ++/* bitmask for bitfield data_tc{t}_credit_max[b:0] */ ++#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_MSK 0x0fff0000 ++/* inverted bitmask for bitfield data_tc{t}_credit_max[b:0] */ ++#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_MSKN 0xf000ffff ++/* lower bit position of bitfield data_tc{t}_credit_max[b:0] */ ++#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_SHIFT 16 ++/* width of bitfield data_tc{t}_credit_max[b:0] */ ++#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_WIDTH 12 ++/* default value of bitfield data_tc{t}_credit_max[b:0] */ ++#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_DEFAULT 0x0 ++ ++/* tx data_tc{t}_weight[8:0] bitfield definitions ++ * preprocessor definitions for the bitfield "data_tc{t}_weight[8:0]". ++ * parameter: tc {t} | stride size 0x4 | range [0, 7] ++ * port="pif_tps_data_tc0_weight_i[8:0]" ++ */ ++ ++/* register address for bitfield data_tc{t}_weight[8:0] */ ++#define HW_ATL2_TPS_DATA_TCTWEIGHT_ADR(tc) (0x00007110 + (tc) * 0x4) ++/* bitmask for bitfield data_tc{t}_weight[8:0] */ ++#define HW_ATL2_TPS_DATA_TCTWEIGHT_MSK 0x000001ff ++/* inverted bitmask for bitfield data_tc{t}_weight[8:0] */ ++#define HW_ATL2_TPS_DATA_TCTWEIGHT_MSKN 0xfffffe00 ++/* lower bit position of bitfield data_tc{t}_weight[8:0] */ ++#define HW_ATL2_TPS_DATA_TCTWEIGHT_SHIFT 0 ++/* width of bitfield data_tc{t}_weight[8:0] */ ++#define HW_ATL2_TPS_DATA_TCTWEIGHT_WIDTH 9 ++/* default value of bitfield data_tc{t}_weight[8:0] */ ++#define HW_ATL2_TPS_DATA_TCTWEIGHT_DEFAULT 0x0 ++ ++/* Launch time control register */ ++#define HW_ATL2_LT_CTRL_ADR 0x00007a1c ++ ++#define HW_ATL2_LT_CTRL_AVB_LEN_CMP_TRSHLD_MSK 0xFFFF0000 ++#define HW_ATL2_LT_CTRL_AVB_LEN_CMP_TRSHLD_SHIFT 16 ++ ++#define HW_ATL2_LT_CTRL_CLK_RATIO_MSK 0x0000FF00 ++#define HW_ATL2_LT_CTRL_CLK_RATIO_SHIFT 8 ++#define HW_ATL2_LT_CTRL_CLK_RATIO_QUATER_SPEED 4 ++#define HW_ATL2_LT_CTRL_CLK_RATIO_HALF_SPEED 2 ++#define HW_ATL2_LT_CTRL_CLK_RATIO_FULL_SPEED 1 ++ ++#define HW_ATL2_LT_CTRL_25G_MODE_SUPPORT_MSK 0x00000008 ++#define HW_ATL2_LT_CTRL_25G_MODE_SUPPORT_SHIFT 3 ++ ++#define HW_ATL2_LT_CTRL_LINK_SPEED_MSK 0x00000007 ++#define HW_ATL2_LT_CTRL_LINK_SPEED_SHIFT 0 ++ ++/* FPGA VER register */ ++#define HW_ATL2_FPGA_VER_ADR 0x000000f4 ++#define HW_ATL2_FPGA_VER_U32(mj, mi, bl, rv) \ ++ ((((mj) & 0xff) << 24) | \ ++ (((mi) & 0xff) << 16) | \ ++ (((bl) & 0xff) << 8) | \ ++ (((rv) & 0xff) << 0)) ++ + /* ahb_mem_addr{f}[31:0] Bitfield Definitions + * Preprocessor definitions for the bitfield "ahb_mem_addr{f}[31:0]". + * Parameter: filter {f} | stride size 0x10 | range [0, 127] +@@ -209,4 +308,13 @@ + /* Default value of bitfield pif_mcp_finished_buf_rd_i */ + #define HW_ATL2_MIF_MCP_FINISHED_READ_DEFAULT 0x0 + ++/* Register address for bitfield pif_mcp_boot_reg */ ++#define HW_ATL2_MIF_BOOT_REG_ADR 0x00003040u ++ ++#define HW_ATL2_MCP_HOST_REQ_INT_READY BIT(0) ++ ++#define HW_ATL2_MCP_HOST_REQ_INT_ADR 0x00000F00u ++#define HW_ATL2_MCP_HOST_REQ_INT_SET_ADR 0x00000F04u ++#define HW_ATL2_MCP_HOST_REQ_INT_CLR_ADR 0x00000F08u ++ + #endif /* HW_ATL2_LLH_INTERNAL_H */ +-- +2.13.6 + diff --git a/SOURCES/0084-netdrv-net-atlantic-common-functions-needed-for-basi.patch b/SOURCES/0084-netdrv-net-atlantic-common-functions-needed-for-basi.patch new file mode 100644 index 0000000..ab00557 --- /dev/null +++ b/SOURCES/0084-netdrv-net-atlantic-common-functions-needed-for-basi.patch @@ -0,0 +1,290 @@ +From 05049d0545c4ac9f280eea9d49ac3d5335a17fcc Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:41 -0500 +Subject: [PATCH 084/139] [netdrv] net: atlantic: common functions needed for + basic A2 init/deinit hw_ops + +Message-id: <1604687916-15087-85-git-send-email-irusskik@redhat.com> +Patchwork-id: 338521 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 084/139] net: atlantic: common functions needed for basic A2 init/deinit hw_ops +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit c1be0bf092bd292ee617622c116f5981a34cce96 +Author: Dmitry Bogdanov +Date: Thu Apr 30 11:04:43 2020 +0300 + + net: atlantic: common functions needed for basic A2 init/deinit hw_ops + + This patch adds common functions (mostly FW-related), which are + needed for basic A2 HW initialization / deinitialization. + + Signed-off-by: Dmitry Bogdanov + Co-developed-by: Igor Russkikh + Signed-off-by: Igor Russkikh + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/Makefile | 1 + + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 3 +- + .../aquantia/atlantic/hw_atl/hw_atl_utils.h | 2 + + .../aquantia/atlantic/hw_atl2/hw_atl2_utils.c | 139 +++++++++++++++++++++ + .../aquantia/atlantic/hw_atl2/hw_atl2_utils.h | 8 ++ + .../aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 12 ++ + 6 files changed, 163 insertions(+), 2 deletions(-) + create mode 100644 drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c + +diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile +index 123142c61ab2..2f5ec1a60be0 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/Makefile ++++ b/drivers/net/ethernet/aquantia/atlantic/Makefile +@@ -24,6 +24,7 @@ atlantic-objs := aq_main.o \ + hw_atl/hw_atl_utils_fw2x.o \ + hw_atl/hw_atl_llh.o \ + hw_atl2/hw_atl2.o \ ++ hw_atl2/hw_atl2_utils.o \ + hw_atl2/hw_atl2_utils_fw.o \ + hw_atl2/hw_atl2_llh.o + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 20655a2170cc..1100d40a0302 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -53,7 +53,6 @@ enum mcp_area { + MCP_AREA_SETTINGS = 0x20000000, + }; + +-static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); + static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, + enum hal_atl_utils_fw_state_e state); + static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self); +@@ -434,7 +433,7 @@ int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p, + p, cnt, MCP_AREA_SETTINGS); + } + +-static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual) ++int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual) + { + const u32 dw_major_mask = 0xff000000U; + const u32 dw_minor_mask = 0x00ffffffU; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index f293c6b9249d..80cbd1a8e378 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -599,6 +599,8 @@ int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size); + int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, + struct hw_atl_utils_fw_rpc **rpc); + ++int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); ++ + extern const struct aq_fw_ops aq_fw_1x_ops; + extern const struct aq_fw_ops aq_fw_2x_ops; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c +new file mode 100644 +index 000000000000..85ccc9a011a0 +--- /dev/null ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c +@@ -0,0 +1,139 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Atlantic Network Driver ++ * Copyright (C) 2020 Marvell International Ltd. ++ */ ++ ++#include ++ ++#include "aq_hw_utils.h" ++#include "hw_atl/hw_atl_utils.h" ++#include "hw_atl2_utils.h" ++#include "hw_atl2_llh.h" ++#include "hw_atl2_llh_internal.h" ++ ++#define HW_ATL2_FW_VER_1X 0x01000000U ++ ++#define AQ_A2_BOOT_STARTED BIT(0x18) ++#define AQ_A2_CRASH_INIT BIT(0x1B) ++#define AQ_A2_BOOT_CODE_FAILED BIT(0x1C) ++#define AQ_A2_FW_INIT_FAILED BIT(0x1D) ++#define AQ_A2_FW_INIT_COMP_SUCCESS BIT(0x1F) ++ ++#define AQ_A2_FW_BOOT_FAILED_MASK (AQ_A2_CRASH_INIT | \ ++ AQ_A2_BOOT_CODE_FAILED | \ ++ AQ_A2_FW_INIT_FAILED) ++#define AQ_A2_FW_BOOT_COMPLETE_MASK (AQ_A2_FW_BOOT_FAILED_MASK | \ ++ AQ_A2_FW_INIT_COMP_SUCCESS) ++ ++#define AQ_A2_FW_BOOT_REQ_REBOOT BIT(0x0) ++#define AQ_A2_FW_BOOT_REQ_HOST_BOOT BIT(0x8) ++#define AQ_A2_FW_BOOT_REQ_MAC_FAST_BOOT BIT(0xA) ++#define AQ_A2_FW_BOOT_REQ_PHY_FAST_BOOT BIT(0xB) ++ ++int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) ++{ ++ int err; ++ ++ self->fw_ver_actual = hw_atl2_utils_get_fw_version(self); ++ ++ if (hw_atl_utils_ver_match(HW_ATL2_FW_VER_1X, ++ self->fw_ver_actual) == 0) { ++ *fw_ops = &aq_a2_fw_ops; ++ } else { ++ aq_pr_err("Bad FW version detected: %x, but continue\n", ++ self->fw_ver_actual); ++ *fw_ops = &aq_a2_fw_ops; ++ } ++ aq_pr_trace("Detect ATL2FW %x\n", self->fw_ver_actual); ++ self->aq_fw_ops = *fw_ops; ++ err = self->aq_fw_ops->init(self); ++ ++ self->chip_features |= ATL_HW_CHIP_ANTIGUA; ++ ++ return err; ++} ++ ++static bool hw_atl2_mcp_boot_complete(struct aq_hw_s *self) ++{ ++ u32 rbl_status; ++ ++ rbl_status = hw_atl2_mif_mcp_boot_reg_get(self); ++ if (rbl_status & AQ_A2_FW_BOOT_COMPLETE_MASK) ++ return true; ++ ++ /* Host boot requested */ ++ if (hw_atl2_mif_host_req_int_get(self) & HW_ATL2_MCP_HOST_REQ_INT_READY) ++ return true; ++ ++ return false; ++} ++ ++int hw_atl2_utils_soft_reset(struct aq_hw_s *self) ++{ ++ bool rbl_complete = false; ++ u32 rbl_status = 0; ++ u32 rbl_request; ++ int err; ++ ++ err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_boot_reg_get, self, ++ rbl_status, ++ ((rbl_status & AQ_A2_BOOT_STARTED) && ++ (rbl_status != 0xFFFFFFFFu)), ++ 10, 500000); ++ if (err) ++ aq_pr_trace("Boot code probably hanged, reboot anyway"); ++ ++ hw_atl2_mif_host_req_int_clr(self, 0x01); ++ rbl_request = AQ_A2_FW_BOOT_REQ_REBOOT; ++#ifdef AQ_CFG_FAST_START ++ rbl_request |= AQ_A2_FW_BOOT_REQ_MAC_FAST_BOOT; ++#endif ++ hw_atl2_mif_mcp_boot_reg_set(self, rbl_request); ++ ++ /* Wait for RBL boot */ ++ err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_boot_reg_get, self, ++ rbl_status, ++ ((rbl_status & AQ_A2_BOOT_STARTED) && ++ (rbl_status != 0xFFFFFFFFu)), ++ 10, 200000); ++ if (err) { ++ aq_pr_err("Boot code hanged"); ++ goto err_exit; ++ } ++ ++ err = readx_poll_timeout_atomic(hw_atl2_mcp_boot_complete, self, ++ rbl_complete, ++ rbl_complete, ++ 10, 2000000); ++ ++ if (err) { ++ aq_pr_err("FW Restart timed out"); ++ goto err_exit; ++ } ++ ++ rbl_status = hw_atl2_mif_mcp_boot_reg_get(self); ++ ++ if (rbl_status & AQ_A2_FW_BOOT_FAILED_MASK) { ++ err = -EIO; ++ aq_pr_err("FW Restart failed"); ++ goto err_exit; ++ } ++ ++ if (hw_atl2_mif_host_req_int_get(self) & ++ HW_ATL2_MCP_HOST_REQ_INT_READY) { ++ err = -EIO; ++ aq_pr_err("No FW detected. Dynamic FW load not implemented"); ++ goto err_exit; ++ } ++ ++ if (self->aq_fw_ops) { ++ err = self->aq_fw_ops->init(self); ++ if (err) { ++ aq_pr_err("FW Init failed"); ++ goto err_exit; ++ } ++ } ++ ++err_exit: ++ return err; ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h +index 5421fbed3db5..2317dd8459d0 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h +@@ -6,6 +6,8 @@ + #ifndef HW_ATL2_UTILS_H + #define HW_ATL2_UTILS_H + ++#include "aq_hw.h" ++ + /* F W A P I */ + + struct link_options_s { +@@ -590,6 +592,12 @@ struct fw_interface_out { + #define AQ_HOST_MODE_LOW_POWER 3U + #define AQ_HOST_MODE_SHUTDOWN 4U + ++int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops); ++ ++int hw_atl2_utils_soft_reset(struct aq_hw_s *self); ++ ++u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self); ++ + int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self, + u8 *base_index, u8 *count); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +index c3e0e5575810..f5fb4b11f51a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +@@ -301,6 +301,18 @@ static int aq_a2_fw_renegotiate(struct aq_hw_s *self) + return err; + } + ++u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self) ++{ ++ struct version_s version; ++ ++ hw_atl2_shared_buffer_read_safe(self, version, &version); ++ ++ /* A2 FW version is stored in reverse order */ ++ return version.mac.major << 24 | ++ version.mac.minor << 16 | ++ version.mac.build; ++} ++ + int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self, + u8 *base_index, u8 *count) + { +-- +2.13.6 + diff --git a/SOURCES/0085-netdrv-net-atlantic-basic-A2-init-deinit-hw_ops.patch b/SOURCES/0085-netdrv-net-atlantic-basic-A2-init-deinit-hw_ops.patch new file mode 100644 index 0000000..a98ad50 --- /dev/null +++ b/SOURCES/0085-netdrv-net-atlantic-basic-A2-init-deinit-hw_ops.patch @@ -0,0 +1,750 @@ +From d4d50dd42996dacdfbcb2ed81985c1987cce651a Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:42 -0500 +Subject: [PATCH 085/139] [netdrv] net: atlantic: basic A2 init/deinit hw_ops + +Message-id: <1604687916-15087-86-git-send-email-irusskik@redhat.com> +Patchwork-id: 338529 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 085/139] net: atlantic: basic A2 init/deinit hw_ops +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit e54dcf4bba3e2c36b3eb89cd9063753c2a3ef459 +Author: Igor Russkikh +Date: Thu Apr 30 11:04:44 2020 +0300 + + net: atlantic: basic A2 init/deinit hw_ops + + This patch adds basic A2 HW initialization / deinitialization. + + Signed-off-by: Igor Russkikh + Co-developed-by: Dmitry Bogdanov + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 3 +- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 24 +- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h | 14 + + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 4 +- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 4 +- + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 344 +++++++++++++++++---- + .../aquantia/atlantic/hw_atl2/hw_atl2_internal.h | 48 +++ + 7 files changed, 362 insertions(+), 79 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index e4a33206d365..73bfb2bbb115 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -362,7 +362,8 @@ int aq_nic_init(struct aq_nic_s *self) + if (err < 0) + goto err_exit; + +- if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_TP) { ++ if (ATL_HW_IS_CHIP_FEATURE(self->aq_hw, ATLANTIC) && ++ self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_TP) { + self->aq_hw->phy_id = HW_ATL_PHY_ID_MAX; + err = aq_phy_init(self->aq_hw); + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 3b42045b9c7d..c46199f14ec4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -187,8 +187,8 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self, +- struct aq_rss_parameters *rss_params) ++int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self, ++ struct aq_rss_parameters *rss_params) + { + struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; + unsigned int addr = 0U; +@@ -215,8 +215,8 @@ static int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self, + return err; + } + +-static int hw_atl_b0_hw_rss_set(struct aq_hw_s *self, +- struct aq_rss_parameters *rss_params) ++int hw_atl_b0_hw_rss_set(struct aq_hw_s *self, ++ struct aq_rss_parameters *rss_params) + { + u32 num_rss_queues = max(1U, self->aq_nic_cfg->num_rss_queues); + u8 *indirection_table = rss_params->indirection_table; +@@ -314,7 +314,7 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, + static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self) + { + /* Tx TC/Queue number config */ +- hw_atl_rpb_tps_tx_tc_mode_set(self, 1U); ++ hw_atl_tpb_tps_tx_tc_mode_set(self, 1U); + + hw_atl_thm_lso_tcp_flag_of_first_pkt_set(self, 0x0FF6U); + hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(self, 0x0FF6U); +@@ -495,7 +495,7 @@ static int hw_atl_b0_hw_ring_rx_start(struct aq_hw_s *self, + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_hw_start(struct aq_hw_s *self) ++int hw_atl_b0_hw_start(struct aq_hw_s *self) + { + hw_atl_tpb_tx_buff_en_set(self, 1); + hw_atl_rpb_rx_buff_en_set(self, 1); +@@ -854,14 +854,14 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self, + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_hw_irq_enable(struct aq_hw_s *self, u64 mask) ++int hw_atl_b0_hw_irq_enable(struct aq_hw_s *self, u64 mask) + { + hw_atl_itr_irq_msk_setlsw_set(self, LODWORD(mask)); + + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_hw_irq_disable(struct aq_hw_s *self, u64 mask) ++int hw_atl_b0_hw_irq_disable(struct aq_hw_s *self, u64 mask) + { + hw_atl_itr_irq_msk_clearlsw_set(self, LODWORD(mask)); + hw_atl_itr_irq_status_clearlsw_set(self, LODWORD(mask)); +@@ -871,7 +871,7 @@ static int hw_atl_b0_hw_irq_disable(struct aq_hw_s *self, u64 mask) + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask) ++int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask) + { + *mask = hw_atl_itr_irq_statuslsw_get(self); + +@@ -880,8 +880,8 @@ static int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask) + + #define IS_FILTER_ENABLED(_F_) ((packet_filter & (_F_)) ? 1U : 0U) + +-static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self, +- unsigned int packet_filter) ++int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self, ++ unsigned int packet_filter) + { + struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; + unsigned int i = 0U; +@@ -1089,7 +1089,7 @@ static int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, + + static int hw_atl_b0_tx_tc_mode_get(struct aq_hw_s *self, u32 *tc_mode) + { +- *tc_mode = hw_atl_rpb_tps_tx_tc_mode_get(self); ++ *tc_mode = hw_atl_tpb_tps_tx_tc_mode_get(self); + return aq_hw_err_from_flags(self); + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +index 09af1683034b..ea7136b06b32 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +@@ -33,4 +33,18 @@ extern const struct aq_hw_ops hw_atl_ops_b0; + + #define hw_atl_ops_b1 hw_atl_ops_b0 + ++int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self, ++ struct aq_rss_parameters *rss_params); ++int hw_atl_b0_hw_rss_set(struct aq_hw_s *self, ++ struct aq_rss_parameters *rss_params); ++ ++int hw_atl_b0_hw_start(struct aq_hw_s *self); ++ ++int hw_atl_b0_hw_irq_enable(struct aq_hw_s *self, u64 mask); ++int hw_atl_b0_hw_irq_disable(struct aq_hw_s *self, u64 mask); ++int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask); ++ ++int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self, ++ unsigned int packet_filter); ++ + #endif /* HW_ATL_B0_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index 8dd3232d72c4..9e2d01a6aac8 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -1318,14 +1318,14 @@ void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en) + HW_ATL_TPB_TX_BUF_EN_SHIFT, tx_buff_en); + } + +-u32 hw_atl_rpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw) ++u32 hw_atl_tpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw) + { + return aq_hw_read_reg_bit(aq_hw, HW_ATL_TPB_TX_TC_MODE_ADDR, + HW_ATL_TPB_TX_TC_MODE_MSK, + HW_ATL_TPB_TX_TC_MODE_SHIFT); + } + +-void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw, ++void hw_atl_tpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw, + u32 tx_traf_class_mode) + { + aq_hw_write_reg_bit(aq_hw, HW_ATL_TPB_TX_TC_MODE_ADDR, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index a4699a682973..b88cb84805d5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -616,11 +616,11 @@ void hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(struct aq_hw_s *aq_hw, + /* tpb */ + + /* set TX Traffic Class Mode */ +-void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw, ++void hw_atl_tpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw, + u32 tx_traf_class_mode); + + /* get TX Traffic Class Mode */ +-u32 hw_atl_rpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw); ++u32 hw_atl_tpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw); + + /* set tx buffer enable */ + void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index 7dd5f9a1c505..ad0b22b3c01f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -6,11 +6,13 @@ + #include "aq_hw.h" + #include "aq_hw_utils.h" + #include "aq_nic.h" ++#include "hw_atl/hw_atl_b0.h" + #include "hw_atl/hw_atl_utils.h" + #include "hw_atl/hw_atl_llh.h" + #include "hw_atl2_utils.h" + #include "hw_atl2_llh.h" + #include "hw_atl2_internal.h" ++#include "hw_atl2_llh_internal.h" + + static int hw_atl2_act_rslvr_table_set(struct aq_hw_s *self, u8 location, + u32 tag, u32 mask, u32 action); +@@ -70,19 +72,106 @@ static u32 hw_atl2_sem_act_rslvr_get(struct aq_hw_s *self) + + static int hw_atl2_hw_reset(struct aq_hw_s *self) + { +- return -EOPNOTSUPP; ++ struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; ++ int err; ++ ++ err = hw_atl2_utils_soft_reset(self); ++ if (err) ++ return err; ++ ++ memset(priv, 0, sizeof(*priv)); ++ ++ self->aq_fw_ops->set_state(self, MPI_RESET); ++ ++ err = aq_hw_err_from_flags(self); ++ ++ return err; + } + +-static int hw_atl2_hw_rss_hash_set(struct aq_hw_s *self, +- struct aq_rss_parameters *rss_params) ++static int hw_atl2_hw_queue_to_tc_map_set(struct aq_hw_s *self) + { +- return -EOPNOTSUPP; ++ if (!hw_atl_rpb_rpf_rx_traf_class_mode_get(self)) { ++ aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(0), 0x11110000); ++ aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(8), 0x33332222); ++ aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(16), 0x55554444); ++ aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(24), 0x77776666); ++ } else { ++ aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(0), 0x00000000); ++ aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(8), 0x11111111); ++ aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(16), 0x22222222); ++ aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(24), 0x33333333); ++ } ++ ++ return aq_hw_err_from_flags(self); ++} ++ ++static int hw_atl2_hw_qos_set(struct aq_hw_s *self) ++{ ++ struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; ++ u32 tx_buff_size = HW_ATL2_TXBUF_MAX; ++ u32 rx_buff_size = HW_ATL2_RXBUF_MAX; ++ unsigned int prio = 0U; ++ u32 threshold = 0U; ++ u32 tc = 0U; ++ ++ /* TPS Descriptor rate init */ ++ hw_atl_tps_tx_pkt_shed_desc_rate_curr_time_res_set(self, 0x0U); ++ hw_atl_tps_tx_pkt_shed_desc_rate_lim_set(self, 0xA); ++ ++ /* TPS VM init */ ++ hw_atl_tps_tx_pkt_shed_desc_vm_arb_mode_set(self, 0U); ++ ++ /* TPS TC credits init */ ++ hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U); ++ hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U); ++ ++ tc = 0; ++ ++ /* TX Packet Scheduler Data TC0 */ ++ hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF0, tc); ++ hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(self, 0x640, tc); ++ hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, tc); ++ hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc); ++ ++ /* Tx buf size TC0 */ ++ hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, tx_buff_size, tc); ++ ++ threshold = (tx_buff_size * (1024 / 32U) * 66U) / 100U; ++ hw_atl_tpb_tx_buff_hi_threshold_per_tc_set(self, threshold, tc); ++ ++ threshold = (tx_buff_size * (1024 / 32U) * 50U) / 100U; ++ hw_atl_tpb_tx_buff_lo_threshold_per_tc_set(self, threshold, tc); ++ ++ /* QoS Rx buf size per TC */ ++ hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, rx_buff_size, tc); ++ ++ threshold = (rx_buff_size * (1024U / 32U) * 66U) / 100U; ++ hw_atl_rpb_rx_buff_hi_threshold_per_tc_set(self, threshold, tc); ++ ++ threshold = (rx_buff_size * (1024U / 32U) * 50U) / 100U; ++ hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(self, threshold, tc); ++ ++ /* QoS 802.1p priority -> TC mapping */ ++ for (prio = 0; prio < 8; ++prio) ++ hw_atl_rpf_rpb_user_priority_tc_map_set(self, prio, ++ cfg->tcs * prio / 8); ++ ++ /* ATL2 Apply legacy ring to TC mapping */ ++ hw_atl2_hw_queue_to_tc_map_set(self); ++ ++ return aq_hw_err_from_flags(self); + } + + static int hw_atl2_hw_rss_set(struct aq_hw_s *self, + struct aq_rss_parameters *rss_params) + { +- return -EOPNOTSUPP; ++ u8 *indirection_table = rss_params->indirection_table; ++ int i; ++ ++ for (i = HW_ATL2_RSS_REDIRECTION_MAX; i--;) ++ hw_atl2_new_rpf_rss_redir_set(self, 0, i, indirection_table[i]); ++ ++ return hw_atl_b0_hw_rss_set(self, rss_params); + } + + static int hw_atl2_hw_offload_set(struct aq_hw_s *self, +@@ -91,6 +180,80 @@ static int hw_atl2_hw_offload_set(struct aq_hw_s *self, + return -EOPNOTSUPP; + } + ++static int hw_atl2_hw_init_tx_path(struct aq_hw_s *self) ++{ ++ /* Tx TC/RSS number config */ ++ hw_atl_tpb_tps_tx_tc_mode_set(self, 1U); ++ ++ hw_atl_thm_lso_tcp_flag_of_first_pkt_set(self, 0x0FF6U); ++ hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(self, 0x0FF6U); ++ hw_atl_thm_lso_tcp_flag_of_last_pkt_set(self, 0x0F7FU); ++ ++ /* Tx interrupts */ ++ hw_atl_tdm_tx_desc_wr_wb_irq_en_set(self, 1U); ++ ++ /* misc */ ++ hw_atl_tdm_tx_dca_en_set(self, 0U); ++ hw_atl_tdm_tx_dca_mode_set(self, 0U); ++ ++ hw_atl_tpb_tx_path_scp_ins_en_set(self, 1U); ++ ++ hw_atl2_tpb_tx_buf_clk_gate_en_set(self, 0U); ++ ++ return aq_hw_err_from_flags(self); ++} ++ ++static void hw_atl2_hw_init_new_rx_filters(struct aq_hw_s *self) ++{ ++ struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; ++ u8 index; ++ ++ hw_atl2_rpf_act_rslvr_section_en_set(self, 0xFFFF); ++ hw_atl2_rpfl2_uc_flr_tag_set(self, HW_ATL2_RPF_TAG_BASE_UC, ++ HW_ATL2_MAC_UC); ++ hw_atl2_rpfl2_bc_flr_tag_set(self, HW_ATL2_RPF_TAG_BASE_UC); ++ ++ index = priv->art_base_index + HW_ATL2_RPF_L2_PROMISC_OFF_INDEX; ++ hw_atl2_act_rslvr_table_set(self, index, 0, ++ HW_ATL2_RPF_TAG_UC_MASK | ++ HW_ATL2_RPF_TAG_ALLMC_MASK, ++ HW_ATL2_ACTION_DROP); ++ ++ index = priv->art_base_index + HW_ATL2_RPF_VLAN_PROMISC_OFF_INDEX; ++ hw_atl2_act_rslvr_table_set(self, index, 0, ++ HW_ATL2_RPF_TAG_VLAN_MASK | ++ HW_ATL2_RPF_TAG_UNTAG_MASK, ++ HW_ATL2_ACTION_DROP); ++ ++ index = priv->art_base_index + HW_ATL2_RPF_VLAN_INDEX; ++ hw_atl2_act_rslvr_table_set(self, index, HW_ATL2_RPF_TAG_BASE_VLAN, ++ HW_ATL2_RPF_TAG_VLAN_MASK, ++ HW_ATL2_ACTION_ASSIGN_TC(0)); ++ ++ index = priv->art_base_index + HW_ATL2_RPF_MAC_INDEX; ++ hw_atl2_act_rslvr_table_set(self, index, HW_ATL2_RPF_TAG_BASE_UC, ++ HW_ATL2_RPF_TAG_UC_MASK, ++ HW_ATL2_ACTION_ASSIGN_TC(0)); ++ ++ index = priv->art_base_index + HW_ATL2_RPF_ALLMC_INDEX; ++ hw_atl2_act_rslvr_table_set(self, index, HW_ATL2_RPF_TAG_BASE_ALLMC, ++ HW_ATL2_RPF_TAG_ALLMC_MASK, ++ HW_ATL2_ACTION_ASSIGN_TC(0)); ++ ++ index = priv->art_base_index + HW_ATL2_RPF_UNTAG_INDEX; ++ hw_atl2_act_rslvr_table_set(self, index, HW_ATL2_RPF_TAG_UNTAG_MASK, ++ HW_ATL2_RPF_TAG_UNTAG_MASK, ++ HW_ATL2_ACTION_ASSIGN_TC(0)); ++ ++ index = priv->art_base_index + HW_ATL2_RPF_VLAN_PROMISC_ON_INDEX; ++ hw_atl2_act_rslvr_table_set(self, index, 0, HW_ATL2_RPF_TAG_VLAN_MASK, ++ HW_ATL2_ACTION_DISABLE); ++ ++ index = priv->art_base_index + HW_ATL2_RPF_L2_PROMISC_ON_INDEX; ++ hw_atl2_act_rslvr_table_set(self, index, 0, HW_ATL2_RPF_TAG_UC_MASK, ++ HW_ATL2_ACTION_DISABLE); ++} ++ + static void hw_atl2_hw_new_rx_filter_vlan_promisc(struct aq_hw_s *self, + bool promisc) + { +@@ -145,6 +308,57 @@ static int hw_atl2_act_rslvr_table_set(struct aq_hw_s *self, u8 location, + return err; + } + ++static int hw_atl2_hw_init_rx_path(struct aq_hw_s *self) ++{ ++ struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; ++ int i; ++ ++ /* Rx TC/RSS number config */ ++ hw_atl_rpb_rpf_rx_traf_class_mode_set(self, 1U); ++ ++ /* Rx flow control */ ++ hw_atl_rpb_rx_flow_ctl_mode_set(self, 1U); ++ ++ hw_atl2_rpf_rss_hash_type_set(self, HW_ATL2_RPF_RSS_HASH_TYPE_ALL); ++ ++ /* RSS Ring selection */ ++ hw_atl_reg_rx_flr_rss_control1set(self, cfg->is_rss ? ++ HW_ATL_RSS_ENABLED_3INDEX_BITS : ++ HW_ATL_RSS_DISABLED); ++ ++ /* Multicast filters */ ++ for (i = HW_ATL2_MAC_MAX; i--;) { ++ hw_atl_rpfl2_uc_flr_en_set(self, (i == 0U) ? 1U : 0U, i); ++ hw_atl_rpfl2unicast_flr_act_set(self, 1U, i); ++ } ++ ++ hw_atl_reg_rx_flr_mcst_flr_msk_set(self, 0x00000000U); ++ hw_atl_reg_rx_flr_mcst_flr_set(self, HW_ATL_MCAST_FLT_ANY_TO_HOST, 0U); ++ ++ /* Vlan filters */ ++ hw_atl_rpf_vlan_outer_etht_set(self, ETH_P_8021AD); ++ hw_atl_rpf_vlan_inner_etht_set(self, ETH_P_8021Q); ++ ++ hw_atl_rpf_vlan_prom_mode_en_set(self, 1); ++ ++ /* Always accept untagged packets */ ++ hw_atl_rpf_vlan_accept_untagged_packets_set(self, 1U); ++ hw_atl_rpf_vlan_untagged_act_set(self, 1U); ++ ++ hw_atl2_hw_init_new_rx_filters(self); ++ ++ /* Rx Interrupts */ ++ hw_atl_rdm_rx_desc_wr_wb_irq_en_set(self, 1U); ++ ++ hw_atl_rpfl2broadcast_flr_act_set(self, 1U); ++ hw_atl_rpfl2broadcast_count_threshold_set(self, 0xFFFFU & (~0U / 256U)); ++ ++ hw_atl_rdm_rx_dca_en_set(self, 0U); ++ hw_atl_rdm_rx_dca_mode_set(self, 0U); ++ ++ return aq_hw_err_from_flags(self); ++} ++ + static int hw_atl2_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) + { + return -EOPNOTSUPP; +@@ -152,7 +366,15 @@ static int hw_atl2_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) + + static int hw_atl2_hw_init(struct aq_hw_s *self, u8 *mac_addr) + { ++ static u32 aq_hw_atl2_igcr_table_[4][2] = { ++ [AQ_HW_IRQ_INVALID] = { 0x20000000U, 0x20000000U }, ++ [AQ_HW_IRQ_LEGACY] = { 0x20000080U, 0x20000080U }, ++ [AQ_HW_IRQ_MSI] = { 0x20000021U, 0x20000025U }, ++ [AQ_HW_IRQ_MSIX] = { 0x20000022U, 0x20000026U }, ++ }; ++ + struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; ++ struct aq_nic_cfg_s *aq_nic_cfg = self->aq_nic_cfg; + u8 base_index, count; + int err; + +@@ -163,7 +385,49 @@ static int hw_atl2_hw_init(struct aq_hw_s *self, u8 *mac_addr) + + priv->art_base_index = 8 * base_index; + +- return -EOPNOTSUPP; ++ hw_atl2_init_launchtime(self); ++ ++ hw_atl2_hw_init_tx_path(self); ++ hw_atl2_hw_init_rx_path(self); ++ ++ hw_atl2_hw_mac_addr_set(self, mac_addr); ++ ++ self->aq_fw_ops->set_link_speed(self, aq_nic_cfg->link_speed_msk); ++ self->aq_fw_ops->set_state(self, MPI_INIT); ++ ++ hw_atl2_hw_qos_set(self); ++ hw_atl2_hw_rss_set(self, &aq_nic_cfg->aq_rss); ++ hw_atl_b0_hw_rss_hash_set(self, &aq_nic_cfg->aq_rss); ++ ++ hw_atl2_rpf_new_enable_set(self, 1); ++ ++ /* Reset link status and read out initial hardware counters */ ++ self->aq_link_status.mbps = 0; ++ self->aq_fw_ops->update_stats(self); ++ ++ err = aq_hw_err_from_flags(self); ++ if (err < 0) ++ goto err_exit; ++ ++ /* Interrupts */ ++ hw_atl_reg_irq_glb_ctl_set(self, ++ aq_hw_atl2_igcr_table_[aq_nic_cfg->irq_type] ++ [(aq_nic_cfg->vecs > 1U) ? ++ 1 : 0]); ++ ++ hw_atl_itr_irq_auto_masklsw_set(self, aq_nic_cfg->aq_hw_caps->irq_mask); ++ ++ /* Interrupts */ ++ hw_atl_reg_gen_irq_map_set(self, ++ ((HW_ATL2_ERR_INT << 0x18) | ++ (1U << 0x1F)) | ++ ((HW_ATL2_ERR_INT << 0x10) | ++ (1U << 0x17)), 0U); ++ ++ hw_atl2_hw_offload_set(self, aq_nic_cfg); ++ ++err_exit: ++ return err; + } + + static int hw_atl2_hw_ring_tx_start(struct aq_hw_s *self, +@@ -178,11 +442,6 @@ static int hw_atl2_hw_ring_rx_start(struct aq_hw_s *self, + return -EOPNOTSUPP; + } + +-static int hw_atl2_hw_start(struct aq_hw_s *self) +-{ +- return -EOPNOTSUPP; +-} +- + static int hw_atl2_hw_ring_tx_xmit(struct aq_hw_s *self, + struct aq_ring_s *ring, + unsigned int frags) +@@ -222,58 +481,14 @@ static int hw_atl2_hw_ring_rx_receive(struct aq_hw_s *self, + return -EOPNOTSUPP; + } + +-static int hw_atl2_hw_irq_enable(struct aq_hw_s *self, u64 mask) +-{ +- return -EOPNOTSUPP; +-} +- +-static int hw_atl2_hw_irq_disable(struct aq_hw_s *self, u64 mask) +-{ +- return -EOPNOTSUPP; +-} +- +-static int hw_atl2_hw_irq_read(struct aq_hw_s *self, u64 *mask) +-{ +- return -EOPNOTSUPP; +-} +- + #define IS_FILTER_ENABLED(_F_) ((packet_filter & (_F_)) ? 1U : 0U) + + static int hw_atl2_hw_packet_filter_set(struct aq_hw_s *self, + unsigned int packet_filter) + { +- struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; +- u32 vlan_promisc; +- u32 l2_promisc; +- unsigned int i; +- +- l2_promisc = IS_FILTER_ENABLED(IFF_PROMISC) || +- !!(cfg->priv_flags & BIT(AQ_HW_LOOPBACK_DMA_NET)); +- vlan_promisc = l2_promisc || cfg->is_vlan_force_promisc; +- +- hw_atl_rpfl2promiscuous_mode_en_set(self, l2_promisc); +- +- hw_atl_rpf_vlan_prom_mode_en_set(self, vlan_promisc); +- + hw_atl2_hw_new_rx_filter_promisc(self, IS_FILTER_ENABLED(IFF_PROMISC)); + +- hw_atl_rpfl2multicast_flr_en_set(self, +- IS_FILTER_ENABLED(IFF_ALLMULTI) && +- IS_FILTER_ENABLED(IFF_MULTICAST), 0); +- +- hw_atl_rpfl2_accept_all_mc_packets_set(self, +- IS_FILTER_ENABLED(IFF_ALLMULTI) && +- IS_FILTER_ENABLED(IFF_MULTICAST)); +- +- hw_atl_rpfl2broadcast_en_set(self, IS_FILTER_ENABLED(IFF_BROADCAST)); +- +- for (i = HW_ATL2_MAC_MIN; i < HW_ATL2_MAC_MAX; ++i) +- hw_atl_rpfl2_uc_flr_en_set(self, +- (cfg->is_mc_list_enabled && +- (i <= cfg->mc_list_count)) ? +- 1U : 0U, i); +- +- return aq_hw_err_from_flags(self); ++ return hw_atl_b0_hw_packet_filter_set(self, packet_filter); + } + + #undef IS_FILTER_ENABLED +@@ -326,7 +541,9 @@ static int hw_atl2_hw_interrupt_moderation_set(struct aq_hw_s *self) + + static int hw_atl2_hw_stop(struct aq_hw_s *self) + { +- return -EOPNOTSUPP; ++ hw_atl_b0_hw_irq_disable(self, HW_ATL2_INT_MASK); ++ ++ return 0; + } + + static int hw_atl2_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) +@@ -400,10 +617,12 @@ static int hw_atl2_hw_vlan_ctrl(struct aq_hw_s *self, bool enable) + } + + const struct aq_hw_ops hw_atl2_ops = { ++ .hw_soft_reset = hw_atl2_utils_soft_reset, ++ .hw_prepare = hw_atl2_utils_initfw, + .hw_set_mac_address = hw_atl2_hw_mac_addr_set, + .hw_init = hw_atl2_hw_init, + .hw_reset = hw_atl2_hw_reset, +- .hw_start = hw_atl2_hw_start, ++ .hw_start = hw_atl_b0_hw_start, + .hw_ring_tx_start = hw_atl2_hw_ring_tx_start, + .hw_ring_tx_stop = hw_atl2_hw_ring_tx_stop, + .hw_ring_rx_start = hw_atl2_hw_ring_rx_start, +@@ -416,9 +635,9 @@ const struct aq_hw_ops hw_atl2_ops = { + .hw_ring_rx_receive = hw_atl2_hw_ring_rx_receive, + .hw_ring_rx_fill = hw_atl2_hw_ring_rx_fill, + +- .hw_irq_enable = hw_atl2_hw_irq_enable, +- .hw_irq_disable = hw_atl2_hw_irq_disable, +- .hw_irq_read = hw_atl2_hw_irq_read, ++ .hw_irq_enable = hw_atl_b0_hw_irq_enable, ++ .hw_irq_disable = hw_atl_b0_hw_irq_disable, ++ .hw_irq_read = hw_atl_b0_hw_irq_read, + + .hw_ring_rx_init = hw_atl2_hw_ring_rx_init, + .hw_ring_tx_init = hw_atl2_hw_ring_tx_init, +@@ -428,7 +647,8 @@ const struct aq_hw_ops hw_atl2_ops = { + .hw_multicast_list_set = hw_atl2_hw_multicast_list_set, + .hw_interrupt_moderation_set = hw_atl2_hw_interrupt_moderation_set, + .hw_rss_set = hw_atl2_hw_rss_set, +- .hw_rss_hash_set = hw_atl2_hw_rss_hash_set, ++ .hw_rss_hash_set = hw_atl_b0_hw_rss_hash_set, + .hw_get_hw_stats = hw_atl2_utils_get_hw_stats, ++ .hw_get_fw_version = hw_atl2_utils_get_fw_version, + .hw_set_offload = hw_atl2_hw_offload_set, + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +index dccc89df2223..eb1243256730 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +@@ -22,6 +22,15 @@ + #define HW_ATL2_MAC_MIN 1U + #define HW_ATL2_MAC_MAX 38U + ++/* interrupts */ ++#define HW_ATL2_ERR_INT 8U ++#define HW_ATL2_INT_MASK (0xFFFFFFFFU) ++ ++#define HW_ATL2_TXBUF_MAX 128U ++#define HW_ATL2_RXBUF_MAX 192U ++ ++#define HW_ATL2_RSS_REDIRECTION_MAX 64U ++ + #define HW_ATL2_TC_MAX 1U + #define HW_ATL2_RSS_MAX 8U + +@@ -57,6 +66,11 @@ + #define HW_ATL2_RPF_TAG_L4_MASK (0x00000007 << HW_ATL2_RPF_TAG_L4_OFFSET) + #define HW_ATL2_RPF_TAG_PCP_MASK (0x00000007 << HW_ATL2_RPF_TAG_PCP_OFFSET) + ++#define HW_ATL2_RPF_TAG_BASE_UC BIT(HW_ATL2_RPF_TAG_UC_OFFSET) ++#define HW_ATL2_RPF_TAG_BASE_ALLMC BIT(HW_ATL2_RPF_TAG_ALLMC_OFFSET) ++#define HW_ATL2_RPF_TAG_BASE_UNTAG BIT(HW_ATL2_RPF_TAG_UNTAG_OFFSET) ++#define HW_ATL2_RPF_TAG_BASE_VLAN BIT(HW_ATL2_RPF_TAG_VLAN_OFFSET) ++ + enum HW_ATL2_RPF_ART_INDEX { + HW_ATL2_RPF_L2_PROMISC_OFF_INDEX, + HW_ATL2_RPF_VLAN_PROMISC_OFF_INDEX, +@@ -65,6 +79,13 @@ enum HW_ATL2_RPF_ART_INDEX { + HW_ATL2_RPF_VLAN_USER_INDEX = HW_ATL2_RPF_ET_PCP_USER_INDEX + 16, + HW_ATL2_RPF_PCP_TO_TC_INDEX = HW_ATL2_RPF_VLAN_USER_INDEX + + HW_ATL_VLAN_MAX_FILTERS, ++ HW_ATL2_RPF_VLAN_INDEX = HW_ATL2_RPF_PCP_TO_TC_INDEX + ++ AQ_CFG_TCS_MAX, ++ HW_ATL2_RPF_MAC_INDEX, ++ HW_ATL2_RPF_ALLMC_INDEX, ++ HW_ATL2_RPF_UNTAG_INDEX, ++ HW_ATL2_RPF_VLAN_PROMISC_ON_INDEX, ++ HW_ATL2_RPF_L2_PROMISC_ON_INDEX, + }; + + #define HW_ATL2_ACTION(ACTION, RSS, INDEX, VALID) \ +@@ -78,6 +99,33 @@ enum HW_ATL2_RPF_ART_INDEX { + #define HW_ATL2_ACTION_ASSIGN_QUEUE(QUEUE) HW_ATL2_ACTION(1, 0, (QUEUE), 1) + #define HW_ATL2_ACTION_ASSIGN_TC(TC) HW_ATL2_ACTION(1, 1, (TC), 1) + ++enum HW_ATL2_RPF_RSS_HASH_TYPE { ++ HW_ATL2_RPF_RSS_HASH_TYPE_NONE = 0, ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV4 = BIT(0), ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV4_TCP = BIT(1), ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV4_UDP = BIT(2), ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV6 = BIT(3), ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_TCP = BIT(4), ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_UDP = BIT(5), ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX = BIT(6), ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX_TCP = BIT(7), ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX_UDP = BIT(8), ++ HW_ATL2_RPF_RSS_HASH_TYPE_ALL = HW_ATL2_RPF_RSS_HASH_TYPE_IPV4 | ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV4_TCP | ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV4_UDP | ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV6 | ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_TCP | ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_UDP | ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX | ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX_TCP | ++ HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX_UDP, ++}; ++ ++#define HW_ATL_RSS_DISABLED 0x00000000U ++#define HW_ATL_RSS_ENABLED_3INDEX_BITS 0xB3333333U ++ ++#define HW_ATL_MCAST_FLT_ANY_TO_HOST 0x00010FFFU ++ + struct hw_atl2_priv { + struct statistics_s last_stats; + unsigned int art_base_index; +-- +2.13.6 + diff --git a/SOURCES/0086-netdrv-net-atlantic-A2-ingress-egress-hw-configurati.patch b/SOURCES/0086-netdrv-net-atlantic-A2-ingress-egress-hw-configurati.patch new file mode 100644 index 0000000..9f5d240 --- /dev/null +++ b/SOURCES/0086-netdrv-net-atlantic-A2-ingress-egress-hw-configurati.patch @@ -0,0 +1,570 @@ +From 37eec24707ad6768576e87d6368ae67fe3d4fc54 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:43 -0500 +Subject: [PATCH 086/139] [netdrv] net: atlantic: A2 ingress / egress hw + configuration + +Message-id: <1604687916-15087-87-git-send-email-irusskik@redhat.com> +Patchwork-id: 338513 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 086/139] net: atlantic: A2 ingress / egress hw configuration +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 43c670c8e48a1817ae4b64683d7d65cad5bb0502 +Author: Igor Russkikh +Date: Thu Apr 30 11:04:45 2020 +0300 + + net: atlantic: A2 ingress / egress hw configuration + + Chip generations are mostly compatible register-wise, but there are still + some differences. Therefore we've made some of first generation (A1) code + non-static to re-use it where possible. + + Some pieces are A2 specific, in which case we redefine/extend such APIs. + + Signed-off-by: Igor Russkikh + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 54 +++---- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h | 23 +++ + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 176 ++++++++++++--------- + .../aquantia/atlantic/hw_atl2/hw_atl2_internal.h | 3 + + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.c | 8 + + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.h | 5 + + .../atlantic/hw_atl2/hw_atl2_llh_internal.h | 8 + + 7 files changed, 172 insertions(+), 105 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index c46199f14ec4..cbb7a00d61b4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -251,9 +251,10 @@ int hw_atl_b0_hw_rss_set(struct aq_hw_s *self, + return err; + } + +-static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, +- struct aq_nic_cfg_s *aq_nic_cfg) ++int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, ++ struct aq_nic_cfg_s *aq_nic_cfg) + { ++ u64 rxcsum = !!(aq_nic_cfg->features & NETIF_F_RXCSUM); + unsigned int i; + + /* TX checksums offloads*/ +@@ -261,10 +262,8 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, + hw_atl_tpo_tcp_udp_crc_offload_en_set(self, 1); + + /* RX checksums offloads*/ +- hw_atl_rpo_ipv4header_crc_offload_en_set(self, !!(aq_nic_cfg->features & +- NETIF_F_RXCSUM)); +- hw_atl_rpo_tcp_udp_crc_offload_en_set(self, !!(aq_nic_cfg->features & +- NETIF_F_RXCSUM)); ++ hw_atl_rpo_ipv4header_crc_offload_en_set(self, rxcsum); ++ hw_atl_rpo_tcp_udp_crc_offload_en_set(self, rxcsum); + + /* LSO offloads*/ + hw_atl_tdm_large_send_offload_en_set(self, 0xFFFFFFFFU); +@@ -272,7 +271,7 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, + /* Outer VLAN tag offload */ + hw_atl_rpo_outer_vlan_tag_mode_set(self, 1U); + +-/* LRO offloads */ ++ /* LRO offloads */ + { + unsigned int val = (8U < HW_ATL_B0_LRO_RXD_MAX) ? 0x3U : + ((4U < HW_ATL_B0_LRO_RXD_MAX) ? 0x2U : +@@ -384,7 +383,7 @@ static int hw_atl_b0_hw_init_rx_path(struct aq_hw_s *self) + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) ++int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) + { + unsigned int h = 0U; + unsigned int l = 0U; +@@ -479,16 +478,14 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr) + return err; + } + +-static int hw_atl_b0_hw_ring_tx_start(struct aq_hw_s *self, +- struct aq_ring_s *ring) ++int hw_atl_b0_hw_ring_tx_start(struct aq_hw_s *self, struct aq_ring_s *ring) + { + hw_atl_tdm_tx_desc_en_set(self, 1, ring->idx); + + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_hw_ring_rx_start(struct aq_hw_s *self, +- struct aq_ring_s *ring) ++int hw_atl_b0_hw_ring_rx_start(struct aq_hw_s *self, struct aq_ring_s *ring) + { + hw_atl_rdm_rx_desc_en_set(self, 1, ring->idx); + +@@ -511,9 +508,8 @@ static int hw_atl_b0_hw_tx_ring_tail_update(struct aq_hw_s *self, + return 0; + } + +-static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, +- struct aq_ring_s *ring, +- unsigned int frags) ++int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, struct aq_ring_s *ring, ++ unsigned int frags) + { + struct aq_ring_buff_s *buff = NULL; + struct hw_atl_txd_s *txd = NULL; +@@ -600,9 +596,8 @@ static int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_hw_ring_rx_init(struct aq_hw_s *self, +- struct aq_ring_s *aq_ring, +- struct aq_ring_param_s *aq_ring_param) ++int hw_atl_b0_hw_ring_rx_init(struct aq_hw_s *self, struct aq_ring_s *aq_ring, ++ struct aq_ring_param_s *aq_ring_param) + { + u32 dma_desc_addr_msw = (u32)(((u64)aq_ring->dx_ring_pa) >> 32); + u32 vlan_rx_stripping = self->aq_nic_cfg->is_vlan_rx_strip; +@@ -643,9 +638,8 @@ static int hw_atl_b0_hw_ring_rx_init(struct aq_hw_s *self, + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_hw_ring_tx_init(struct aq_hw_s *self, +- struct aq_ring_s *aq_ring, +- struct aq_ring_param_s *aq_ring_param) ++int hw_atl_b0_hw_ring_tx_init(struct aq_hw_s *self, struct aq_ring_s *aq_ring, ++ struct aq_ring_param_s *aq_ring_param) + { + u32 dma_desc_msw_addr = (u32)(((u64)aq_ring->dx_ring_pa) >> 32); + u32 dma_desc_lsw_addr = (u32)aq_ring->dx_ring_pa; +@@ -673,9 +667,8 @@ static int hw_atl_b0_hw_ring_tx_init(struct aq_hw_s *self, + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_hw_ring_rx_fill(struct aq_hw_s *self, +- struct aq_ring_s *ring, +- unsigned int sw_tail_old) ++int hw_atl_b0_hw_ring_rx_fill(struct aq_hw_s *self, struct aq_ring_s *ring, ++ unsigned int sw_tail_old) + { + for (; sw_tail_old != ring->sw_tail; + sw_tail_old = aq_ring_next_dx(ring, sw_tail_old)) { +@@ -734,8 +727,8 @@ static int hw_atl_b0_hw_ring_hwts_rx_receive(struct aq_hw_s *self, + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self, +- struct aq_ring_s *ring) ++int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self, ++ struct aq_ring_s *ring) + { + unsigned int hw_head_; + int err = 0; +@@ -753,8 +746,7 @@ static int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self, + return err; + } + +-static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self, +- struct aq_ring_s *ring) ++int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self, struct aq_ring_s *ring) + { + for (; ring->hw_head != ring->sw_tail; + ring->hw_head = aq_ring_next_dx(ring, ring->hw_head)) { +@@ -1071,16 +1063,14 @@ static int hw_atl_b0_hw_stop(struct aq_hw_s *self) + return err; + } + +-static int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, +- struct aq_ring_s *ring) ++int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) + { + hw_atl_tdm_tx_desc_en_set(self, 0U, ring->idx); + + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, +- struct aq_ring_s *ring) ++int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) + { + hw_atl_rdm_rx_desc_en_set(self, 0U, ring->idx); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +index ea7136b06b32..f5091d79ab43 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +@@ -37,6 +37,29 @@ int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self, + struct aq_rss_parameters *rss_params); + int hw_atl_b0_hw_rss_set(struct aq_hw_s *self, + struct aq_rss_parameters *rss_params); ++int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, ++ struct aq_nic_cfg_s *aq_nic_cfg); ++ ++int hw_atl_b0_hw_ring_tx_start(struct aq_hw_s *self, struct aq_ring_s *ring); ++int hw_atl_b0_hw_ring_rx_start(struct aq_hw_s *self, struct aq_ring_s *ring); ++ ++int hw_atl_b0_hw_ring_rx_init(struct aq_hw_s *self, struct aq_ring_s *aq_ring, ++ struct aq_ring_param_s *aq_ring_param); ++int hw_atl_b0_hw_ring_rx_fill(struct aq_hw_s *self, struct aq_ring_s *ring, ++ unsigned int sw_tail_old); ++int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self, struct aq_ring_s *ring); ++ ++int hw_atl_b0_hw_ring_tx_init(struct aq_hw_s *self, struct aq_ring_s *aq_ring, ++ struct aq_ring_param_s *aq_ring_param); ++int hw_atl_b0_hw_ring_tx_xmit(struct aq_hw_s *self, struct aq_ring_s *ring, ++ unsigned int frags); ++int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self, ++ struct aq_ring_s *ring); ++ ++int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring); ++int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, struct aq_ring_s *ring); ++ ++int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr); + + int hw_atl_b0_hw_start(struct aq_hw_s *self); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index ad0b22b3c01f..04d194f754fa 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -5,6 +5,7 @@ + + #include "aq_hw.h" + #include "aq_hw_utils.h" ++#include "aq_ring.h" + #include "aq_nic.h" + #include "hw_atl/hw_atl_b0.h" + #include "hw_atl/hw_atl_utils.h" +@@ -174,12 +175,6 @@ static int hw_atl2_hw_rss_set(struct aq_hw_s *self, + return hw_atl_b0_hw_rss_set(self, rss_params); + } + +-static int hw_atl2_hw_offload_set(struct aq_hw_s *self, +- struct aq_nic_cfg_s *aq_nic_cfg) +-{ +- return -EOPNOTSUPP; +-} +- + static int hw_atl2_hw_init_tx_path(struct aq_hw_s *self) + { + /* Tx TC/RSS number config */ +@@ -359,11 +354,6 @@ static int hw_atl2_hw_init_rx_path(struct aq_hw_s *self) + return aq_hw_err_from_flags(self); + } + +-static int hw_atl2_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) +-{ +- return -EOPNOTSUPP; +-} +- + static int hw_atl2_hw_init(struct aq_hw_s *self, u8 *mac_addr) + { + static u32 aq_hw_atl2_igcr_table_[4][2] = { +@@ -390,7 +380,7 @@ static int hw_atl2_hw_init(struct aq_hw_s *self, u8 *mac_addr) + hw_atl2_hw_init_tx_path(self); + hw_atl2_hw_init_rx_path(self); + +- hw_atl2_hw_mac_addr_set(self, mac_addr); ++ hw_atl_b0_hw_mac_addr_set(self, mac_addr); + + self->aq_fw_ops->set_link_speed(self, aq_nic_cfg->link_speed_msk); + self->aq_fw_ops->set_state(self, MPI_INIT); +@@ -424,61 +414,24 @@ static int hw_atl2_hw_init(struct aq_hw_s *self, u8 *mac_addr) + ((HW_ATL2_ERR_INT << 0x10) | + (1U << 0x17)), 0U); + +- hw_atl2_hw_offload_set(self, aq_nic_cfg); ++ hw_atl_b0_hw_offload_set(self, aq_nic_cfg); + + err_exit: + return err; + } + +-static int hw_atl2_hw_ring_tx_start(struct aq_hw_s *self, +- struct aq_ring_s *ring) +-{ +- return -EOPNOTSUPP; +-} +- +-static int hw_atl2_hw_ring_rx_start(struct aq_hw_s *self, +- struct aq_ring_s *ring) +-{ +- return -EOPNOTSUPP; +-} +- +-static int hw_atl2_hw_ring_tx_xmit(struct aq_hw_s *self, +- struct aq_ring_s *ring, +- unsigned int frags) +-{ +- return -EOPNOTSUPP; +-} +- + static int hw_atl2_hw_ring_rx_init(struct aq_hw_s *self, + struct aq_ring_s *aq_ring, + struct aq_ring_param_s *aq_ring_param) + { +- return -EOPNOTSUPP; ++ return hw_atl_b0_hw_ring_rx_init(self, aq_ring, aq_ring_param); + } + + static int hw_atl2_hw_ring_tx_init(struct aq_hw_s *self, + struct aq_ring_s *aq_ring, + struct aq_ring_param_s *aq_ring_param) + { +- return -EOPNOTSUPP; +-} +- +-static int hw_atl2_hw_ring_rx_fill(struct aq_hw_s *self, struct aq_ring_s *ring, +- unsigned int sw_tail_old) +-{ +- return -EOPNOTSUPP; +-} +- +-static int hw_atl2_hw_ring_tx_head_update(struct aq_hw_s *self, +- struct aq_ring_s *ring) +-{ +- return -EOPNOTSUPP; +-} +- +-static int hw_atl2_hw_ring_rx_receive(struct aq_hw_s *self, +- struct aq_ring_s *ring) +-{ +- return -EOPNOTSUPP; ++ return hw_atl_b0_hw_ring_tx_init(self, aq_ring, aq_ring_param); + } + + #define IS_FILTER_ENABLED(_F_) ((packet_filter & (_F_)) ? 1U : 0U) +@@ -536,7 +489,94 @@ static int hw_atl2_hw_multicast_list_set(struct aq_hw_s *self, + + static int hw_atl2_hw_interrupt_moderation_set(struct aq_hw_s *self) + { +- return -EOPNOTSUPP; ++ unsigned int i = 0U; ++ u32 itr_tx = 2U; ++ u32 itr_rx = 2U; ++ ++ switch (self->aq_nic_cfg->itr) { ++ case AQ_CFG_INTERRUPT_MODERATION_ON: ++ case AQ_CFG_INTERRUPT_MODERATION_AUTO: ++ hw_atl_tdm_tx_desc_wr_wb_irq_en_set(self, 0U); ++ hw_atl_tdm_tdm_intr_moder_en_set(self, 1U); ++ hw_atl_rdm_rx_desc_wr_wb_irq_en_set(self, 0U); ++ hw_atl_rdm_rdm_intr_moder_en_set(self, 1U); ++ ++ if (self->aq_nic_cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON) { ++ /* HW timers are in 2us units */ ++ int tx_max_timer = self->aq_nic_cfg->tx_itr / 2; ++ int tx_min_timer = tx_max_timer / 2; ++ ++ int rx_max_timer = self->aq_nic_cfg->rx_itr / 2; ++ int rx_min_timer = rx_max_timer / 2; ++ ++ tx_max_timer = min(HW_ATL2_INTR_MODER_MAX, ++ tx_max_timer); ++ tx_min_timer = min(HW_ATL2_INTR_MODER_MIN, ++ tx_min_timer); ++ rx_max_timer = min(HW_ATL2_INTR_MODER_MAX, ++ rx_max_timer); ++ rx_min_timer = min(HW_ATL2_INTR_MODER_MIN, ++ rx_min_timer); ++ ++ itr_tx |= tx_min_timer << 0x8U; ++ itr_tx |= tx_max_timer << 0x10U; ++ itr_rx |= rx_min_timer << 0x8U; ++ itr_rx |= rx_max_timer << 0x10U; ++ } else { ++ static unsigned int hw_atl2_timers_table_tx_[][2] = { ++ {0xfU, 0xffU}, /* 10Gbit */ ++ {0xfU, 0x1ffU}, /* 5Gbit */ ++ {0xfU, 0x1ffU}, /* 5Gbit 5GS */ ++ {0xfU, 0x1ffU}, /* 2.5Gbit */ ++ {0xfU, 0x1ffU}, /* 1Gbit */ ++ {0xfU, 0x1ffU}, /* 100Mbit */ ++ }; ++ static unsigned int hw_atl2_timers_table_rx_[][2] = { ++ {0x6U, 0x38U},/* 10Gbit */ ++ {0xCU, 0x70U},/* 5Gbit */ ++ {0xCU, 0x70U},/* 5Gbit 5GS */ ++ {0x18U, 0xE0U},/* 2.5Gbit */ ++ {0x30U, 0x80U},/* 1Gbit */ ++ {0x4U, 0x50U},/* 100Mbit */ ++ }; ++ unsigned int mbps = self->aq_link_status.mbps; ++ unsigned int speed_index; ++ ++ speed_index = hw_atl_utils_mbps_2_speed_index(mbps); ++ ++ /* Update user visible ITR settings */ ++ self->aq_nic_cfg->tx_itr = hw_atl2_timers_table_tx_ ++ [speed_index][1] * 2; ++ self->aq_nic_cfg->rx_itr = hw_atl2_timers_table_rx_ ++ [speed_index][1] * 2; ++ ++ itr_tx |= hw_atl2_timers_table_tx_ ++ [speed_index][0] << 0x8U; ++ itr_tx |= hw_atl2_timers_table_tx_ ++ [speed_index][1] << 0x10U; ++ ++ itr_rx |= hw_atl2_timers_table_rx_ ++ [speed_index][0] << 0x8U; ++ itr_rx |= hw_atl2_timers_table_rx_ ++ [speed_index][1] << 0x10U; ++ } ++ break; ++ case AQ_CFG_INTERRUPT_MODERATION_OFF: ++ hw_atl_tdm_tx_desc_wr_wb_irq_en_set(self, 1U); ++ hw_atl_tdm_tdm_intr_moder_en_set(self, 0U); ++ hw_atl_rdm_rx_desc_wr_wb_irq_en_set(self, 1U); ++ hw_atl_rdm_rdm_intr_moder_en_set(self, 0U); ++ itr_tx = 0U; ++ itr_rx = 0U; ++ break; ++ } ++ ++ for (i = HW_ATL2_RINGS_MAX; i--;) { ++ hw_atl2_reg_tx_intr_moder_ctrl_set(self, itr_tx, i); ++ hw_atl_reg_rx_intr_moder_ctrl_set(self, itr_rx, i); ++ } ++ ++ return aq_hw_err_from_flags(self); + } + + static int hw_atl2_hw_stop(struct aq_hw_s *self) +@@ -546,16 +586,6 @@ static int hw_atl2_hw_stop(struct aq_hw_s *self) + return 0; + } + +-static int hw_atl2_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) +-{ +- return -EOPNOTSUPP; +-} +- +-static int hw_atl2_hw_ring_rx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) +-{ +- return -EOPNOTSUPP; +-} +- + static struct aq_stats_s *hw_atl2_utils_get_hw_stats(struct aq_hw_s *self) + { + return &self->curr_stats; +@@ -619,21 +649,21 @@ static int hw_atl2_hw_vlan_ctrl(struct aq_hw_s *self, bool enable) + const struct aq_hw_ops hw_atl2_ops = { + .hw_soft_reset = hw_atl2_utils_soft_reset, + .hw_prepare = hw_atl2_utils_initfw, +- .hw_set_mac_address = hw_atl2_hw_mac_addr_set, ++ .hw_set_mac_address = hw_atl_b0_hw_mac_addr_set, + .hw_init = hw_atl2_hw_init, + .hw_reset = hw_atl2_hw_reset, + .hw_start = hw_atl_b0_hw_start, +- .hw_ring_tx_start = hw_atl2_hw_ring_tx_start, +- .hw_ring_tx_stop = hw_atl2_hw_ring_tx_stop, +- .hw_ring_rx_start = hw_atl2_hw_ring_rx_start, +- .hw_ring_rx_stop = hw_atl2_hw_ring_rx_stop, ++ .hw_ring_tx_start = hw_atl_b0_hw_ring_tx_start, ++ .hw_ring_tx_stop = hw_atl_b0_hw_ring_tx_stop, ++ .hw_ring_rx_start = hw_atl_b0_hw_ring_rx_start, ++ .hw_ring_rx_stop = hw_atl_b0_hw_ring_rx_stop, + .hw_stop = hw_atl2_hw_stop, + +- .hw_ring_tx_xmit = hw_atl2_hw_ring_tx_xmit, +- .hw_ring_tx_head_update = hw_atl2_hw_ring_tx_head_update, ++ .hw_ring_tx_xmit = hw_atl_b0_hw_ring_tx_xmit, ++ .hw_ring_tx_head_update = hw_atl_b0_hw_ring_tx_head_update, + +- .hw_ring_rx_receive = hw_atl2_hw_ring_rx_receive, +- .hw_ring_rx_fill = hw_atl2_hw_ring_rx_fill, ++ .hw_ring_rx_receive = hw_atl_b0_hw_ring_rx_receive, ++ .hw_ring_rx_fill = hw_atl_b0_hw_ring_rx_fill, + + .hw_irq_enable = hw_atl_b0_hw_irq_enable, + .hw_irq_disable = hw_atl_b0_hw_irq_disable, +@@ -650,5 +680,5 @@ const struct aq_hw_ops hw_atl2_ops = { + .hw_rss_hash_set = hw_atl_b0_hw_rss_hash_set, + .hw_get_hw_stats = hw_atl2_utils_get_hw_stats, + .hw_get_fw_version = hw_atl2_utils_get_fw_version, +- .hw_set_offload = hw_atl2_hw_offload_set, ++ .hw_set_offload = hw_atl_b0_hw_offload_set, + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +index eb1243256730..e66b3583bfe9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +@@ -34,6 +34,9 @@ + #define HW_ATL2_TC_MAX 1U + #define HW_ATL2_RSS_MAX 8U + ++#define HW_ATL2_INTR_MODER_MAX 0x1FF ++#define HW_ATL2_INTR_MODER_MIN 0xFF ++ + #define HW_ATL2_MIN_RXD \ + (ALIGN(AQ_CFG_SKB_FRAGS_MAX + 1U, AQ_HW_RXD_MULTIPLE)) + #define HW_ATL2_MIN_TXD \ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +index af176e1e5a18..e779d70fde66 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +@@ -68,6 +68,14 @@ void hw_atl2_tpb_tx_buf_clk_gate_en_set(struct aq_hw_s *aq_hw, u32 clk_gate_en) + clk_gate_en); + } + ++void hw_atl2_reg_tx_intr_moder_ctrl_set(struct aq_hw_s *aq_hw, ++ u32 tx_intr_moderation_ctl, ++ u32 queue) ++{ ++ aq_hw_write_reg(aq_hw, HW_ATL2_TX_INTR_MODERATION_CTL_ADR(queue), ++ tx_intr_moderation_ctl); ++} ++ + void hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw, + u32 max_credit, + u32 tc) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +index 4acbbceb623f..8c6d78a64d42 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +@@ -10,6 +10,11 @@ + + struct aq_hw_s; + ++/* Set TX Interrupt Moderation Control Register */ ++void hw_atl2_reg_tx_intr_moder_ctrl_set(struct aq_hw_s *aq_hw, ++ u32 tx_intr_moderation_ctl, ++ u32 queue); ++ + /** Set RSS HASH type */ + void hw_atl2_rpf_rss_hash_type_set(struct aq_hw_s *aq_hw, u32 rss_hash_type); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +index 14b78e090950..cde9e9d2836d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +@@ -178,6 +178,14 @@ + /* default value of bitfield data_tc{t}_weight[8:0] */ + #define HW_ATL2_TPS_DATA_TCTWEIGHT_DEFAULT 0x0 + ++/* tx interrupt moderation control register definitions ++ * Preprocessor definitions for TX Interrupt Moderation Control Register ++ * Base Address: 0x00007c28 ++ * Parameter: queue {Q} | stride size 0x4 | range [0, 31] ++ */ ++ ++#define HW_ATL2_TX_INTR_MODERATION_CTL_ADR(queue) (0x00007c28u + (queue) * 0x40) ++ + /* Launch time control register */ + #define HW_ATL2_LT_CTRL_ADR 0x00007a1c + +-- +2.13.6 + diff --git a/SOURCES/0087-netdrv-net-atlantic-use-__packed-instead-of-the-full.patch b/SOURCES/0087-netdrv-net-atlantic-use-__packed-instead-of-the-full.patch new file mode 100644 index 0000000..51c30f0 --- /dev/null +++ b/SOURCES/0087-netdrv-net-atlantic-use-__packed-instead-of-the-full.patch @@ -0,0 +1,64 @@ +From df116d1021a40269baf7a6211166b4c27f429f58 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:44 -0500 +Subject: [PATCH 087/139] [netdrv] net: atlantic: use __packed instead of the + full expansion + +Message-id: <1604687916-15087-88-git-send-email-irusskik@redhat.com> +Patchwork-id: 338514 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 087/139] net: atlantic: use __packed instead of the full expansion. +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 38e86bfcf7f565639d89ce99ecf41a598f652cdc +Author: Mark Starovoytov +Date: Sat May 9 09:46:54 2020 +0300 + + net: atlantic: use __packed instead of the full expansion. + + This patches fixes the review comment made by Jakub Kicinski + in the "net: atlantic: A2 support" patch series. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: Jakub Kicinski + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h +index 2317dd8459d0..b66fa346581c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h +@@ -103,7 +103,7 @@ struct sleep_proxy_s { + u32 crc32; + } wake_up_pattern[8]; + +- struct __attribute__ ((__packed__)) { ++ struct __packed { + u8 arp_responder:1; + u8 echo_responder:1; + u8 igmp_client:1; +@@ -119,7 +119,7 @@ struct sleep_proxy_s { + u32 ipv4_offload_addr[8]; + u32 reserved[8]; + +- struct __attribute__ ((__packed__)) { ++ struct __packed { + u8 ns_responder:1; + u8 echo_responder:1; + u8 mld_client:1; +-- +2.13.6 + diff --git a/SOURCES/0088-netdrv-net-atlantic-rename-AQ_NIC_RATE_2GS-to-AQ_NIC.patch b/SOURCES/0088-netdrv-net-atlantic-rename-AQ_NIC_RATE_2GS-to-AQ_NIC.patch new file mode 100644 index 0000000..e5837a9 --- /dev/null +++ b/SOURCES/0088-netdrv-net-atlantic-rename-AQ_NIC_RATE_2GS-to-AQ_NIC.patch @@ -0,0 +1,363 @@ +From 64e7157cb3b8b12053e9ec373fbf6790c66cfd20 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:45 -0500 +Subject: [PATCH 088/139] [netdrv] net: atlantic: rename AQ_NIC_RATE_2GS to + AQ_NIC_RATE_2G5 + +Message-id: <1604687916-15087-89-git-send-email-irusskik@redhat.com> +Patchwork-id: 338518 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 088/139] net: atlantic: rename AQ_NIC_RATE_2GS to AQ_NIC_RATE_2G5 +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 843e1396f62ed7ff57feaea9ceb3374ad42f445f +Author: Mark Starovoytov +Date: Sat May 9 09:46:56 2020 +0300 + + net: atlantic: rename AQ_NIC_RATE_2GS to AQ_NIC_RATE_2G5 + + This patch changes the constant name to a more logical "2G5" + (for 2.5G speeds). + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: Jakub Kicinski + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_common.h | 11 ++++++----- + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 2 +- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 13 +++++++------ + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 15 ++++++++------- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 15 ++++++++------- + .../net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c | 9 +++++---- + .../net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h | 9 +++++---- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 13 +++++++------ + drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 2 +- + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 2 +- + 10 files changed, 49 insertions(+), 42 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +index 53620ba6d7a6..52ad9433cabc 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +@@ -1,7 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_common.h: Basic includes for all files in project. */ +@@ -53,14 +54,14 @@ + #define AQ_NIC_RATE_10G BIT(0) + #define AQ_NIC_RATE_5G BIT(1) + #define AQ_NIC_RATE_5GSR BIT(2) +-#define AQ_NIC_RATE_2GS BIT(3) ++#define AQ_NIC_RATE_2G5 BIT(3) + #define AQ_NIC_RATE_1G BIT(4) + #define AQ_NIC_RATE_100M BIT(5) + #define AQ_NIC_RATE_10M BIT(6) + + #define AQ_NIC_RATE_EEE_10G BIT(7) + #define AQ_NIC_RATE_EEE_5G BIT(8) +-#define AQ_NIC_RATE_EEE_2GS BIT(9) ++#define AQ_NIC_RATE_EEE_2G5 BIT(9) + #define AQ_NIC_RATE_EEE_1G BIT(10) + #define AQ_NIC_RATE_EEE_100M BIT(11) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 46e8a17e7131..a0d8f9366e1b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -476,7 +476,7 @@ static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed) + if (speed & AQ_NIC_RATE_EEE_10G) + rate |= SUPPORTED_10000baseT_Full; + +- if (speed & AQ_NIC_RATE_EEE_2GS) ++ if (speed & AQ_NIC_RATE_EEE_2G5) + rate |= SUPPORTED_2500baseX_Full; + + if (speed & AQ_NIC_RATE_EEE_1G) +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 73bfb2bbb115..ee8218d43b31 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -1,7 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_nic.c: Definition of common code for NIC. */ +@@ -878,7 +879,7 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, + ethtool_link_ksettings_add_link_mode(cmd, supported, + 5000baseT_Full); + +- if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_2GS) ++ if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_2G5) + ethtool_link_ksettings_add_link_mode(cmd, supported, + 2500baseT_Full); + +@@ -921,7 +922,7 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 5000baseT_Full); + +- if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_2GS) ++ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_2G5) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 2500baseT_Full); + +@@ -980,7 +981,7 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self, + break; + + case SPEED_2500: +- rate = AQ_NIC_RATE_2GS; ++ rate = AQ_NIC_RATE_2G5; + break; + + case SPEED_5000: +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index eee265b4415a..70f06c40bdf2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -1,7 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File hw_atl_a0.c: Definition of Atlantic hardware specific functions. */ +@@ -47,7 +48,7 @@ const struct aq_hw_caps_s hw_atl_a0_caps_aqc100 = { + DEFAULT_A0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_FIBRE, + .link_speed_msk = AQ_NIC_RATE_5G | +- AQ_NIC_RATE_2GS | ++ AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M, + }; +@@ -57,7 +58,7 @@ const struct aq_hw_caps_s hw_atl_a0_caps_aqc107 = { + .media_type = AQ_HW_MEDIA_TYPE_TP, + .link_speed_msk = AQ_NIC_RATE_10G | + AQ_NIC_RATE_5G | +- AQ_NIC_RATE_2GS | ++ AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M, + }; +@@ -66,7 +67,7 @@ const struct aq_hw_caps_s hw_atl_a0_caps_aqc108 = { + DEFAULT_A0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_TP, + .link_speed_msk = AQ_NIC_RATE_5G | +- AQ_NIC_RATE_2GS | ++ AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M, + }; +@@ -74,7 +75,7 @@ const struct aq_hw_caps_s hw_atl_a0_caps_aqc108 = { + const struct aq_hw_caps_s hw_atl_a0_caps_aqc109 = { + DEFAULT_A0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_TP, +- .link_speed_msk = AQ_NIC_RATE_2GS | ++ .link_speed_msk = AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M, + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index cbb7a00d61b4..1d872547a87c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1,7 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File hw_atl_b0.c: Definition of Atlantic hardware specific functions. */ +@@ -59,7 +60,7 @@ const struct aq_hw_caps_s hw_atl_b0_caps_aqc100 = { + .media_type = AQ_HW_MEDIA_TYPE_FIBRE, + .link_speed_msk = AQ_NIC_RATE_10G | + AQ_NIC_RATE_5G | +- AQ_NIC_RATE_2GS | ++ AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M, + }; +@@ -69,7 +70,7 @@ const struct aq_hw_caps_s hw_atl_b0_caps_aqc107 = { + .media_type = AQ_HW_MEDIA_TYPE_TP, + .link_speed_msk = AQ_NIC_RATE_10G | + AQ_NIC_RATE_5G | +- AQ_NIC_RATE_2GS | ++ AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M, + }; +@@ -78,7 +79,7 @@ const struct aq_hw_caps_s hw_atl_b0_caps_aqc108 = { + DEFAULT_B0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_TP, + .link_speed_msk = AQ_NIC_RATE_5G | +- AQ_NIC_RATE_2GS | ++ AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M, + }; +@@ -86,7 +87,7 @@ const struct aq_hw_caps_s hw_atl_b0_caps_aqc108 = { + const struct aq_hw_caps_s hw_atl_b0_caps_aqc109 = { + DEFAULT_B0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_TP, +- .link_speed_msk = AQ_NIC_RATE_2GS | ++ .link_speed_msk = AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M, + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 1100d40a0302..73c0f41df8d8 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -1,7 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File hw_atl_utils.c: Definition of common functions for Atlantic hardware +@@ -687,7 +688,7 @@ int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self) + link_status->mbps = 5000U; + break; + +- case HAL_ATLANTIC_RATE_2GS: ++ case HAL_ATLANTIC_RATE_2G5: + link_status->mbps = 2500U; + break; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index 80cbd1a8e378..c74cf5cf7e46 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -1,7 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File hw_atl_utils.h: Declaration of common functions for Atlantic hardware +@@ -392,7 +393,7 @@ enum hal_atl_utils_fw_state_e { + #define HAL_ATLANTIC_RATE_10G BIT(0) + #define HAL_ATLANTIC_RATE_5G BIT(1) + #define HAL_ATLANTIC_RATE_5GSR BIT(2) +-#define HAL_ATLANTIC_RATE_2GS BIT(3) ++#define HAL_ATLANTIC_RATE_2G5 BIT(3) + #define HAL_ATLANTIC_RATE_1G BIT(4) + #define HAL_ATLANTIC_RATE_100M BIT(5) + #define HAL_ATLANTIC_RATE_INVALID BIT(6) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index 77a4ed64830f..719fad921cb8 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -1,7 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File hw_atl_utils_fw2x.c: Definition of firmware 2.x functions for +@@ -131,7 +132,7 @@ static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed) + if (speed & AQ_NIC_RATE_5GSR) + rate |= FW2X_RATE_5G; + +- if (speed & AQ_NIC_RATE_2GS) ++ if (speed & AQ_NIC_RATE_2G5) + rate |= FW2X_RATE_2G5; + + if (speed & AQ_NIC_RATE_1G) +@@ -152,7 +153,7 @@ static u32 fw2x_to_eee_mask(u32 speed) + if (speed & HW_ATL_FW2X_CAP_EEE_5G_MASK) + rate |= AQ_NIC_RATE_EEE_5G; + if (speed & HW_ATL_FW2X_CAP_EEE_2G5_MASK) +- rate |= AQ_NIC_RATE_EEE_2GS; ++ rate |= AQ_NIC_RATE_EEE_2G5; + if (speed & HW_ATL_FW2X_CAP_EEE_1G_MASK) + rate |= AQ_NIC_RATE_EEE_1G; + +@@ -167,7 +168,7 @@ static u32 eee_mask_to_fw2x(u32 speed) + rate |= HW_ATL_FW2X_CAP_EEE_10G_MASK; + if (speed & AQ_NIC_RATE_EEE_5G) + rate |= HW_ATL_FW2X_CAP_EEE_5G_MASK; +- if (speed & AQ_NIC_RATE_EEE_2GS) ++ if (speed & AQ_NIC_RATE_EEE_2G5) + rate |= HW_ATL_FW2X_CAP_EEE_2G5_MASK; + if (speed & AQ_NIC_RATE_EEE_1G) + rate |= HW_ATL_FW2X_CAP_EEE_1G_MASK; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index 04d194f754fa..84d9b828dc4e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -60,7 +60,7 @@ const struct aq_hw_caps_s hw_atl2_caps_aqc113 = { + .media_type = AQ_HW_MEDIA_TYPE_TP, + .link_speed_msk = AQ_NIC_RATE_10G | + AQ_NIC_RATE_5G | +- AQ_NIC_RATE_2GS | ++ AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M | + AQ_NIC_RATE_10M, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +index f5fb4b11f51a..e8f4aad8c1e5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +@@ -129,7 +129,7 @@ static void a2_link_speed_mask2fw(u32 speed, + link_options->rate_10G = !!(speed & AQ_NIC_RATE_10G); + link_options->rate_5G = !!(speed & AQ_NIC_RATE_5G); + link_options->rate_N5G = !!(speed & AQ_NIC_RATE_5GSR); +- link_options->rate_2P5G = !!(speed & AQ_NIC_RATE_2GS); ++ link_options->rate_2P5G = !!(speed & AQ_NIC_RATE_2G5); + link_options->rate_N2P5G = link_options->rate_2P5G; + link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G); + link_options->rate_100M = !!(speed & AQ_NIC_RATE_100M); +-- +2.13.6 + diff --git a/SOURCES/0089-netdrv-net-atlantic-remove-TPO2-check-from-A0-code.patch b/SOURCES/0089-netdrv-net-atlantic-remove-TPO2-check-from-A0-code.patch new file mode 100644 index 0000000..1cf91d5 --- /dev/null +++ b/SOURCES/0089-netdrv-net-atlantic-remove-TPO2-check-from-A0-code.patch @@ -0,0 +1,55 @@ +From 1b38e48b56c98151356fccf0c2ad1e277566fa79 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:46 -0500 +Subject: [PATCH 089/139] [netdrv] net: atlantic: remove TPO2 check from A0 + code + +Message-id: <1604687916-15087-90-git-send-email-irusskik@redhat.com> +Patchwork-id: 338520 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 089/139] net: atlantic: remove TPO2 check from A0 code +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit c64d7b23f51161ceb6e92f8e5b8077e8e04ddbef +Author: Mark Starovoytov +Date: Sat May 9 09:46:57 2020 +0300 + + net: atlantic: remove TPO2 check from A0 code + + TPO2 was introduced in B0 only, no reason to check for it in A0 code. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: Jakub Kicinski + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index 70f06c40bdf2..1b0670a8ae33 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -268,8 +268,7 @@ static int hw_atl_a0_hw_init_tx_path(struct aq_hw_s *self) + hw_atl_tdm_tx_desc_wr_wb_irq_en_set(self, 1U); + + /* misc */ +- aq_hw_write_reg(self, 0x00007040U, ATL_HW_IS_CHIP_FEATURE(self, TPO2) ? +- 0x00010000U : 0x00000000U); ++ aq_hw_write_reg(self, 0x00007040U, 0x00000000U); + hw_atl_tdm_tx_dca_en_set(self, 0U); + hw_atl_tdm_tx_dca_mode_set(self, 0U); + +-- +2.13.6 + diff --git a/SOURCES/0090-netdrv-net-atlantic-remove-hw_atl_b0_hw_rss_set-call.patch b/SOURCES/0090-netdrv-net-atlantic-remove-hw_atl_b0_hw_rss_set-call.patch new file mode 100644 index 0000000..828aaeb --- /dev/null +++ b/SOURCES/0090-netdrv-net-atlantic-remove-hw_atl_b0_hw_rss_set-call.patch @@ -0,0 +1,96 @@ +From c95311eccb9cb3c5fe7c9b29bb040d9a6d641c50 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:47 -0500 +Subject: [PATCH 090/139] [netdrv] net: atlantic: remove hw_atl_b0_hw_rss_set + call from A2 code + +Message-id: <1604687916-15087-91-git-send-email-irusskik@redhat.com> +Patchwork-id: 338507 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 090/139] net: atlantic: remove hw_atl_b0_hw_rss_set call from A2 code +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit ad46bd5ec357ebb18c42398d8760bad4d611b53e +Author: Mark Starovoytov +Date: Sat May 9 09:46:58 2020 +0300 + + net: atlantic: remove hw_atl_b0_hw_rss_set call from A2 code + + No need to call hw_atl_b0_hw_rss_set from hw_atl2_hw_rss_set + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: Jakub Kicinski + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 4 ++-- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h | 9 ++++----- + drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 2 +- + 3 files changed, 7 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 1d872547a87c..fa3cd7e9954b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -216,8 +216,8 @@ int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self, + return err; + } + +-int hw_atl_b0_hw_rss_set(struct aq_hw_s *self, +- struct aq_rss_parameters *rss_params) ++static int hw_atl_b0_hw_rss_set(struct aq_hw_s *self, ++ struct aq_rss_parameters *rss_params) + { + u32 num_rss_queues = max(1U, self->aq_nic_cfg->num_rss_queues); + u8 *indirection_table = rss_params->indirection_table; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +index f5091d79ab43..b855459272ca 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +@@ -1,7 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File hw_atl_b0.h: Declaration of abstract interface for Atlantic hardware +@@ -35,8 +36,6 @@ extern const struct aq_hw_ops hw_atl_ops_b0; + + int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self, + struct aq_rss_parameters *rss_params); +-int hw_atl_b0_hw_rss_set(struct aq_hw_s *self, +- struct aq_rss_parameters *rss_params); + int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, + struct aq_nic_cfg_s *aq_nic_cfg); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index 84d9b828dc4e..6f2b33ae3d06 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -172,7 +172,7 @@ static int hw_atl2_hw_rss_set(struct aq_hw_s *self, + for (i = HW_ATL2_RSS_REDIRECTION_MAX; i--;) + hw_atl2_new_rpf_rss_redir_set(self, 0, i, indirection_table[i]); + +- return hw_atl_b0_hw_rss_set(self, rss_params); ++ return aq_hw_err_from_flags(self); + } + + static int hw_atl2_hw_init_tx_path(struct aq_hw_s *self) +-- +2.13.6 + diff --git a/SOURCES/0091-netdrv-net-atlantic-remove-check-for-boot-code-survi.patch b/SOURCES/0091-netdrv-net-atlantic-remove-check-for-boot-code-survi.patch new file mode 100644 index 0000000..9d03043 --- /dev/null +++ b/SOURCES/0091-netdrv-net-atlantic-remove-check-for-boot-code-survi.patch @@ -0,0 +1,61 @@ +From f6b03427010b384184320f64ce0b3400cf3717bd Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:48 -0500 +Subject: [PATCH 091/139] [netdrv] net: atlantic: remove check for boot code + survivability before reset request + +Message-id: <1604687916-15087-92-git-send-email-irusskik@redhat.com> +Patchwork-id: 338510 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 091/139] net: atlantic: remove check for boot code survivability before reset request +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 097d638cf4e19be208d26c6bbbca7f8da348294a +Author: Mark Starovoytov +Date: Sat May 9 09:46:59 2020 +0300 + + net: atlantic: remove check for boot code survivability before reset request + + This patch removes unnecessary check for boot code survivability before + reset request. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: Jakub Kicinski + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c +index 85ccc9a011a0..f3766780e975 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c +@@ -75,14 +75,6 @@ int hw_atl2_utils_soft_reset(struct aq_hw_s *self) + u32 rbl_request; + int err; + +- err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_boot_reg_get, self, +- rbl_status, +- ((rbl_status & AQ_A2_BOOT_STARTED) && +- (rbl_status != 0xFFFFFFFFu)), +- 10, 500000); +- if (err) +- aq_pr_trace("Boot code probably hanged, reboot anyway"); +- + hw_atl2_mif_host_req_int_clr(self, 0x01); + rbl_request = AQ_A2_FW_BOOT_REQ_REBOOT; + #ifdef AQ_CFG_FAST_START +-- +2.13.6 + diff --git a/SOURCES/0092-netdrv-net-atlantic-unify-MAC-generation.patch b/SOURCES/0092-netdrv-net-atlantic-unify-MAC-generation.patch new file mode 100644 index 0000000..942d759 --- /dev/null +++ b/SOURCES/0092-netdrv-net-atlantic-unify-MAC-generation.patch @@ -0,0 +1,170 @@ +From 87996301447ff46d4dbdc81cade0315957c3ffbb Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:49 -0500 +Subject: [PATCH 092/139] [netdrv] net: atlantic: unify MAC generation + +Message-id: <1604687916-15087-93-git-send-email-irusskik@redhat.com> +Patchwork-id: 338515 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 092/139] net: atlantic: unify MAC generation +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit b4de6c49e569c7ca91bf0d4c25cdb6eeca9c9529 +Author: Mark Starovoytov +Date: Sat May 9 09:47:00 2020 +0300 + + net: atlantic: unify MAC generation + + This patch unifies invalid MAC address handling with other drivers. + + Basically we've switched to using standard APIs (is_valid_ether_addr / + eth_hw_addr_random) where possible. + It's worth noting that some of engineering Aquantia NICs might be + provisioned with a partially zeroed out MAC, which is still invalid, + but not caught by is_valid_ether_addr(), so we've added a special + handling for this case. + + Also adding a warning in case of fallback to random MAC, because + this shouldn't be needed on production NICs, they should all be + provisioned with unique MAC. + + NB! Default systemd/udevd configuration is 'MACAddressPolicy=persistent'. + This causes MAC address to be persisted across driver reloads and + reboots. We had to change it to 'none' for verification purposes. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: Jakub Kicinski + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 14 +++++++++++++ + .../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 22 --------------------- + .../aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 23 +--------------------- + 3 files changed, 15 insertions(+), 44 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index ee8218d43b31..4918c6867c2b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -264,6 +264,14 @@ static int aq_nic_hw_prepare(struct aq_nic_s *self) + return err; + } + ++static bool aq_nic_is_valid_ether_addr(const u8 *addr) ++{ ++ /* Some engineering samples of Aquantia NICs are provisioned with a ++ * partially populated MAC, which is still invalid. ++ */ ++ return !(addr[0] == 0 && addr[1] == 0 && addr[2] == 0); ++} ++ + int aq_nic_ndev_register(struct aq_nic_s *self) + { + int err = 0; +@@ -284,6 +292,12 @@ int aq_nic_ndev_register(struct aq_nic_s *self) + if (err) + goto err_exit; + ++ if (!is_valid_ether_addr(self->ndev->dev_addr) || ++ !aq_nic_is_valid_ether_addr(self->ndev->dev_addr)) { ++ netdev_warn(self->ndev, "MAC is invalid, will use random."); ++ eth_hw_addr_random(self->ndev); ++ } ++ + #if defined(AQ_CFG_MAC_ADDR_PERMANENT) + { + static u8 mac_addr_permanent[] = AQ_CFG_MAC_ADDR_PERMANENT; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index 719fad921cb8..8296a1e63522 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -280,8 +280,6 @@ static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac) + u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR); + u32 mac_addr[2] = { 0 }; + int err = 0; +- u32 h = 0U; +- u32 l = 0U; + + if (efuse_addr != 0) { + err = hw_atl_utils_fw_downld_dwords(self, +@@ -296,26 +294,6 @@ static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac) + + ether_addr_copy(mac, (u8 *)mac_addr); + +- if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) { +- unsigned int rnd = 0; +- +- get_random_bytes(&rnd, sizeof(unsigned int)); +- +- l = 0xE3000000U | (0xFFFFU & rnd) | (0x00 << 16); +- h = 0x8001300EU; +- +- mac[5] = (u8)(0xFFU & l); +- l >>= 8; +- mac[4] = (u8)(0xFFU & l); +- l >>= 8; +- mac[3] = (u8)(0xFFU & l); +- l >>= 8; +- mac[2] = (u8)(0xFFU & l); +- mac[1] = (u8)(0xFFU & h); +- h >>= 8; +- mac[0] = (u8)(0xFFU & h); +- } +- + return err; + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +index e8f4aad8c1e5..0ffc33bd67d0 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +@@ -6,6 +6,7 @@ + #include + + #include "aq_hw.h" ++#include "aq_hw_utils.h" + #include "hw_atl/hw_atl_llh.h" + #include "hw_atl2_utils.h" + #include "hw_atl2_llh.h" +@@ -212,28 +213,6 @@ static int aq_a2_fw_get_mac_permanent(struct aq_hw_s *self, u8 *mac) + hw_atl2_shared_buffer_get(self, mac_address, mac_address); + ether_addr_copy(mac, (u8 *)mac_address.aligned.mac_address); + +- if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) { +- unsigned int rnd = 0; +- u32 h; +- u32 l; +- +- get_random_bytes(&rnd, sizeof(unsigned int)); +- +- l = 0xE3000000U | (0xFFFFU & rnd) | (0x00 << 16); +- h = 0x8001300EU; +- +- mac[5] = (u8)(0xFFU & l); +- l >>= 8; +- mac[4] = (u8)(0xFFU & l); +- l >>= 8; +- mac[3] = (u8)(0xFFU & l); +- l >>= 8; +- mac[2] = (u8)(0xFFU & l); +- mac[1] = (u8)(0xFFU & h); +- h >>= 8; +- mac[0] = (u8)(0xFFU & h); +- } +- + return 0; + } + +-- +2.13.6 + diff --git a/SOURCES/0093-netdrv-net-atlantic-changes-for-multi-TC-support.patch b/SOURCES/0093-netdrv-net-atlantic-changes-for-multi-TC-support.patch new file mode 100644 index 0000000..b8da8d2 --- /dev/null +++ b/SOURCES/0093-netdrv-net-atlantic-changes-for-multi-TC-support.patch @@ -0,0 +1,558 @@ +From a488999bedd7f01e8a113c097ac3c968e0513046 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:50 -0500 +Subject: [PATCH 093/139] [netdrv] net: atlantic: changes for multi-TC support + +Message-id: <1604687916-15087-94-git-send-email-irusskik@redhat.com> +Patchwork-id: 338511 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 093/139] net: atlantic: changes for multi-TC support +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 8ce84271697a2346e88582480b26b7e244a8603a +Author: Dmitry Bezrukov +Date: Fri May 22 11:19:37 2020 +0300 + + net: atlantic: changes for multi-TC support + + This patch contains the following changes: + * access cfg via aq_nic_get_cfg() in aq_nic_start() and aq_nic_map_skb(); + * call aq_nic_get_dev() just once in aq_nic_map_skb(); + * move ring allocation/deallocation out of aq_vec_alloc()/aq_vec_free(); + * add the missing aq_nic_deinit() in atl_resume_common(); + * rename 'tcs' field to 'tcs_max' in aq_hw_caps_s to differentiate it from + the 'tcs' field in aq_nic_cfg_s, which is used for the current number of + TCs; + * update _TC_MAX defines to the actual number of supported TCs; + * move tx_tc_mode register defines slightly higher (just to keep the order + of definitions); + * separate variables for TX/RX buff_size in hw_atl*_hw_qos_set(); + * use AQ_HW_*_TC instead of hardcoded magic numbers; + * actually use the 'ret' value in aq_mdo_add_secy(); + + Signed-off-by: Dmitry Bezrukov + Co-developed-by: Mark Starovoytov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 4 +- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 43 +++++++++++++------- + .../net/ethernet/aquantia/atlantic/aq_pci_func.c | 3 ++ + drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 47 ++++++++++++++-------- + drivers/net/ethernet/aquantia/atlantic/aq_vec.h | 3 ++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 2 +- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 34 +++++++--------- + .../aquantia/atlantic/hw_atl/hw_atl_b0_internal.h | 2 +- + .../aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 31 ++++++++------ + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 4 +- + .../aquantia/atlantic/hw_atl2/hw_atl2_internal.h | 2 +- + 11 files changed, 104 insertions(+), 71 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index ccdace2ccad2..d63cebceb554 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -46,7 +46,7 @@ struct aq_hw_caps_s { + u32 mac_regs_count; + u32 hw_alive_check_addr; + u8 msix_irqs; +- u8 tcs; ++ u8 tcs_max; + u8 rxd_alignment; + u8 rxd_size; + u8 txd_alignment; +@@ -120,6 +120,8 @@ struct aq_stats_s { + #define AQ_HW_TXD_MULTIPLE 8U + #define AQ_HW_RXD_MULTIPLE 8U + ++#define AQ_HW_PTP_TC 2U ++ + #define AQ_HW_LED_BLINK 0x2U + #define AQ_HW_LED_DEFAULT 0x0U + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 4918c6867c2b..369f71e8edef 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -383,9 +383,15 @@ int aq_nic_init(struct aq_nic_s *self) + err = aq_phy_init(self->aq_hw); + } + +- for (i = 0U, aq_vec = self->aq_vec[0]; +- self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) ++ for (i = 0U; i < self->aq_vecs; i++) { ++ aq_vec = self->aq_vec[i]; ++ err = aq_vec_ring_alloc(aq_vec, self, i, ++ aq_nic_get_cfg(self)); ++ if (err) ++ goto err_exit; ++ + aq_vec_init(aq_vec, self->aq_hw_ops, self->aq_hw); ++ } + + err = aq_ptp_init(self, self->irqvecs - 1); + if (err < 0) +@@ -408,9 +414,12 @@ int aq_nic_init(struct aq_nic_s *self) + int aq_nic_start(struct aq_nic_s *self) + { + struct aq_vec_s *aq_vec = NULL; ++ struct aq_nic_cfg_s *cfg; + unsigned int i = 0U; + int err = 0; + ++ cfg = aq_nic_get_cfg(self); ++ + err = self->aq_hw_ops->hw_multicast_list_set(self->aq_hw, + self->mc_list.ar, + self->mc_list.count); +@@ -448,7 +457,7 @@ int aq_nic_start(struct aq_nic_s *self) + timer_setup(&self->service_timer, aq_nic_service_timer_cb, 0); + aq_nic_service_timer_cb(&self->service_timer); + +- if (self->aq_nic_cfg.is_polling) { ++ if (cfg->is_polling) { + timer_setup(&self->polling_timer, aq_nic_polling_timer_cb, 0); + mod_timer(&self->polling_timer, jiffies + + AQ_CFG_POLLING_TIMER_INTERVAL); +@@ -466,16 +475,16 @@ int aq_nic_start(struct aq_nic_s *self) + if (err < 0) + goto err_exit; + +- if (self->aq_nic_cfg.link_irq_vec) { ++ if (cfg->link_irq_vec) { + int irqvec = pci_irq_vector(self->pdev, +- self->aq_nic_cfg.link_irq_vec); ++ cfg->link_irq_vec); + err = request_threaded_irq(irqvec, NULL, + aq_linkstate_threaded_isr, + IRQF_SHARED | IRQF_ONESHOT, + self->ndev->name, self); + if (err < 0) + goto err_exit; +- self->msix_entry_mask |= (1 << self->aq_nic_cfg.link_irq_vec); ++ self->msix_entry_mask |= (1 << cfg->link_irq_vec); + } + + err = self->aq_hw_ops->hw_irq_enable(self->aq_hw, +@@ -502,6 +511,8 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + struct aq_ring_s *ring) + { + unsigned int nr_frags = skb_shinfo(skb)->nr_frags; ++ struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(self); ++ struct device *dev = aq_nic_get_dev(self); + struct aq_ring_buff_s *first = NULL; + u8 ipver = ip_hdr(skb)->version; + struct aq_ring_buff_s *dx_buff; +@@ -543,7 +554,7 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + need_context_tag = true; + } + +- if (self->aq_nic_cfg.is_vlan_tx_insert && skb_vlan_tag_present(skb)) { ++ if (cfg->is_vlan_tx_insert && skb_vlan_tag_present(skb)) { + dx_buff->vlan_tx_tag = skb_vlan_tag_get(skb); + dx_buff->len_pkt = skb->len; + dx_buff->is_vlan = 1U; +@@ -558,12 +569,12 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + } + + dx_buff->len = skb_headlen(skb); +- dx_buff->pa = dma_map_single(aq_nic_get_dev(self), ++ dx_buff->pa = dma_map_single(dev, + skb->data, + dx_buff->len, + DMA_TO_DEVICE); + +- if (unlikely(dma_mapping_error(aq_nic_get_dev(self), dx_buff->pa))) { ++ if (unlikely(dma_mapping_error(dev, dx_buff->pa))) { + ret = 0; + goto exit; + } +@@ -595,13 +606,13 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + else + buff_size = frag_len; + +- frag_pa = skb_frag_dma_map(aq_nic_get_dev(self), ++ frag_pa = skb_frag_dma_map(dev, + frag, + buff_offset, + buff_size, + DMA_TO_DEVICE); + +- if (unlikely(dma_mapping_error(aq_nic_get_dev(self), ++ if (unlikely(dma_mapping_error(dev, + frag_pa))) + goto mapping_error; + +@@ -635,12 +646,12 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + if (!(dx_buff->is_gso_tcp || dx_buff->is_gso_udp) && + !dx_buff->is_vlan && dx_buff->pa) { + if (unlikely(dx_buff->is_sop)) { +- dma_unmap_single(aq_nic_get_dev(self), ++ dma_unmap_single(dev, + dx_buff->pa, + dx_buff->len, + DMA_TO_DEVICE); + } else { +- dma_unmap_page(aq_nic_get_dev(self), ++ dma_unmap_page(dev, + dx_buff->pa, + dx_buff->len, + DMA_TO_DEVICE); +@@ -1129,9 +1140,11 @@ void aq_nic_deinit(struct aq_nic_s *self, bool link_down) + if (!self) + goto err_exit; + +- for (i = 0U, aq_vec = self->aq_vec[0]; +- self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) ++ for (i = 0U; i < self->aq_vecs; i++) { ++ aq_vec = self->aq_vec[i]; + aq_vec_deinit(aq_vec); ++ aq_vec_ring_free(aq_vec); ++ } + + aq_ptp_unregister(self); + aq_ptp_ring_deinit(self); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +index 34d5aaf40e19..908b35f1e7a2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +@@ -426,6 +426,9 @@ static int atl_resume_common(struct device *dev, bool deep) + netif_tx_start_all_queues(nic->ndev); + + err_exit: ++ if (ret < 0) ++ aq_nic_deinit(nic, true); ++ + rtnl_unlock(); + + return ret; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +index f40a427970dc..d5650cd6e236 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +@@ -103,16 +103,11 @@ static int aq_vec_poll(struct napi_struct *napi, int budget) + struct aq_vec_s *aq_vec_alloc(struct aq_nic_s *aq_nic, unsigned int idx, + struct aq_nic_cfg_s *aq_nic_cfg) + { +- struct aq_ring_s *ring = NULL; + struct aq_vec_s *self = NULL; +- unsigned int i = 0U; +- int err = 0; + + self = kzalloc(sizeof(*self), GFP_KERNEL); +- if (!self) { +- err = -ENOMEM; ++ if (!self) + goto err_exit; +- } + + self->aq_nic = aq_nic; + self->aq_ring_param.vec_idx = idx; +@@ -128,10 +123,19 @@ struct aq_vec_s *aq_vec_alloc(struct aq_nic_s *aq_nic, unsigned int idx, + netif_napi_add(aq_nic_get_ndev(aq_nic), &self->napi, + aq_vec_poll, AQ_CFG_NAPI_WEIGHT); + ++err_exit: ++ return self; ++} ++ ++int aq_vec_ring_alloc(struct aq_vec_s *self, struct aq_nic_s *aq_nic, ++ unsigned int idx, struct aq_nic_cfg_s *aq_nic_cfg) ++{ ++ struct aq_ring_s *ring = NULL; ++ unsigned int i = 0U; ++ int err = 0; ++ + for (i = 0; i < aq_nic_cfg->tcs; ++i) { +- unsigned int idx_ring = AQ_NIC_TCVEC2RING(self->nic, +- self->tx_rings, +- self->aq_ring_param.vec_idx); ++ unsigned int idx_ring = AQ_NIC_TCVEC2RING(aq_nic, i, idx); + + ring = aq_ring_tx_alloc(&self->ring[i][AQ_VEC_TX_ID], aq_nic, + idx_ring, aq_nic_cfg); +@@ -156,11 +160,11 @@ struct aq_vec_s *aq_vec_alloc(struct aq_nic_s *aq_nic, unsigned int idx, + + err_exit: + if (err < 0) { +- aq_vec_free(self); ++ aq_vec_ring_free(self); + self = NULL; + } + +- return self; ++ return err; + } + + int aq_vec_init(struct aq_vec_s *self, const struct aq_hw_ops *aq_hw_ops, +@@ -270,6 +274,18 @@ err_exit:; + + void aq_vec_free(struct aq_vec_s *self) + { ++ if (!self) ++ goto err_exit; ++ ++ netif_napi_del(&self->napi); ++ ++ kfree(self); ++ ++err_exit:; ++} ++ ++void aq_vec_ring_free(struct aq_vec_s *self) ++{ + struct aq_ring_s *ring = NULL; + unsigned int i = 0U; + +@@ -279,13 +295,12 @@ void aq_vec_free(struct aq_vec_s *self) + for (i = 0U, ring = self->ring[0]; + self->tx_rings > i; ++i, ring = self->ring[i]) { + aq_ring_free(&ring[AQ_VEC_TX_ID]); +- aq_ring_free(&ring[AQ_VEC_RX_ID]); ++ if (i < self->rx_rings) ++ aq_ring_free(&ring[AQ_VEC_RX_ID]); + } + +- netif_napi_del(&self->napi); +- +- kfree(self); +- ++ self->tx_rings = 0; ++ self->rx_rings = 0; + err_exit:; + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.h b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h +index 0fe8e0904c7f..0ee86b26df8a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h +@@ -25,10 +25,13 @@ irqreturn_t aq_vec_isr(int irq, void *private); + irqreturn_t aq_vec_isr_legacy(int irq, void *private); + struct aq_vec_s *aq_vec_alloc(struct aq_nic_s *aq_nic, unsigned int idx, + struct aq_nic_cfg_s *aq_nic_cfg); ++int aq_vec_ring_alloc(struct aq_vec_s *self, struct aq_nic_s *aq_nic, ++ unsigned int idx, struct aq_nic_cfg_s *aq_nic_cfg); + int aq_vec_init(struct aq_vec_s *self, const struct aq_hw_ops *aq_hw_ops, + struct aq_hw_s *aq_hw); + void aq_vec_deinit(struct aq_vec_s *self); + void aq_vec_free(struct aq_vec_s *self); ++void aq_vec_ring_free(struct aq_vec_s *self); + int aq_vec_start(struct aq_vec_s *self); + void aq_vec_stop(struct aq_vec_s *self); + cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index 1b0670a8ae33..88b17cf77625 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -21,7 +21,7 @@ + .msix_irqs = 4U, \ + .irq_mask = ~0U, \ + .vecs = HW_ATL_A0_RSS_MAX, \ +- .tcs = HW_ATL_A0_TC_MAX, \ ++ .tcs_max = HW_ATL_A0_TC_MAX, \ + .rxd_alignment = 1U, \ + .rxd_size = HW_ATL_A0_RXD_SIZE, \ + .rxds_max = HW_ATL_A0_MAX_RXD, \ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index fa3cd7e9954b..bee4fb3c8741 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -23,7 +23,7 @@ + .msix_irqs = 8U, \ + .irq_mask = ~0U, \ + .vecs = HW_ATL_B0_RSS_MAX, \ +- .tcs = HW_ATL_B0_TC_MAX, \ ++ .tcs_max = HW_ATL_B0_TC_MAX, \ + .rxd_alignment = 1U, \ + .rxd_size = HW_ATL_B0_RXD_SIZE, \ + .rxds_max = HW_ATL_B0_MAX_RXD, \ +@@ -116,8 +116,9 @@ static int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc) + + static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + { ++ u32 tx_buff_size = HW_ATL_B0_TXBUF_MAX; ++ u32 rx_buff_size = HW_ATL_B0_RXBUF_MAX; + unsigned int i_priority = 0U; +- u32 buff_size = 0U; + u32 tc = 0U; + + /* TPS Descriptor rate init */ +@@ -131,8 +132,6 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U); + hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U); + +- tc = 0; +- + /* TX Packet Scheduler Data TC0 */ + hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF, tc); + hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0x64, tc); +@@ -140,46 +139,41 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc); + + /* Tx buf size TC0 */ +- buff_size = HW_ATL_B0_TXBUF_MAX - HW_ATL_B0_PTP_TXBUF_SIZE; ++ tx_buff_size -= HW_ATL_B0_PTP_TXBUF_SIZE; + +- hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, buff_size, tc); ++ hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, tx_buff_size, tc); + hw_atl_tpb_tx_buff_hi_threshold_per_tc_set(self, +- (buff_size * ++ (tx_buff_size * + (1024 / 32U) * 66U) / + 100U, tc); + hw_atl_tpb_tx_buff_lo_threshold_per_tc_set(self, +- (buff_size * ++ (tx_buff_size * + (1024 / 32U) * 50U) / + 100U, tc); + /* Init TC2 for PTP_TX */ +- tc = 2; +- + hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, HW_ATL_B0_PTP_TXBUF_SIZE, +- tc); ++ AQ_HW_PTP_TC); + + /* QoS Rx buf size per TC */ +- tc = 0; +- buff_size = HW_ATL_B0_RXBUF_MAX - HW_ATL_B0_PTP_RXBUF_SIZE; ++ rx_buff_size -= HW_ATL_B0_PTP_RXBUF_SIZE; + +- hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, buff_size, tc); ++ hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, rx_buff_size, tc); + hw_atl_rpb_rx_buff_hi_threshold_per_tc_set(self, +- (buff_size * ++ (rx_buff_size * + (1024U / 32U) * 66U) / + 100U, tc); + hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(self, +- (buff_size * ++ (rx_buff_size * + (1024U / 32U) * 50U) / + 100U, tc); + + hw_atl_b0_set_fc(self, self->aq_nic_cfg->fc.req, tc); + + /* Init TC2 for PTP_RX */ +- tc = 2; +- + hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, HW_ATL_B0_PTP_RXBUF_SIZE, +- tc); ++ AQ_HW_PTP_TC); + /* No flow control for PTP */ +- hw_atl_rpb_rx_xoff_en_per_tc_set(self, 0U, tc); ++ hw_atl_rpb_rx_xoff_en_per_tc_set(self, 0U, AQ_HW_PTP_TC); + + /* QoS 802.1p priority -> TC mapping */ + for (i_priority = 8U; i_priority--;) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +index 7ab23a1751d3..4fba4e0928c7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +@@ -75,7 +75,7 @@ + #define HW_ATL_B0_RSS_HASHKEY_BITS 320U + + #define HW_ATL_B0_TCRSS_4_8 1 +-#define HW_ATL_B0_TC_MAX 1U ++#define HW_ATL_B0_TC_MAX 8U + #define HW_ATL_B0_RSS_MAX 8U + + #define HW_ATL_B0_LRO_RXD_MAX 16U +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +index 18de2f7b8959..5d86ffab4ece 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +@@ -2038,6 +2038,24 @@ + /* default value of bitfield lso_tcp_flag_mid[b:0] */ + #define HW_ATL_THM_LSO_TCP_FLAG_MID_DEFAULT 0x0 + ++/* tx tx_tc_mode bitfield definitions ++ * preprocessor definitions for the bitfield "tx_tc_mode". ++ * port="pif_tpb_tx_tc_mode_i,pif_tps_tx_tc_mode_i" ++ */ ++ ++/* register address for bitfield tx_tc_mode */ ++#define HW_ATL_TPB_TX_TC_MODE_ADDR 0x00007900 ++/* bitmask for bitfield tx_tc_mode */ ++#define HW_ATL_TPB_TX_TC_MODE_MSK 0x00000100 ++/* inverted bitmask for bitfield tx_tc_mode */ ++#define HW_ATL_TPB_TX_TC_MODE_MSKN 0xFFFFFEFF ++/* lower bit position of bitfield tx_tc_mode */ ++#define HW_ATL_TPB_TX_TC_MODE_SHIFT 8 ++/* width of bitfield tx_tc_mode */ ++#define HW_ATL_TPB_TX_TC_MODE_WIDTH 1 ++/* default value of bitfield tx_tc_mode */ ++#define HW_ATL_TPB_TX_TC_MODE_DEFAULT 0x0 ++ + /* tx tx_buf_en bitfield definitions + * preprocessor definitions for the bitfield "tx_buf_en". + * port="pif_tpb_tx_buf_en_i" +@@ -2056,19 +2074,6 @@ + /* default value of bitfield tx_buf_en */ + #define HW_ATL_TPB_TX_BUF_EN_DEFAULT 0x0 + +-/* register address for bitfield tx_tc_mode */ +-#define HW_ATL_TPB_TX_TC_MODE_ADDR 0x00007900 +-/* bitmask for bitfield tx_tc_mode */ +-#define HW_ATL_TPB_TX_TC_MODE_MSK 0x00000100 +-/* inverted bitmask for bitfield tx_tc_mode */ +-#define HW_ATL_TPB_TX_TC_MODE_MSKN 0xFFFFFEFF +-/* lower bit position of bitfield tx_tc_mode */ +-#define HW_ATL_TPB_TX_TC_MODE_SHIFT 8 +-/* width of bitfield tx_tc_mode */ +-#define HW_ATL_TPB_TX_TC_MODE_WIDTH 1 +-/* default value of bitfield tx_tc_mode */ +-#define HW_ATL_TPB_TX_TC_MODE_DEFAULT 0x0 +- + /* tx tx{b}_hi_thresh[c:0] bitfield definitions + * preprocessor definitions for the bitfield "tx{b}_hi_thresh[c:0]". + * parameter: buffer {b} | stride size 0x10 | range [0, 7] +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index 6f2b33ae3d06..ccdb74562270 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -23,7 +23,7 @@ static int hw_atl2_act_rslvr_table_set(struct aq_hw_s *self, u8 location, + .msix_irqs = 8U, \ + .irq_mask = ~0U, \ + .vecs = HW_ATL2_RSS_MAX, \ +- .tcs = HW_ATL2_TC_MAX, \ ++ .tcs_max = HW_ATL2_TC_MAX, \ + .rxd_alignment = 1U, \ + .rxd_size = HW_ATL2_RXD_SIZE, \ + .rxds_max = HW_ATL2_MAX_RXD, \ +@@ -126,8 +126,6 @@ static int hw_atl2_hw_qos_set(struct aq_hw_s *self) + hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U); + hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U); + +- tc = 0; +- + /* TX Packet Scheduler Data TC0 */ + hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF0, tc); + hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(self, 0x640, tc); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +index e66b3583bfe9..be0c049ea582 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +@@ -31,7 +31,7 @@ + + #define HW_ATL2_RSS_REDIRECTION_MAX 64U + +-#define HW_ATL2_TC_MAX 1U ++#define HW_ATL2_TC_MAX 8U + #define HW_ATL2_RSS_MAX 8U + + #define HW_ATL2_INTR_MODER_MAX 0x1FF +-- +2.13.6 + diff --git a/SOURCES/0094-netdrv-net-atlantic-move-PTP-TC-initialization-to-a-.patch b/SOURCES/0094-netdrv-net-atlantic-move-PTP-TC-initialization-to-a-.patch new file mode 100644 index 0000000..19d8c50 --- /dev/null +++ b/SOURCES/0094-netdrv-net-atlantic-move-PTP-TC-initialization-to-a-.patch @@ -0,0 +1,115 @@ +From 613137da8963190f61894421e8f266241738446e Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:51 -0500 +Subject: [PATCH 094/139] [netdrv] net: atlantic: move PTP TC initialization to + a separate function + +Message-id: <1604687916-15087-95-git-send-email-irusskik@redhat.com> +Patchwork-id: 338516 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 094/139] net: atlantic: move PTP TC initialization to a separate function +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 593dd0fc202eed27de07c5df9ef24a3c00cf0c09 +Author: Dmitry Bezrukov +Date: Fri May 22 11:19:38 2020 +0300 + + net: atlantic: move PTP TC initialization to a separate function + + This patch moves the PTP TC initialization into a separate function. + + Signed-off-by: Dmitry Bezrukov + Co-developed-by: Mark Starovoytov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 31 +++++++++++++--------- + 1 file changed, 19 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index bee4fb3c8741..0ff3f6eea022 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -114,6 +114,21 @@ static int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc) + return 0; + } + ++static int hw_atl_b0_tc_ptp_set(struct aq_hw_s *self) ++{ ++ /* Init TC2 for PTP_TX */ ++ hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, HW_ATL_B0_PTP_TXBUF_SIZE, ++ AQ_HW_PTP_TC); ++ ++ /* Init TC2 for PTP_RX */ ++ hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, HW_ATL_B0_PTP_RXBUF_SIZE, ++ AQ_HW_PTP_TC); ++ /* No flow control for PTP */ ++ hw_atl_rpb_rx_xoff_en_per_tc_set(self, 0U, AQ_HW_PTP_TC); ++ ++ return aq_hw_err_from_flags(self); ++} ++ + static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + { + u32 tx_buff_size = HW_ATL_B0_TXBUF_MAX; +@@ -121,6 +136,9 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + unsigned int i_priority = 0U; + u32 tc = 0U; + ++ tx_buff_size -= HW_ATL_B0_PTP_TXBUF_SIZE; ++ rx_buff_size -= HW_ATL_B0_PTP_RXBUF_SIZE; ++ + /* TPS Descriptor rate init */ + hw_atl_tps_tx_pkt_shed_desc_rate_curr_time_res_set(self, 0x0U); + hw_atl_tps_tx_pkt_shed_desc_rate_lim_set(self, 0xA); +@@ -139,8 +157,6 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc); + + /* Tx buf size TC0 */ +- tx_buff_size -= HW_ATL_B0_PTP_TXBUF_SIZE; +- + hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, tx_buff_size, tc); + hw_atl_tpb_tx_buff_hi_threshold_per_tc_set(self, + (tx_buff_size * +@@ -150,13 +166,8 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + (tx_buff_size * + (1024 / 32U) * 50U) / + 100U, tc); +- /* Init TC2 for PTP_TX */ +- hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, HW_ATL_B0_PTP_TXBUF_SIZE, +- AQ_HW_PTP_TC); + + /* QoS Rx buf size per TC */ +- rx_buff_size -= HW_ATL_B0_PTP_RXBUF_SIZE; +- + hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, rx_buff_size, tc); + hw_atl_rpb_rx_buff_hi_threshold_per_tc_set(self, + (rx_buff_size * +@@ -169,11 +180,7 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + + hw_atl_b0_set_fc(self, self->aq_nic_cfg->fc.req, tc); + +- /* Init TC2 for PTP_RX */ +- hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, HW_ATL_B0_PTP_RXBUF_SIZE, +- AQ_HW_PTP_TC); +- /* No flow control for PTP */ +- hw_atl_rpb_rx_xoff_en_per_tc_set(self, 0U, AQ_HW_PTP_TC); ++ hw_atl_b0_tc_ptp_set(self); + + /* QoS 802.1p priority -> TC mapping */ + for (i_priority = 8U; i_priority--;) +-- +2.13.6 + diff --git a/SOURCES/0095-netdrv-net-atlantic-changes-for-multi-TC-support.patch b/SOURCES/0095-netdrv-net-atlantic-changes-for-multi-TC-support.patch new file mode 100644 index 0000000..ad343b5 --- /dev/null +++ b/SOURCES/0095-netdrv-net-atlantic-changes-for-multi-TC-support.patch @@ -0,0 +1,322 @@ +From 9f7130b01ee90802169a86ddd659b5248e9a6009 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:52 -0500 +Subject: [PATCH 095/139] [netdrv] net: atlantic: changes for multi-TC support + +Message-id: <1604687916-15087-96-git-send-email-irusskik@redhat.com> +Patchwork-id: 338517 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 095/139] net: atlantic: changes for multi-TC support +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 0aa7bc3ee4652e0790f9b42c93c769b59b9f2308 +Author: Dmitry Bezrukov +Date: Fri May 22 11:19:39 2020 +0300 + + net: atlantic: changes for multi-TC support + + This patch contains the following changes: + * add cfg->is_ptp (used for PTP enable/disable switch, which + is described in more details below); + * add cfg->tc_mode (A1 supports 2 HW modes only); + * setup queue to TC mapping based on TC mode on A2; + * remove hw_tx_tc_mode_get / hw_rx_tc_mode_get hw_ops. + + In the first generation of our hardware (A1), a whole traffic class is + consumed for PTP handling in FW (FW uses it to send the ptp data and to + send back timestamps). + The 'is_ptp' flag introduced in this patch will be used in to automatically + disable PTP when a conflicting configuration is detected, e.g. when + multiple TCs are enabled. + + Signed-off-by: Dmitry Bezrukov + Co-developed-by: Mark Starovoytov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 10 +++--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 26 +++++++++----- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 2 ++ + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 27 +++++++-------- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 25 ++++---------- + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 40 ++++++++++++++++------ + 6 files changed, 75 insertions(+), 55 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index d63cebceb554..20ec45ec9440 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -18,6 +18,12 @@ + #define AQ_HW_MAC_COUNTER_HZ 312500000ll + #define AQ_HW_PHY_COUNTER_HZ 160000000ll + ++enum aq_tc_mode { ++ AQ_TC_MODE_INVALID = -1, ++ AQ_TC_MODE_8TCS, ++ AQ_TC_MODE_4TCS, ++}; ++ + #define AQ_RX_FIRST_LOC_FVLANID 0U + #define AQ_RX_LAST_LOC_FVLANID 15U + #define AQ_RX_FIRST_LOC_FETHERT 16U +@@ -281,10 +287,6 @@ struct aq_hw_ops { + int (*hw_set_offload)(struct aq_hw_s *self, + struct aq_nic_cfg_s *aq_nic_cfg); + +- int (*hw_tx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode); +- +- int (*hw_rx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode); +- + int (*hw_ring_hwts_rx_fill)(struct aq_hw_s *self, + struct aq_ring_s *aq_ring); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 369f71e8edef..502e4115e2b3 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -88,6 +88,7 @@ void aq_nic_cfg_start(struct aq_nic_s *self) + cfg->is_autoneg = AQ_CFG_IS_AUTONEG_DEF; + + cfg->is_lro = AQ_CFG_IS_LRO_DEF; ++ cfg->is_ptp = true; + + /*descriptors */ + cfg->rxds = min(cfg->aq_hw_caps->rxds_max, AQ_CFG_RXDS_DEF); +@@ -121,6 +122,11 @@ void aq_nic_cfg_start(struct aq_nic_s *self) + cfg->vecs = 1U; + } + ++ if (cfg->vecs <= 4) ++ cfg->tc_mode = AQ_TC_MODE_8TCS; ++ else ++ cfg->tc_mode = AQ_TC_MODE_4TCS; ++ + /* Check if we have enough vectors allocated for + * link status IRQ. If no - we'll know link state from + * slower service task. +@@ -393,17 +399,19 @@ int aq_nic_init(struct aq_nic_s *self) + aq_vec_init(aq_vec, self->aq_hw_ops, self->aq_hw); + } + +- err = aq_ptp_init(self, self->irqvecs - 1); +- if (err < 0) +- goto err_exit; ++ if (aq_nic_get_cfg(self)->is_ptp) { ++ err = aq_ptp_init(self, self->irqvecs - 1); ++ if (err < 0) ++ goto err_exit; + +- err = aq_ptp_ring_alloc(self); +- if (err < 0) +- goto err_exit; ++ err = aq_ptp_ring_alloc(self); ++ if (err < 0) ++ goto err_exit; + +- err = aq_ptp_ring_init(self); +- if (err < 0) +- goto err_exit; ++ err = aq_ptp_ring_init(self); ++ if (err < 0) ++ goto err_exit; ++ } + + netif_carrier_off(self->ndev); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index 26436671c474..e47eec2a42b2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -58,6 +58,8 @@ struct aq_nic_cfg_s { + bool is_polling; + bool is_rss; + bool is_lro; ++ bool is_ptp; ++ enum aq_tc_mode tc_mode; + u32 priv_flags; + u8 tcs; + struct aq_rss_parameters aq_rss; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index 58e8c641e8b3..599ced261b2a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -945,26 +945,29 @@ void aq_ptp_ring_deinit(struct aq_nic_s *aq_nic) + #define PTP_4TC_RING_IDX 16 + #define PTP_HWST_RING_IDX 31 + ++/* Index must be 8 (8 TCs) or 16 (4 TCs). ++ * It depends on Traffic Class mode. ++ */ ++static unsigned int ptp_ring_idx(const enum aq_tc_mode tc_mode) ++{ ++ if (tc_mode == AQ_TC_MODE_8TCS) ++ return PTP_8TC_RING_IDX; ++ ++ return PTP_4TC_RING_IDX; ++} ++ + int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic) + { + struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; + unsigned int tx_ring_idx, rx_ring_idx; + struct aq_ring_s *hwts; +- u32 tx_tc_mode, rx_tc_mode; + struct aq_ring_s *ring; + int err; + + if (!aq_ptp) + return 0; + +- /* Index must to be 8 (8 TCs) or 16 (4 TCs). +- * It depends from Traffic Class mode. +- */ +- aq_nic->aq_hw_ops->hw_tx_tc_mode_get(aq_nic->aq_hw, &tx_tc_mode); +- if (tx_tc_mode == 0) +- tx_ring_idx = PTP_8TC_RING_IDX; +- else +- tx_ring_idx = PTP_4TC_RING_IDX; ++ tx_ring_idx = ptp_ring_idx(aq_nic->aq_nic_cfg.tc_mode); + + ring = aq_ring_tx_alloc(&aq_ptp->ptp_tx, aq_nic, + tx_ring_idx, &aq_nic->aq_nic_cfg); +@@ -973,11 +976,7 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic) + goto err_exit; + } + +- aq_nic->aq_hw_ops->hw_rx_tc_mode_get(aq_nic->aq_hw, &rx_tc_mode); +- if (rx_tc_mode == 0) +- rx_ring_idx = PTP_8TC_RING_IDX; +- else +- rx_ring_idx = PTP_4TC_RING_IDX; ++ rx_ring_idx = ptp_ring_idx(aq_nic->aq_nic_cfg.tc_mode); + + ring = aq_ring_rx_alloc(&aq_ptp->ptp_rx, aq_nic, + rx_ring_idx, &aq_nic->aq_nic_cfg); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 0ff3f6eea022..7caf586ea56c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -131,13 +131,16 @@ static int hw_atl_b0_tc_ptp_set(struct aq_hw_s *self) + + static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + { ++ struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; + u32 tx_buff_size = HW_ATL_B0_TXBUF_MAX; + u32 rx_buff_size = HW_ATL_B0_RXBUF_MAX; + unsigned int i_priority = 0U; + u32 tc = 0U; + +- tx_buff_size -= HW_ATL_B0_PTP_TXBUF_SIZE; +- rx_buff_size -= HW_ATL_B0_PTP_RXBUF_SIZE; ++ if (cfg->is_ptp) { ++ tx_buff_size -= HW_ATL_B0_PTP_TXBUF_SIZE; ++ rx_buff_size -= HW_ATL_B0_PTP_RXBUF_SIZE; ++ } + + /* TPS Descriptor rate init */ + hw_atl_tps_tx_pkt_shed_desc_rate_curr_time_res_set(self, 0x0U); +@@ -180,7 +183,8 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + + hw_atl_b0_set_fc(self, self->aq_nic_cfg->fc.req, tc); + +- hw_atl_b0_tc_ptp_set(self); ++ if (cfg->is_ptp) ++ hw_atl_b0_tc_ptp_set(self); + + /* QoS 802.1p priority -> TC mapping */ + for (i_priority = 8U; i_priority--;) +@@ -1079,18 +1083,6 @@ int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_tx_tc_mode_get(struct aq_hw_s *self, u32 *tc_mode) +-{ +- *tc_mode = hw_atl_tpb_tps_tx_tc_mode_get(self); +- return aq_hw_err_from_flags(self); +-} +- +-static int hw_atl_b0_rx_tc_mode_get(struct aq_hw_s *self, u32 *tc_mode) +-{ +- *tc_mode = hw_atl_rpb_rpf_rx_traf_class_mode_get(self); +- return aq_hw_err_from_flags(self); +-} +- + #define get_ptp_ts_val_u64(self, indx) \ + ((u64)(hw_atl_pcs_ptp_clock_get(self, indx) & 0xffff)) + +@@ -1508,9 +1500,6 @@ const struct aq_hw_ops hw_atl_ops_b0 = { + .hw_get_hw_stats = hw_atl_utils_get_hw_stats, + .hw_get_fw_version = hw_atl_utils_get_fw_version, + +- .hw_tx_tc_mode_get = hw_atl_b0_tx_tc_mode_get, +- .hw_rx_tc_mode_get = hw_atl_b0_rx_tc_mode_get, +- + .hw_ring_hwts_rx_fill = hw_atl_b0_hw_ring_hwts_rx_fill, + .hw_ring_hwts_rx_receive = hw_atl_b0_hw_ring_hwts_rx_receive, + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index ccdb74562270..a14118550882 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -91,16 +91,36 @@ static int hw_atl2_hw_reset(struct aq_hw_s *self) + + static int hw_atl2_hw_queue_to_tc_map_set(struct aq_hw_s *self) + { +- if (!hw_atl_rpb_rpf_rx_traf_class_mode_get(self)) { +- aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(0), 0x11110000); +- aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(8), 0x33332222); +- aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(16), 0x55554444); +- aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(24), 0x77776666); +- } else { +- aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(0), 0x00000000); +- aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(8), 0x11111111); +- aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(16), 0x22222222); +- aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(24), 0x33333333); ++ struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; ++ unsigned int tcs, q_per_tc; ++ unsigned int tc, q; ++ u32 value = 0; ++ ++ switch (cfg->tc_mode) { ++ case AQ_TC_MODE_8TCS: ++ tcs = 8; ++ q_per_tc = 4; ++ break; ++ case AQ_TC_MODE_4TCS: ++ tcs = 4; ++ q_per_tc = 8; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ for (tc = 0; tc != tcs; tc++) { ++ unsigned int tc_q_offset = tc * q_per_tc; ++ ++ for (q = tc_q_offset; q != tc_q_offset + q_per_tc; q++) ++ value |= tc << HW_ATL2_RX_Q_TC_MAP_SHIFT(q); ++ ++ if (HW_ATL2_RX_Q_TC_MAP_ADR(q) != ++ HW_ATL2_RX_Q_TC_MAP_ADR(q - 1)) { ++ aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(q - 1), ++ value); ++ value = 0; ++ } + } + + return aq_hw_err_from_flags(self); +-- +2.13.6 + diff --git a/SOURCES/0096-netdrv-net-atlantic-QoS-implementation-multi-TC-supp.patch b/SOURCES/0096-netdrv-net-atlantic-QoS-implementation-multi-TC-supp.patch new file mode 100644 index 0000000..2f674d3 --- /dev/null +++ b/SOURCES/0096-netdrv-net-atlantic-QoS-implementation-multi-TC-supp.patch @@ -0,0 +1,884 @@ +From 16053b24b373aec7812f1ba4dfb41155b716e32c Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:53 -0500 +Subject: [PATCH 096/139] [netdrv] net: atlantic: QoS implementation: multi-TC + support + +Message-id: <1604687916-15087-97-git-send-email-irusskik@redhat.com> +Patchwork-id: 338519 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 096/139] net: atlantic: QoS implementation: multi-TC support +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit a83fe6b6ad6b10f6912025ae23bd5c2596a4e7f4 +Author: Dmitry Bezrukov +Date: Fri May 22 11:19:40 2020 +0300 + + net: atlantic: QoS implementation: multi-TC support + + This patch adds multi-TC support. + + PTP is automatically disabled when the user enables more than 2 TCs, + otherwise traffic on TC2 won't quite work, because it's reserved for PTP. + + Signed-off-by: Dmitry Bezrukov + Co-developed-by: Dmitry Bogdanov + Signed-off-by: Dmitry Bogdanov + Co-developed-by: Mark Starovoytov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/aq_filters.c | 11 +- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 5 +- + .../net/ethernet/aquantia/atlantic/aq_hw_utils.c | 26 +++++ + .../net/ethernet/aquantia/atlantic/aq_hw_utils.h | 2 + + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 39 ++++++- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 61 ++++++++++- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 14 ++- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 19 +++- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 74 +++++++------ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 9 +- + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 122 ++++++++++++--------- + .../aquantia/atlantic/hw_atl2/hw_atl2_internal.h | 7 -- + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.c | 8 ++ + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.h | 4 + + .../atlantic/hw_atl2/hw_atl2_llh_internal.h | 10 ++ + 15 files changed, 295 insertions(+), 116 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c +index 03ff92bc4a7f..1bc4d33a0ce5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c +@@ -153,6 +153,8 @@ aq_check_approve_fvlan(struct aq_nic_s *aq_nic, + struct aq_hw_rx_fltrs_s *rx_fltrs, + struct ethtool_rx_flow_spec *fsp) + { ++ struct aq_nic_cfg_s *cfg = &aq_nic->aq_nic_cfg; ++ + if (fsp->location < AQ_RX_FIRST_LOC_FVLANID || + fsp->location > AQ_RX_LAST_LOC_FVLANID) { + netdev_err(aq_nic->ndev, +@@ -170,10 +172,10 @@ aq_check_approve_fvlan(struct aq_nic_s *aq_nic, + return -EINVAL; + } + +- if (fsp->ring_cookie > aq_nic->aq_nic_cfg.num_rss_queues) { ++ if (fsp->ring_cookie > cfg->num_rss_queues * cfg->tcs) { + netdev_err(aq_nic->ndev, + "ethtool: queue number must be in range [0, %d]", +- aq_nic->aq_nic_cfg.num_rss_queues - 1); ++ cfg->num_rss_queues * cfg->tcs - 1); + return -EINVAL; + } + return 0; +@@ -262,6 +264,7 @@ static bool __must_check + aq_rule_is_not_correct(struct aq_nic_s *aq_nic, + struct ethtool_rx_flow_spec *fsp) + { ++ struct aq_nic_cfg_s *cfg = &aq_nic->aq_nic_cfg; + bool rule_is_not_correct = false; + + if (!aq_nic) { +@@ -274,11 +277,11 @@ aq_rule_is_not_correct(struct aq_nic_s *aq_nic, + } else if (aq_check_filter(aq_nic, fsp)) { + rule_is_not_correct = true; + } else if (fsp->ring_cookie != RX_CLS_FLOW_DISC) { +- if (fsp->ring_cookie >= aq_nic->aq_nic_cfg.num_rss_queues) { ++ if (fsp->ring_cookie >= cfg->num_rss_queues * cfg->tcs) { + netdev_err(aq_nic->ndev, + "ethtool: The specified action is invalid.\n" + "Maximum allowable value action is %u.\n", +- aq_nic->aq_nic_cfg.num_rss_queues - 1); ++ cfg->num_rss_queues * cfg->tcs - 1); + rule_is_not_correct = true; + } + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index 20ec45ec9440..c82061eb65a1 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -121,11 +121,12 @@ struct aq_stats_s { + #define AQ_HW_MEDIA_TYPE_TP 1U + #define AQ_HW_MEDIA_TYPE_FIBRE 2U + +-#define AQ_HW_MULTICAST_ADDRESS_MAX 32U +- + #define AQ_HW_TXD_MULTIPLE 8U + #define AQ_HW_RXD_MULTIPLE 8U + ++#define AQ_HW_QUEUES_MAX 32U ++#define AQ_HW_MULTICAST_ADDRESS_MAX 32U ++ + #define AQ_HW_PTP_TC 2U + + #define AQ_HW_LED_BLINK 0x2U +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +index 7dbf49adcea6..342c5179f846 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +@@ -79,3 +79,29 @@ int aq_hw_err_from_flags(struct aq_hw_s *hw) + err_exit: + return err; + } ++ ++int aq_hw_num_tcs(struct aq_hw_s *hw) ++{ ++ switch (hw->aq_nic_cfg->tc_mode) { ++ case AQ_TC_MODE_8TCS: ++ return 8; ++ case AQ_TC_MODE_4TCS: ++ return 4; ++ default: ++ break; ++ } ++ ++ return 1; ++} ++ ++int aq_hw_q_per_tc(struct aq_hw_s *hw) ++{ ++ switch (hw->aq_nic_cfg->tc_mode) { ++ case AQ_TC_MODE_8TCS: ++ return 4; ++ case AQ_TC_MODE_4TCS: ++ return 8; ++ default: ++ return 4; ++ } ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +index 9ef82d487e01..32aa5f2fb840 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +@@ -34,5 +34,7 @@ u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value); + u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg); + int aq_hw_err_from_flags(struct aq_hw_s *hw); ++int aq_hw_num_tcs(struct aq_hw_s *hw); ++int aq_hw_q_per_tc(struct aq_hw_s *hw); + + #endif /* AQ_HW_UTILS_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index 9fcab646cbd5..ef9e969fbf7a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -12,11 +12,13 @@ + #include "aq_ethtool.h" + #include "aq_ptp.h" + #include "aq_filters.h" ++#include "aq_hw_utils.h" + + #include + #include + #include + #include ++#include + + MODULE_LICENSE("GPL v2"); + MODULE_AUTHOR(AQ_CFG_DRV_AUTHOR); +@@ -38,7 +40,7 @@ struct net_device *aq_ndev_alloc(void) + struct net_device *ndev = NULL; + struct aq_nic_s *aq_nic = NULL; + +- ndev = alloc_etherdev_mq(sizeof(struct aq_nic_s), AQ_CFG_VECS_MAX); ++ ndev = alloc_etherdev_mq(sizeof(struct aq_nic_s), AQ_HW_QUEUES_MAX); + if (!ndev) + return NULL; + +@@ -330,6 +332,40 @@ static int aq_ndo_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, + return 0; + } + ++static int aq_validate_mqprio_opt(struct aq_nic_s *self, ++ const unsigned int num_tc) ++{ ++ if (num_tc > aq_hw_num_tcs(self->aq_hw)) { ++ netdev_err(self->ndev, "Too many TCs requested\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (num_tc != 0 && !is_power_of_2(num_tc)) { ++ netdev_err(self->ndev, "TC count should be power of 2\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++static int aq_ndo_setup_tc(struct net_device *dev, enum tc_setup_type type, ++ void *type_data) ++{ ++ struct aq_nic_s *aq_nic = netdev_priv(dev); ++ struct tc_mqprio_qopt *mqprio = type_data; ++ int err; ++ ++ if (type != TC_SETUP_QDISC_MQPRIO) ++ return -EOPNOTSUPP; ++ ++ err = aq_validate_mqprio_opt(aq_nic, mqprio->num_tc); ++ if (err) ++ return err; ++ ++ return aq_nic_setup_tc_mqprio(aq_nic, mqprio->num_tc, ++ mqprio->prio_tc_map); ++} ++ + static const struct net_device_ops aq_ndev_ops = { + .ndo_open = aq_ndev_open, + .ndo_stop = aq_ndev_close, +@@ -341,6 +377,7 @@ static const struct net_device_ops aq_ndev_ops = { + .ndo_do_ioctl = aq_ndev_ioctl, + .ndo_vlan_rx_add_vid = aq_ndo_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = aq_ndo_vlan_rx_kill_vid, ++ .ndo_setup_tc = aq_ndo_setup_tc, + }; + + static int __init aq_ndev_init_module(void) +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 502e4115e2b3..4cd6b599f31f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + static unsigned int aq_itr = AQ_CFG_INTERRUPT_MODERATION_AUTO; + module_param_named(aq_itr, aq_itr, uint, 0644); +@@ -67,6 +68,7 @@ static void aq_nic_rss_init(struct aq_nic_s *self, unsigned int num_rss_queues) + void aq_nic_cfg_start(struct aq_nic_s *self) + { + struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; ++ int i; + + cfg->tcs = AQ_CFG_TCS_DEF; + +@@ -141,6 +143,9 @@ void aq_nic_cfg_start(struct aq_nic_s *self) + cfg->is_vlan_rx_strip = !!(cfg->features & NETIF_F_HW_VLAN_CTAG_RX); + cfg->is_vlan_tx_insert = !!(cfg->features & NETIF_F_HW_VLAN_CTAG_TX); + cfg->is_vlan_force_promisc = true; ++ ++ for (i = 0; i < sizeof(cfg->prio_tc_map); i++) ++ cfg->prio_tc_map[i] = cfg->tcs * i / 8; + } + + static int aq_nic_update_link_status(struct aq_nic_s *self) +@@ -501,14 +506,21 @@ int aq_nic_start(struct aq_nic_s *self) + goto err_exit; + } + +- err = netif_set_real_num_tx_queues(self->ndev, self->aq_vecs); ++ err = netif_set_real_num_tx_queues(self->ndev, ++ self->aq_vecs * cfg->tcs); + if (err < 0) + goto err_exit; + +- err = netif_set_real_num_rx_queues(self->ndev, self->aq_vecs); ++ err = netif_set_real_num_rx_queues(self->ndev, ++ self->aq_vecs * cfg->tcs); + if (err < 0) + goto err_exit; + ++ for (i = 0; i < cfg->tcs; i++) { ++ u16 offset = self->aq_vecs * i; ++ ++ netdev_set_tc_queue(self->ndev, i, self->aq_vecs, offset); ++ } + netif_tx_start_all_queues(self->ndev); + + err_exit: +@@ -674,10 +686,10 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) + { + unsigned int vec = skb->queue_mapping % self->aq_nic_cfg.vecs; ++ unsigned int tc = skb->queue_mapping / self->aq_nic_cfg.vecs; + struct aq_ring_s *ring = NULL; + unsigned int frags = 0U; + int err = NETDEV_TX_OK; +- unsigned int tc = 0U; + + frags = skb_shinfo(skb)->nr_frags + 1; + +@@ -696,7 +708,8 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) + } + + /* Above status update may stop the queue. Check this. */ +- if (__netif_subqueue_stopped(self->ndev, ring->idx)) { ++ if (__netif_subqueue_stopped(self->ndev, ++ AQ_NIC_RING2QMAP(self, ring->idx))) { + err = NETDEV_TX_BUSY; + goto err_exit; + } +@@ -1250,3 +1263,43 @@ void aq_nic_release_filter(struct aq_nic_s *self, enum aq_rx_filter_type type, + break; + } + } ++ ++int aq_nic_setup_tc_mqprio(struct aq_nic_s *self, u32 tcs, u8 *prio_tc_map) ++{ ++ struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; ++ bool ndev_running; ++ int err = 0; ++ int i; ++ ++ /* if already the same configuration or ++ * disable request (tcs is 0) and we already is disabled ++ */ ++ if (tcs == cfg->tcs || (tcs == 0 && !cfg->is_qos)) ++ return 0; ++ ++ ndev_running = netif_running(self->ndev); ++ if (ndev_running) ++ dev_close(self->ndev); ++ ++ cfg->tcs = tcs; ++ if (cfg->tcs == 0) ++ cfg->tcs = 1; ++ if (prio_tc_map) ++ memcpy(cfg->prio_tc_map, prio_tc_map, sizeof(cfg->prio_tc_map)); ++ else ++ for (i = 0; i < sizeof(cfg->prio_tc_map); i++) ++ cfg->prio_tc_map[i] = cfg->tcs * i / 8; ++ ++ cfg->is_qos = (tcs != 0 ? true : false); ++ cfg->is_ptp = (cfg->tcs <= AQ_HW_PTP_TC); ++ if (!cfg->is_ptp) ++ netdev_warn(self->ndev, "%s\n", ++ "PTP is auto disabled due to requested TC count."); ++ ++ netdev_set_num_tc(self->ndev, cfg->tcs); ++ ++ if (ndev_running) ++ err = dev_open(self->ndev, NULL); ++ ++ return err; ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index e47eec2a42b2..75e1a4603c49 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -58,10 +58,12 @@ struct aq_nic_cfg_s { + bool is_polling; + bool is_rss; + bool is_lro; ++ bool is_qos; + bool is_ptp; + enum aq_tc_mode tc_mode; + u32 priv_flags; + u8 tcs; ++ u8 prio_tc_map[8]; + struct aq_rss_parameters aq_rss; + u32 eee_speeds; + }; +@@ -78,8 +80,15 @@ struct aq_nic_cfg_s { + #define AQ_NIC_WOL_MODES (WAKE_MAGIC |\ + WAKE_PHY) + ++#define AQ_NIC_RING_PER_TC(_NIC_) \ ++ (((_NIC_)->aq_nic_cfg.tc_mode == AQ_TC_MODE_4TCS) ? 8 : 4) ++ + #define AQ_NIC_TCVEC2RING(_NIC_, _TC_, _VEC_) \ +- ((_TC_) * AQ_CFG_TCS_MAX + (_VEC_)) ++ ((_TC_) * AQ_NIC_RING_PER_TC(_NIC_) + (_VEC_)) ++ ++#define AQ_NIC_RING2QMAP(_NIC_, _ID_) \ ++ ((_ID_) / AQ_NIC_RING_PER_TC(_NIC_) * (_NIC_)->aq_vecs + \ ++ ((_ID_) % AQ_NIC_RING_PER_TC(_NIC_))) + + struct aq_hw_rx_fl2 { + struct aq_rx_filter_vlan aq_vlans[AQ_VLAN_MAX_FILTERS]; +@@ -105,7 +114,7 @@ struct aq_nic_s { + atomic_t flags; + u32 msg_enable; + struct aq_vec_s *aq_vec[AQ_CFG_VECS_MAX]; +- struct aq_ring_s *aq_ring_tx[AQ_CFG_VECS_MAX * AQ_CFG_TCS_MAX]; ++ struct aq_ring_s *aq_ring_tx[AQ_HW_QUEUES_MAX]; + struct aq_hw_s *aq_hw; + struct net_device *ndev; + unsigned int aq_vecs; +@@ -179,4 +188,5 @@ void aq_nic_shutdown(struct aq_nic_s *self); + u8 aq_nic_reserve_filter(struct aq_nic_s *self, enum aq_rx_filter_type type); + void aq_nic_release_filter(struct aq_nic_s *self, enum aq_rx_filter_type type, + u32 location); ++int aq_nic_setup_tc_mqprio(struct aq_nic_s *self, u32 tcs, u8 *prio_tc_map); + #endif /* AQ_NIC_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index bae95a618560..68fdb3994088 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -232,8 +232,11 @@ void aq_ring_queue_wake(struct aq_ring_s *ring) + { + struct net_device *ndev = aq_nic_get_ndev(ring->aq_nic); + +- if (__netif_subqueue_stopped(ndev, ring->idx)) { +- netif_wake_subqueue(ndev, ring->idx); ++ if (__netif_subqueue_stopped(ndev, ++ AQ_NIC_RING2QMAP(ring->aq_nic, ++ ring->idx))) { ++ netif_wake_subqueue(ndev, ++ AQ_NIC_RING2QMAP(ring->aq_nic, ring->idx)); + ring->stats.tx.queue_restarts++; + } + } +@@ -242,8 +245,11 @@ void aq_ring_queue_stop(struct aq_ring_s *ring) + { + struct net_device *ndev = aq_nic_get_ndev(ring->aq_nic); + +- if (!__netif_subqueue_stopped(ndev, ring->idx)) +- netif_stop_subqueue(ndev, ring->idx); ++ if (!__netif_subqueue_stopped(ndev, ++ AQ_NIC_RING2QMAP(ring->aq_nic, ++ ring->idx))) ++ netif_stop_subqueue(ndev, ++ AQ_NIC_RING2QMAP(ring->aq_nic, ring->idx)); + } + + bool aq_ring_tx_clean(struct aq_ring_s *self) +@@ -466,7 +472,10 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + buff->is_hash_l4 ? PKT_HASH_TYPE_L4 : + PKT_HASH_TYPE_NONE); + /* Send all PTP traffic to 0 queue */ +- skb_record_rx_queue(skb, is_ptp_ring ? 0 : self->idx); ++ skb_record_rx_queue(skb, ++ is_ptp_ring ? 0 ++ : AQ_NIC_RING2QMAP(self->aq_nic, ++ self->idx)); + + ++self->stats.rx.packets; + self->stats.rx.bytes += skb->len; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 7caf586ea56c..775382440b47 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -46,7 +46,8 @@ + NETIF_F_HW_VLAN_CTAG_RX | \ + NETIF_F_HW_VLAN_CTAG_TX | \ + NETIF_F_GSO_UDP_L4 | \ +- NETIF_F_GSO_PARTIAL, \ ++ NETIF_F_GSO_PARTIAL | \ ++ NETIF_F_HW_TC, \ + .hw_priv_flags = IFF_UNICAST_FLT, \ + .flow_control = true, \ + .mtu = HW_ATL_B0_MTU_JUMBO, \ +@@ -134,7 +135,7 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; + u32 tx_buff_size = HW_ATL_B0_TXBUF_MAX; + u32 rx_buff_size = HW_ATL_B0_RXBUF_MAX; +- unsigned int i_priority = 0U; ++ unsigned int prio = 0U; + u32 tc = 0U; + + if (cfg->is_ptp) { +@@ -153,42 +154,45 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U); + hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U); + +- /* TX Packet Scheduler Data TC0 */ +- hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF, tc); +- hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0x64, tc); +- hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, tc); +- hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc); +- +- /* Tx buf size TC0 */ +- hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, tx_buff_size, tc); +- hw_atl_tpb_tx_buff_hi_threshold_per_tc_set(self, +- (tx_buff_size * +- (1024 / 32U) * 66U) / +- 100U, tc); +- hw_atl_tpb_tx_buff_lo_threshold_per_tc_set(self, +- (tx_buff_size * +- (1024 / 32U) * 50U) / +- 100U, tc); +- +- /* QoS Rx buf size per TC */ +- hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, rx_buff_size, tc); +- hw_atl_rpb_rx_buff_hi_threshold_per_tc_set(self, +- (rx_buff_size * +- (1024U / 32U) * 66U) / +- 100U, tc); +- hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(self, +- (rx_buff_size * +- (1024U / 32U) * 50U) / +- 100U, tc); +- +- hw_atl_b0_set_fc(self, self->aq_nic_cfg->fc.req, tc); ++ tx_buff_size /= cfg->tcs; ++ rx_buff_size /= cfg->tcs; ++ for (tc = 0; tc < cfg->tcs; tc++) { ++ u32 threshold = 0U; ++ ++ /* TX Packet Scheduler Data TC0 */ ++ hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF, tc); ++ hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0x64, tc); ++ hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, tc); ++ hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc); ++ ++ /* Tx buf size TC0 */ ++ hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, tx_buff_size, tc); ++ ++ threshold = (tx_buff_size * (1024 / 32U) * 66U) / 100U; ++ hw_atl_tpb_tx_buff_hi_threshold_per_tc_set(self, threshold, tc); ++ ++ threshold = (tx_buff_size * (1024 / 32U) * 50U) / 100U; ++ hw_atl_tpb_tx_buff_lo_threshold_per_tc_set(self, threshold, tc); ++ ++ /* QoS Rx buf size per TC */ ++ hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, rx_buff_size, tc); ++ ++ threshold = (rx_buff_size * (1024U / 32U) * 66U) / 100U; ++ hw_atl_rpb_rx_buff_hi_threshold_per_tc_set(self, threshold, tc); ++ ++ threshold = (rx_buff_size * (1024U / 32U) * 50U) / 100U; ++ hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(self, threshold, tc); ++ ++ hw_atl_b0_set_fc(self, self->aq_nic_cfg->fc.req, tc); ++ } + + if (cfg->is_ptp) + hw_atl_b0_tc_ptp_set(self); + + /* QoS 802.1p priority -> TC mapping */ +- for (i_priority = 8U; i_priority--;) +- hw_atl_rpf_rpb_user_priority_tc_map_set(self, i_priority, 0U); ++ for (prio = 0; prio < 8; ++prio) ++ hw_atl_rpf_rpb_user_priority_tc_map_set(self, prio, ++ cfg->prio_tc_map[prio]); + + return aq_hw_err_from_flags(self); + } +@@ -319,7 +323,7 @@ int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, + static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self) + { + /* Tx TC/Queue number config */ +- hw_atl_tpb_tps_tx_tc_mode_set(self, 1U); ++ hw_atl_tpb_tps_tx_tc_mode_set(self, self->aq_nic_cfg->tc_mode); + + hw_atl_thm_lso_tcp_flag_of_first_pkt_set(self, 0x0FF6U); + hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(self, 0x0FF6U); +@@ -345,7 +349,7 @@ static int hw_atl_b0_hw_init_rx_path(struct aq_hw_s *self) + int i; + + /* Rx TC/RSS number config */ +- hw_atl_rpb_rpf_rx_traf_class_mode_set(self, 1U); ++ hw_atl_rpb_rpf_rx_traf_class_mode_set(self, cfg->tc_mode); + + /* Rx flow control */ + hw_atl_rpb_rx_flow_ctl_mode_set(self, 1U); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index 9e2d01a6aac8..8cb6765a1398 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -754,7 +754,7 @@ void hw_atl_rpfl2_accept_all_mc_packets_set(struct aq_hw_s *aq_hw, + } + + void hw_atl_rpf_rpb_user_priority_tc_map_set(struct aq_hw_s *aq_hw, +- u32 user_priority_tc_map, u32 tc) ++ u32 user_priority, u32 tc) + { + /* register address for bitfield rx_tc_up{t}[2:0] */ + static u32 rpf_rpb_rx_tc_upt_adr[8] = { +@@ -773,10 +773,9 @@ void hw_atl_rpf_rpb_user_priority_tc_map_set(struct aq_hw_s *aq_hw, + 0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U + }; + +- aq_hw_write_reg_bit(aq_hw, rpf_rpb_rx_tc_upt_adr[tc], +- rpf_rpb_rx_tc_upt_msk[tc], +- rpf_rpb_rx_tc_upt_shft[tc], +- user_priority_tc_map); ++ aq_hw_write_reg_bit(aq_hw, rpf_rpb_rx_tc_upt_adr[user_priority], ++ rpf_rpb_rx_tc_upt_msk[user_priority], ++ rpf_rpb_rx_tc_upt_shft[user_priority], tc); + } + + void hw_atl_rpf_rss_key_addr_set(struct aq_hw_s *aq_hw, u32 rss_key_addr) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index a14118550882..05c049661b2e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -47,7 +47,8 @@ static int hw_atl2_act_rslvr_table_set(struct aq_hw_s *self, u8 location, + NETIF_F_HW_VLAN_CTAG_RX | \ + NETIF_F_HW_VLAN_CTAG_TX | \ + NETIF_F_GSO_UDP_L4 | \ +- NETIF_F_GSO_PARTIAL, \ ++ NETIF_F_GSO_PARTIAL | \ ++ NETIF_F_HW_TC, \ + .hw_priv_flags = IFF_UNICAST_FLT, \ + .flow_control = true, \ + .mtu = HW_ATL2_MTU_JUMBO, \ +@@ -132,7 +133,6 @@ static int hw_atl2_hw_qos_set(struct aq_hw_s *self) + u32 tx_buff_size = HW_ATL2_TXBUF_MAX; + u32 rx_buff_size = HW_ATL2_RXBUF_MAX; + unsigned int prio = 0U; +- u32 threshold = 0U; + u32 tc = 0U; + + /* TPS Descriptor rate init */ +@@ -146,34 +146,41 @@ static int hw_atl2_hw_qos_set(struct aq_hw_s *self) + hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U); + hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U); + +- /* TX Packet Scheduler Data TC0 */ +- hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF0, tc); +- hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(self, 0x640, tc); +- hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, tc); +- hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc); ++ tx_buff_size /= cfg->tcs; ++ rx_buff_size /= cfg->tcs; ++ for (tc = 0; tc < cfg->tcs; tc++) { ++ u32 threshold = 0U; + +- /* Tx buf size TC0 */ +- hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, tx_buff_size, tc); ++ /* TX Packet Scheduler Data TC0 */ ++ hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF0, ++ tc); ++ hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(self, 0x640, tc); ++ hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, tc); ++ hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc); + +- threshold = (tx_buff_size * (1024 / 32U) * 66U) / 100U; +- hw_atl_tpb_tx_buff_hi_threshold_per_tc_set(self, threshold, tc); ++ /* Tx buf size TC0 */ ++ hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, tx_buff_size, tc); + +- threshold = (tx_buff_size * (1024 / 32U) * 50U) / 100U; +- hw_atl_tpb_tx_buff_lo_threshold_per_tc_set(self, threshold, tc); ++ threshold = (tx_buff_size * (1024 / 32U) * 66U) / 100U; ++ hw_atl_tpb_tx_buff_hi_threshold_per_tc_set(self, threshold, tc); + +- /* QoS Rx buf size per TC */ +- hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, rx_buff_size, tc); ++ threshold = (tx_buff_size * (1024 / 32U) * 50U) / 100U; ++ hw_atl_tpb_tx_buff_lo_threshold_per_tc_set(self, threshold, tc); + +- threshold = (rx_buff_size * (1024U / 32U) * 66U) / 100U; +- hw_atl_rpb_rx_buff_hi_threshold_per_tc_set(self, threshold, tc); ++ /* QoS Rx buf size per TC */ ++ hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, rx_buff_size, tc); + +- threshold = (rx_buff_size * (1024U / 32U) * 50U) / 100U; +- hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(self, threshold, tc); ++ threshold = (rx_buff_size * (1024U / 32U) * 66U) / 100U; ++ hw_atl_rpb_rx_buff_hi_threshold_per_tc_set(self, threshold, tc); ++ ++ threshold = (rx_buff_size * (1024U / 32U) * 50U) / 100U; ++ hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(self, threshold, tc); ++ } + + /* QoS 802.1p priority -> TC mapping */ + for (prio = 0; prio < 8; ++prio) + hw_atl_rpf_rpb_user_priority_tc_map_set(self, prio, +- cfg->tcs * prio / 8); ++ cfg->prio_tc_map[prio]); + + /* ATL2 Apply legacy ring to TC mapping */ + hw_atl2_hw_queue_to_tc_map_set(self); +@@ -184,11 +191,24 @@ static int hw_atl2_hw_qos_set(struct aq_hw_s *self) + static int hw_atl2_hw_rss_set(struct aq_hw_s *self, + struct aq_rss_parameters *rss_params) + { +- u8 *indirection_table = rss_params->indirection_table; ++ u8 *indirection_table = rss_params->indirection_table; ++ const u32 num_tcs = aq_hw_num_tcs(self); ++ u32 rpf_redir2_enable; ++ int tc; + int i; + +- for (i = HW_ATL2_RSS_REDIRECTION_MAX; i--;) +- hw_atl2_new_rpf_rss_redir_set(self, 0, i, indirection_table[i]); ++ rpf_redir2_enable = num_tcs > 4 ? 1 : 0; ++ ++ hw_atl2_rpf_redirection_table2_select_set(self, rpf_redir2_enable); ++ ++ for (i = HW_ATL2_RSS_REDIRECTION_MAX; i--;) { ++ for (tc = 0; tc != num_tcs; tc++) { ++ hw_atl2_new_rpf_rss_redir_set(self, tc, i, ++ tc * ++ aq_hw_q_per_tc(self) + ++ indirection_table[i]); ++ } ++ } + + return aq_hw_err_from_flags(self); + } +@@ -196,7 +216,7 @@ static int hw_atl2_hw_rss_set(struct aq_hw_s *self, + static int hw_atl2_hw_init_tx_path(struct aq_hw_s *self) + { + /* Tx TC/RSS number config */ +- hw_atl_tpb_tps_tx_tc_mode_set(self, 1U); ++ hw_atl_tpb_tps_tx_tc_mode_set(self, self->aq_nic_cfg->tc_mode); + + hw_atl_thm_lso_tcp_flag_of_first_pkt_set(self, 0x0FF6U); + hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(self, 0x0FF6U); +@@ -219,13 +239,29 @@ static int hw_atl2_hw_init_tx_path(struct aq_hw_s *self) + static void hw_atl2_hw_init_new_rx_filters(struct aq_hw_s *self) + { + struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; ++ u8 *prio_tc_map = self->aq_nic_cfg->prio_tc_map; ++ u16 action; + u8 index; ++ int i; + ++ /* Action Resolver Table (ART) is used by RPF to decide which action ++ * to take with a packet based upon input tag and tag mask, where: ++ * - input tag is a combination of 3-bit VLan Prio (PTP) and ++ * 29-bit concatenation of all tags from filter block; ++ * - tag mask is a mask used for matching against input tag. ++ * The input_tag is compared with the all the Requested_tags in the ++ * Record table to find a match. Action field of the selected matched ++ * REC entry is used for further processing. If multiple entries match, ++ * the lowest REC entry, Action field will be selected. ++ */ + hw_atl2_rpf_act_rslvr_section_en_set(self, 0xFFFF); + hw_atl2_rpfl2_uc_flr_tag_set(self, HW_ATL2_RPF_TAG_BASE_UC, + HW_ATL2_MAC_UC); + hw_atl2_rpfl2_bc_flr_tag_set(self, HW_ATL2_RPF_TAG_BASE_UC); + ++ /* FW reserves the beginning of ART, thus all driver entries must ++ * start from the offset specified in FW caps. ++ */ + index = priv->art_base_index + HW_ATL2_RPF_L2_PROMISC_OFF_INDEX; + hw_atl2_act_rslvr_table_set(self, index, 0, + HW_ATL2_RPF_TAG_UC_MASK | +@@ -238,33 +274,17 @@ static void hw_atl2_hw_init_new_rx_filters(struct aq_hw_s *self) + HW_ATL2_RPF_TAG_UNTAG_MASK, + HW_ATL2_ACTION_DROP); + +- index = priv->art_base_index + HW_ATL2_RPF_VLAN_INDEX; +- hw_atl2_act_rslvr_table_set(self, index, HW_ATL2_RPF_TAG_BASE_VLAN, +- HW_ATL2_RPF_TAG_VLAN_MASK, +- HW_ATL2_ACTION_ASSIGN_TC(0)); ++ /* Configure ART to map given VLan Prio (PCP) to the TC index for ++ * RSS redirection table. ++ */ ++ for (i = 0; i < 8; i++) { ++ action = HW_ATL2_ACTION_ASSIGN_TC(prio_tc_map[i]); + +- index = priv->art_base_index + HW_ATL2_RPF_MAC_INDEX; +- hw_atl2_act_rslvr_table_set(self, index, HW_ATL2_RPF_TAG_BASE_UC, +- HW_ATL2_RPF_TAG_UC_MASK, +- HW_ATL2_ACTION_ASSIGN_TC(0)); +- +- index = priv->art_base_index + HW_ATL2_RPF_ALLMC_INDEX; +- hw_atl2_act_rslvr_table_set(self, index, HW_ATL2_RPF_TAG_BASE_ALLMC, +- HW_ATL2_RPF_TAG_ALLMC_MASK, +- HW_ATL2_ACTION_ASSIGN_TC(0)); +- +- index = priv->art_base_index + HW_ATL2_RPF_UNTAG_INDEX; +- hw_atl2_act_rslvr_table_set(self, index, HW_ATL2_RPF_TAG_UNTAG_MASK, +- HW_ATL2_RPF_TAG_UNTAG_MASK, +- HW_ATL2_ACTION_ASSIGN_TC(0)); +- +- index = priv->art_base_index + HW_ATL2_RPF_VLAN_PROMISC_ON_INDEX; +- hw_atl2_act_rslvr_table_set(self, index, 0, HW_ATL2_RPF_TAG_VLAN_MASK, +- HW_ATL2_ACTION_DISABLE); +- +- index = priv->art_base_index + HW_ATL2_RPF_L2_PROMISC_ON_INDEX; +- hw_atl2_act_rslvr_table_set(self, index, 0, HW_ATL2_RPF_TAG_UC_MASK, +- HW_ATL2_ACTION_DISABLE); ++ index = priv->art_base_index + HW_ATL2_RPF_PCP_TO_TC_INDEX + i; ++ hw_atl2_act_rslvr_table_set(self, index, ++ i << HW_ATL2_RPF_TAG_PCP_OFFSET, ++ HW_ATL2_RPF_TAG_PCP_MASK, action); ++ } + } + + static void hw_atl2_hw_new_rx_filter_vlan_promisc(struct aq_hw_s *self, +@@ -327,7 +347,7 @@ static int hw_atl2_hw_init_rx_path(struct aq_hw_s *self) + int i; + + /* Rx TC/RSS number config */ +- hw_atl_rpb_rpf_rx_traf_class_mode_set(self, 1U); ++ hw_atl_rpb_rpf_rx_traf_class_mode_set(self, cfg->tc_mode); + + /* Rx flow control */ + hw_atl_rpb_rx_flow_ctl_mode_set(self, 1U); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +index be0c049ea582..9ac1979a4867 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +@@ -82,13 +82,6 @@ enum HW_ATL2_RPF_ART_INDEX { + HW_ATL2_RPF_VLAN_USER_INDEX = HW_ATL2_RPF_ET_PCP_USER_INDEX + 16, + HW_ATL2_RPF_PCP_TO_TC_INDEX = HW_ATL2_RPF_VLAN_USER_INDEX + + HW_ATL_VLAN_MAX_FILTERS, +- HW_ATL2_RPF_VLAN_INDEX = HW_ATL2_RPF_PCP_TO_TC_INDEX + +- AQ_CFG_TCS_MAX, +- HW_ATL2_RPF_MAC_INDEX, +- HW_ATL2_RPF_ALLMC_INDEX, +- HW_ATL2_RPF_UNTAG_INDEX, +- HW_ATL2_RPF_VLAN_PROMISC_ON_INDEX, +- HW_ATL2_RPF_L2_PROMISC_ON_INDEX, + }; + + #define HW_ATL2_ACTION(ACTION, RSS, INDEX, VALID) \ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +index e779d70fde66..f096d0a6bda9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +@@ -7,6 +7,14 @@ + #include "hw_atl2_llh_internal.h" + #include "aq_hw_utils.h" + ++void hw_atl2_rpf_redirection_table2_select_set(struct aq_hw_s *aq_hw, ++ u32 select) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_ADR, ++ HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_MSK, ++ HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_SHIFT, select); ++} ++ + void hw_atl2_rpf_rss_hash_type_set(struct aq_hw_s *aq_hw, u32 rss_hash_type) + { + aq_hw_write_reg_bit(aq_hw, HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_ADR, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +index 8c6d78a64d42..5c1ae755ffae 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +@@ -15,6 +15,10 @@ void hw_atl2_reg_tx_intr_moder_ctrl_set(struct aq_hw_s *aq_hw, + u32 tx_intr_moderation_ctl, + u32 queue); + ++/* Set Redirection Table 2 Select */ ++void hw_atl2_rpf_redirection_table2_select_set(struct aq_hw_s *aq_hw, ++ u32 select); ++ + /** Set RSS HASH type */ + void hw_atl2_rpf_rss_hash_type_set(struct aq_hw_s *aq_hw, u32 rss_hash_type); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +index cde9e9d2836d..b0ac8cd581d7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +@@ -6,6 +6,16 @@ + #ifndef HW_ATL2_LLH_INTERNAL_H + #define HW_ATL2_LLH_INTERNAL_H + ++/* RX pif_rpf_redir_2_en_i Bitfield Definitions ++ * PORT="pif_rpf_redir_2_en_i" ++ */ ++#define HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_ADR 0x000054C8 ++#define HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_MSK 0x00001000 ++#define HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_MSKN 0xFFFFEFFF ++#define HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_SHIFT 12 ++#define HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_WIDTH 1 ++#define HW_ATL2_RPF_PIF_RPF_REDIR2_ENI_DEFAULT 0x0 ++ + /* RX pif_rpf_rss_hash_type_i Bitfield Definitions + */ + #define HW_ATL2_RPF_PIF_RPF_RSS_HASH_TYPEI_ADR 0x000054C8 +-- +2.13.6 + diff --git a/SOURCES/0097-netdrv-net-atlantic-per-TC-queue-statistics.patch b/SOURCES/0097-netdrv-net-atlantic-per-TC-queue-statistics.patch new file mode 100644 index 0000000..badfcab --- /dev/null +++ b/SOURCES/0097-netdrv-net-atlantic-per-TC-queue-statistics.patch @@ -0,0 +1,249 @@ +From a4477af740ee30edca0c22965bb75d9a59a68e96 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:54 -0500 +Subject: [PATCH 097/139] [netdrv] net: atlantic: per-TC queue statistics + +Message-id: <1604687916-15087-98-git-send-email-irusskik@redhat.com> +Patchwork-id: 338522 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 097/139] net: atlantic: per-TC queue statistics +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 4272ba8b11f88be8daca5e2477bfe110145d559c +Author: Mark Starovoytov +Date: Fri May 22 11:19:41 2020 +0300 + + net: atlantic: per-TC queue statistics + + This patch adds support for per-TC queue statistics. + + By default (single TC), the output is the same as it used to be, e.g.: + Queue[0] InPackets: 2 + Queue[0] OutPackets: 8 + Queue[0] Restarts: 0 + Queue[0] InJumboPackets: 0 + Queue[0] InLroPackets: 0 + Queue[0] InErrors: 0 + + If several TCs are enabled, then each queue statistics line is prefixed + with TC number, e.g.: + TC0 Queue[0] InPackets: 6 + TC0 Queue[0] OutPackets: 11 + Queue numbering is end-to-end, so: + TC1 Queue[4] InPackets: 0 + TC1 Queue[4] OutPackets: 22 + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 49 ++++++++++++++-------- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 12 ++++-- + drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 24 ++++++----- + drivers/net/ethernet/aquantia/atlantic/aq_vec.h | 5 +-- + 4 files changed, 54 insertions(+), 36 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index a0d8f9366e1b..e0d45cda1d11 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -87,13 +87,13 @@ static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = { + "InDroppedDma", + }; + +-static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = { +- "Queue[%d] InPackets", +- "Queue[%d] OutPackets", +- "Queue[%d] Restarts", +- "Queue[%d] InJumboPackets", +- "Queue[%d] InLroPackets", +- "Queue[%d] InErrors", ++static const char * const aq_ethtool_queue_stat_names[] = { ++ "%sQueue[%d] InPackets", ++ "%sQueue[%d] OutPackets", ++ "%sQueue[%d] Restarts", ++ "%sQueue[%d] InJumboPackets", ++ "%sQueue[%d] InLroPackets", ++ "%sQueue[%d] InErrors", + }; + + static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = { +@@ -109,7 +109,8 @@ static u32 aq_ethtool_n_stats(struct net_device *ndev) + struct aq_nic_s *nic = netdev_priv(ndev); + struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic); + u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) + +- ARRAY_SIZE(aq_ethtool_queue_stat_names) * cfg->vecs; ++ ARRAY_SIZE(aq_ethtool_queue_stat_names) * cfg->vecs * ++ cfg->tcs; + + return n_stats; + } +@@ -151,28 +152,40 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev, + static void aq_ethtool_get_strings(struct net_device *ndev, + u32 stringset, u8 *data) + { +- struct aq_nic_s *aq_nic = netdev_priv(ndev); ++ struct aq_nic_s *nic = netdev_priv(ndev); + struct aq_nic_cfg_s *cfg; + u8 *p = data; + int i, si; + +- cfg = aq_nic_get_cfg(aq_nic); ++ cfg = aq_nic_get_cfg(nic); + + switch (stringset) { +- case ETH_SS_STATS: ++ case ETH_SS_STATS: { ++ const int stat_cnt = ARRAY_SIZE(aq_ethtool_queue_stat_names); ++ char tc_string[8]; ++ int tc; ++ ++ memset(tc_string, 0, sizeof(tc_string)); + memcpy(p, aq_ethtool_stat_names, + sizeof(aq_ethtool_stat_names)); + p = p + sizeof(aq_ethtool_stat_names); +- for (i = 0; i < cfg->vecs; i++) { +- for (si = 0; +- si < ARRAY_SIZE(aq_ethtool_queue_stat_names); +- si++) { +- snprintf(p, ETH_GSTRING_LEN, +- aq_ethtool_queue_stat_names[si], i); +- p += ETH_GSTRING_LEN; ++ ++ for (tc = 0; tc < cfg->tcs; tc++) { ++ if (cfg->is_qos) ++ snprintf(tc_string, 8, "TC%d ", tc); ++ ++ for (i = 0; i < cfg->vecs; i++) { ++ for (si = 0; si < stat_cnt; si++) { ++ snprintf(p, ETH_GSTRING_LEN, ++ aq_ethtool_queue_stat_names[si], ++ tc_string, ++ AQ_NIC_TCVEC2RING(nic, tc, i)); ++ p += ETH_GSTRING_LEN; ++ } + } + } + break; ++ } + case ETH_SS_PRIV_FLAGS: + memcpy(p, aq_ethtool_priv_flag_names, + sizeof(aq_ethtool_priv_flag_names)); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 4cd6b599f31f..ab6f42d6f26f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -839,6 +839,7 @@ u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data) + struct aq_stats_s *stats; + unsigned int count = 0U; + unsigned int i = 0U; ++ unsigned int tc; + + if (self->aq_fw_ops->update_stats) { + mutex_lock(&self->fwreq_mutex); +@@ -877,10 +878,13 @@ u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data) + + data += i; + +- for (i = 0U, aq_vec = self->aq_vec[0]; +- aq_vec && self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) { +- data += count; +- aq_vec_get_sw_stats(aq_vec, data, &count); ++ for (tc = 0U; tc < self->aq_nic_cfg.tcs; tc++) { ++ for (i = 0U, aq_vec = self->aq_vec[0]; ++ aq_vec && self->aq_vecs > i; ++ ++i, aq_vec = self->aq_vec[i]) { ++ data += count; ++ aq_vec_get_sw_stats(aq_vec, tc, data, &count); ++ } + } + + data += count; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +index d5650cd6e236..41826c10700f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +@@ -348,16 +348,14 @@ cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self) + return &self->aq_ring_param.affinity_mask; + } + +-void aq_vec_add_stats(struct aq_vec_s *self, +- struct aq_ring_stats_rx_s *stats_rx, +- struct aq_ring_stats_tx_s *stats_tx) ++static void aq_vec_add_stats(struct aq_vec_s *self, ++ const unsigned int tc, ++ struct aq_ring_stats_rx_s *stats_rx, ++ struct aq_ring_stats_tx_s *stats_tx) + { +- struct aq_ring_s *ring = NULL; +- unsigned int r = 0U; ++ struct aq_ring_s *ring = self->ring[tc]; + +- for (r = 0U, ring = self->ring[0]; +- self->tx_rings > r; ++r, ring = self->ring[r]) { +- struct aq_ring_stats_tx_s *tx = &ring[AQ_VEC_TX_ID].stats.tx; ++ if (tc < self->rx_rings) { + struct aq_ring_stats_rx_s *rx = &ring[AQ_VEC_RX_ID].stats.rx; + + stats_rx->packets += rx->packets; +@@ -368,6 +366,10 @@ void aq_vec_add_stats(struct aq_vec_s *self, + stats_rx->pg_losts += rx->pg_losts; + stats_rx->pg_flips += rx->pg_flips; + stats_rx->pg_reuses += rx->pg_reuses; ++ } ++ ++ if (tc < self->tx_rings) { ++ struct aq_ring_stats_tx_s *tx = &ring[AQ_VEC_TX_ID].stats.tx; + + stats_tx->packets += tx->packets; + stats_tx->bytes += tx->bytes; +@@ -376,7 +378,8 @@ void aq_vec_add_stats(struct aq_vec_s *self, + } + } + +-int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data, unsigned int *p_count) ++int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data, ++ unsigned int *p_count) + { + struct aq_ring_stats_rx_s stats_rx; + struct aq_ring_stats_tx_s stats_tx; +@@ -384,7 +387,8 @@ int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data, unsigned int *p_count) + + memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s)); + memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s)); +- aq_vec_add_stats(self, &stats_rx, &stats_tx); ++ ++ aq_vec_add_stats(self, tc, &stats_rx, &stats_tx); + + /* This data should mimic aq_ethtool_queue_stat_names structure + */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.h b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h +index 0ee86b26df8a..541af85e6510 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h +@@ -35,10 +35,7 @@ void aq_vec_ring_free(struct aq_vec_s *self); + int aq_vec_start(struct aq_vec_s *self); + void aq_vec_stop(struct aq_vec_s *self); + cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self); +-int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data, ++int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data, + unsigned int *p_count); +-void aq_vec_add_stats(struct aq_vec_s *self, +- struct aq_ring_stats_rx_s *stats_rx, +- struct aq_ring_stats_tx_s *stats_tx); + + #endif /* AQ_VEC_H */ +-- +2.13.6 + diff --git a/SOURCES/0098-netdrv-net-atlantic-make-TCVEC2RING-accept-nic_cfg.patch b/SOURCES/0098-netdrv-net-atlantic-make-TCVEC2RING-accept-nic_cfg.patch new file mode 100644 index 0000000..bb73de6 --- /dev/null +++ b/SOURCES/0098-netdrv-net-atlantic-make-TCVEC2RING-accept-nic_cfg.patch @@ -0,0 +1,133 @@ +From ec66a49c87cc5c330633d0b0eb8e3aabff214052 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:55 -0500 +Subject: [PATCH 098/139] [netdrv] net: atlantic: make TCVEC2RING accept + nic_cfg + +Message-id: <1604687916-15087-99-git-send-email-irusskik@redhat.com> +Patchwork-id: 338523 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 098/139] net: atlantic: make TCVEC2RING accept nic_cfg +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit b9e989262a3e2e9b795361a7e7978d64851eb98f +Author: Mark Starovoytov +Date: Fri May 22 11:19:42 2020 +0300 + + net: atlantic: make TCVEC2RING accept nic_cfg + + This patch updates TCVEC2RING to accept nic_cfg, which is needed to be able + to use it from hw_atl. + The name is updated to reflect the changes. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 2 +- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 9 +++++---- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 13 +++++++------ + drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 3 ++- + 4 files changed, 15 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index e0d45cda1d11..ff1e254f7471 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -179,7 +179,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev, + snprintf(p, ETH_GSTRING_LEN, + aq_ethtool_queue_stat_names[si], + tc_string, +- AQ_NIC_TCVEC2RING(nic, tc, i)); ++ AQ_NIC_CFG_TCVEC2RING(cfg, tc, i)); + p += ETH_GSTRING_LEN; + } + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index ab6f42d6f26f..b77053c8bd47 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -685,15 +685,16 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb, + + int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) + { +- unsigned int vec = skb->queue_mapping % self->aq_nic_cfg.vecs; +- unsigned int tc = skb->queue_mapping / self->aq_nic_cfg.vecs; ++ struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(self); ++ unsigned int vec = skb->queue_mapping % cfg->vecs; ++ unsigned int tc = skb->queue_mapping / cfg->vecs; + struct aq_ring_s *ring = NULL; + unsigned int frags = 0U; + int err = NETDEV_TX_OK; + + frags = skb_shinfo(skb)->nr_frags + 1; + +- ring = self->aq_ring_tx[AQ_NIC_TCVEC2RING(self, tc, vec)]; ++ ring = self->aq_ring_tx[AQ_NIC_CFG_TCVEC2RING(cfg, tc, vec)]; + + if (frags > AQ_CFG_SKB_FRAGS_MAX) { + dev_kfree_skb_any(skb); +@@ -702,7 +703,7 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) + + aq_ring_update_queue_state(ring); + +- if (self->aq_nic_cfg.priv_flags & BIT(AQ_HW_LOOPBACK_DMA_NET)) { ++ if (cfg->priv_flags & BIT(AQ_HW_LOOPBACK_DMA_NET)) { + err = NETDEV_TX_BUSY; + goto err_exit; + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index 75e1a4603c49..7ab08af8d7ce 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -80,15 +80,16 @@ struct aq_nic_cfg_s { + #define AQ_NIC_WOL_MODES (WAKE_MAGIC |\ + WAKE_PHY) + +-#define AQ_NIC_RING_PER_TC(_NIC_) \ +- (((_NIC_)->aq_nic_cfg.tc_mode == AQ_TC_MODE_4TCS) ? 8 : 4) ++#define AQ_NIC_CFG_RING_PER_TC(_NIC_CFG_) \ ++ (((_NIC_CFG_)->tc_mode == AQ_TC_MODE_4TCS) ? 8 : 4) + +-#define AQ_NIC_TCVEC2RING(_NIC_, _TC_, _VEC_) \ +- ((_TC_) * AQ_NIC_RING_PER_TC(_NIC_) + (_VEC_)) ++#define AQ_NIC_CFG_TCVEC2RING(_NIC_CFG_, _TC_, _VEC_) \ ++ ((_TC_) * AQ_NIC_CFG_RING_PER_TC(_NIC_CFG_) + (_VEC_)) + + #define AQ_NIC_RING2QMAP(_NIC_, _ID_) \ +- ((_ID_) / AQ_NIC_RING_PER_TC(_NIC_) * (_NIC_)->aq_vecs + \ +- ((_ID_) % AQ_NIC_RING_PER_TC(_NIC_))) ++ ((_ID_) / AQ_NIC_CFG_RING_PER_TC(&(_NIC_)->aq_nic_cfg) * \ ++ (_NIC_)->aq_vecs + \ ++ ((_ID_) % AQ_NIC_CFG_RING_PER_TC(&(_NIC_)->aq_nic_cfg))) + + struct aq_hw_rx_fl2 { + struct aq_rx_filter_vlan aq_vlans[AQ_VLAN_MAX_FILTERS]; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +index 41826c10700f..d1d43c8ce400 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +@@ -135,7 +135,8 @@ int aq_vec_ring_alloc(struct aq_vec_s *self, struct aq_nic_s *aq_nic, + int err = 0; + + for (i = 0; i < aq_nic_cfg->tcs; ++i) { +- unsigned int idx_ring = AQ_NIC_TCVEC2RING(aq_nic, i, idx); ++ const unsigned int idx_ring = AQ_NIC_CFG_TCVEC2RING(aq_nic_cfg, ++ i, idx); + + ring = aq_ring_tx_alloc(&self->ring[i][AQ_VEC_TX_ID], aq_nic, + idx_ring, aq_nic_cfg); +-- +2.13.6 + diff --git a/SOURCES/0099-netdrv-net-atlantic-QoS-implementation-max_rate.patch b/SOURCES/0099-netdrv-net-atlantic-QoS-implementation-max_rate.patch new file mode 100644 index 0000000..42a9d6b --- /dev/null +++ b/SOURCES/0099-netdrv-net-atlantic-QoS-implementation-max_rate.patch @@ -0,0 +1,491 @@ +From 2d0d470b050300924657a40aeac2a98ba4b75cd9 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:56 -0500 +Subject: [PATCH 099/139] [netdrv] net: atlantic: QoS implementation: max_rate + +Message-id: <1604687916-15087-100-git-send-email-irusskik@redhat.com> +Patchwork-id: 338525 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 099/139] net: atlantic: QoS implementation: max_rate +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 7327699f35f8e90b32c03080b5cba4e9aa95e087 +Author: Mark Starovoytov +Date: Fri May 22 11:19:43 2020 +0300 + + net: atlantic: QoS implementation: max_rate + + This patch adds initial support for mqprio rate limiters (max_rate only). + + Atlantic HW supports Rate-Shaping for time-sensitive traffic at per + Traffic Class (TC) granularity. + Target rate is defined by: + * nominal link rate (always 10G); + * rate factor (ratio between nominal rate and max allowed). + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 3 + + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 30 ++++++++-- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 20 +++++++ + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 3 + + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 58 ++++++++++++++++-- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h | 2 + + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 36 +++++++++++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 16 +++++ + .../aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 70 ++++++++++++++++++++++ + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 9 +-- + 10 files changed, 235 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index c82061eb65a1..0c258726af8c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -35,6 +35,9 @@ enum aq_tc_mode { + (AQ_RX_LAST_LOC_FVLANID - AQ_RX_FIRST_LOC_FVLANID + 1U) + #define AQ_RX_QUEUE_NOT_ASSIGNED 0xFFU + ++/* Used for rate to Mbps conversion */ ++#define AQ_MBPS_DIVISOR 125000 /* 1000000 / 8 */ ++ + /* NIC H/W capabilities */ + struct aq_hw_caps_s { + u64 hw_features; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index ef9e969fbf7a..d8817047f4ef 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -333,8 +333,12 @@ static int aq_ndo_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, + } + + static int aq_validate_mqprio_opt(struct aq_nic_s *self, ++ struct tc_mqprio_qopt_offload *mqprio, + const unsigned int num_tc) + { ++ const bool has_min_rate = !!(mqprio->flags & TC_MQPRIO_F_MIN_RATE); ++ int i; ++ + if (num_tc > aq_hw_num_tcs(self->aq_hw)) { + netdev_err(self->ndev, "Too many TCs requested\n"); + return -EOPNOTSUPP; +@@ -345,25 +349,43 @@ static int aq_validate_mqprio_opt(struct aq_nic_s *self, + return -EOPNOTSUPP; + } + ++ for (i = 0; i < num_tc; i++) { ++ if (has_min_rate && mqprio->min_rate[i]) { ++ netdev_err(self->ndev, ++ "Min tx rate is not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ } ++ + return 0; + } + + static int aq_ndo_setup_tc(struct net_device *dev, enum tc_setup_type type, + void *type_data) + { ++ struct tc_mqprio_qopt_offload *mqprio = type_data; + struct aq_nic_s *aq_nic = netdev_priv(dev); +- struct tc_mqprio_qopt *mqprio = type_data; + int err; ++ int i; + + if (type != TC_SETUP_QDISC_MQPRIO) + return -EOPNOTSUPP; + +- err = aq_validate_mqprio_opt(aq_nic, mqprio->num_tc); ++ err = aq_validate_mqprio_opt(aq_nic, mqprio, mqprio->qopt.num_tc); + if (err) + return err; + +- return aq_nic_setup_tc_mqprio(aq_nic, mqprio->num_tc, +- mqprio->prio_tc_map); ++ if (mqprio->flags & TC_MQPRIO_F_MAX_RATE) { ++ for (i = 0; i < mqprio->qopt.num_tc; i++) { ++ u64 max_rate = mqprio->max_rate[i]; ++ ++ do_div(max_rate, AQ_MBPS_DIVISOR); ++ aq_nic_setup_tc_max_rate(aq_nic, i, (u32)max_rate); ++ } ++ } ++ ++ return aq_nic_setup_tc_mqprio(aq_nic, mqprio->qopt.num_tc, ++ mqprio->qopt.prio_tc_map); + } + + static const struct net_device_ops aq_ndev_ops = { +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index b77053c8bd47..121e8d8875c8 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -1308,3 +1308,23 @@ int aq_nic_setup_tc_mqprio(struct aq_nic_s *self, u32 tcs, u8 *prio_tc_map) + + return err; + } ++ ++int aq_nic_setup_tc_max_rate(struct aq_nic_s *self, const unsigned int tc, ++ const u32 max_rate) ++{ ++ struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; ++ ++ if (tc >= AQ_CFG_TCS_MAX) ++ return -EINVAL; ++ ++ if (max_rate && max_rate < 10) { ++ netdev_warn(self->ndev, ++ "Setting %s to the minimum usable value of %dMbps.\n", ++ "max rate", 10); ++ cfg->tc_max_rate[tc] = 10; ++ } else { ++ cfg->tc_max_rate[tc] = max_rate; ++ } ++ ++ return 0; ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index 7ab08af8d7ce..7dd2530453da 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -64,6 +64,7 @@ struct aq_nic_cfg_s { + u32 priv_flags; + u8 tcs; + u8 prio_tc_map[8]; ++ u32 tc_max_rate[AQ_CFG_TCS_MAX]; + struct aq_rss_parameters aq_rss; + u32 eee_speeds; + }; +@@ -190,4 +191,6 @@ u8 aq_nic_reserve_filter(struct aq_nic_s *self, enum aq_rx_filter_type type); + void aq_nic_release_filter(struct aq_nic_s *self, enum aq_rx_filter_type type, + u32 location); + int aq_nic_setup_tc_mqprio(struct aq_nic_s *self, u32 tcs, u8 *prio_tc_map); ++int aq_nic_setup_tc_max_rate(struct aq_nic_s *self, const unsigned int tc, ++ const u32 max_rate); + #endif /* AQ_NIC_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 775382440b47..abc86eb4f525 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -138,6 +138,8 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + unsigned int prio = 0U; + u32 tc = 0U; + ++ hw_atl_b0_hw_init_tx_tc_rate_limit(self); ++ + if (cfg->is_ptp) { + tx_buff_size -= HW_ATL_B0_PTP_TXBUF_SIZE; + rx_buff_size -= HW_ATL_B0_PTP_RXBUF_SIZE; +@@ -151,7 +153,6 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + hw_atl_tps_tx_pkt_shed_desc_vm_arb_mode_set(self, 0U); + + /* TPS TC credits init */ +- hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U); + hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U); + + tx_buff_size /= cfg->tcs; +@@ -162,8 +163,6 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + /* TX Packet Scheduler Data TC0 */ + hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF, tc); + hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0x64, tc); +- hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, tc); +- hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc); + + /* Tx buf size TC0 */ + hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, tx_buff_size, tc); +@@ -320,10 +319,61 @@ int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, + return aq_hw_err_from_flags(self); + } + ++int hw_atl_b0_hw_init_tx_tc_rate_limit(struct aq_hw_s *self) ++{ ++ /* Scale factor is based on the number of bits in fractional portion */ ++ static const u32 scale = BIT(HW_ATL_TPS_DESC_RATE_Y_WIDTH); ++ static const u32 frac_msk = HW_ATL_TPS_DESC_RATE_Y_MSK >> ++ HW_ATL_TPS_DESC_RATE_Y_SHIFT; ++ struct aq_nic_cfg_s *nic_cfg = self->aq_nic_cfg; ++ int tc; ++ ++ hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U); ++ hw_atl_tps_tx_desc_rate_mode_set(self, nic_cfg->is_qos ? 1U : 0U); ++ for (tc = 0; tc != nic_cfg->tcs; tc++) { ++ const u32 en = (nic_cfg->tc_max_rate[tc] != 0) ? 1U : 0U; ++ const u32 desc = AQ_NIC_CFG_TCVEC2RING(nic_cfg, tc, 0); ++ ++ hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, tc); ++ hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc); ++ ++ hw_atl_tps_tx_desc_rate_en_set(self, desc, en); ++ ++ if (en) { ++ /* Nominal rate is always 10G */ ++ const u32 rate = 10000U * scale / ++ nic_cfg->tc_max_rate[tc]; ++ const u32 rate_int = rate >> ++ HW_ATL_TPS_DESC_RATE_Y_WIDTH; ++ const u32 rate_frac = rate & frac_msk; ++ ++ hw_atl_tps_tx_desc_rate_x_set(self, desc, rate_int); ++ hw_atl_tps_tx_desc_rate_y_set(self, desc, rate_frac); ++ } else { ++ /* A value of 1 indicates the queue is not ++ * rate controlled. ++ */ ++ hw_atl_tps_tx_desc_rate_x_set(self, desc, 1U); ++ hw_atl_tps_tx_desc_rate_y_set(self, desc, 0U); ++ } ++ } ++ for (tc = nic_cfg->tcs; tc != AQ_CFG_TCS_MAX; tc++) { ++ const u32 desc = AQ_NIC_CFG_TCVEC2RING(nic_cfg, tc, 0); ++ ++ hw_atl_tps_tx_desc_rate_en_set(self, desc, 0U); ++ hw_atl_tps_tx_desc_rate_x_set(self, desc, 1U); ++ hw_atl_tps_tx_desc_rate_y_set(self, desc, 0U); ++ } ++ ++ return aq_hw_err_from_flags(self); ++} ++ + static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self) + { ++ struct aq_nic_cfg_s *nic_cfg = self->aq_nic_cfg; ++ + /* Tx TC/Queue number config */ +- hw_atl_tpb_tps_tx_tc_mode_set(self, self->aq_nic_cfg->tc_mode); ++ hw_atl_tpb_tps_tx_tc_mode_set(self, nic_cfg->tc_mode); + + hw_atl_thm_lso_tcp_flag_of_first_pkt_set(self, 0x0FF6U); + hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(self, 0x0FF6U); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +index b855459272ca..992ee4ed37cc 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +@@ -62,6 +62,8 @@ int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr); + + int hw_atl_b0_hw_start(struct aq_hw_s *self); + ++int hw_atl_b0_hw_init_tx_tc_rate_limit(struct aq_hw_s *self); ++ + int hw_atl_b0_hw_irq_enable(struct aq_hw_s *self, u64 mask); + int hw_atl_b0_hw_irq_disable(struct aq_hw_s *self, u64 mask); + int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index 8cb6765a1398..0ea791a9c100 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -1511,6 +1511,42 @@ void hw_atl_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw, + tx_pkt_shed_tc_data_weight); + } + ++void hw_atl_tps_tx_desc_rate_mode_set(struct aq_hw_s *aq_hw, ++ const u32 rate_mode) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL_TPS_TX_DESC_RATE_MODE_ADR, ++ HW_ATL_TPS_TX_DESC_RATE_MODE_MSK, ++ HW_ATL_TPS_TX_DESC_RATE_MODE_SHIFT, ++ rate_mode); ++} ++ ++void hw_atl_tps_tx_desc_rate_en_set(struct aq_hw_s *aq_hw, const u32 desc, ++ const u32 enable) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL_TPS_DESC_RATE_EN_ADR(desc), ++ HW_ATL_TPS_DESC_RATE_EN_MSK, ++ HW_ATL_TPS_DESC_RATE_EN_SHIFT, ++ enable); ++} ++ ++void hw_atl_tps_tx_desc_rate_x_set(struct aq_hw_s *aq_hw, const u32 desc, ++ const u32 rate_int) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL_TPS_DESC_RATE_X_ADR(desc), ++ HW_ATL_TPS_DESC_RATE_X_MSK, ++ HW_ATL_TPS_DESC_RATE_X_SHIFT, ++ rate_int); ++} ++ ++void hw_atl_tps_tx_desc_rate_y_set(struct aq_hw_s *aq_hw, const u32 desc, ++ const u32 rate_frac) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL_TPS_DESC_RATE_Y_ADR(desc), ++ HW_ATL_TPS_DESC_RATE_Y_MSK, ++ HW_ATL_TPS_DESC_RATE_Y_SHIFT, ++ rate_frac); ++} ++ + /* tx */ + void hw_atl_tx_tx_reg_res_dis_set(struct aq_hw_s *aq_hw, u32 tx_reg_res_dis) + { +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index b88cb84805d5..c56cc4e8e13c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -710,6 +710,22 @@ void hw_atl_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw, + u32 tx_pkt_shed_tc_data_weight, + u32 tc); + ++/* set tx descriptor rate mode */ ++void hw_atl_tps_tx_desc_rate_mode_set(struct aq_hw_s *aq_hw, ++ const u32 rate_mode); ++ ++/* set tx packet scheduler descriptor rate enable */ ++void hw_atl_tps_tx_desc_rate_en_set(struct aq_hw_s *aq_hw, const u32 desc, ++ const u32 enable); ++ ++/* set tx packet scheduler descriptor rate integral value */ ++void hw_atl_tps_tx_desc_rate_x_set(struct aq_hw_s *aq_hw, const u32 desc, ++ const u32 rate_int); ++ ++/* set tx packet scheduler descriptor rate fractional value */ ++void hw_atl_tps_tx_desc_rate_y_set(struct aq_hw_s *aq_hw, const u32 desc, ++ const u32 rate_frac); ++ + /* tx */ + + /* set tx register reset disable */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +index 5d86ffab4ece..06220792daf1 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +@@ -2056,6 +2056,24 @@ + /* default value of bitfield tx_tc_mode */ + #define HW_ATL_TPB_TX_TC_MODE_DEFAULT 0x0 + ++/* tx tx_desc_rate_mode bitfield definitions ++ * preprocessor definitions for the bitfield "tx_desc_rate_mode". ++ * port="pif_tps_desc_rate_mode_i" ++ */ ++ ++/* register address for bitfield tx_desc_rate_mode */ ++#define HW_ATL_TPS_TX_DESC_RATE_MODE_ADR 0x00007900 ++/* bitmask for bitfield tx_desc_rate_mode */ ++#define HW_ATL_TPS_TX_DESC_RATE_MODE_MSK 0x00000080 ++/* inverted bitmask for bitfield tx_desc_rate_mode */ ++#define HW_ATL_TPS_TX_DESC_RATE_MODE_MSKN 0xFFFFFF7F ++/* lower bit position of bitfield tx_desc_rate_mode */ ++#define HW_ATL_TPS_TX_DESC_RATE_MODE_SHIFT 7 ++/* width of bitfield tx_desc_rate_mode */ ++#define HW_ATL_TPS_TX_DESC_RATE_MODE_WIDTH 1 ++/* default value of bitfield tx_desc_rate_mode */ ++#define HW_ATL_TPS_TX_DESC_RATE_MODE_DEFAULT 0x0 ++ + /* tx tx_buf_en bitfield definitions + * preprocessor definitions for the bitfield "tx_buf_en". + * port="pif_tpb_tx_buf_en_i" +@@ -2275,6 +2293,58 @@ + /* default value of bitfield data_tc_arb_mode */ + #define HW_ATL_TPS_DATA_TC_ARB_MODE_DEFAULT 0x0 + ++/* tx desc{r}_rate_en bitfield definitions ++ * preprocessor definitions for the bitfield "desc{r}_rate_en". ++ * port="pif_tps_desc_rate_en_i[0]" ++ */ ++ ++/* register address for bitfield desc{r}_rate_en */ ++#define HW_ATL_TPS_DESC_RATE_EN_ADR(desc) (0x00007408 + (desc) * 0x10) ++/* bitmask for bitfield desc{r}_rate_en */ ++#define HW_ATL_TPS_DESC_RATE_EN_MSK 0x80000000 ++/* inverted bitmask for bitfield desc{r}_rate_en */ ++#define HW_ATL_TPS_DESC_RATE_EN_MSKN 0x7FFFFFFF ++/* lower bit position of bitfield desc{r}_rate_en */ ++#define HW_ATL_TPS_DESC_RATE_EN_SHIFT 31 ++/* width of bitfield desc{r}_rate_en */ ++#define HW_ATL_TPS_DESC_RATE_EN_WIDTH 1 ++/* default value of bitfield desc{r}_rate_en */ ++#define HW_ATL_TPS_DESC_RATE_EN_DEFAULT 0x0 ++ ++/* tx desc{r}_rate_x bitfield definitions ++ * preprocessor definitions for the bitfield "desc{r}_rate_x". ++ * port="pif_tps_desc0_rate_x" ++ */ ++/* register address for bitfield desc{r}_rate_x */ ++#define HW_ATL_TPS_DESC_RATE_X_ADR(desc) (0x00007408 + (desc) * 0x10) ++/* bitmask for bitfield desc{r}_rate_x */ ++#define HW_ATL_TPS_DESC_RATE_X_MSK 0x03FF0000 ++/* inverted bitmask for bitfield desc{r}_rate_x */ ++#define HW_ATL_TPS_DESC_RATE_X_MSKN 0xFC00FFFF ++/* lower bit position of bitfield desc{r}_rate_x */ ++#define HW_ATL_TPS_DESC_RATE_X_SHIFT 16 ++/* width of bitfield desc{r}_rate_x */ ++#define HW_ATL_TPS_DESC_RATE_X_WIDTH 10 ++/* default value of bitfield desc{r}_rate_x */ ++#define HW_ATL_TPS_DESC_RATE_X_DEFAULT 0x0 ++ ++/* tx desc{r}_rate_y bitfield definitions ++ * preprocessor definitions for the bitfield "desc{r}_rate_y". ++ * port="pif_tps_desc0_rate_y" ++ */ ++/* register address for bitfield desc{r}_rate_y */ ++#define HW_ATL_TPS_DESC_RATE_Y_ADR(desc) (0x00007408 + (desc) * 0x10) ++/* bitmask for bitfield desc{r}_rate_y */ ++#define HW_ATL_TPS_DESC_RATE_Y_MSK 0x00003FFF ++/* inverted bitmask for bitfield desc{r}_rate_y */ ++#define HW_ATL_TPS_DESC_RATE_Y_MSKN 0xFFFFC000 ++/* lower bit position of bitfield desc{r}_rate_y */ ++#define HW_ATL_TPS_DESC_RATE_Y_SHIFT 0 ++/* width of bitfield desc{r}_rate_y */ ++#define HW_ATL_TPS_DESC_RATE_Y_WIDTH 14 ++/* default value of bitfield desc{r}_rate_y */ ++#define HW_ATL_TPS_DESC_RATE_Y_DEFAULT 0x0 ++ + /* tx desc_rate_ta_rst bitfield definitions + * preprocessor definitions for the bitfield "desc_rate_ta_rst". + * port="pif_tps_desc_rate_ta_rst_i" +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index 05c049661b2e..b42ff81adfeb 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -135,6 +135,8 @@ static int hw_atl2_hw_qos_set(struct aq_hw_s *self) + unsigned int prio = 0U; + u32 tc = 0U; + ++ hw_atl_b0_hw_init_tx_tc_rate_limit(self); ++ + /* TPS Descriptor rate init */ + hw_atl_tps_tx_pkt_shed_desc_rate_curr_time_res_set(self, 0x0U); + hw_atl_tps_tx_pkt_shed_desc_rate_lim_set(self, 0xA); +@@ -143,7 +145,6 @@ static int hw_atl2_hw_qos_set(struct aq_hw_s *self) + hw_atl_tps_tx_pkt_shed_desc_vm_arb_mode_set(self, 0U); + + /* TPS TC credits init */ +- hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U); + hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U); + + tx_buff_size /= cfg->tcs; +@@ -155,8 +156,6 @@ static int hw_atl2_hw_qos_set(struct aq_hw_s *self) + hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF0, + tc); + hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(self, 0x640, tc); +- hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, tc); +- hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc); + + /* Tx buf size TC0 */ + hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, tx_buff_size, tc); +@@ -215,8 +214,10 @@ static int hw_atl2_hw_rss_set(struct aq_hw_s *self, + + static int hw_atl2_hw_init_tx_path(struct aq_hw_s *self) + { ++ struct aq_nic_cfg_s *nic_cfg = self->aq_nic_cfg; ++ + /* Tx TC/RSS number config */ +- hw_atl_tpb_tps_tx_tc_mode_set(self, self->aq_nic_cfg->tc_mode); ++ hw_atl_tpb_tps_tx_tc_mode_set(self, nic_cfg->tc_mode); + + hw_atl_thm_lso_tcp_flag_of_first_pkt_set(self, 0x0FF6U); + hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(self, 0x0FF6U); +-- +2.13.6 + diff --git a/SOURCES/0100-netdrv-net-atlantic-automatically-downgrade-the-numb.patch b/SOURCES/0100-netdrv-net-atlantic-automatically-downgrade-the-numb.patch new file mode 100644 index 0000000..c52587e --- /dev/null +++ b/SOURCES/0100-netdrv-net-atlantic-automatically-downgrade-the-numb.patch @@ -0,0 +1,250 @@ +From 544f90bf8327f6898b8e3cfd648b101b48d58189 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:57 -0500 +Subject: [PATCH 100/139] [netdrv] net: atlantic: automatically downgrade the + number of queues if necessary + +Message-id: <1604687916-15087-101-git-send-email-irusskik@redhat.com> +Patchwork-id: 338531 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 100/139] net: atlantic: automatically downgrade the number of queues if necessary +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 14ef766b13822001087d468aa41f22caa2a42022 +Author: Mark Starovoytov +Date: Fri May 22 11:19:44 2020 +0300 + + net: atlantic: automatically downgrade the number of queues if necessary + + This patch adds support for automatic queue number downgrade. + + On A2: this is a must have, because only TC0/TC1 support more than 4Q. + Other TCs support 4Qs maximum. + Thus, on A2 we must downgrade the number of queues per TC to 4, if more + than 2 TCs are requested. + + On A1: this allows using 8TCs even on systems with cpu count >= 8, when + we have 8 queues by default. + We will just automatically switch to 8TCx4Q mode in this case. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 15 ++--- + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 5 +- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 78 +++++++++++++++------- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 1 + + 4 files changed, 63 insertions(+), 36 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index ff1e254f7471..59e7b326cfda 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -664,8 +664,6 @@ static int aq_set_ringparam(struct net_device *ndev, + dev_close(ndev); + } + +- aq_nic_free_vectors(aq_nic); +- + cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min); + cfg->rxds = min(cfg->rxds, hw_caps->rxds_max); + cfg->rxds = ALIGN(cfg->rxds, AQ_HW_RXD_MULTIPLE); +@@ -674,15 +672,10 @@ static int aq_set_ringparam(struct net_device *ndev, + cfg->txds = min(cfg->txds, hw_caps->txds_max); + cfg->txds = ALIGN(cfg->txds, AQ_HW_TXD_MULTIPLE); + +- for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < cfg->vecs; +- aq_nic->aq_vecs++) { +- aq_nic->aq_vec[aq_nic->aq_vecs] = +- aq_vec_alloc(aq_nic, aq_nic->aq_vecs, cfg); +- if (unlikely(!aq_nic->aq_vec[aq_nic->aq_vecs])) { +- err = -ENOMEM; +- goto err_exit; +- } +- } ++ err = aq_nic_realloc_vectors(aq_nic); ++ if (err) ++ goto err_exit; ++ + if (ndev_running) + err = dev_open(ndev, NULL); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index d8817047f4ef..57a116ccad55 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -337,9 +337,12 @@ static int aq_validate_mqprio_opt(struct aq_nic_s *self, + const unsigned int num_tc) + { + const bool has_min_rate = !!(mqprio->flags & TC_MQPRIO_F_MIN_RATE); ++ struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(self); ++ const unsigned int tcs_max = min_t(u8, aq_nic_cfg->aq_hw_caps->tcs_max, ++ AQ_CFG_TCS_MAX); + int i; + +- if (num_tc > aq_hw_num_tcs(self->aq_hw)) { ++ if (num_tc > tcs_max) { + netdev_err(self->ndev, "Too many TCs requested\n"); + return -EOPNOTSUPP; + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 121e8d8875c8..4ed370777411 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -64,6 +64,33 @@ static void aq_nic_rss_init(struct aq_nic_s *self, unsigned int num_rss_queues) + rss_params->indirection_table[i] = i & (num_rss_queues - 1); + } + ++/* Recalculate the number of vectors */ ++static void aq_nic_cfg_update_num_vecs(struct aq_nic_s *self) ++{ ++ struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; ++ ++ cfg->vecs = min(cfg->aq_hw_caps->vecs, AQ_CFG_VECS_DEF); ++ cfg->vecs = min(cfg->vecs, num_online_cpus()); ++ if (self->irqvecs > AQ_HW_SERVICE_IRQS) ++ cfg->vecs = min(cfg->vecs, self->irqvecs - AQ_HW_SERVICE_IRQS); ++ /* cfg->vecs should be power of 2 for RSS */ ++ cfg->vecs = rounddown_pow_of_two(cfg->vecs); ++ ++ if (ATL_HW_IS_CHIP_FEATURE(self->aq_hw, ANTIGUA)) { ++ if (cfg->tcs > 2) ++ cfg->vecs = min(cfg->vecs, 4U); ++ } ++ ++ if (cfg->vecs <= 4) ++ cfg->tc_mode = AQ_TC_MODE_8TCS; ++ else ++ cfg->tc_mode = AQ_TC_MODE_4TCS; ++ ++ /*rss rings */ ++ cfg->num_rss_queues = min(cfg->vecs, AQ_CFG_NUM_RSS_QUEUES_DEF); ++ aq_nic_rss_init(self, cfg->num_rss_queues); ++} ++ + /* Checks hw_caps and 'corrects' aq_nic_cfg in runtime */ + void aq_nic_cfg_start(struct aq_nic_s *self) + { +@@ -80,7 +107,6 @@ void aq_nic_cfg_start(struct aq_nic_s *self) + + cfg->rxpageorder = AQ_CFG_RX_PAGEORDER; + cfg->is_rss = AQ_CFG_IS_RSS_DEF; +- cfg->num_rss_queues = AQ_CFG_NUM_RSS_QUEUES_DEF; + cfg->aq_rss.base_cpu_number = AQ_CFG_RSS_BASE_CPU_NUM_DEF; + cfg->fc.req = AQ_CFG_FC_MODE; + cfg->wol = AQ_CFG_WOL_MODES; +@@ -96,24 +122,7 @@ void aq_nic_cfg_start(struct aq_nic_s *self) + cfg->rxds = min(cfg->aq_hw_caps->rxds_max, AQ_CFG_RXDS_DEF); + cfg->txds = min(cfg->aq_hw_caps->txds_max, AQ_CFG_TXDS_DEF); + +- /*rss rings */ +- cfg->vecs = min(cfg->aq_hw_caps->vecs, AQ_CFG_VECS_DEF); +- cfg->vecs = min(cfg->vecs, num_online_cpus()); +- if (self->irqvecs > AQ_HW_SERVICE_IRQS) +- cfg->vecs = min(cfg->vecs, self->irqvecs - AQ_HW_SERVICE_IRQS); +- /* cfg->vecs should be power of 2 for RSS */ +- if (cfg->vecs >= 8U) +- cfg->vecs = 8U; +- else if (cfg->vecs >= 4U) +- cfg->vecs = 4U; +- else if (cfg->vecs >= 2U) +- cfg->vecs = 2U; +- else +- cfg->vecs = 1U; +- +- cfg->num_rss_queues = min(cfg->vecs, AQ_CFG_NUM_RSS_QUEUES_DEF); +- +- aq_nic_rss_init(self, cfg->num_rss_queues); ++ aq_nic_cfg_update_num_vecs(self); + + cfg->irq_type = aq_pci_func_get_irq_type(self); + +@@ -124,11 +133,6 @@ void aq_nic_cfg_start(struct aq_nic_s *self) + cfg->vecs = 1U; + } + +- if (cfg->vecs <= 4) +- cfg->tc_mode = AQ_TC_MODE_8TCS; +- else +- cfg->tc_mode = AQ_TC_MODE_4TCS; +- + /* Check if we have enough vectors allocated for + * link status IRQ. If no - we'll know link state from + * slower service task. +@@ -1203,6 +1207,22 @@ void aq_nic_free_vectors(struct aq_nic_s *self) + err_exit:; + } + ++int aq_nic_realloc_vectors(struct aq_nic_s *self) ++{ ++ struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(self); ++ ++ aq_nic_free_vectors(self); ++ ++ for (self->aq_vecs = 0; self->aq_vecs < cfg->vecs; self->aq_vecs++) { ++ self->aq_vec[self->aq_vecs] = aq_vec_alloc(self, self->aq_vecs, ++ cfg); ++ if (unlikely(!self->aq_vec[self->aq_vecs])) ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ + void aq_nic_shutdown(struct aq_nic_s *self) + { + int err = 0; +@@ -1272,6 +1292,7 @@ void aq_nic_release_filter(struct aq_nic_s *self, enum aq_rx_filter_type type, + int aq_nic_setup_tc_mqprio(struct aq_nic_s *self, u32 tcs, u8 *prio_tc_map) + { + struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; ++ const unsigned int prev_vecs = cfg->vecs; + bool ndev_running; + int err = 0; + int i; +@@ -1303,9 +1324,18 @@ int aq_nic_setup_tc_mqprio(struct aq_nic_s *self, u32 tcs, u8 *prio_tc_map) + + netdev_set_num_tc(self->ndev, cfg->tcs); + ++ /* Changing the number of TCs might change the number of vectors */ ++ aq_nic_cfg_update_num_vecs(self); ++ if (prev_vecs != cfg->vecs) { ++ err = aq_nic_realloc_vectors(self); ++ if (err) ++ goto err_exit; ++ } ++ + if (ndev_running) + err = dev_open(self->ndev, NULL); + ++err_exit: + return err; + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index 7dd2530453da..cff42a2a2936 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -173,6 +173,7 @@ void aq_nic_deinit(struct aq_nic_s *self, bool link_down); + void aq_nic_set_power(struct aq_nic_s *self); + void aq_nic_free_hot_resources(struct aq_nic_s *self); + void aq_nic_free_vectors(struct aq_nic_s *self); ++int aq_nic_realloc_vectors(struct aq_nic_s *self); + int aq_nic_set_mtu(struct aq_nic_s *self, int new_mtu); + int aq_nic_set_mac(struct aq_nic_s *self, struct net_device *ndev); + int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags); +-- +2.13.6 + diff --git a/SOURCES/0101-netdrv-net-atlantic-always-use-random-TC-queue-mappi.patch b/SOURCES/0101-netdrv-net-atlantic-always-use-random-TC-queue-mappi.patch new file mode 100644 index 0000000..c7634d2 --- /dev/null +++ b/SOURCES/0101-netdrv-net-atlantic-always-use-random-TC-queue-mappi.patch @@ -0,0 +1,195 @@ +From 6f5c5d05c208ff797139ccf4908b50ffcfbfdac4 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:58 -0500 +Subject: [PATCH 101/139] [netdrv] net: atlantic: always use random TC-queue + mapping for TX on A2 + +Message-id: <1604687916-15087-102-git-send-email-irusskik@redhat.com> +Patchwork-id: 338524 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 101/139] net: atlantic: always use random TC-queue mapping for TX on A2. +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 5479e8436f32cdbe76d63119459a7d651c1c39ed +Author: Mark Starovoytov +Date: Fri May 22 11:19:45 2020 +0300 + + net: atlantic: always use random TC-queue mapping for TX on A2. + + This patch changes the TC-queue mapping mechanism used on A2. + Configure the A2 HW in such a way that we can keep queue index mapping + exactly as it was on A1. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 31 ++++++++++++----- + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.c | 9 +++++ + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.h | 4 +++ + .../atlantic/hw_atl2/hw_atl2_llh_internal.h | 39 ++++++++++++++++++++-- + 4 files changed, 72 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index b42ff81adfeb..a5bffadde6df 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -95,7 +95,10 @@ static int hw_atl2_hw_queue_to_tc_map_set(struct aq_hw_s *self) + struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; + unsigned int tcs, q_per_tc; + unsigned int tc, q; +- u32 value = 0; ++ u32 rx_map = 0; ++ u32 tx_map = 0; ++ ++ hw_atl2_tpb_tx_tc_q_rand_map_en_set(self, 1U); + + switch (cfg->tc_mode) { + case AQ_TC_MODE_8TCS: +@@ -113,14 +116,24 @@ static int hw_atl2_hw_queue_to_tc_map_set(struct aq_hw_s *self) + for (tc = 0; tc != tcs; tc++) { + unsigned int tc_q_offset = tc * q_per_tc; + +- for (q = tc_q_offset; q != tc_q_offset + q_per_tc; q++) +- value |= tc << HW_ATL2_RX_Q_TC_MAP_SHIFT(q); ++ for (q = tc_q_offset; q != tc_q_offset + q_per_tc; q++) { ++ rx_map |= tc << HW_ATL2_RX_Q_TC_MAP_SHIFT(q); ++ if (HW_ATL2_RX_Q_TC_MAP_ADR(q) != ++ HW_ATL2_RX_Q_TC_MAP_ADR(q + 1)) { ++ aq_hw_write_reg(self, ++ HW_ATL2_RX_Q_TC_MAP_ADR(q), ++ rx_map); ++ rx_map = 0; ++ } + +- if (HW_ATL2_RX_Q_TC_MAP_ADR(q) != +- HW_ATL2_RX_Q_TC_MAP_ADR(q - 1)) { +- aq_hw_write_reg(self, HW_ATL2_RX_Q_TC_MAP_ADR(q - 1), +- value); +- value = 0; ++ tx_map |= tc << HW_ATL2_TX_Q_TC_MAP_SHIFT(q); ++ if (HW_ATL2_TX_Q_TC_MAP_ADR(q) != ++ HW_ATL2_TX_Q_TC_MAP_ADR(q + 1)) { ++ aq_hw_write_reg(self, ++ HW_ATL2_TX_Q_TC_MAP_ADR(q), ++ tx_map); ++ tx_map = 0; ++ } + } + } + +@@ -181,7 +194,7 @@ static int hw_atl2_hw_qos_set(struct aq_hw_s *self) + hw_atl_rpf_rpb_user_priority_tc_map_set(self, prio, + cfg->prio_tc_map[prio]); + +- /* ATL2 Apply legacy ring to TC mapping */ ++ /* ATL2 Apply ring to TC mapping */ + hw_atl2_hw_queue_to_tc_map_set(self); + + return aq_hw_err_from_flags(self); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +index f096d0a6bda9..6817fa57cc83 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +@@ -68,6 +68,15 @@ void hw_atl2_rpf_vlan_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter) + + /* TX */ + ++void hw_atl2_tpb_tx_tc_q_rand_map_en_set(struct aq_hw_s *aq_hw, ++ const u32 tc_q_rand_map_en) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_ADR, ++ HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_MSK, ++ HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_SHIFT, ++ tc_q_rand_map_en); ++} ++ + void hw_atl2_tpb_tx_buf_clk_gate_en_set(struct aq_hw_s *aq_hw, u32 clk_gate_en) + { + aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_ADR, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +index 5c1ae755ffae..d4b087d1dec1 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +@@ -38,6 +38,10 @@ void hw_atl2_new_rpf_rss_redir_set(struct aq_hw_s *aq_hw, u32 tc, u32 index, + /* Set VLAN filter tag */ + void hw_atl2_rpf_vlan_flr_tag_set(struct aq_hw_s *aq_hw, u32 tag, u32 filter); + ++/* set tx random TC-queue mapping enable bit */ ++void hw_atl2_tpb_tx_tc_q_rand_map_en_set(struct aq_hw_s *aq_hw, ++ const u32 tc_q_rand_map_en); ++ + /* set tx buffer clock gate enable */ + void hw_atl2_tpb_tx_buf_clk_gate_en_set(struct aq_hw_s *aq_hw, u32 clk_gate_en); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +index b0ac8cd581d7..bf0198ca4e85 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +@@ -132,6 +132,24 @@ + /* Default value of bitfield rx_q{Q}_tc_map[2:0] */ + #define HW_ATL2_RX_Q_TC_MAP_DEFAULT 0x0 + ++/* tx tx_tc_q_rand_map_en bitfield definitions ++ * preprocessor definitions for the bitfield "tx_tc_q_rand_map_en". ++ * port="pif_tpb_tx_tc_q_rand_map_en_i" ++ */ ++ ++/* register address for bitfield tx_tc_q_rand_map_en */ ++#define HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_ADR 0x00007900 ++/* bitmask for bitfield tx_tc_q_rand_map_en */ ++#define HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_MSK 0x00000200 ++/* inverted bitmask for bitfield tx_tc_q_rand_map_en */ ++#define HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_MSKN 0xFFFFFDFF ++/* lower bit position of bitfield tx_tc_q_rand_map_en */ ++#define HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_SHIFT 9 ++/* width of bitfield tx_tc_q_rand_map_en */ ++#define HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_WIDTH 1 ++/* default value of bitfield tx_tc_q_rand_map_en */ ++#define HW_ATL2_TPB_TX_TC_Q_RAND_MAP_EN_DEFAULT 0x0 ++ + /* tx tx_buffer_clk_gate_en bitfield definitions + * preprocessor definitions for the bitfield "tx_buffer_clk_gate_en". + * port="pif_tpb_tx_buffer_clk_gate_en_i" +@@ -150,8 +168,25 @@ + /* default value of bitfield tx_buffer_clk_gate_en */ + #define HW_ATL2_TPB_TX_BUF_CLK_GATE_EN_DEFAULT 0x0 + +-/* tx data_tc{t}_credit_max[b:0] bitfield definitions +- * preprocessor definitions for the bitfield "data_tc{t}_credit_max[b:0]". ++/* tx tx_q_tc_map{q} bitfield definitions ++ * preprocessor definitions for the bitfield "tx_q_tc_map{q}". ++ * parameter: queue {q} | bit-level stride | range [0, 31] ++ * port="pif_tpb_tx_q_tc_map0_i[2:0]" ++ */ ++ ++/* register address for bitfield tx_q_tc_map{q} */ ++#define HW_ATL2_TX_Q_TC_MAP_ADR(queue) \ ++ (((queue) < 32) ? 0x0000799C + ((queue) / 4) * 4 : 0) ++/* lower bit position of bitfield tx_q_tc_map{q} */ ++#define HW_ATL2_TX_Q_TC_MAP_SHIFT(queue) \ ++ (((queue) < 32) ? ((queue) * 8) % 32 : 0) ++/* width of bitfield tx_q_tc_map{q} */ ++#define HW_ATL2_TX_Q_TC_MAP_WIDTH 3 ++/* default value of bitfield tx_q_tc_map{q} */ ++#define HW_ATL2_TX_Q_TC_MAP_DEFAULT 0x0 ++ ++/* tx data_tc{t}_credit_max[f:0] bitfield definitions ++ * preprocessor definitions for the bitfield "data_tc{t}_credit_max[f:0]". + * parameter: tc {t} | stride size 0x4 | range [0, 7] + * port="pif_tps_data_tc0_credit_max_i[11:0]" + */ +-- +2.13.6 + diff --git a/SOURCES/0102-netdrv-net-atlantic-change-the-order-of-arguments-fo.patch b/SOURCES/0102-netdrv-net-atlantic-change-the-order-of-arguments-fo.patch new file mode 100644 index 0000000..6c6122c --- /dev/null +++ b/SOURCES/0102-netdrv-net-atlantic-change-the-order-of-arguments-fo.patch @@ -0,0 +1,249 @@ +From 8b50fbaae1dc15843d32a3861dd13a1c55deeccb Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:37:59 -0500 +Subject: [PATCH 102/139] [netdrv] net: atlantic: change the order of arguments + for TC weight/credit setters + +Message-id: <1604687916-15087-103-git-send-email-irusskik@redhat.com> +Patchwork-id: 338532 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 102/139] net: atlantic: change the order of arguments for TC weight/credit setters +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit b64f2ac9955bcd3547329c30d8f7a55f84297df8 +Author: Mark Starovoytov +Date: Fri May 22 11:19:46 2020 +0300 + + net: atlantic: change the order of arguments for TC weight/credit setters + + This patch changes the order of arguments for TC weight/credit setter + functions. + Having the "value to be set" on the right is slightly more robust in + a sense that it's more natural for the humans, so it's a bit more + error-proof this way. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 8 ++++---- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 8 ++++---- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 20 ++++++++++---------- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 16 ++++++++-------- + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c | 10 +++++----- + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h | 8 ++++---- + 6 files changed, 35 insertions(+), 35 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index 88b17cf77625..a312864969af 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -136,10 +136,10 @@ static int hw_atl_a0_hw_qos_set(struct aq_hw_s *self) + hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U); + hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U); + +- hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF, 0U); +- hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0x64, 0U); +- hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, 0U); +- hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, 0U); ++ hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0U, 0xFFF); ++ hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0U, 0x64); ++ hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0U, 0x50); ++ hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0U, 0x1E); + + /* Tx buf size */ + buff_size = HW_ATL_A0_TXBUF_MAX; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index abc86eb4f525..2448a09ef7b9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -161,8 +161,8 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + u32 threshold = 0U; + + /* TX Packet Scheduler Data TC0 */ +- hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF, tc); +- hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0x64, tc); ++ hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, tc, 0xFFF); ++ hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, tc, 0x64); + + /* Tx buf size TC0 */ + hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, tx_buff_size, tc); +@@ -334,8 +334,8 @@ int hw_atl_b0_hw_init_tx_tc_rate_limit(struct aq_hw_s *self) + const u32 en = (nic_cfg->tc_max_rate[tc] != 0) ? 1U : 0U; + const u32 desc = AQ_NIC_CFG_TCVEC2RING(nic_cfg, tc, 0); + +- hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, tc); +- hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc); ++ hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, tc, 0x50); ++ hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, tc, 0x1E); + + hw_atl_tps_tx_desc_rate_en_set(self, desc, en); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index 0ea791a9c100..3c8e8047ea1e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -1463,8 +1463,8 @@ void hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(struct aq_hw_s *aq_hw, + } + + void hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(struct aq_hw_s *aq_hw, +- u32 max_credit, +- u32 tc) ++ const u32 tc, ++ const u32 max_credit) + { + aq_hw_write_reg_bit(aq_hw, HW_ATL_TPS_DESC_TCTCREDIT_MAX_ADR(tc), + HW_ATL_TPS_DESC_TCTCREDIT_MAX_MSK, +@@ -1473,13 +1473,13 @@ void hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(struct aq_hw_s *aq_hw, + } + + void hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(struct aq_hw_s *aq_hw, +- u32 tx_pkt_shed_desc_tc_weight, +- u32 tc) ++ const u32 tc, ++ const u32 weight) + { + aq_hw_write_reg_bit(aq_hw, HW_ATL_TPS_DESC_TCTWEIGHT_ADR(tc), + HW_ATL_TPS_DESC_TCTWEIGHT_MSK, + HW_ATL_TPS_DESC_TCTWEIGHT_SHIFT, +- tx_pkt_shed_desc_tc_weight); ++ weight); + } + + void hw_atl_tps_tx_pkt_shed_desc_vm_arb_mode_set(struct aq_hw_s *aq_hw, +@@ -1492,8 +1492,8 @@ void hw_atl_tps_tx_pkt_shed_desc_vm_arb_mode_set(struct aq_hw_s *aq_hw, + } + + void hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw, +- u32 max_credit, +- u32 tc) ++ const u32 tc, ++ const u32 max_credit) + { + aq_hw_write_reg_bit(aq_hw, HW_ATL_TPS_DATA_TCTCREDIT_MAX_ADR(tc), + HW_ATL_TPS_DATA_TCTCREDIT_MAX_MSK, +@@ -1502,13 +1502,13 @@ void hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw, + } + + void hw_atl_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw, +- u32 tx_pkt_shed_tc_data_weight, +- u32 tc) ++ const u32 tc, ++ const u32 weight) + { + aq_hw_write_reg_bit(aq_hw, HW_ATL_TPS_DATA_TCTWEIGHT_ADR(tc), + HW_ATL_TPS_DATA_TCTWEIGHT_MSK, + HW_ATL_TPS_DATA_TCTWEIGHT_SHIFT, +- tx_pkt_shed_tc_data_weight); ++ weight); + } + + void hw_atl_tps_tx_desc_rate_mode_set(struct aq_hw_s *aq_hw, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index c56cc4e8e13c..61a6f70c51cd 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -688,13 +688,13 @@ void hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(struct aq_hw_s *aq_hw, + + /* set tx packet scheduler descriptor tc max credit */ + void hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(struct aq_hw_s *aq_hw, +- u32 max_credit, +- u32 tc); ++ const u32 tc, ++ const u32 max_credit); + + /* set tx packet scheduler descriptor tc weight */ + void hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(struct aq_hw_s *aq_hw, +- u32 tx_pkt_shed_desc_tc_weight, +- u32 tc); ++ const u32 tc, ++ const u32 weight); + + /* set tx packet scheduler descriptor vm arbitration mode */ + void hw_atl_tps_tx_pkt_shed_desc_vm_arb_mode_set(struct aq_hw_s *aq_hw, +@@ -702,13 +702,13 @@ void hw_atl_tps_tx_pkt_shed_desc_vm_arb_mode_set(struct aq_hw_s *aq_hw, + + /* set tx packet scheduler tc data max credit */ + void hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw, +- u32 max_credit, +- u32 tc); ++ const u32 tc, ++ const u32 max_credit); + + /* set tx packet scheduler tc data weight */ + void hw_atl_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw, +- u32 tx_pkt_shed_tc_data_weight, +- u32 tc); ++ const u32 tc, ++ const u32 weight); + + /* set tx descriptor rate mode */ + void hw_atl_tps_tx_desc_rate_mode_set(struct aq_hw_s *aq_hw, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +index 6817fa57cc83..c6a6ba66eb05 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +@@ -94,8 +94,8 @@ void hw_atl2_reg_tx_intr_moder_ctrl_set(struct aq_hw_s *aq_hw, + } + + void hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw, +- u32 max_credit, +- u32 tc) ++ const u32 tc, ++ const u32 max_credit) + { + aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPS_DATA_TCTCREDIT_MAX_ADR(tc), + HW_ATL2_TPS_DATA_TCTCREDIT_MAX_MSK, +@@ -104,13 +104,13 @@ void hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw, + } + + void hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw, +- u32 tx_pkt_shed_tc_data_weight, +- u32 tc) ++ const u32 tc, ++ const u32 weight) + { + aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPS_DATA_TCTWEIGHT_ADR(tc), + HW_ATL2_TPS_DATA_TCTWEIGHT_MSK, + HW_ATL2_TPS_DATA_TCTWEIGHT_SHIFT, +- tx_pkt_shed_tc_data_weight); ++ weight); + } + + u32 hw_atl2_get_hw_version(struct aq_hw_s *aq_hw) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +index d4b087d1dec1..883fa009bc0e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +@@ -47,13 +47,13 @@ void hw_atl2_tpb_tx_buf_clk_gate_en_set(struct aq_hw_s *aq_hw, u32 clk_gate_en); + + /* set tx packet scheduler tc data max credit */ + void hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw, +- u32 max_credit, +- u32 tc); ++ const u32 tc, ++ const u32 max_credit); + + /* set tx packet scheduler tc data weight */ + void hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(struct aq_hw_s *aq_hw, +- u32 tx_pkt_shed_tc_data_weight, +- u32 tc); ++ const u32 tc, ++ const u32 weight); + + u32 hw_atl2_get_hw_version(struct aq_hw_s *aq_hw); + +-- +2.13.6 + diff --git a/SOURCES/0103-netdrv-net-atlantic-QoS-implementation-min_rate.patch b/SOURCES/0103-netdrv-net-atlantic-QoS-implementation-min_rate.patch new file mode 100644 index 0000000..e42c42d --- /dev/null +++ b/SOURCES/0103-netdrv-net-atlantic-QoS-implementation-min_rate.patch @@ -0,0 +1,629 @@ +From f06388f23d1c12b2c1acbbcddf8e9832e28d4e37 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:00 -0500 +Subject: [PATCH 103/139] [netdrv] net: atlantic: QoS implementation: min_rate + +Message-id: <1604687916-15087-104-git-send-email-irusskik@redhat.com> +Patchwork-id: 338526 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 103/139] net: atlantic: QoS implementation: min_rate +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 2deac71ac492a6025b163701436e0aa39435a05f +Author: Mark Starovoytov +Date: Fri May 22 11:19:47 2020 +0300 + + net: atlantic: QoS implementation: min_rate + + This patch adds support for mqprio min_rate limiters. + + A2 HW supports Weighted Strict Priority (WSP) arbitration for Tx Descriptor + Queue scheduling among TCs, which can be used for min_rate shaping. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 2 + + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 26 +++-- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 28 +++++ + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 4 + + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 77 +++++++++++-- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h | 2 - + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 127 +++++++++++++++++++-- + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.c | 9 ++ + .../aquantia/atlantic/hw_atl2/hw_atl2_llh.h | 3 + + .../atlantic/hw_atl2/hw_atl2_llh_internal.h | 62 ++++++---- + 10 files changed, 286 insertions(+), 54 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index 0c258726af8c..4a7fea467b78 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -280,6 +280,8 @@ struct aq_hw_ops { + int (*hw_rss_hash_set)(struct aq_hw_s *self, + struct aq_rss_parameters *rss_params); + ++ int (*hw_tc_rate_limit_set)(struct aq_hw_s *self); ++ + int (*hw_get_regs)(struct aq_hw_s *self, + const struct aq_hw_caps_s *aq_hw_caps, + u32 *regs_buff); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index 57a116ccad55..8a1da044e908 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -340,7 +340,6 @@ static int aq_validate_mqprio_opt(struct aq_nic_s *self, + struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(self); + const unsigned int tcs_max = min_t(u8, aq_nic_cfg->aq_hw_caps->tcs_max, + AQ_CFG_TCS_MAX); +- int i; + + if (num_tc > tcs_max) { + netdev_err(self->ndev, "Too many TCs requested\n"); +@@ -352,12 +351,9 @@ static int aq_validate_mqprio_opt(struct aq_nic_s *self, + return -EOPNOTSUPP; + } + +- for (i = 0; i < num_tc; i++) { +- if (has_min_rate && mqprio->min_rate[i]) { +- netdev_err(self->ndev, +- "Min tx rate is not supported\n"); +- return -EOPNOTSUPP; +- } ++ if (has_min_rate && !ATL_HW_IS_CHIP_FEATURE(self->aq_hw, ANTIGUA)) { ++ netdev_err(self->ndev, "Min tx rate is not supported\n"); ++ return -EOPNOTSUPP; + } + + return 0; +@@ -368,23 +364,35 @@ static int aq_ndo_setup_tc(struct net_device *dev, enum tc_setup_type type, + { + struct tc_mqprio_qopt_offload *mqprio = type_data; + struct aq_nic_s *aq_nic = netdev_priv(dev); ++ bool has_min_rate; ++ bool has_max_rate; + int err; + int i; + + if (type != TC_SETUP_QDISC_MQPRIO) + return -EOPNOTSUPP; + ++ has_min_rate = !!(mqprio->flags & TC_MQPRIO_F_MIN_RATE); ++ has_max_rate = !!(mqprio->flags & TC_MQPRIO_F_MAX_RATE); ++ + err = aq_validate_mqprio_opt(aq_nic, mqprio, mqprio->qopt.num_tc); + if (err) + return err; + +- if (mqprio->flags & TC_MQPRIO_F_MAX_RATE) { +- for (i = 0; i < mqprio->qopt.num_tc; i++) { ++ for (i = 0; i < mqprio->qopt.num_tc; i++) { ++ if (has_max_rate) { + u64 max_rate = mqprio->max_rate[i]; + + do_div(max_rate, AQ_MBPS_DIVISOR); + aq_nic_setup_tc_max_rate(aq_nic, i, (u32)max_rate); + } ++ ++ if (has_min_rate) { ++ u64 min_rate = mqprio->min_rate[i]; ++ ++ do_div(min_rate, AQ_MBPS_DIVISOR); ++ aq_nic_setup_tc_min_rate(aq_nic, i, (u32)min_rate); ++ } + } + + return aq_nic_setup_tc_mqprio(aq_nic, mqprio->qopt.num_tc, +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 4ed370777411..04d2faae298b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -192,6 +192,9 @@ static int aq_nic_update_link_status(struct aq_nic_s *self) + aq_utils_obj_clear(&self->flags, + AQ_NIC_LINK_DOWN); + netif_carrier_on(self->ndev); ++ if (self->aq_hw_ops->hw_tc_rate_limit_set) ++ self->aq_hw_ops->hw_tc_rate_limit_set(self->aq_hw); ++ + netif_tx_wake_all_queues(self->ndev); + } + if (netif_carrier_ok(self->ndev) && !self->link_status.mbps) { +@@ -1358,3 +1361,28 @@ int aq_nic_setup_tc_max_rate(struct aq_nic_s *self, const unsigned int tc, + + return 0; + } ++ ++int aq_nic_setup_tc_min_rate(struct aq_nic_s *self, const unsigned int tc, ++ const u32 min_rate) ++{ ++ struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; ++ ++ if (tc >= AQ_CFG_TCS_MAX) ++ return -EINVAL; ++ ++ if (min_rate) ++ set_bit(tc, &cfg->tc_min_rate_msk); ++ else ++ clear_bit(tc, &cfg->tc_min_rate_msk); ++ ++ if (min_rate && min_rate < 20) { ++ netdev_warn(self->ndev, ++ "Setting %s to the minimum usable value of %dMbps.\n", ++ "min rate", 20); ++ cfg->tc_min_rate[tc] = 20; ++ } else { ++ cfg->tc_min_rate[tc] = min_rate; ++ } ++ ++ return 0; ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index cff42a2a2936..aa9efa56f5f6 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -65,6 +65,8 @@ struct aq_nic_cfg_s { + u8 tcs; + u8 prio_tc_map[8]; + u32 tc_max_rate[AQ_CFG_TCS_MAX]; ++ unsigned long tc_min_rate_msk; ++ u32 tc_min_rate[AQ_CFG_TCS_MAX]; + struct aq_rss_parameters aq_rss; + u32 eee_speeds; + }; +@@ -194,4 +196,6 @@ void aq_nic_release_filter(struct aq_nic_s *self, enum aq_rx_filter_type type, + int aq_nic_setup_tc_mqprio(struct aq_nic_s *self, u32 tcs, u8 *prio_tc_map); + int aq_nic_setup_tc_max_rate(struct aq_nic_s *self, const unsigned int tc, + const u32 max_rate); ++int aq_nic_setup_tc_min_rate(struct aq_nic_s *self, const unsigned int tc, ++ const u32 min_rate); + #endif /* AQ_NIC_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 2448a09ef7b9..320f3669305d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -138,8 +138,6 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + unsigned int prio = 0U; + u32 tc = 0U; + +- hw_atl_b0_hw_init_tx_tc_rate_limit(self); +- + if (cfg->is_ptp) { + tx_buff_size -= HW_ATL_B0_PTP_TXBUF_SIZE; + rx_buff_size -= HW_ATL_B0_PTP_RXBUF_SIZE; +@@ -152,18 +150,11 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self) + /* TPS VM init */ + hw_atl_tps_tx_pkt_shed_desc_vm_arb_mode_set(self, 0U); + +- /* TPS TC credits init */ +- hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U); +- + tx_buff_size /= cfg->tcs; + rx_buff_size /= cfg->tcs; + for (tc = 0; tc < cfg->tcs; tc++) { + u32 threshold = 0U; + +- /* TX Packet Scheduler Data TC0 */ +- hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, tc, 0xFFF); +- hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, tc, 0x64); +- + /* Tx buf size TC0 */ + hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, tx_buff_size, tc); + +@@ -319,24 +310,87 @@ int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, + return aq_hw_err_from_flags(self); + } + +-int hw_atl_b0_hw_init_tx_tc_rate_limit(struct aq_hw_s *self) ++static int hw_atl_b0_hw_init_tx_tc_rate_limit(struct aq_hw_s *self) + { ++ static const u32 max_weight = BIT(HW_ATL_TPS_DATA_TCTWEIGHT_WIDTH) - 1; + /* Scale factor is based on the number of bits in fractional portion */ + static const u32 scale = BIT(HW_ATL_TPS_DESC_RATE_Y_WIDTH); + static const u32 frac_msk = HW_ATL_TPS_DESC_RATE_Y_MSK >> + HW_ATL_TPS_DESC_RATE_Y_SHIFT; ++ const u32 link_speed = self->aq_link_status.mbps; + struct aq_nic_cfg_s *nic_cfg = self->aq_nic_cfg; ++ unsigned long num_min_rated_tcs = 0; ++ u32 tc_weight[AQ_CFG_TCS_MAX]; ++ u32 fixed_max_credit; ++ u8 min_rate_msk = 0; ++ u32 sum_weight = 0; + int tc; + ++ /* By default max_credit is based upon MTU (in unit of 64b) */ ++ fixed_max_credit = nic_cfg->aq_hw_caps->mtu / 64; ++ ++ if (link_speed) { ++ min_rate_msk = nic_cfg->tc_min_rate_msk & ++ (BIT(nic_cfg->tcs) - 1); ++ num_min_rated_tcs = hweight8(min_rate_msk); ++ } ++ ++ /* First, calculate weights where min_rate is specified */ ++ if (num_min_rated_tcs) { ++ for (tc = 0; tc != nic_cfg->tcs; tc++) { ++ if (!nic_cfg->tc_min_rate[tc]) { ++ tc_weight[tc] = 0; ++ continue; ++ } ++ ++ tc_weight[tc] = (-1L + link_speed + ++ nic_cfg->tc_min_rate[tc] * ++ max_weight) / ++ link_speed; ++ tc_weight[tc] = min(tc_weight[tc], max_weight); ++ sum_weight += tc_weight[tc]; ++ } ++ } ++ ++ /* WSP, if min_rate is set for at least one TC. ++ * RR otherwise. ++ */ ++ hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, min_rate_msk ? 1U : 0U); ++ /* Data TC Arbiter takes precedence over Descriptor TC Arbiter, ++ * leave Descriptor TC Arbiter as RR. ++ */ + hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U); ++ + hw_atl_tps_tx_desc_rate_mode_set(self, nic_cfg->is_qos ? 1U : 0U); ++ + for (tc = 0; tc != nic_cfg->tcs; tc++) { + const u32 en = (nic_cfg->tc_max_rate[tc] != 0) ? 1U : 0U; + const u32 desc = AQ_NIC_CFG_TCVEC2RING(nic_cfg, tc, 0); ++ u32 weight, max_credit; + +- hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, tc, 0x50); ++ hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, tc, ++ fixed_max_credit); + hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, tc, 0x1E); + ++ if (num_min_rated_tcs) { ++ weight = tc_weight[tc]; ++ ++ if (!weight && sum_weight < max_weight) ++ weight = (max_weight - sum_weight) / ++ (nic_cfg->tcs - num_min_rated_tcs); ++ else if (!weight) ++ weight = 0x64; ++ ++ max_credit = max(8 * weight, fixed_max_credit); ++ } else { ++ weight = 0x64; ++ max_credit = 0xFFF; ++ } ++ ++ hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, tc, weight); ++ hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, tc, ++ max_credit); ++ + hw_atl_tps_tx_desc_rate_en_set(self, desc, en); + + if (en) { +@@ -1550,6 +1604,7 @@ const struct aq_hw_ops hw_atl_ops_b0 = { + .hw_interrupt_moderation_set = hw_atl_b0_hw_interrupt_moderation_set, + .hw_rss_set = hw_atl_b0_hw_rss_set, + .hw_rss_hash_set = hw_atl_b0_hw_rss_hash_set, ++ .hw_tc_rate_limit_set = hw_atl_b0_hw_init_tx_tc_rate_limit, + .hw_get_regs = hw_atl_utils_hw_get_regs, + .hw_get_hw_stats = hw_atl_utils_get_hw_stats, + .hw_get_fw_version = hw_atl_utils_get_fw_version, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +index 992ee4ed37cc..b855459272ca 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +@@ -62,8 +62,6 @@ int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr); + + int hw_atl_b0_hw_start(struct aq_hw_s *self); + +-int hw_atl_b0_hw_init_tx_tc_rate_limit(struct aq_hw_s *self); +- + int hw_atl_b0_hw_irq_enable(struct aq_hw_s *self, u64 mask); + int hw_atl_b0_hw_irq_disable(struct aq_hw_s *self, u64 mask); + int hw_atl_b0_hw_irq_read(struct aq_hw_s *self, u64 *mask); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index a5bffadde6df..f941773b3e20 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -10,6 +10,7 @@ + #include "hw_atl/hw_atl_b0.h" + #include "hw_atl/hw_atl_utils.h" + #include "hw_atl/hw_atl_llh.h" ++#include "hw_atl/hw_atl_llh_internal.h" + #include "hw_atl2_utils.h" + #include "hw_atl2_llh.h" + #include "hw_atl2_internal.h" +@@ -148,8 +149,6 @@ static int hw_atl2_hw_qos_set(struct aq_hw_s *self) + unsigned int prio = 0U; + u32 tc = 0U; + +- hw_atl_b0_hw_init_tx_tc_rate_limit(self); +- + /* TPS Descriptor rate init */ + hw_atl_tps_tx_pkt_shed_desc_rate_curr_time_res_set(self, 0x0U); + hw_atl_tps_tx_pkt_shed_desc_rate_lim_set(self, 0xA); +@@ -157,19 +156,11 @@ static int hw_atl2_hw_qos_set(struct aq_hw_s *self) + /* TPS VM init */ + hw_atl_tps_tx_pkt_shed_desc_vm_arb_mode_set(self, 0U); + +- /* TPS TC credits init */ +- hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U); +- + tx_buff_size /= cfg->tcs; + rx_buff_size /= cfg->tcs; + for (tc = 0; tc < cfg->tcs; tc++) { + u32 threshold = 0U; + +- /* TX Packet Scheduler Data TC0 */ +- hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF0, +- tc); +- hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(self, 0x640, tc); +- + /* Tx buf size TC0 */ + hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, tx_buff_size, tc); + +@@ -225,6 +216,121 @@ static int hw_atl2_hw_rss_set(struct aq_hw_s *self, + return aq_hw_err_from_flags(self); + } + ++static int hw_atl2_hw_init_tx_tc_rate_limit(struct aq_hw_s *self) ++{ ++ static const u32 max_weight = BIT(HW_ATL2_TPS_DATA_TCTWEIGHT_WIDTH) - 1; ++ /* Scale factor is based on the number of bits in fractional portion */ ++ static const u32 scale = BIT(HW_ATL_TPS_DESC_RATE_Y_WIDTH); ++ static const u32 frac_msk = HW_ATL_TPS_DESC_RATE_Y_MSK >> ++ HW_ATL_TPS_DESC_RATE_Y_SHIFT; ++ const u32 link_speed = self->aq_link_status.mbps; ++ struct aq_nic_cfg_s *nic_cfg = self->aq_nic_cfg; ++ unsigned long num_min_rated_tcs = 0; ++ u32 tc_weight[AQ_CFG_TCS_MAX]; ++ u32 fixed_max_credit_4b; ++ u32 fixed_max_credit; ++ u8 min_rate_msk = 0; ++ u32 sum_weight = 0; ++ int tc; ++ ++ /* By default max_credit is based upon MTU (in unit of 64b) */ ++ fixed_max_credit = nic_cfg->aq_hw_caps->mtu / 64; ++ /* in unit of 4b */ ++ fixed_max_credit_4b = nic_cfg->aq_hw_caps->mtu / 4; ++ ++ if (link_speed) { ++ min_rate_msk = nic_cfg->tc_min_rate_msk & ++ (BIT(nic_cfg->tcs) - 1); ++ num_min_rated_tcs = hweight8(min_rate_msk); ++ } ++ ++ /* First, calculate weights where min_rate is specified */ ++ if (num_min_rated_tcs) { ++ for (tc = 0; tc != nic_cfg->tcs; tc++) { ++ if (!nic_cfg->tc_min_rate[tc]) { ++ tc_weight[tc] = 0; ++ continue; ++ } ++ ++ tc_weight[tc] = (-1L + link_speed + ++ nic_cfg->tc_min_rate[tc] * ++ max_weight) / ++ link_speed; ++ tc_weight[tc] = min(tc_weight[tc], max_weight); ++ sum_weight += tc_weight[tc]; ++ } ++ } ++ ++ /* WSP, if min_rate is set for at least one TC. ++ * RR otherwise. ++ */ ++ hw_atl2_tps_tx_pkt_shed_data_arb_mode_set(self, min_rate_msk ? 1U : 0U); ++ /* Data TC Arbiter takes precedence over Descriptor TC Arbiter, ++ * leave Descriptor TC Arbiter as RR. ++ */ ++ hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U); ++ ++ hw_atl_tps_tx_desc_rate_mode_set(self, nic_cfg->is_qos ? 1U : 0U); ++ ++ for (tc = 0; tc != nic_cfg->tcs; tc++) { ++ const u32 en = (nic_cfg->tc_max_rate[tc] != 0) ? 1U : 0U; ++ const u32 desc = AQ_NIC_CFG_TCVEC2RING(nic_cfg, tc, 0); ++ u32 weight, max_credit; ++ ++ hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, tc, ++ fixed_max_credit); ++ hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, tc, 0x1E); ++ ++ if (num_min_rated_tcs) { ++ weight = tc_weight[tc]; ++ ++ if (!weight && sum_weight < max_weight) ++ weight = (max_weight - sum_weight) / ++ (nic_cfg->tcs - num_min_rated_tcs); ++ else if (!weight) ++ weight = 0x640; ++ ++ max_credit = max(2 * weight, fixed_max_credit_4b); ++ } else { ++ weight = 0x640; ++ max_credit = 0xFFF0; ++ } ++ ++ hw_atl2_tps_tx_pkt_shed_tc_data_weight_set(self, tc, weight); ++ hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(self, tc, ++ max_credit); ++ ++ hw_atl_tps_tx_desc_rate_en_set(self, desc, en); ++ ++ if (en) { ++ /* Nominal rate is always 10G */ ++ const u32 rate = 10000U * scale / ++ nic_cfg->tc_max_rate[tc]; ++ const u32 rate_int = rate >> ++ HW_ATL_TPS_DESC_RATE_Y_WIDTH; ++ const u32 rate_frac = rate & frac_msk; ++ ++ hw_atl_tps_tx_desc_rate_x_set(self, desc, rate_int); ++ hw_atl_tps_tx_desc_rate_y_set(self, desc, rate_frac); ++ } else { ++ /* A value of 1 indicates the queue is not ++ * rate controlled. ++ */ ++ hw_atl_tps_tx_desc_rate_x_set(self, desc, 1U); ++ hw_atl_tps_tx_desc_rate_y_set(self, desc, 0U); ++ } ++ } ++ for (tc = nic_cfg->tcs; tc != AQ_CFG_TCS_MAX; tc++) { ++ const u32 desc = AQ_NIC_CFG_TCVEC2RING(nic_cfg, tc, 0); ++ ++ hw_atl_tps_tx_desc_rate_en_set(self, desc, 0U); ++ hw_atl_tps_tx_desc_rate_x_set(self, desc, 1U); ++ hw_atl_tps_tx_desc_rate_y_set(self, desc, 0U); ++ } ++ ++ return aq_hw_err_from_flags(self); ++} ++ + static int hw_atl2_hw_init_tx_path(struct aq_hw_s *self) + { + struct aq_nic_cfg_s *nic_cfg = self->aq_nic_cfg; +@@ -730,6 +836,7 @@ const struct aq_hw_ops hw_atl2_ops = { + .hw_interrupt_moderation_set = hw_atl2_hw_interrupt_moderation_set, + .hw_rss_set = hw_atl2_hw_rss_set, + .hw_rss_hash_set = hw_atl_b0_hw_rss_hash_set, ++ .hw_tc_rate_limit_set = hw_atl2_hw_init_tx_tc_rate_limit, + .hw_get_hw_stats = hw_atl2_utils_get_hw_stats, + .hw_get_fw_version = hw_atl2_utils_get_fw_version, + .hw_set_offload = hw_atl_b0_hw_offload_set, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +index c6a6ba66eb05..cd954b11d24a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.c +@@ -93,6 +93,15 @@ void hw_atl2_reg_tx_intr_moder_ctrl_set(struct aq_hw_s *aq_hw, + tx_intr_moderation_ctl); + } + ++void hw_atl2_tps_tx_pkt_shed_data_arb_mode_set(struct aq_hw_s *aq_hw, ++ const u32 data_arb_mode) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL2_TPS_DATA_TC_ARB_MODE_ADR, ++ HW_ATL2_TPS_DATA_TC_ARB_MODE_MSK, ++ HW_ATL2_TPS_DATA_TC_ARB_MODE_SHIFT, ++ data_arb_mode); ++} ++ + void hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw, + const u32 tc, + const u32 max_credit) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +index 883fa009bc0e..98c7a4621297 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh.h +@@ -45,6 +45,9 @@ void hw_atl2_tpb_tx_tc_q_rand_map_en_set(struct aq_hw_s *aq_hw, + /* set tx buffer clock gate enable */ + void hw_atl2_tpb_tx_buf_clk_gate_en_set(struct aq_hw_s *aq_hw, u32 clk_gate_en); + ++void hw_atl2_tps_tx_pkt_shed_data_arb_mode_set(struct aq_hw_s *aq_hw, ++ const u32 data_arb_mode); ++ + /* set tx packet scheduler tc data max credit */ + void hw_atl2_tps_tx_pkt_shed_tc_data_max_credit_set(struct aq_hw_s *aq_hw, + const u32 tc, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +index bf0198ca4e85..e34c5cda061e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_llh_internal.h +@@ -185,42 +185,60 @@ + /* default value of bitfield tx_q_tc_map{q} */ + #define HW_ATL2_TX_Q_TC_MAP_DEFAULT 0x0 + ++/* tx data_tc_arb_mode bitfield definitions ++ * preprocessor definitions for the bitfield "data_tc_arb_mode". ++ * port="pif_tps_data_tc_arb_mode_i" ++ */ ++ ++/* register address for bitfield data_tc_arb_mode */ ++#define HW_ATL2_TPS_DATA_TC_ARB_MODE_ADR 0x00007100 ++/* bitmask for bitfield data_tc_arb_mode */ ++#define HW_ATL2_TPS_DATA_TC_ARB_MODE_MSK 0x00000003 ++/* inverted bitmask for bitfield data_tc_arb_mode */ ++#define HW_ATL2_TPS_DATA_TC_ARB_MODE_MSKN 0xfffffffc ++/* lower bit position of bitfield data_tc_arb_mode */ ++#define HW_ATL2_TPS_DATA_TC_ARB_MODE_SHIFT 0 ++/* width of bitfield data_tc_arb_mode */ ++#define HW_ATL2_TPS_DATA_TC_ARB_MODE_WIDTH 2 ++/* default value of bitfield data_tc_arb_mode */ ++#define HW_ATL2_TPS_DATA_TC_ARB_MODE_DEFAULT 0x0 ++ + /* tx data_tc{t}_credit_max[f:0] bitfield definitions + * preprocessor definitions for the bitfield "data_tc{t}_credit_max[f:0]". + * parameter: tc {t} | stride size 0x4 | range [0, 7] +- * port="pif_tps_data_tc0_credit_max_i[11:0]" ++ * port="pif_tps_data_tc0_credit_max_i[15:0]" + */ + +-/* register address for bitfield data_tc{t}_credit_max[b:0] */ ++/* register address for bitfield data_tc{t}_credit_max[f:0] */ + #define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_ADR(tc) (0x00007110 + (tc) * 0x4) +-/* bitmask for bitfield data_tc{t}_credit_max[b:0] */ +-#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_MSK 0x0fff0000 +-/* inverted bitmask for bitfield data_tc{t}_credit_max[b:0] */ +-#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_MSKN 0xf000ffff +-/* lower bit position of bitfield data_tc{t}_credit_max[b:0] */ ++/* bitmask for bitfield data_tc{t}_credit_max[f:0] */ ++#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_MSK 0xffff0000 ++/* inverted bitmask for bitfield data_tc{t}_credit_max[f:0] */ ++#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_MSKN 0x0000ffff ++/* lower bit position of bitfield data_tc{t}_credit_max[f:0] */ + #define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_SHIFT 16 +-/* width of bitfield data_tc{t}_credit_max[b:0] */ +-#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_WIDTH 12 +-/* default value of bitfield data_tc{t}_credit_max[b:0] */ ++/* width of bitfield data_tc{t}_credit_max[f:0] */ ++#define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_WIDTH 16 ++/* default value of bitfield data_tc{t}_credit_max[f:0] */ + #define HW_ATL2_TPS_DATA_TCTCREDIT_MAX_DEFAULT 0x0 + +-/* tx data_tc{t}_weight[8:0] bitfield definitions +- * preprocessor definitions for the bitfield "data_tc{t}_weight[8:0]". ++/* tx data_tc{t}_weight[e:0] bitfield definitions ++ * preprocessor definitions for the bitfield "data_tc{t}_weight[e:0]". + * parameter: tc {t} | stride size 0x4 | range [0, 7] +- * port="pif_tps_data_tc0_weight_i[8:0]" ++ * port="pif_tps_data_tc0_weight_i[14:0]" + */ + +-/* register address for bitfield data_tc{t}_weight[8:0] */ ++/* register address for bitfield data_tc{t}_weight[e:0] */ + #define HW_ATL2_TPS_DATA_TCTWEIGHT_ADR(tc) (0x00007110 + (tc) * 0x4) +-/* bitmask for bitfield data_tc{t}_weight[8:0] */ +-#define HW_ATL2_TPS_DATA_TCTWEIGHT_MSK 0x000001ff +-/* inverted bitmask for bitfield data_tc{t}_weight[8:0] */ +-#define HW_ATL2_TPS_DATA_TCTWEIGHT_MSKN 0xfffffe00 +-/* lower bit position of bitfield data_tc{t}_weight[8:0] */ ++/* bitmask for bitfield data_tc{t}_weight[e:0] */ ++#define HW_ATL2_TPS_DATA_TCTWEIGHT_MSK 0x00007fff ++/* inverted bitmask for bitfield data_tc{t}_weight[e:0] */ ++#define HW_ATL2_TPS_DATA_TCTWEIGHT_MSKN 0xffff8000 ++/* lower bit position of bitfield data_tc{t}_weight[e:0] */ + #define HW_ATL2_TPS_DATA_TCTWEIGHT_SHIFT 0 +-/* width of bitfield data_tc{t}_weight[8:0] */ +-#define HW_ATL2_TPS_DATA_TCTWEIGHT_WIDTH 9 +-/* default value of bitfield data_tc{t}_weight[8:0] */ ++/* width of bitfield data_tc{t}_weight[e:0] */ ++#define HW_ATL2_TPS_DATA_TCTWEIGHT_WIDTH 15 ++/* default value of bitfield data_tc{t}_weight[e:0] */ + #define HW_ATL2_TPS_DATA_TCTWEIGHT_DEFAULT 0x0 + + /* tx interrupt moderation control register definitions +-- +2.13.6 + diff --git a/SOURCES/0104-netdrv-net-atlantic-proper-rss_ctrl1-54c0-initializa.patch b/SOURCES/0104-netdrv-net-atlantic-proper-rss_ctrl1-54c0-initializa.patch new file mode 100644 index 0000000..8786bc2 --- /dev/null +++ b/SOURCES/0104-netdrv-net-atlantic-proper-rss_ctrl1-54c0-initializa.patch @@ -0,0 +1,141 @@ +From 7df3335e29aad289cb8a5a498cf237c04f6cfec9 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:01 -0500 +Subject: [PATCH 104/139] [netdrv] net: atlantic: proper rss_ctrl1 (54c0) + initialization + +Message-id: <1604687916-15087-105-git-send-email-irusskik@redhat.com> +Patchwork-id: 338533 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 104/139] net: atlantic: proper rss_ctrl1 (54c0) initialization +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 40f05e5b0d0e6ed5cc868cd09fa976495716b8f9 +Author: Mark Starovoytov +Date: Fri May 22 11:19:48 2020 +0300 + + net: atlantic: proper rss_ctrl1 (54c0) initialization + + This patch fixes an inconsistency between code and spec, which + was found while working on the QoS implementation. + + When 8TCs are used, 2 is the maximum supported number of index bits. + In a 4TC mode, we do support 3, but we shouldn't really use the bytes, + which are intended for the 8TC mode. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 16 ++++++++++++++-- + .../net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h | 2 ++ + .../aquantia/atlantic/hw_atl/hw_atl_b0_internal.h | 4 ++++ + drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 4 +--- + .../aquantia/atlantic/hw_atl2/hw_atl2_internal.h | 3 --- + 5 files changed, 21 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 320f3669305d..14d79f70cad7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -447,6 +447,19 @@ static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self) + return aq_hw_err_from_flags(self); + } + ++void hw_atl_b0_hw_init_rx_rss_ctrl1(struct aq_hw_s *self) ++{ ++ struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; ++ u32 rss_ctrl1 = HW_ATL_RSS_DISABLED; ++ ++ if (cfg->is_rss) ++ rss_ctrl1 = (cfg->tc_mode == AQ_TC_MODE_8TCS) ? ++ HW_ATL_RSS_ENABLED_8TCS_2INDEX_BITS : ++ HW_ATL_RSS_ENABLED_4TCS_3INDEX_BITS; ++ ++ hw_atl_reg_rx_flr_rss_control1set(self, rss_ctrl1); ++} ++ + static int hw_atl_b0_hw_init_rx_path(struct aq_hw_s *self) + { + struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; +@@ -459,8 +472,7 @@ static int hw_atl_b0_hw_init_rx_path(struct aq_hw_s *self) + hw_atl_rpb_rx_flow_ctl_mode_set(self, 1U); + + /* RSS Ring selection */ +- hw_atl_reg_rx_flr_rss_control1set(self, cfg->is_rss ? +- 0xB3333333U : 0x00000000U); ++ hw_atl_b0_hw_init_rx_rss_ctrl1(self); + + /* Multicast filters */ + for (i = HW_ATL_B0_MAC_MAX; i--;) { +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +index b855459272ca..30f468f2084d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +@@ -58,6 +58,8 @@ int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self, + int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring); + int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, struct aq_ring_s *ring); + ++void hw_atl_b0_hw_init_rx_rss_ctrl1(struct aq_hw_s *self); ++ + int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr); + + int hw_atl_b0_hw_start(struct aq_hw_s *self); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +index 4fba4e0928c7..cf460d61a45e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +@@ -151,6 +151,10 @@ + #define HW_ATL_B0_MAX_RXD 8184U + #define HW_ATL_B0_MAX_TXD 8184U + ++#define HW_ATL_RSS_DISABLED 0x00000000U ++#define HW_ATL_RSS_ENABLED_8TCS_2INDEX_BITS 0xA2222222U ++#define HW_ATL_RSS_ENABLED_4TCS_3INDEX_BITS 0x80003333U ++ + /* HW layer capabilities */ + + #endif /* HW_ATL_B0_INTERNAL_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index f941773b3e20..8df9d4ef36f0 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -475,9 +475,7 @@ static int hw_atl2_hw_init_rx_path(struct aq_hw_s *self) + hw_atl2_rpf_rss_hash_type_set(self, HW_ATL2_RPF_RSS_HASH_TYPE_ALL); + + /* RSS Ring selection */ +- hw_atl_reg_rx_flr_rss_control1set(self, cfg->is_rss ? +- HW_ATL_RSS_ENABLED_3INDEX_BITS : +- HW_ATL_RSS_DISABLED); ++ hw_atl_b0_hw_init_rx_rss_ctrl1(self); + + /* Multicast filters */ + for (i = HW_ATL2_MAC_MAX; i--;) { +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +index 9ac1979a4867..5a89bb8722f9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_internal.h +@@ -117,9 +117,6 @@ enum HW_ATL2_RPF_RSS_HASH_TYPE { + HW_ATL2_RPF_RSS_HASH_TYPE_IPV6_EX_UDP, + }; + +-#define HW_ATL_RSS_DISABLED 0x00000000U +-#define HW_ATL_RSS_ENABLED_3INDEX_BITS 0xB3333333U +- + #define HW_ATL_MCAST_FLT_ANY_TO_HOST 0x00010FFFU + + struct hw_atl2_priv { +-- +2.13.6 + diff --git a/SOURCES/0105-netdrv-net-atlantic-A2-half-duplex-support.patch b/SOURCES/0105-netdrv-net-atlantic-A2-half-duplex-support.patch new file mode 100644 index 0000000..bb95179 --- /dev/null +++ b/SOURCES/0105-netdrv-net-atlantic-A2-half-duplex-support.patch @@ -0,0 +1,291 @@ +From 0a2ffafa7bd0fdac22c58063462fad89fadf63ad Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:02 -0500 +Subject: [PATCH 105/139] [netdrv] net: atlantic: A2: half duplex support + +Message-id: <1604687916-15087-106-git-send-email-irusskik@redhat.com> +Patchwork-id: 338527 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 105/139] net: atlantic: A2: half duplex support +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 071a02046c262f633ef8d9064cf36fd6def6d0a5 +Author: Igor Russkikh +Date: Mon Jun 22 17:53:04 2020 +0300 + + net: atlantic: A2: half duplex support + + This patch adds support for 10M/100M/1G half duplex rates, which are + supported by A2 in additional to full duplex rates supported by A1. + + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_common.h | 13 +++-- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 8 +-- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 60 +++++++++++++++++----- + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 1 + + .../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 1 + + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 5 +- + .../aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 5 ++ + 7 files changed, 70 insertions(+), 23 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +index 52ad9433cabc..1587528ca3f6 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +@@ -58,11 +58,14 @@ + #define AQ_NIC_RATE_1G BIT(4) + #define AQ_NIC_RATE_100M BIT(5) + #define AQ_NIC_RATE_10M BIT(6) ++#define AQ_NIC_RATE_1G_HALF BIT(7) ++#define AQ_NIC_RATE_100M_HALF BIT(8) ++#define AQ_NIC_RATE_10M_HALF BIT(9) + +-#define AQ_NIC_RATE_EEE_10G BIT(7) +-#define AQ_NIC_RATE_EEE_5G BIT(8) +-#define AQ_NIC_RATE_EEE_2G5 BIT(9) +-#define AQ_NIC_RATE_EEE_1G BIT(10) +-#define AQ_NIC_RATE_EEE_100M BIT(11) ++#define AQ_NIC_RATE_EEE_10G BIT(10) ++#define AQ_NIC_RATE_EEE_5G BIT(11) ++#define AQ_NIC_RATE_EEE_2G5 BIT(12) ++#define AQ_NIC_RATE_EEE_1G BIT(13) ++#define AQ_NIC_RATE_EEE_100M BIT(14) + + #endif /* AQ_COMMON_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index 4a7fea467b78..a8efd6543f97 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -1,7 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_hw.h: Declaration of abstract interface for NIC hardware specific +@@ -69,6 +70,7 @@ struct aq_hw_caps_s { + + struct aq_hw_link_status_s { + unsigned int mbps; ++ bool full_duplex; + }; + + struct aq_stats_s { +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 04d2faae298b..45d33797fa73 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -923,8 +923,11 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, + cmd->base.port = PORT_FIBRE; + else + cmd->base.port = PORT_TP; +- /* This driver supports only 10G capable adapters, so DUPLEX_FULL */ +- cmd->base.duplex = DUPLEX_FULL; ++ ++ cmd->base.duplex = DUPLEX_UNKNOWN; ++ if (self->link_status.mbps) ++ cmd->base.duplex = self->link_status.full_duplex ? ++ DUPLEX_FULL : DUPLEX_HALF; + cmd->base.autoneg = self->aq_nic_cfg.is_autoneg; + + ethtool_link_ksettings_zero_link_mode(cmd, supported); +@@ -945,14 +948,26 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, + ethtool_link_ksettings_add_link_mode(cmd, supported, + 1000baseT_Full); + ++ if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_1G_HALF) ++ ethtool_link_ksettings_add_link_mode(cmd, supported, ++ 1000baseT_Half); ++ + if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_100M) + ethtool_link_ksettings_add_link_mode(cmd, supported, + 100baseT_Full); + ++ if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_100M_HALF) ++ ethtool_link_ksettings_add_link_mode(cmd, supported, ++ 100baseT_Half); ++ + if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_10M) + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10baseT_Full); + ++ if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_10M_HALF) ++ ethtool_link_ksettings_add_link_mode(cmd, supported, ++ 10baseT_Half); ++ + if (self->aq_nic_cfg.aq_hw_caps->flow_control) { + ethtool_link_ksettings_add_link_mode(cmd, supported, + Pause); +@@ -972,30 +987,42 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, + if (self->aq_nic_cfg.is_autoneg) + ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg); + +- if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10G) ++ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10G) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10000baseT_Full); + +- if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_5G) ++ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_5G) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 5000baseT_Full); + +- if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_2G5) ++ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_2G5) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 2500baseT_Full); + +- if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_1G) ++ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_1G) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 1000baseT_Full); + +- if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_100M) ++ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_1G_HALF) ++ ethtool_link_ksettings_add_link_mode(cmd, advertising, ++ 1000baseT_Half); ++ ++ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_100M) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 100baseT_Full); + +- if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10M) ++ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_100M_HALF) ++ ethtool_link_ksettings_add_link_mode(cmd, advertising, ++ 100baseT_Half); ++ ++ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10M) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10baseT_Full); + ++ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10M_HALF) ++ ethtool_link_ksettings_add_link_mode(cmd, advertising, ++ 10baseT_Half); ++ + if (self->aq_nic_cfg.fc.cur & AQ_NIC_FC_RX) + ethtool_link_ksettings_add_link_mode(cmd, advertising, + Pause); +@@ -1015,27 +1042,32 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, + int aq_nic_set_link_ksettings(struct aq_nic_s *self, + const struct ethtool_link_ksettings *cmd) + { +- u32 speed = 0U; ++ int fduplex = (cmd->base.duplex == DUPLEX_FULL); ++ u32 speed = cmd->base.speed; + u32 rate = 0U; + int err = 0; + ++ if (!fduplex && speed > SPEED_1000) { ++ err = -EINVAL; ++ goto err_exit; ++ } ++ + if (cmd->base.autoneg == AUTONEG_ENABLE) { + rate = self->aq_nic_cfg.aq_hw_caps->link_speed_msk; + self->aq_nic_cfg.is_autoneg = true; + } else { +- speed = cmd->base.speed; +- + switch (speed) { + case SPEED_10: +- rate = AQ_NIC_RATE_10M; ++ rate = fduplex ? AQ_NIC_RATE_10M : AQ_NIC_RATE_10M_HALF; + break; + + case SPEED_100: +- rate = AQ_NIC_RATE_100M; ++ rate = fduplex ? AQ_NIC_RATE_100M ++ : AQ_NIC_RATE_100M_HALF; + break; + + case SPEED_1000: +- rate = AQ_NIC_RATE_1G; ++ rate = fduplex ? AQ_NIC_RATE_1G : AQ_NIC_RATE_1G_HALF; + break; + + case SPEED_2500: +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 73c0f41df8d8..1d9dee4951f9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -704,6 +704,7 @@ int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self) + return -EBUSY; + } + } ++ link_status->full_duplex = true; + + return 0; + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index 8296a1e63522..92ae60ac5735 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -271,6 +271,7 @@ static int aq_fw2x_update_link_status(struct aq_hw_s *self) + } else { + link_status->mbps = 0; + } ++ link_status->full_duplex = true; + + return 0; + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index 8df9d4ef36f0..239d077e21d7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -64,8 +64,11 @@ const struct aq_hw_caps_s hw_atl2_caps_aqc113 = { + AQ_NIC_RATE_5G | + AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | ++ AQ_NIC_RATE_1G_HALF | + AQ_NIC_RATE_100M | +- AQ_NIC_RATE_10M, ++ AQ_NIC_RATE_100M_HALF | ++ AQ_NIC_RATE_10M | ++ AQ_NIC_RATE_10M_HALF, + }; + + static u32 hw_atl2_sem_act_rslvr_get(struct aq_hw_s *self) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +index 0ffc33bd67d0..d64dfae8803e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +@@ -135,6 +135,10 @@ static void a2_link_speed_mask2fw(u32 speed, + link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G); + link_options->rate_100M = !!(speed & AQ_NIC_RATE_100M); + link_options->rate_10M = !!(speed & AQ_NIC_RATE_10M); ++ ++ link_options->rate_1G_hd = !!(speed & AQ_NIC_RATE_1G_HALF); ++ link_options->rate_100M_hd = !!(speed & AQ_NIC_RATE_100M_HALF); ++ link_options->rate_10M_hd = !!(speed & AQ_NIC_RATE_10M_HALF); + } + + static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed) +@@ -202,6 +206,7 @@ static int aq_a2_fw_update_link_status(struct aq_hw_s *self) + default: + self->aq_link_status.mbps = 0; + } ++ self->aq_link_status.full_duplex = link_status.duplex; + + return 0; + } +-- +2.13.6 + diff --git a/SOURCES/0106-netdrv-net-atlantic-remove-baseX-usage.patch b/SOURCES/0106-netdrv-net-atlantic-remove-baseX-usage.patch new file mode 100644 index 0000000..2d9462b --- /dev/null +++ b/SOURCES/0106-netdrv-net-atlantic-remove-baseX-usage.patch @@ -0,0 +1,56 @@ +From fb3237242fc7f7c8ac73dd9df0b784ac9a4b9f1c Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:03 -0500 +Subject: [PATCH 106/139] [netdrv] net: atlantic: remove baseX usage + +Message-id: <1604687916-15087-107-git-send-email-irusskik@redhat.com> +Patchwork-id: 338535 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 106/139] net: atlantic: remove baseX usage +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit e61b28686bae30b824b690c75d011a61f90c52dd +Author: Nikita Danilov +Date: Mon Jun 22 17:53:05 2020 +0300 + + net: atlantic: remove baseX usage + + This patch removes 2.5G baseX wrong usage/reporting, since it shouldn't have + been mixed with baseT. + + Signed-off-by: Nikita Danilov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 59e7b326cfda..bd9b1991df81 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -489,9 +489,6 @@ static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed) + if (speed & AQ_NIC_RATE_EEE_10G) + rate |= SUPPORTED_10000baseT_Full; + +- if (speed & AQ_NIC_RATE_EEE_2G5) +- rate |= SUPPORTED_2500baseX_Full; +- + if (speed & AQ_NIC_RATE_EEE_1G) + rate |= SUPPORTED_1000baseT_Full; + +-- +2.13.6 + diff --git a/SOURCES/0107-netdrv-net-atlantic-A2-EEE-support.patch b/SOURCES/0107-netdrv-net-atlantic-A2-EEE-support.patch new file mode 100644 index 0000000..5a7cae2 --- /dev/null +++ b/SOURCES/0107-netdrv-net-atlantic-A2-EEE-support.patch @@ -0,0 +1,216 @@ +From b9ba5bd88e7727149c705746222338bab7026b24 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:04 -0500 +Subject: [PATCH 107/139] [netdrv] net: atlantic: A2: EEE support + +Message-id: <1604687916-15087-108-git-send-email-irusskik@redhat.com> +Patchwork-id: 338536 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 107/139] net: atlantic: A2: EEE support +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit ce6a690ccc99a7ece8b061d88d9457ddb556a749 +Author: Nikita Danilov +Date: Mon Jun 22 17:53:06 2020 +0300 + + net: atlantic: A2: EEE support + + This patch adds EEE support on A2. + + Signed-off-by: Nikita Danilov + Co-developed-by: Igor Russkikh + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_common.h | 5 ++ + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 11 +-- + .../aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 80 ++++++++++++++++++++++ + 3 files changed, 91 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +index 1587528ca3f6..23b2d390fcdd 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +@@ -67,5 +67,10 @@ + #define AQ_NIC_RATE_EEE_2G5 BIT(12) + #define AQ_NIC_RATE_EEE_1G BIT(13) + #define AQ_NIC_RATE_EEE_100M BIT(14) ++#define AQ_NIC_RATE_EEE_MSK (AQ_NIC_RATE_EEE_10G |\ ++ AQ_NIC_RATE_EEE_5G |\ ++ AQ_NIC_RATE_EEE_2G5 |\ ++ AQ_NIC_RATE_EEE_1G |\ ++ AQ_NIC_RATE_EEE_100M) + + #endif /* AQ_COMMON_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index bd9b1991df81..f800f69690ae 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -1,7 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_ethtool.c: Definition of ethertool related functions. */ +@@ -482,7 +483,7 @@ static int aq_ethtool_get_ts_info(struct net_device *ndev, + return 0; + } + +-static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed) ++static u32 eee_mask_to_ethtool_mask(u32 speed) + { + u32 rate = 0; + +@@ -524,7 +525,7 @@ static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee) + eee->eee_enabled = !!eee->advertised; + + eee->tx_lpi_enabled = eee->eee_enabled; +- if (eee->advertised & eee->lp_advertised) ++ if ((supported_rates & rate) & AQ_NIC_RATE_EEE_MSK) + eee->eee_active = true; + + return 0; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +index d64dfae8803e..9216517f6e65 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +@@ -7,6 +7,7 @@ + + #include "aq_hw.h" + #include "aq_hw_utils.h" ++#include "aq_nic.h" + #include "hw_atl/hw_atl_llh.h" + #include "hw_atl2_utils.h" + #include "hw_atl2_llh.h" +@@ -141,6 +142,42 @@ static void a2_link_speed_mask2fw(u32 speed, + link_options->rate_10M_hd = !!(speed & AQ_NIC_RATE_10M_HALF); + } + ++static u32 a2_fw_dev_to_eee_mask(struct device_link_caps_s *device_link_caps) ++{ ++ u32 rate = 0; ++ ++ if (device_link_caps->eee_10G) ++ rate |= AQ_NIC_RATE_EEE_10G; ++ if (device_link_caps->eee_5G) ++ rate |= AQ_NIC_RATE_EEE_5G; ++ if (device_link_caps->eee_2P5G) ++ rate |= AQ_NIC_RATE_EEE_2G5; ++ if (device_link_caps->eee_1G) ++ rate |= AQ_NIC_RATE_EEE_1G; ++ if (device_link_caps->eee_100M) ++ rate |= AQ_NIC_RATE_EEE_100M; ++ ++ return rate; ++} ++ ++static u32 a2_fw_lkp_to_mask(struct lkp_link_caps_s *lkp_link_caps) ++{ ++ u32 rate = 0; ++ ++ if (lkp_link_caps->eee_10G) ++ rate |= AQ_NIC_RATE_EEE_10G; ++ if (lkp_link_caps->eee_5G) ++ rate |= AQ_NIC_RATE_EEE_5G; ++ if (lkp_link_caps->eee_2P5G) ++ rate |= AQ_NIC_RATE_EEE_2G5; ++ if (lkp_link_caps->eee_1G) ++ rate |= AQ_NIC_RATE_EEE_1G; ++ if (lkp_link_caps->eee_100M) ++ rate |= AQ_NIC_RATE_EEE_100M; ++ ++ return rate; ++} ++ + static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed) + { + struct link_options_s link_options; +@@ -153,6 +190,17 @@ static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed) + return hw_atl2_shared_buffer_finish_ack(self); + } + ++static void aq_a2_fw_upd_eee_rate_bits(struct aq_hw_s *self, ++ struct link_options_s *link_options, ++ u32 eee_speeds) ++{ ++ link_options->eee_10G = !!(eee_speeds & AQ_NIC_RATE_EEE_10G); ++ link_options->eee_5G = !!(eee_speeds & AQ_NIC_RATE_EEE_5G); ++ link_options->eee_2P5G = !!(eee_speeds & AQ_NIC_RATE_EEE_2G5); ++ link_options->eee_1G = !!(eee_speeds & AQ_NIC_RATE_EEE_1G); ++ link_options->eee_100M = !!(eee_speeds & AQ_NIC_RATE_EEE_100M); ++} ++ + static int aq_a2_fw_set_state(struct aq_hw_s *self, + enum hal_atl_utils_fw_state_e state) + { +@@ -163,6 +211,8 @@ static int aq_a2_fw_set_state(struct aq_hw_s *self, + switch (state) { + case MPI_INIT: + link_options.link_up = 1U; ++ aq_a2_fw_upd_eee_rate_bits(self, &link_options, ++ self->aq_nic_cfg->eee_speeds); + break; + case MPI_DEINIT: + link_options.link_up = 0U; +@@ -265,6 +315,34 @@ static int aq_a2_fw_update_stats(struct aq_hw_s *self) + return 0; + } + ++static int aq_a2_fw_set_eee_rate(struct aq_hw_s *self, u32 speed) ++{ ++ struct link_options_s link_options; ++ ++ hw_atl2_shared_buffer_get(self, link_options, link_options); ++ ++ aq_a2_fw_upd_eee_rate_bits(self, &link_options, speed); ++ ++ hw_atl2_shared_buffer_write(self, link_options, link_options); ++ ++ return hw_atl2_shared_buffer_finish_ack(self); ++} ++ ++static int aq_a2_fw_get_eee_rate(struct aq_hw_s *self, u32 *rate, ++ u32 *supported_rates) ++{ ++ struct device_link_caps_s device_link_caps; ++ struct lkp_link_caps_s lkp_link_caps; ++ ++ hw_atl2_shared_buffer_read(self, device_link_caps, device_link_caps); ++ hw_atl2_shared_buffer_read(self, lkp_link_caps, lkp_link_caps); ++ ++ *supported_rates = a2_fw_dev_to_eee_mask(&device_link_caps); ++ *rate = a2_fw_lkp_to_mask(&lkp_link_caps); ++ ++ return 0; ++} ++ + static int aq_a2_fw_renegotiate(struct aq_hw_s *self) + { + struct link_options_s link_options; +@@ -322,4 +400,6 @@ const struct aq_fw_ops aq_a2_fw_ops = { + .set_state = aq_a2_fw_set_state, + .update_link_status = aq_a2_fw_update_link_status, + .update_stats = aq_a2_fw_update_stats, ++ .set_eee_rate = aq_a2_fw_set_eee_rate, ++ .get_eee_rate = aq_a2_fw_get_eee_rate, + }; +-- +2.13.6 + diff --git a/SOURCES/0108-netdrv-net-atlantic-A2-flow-control-support.patch b/SOURCES/0108-netdrv-net-atlantic-A2-flow-control-support.patch new file mode 100644 index 0000000..d88471c --- /dev/null +++ b/SOURCES/0108-netdrv-net-atlantic-A2-flow-control-support.patch @@ -0,0 +1,155 @@ +From 8095efeaaa3a8bf4eaddded46439374b45a4b38a Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:05 -0500 +Subject: [PATCH 108/139] [netdrv] net: atlantic: A2: flow control support + +Message-id: <1604687916-15087-109-git-send-email-irusskik@redhat.com> +Patchwork-id: 338539 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 108/139] net: atlantic: A2: flow control support +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 3e168de529b14edd13c6842ff7bd415f25672db8 +Author: Igor Russkikh +Date: Mon Jun 22 17:53:07 2020 +0300 + + net: atlantic: A2: flow control support + + This patch adds flow control support on A2. + + Co-developed-by: Dmitry Bogdanov + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 2 +- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h | 2 ++ + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 3 ++ + .../aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 36 ++++++++++++++++++++++ + 4 files changed, 42 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 14d79f70cad7..8ed6fd845969 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -108,7 +108,7 @@ static int hw_atl_b0_hw_reset(struct aq_hw_s *self) + return err; + } + +-static int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc) ++int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc) + { + hw_atl_rpb_rx_xoff_en_per_tc_set(self, !!(fc & AQ_NIC_FC_RX), tc); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +index 30f468f2084d..bd9a6fb005c9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +@@ -62,6 +62,8 @@ void hw_atl_b0_hw_init_rx_rss_ctrl1(struct aq_hw_s *self); + + int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr); + ++int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc); ++ + int hw_atl_b0_hw_start(struct aq_hw_s *self); + + int hw_atl_b0_hw_irq_enable(struct aq_hw_s *self, u64 mask); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index 239d077e21d7..c306c26e802b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -181,6 +181,8 @@ static int hw_atl2_hw_qos_set(struct aq_hw_s *self) + + threshold = (rx_buff_size * (1024U / 32U) * 50U) / 100U; + hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(self, threshold, tc); ++ ++ hw_atl_b0_set_fc(self, self->aq_nic_cfg->fc.req, tc); + } + + /* QoS 802.1p priority -> TC mapping */ +@@ -841,4 +843,5 @@ const struct aq_hw_ops hw_atl2_ops = { + .hw_get_hw_stats = hw_atl2_utils_get_hw_stats, + .hw_get_fw_version = hw_atl2_utils_get_fw_version, + .hw_set_offload = hw_atl_b0_hw_offload_set, ++ .hw_set_fc = hw_atl_b0_set_fc, + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +index 9216517f6e65..0edcc0253b2e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +@@ -190,6 +190,15 @@ static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed) + return hw_atl2_shared_buffer_finish_ack(self); + } + ++static void aq_a2_fw_set_mpi_flow_control(struct aq_hw_s *self, ++ struct link_options_s *link_options) ++{ ++ u32 flow_control = self->aq_nic_cfg->fc.req; ++ ++ link_options->pause_rx = !!(flow_control & AQ_NIC_FC_RX); ++ link_options->pause_tx = !!(flow_control & AQ_NIC_FC_TX); ++} ++ + static void aq_a2_fw_upd_eee_rate_bits(struct aq_hw_s *self, + struct link_options_s *link_options, + u32 eee_speeds) +@@ -213,6 +222,7 @@ static int aq_a2_fw_set_state(struct aq_hw_s *self, + link_options.link_up = 1U; + aq_a2_fw_upd_eee_rate_bits(self, &link_options, + self->aq_nic_cfg->eee_speeds); ++ aq_a2_fw_set_mpi_flow_control(self, &link_options); + break; + case MPI_DEINIT: + link_options.link_up = 0U; +@@ -363,6 +373,30 @@ static int aq_a2_fw_renegotiate(struct aq_hw_s *self) + return err; + } + ++static int aq_a2_fw_set_flow_control(struct aq_hw_s *self) ++{ ++ struct link_options_s link_options; ++ ++ hw_atl2_shared_buffer_get(self, link_options, link_options); ++ ++ aq_a2_fw_set_mpi_flow_control(self, &link_options); ++ ++ hw_atl2_shared_buffer_write(self, link_options, link_options); ++ ++ return hw_atl2_shared_buffer_finish_ack(self); ++} ++ ++static u32 aq_a2_fw_get_flow_control(struct aq_hw_s *self, u32 *fcmode) ++{ ++ struct link_status_s link_status; ++ ++ hw_atl2_shared_buffer_read(self, link_status, link_status); ++ ++ *fcmode = ((link_status.pause_rx) ? AQ_NIC_FC_RX : 0) | ++ ((link_status.pause_tx) ? AQ_NIC_FC_TX : 0); ++ return 0; ++} ++ + u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self) + { + struct version_s version; +@@ -402,4 +436,6 @@ const struct aq_fw_ops aq_a2_fw_ops = { + .update_stats = aq_a2_fw_update_stats, + .set_eee_rate = aq_a2_fw_set_eee_rate, + .get_eee_rate = aq_a2_fw_get_eee_rate, ++ .set_flow_control = aq_a2_fw_set_flow_control, ++ .get_flow_control = aq_a2_fw_get_flow_control, + }; +-- +2.13.6 + diff --git a/SOURCES/0109-netdrv-net-atlantic-A2-report-link-partner-capabilit.patch b/SOURCES/0109-netdrv-net-atlantic-A2-report-link-partner-capabilit.patch new file mode 100644 index 0000000..761837c --- /dev/null +++ b/SOURCES/0109-netdrv-net-atlantic-A2-report-link-partner-capabilit.patch @@ -0,0 +1,183 @@ +From a04e918f7758128efdc5e7f158879a131be20cd1 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:06 -0500 +Subject: [PATCH 109/139] [netdrv] net: atlantic: A2: report link partner + capabilities + +Message-id: <1604687916-15087-110-git-send-email-irusskik@redhat.com> +Patchwork-id: 338528 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 109/139] net: atlantic: A2: report link partner capabilities +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 2b53b04de3b185ada35155e668a24a68f6a753ba +Author: Dmitry Bogdanov +Date: Mon Jun 22 17:53:08 2020 +0300 + + net: atlantic: A2: report link partner capabilities + + This patch adds link partner capabilities reporting support on A2. + In particular, the following capabilities are available for reporting: + * link rate; + * EEE; + * flow control. + + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 2 + + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 49 ++++++++++++++++++++++ + .../aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 30 +++++++++++++ + 3 files changed, 81 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index a8efd6543f97..d203057f49eb 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -71,6 +71,8 @@ struct aq_hw_caps_s { + struct aq_hw_link_status_s { + unsigned int mbps; + bool full_duplex; ++ u32 lp_link_speed_msk; ++ u32 lp_flow_control; + }; + + struct aq_stats_s { +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 45d33797fa73..321c9abd909c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -919,6 +919,8 @@ static void aq_nic_update_ndev_stats(struct aq_nic_s *self) + void aq_nic_get_link_ksettings(struct aq_nic_s *self, + struct ethtool_link_ksettings *cmd) + { ++ u32 lp_link_speed_msk; ++ + if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_FIBRE) + cmd->base.port = PORT_FIBRE; + else +@@ -1037,6 +1039,53 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, + ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE); + else + ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); ++ ++ ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising); ++ lp_link_speed_msk = self->aq_hw->aq_link_status.lp_link_speed_msk; ++ ++ if (lp_link_speed_msk & AQ_NIC_RATE_10G) ++ ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, ++ 10000baseT_Full); ++ ++ if (lp_link_speed_msk & AQ_NIC_RATE_5G) ++ ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, ++ 5000baseT_Full); ++ ++ if (lp_link_speed_msk & AQ_NIC_RATE_2G5) ++ ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, ++ 2500baseT_Full); ++ ++ if (lp_link_speed_msk & AQ_NIC_RATE_1G) ++ ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, ++ 1000baseT_Full); ++ ++ if (lp_link_speed_msk & AQ_NIC_RATE_1G_HALF) ++ ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, ++ 1000baseT_Half); ++ ++ if (lp_link_speed_msk & AQ_NIC_RATE_100M) ++ ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, ++ 100baseT_Full); ++ ++ if (lp_link_speed_msk & AQ_NIC_RATE_100M_HALF) ++ ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, ++ 100baseT_Half); ++ ++ if (lp_link_speed_msk & AQ_NIC_RATE_10M) ++ ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, ++ 10baseT_Full); ++ ++ if (lp_link_speed_msk & AQ_NIC_RATE_10M_HALF) ++ ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, ++ 10baseT_Half); ++ ++ if (self->aq_hw->aq_link_status.lp_flow_control & AQ_NIC_FC_RX) ++ ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, ++ Pause); ++ if (!!(self->aq_hw->aq_link_status.lp_flow_control & AQ_NIC_FC_TX) ^ ++ !!(self->aq_hw->aq_link_status.lp_flow_control & AQ_NIC_FC_RX)) ++ ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, ++ Asym_Pause); + } + + int aq_nic_set_link_ksettings(struct aq_nic_s *self, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +index 0edcc0253b2e..c5d1a1404042 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +@@ -164,6 +164,27 @@ static u32 a2_fw_lkp_to_mask(struct lkp_link_caps_s *lkp_link_caps) + { + u32 rate = 0; + ++ if (lkp_link_caps->rate_10G) ++ rate |= AQ_NIC_RATE_10G; ++ if (lkp_link_caps->rate_5G) ++ rate |= AQ_NIC_RATE_5G; ++ if (lkp_link_caps->rate_N5G) ++ rate |= AQ_NIC_RATE_5GSR; ++ if (lkp_link_caps->rate_2P5G) ++ rate |= AQ_NIC_RATE_2G5; ++ if (lkp_link_caps->rate_1G) ++ rate |= AQ_NIC_RATE_1G; ++ if (lkp_link_caps->rate_1G_hd) ++ rate |= AQ_NIC_RATE_1G_HALF; ++ if (lkp_link_caps->rate_100M) ++ rate |= AQ_NIC_RATE_100M; ++ if (lkp_link_caps->rate_100M_hd) ++ rate |= AQ_NIC_RATE_100M_HALF; ++ if (lkp_link_caps->rate_10M) ++ rate |= AQ_NIC_RATE_10M; ++ if (lkp_link_caps->rate_10M_hd) ++ rate |= AQ_NIC_RATE_10M_HALF; ++ + if (lkp_link_caps->eee_10G) + rate |= AQ_NIC_RATE_EEE_10G; + if (lkp_link_caps->eee_5G) +@@ -240,6 +261,7 @@ static int aq_a2_fw_set_state(struct aq_hw_s *self, + + static int aq_a2_fw_update_link_status(struct aq_hw_s *self) + { ++ struct lkp_link_caps_s lkp_link_caps; + struct link_status_s link_status; + + hw_atl2_shared_buffer_read(self, link_status, link_status); +@@ -268,6 +290,14 @@ static int aq_a2_fw_update_link_status(struct aq_hw_s *self) + } + self->aq_link_status.full_duplex = link_status.duplex; + ++ hw_atl2_shared_buffer_read(self, lkp_link_caps, lkp_link_caps); ++ ++ self->aq_link_status.lp_link_speed_msk = ++ a2_fw_lkp_to_mask(&lkp_link_caps); ++ self->aq_link_status.lp_flow_control = ++ ((lkp_link_caps.pause_rx) ? AQ_NIC_FC_RX : 0) | ++ ((lkp_link_caps.pause_tx) ? AQ_NIC_FC_TX : 0); ++ + return 0; + } + +-- +2.13.6 + diff --git a/SOURCES/0110-netdrv-net-atlantic-A2-phy-loopback-support.patch b/SOURCES/0110-netdrv-net-atlantic-A2-phy-loopback-support.patch new file mode 100644 index 0000000..dcdad26 --- /dev/null +++ b/SOURCES/0110-netdrv-net-atlantic-A2-phy-loopback-support.patch @@ -0,0 +1,145 @@ +From 3b424fc9c6e2cb55c3a59e2be46e178ebaeb3f2d Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:07 -0500 +Subject: [PATCH 110/139] [netdrv] net: atlantic: A2: phy loopback support + +Message-id: <1604687916-15087-111-git-send-email-irusskik@redhat.com> +Patchwork-id: 338538 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 110/139] net: atlantic: A2: phy loopback support +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit ecab78703f3b87b3e21160719b08819c7cc0f4e5 +Author: Dmitry Bogdanov +Date: Mon Jun 22 17:53:09 2020 +0300 + + net: atlantic: A2: phy loopback support + + This patch adds the phy loopback support on A2. + + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 5 +++-- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 2 +- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h | 1 + + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 1 + + .../aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 23 ++++++++++++++++++++++ + 5 files changed, 29 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index f800f69690ae..0a611feb94ea 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -707,6 +707,7 @@ static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags) + struct aq_nic_s *aq_nic = netdev_priv(ndev); + struct aq_nic_cfg_s *cfg; + u32 priv_flags; ++ int ret = 0; + + cfg = aq_nic_get_cfg(aq_nic); + priv_flags = cfg->priv_flags; +@@ -728,10 +729,10 @@ static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags) + dev_open(ndev, NULL); + } + } else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) { +- aq_nic_set_loopback(aq_nic); ++ ret = aq_nic_set_loopback(aq_nic); + } + +- return 0; ++ return ret; + } + + const struct ethtool_ops aq_ethtool_ops = { +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 8ed6fd845969..b023c3324a59 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1556,7 +1556,7 @@ static int hw_atl_b0_hw_vlan_ctrl(struct aq_hw_s *self, bool enable) + return aq_hw_err_from_flags(self); + } + +-static int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable) ++int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable) + { + switch (mode) { + case AQ_HW_LOOPBACK_DMA_SYS: +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +index bd9a6fb005c9..66d158900141 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +@@ -63,6 +63,7 @@ void hw_atl_b0_hw_init_rx_rss_ctrl1(struct aq_hw_s *self); + int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr); + + int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc); ++int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable); + + int hw_atl_b0_hw_start(struct aq_hw_s *self); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index c306c26e802b..c65e6daad0e5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -843,5 +843,6 @@ const struct aq_hw_ops hw_atl2_ops = { + .hw_get_hw_stats = hw_atl2_utils_get_hw_stats, + .hw_get_fw_version = hw_atl2_utils_get_fw_version, + .hw_set_offload = hw_atl_b0_hw_offload_set, ++ .hw_set_loopback = hw_atl_b0_set_loopback, + .hw_set_fc = hw_atl_b0_set_fc, + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +index c5d1a1404042..3a9352190816 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +@@ -427,6 +427,28 @@ static u32 aq_a2_fw_get_flow_control(struct aq_hw_s *self, u32 *fcmode) + return 0; + } + ++static int aq_a2_fw_set_phyloopback(struct aq_hw_s *self, u32 mode, bool enable) ++{ ++ struct link_options_s link_options; ++ ++ hw_atl2_shared_buffer_get(self, link_options, link_options); ++ ++ switch (mode) { ++ case AQ_HW_LOOPBACK_PHYINT_SYS: ++ link_options.internal_loopback = enable; ++ break; ++ case AQ_HW_LOOPBACK_PHYEXT_SYS: ++ link_options.external_loopback = enable; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ hw_atl2_shared_buffer_write(self, link_options, link_options); ++ ++ return hw_atl2_shared_buffer_finish_ack(self); ++} ++ + u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self) + { + struct version_s version; +@@ -468,4 +490,5 @@ const struct aq_fw_ops aq_a2_fw_ops = { + .get_eee_rate = aq_a2_fw_get_eee_rate, + .set_flow_control = aq_a2_fw_set_flow_control, + .get_flow_control = aq_a2_fw_get_flow_control, ++ .set_phyloopback = aq_a2_fw_set_phyloopback, + }; +-- +2.13.6 + diff --git a/SOURCES/0111-netdrv-net-atlantic-fix-variable-type-in-aq_ethtool_.patch b/SOURCES/0111-netdrv-net-atlantic-fix-variable-type-in-aq_ethtool_.patch new file mode 100644 index 0000000..dd89924 --- /dev/null +++ b/SOURCES/0111-netdrv-net-atlantic-fix-variable-type-in-aq_ethtool_.patch @@ -0,0 +1,62 @@ +From 158cf9fc8903f1f3e23eefcc717b286ead2bd3eb Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:08 -0500 +Subject: [PATCH 111/139] [netdrv] net: atlantic: fix variable type in + aq_ethtool_get_pauseparam + +Message-id: <1604687916-15087-112-git-send-email-irusskik@redhat.com> +Patchwork-id: 338530 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 111/139] net: atlantic: fix variable type in aq_ethtool_get_pauseparam +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit e39b8ffeb9b9a185438b6dc21bb9997f9fb29cbe +Author: Nikita Danilov +Date: Fri Jun 26 21:40:32 2020 +0300 + + net: atlantic: fix variable type in aq_ethtool_get_pauseparam + + This patch fixes the type for variable which is assigned from enum, + as such it should have been int, not u32. + + Signed-off-by: Nikita Danilov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 0a611feb94ea..c768a99a263e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -587,13 +587,12 @@ static void aq_ethtool_get_pauseparam(struct net_device *ndev, + struct ethtool_pauseparam *pause) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); +- u32 fc = aq_nic->aq_nic_cfg.fc.req; ++ int fc = aq_nic->aq_nic_cfg.fc.req; + + pause->autoneg = 0; + + pause->rx_pause = !!(fc & AQ_NIC_FC_RX); + pause->tx_pause = !!(fc & AQ_NIC_FC_TX); +- + } + + static int aq_ethtool_set_pauseparam(struct net_device *ndev, +-- +2.13.6 + diff --git a/SOURCES/0112-netdrv-net-atlantic-Replace-ENOTSUPP-usage-to-EOPNOT.patch b/SOURCES/0112-netdrv-net-atlantic-Replace-ENOTSUPP-usage-to-EOPNOT.patch new file mode 100644 index 0000000..ee303a8 --- /dev/null +++ b/SOURCES/0112-netdrv-net-atlantic-Replace-ENOTSUPP-usage-to-EOPNOT.patch @@ -0,0 +1,69 @@ +From 45221782c63e029f476065b425dea7235d74614c Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:09 -0500 +Subject: [PATCH 112/139] [netdrv] net: atlantic: Replace ENOTSUPP usage to + EOPNOTSUPP + +Message-id: <1604687916-15087-113-git-send-email-irusskik@redhat.com> +Patchwork-id: 338534 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 112/139] net: atlantic: Replace ENOTSUPP usage to EOPNOTSUPP +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit e35df2186580885c59886452c9b33f02f57ab91f +Author: Mark Starovoytov +Date: Fri Jun 26 21:40:33 2020 +0300 + + net: atlantic: Replace ENOTSUPP usage to EOPNOTSUPP + + This patch replaces ENOTSUPP (where it was used by mistake) with + EOPNOTSUPP. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 2 +- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 321c9abd909c..d75694e9a162 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -1172,7 +1172,7 @@ int aq_nic_set_loopback(struct aq_nic_s *self) + + if (!self->aq_hw_ops->hw_set_loopback || + !self->aq_fw_ops->set_phyloopback) +- return -ENOTSUPP; ++ return -EOPNOTSUPP; + + mutex_lock(&self->fwreq_mutex); + self->aq_hw_ops->hw_set_loopback(self->aq_hw, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 1d9dee4951f9..bf4c41cc312b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -217,7 +217,7 @@ static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self) + + if (rbl_status == 0xF1A7) { + aq_pr_err("No FW detected. Dynamic FW load not implemented\n"); +- return -ENOTSUPP; ++ return -EOPNOTSUPP; + } + + for (k = 0; k < 1000; k++) { +-- +2.13.6 + diff --git a/SOURCES/0113-netdrv-net-atlantic-make-aq_pci_func_init-static.patch b/SOURCES/0113-netdrv-net-atlantic-make-aq_pci_func_init-static.patch new file mode 100644 index 0000000..7440412 --- /dev/null +++ b/SOURCES/0113-netdrv-net-atlantic-make-aq_pci_func_init-static.patch @@ -0,0 +1,91 @@ +From 60461039ea30f77338af1143e6e2106baa6982c4 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:10 -0500 +Subject: [PATCH 113/139] [netdrv] net: atlantic: make aq_pci_func_init static + +Message-id: <1604687916-15087-114-git-send-email-irusskik@redhat.com> +Patchwork-id: 338537 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 113/139] net: atlantic: make aq_pci_func_init static +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit ab3518acac42751f5e85c57d5d14ffcd897e1957 +Author: Mark Starovoytov +Date: Fri Jun 26 21:40:34 2020 +0300 + + net: atlantic: make aq_pci_func_init static + + This patch makes aq_pci_func_init() static, because it's not used anywhere + outside the file itself. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 9 +++++---- + drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h | 8 ++++---- + 2 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +index 908b35f1e7a2..4526d80acb37 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +@@ -1,7 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_pci_func.c: Definition of PCI functions. */ +@@ -113,7 +114,7 @@ static int aq_pci_probe_get_hw_by_id(struct pci_dev *pdev, + return 0; + } + +-int aq_pci_func_init(struct pci_dev *pdev) ++static int aq_pci_func_init(struct pci_dev *pdev) + { + int err; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h +index 77be7ee0d7b3..3fa5f7a73680 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h +@@ -1,7 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_pci_func.h: Declaration of PCI functions. */ +@@ -19,7 +20,6 @@ struct aq_board_revision_s { + const struct aq_hw_caps_s *caps; + }; + +-int aq_pci_func_init(struct pci_dev *pdev); + int aq_pci_func_alloc_irq(struct aq_nic_s *self, unsigned int i, + char *name, irq_handler_t irq_handler, + void *irq_arg, cpumask_t *affinity_mask); +-- +2.13.6 + diff --git a/SOURCES/0114-netdrv-net-atlantic-fix-typo-in-aq_ring_tx_clean.patch b/SOURCES/0114-netdrv-net-atlantic-fix-typo-in-aq_ring_tx_clean.patch new file mode 100644 index 0000000..06ff01e --- /dev/null +++ b/SOURCES/0114-netdrv-net-atlantic-fix-typo-in-aq_ring_tx_clean.patch @@ -0,0 +1,67 @@ +From 9134c7de8d7f224e6cefa20aab03fc28f2aba16f Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:11 -0500 +Subject: [PATCH 114/139] [netdrv] net: atlantic: fix typo in aq_ring_tx_clean + +Message-id: <1604687916-15087-115-git-send-email-irusskik@redhat.com> +Patchwork-id: 338544 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 114/139] net: atlantic: fix typo in aq_ring_tx_clean +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 586616cbd4663a51a53f57ad503d7a93416762c0 +Author: Mark Starovoytov +Date: Fri Jun 26 21:40:35 2020 +0300 + + net: atlantic: fix typo in aq_ring_tx_clean + + This patch fixes a typo in aq_ring_tx_clean. + stats is a union, so the typo doesn't cause any issues, but it's a typo + nonetheless. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index 68fdb3994088..b67b24a0d9a6 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -1,7 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_ring.c: Definition of functions for Rx/Tx rings. */ +@@ -279,7 +280,7 @@ bool aq_ring_tx_clean(struct aq_ring_s *self) + } + + if (unlikely(buff->is_eop)) { +- ++self->stats.rx.packets; ++ ++self->stats.tx.packets; + self->stats.tx.bytes += buff->skb->len; + + dev_kfree_skb_any(buff->skb); +-- +2.13.6 + diff --git a/SOURCES/0115-netdrv-net-atlantic-missing-space-in-a-comment-in-aq.patch b/SOURCES/0115-netdrv-net-atlantic-missing-space-in-a-comment-in-aq.patch new file mode 100644 index 0000000..87762cc --- /dev/null +++ b/SOURCES/0115-netdrv-net-atlantic-missing-space-in-a-comment-in-aq.patch @@ -0,0 +1,67 @@ +From d1ef010ee439ed345501c6031613d526f6baa904 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:12 -0500 +Subject: [PATCH 115/139] [netdrv] net: atlantic: missing space in a comment in + aq_nic.h + +Message-id: <1604687916-15087-116-git-send-email-irusskik@redhat.com> +Patchwork-id: 338541 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 115/139] net: atlantic: missing space in a comment in aq_nic.h +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 6ec99221d780b3b4b86cf9cdafc18699ff3d06c9 +Author: Dmitry Bezrukov +Date: Fri Jun 26 21:40:36 2020 +0300 + + net: atlantic: missing space in a comment in aq_nic.h + + This patch add a missing space in the comment in aq_nic.h + + Signed-off-by: Dmitry Bezrukov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index aa9efa56f5f6..80c70938afd7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -1,7 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_nic.h: Declaration of common code for NIC. */ +@@ -110,7 +111,7 @@ struct aq_hw_rx_fltrs_s { + u16 active_filters; + struct aq_hw_rx_fl2 fl2; + struct aq_hw_rx_fl3l4 fl3l4; +- /*filter ether type */ ++ /* filter ether type */ + u8 fet_reserved_count; + }; + +-- +2.13.6 + diff --git a/SOURCES/0116-netdrv-net-atlantic-add-alignment-checks-in-hw_atl2_.patch b/SOURCES/0116-netdrv-net-atlantic-add-alignment-checks-in-hw_atl2_.patch new file mode 100644 index 0000000..c736775 --- /dev/null +++ b/SOURCES/0116-netdrv-net-atlantic-add-alignment-checks-in-hw_atl2_.patch @@ -0,0 +1,113 @@ +From cedf24913933c10e49591d19712dcbb198ae9d8d Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:13 -0500 +Subject: [PATCH 116/139] [netdrv] net: atlantic: add alignment checks in + hw_atl2_utils_fw.c + +Message-id: <1604687916-15087-117-git-send-email-irusskik@redhat.com> +Patchwork-id: 338543 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 116/139] net: atlantic: add alignment checks in hw_atl2_utils_fw.c +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 8664240e303827de2d40f38fc397d1912309359c +Author: Mark Starovoytov +Date: Fri Jun 26 21:40:37 2020 +0300 + + net: atlantic: add alignment checks in hw_atl2_utils_fw.c + + This patch adds alignment checks in all the helper macros in + hw_atl2_utils_fw.c + These alignment checks are compile-time, so runtime is not affected. + + All these helper macros assume the length to be aligned (multiple of 4). + If it's not aligned, then there might be issues, e.g. stack corruption. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 32 +++++++++++++++++++--- + 1 file changed, 28 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +index 3a9352190816..a8ce9a2c1c51 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +@@ -16,15 +16,29 @@ + #define AQ_A2_FW_READ_TRY_MAX 1000 + + #define hw_atl2_shared_buffer_write(HW, ITEM, VARIABLE) \ ++{\ ++ BUILD_BUG_ON_MSG((offsetof(struct fw_interface_in, ITEM) % \ ++ sizeof(u32)) != 0,\ ++ "Unaligned write " # ITEM);\ ++ BUILD_BUG_ON_MSG((sizeof(VARIABLE) % sizeof(u32)) != 0,\ ++ "Unaligned write length " # ITEM);\ + hw_atl2_mif_shared_buf_write(HW,\ + (offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\ +- (u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32)) ++ (u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32));\ ++} + + #define hw_atl2_shared_buffer_get(HW, ITEM, VARIABLE) \ ++{\ ++ BUILD_BUG_ON_MSG((offsetof(struct fw_interface_in, ITEM) % \ ++ sizeof(u32)) != 0,\ ++ "Unaligned get " # ITEM);\ ++ BUILD_BUG_ON_MSG((sizeof(VARIABLE) % sizeof(u32)) != 0,\ ++ "Unaligned get length " # ITEM);\ + hw_atl2_mif_shared_buf_get(HW, \ + (offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\ + (u32 *)&(VARIABLE), \ +- sizeof(VARIABLE) / sizeof(u32)) ++ sizeof(VARIABLE) / sizeof(u32));\ ++} + + /* This should never be used on non atomic fields, + * treat any > u32 read as non atomic. +@@ -33,7 +47,9 @@ + {\ + BUILD_BUG_ON_MSG((offsetof(struct fw_interface_out, ITEM) % \ + sizeof(u32)) != 0,\ +- "Non aligned read " # ITEM);\ ++ "Unaligned read " # ITEM);\ ++ BUILD_BUG_ON_MSG((sizeof(VARIABLE) % sizeof(u32)) != 0,\ ++ "Unaligned read length " # ITEM);\ + BUILD_BUG_ON_MSG(sizeof(VARIABLE) > sizeof(u32),\ + "Non atomic read " # ITEM);\ + hw_atl2_mif_shared_buf_read(HW, \ +@@ -42,10 +58,18 @@ + } + + #define hw_atl2_shared_buffer_read_safe(HW, ITEM, DATA) \ ++({\ ++ BUILD_BUG_ON_MSG((offsetof(struct fw_interface_out, ITEM) % \ ++ sizeof(u32)) != 0,\ ++ "Unaligned read_safe " # ITEM);\ ++ BUILD_BUG_ON_MSG((sizeof(((struct fw_interface_out *)0)->ITEM) % \ ++ sizeof(u32)) != 0,\ ++ "Unaligned read_safe length " # ITEM);\ + hw_atl2_shared_buffer_read_block((HW), \ + (offsetof(struct fw_interface_out, ITEM) / sizeof(u32)),\ + sizeof(((struct fw_interface_out *)0)->ITEM) / sizeof(u32),\ +- (DATA)) ++ (DATA));\ ++}) + + static int hw_atl2_shared_buffer_read_block(struct aq_hw_s *self, + u32 offset, u32 dwords, void *data) +-- +2.13.6 + diff --git a/SOURCES/0117-netdrv-net-atlantic-put-ptp-code-under-IS_REACHABLE-.patch b/SOURCES/0117-netdrv-net-atlantic-put-ptp-code-under-IS_REACHABLE-.patch new file mode 100644 index 0000000..77ac1fd --- /dev/null +++ b/SOURCES/0117-netdrv-net-atlantic-put-ptp-code-under-IS_REACHABLE-.patch @@ -0,0 +1,204 @@ +From eb83f25d9bbcb697781c7a71982f49378ea08fe3 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:14 -0500 +Subject: [PATCH 117/139] [netdrv] net: atlantic: put ptp code under + IS_REACHABLE check + +Message-id: <1604687916-15087-118-git-send-email-irusskik@redhat.com> +Patchwork-id: 338545 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 117/139] net: atlantic: put ptp code under IS_REACHABLE check +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 4378b882bf03f2e0471b7d92fa97a7227ff3a126 +Author: Igor Russkikh +Date: Fri Jun 26 21:40:38 2020 +0300 + + net: atlantic: put ptp code under IS_REACHABLE check + + A1 requires additional processing for both egress and ingress to support + PTP. + And it makes sense to get rid of this processing altogether (via ifdef), + if PTP clock is disabled globally. + + This patch puts the PTP code under the corresponding IS_REACHABLE check. + + Signed-off-by: Igor Russkikh + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 2 ++ + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 20 ++++++++++++++++---- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 9 +++++++-- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 2 ++ + 4 files changed, 27 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index c768a99a263e..7d8970a36092 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -478,7 +478,9 @@ static int aq_ethtool_get_ts_info(struct net_device *ndev, + BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V2_EVENT); + ++#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) + info->phc_index = ptp_clock_index(aq_ptp_get_ptp_clock(aq_nic->aq_ptp)); ++#endif + + return 0; + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index 8a1da044e908..dfb29b933eb7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -1,7 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_main.c: Main file for aQuantia Linux driver. */ +@@ -98,6 +99,7 @@ static int aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); + ++#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) + if (unlikely(aq_utils_obj_test(&aq_nic->flags, AQ_NIC_PTP_DPATH_UP))) { + /* Hardware adds the Timestamp for PTPv2 802.AS1 + * and PTPv2 IPv4 UDP. +@@ -114,6 +116,7 @@ static int aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev) + unlikely(eth_hdr(skb)->h_proto == htons(ETH_P_1588))) + return aq_ptp_xmit(aq_nic, skb); + } ++#endif + + skb_tx_timestamp(skb); + return aq_nic_xmit(aq_nic, skb); +@@ -222,6 +225,7 @@ static void aq_ndev_set_multicast_settings(struct net_device *ndev) + (void)aq_nic_set_multicast_list(aq_nic, ndev); + } + ++#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) + static int aq_ndev_config_hwtstamp(struct aq_nic_s *aq_nic, + struct hwtstamp_config *config) + { +@@ -256,26 +260,31 @@ static int aq_ndev_config_hwtstamp(struct aq_nic_s *aq_nic, + + return aq_ptp_hwtstamp_config_set(aq_nic->aq_ptp, config); + } ++#endif + + static int aq_ndev_hwtstamp_set(struct aq_nic_s *aq_nic, struct ifreq *ifr) + { + struct hwtstamp_config config; ++#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) + int ret_val; ++#endif + + if (!aq_nic->aq_ptp) + return -EOPNOTSUPP; + + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) + return -EFAULT; +- ++#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) + ret_val = aq_ndev_config_hwtstamp(aq_nic, &config); + if (ret_val) + return ret_val; ++#endif + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? + -EFAULT : 0; + } + ++#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) + static int aq_ndev_hwtstamp_get(struct aq_nic_s *aq_nic, struct ifreq *ifr) + { + struct hwtstamp_config config; +@@ -287,6 +296,7 @@ static int aq_ndev_hwtstamp_get(struct aq_nic_s *aq_nic, struct ifreq *ifr) + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? + -EFAULT : 0; + } ++#endif + + static int aq_ndev_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) + { +@@ -296,8 +306,10 @@ static int aq_ndev_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) + case SIOCSHWTSTAMP: + return aq_ndev_hwtstamp_set(aq_nic, ifr); + ++#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) + case SIOCGHWTSTAMP: + return aq_ndev_hwtstamp_get(aq_nic, ifr); ++#endif + } + + return -EOPNOTSUPP; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index 599ced261b2a..cb9bf41470fd 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -1,6 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* Aquantia Corporation Network Driver +- * Copyright (C) 2014-2019 Aquantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_ptp.c: +@@ -18,6 +20,8 @@ + #include "aq_phy.h" + #include "aq_filters.h" + ++#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) ++ + #define AQ_PTP_TX_TIMEOUT (HZ * 10) + + #define POLL_SYNC_TIMER_MS 15 +@@ -1389,3 +1393,4 @@ static void aq_ptp_poll_sync_work_cb(struct work_struct *w) + schedule_delayed_work(&aq_ptp->poll_sync, timeout); + } + } ++#endif +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index b67b24a0d9a6..8dd59e9fc3aa 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -490,6 +490,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + + void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic) + { ++#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) + while (self->sw_head != self->hw_head) { + u64 ns; + +@@ -501,6 +502,7 @@ void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic) + + self->sw_head = aq_ring_next_dx(self, self->sw_head); + } ++#endif + } + + int aq_ring_rx_fill(struct aq_ring_s *self) +-- +2.13.6 + diff --git a/SOURCES/0118-netdrv-net-aquantia-fix-aq_ndev_start_xmit-s-return-.patch b/SOURCES/0118-netdrv-net-aquantia-fix-aq_ndev_start_xmit-s-return-.patch new file mode 100644 index 0000000..c44d663 --- /dev/null +++ b/SOURCES/0118-netdrv-net-aquantia-fix-aq_ndev_start_xmit-s-return-.patch @@ -0,0 +1,57 @@ +From 8844a2002ce82417b46629701df3c7535250bdcb Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:15 -0500 +Subject: [PATCH 118/139] [netdrv] net: aquantia: fix aq_ndev_start_xmit()'s + return type + +Message-id: <1604687916-15087-119-git-send-email-irusskik@redhat.com> +Patchwork-id: 338540 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 118/139] net: aquantia: fix aq_ndev_start_xmit()'s return type +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 92c5e1150732ac7cc3f876183db62b08572ec63e +Author: Luc Van Oostenryck +Date: Sun Jun 28 21:53:27 2020 +0200 + + net: aquantia: fix aq_ndev_start_xmit()'s return type + + The method ndo_start_xmit() is defined as returning an 'netdev_tx_t', + which is a typedef for an enum type, but the implementation in this + driver returns an 'int'. + + Fix this by returning 'netdev_tx_t' in this driver too. + + Signed-off-by: Luc Van Oostenryck + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +index dfb29b933eb7..8f70a3909929 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c +@@ -95,7 +95,7 @@ static int aq_ndev_close(struct net_device *ndev) + return err; + } + +-static int aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev) ++static netdev_tx_t aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev) + { + struct aq_nic_s *aq_nic = netdev_priv(ndev); + +-- +2.13.6 + diff --git a/SOURCES/0119-netdrv-net-atlantic-fix-ip-dst-and-ipv6-address-filt.patch b/SOURCES/0119-netdrv-net-atlantic-fix-ip-dst-and-ipv6-address-filt.patch new file mode 100644 index 0000000..b1d3d00 --- /dev/null +++ b/SOURCES/0119-netdrv-net-atlantic-fix-ip-dst-and-ipv6-address-filt.patch @@ -0,0 +1,82 @@ +From b8d0c406dd0c8777bea6d5d9e1887063180dae2c Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:16 -0500 +Subject: [PATCH 119/139] [netdrv] net: atlantic: fix ip dst and ipv6 address + filters + +Message-id: <1604687916-15087-120-git-send-email-irusskik@redhat.com> +Patchwork-id: 338567 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 119/139] net: atlantic: fix ip dst and ipv6 address filters +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit a42e6aee7f47a8a68d09923c720fc8f605a04207 +Author: Dmitry Bogdanov +Date: Wed Jul 8 17:17:10 2020 +0300 + + net: atlantic: fix ip dst and ipv6 address filters + + This patch fixes ip dst and ipv6 address filters. + There were 2 mistakes in the code, which led to the issue: + * invalid register was used for ipv4 dst address; + * incorrect write order of dwords for ipv6 addresses. + + Fixes: 23e7a718a49b ("net: aquantia: add rx-flow filter definitions") + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Mark Starovoytov + Signed-off-by: Alexander Lobakin + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 4 ++-- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index 3c8e8047ea1e..d775b23025c1 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -1700,7 +1700,7 @@ void hw_atl_rpfl3l4_ipv6_src_addr_set(struct aq_hw_s *aq_hw, u8 location, + for (i = 0; i < 4; ++i) + aq_hw_write_reg(aq_hw, + HW_ATL_RPF_L3_SRCA_ADR(location + i), +- ipv6_src[i]); ++ ipv6_src[3 - i]); + } + + void hw_atl_rpfl3l4_ipv6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location, +@@ -1711,7 +1711,7 @@ void hw_atl_rpfl3l4_ipv6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location, + for (i = 0; i < 4; ++i) + aq_hw_write_reg(aq_hw, + HW_ATL_RPF_L3_DSTA_ADR(location + i), +- ipv6_dest[i]); ++ ipv6_dest[3 - i]); + } + + u32 hw_atl_sem_ram_get(struct aq_hw_s *self) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +index 06220792daf1..7430ff025134 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +@@ -1360,7 +1360,7 @@ + */ + + /* Register address for bitfield pif_rpf_l3_da0_i[31:0] */ +-#define HW_ATL_RPF_L3_DSTA_ADR(filter) (0x000053B0 + (filter) * 0x4) ++#define HW_ATL_RPF_L3_DSTA_ADR(filter) (0x000053D0 + (filter) * 0x4) + /* Bitmask for bitfield l3_da0[1F:0] */ + #define HW_ATL_RPF_L3_DSTA_MSK 0xFFFFFFFFu + /* Inverted bitmask for bitfield l3_da0[1F:0] */ +-- +2.13.6 + diff --git a/SOURCES/0120-netdrv-net-atlantic-disable-PTP-on-AQC111-AQC112.patch b/SOURCES/0120-netdrv-net-atlantic-disable-PTP-on-AQC111-AQC112.patch new file mode 100644 index 0000000..d4c7f6b --- /dev/null +++ b/SOURCES/0120-netdrv-net-atlantic-disable-PTP-on-AQC111-AQC112.patch @@ -0,0 +1,222 @@ +From 30aa407c61b51affcb753a12a2f347daee0a17a4 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:17 -0500 +Subject: [PATCH 120/139] [netdrv] net: atlantic: disable PTP on AQC111, AQC112 + +Message-id: <1604687916-15087-121-git-send-email-irusskik@redhat.com> +Patchwork-id: 338542 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 120/139] net: atlantic: disable PTP on AQC111, AQC112 +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 23e500e88723f243c27e1b26c9d035d4cdd1b24a +Author: Nikita Danilov +Date: Fri Jul 17 23:39:49 2020 +0300 + + net: atlantic: disable PTP on AQC111, AQC112 + + This patch disables PTP on AQC111 and AQC112 due to a known HW issue, + which can cause datapath issues. + + Ideally PTP block should have been disabled via PHY provisioning, but + unfortunately many units have been shipped with enabled PTP block. + Thus, we have to work around this in the driver. + + Fixes: dbcd6806af420 ("net: aquantia: add support for Phy access") + Signed-off-by: Nikita Danilov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 1 + + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 9 +++++++ + drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 2 ++ + drivers/net/ethernet/aquantia/atlantic/aq_phy.c | 29 ++++++++++++++++++++-- + drivers/net/ethernet/aquantia/atlantic/aq_phy.h | 8 ++++-- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 19 ++++++++++++++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h | 10 +++----- + 7 files changed, 68 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index d203057f49eb..9fab7a1bea71 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -65,6 +65,7 @@ struct aq_hw_caps_s { + u8 rx_rings; + bool flow_control; + bool is_64_dma; ++ u32 quirks; + u32 priv_data_len; + }; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index d75694e9a162..1513669b2529 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -399,6 +399,15 @@ int aq_nic_init(struct aq_nic_s *self) + self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_TP) { + self->aq_hw->phy_id = HW_ATL_PHY_ID_MAX; + err = aq_phy_init(self->aq_hw); ++ ++ /* Disable the PTP on NICs where it's known to cause datapath ++ * problems. ++ * Ideally this should have been done by PHY provisioning, but ++ * many units have been shipped with enabled PTP block already. ++ */ ++ if (self->aq_nic_cfg.aq_hw_caps->quirks & AQ_NIC_QUIRK_BAD_PTP) ++ if (self->aq_hw->phy_id != HW_ATL_PHY_ID_MAX) ++ aq_phy_disable_ptp(self->aq_hw); + } + + for (i = 0U; i < self->aq_vecs; i++) { +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +index 80c70938afd7..b5b0a66ccc03 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +@@ -81,6 +81,8 @@ struct aq_nic_cfg_s { + #define AQ_NIC_FLAG_ERR_UNPLUG 0x40000000U + #define AQ_NIC_FLAG_ERR_HW 0x80000000U + ++#define AQ_NIC_QUIRK_BAD_PTP BIT(0) ++ + #define AQ_NIC_WOL_MODES (WAKE_MAGIC |\ + WAKE_PHY) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_phy.c b/drivers/net/ethernet/aquantia/atlantic/aq_phy.c +index 51ae921e3e1f..949ac2351701 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_phy.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_phy.c +@@ -1,10 +1,14 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* aQuantia Corporation Network Driver +- * Copyright (C) 2018-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2018-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + #include "aq_phy.h" + ++#define HW_ATL_PTP_DISABLE_MSK BIT(10) ++ + bool aq_mdio_busy_wait(struct aq_hw_s *aq_hw) + { + int err = 0; +@@ -145,3 +149,24 @@ bool aq_phy_init(struct aq_hw_s *aq_hw) + + return true; + } ++ ++void aq_phy_disable_ptp(struct aq_hw_s *aq_hw) ++{ ++ static const u16 ptp_registers[] = { ++ 0x031e, ++ 0x031d, ++ 0x031c, ++ 0x031b, ++ }; ++ u16 val; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ptp_registers); i++) { ++ val = aq_phy_read_reg(aq_hw, MDIO_MMD_VEND1, ++ ptp_registers[i]); ++ ++ aq_phy_write_reg(aq_hw, MDIO_MMD_VEND1, ++ ptp_registers[i], ++ val & ~HW_ATL_PTP_DISABLE_MSK); ++ } ++} +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_phy.h b/drivers/net/ethernet/aquantia/atlantic/aq_phy.h +index 84b72ad04a4a..86cc1ee836e2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_phy.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_phy.h +@@ -1,6 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* aQuantia Corporation Network Driver +- * Copyright (C) 2018-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2018-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + #ifndef AQ_PHY_H +@@ -29,4 +31,6 @@ bool aq_phy_init_phy_id(struct aq_hw_s *aq_hw); + + bool aq_phy_init(struct aq_hw_s *aq_hw); + ++void aq_phy_disable_ptp(struct aq_hw_s *aq_hw); ++ + #endif /* AQ_PHY_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index b023c3324a59..b59333898fb7 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -93,6 +93,25 @@ const struct aq_hw_caps_s hw_atl_b0_caps_aqc109 = { + AQ_NIC_RATE_100M, + }; + ++const struct aq_hw_caps_s hw_atl_b0_caps_aqc111 = { ++ DEFAULT_B0_BOARD_BASIC_CAPABILITIES, ++ .media_type = AQ_HW_MEDIA_TYPE_TP, ++ .link_speed_msk = AQ_NIC_RATE_5G | ++ AQ_NIC_RATE_2G5 | ++ AQ_NIC_RATE_1G | ++ AQ_NIC_RATE_100M, ++ .quirks = AQ_NIC_QUIRK_BAD_PTP, ++}; ++ ++const struct aq_hw_caps_s hw_atl_b0_caps_aqc112 = { ++ DEFAULT_B0_BOARD_BASIC_CAPABILITIES, ++ .media_type = AQ_HW_MEDIA_TYPE_TP, ++ .link_speed_msk = AQ_NIC_RATE_2G5 | ++ AQ_NIC_RATE_1G | ++ AQ_NIC_RATE_100M, ++ .quirks = AQ_NIC_QUIRK_BAD_PTP, ++}; ++ + static int hw_atl_b0_hw_reset(struct aq_hw_s *self) + { + int err = 0; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +index 66d158900141..d8db972113ec 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +@@ -18,17 +18,15 @@ extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc100; + extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc107; + extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc108; + extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc109; +- +-#define hw_atl_b0_caps_aqc111 hw_atl_b0_caps_aqc108 +-#define hw_atl_b0_caps_aqc112 hw_atl_b0_caps_aqc109 ++extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc111; ++extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc112; + + #define hw_atl_b0_caps_aqc100s hw_atl_b0_caps_aqc100 + #define hw_atl_b0_caps_aqc107s hw_atl_b0_caps_aqc107 + #define hw_atl_b0_caps_aqc108s hw_atl_b0_caps_aqc108 + #define hw_atl_b0_caps_aqc109s hw_atl_b0_caps_aqc109 +- +-#define hw_atl_b0_caps_aqc111s hw_atl_b0_caps_aqc108 +-#define hw_atl_b0_caps_aqc112s hw_atl_b0_caps_aqc109 ++#define hw_atl_b0_caps_aqc111s hw_atl_b0_caps_aqc111 ++#define hw_atl_b0_caps_aqc112s hw_atl_b0_caps_aqc112 + + extern const struct aq_hw_ops hw_atl_ops_b0; + +-- +2.13.6 + diff --git a/SOURCES/0121-netdrv-net-atlantic-align-return-value-of-ver_match-.patch b/SOURCES/0121-netdrv-net-atlantic-align-return-value-of-ver_match-.patch new file mode 100644 index 0000000..1c112b6 --- /dev/null +++ b/SOURCES/0121-netdrv-net-atlantic-align-return-value-of-ver_match-.patch @@ -0,0 +1,136 @@ +From 5f7041ec9842b65368681999afefa4fd32560c54 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:18 -0500 +Subject: [PATCH 121/139] [netdrv] net: atlantic: align return value of + ver_match function with function name + +Message-id: <1604687916-15087-122-git-send-email-irusskik@redhat.com> +Patchwork-id: 338546 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 121/139] net: atlantic: align return value of ver_match function with function name +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit b567edbfc85ac375181862808928aeb381560c68 +Author: Mark Starovoytov +Date: Fri Jul 17 21:01:46 2020 +0300 + + net: atlantic: align return value of ver_match function with function name + + This patch aligns the return value of hw_atl_utils_ver_match function with + its name. + Change the return type to bool, because it's better aligned with the actual + usage. Return true when the version matches, false otherwise. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 29 ++++++++++------------ + .../aquantia/atlantic/hw_atl/hw_atl_utils.h | 2 +- + .../aquantia/atlantic/hw_atl2/hw_atl2_utils.c | 3 +-- + 3 files changed, 15 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index bf4c41cc312b..22f68e4a638c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -72,14 +72,11 @@ int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) + + self->fw_ver_actual = hw_atl_utils_get_fw_version(self); + +- if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, +- self->fw_ver_actual) == 0) { ++ if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, self->fw_ver_actual)) { + *fw_ops = &aq_fw_1x_ops; +- } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X, +- self->fw_ver_actual) == 0) { ++ } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X, self->fw_ver_actual)) { + *fw_ops = &aq_fw_2x_ops; +- } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X, +- self->fw_ver_actual) == 0) { ++ } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X, self->fw_ver_actual)) { + *fw_ops = &aq_fw_2x_ops; + } else { + aq_pr_err("Bad FW version detected: %x\n", +@@ -262,9 +259,9 @@ int hw_atl_utils_soft_reset(struct aq_hw_s *self) + /* FW 1.x may bootup in an invalid POWER state (WOL feature). + * We should work around this by forcing its state back to DEINIT + */ +- if (!hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, +- aq_hw_read_reg(self, +- HW_ATL_MPI_FW_VERSION))) { ++ if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, ++ aq_hw_read_reg(self, ++ HW_ATL_MPI_FW_VERSION))) { + int err = 0; + + hw_atl_utils_mpi_set_state(self, MPI_DEINIT); +@@ -434,20 +431,20 @@ int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p, + p, cnt, MCP_AREA_SETTINGS); + } + +-int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual) ++bool hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual) + { + const u32 dw_major_mask = 0xff000000U; + const u32 dw_minor_mask = 0x00ffffffU; +- int err = 0; ++ bool ver_match; + +- err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0; +- if (err < 0) ++ ver_match = (dw_major_mask & (ver_expected ^ ver_actual)) ? false : true; ++ if (!ver_match) + goto err_exit; +- err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ? +- -EOPNOTSUPP : 0; ++ ver_match = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ? ++ false : true; + + err_exit: +- return err; ++ return ver_match; + } + + static int hw_atl_utils_init_ucp(struct aq_hw_s *self, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +index c74cf5cf7e46..f402a7c96b59 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +@@ -600,7 +600,7 @@ int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size); + int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, + struct hw_atl_utils_fw_rpc **rpc); + +-int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); ++bool hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); + + extern const struct aq_fw_ops aq_fw_1x_ops; + extern const struct aq_fw_ops aq_fw_2x_ops; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c +index f3766780e975..0fe6257d9c08 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c +@@ -36,8 +36,7 @@ int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) + + self->fw_ver_actual = hw_atl2_utils_get_fw_version(self); + +- if (hw_atl_utils_ver_match(HW_ATL2_FW_VER_1X, +- self->fw_ver_actual) == 0) { ++ if (hw_atl_utils_ver_match(HW_ATL2_FW_VER_1X, self->fw_ver_actual)) { + *fw_ops = &aq_a2_fw_ops; + } else { + aq_pr_err("Bad FW version detected: %x, but continue\n", +-- +2.13.6 + diff --git a/SOURCES/0122-netdrv-net-atlantic-add-support-for-FW-4.x.patch b/SOURCES/0122-netdrv-net-atlantic-add-support-for-FW-4.x.patch new file mode 100644 index 0000000..57453cf --- /dev/null +++ b/SOURCES/0122-netdrv-net-atlantic-add-support-for-FW-4.x.patch @@ -0,0 +1,215 @@ +From b138d4d13acd27b139869cec9aee7896a9275181 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:19 -0500 +Subject: [PATCH 122/139] [netdrv] net: atlantic: add support for FW 4.x + +Message-id: <1604687916-15087-123-git-send-email-irusskik@redhat.com> +Patchwork-id: 338547 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 122/139] net: atlantic: add support for FW 4.x +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 0044b1e1470aa62eeabb24983e2ff5433a68666a +Author: Dmitry Bogdanov +Date: Fri Jul 17 21:01:47 2020 +0300 + + net: atlantic: add support for FW 4.x + + This patch adds support for FW 4.x, which is about to get into the + production for some products. + 4.x is mostly compatible with 3.x, save for soft reset, which requires + the acquisition of 2 additional semaphores. + Other differences (e.g. absence of PTP support) are handled via + capabilities. + + Note: 4.x targets specific products only. 3.x is still the main firmware + branch, which should be used by most users (at least for now). + + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 17 +++++++++-- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 10 +++++-- + .../aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 11 +++++-- + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 35 ++++++++++++++++++---- + 4 files changed, 58 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index d775b23025c1..9c3debae425f 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -1,7 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File hw_atl_llh.c: Definitions of bitfield and register access functions for +@@ -1724,6 +1725,16 @@ u32 hw_atl_sem_mdio_get(struct aq_hw_s *self) + return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_MDIO); + } + ++u32 hw_atl_sem_reset1_get(struct aq_hw_s *self) ++{ ++ return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RESET1); ++} ++ ++u32 hw_atl_sem_reset2_get(struct aq_hw_s *self) ++{ ++ return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RESET2); ++} ++ + u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp) + { + return aq_hw_read_reg(aq_hw, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index 61a6f70c51cd..f0954711df24 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -1,7 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File hw_atl_llh.h: Declarations of bitfield and register access functions for +@@ -838,6 +839,9 @@ u32 hw_atl_sem_ram_get(struct aq_hw_s *self); + /* get global microprocessor mdio semaphore */ + u32 hw_atl_sem_mdio_get(struct aq_hw_s *self); + ++u32 hw_atl_sem_reset1_get(struct aq_hw_s *self); ++u32 hw_atl_sem_reset2_get(struct aq_hw_s *self); ++ + /* get global microprocessor scratch pad register */ + u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +index 7430ff025134..ee11cb88325e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +@@ -1,7 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File hw_atl_llh_internal.h: Preprocessor definitions +@@ -2837,7 +2838,11 @@ + /* Default value of bitfield MDIO Address [F:0] */ + #define HW_ATL_MDIO_ADDRESS_DEFAULT 0x0 + ++#define HW_ATL_MIF_RESET_TIMEOUT_ADR 0x00000348 ++ + #define HW_ATL_FW_SM_MDIO 0x0U + #define HW_ATL_FW_SM_RAM 0x2U ++#define HW_ATL_FW_SM_RESET1 0x3U ++#define HW_ATL_FW_SM_RESET2 0x4U + + #endif /* HW_ATL_LLH_INTERNAL_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 22f68e4a638c..cacab3352cb8 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -46,6 +46,7 @@ + #define HW_ATL_FW_VER_1X 0x01050006U + #define HW_ATL_FW_VER_2X 0x02000000U + #define HW_ATL_FW_VER_3X 0x03000000U ++#define HW_ATL_FW_VER_4X 0x04000000U + + #define FORCE_FLASHLESS 0 + +@@ -78,6 +79,8 @@ int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) + *fw_ops = &aq_fw_2x_ops; + } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X, self->fw_ver_actual)) { + *fw_ops = &aq_fw_2x_ops; ++ } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_4X, self->fw_ver_actual)) { ++ *fw_ops = &aq_fw_2x_ops; + } else { + aq_pr_err("Bad FW version detected: %x\n", + self->fw_ver_actual); +@@ -236,6 +239,7 @@ static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self) + + int hw_atl_utils_soft_reset(struct aq_hw_s *self) + { ++ int ver = hw_atl_utils_get_fw_version(self); + u32 boot_exit_code = 0; + u32 val; + int k; +@@ -256,14 +260,12 @@ int hw_atl_utils_soft_reset(struct aq_hw_s *self) + + self->rbl_enabled = (boot_exit_code != 0); + +- /* FW 1.x may bootup in an invalid POWER state (WOL feature). +- * We should work around this by forcing its state back to DEINIT +- */ +- if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, +- aq_hw_read_reg(self, +- HW_ATL_MPI_FW_VERSION))) { ++ if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, ver)) { + int err = 0; + ++ /* FW 1.x may bootup in an invalid POWER state (WOL feature). ++ * We should work around this by forcing its state back to DEINIT ++ */ + hw_atl_utils_mpi_set_state(self, MPI_DEINIT); + err = readx_poll_timeout_atomic(hw_atl_utils_mpi_get_state, + self, val, +@@ -272,6 +274,27 @@ int hw_atl_utils_soft_reset(struct aq_hw_s *self) + 10, 10000U); + if (err) + return err; ++ } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_4X, ver)) { ++ u64 sem_timeout = aq_hw_read_reg(self, HW_ATL_MIF_RESET_TIMEOUT_ADR); ++ ++ /* Acquire 2 semaphores before issuing reset for FW 4.x */ ++ if (sem_timeout > 3000) ++ sem_timeout = 3000; ++ sem_timeout = sem_timeout * 1000; ++ ++ if (sem_timeout != 0) { ++ int err; ++ ++ err = readx_poll_timeout_atomic(hw_atl_sem_reset1_get, self, val, ++ val == 1U, 1U, sem_timeout); ++ if (err) ++ aq_pr_err("reset sema1 timeout"); ++ ++ err = readx_poll_timeout_atomic(hw_atl_sem_reset2_get, self, val, ++ val == 1U, 1U, sem_timeout); ++ if (err) ++ aq_pr_err("reset sema2 timeout"); ++ } + } + + if (self->rbl_enabled) +-- +2.13.6 + diff --git a/SOURCES/0123-netdrv-net-atlantic-move-FRAC_PER_NS-to-aq_hw.h.patch b/SOURCES/0123-netdrv-net-atlantic-move-FRAC_PER_NS-to-aq_hw.h.patch new file mode 100644 index 0000000..f509d8f --- /dev/null +++ b/SOURCES/0123-netdrv-net-atlantic-move-FRAC_PER_NS-to-aq_hw.h.patch @@ -0,0 +1,109 @@ +From 98702336d8b43dfb3a92f2165fbd79b0b6e8ce6d Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:20 -0500 +Subject: [PATCH 123/139] [netdrv] net: atlantic: move FRAC_PER_NS to aq_hw.h + +Message-id: <1604687916-15087-124-git-send-email-irusskik@redhat.com> +Patchwork-id: 338548 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 123/139] net: atlantic: move FRAC_PER_NS to aq_hw.h +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 519f0cefb4bcac8faf76b2a7b4042fb950eea23e +Author: Mark Starovoytov +Date: Mon Jul 20 21:32:32 2020 +0300 + + net: atlantic: move FRAC_PER_NS to aq_hw.h + + This patch moves FRAC_PER_NS to aq_hw.h so that it can be used in both + hw_atl (A1) and hw_atl2 (A2) in the future. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 2 ++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 20 +++++++++----------- + 2 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index 9fab7a1bea71..986f13809ad5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -36,6 +36,8 @@ enum aq_tc_mode { + (AQ_RX_LAST_LOC_FVLANID - AQ_RX_FIRST_LOC_FVLANID + 1U) + #define AQ_RX_QUEUE_NOT_ASSIGNED 0xFFU + ++#define AQ_FRAC_PER_NS 0x100000000LL ++ + /* Used for rate to Mbps conversion */ + #define AQ_MBPS_DIVISOR 125000 /* 1000000 / 8 */ + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index b59333898fb7..6569bdcea69d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -54,8 +54,6 @@ + .mac_regs_count = 88, \ + .hw_alive_check_addr = 0x10U + +-#define FRAC_PER_NS 0x100000000LL +- + const struct aq_hw_caps_s hw_atl_b0_caps_aqc100 = { + DEFAULT_B0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_FIBRE, +@@ -1252,7 +1250,7 @@ static void hw_atl_b0_adj_params_get(u64 freq, s64 adj, u32 *ns, u32 *fns) + if (base_ns != nsi * NSEC_PER_SEC) { + s64 divisor = div64_s64((s64)NSEC_PER_SEC * NSEC_PER_SEC, + base_ns - nsi * NSEC_PER_SEC); +- nsi_frac = div64_s64(FRAC_PER_NS * NSEC_PER_SEC, divisor); ++ nsi_frac = div64_s64(AQ_FRAC_PER_NS * NSEC_PER_SEC, divisor); + } + + *ns = (u32)nsi; +@@ -1265,23 +1263,23 @@ hw_atl_b0_mac_adj_param_calc(struct hw_fw_request_ptp_adj_freq *ptp_adj_freq, + { + s64 adj_fns_val; + s64 fns_in_sec_phy = phyfreq * (ptp_adj_freq->fns_phy + +- FRAC_PER_NS * ptp_adj_freq->ns_phy); ++ AQ_FRAC_PER_NS * ptp_adj_freq->ns_phy); + s64 fns_in_sec_mac = macfreq * (ptp_adj_freq->fns_mac + +- FRAC_PER_NS * ptp_adj_freq->ns_mac); +- s64 fault_in_sec_phy = FRAC_PER_NS * NSEC_PER_SEC - fns_in_sec_phy; +- s64 fault_in_sec_mac = FRAC_PER_NS * NSEC_PER_SEC - fns_in_sec_mac; ++ AQ_FRAC_PER_NS * ptp_adj_freq->ns_mac); ++ s64 fault_in_sec_phy = AQ_FRAC_PER_NS * NSEC_PER_SEC - fns_in_sec_phy; ++ s64 fault_in_sec_mac = AQ_FRAC_PER_NS * NSEC_PER_SEC - fns_in_sec_mac; + /* MAC MCP counter freq is macfreq / 4 */ + s64 diff_in_mcp_overflow = (fault_in_sec_mac - fault_in_sec_phy) * +- 4 * FRAC_PER_NS; ++ 4 * AQ_FRAC_PER_NS; + + diff_in_mcp_overflow = div64_s64(diff_in_mcp_overflow, + AQ_HW_MAC_COUNTER_HZ); +- adj_fns_val = (ptp_adj_freq->fns_mac + FRAC_PER_NS * ++ adj_fns_val = (ptp_adj_freq->fns_mac + AQ_FRAC_PER_NS * + ptp_adj_freq->ns_mac) + diff_in_mcp_overflow; + +- ptp_adj_freq->mac_ns_adj = div64_s64(adj_fns_val, FRAC_PER_NS); ++ ptp_adj_freq->mac_ns_adj = div64_s64(adj_fns_val, AQ_FRAC_PER_NS); + ptp_adj_freq->mac_fns_adj = adj_fns_val - ptp_adj_freq->mac_ns_adj * +- FRAC_PER_NS; ++ AQ_FRAC_PER_NS; + } + + static int hw_atl_b0_adj_sys_clock(struct aq_hw_s *self, s64 delta) +-- +2.13.6 + diff --git a/SOURCES/0124-netdrv-net-atlantic-use-simple-assignment-in-_get_st.patch b/SOURCES/0124-netdrv-net-atlantic-use-simple-assignment-in-_get_st.patch new file mode 100644 index 0000000..15d5512 --- /dev/null +++ b/SOURCES/0124-netdrv-net-atlantic-use-simple-assignment-in-_get_st.patch @@ -0,0 +1,129 @@ +From 160379b0e060e5eca5d817ec9485f7464cf64cb0 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:21 -0500 +Subject: [PATCH 124/139] [netdrv] net: atlantic: use simple assignment in + _get_stats and _get_sw_stats + +Message-id: <1604687916-15087-125-git-send-email-irusskik@redhat.com> +Patchwork-id: 338566 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 124/139] net: atlantic: use simple assignment in _get_stats and _get_sw_stats +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 3624aa3c2582e4b9097e7648f6f03c82e474ceb8 +Author: Mark Starovoytov +Date: Mon Jul 20 21:32:33 2020 +0300 + + net: atlantic: use simple assignment in _get_stats and _get_sw_stats + + This patch replaces addition assignment operator with a simple assignment + in aq_vec_get_stats() and aq_vec_get_sw_stats(), because it is + sufficient in both cases and this change simplifies the introduction of + u64_stats_update_* in these functions. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 47 +++++++++++++------------ + 1 file changed, 24 insertions(+), 23 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +index d1d43c8ce400..2acdaee18ba0 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +@@ -1,7 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_vec.c: Definition of common structure for vector of Rx and Tx rings. +@@ -349,7 +350,7 @@ cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self) + return &self->aq_ring_param.affinity_mask; + } + +-static void aq_vec_add_stats(struct aq_vec_s *self, ++static void aq_vec_get_stats(struct aq_vec_s *self, + const unsigned int tc, + struct aq_ring_stats_rx_s *stats_rx, + struct aq_ring_stats_tx_s *stats_tx) +@@ -359,23 +360,23 @@ static void aq_vec_add_stats(struct aq_vec_s *self, + if (tc < self->rx_rings) { + struct aq_ring_stats_rx_s *rx = &ring[AQ_VEC_RX_ID].stats.rx; + +- stats_rx->packets += rx->packets; +- stats_rx->bytes += rx->bytes; +- stats_rx->errors += rx->errors; +- stats_rx->jumbo_packets += rx->jumbo_packets; +- stats_rx->lro_packets += rx->lro_packets; +- stats_rx->pg_losts += rx->pg_losts; +- stats_rx->pg_flips += rx->pg_flips; +- stats_rx->pg_reuses += rx->pg_reuses; ++ stats_rx->packets = rx->packets; ++ stats_rx->bytes = rx->bytes; ++ stats_rx->errors = rx->errors; ++ stats_rx->jumbo_packets = rx->jumbo_packets; ++ stats_rx->lro_packets = rx->lro_packets; ++ stats_rx->pg_losts = rx->pg_losts; ++ stats_rx->pg_flips = rx->pg_flips; ++ stats_rx->pg_reuses = rx->pg_reuses; + } + + if (tc < self->tx_rings) { + struct aq_ring_stats_tx_s *tx = &ring[AQ_VEC_TX_ID].stats.tx; + +- stats_tx->packets += tx->packets; +- stats_tx->bytes += tx->bytes; +- stats_tx->errors += tx->errors; +- stats_tx->queue_restarts += tx->queue_restarts; ++ stats_tx->packets = tx->packets; ++ stats_tx->bytes = tx->bytes; ++ stats_tx->errors = tx->errors; ++ stats_tx->queue_restarts = tx->queue_restarts; + } + } + +@@ -389,16 +390,16 @@ int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data, + memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s)); + memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s)); + +- aq_vec_add_stats(self, tc, &stats_rx, &stats_tx); ++ aq_vec_get_stats(self, tc, &stats_rx, &stats_tx); + + /* This data should mimic aq_ethtool_queue_stat_names structure + */ +- data[count] += stats_rx.packets; +- data[++count] += stats_tx.packets; +- data[++count] += stats_tx.queue_restarts; +- data[++count] += stats_rx.jumbo_packets; +- data[++count] += stats_rx.lro_packets; +- data[++count] += stats_rx.errors; ++ data[count] = stats_rx.packets; ++ data[++count] = stats_tx.packets; ++ data[++count] = stats_tx.queue_restarts; ++ data[++count] = stats_rx.jumbo_packets; ++ data[++count] = stats_rx.lro_packets; ++ data[++count] = stats_rx.errors; + + if (p_count) + *p_count = ++count; +-- +2.13.6 + diff --git a/SOURCES/0125-netdrv-net-atlantic-make-_get_sw_stats-return-count-.patch b/SOURCES/0125-netdrv-net-atlantic-make-_get_sw_stats-return-count-.patch new file mode 100644 index 0000000..333916b --- /dev/null +++ b/SOURCES/0125-netdrv-net-atlantic-make-_get_sw_stats-return-count-.patch @@ -0,0 +1,113 @@ +From 5bd69b4a464d9e38ca8e0630aa87bd31c54cab35 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:22 -0500 +Subject: [PATCH 125/139] [netdrv] net: atlantic: make _get_sw_stats return + count as return value + +Message-id: <1604687916-15087-126-git-send-email-irusskik@redhat.com> +Patchwork-id: 338549 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 125/139] net: atlantic: make _get_sw_stats return count as return value +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit b772112c5af0e45ddcacb144545f06bdc594c736 +Author: Mark Starovoytov +Date: Mon Jul 20 21:32:34 2020 +0300 + + net: atlantic: make _get_sw_stats return count as return value + + This patch changes aq_vec_get_sw_stats() to return count as a return + value (which was unused) instead of an out parameter. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 4 ++-- + drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 8 ++------ + drivers/net/ethernet/aquantia/atlantic/aq_vec.h | 10 +++++----- + 3 files changed, 9 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 1513669b2529..7cb2b863d7ac 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -900,13 +900,13 @@ u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data) + aq_vec && self->aq_vecs > i; + ++i, aq_vec = self->aq_vec[i]) { + data += count; +- aq_vec_get_sw_stats(aq_vec, tc, data, &count); ++ count = aq_vec_get_sw_stats(aq_vec, tc, data); + } + } + + data += count; + +-err_exit:; ++err_exit: + return data; + } + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +index 2acdaee18ba0..8f0a0d18e711 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +@@ -380,8 +380,7 @@ static void aq_vec_get_stats(struct aq_vec_s *self, + } + } + +-int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data, +- unsigned int *p_count) ++unsigned int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data) + { + struct aq_ring_stats_rx_s stats_rx; + struct aq_ring_stats_tx_s stats_tx; +@@ -401,8 +400,5 @@ int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data, + data[++count] = stats_rx.lro_packets; + data[++count] = stats_rx.errors; + +- if (p_count) +- *p_count = ++count; +- +- return 0; ++ return ++count; + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.h b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h +index 541af85e6510..c079fef80da8 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h +@@ -1,7 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_vec.h: Definition of common structures for vector of Rx and Tx rings. +@@ -35,7 +36,6 @@ void aq_vec_ring_free(struct aq_vec_s *self); + int aq_vec_start(struct aq_vec_s *self); + void aq_vec_stop(struct aq_vec_s *self); + cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self); +-int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data, +- unsigned int *p_count); ++unsigned int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data); + + #endif /* AQ_VEC_H */ +-- +2.13.6 + diff --git a/SOURCES/0126-netdrv-net-atlantic-split-rx-and-tx-per-queue-stats.patch b/SOURCES/0126-netdrv-net-atlantic-split-rx-and-tx-per-queue-stats.patch new file mode 100644 index 0000000..b676e67 --- /dev/null +++ b/SOURCES/0126-netdrv-net-atlantic-split-rx-and-tx-per-queue-stats.patch @@ -0,0 +1,358 @@ +From 0c578e6b0fb33e283d6809ee530ab366c89f29e9 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:23 -0500 +Subject: [PATCH 126/139] [netdrv] net: atlantic: split rx and tx per-queue + stats + +Message-id: <1604687916-15087-127-git-send-email-irusskik@redhat.com> +Patchwork-id: 338550 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 126/139] net: atlantic: split rx and tx per-queue stats +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 508f2e3dce454843ffd689bb2cf0739a954dd1e9 +Author: Mark Starovoytov +Date: Mon Jul 20 21:32:35 2020 +0300 + + net: atlantic: split rx and tx per-queue stats + + This patch splits rx and tx per-queue stats. + This change simplifies the follow-up introduction of PTP stats and + u64_stats_update_* usage. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 28 ++++++++--- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 6 +-- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 28 ++++++++--- + drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 10 +++- + drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 58 +++++----------------- + drivers/net/ethernet/aquantia/atlantic/aq_vec.h | 1 + + 6 files changed, 68 insertions(+), 63 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 7d8970a36092..458491ef24b9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -88,15 +88,18 @@ static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = { + "InDroppedDma", + }; + +-static const char * const aq_ethtool_queue_stat_names[] = { ++static const char * const aq_ethtool_queue_rx_stat_names[] = { + "%sQueue[%d] InPackets", +- "%sQueue[%d] OutPackets", +- "%sQueue[%d] Restarts", + "%sQueue[%d] InJumboPackets", + "%sQueue[%d] InLroPackets", + "%sQueue[%d] InErrors", + }; + ++static const char * const aq_ethtool_queue_tx_stat_names[] = { ++ "%sQueue[%d] OutPackets", ++ "%sQueue[%d] Restarts", ++}; ++ + static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = { + "DMASystemLoopback", + "PKTSystemLoopback", +@@ -107,11 +110,12 @@ static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = { + + static u32 aq_ethtool_n_stats(struct net_device *ndev) + { ++ const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names); ++ const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names); + struct aq_nic_s *nic = netdev_priv(ndev); + struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic); + u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) + +- ARRAY_SIZE(aq_ethtool_queue_stat_names) * cfg->vecs * +- cfg->tcs; ++ (rx_stat_cnt + tx_stat_cnt) * cfg->vecs * cfg->tcs; + + return n_stats; + } +@@ -162,7 +166,8 @@ static void aq_ethtool_get_strings(struct net_device *ndev, + + switch (stringset) { + case ETH_SS_STATS: { +- const int stat_cnt = ARRAY_SIZE(aq_ethtool_queue_stat_names); ++ const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names); ++ const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names); + char tc_string[8]; + int tc; + +@@ -176,9 +181,16 @@ static void aq_ethtool_get_strings(struct net_device *ndev, + snprintf(tc_string, 8, "TC%d ", tc); + + for (i = 0; i < cfg->vecs; i++) { +- for (si = 0; si < stat_cnt; si++) { ++ for (si = 0; si < rx_stat_cnt; si++) { ++ snprintf(p, ETH_GSTRING_LEN, ++ aq_ethtool_queue_rx_stat_names[si], ++ tc_string, ++ AQ_NIC_CFG_TCVEC2RING(cfg, tc, i)); ++ p += ETH_GSTRING_LEN; ++ } ++ for (si = 0; si < tx_stat_cnt; si++) { + snprintf(p, ETH_GSTRING_LEN, +- aq_ethtool_queue_stat_names[si], ++ aq_ethtool_queue_tx_stat_names[si], + tc_string, + AQ_NIC_CFG_TCVEC2RING(cfg, tc, i)); + p += ETH_GSTRING_LEN; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index cb9bf41470fd..116b8891c9c4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -844,7 +844,7 @@ int aq_ptp_ring_init(struct aq_nic_s *aq_nic) + if (!aq_ptp) + return 0; + +- err = aq_ring_init(&aq_ptp->ptp_tx); ++ err = aq_ring_init(&aq_ptp->ptp_tx, ATL_RING_TX); + if (err < 0) + goto err_exit; + err = aq_nic->aq_hw_ops->hw_ring_tx_init(aq_nic->aq_hw, +@@ -853,7 +853,7 @@ int aq_ptp_ring_init(struct aq_nic_s *aq_nic) + if (err < 0) + goto err_exit; + +- err = aq_ring_init(&aq_ptp->ptp_rx); ++ err = aq_ring_init(&aq_ptp->ptp_rx, ATL_RING_RX); + if (err < 0) + goto err_exit; + err = aq_nic->aq_hw_ops->hw_ring_rx_init(aq_nic->aq_hw, +@@ -871,7 +871,7 @@ int aq_ptp_ring_init(struct aq_nic_s *aq_nic) + if (err < 0) + goto err_rx_free; + +- err = aq_ring_init(&aq_ptp->hwts_rx); ++ err = aq_ring_init(&aq_ptp->hwts_rx, ATL_RING_RX); + if (err < 0) + goto err_rx_free; + err = aq_nic->aq_hw_ops->hw_ring_rx_init(aq_nic->aq_hw, +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index 8dd59e9fc3aa..fc4e10b064fd 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -206,11 +206,12 @@ aq_ring_hwts_rx_alloc(struct aq_ring_s *self, struct aq_nic_s *aq_nic, + return self; + } + +-int aq_ring_init(struct aq_ring_s *self) ++int aq_ring_init(struct aq_ring_s *self, const enum atl_ring_type ring_type) + { + self->hw_head = 0; + self->sw_head = 0; + self->sw_tail = 0; ++ self->ring_type = ring_type; + + return 0; + } +@@ -538,7 +539,7 @@ int aq_ring_rx_fill(struct aq_ring_s *self) + void aq_ring_rx_deinit(struct aq_ring_s *self) + { + if (!self) +- goto err_exit; ++ return; + + for (; self->sw_head != self->sw_tail; + self->sw_head = aq_ring_next_dx(self, self->sw_head)) { +@@ -546,14 +547,12 @@ void aq_ring_rx_deinit(struct aq_ring_s *self) + + aq_free_rxpage(&buff->rxdata, aq_nic_get_dev(self->aq_nic)); + } +- +-err_exit:; + } + + void aq_ring_free(struct aq_ring_s *self) + { + if (!self) +- goto err_exit; ++ return; + + kfree(self->buff_ring); + +@@ -561,6 +560,23 @@ void aq_ring_free(struct aq_ring_s *self) + dma_free_coherent(aq_nic_get_dev(self->aq_nic), + self->size * self->dx_size, self->dx_ring, + self->dx_ring_pa); ++} ++ ++unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data) ++{ ++ unsigned int count = 0U; ++ ++ if (self->ring_type == ATL_RING_RX) { ++ /* This data should mimic aq_ethtool_queue_rx_stat_names structure */ ++ data[count] = self->stats.rx.packets; ++ data[++count] = self->stats.rx.jumbo_packets; ++ data[++count] = self->stats.rx.lro_packets; ++ data[++count] = self->stats.rx.errors; ++ } else { ++ /* This data should mimic aq_ethtool_queue_tx_stat_names structure */ ++ data[count] = self->stats.tx.packets; ++ data[++count] = self->stats.tx.queue_restarts; ++ } + +-err_exit:; ++ return ++count; + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +index 2c96f20f6289..0cd761ba47a3 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +@@ -110,6 +110,11 @@ union aq_ring_stats_s { + struct aq_ring_stats_tx_s tx; + }; + ++enum atl_ring_type { ++ ATL_RING_TX, ++ ATL_RING_RX, ++}; ++ + struct aq_ring_s { + struct aq_ring_buff_s *buff_ring; + u8 *dx_ring; /* descriptors ring, dma shared mem */ +@@ -124,6 +129,7 @@ struct aq_ring_s { + unsigned int page_order; + union aq_ring_stats_s stats; + dma_addr_t dx_ring_pa; ++ enum atl_ring_type ring_type; + }; + + struct aq_ring_param_s { +@@ -163,7 +169,7 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self, + struct aq_nic_s *aq_nic, + unsigned int idx, + struct aq_nic_cfg_s *aq_nic_cfg); +-int aq_ring_init(struct aq_ring_s *self); ++int aq_ring_init(struct aq_ring_s *self, const enum atl_ring_type ring_type); + void aq_ring_rx_deinit(struct aq_ring_s *self); + void aq_ring_free(struct aq_ring_s *self); + void aq_ring_update_queue_state(struct aq_ring_s *ring); +@@ -181,4 +187,6 @@ struct aq_ring_s *aq_ring_hwts_rx_alloc(struct aq_ring_s *self, + unsigned int size, unsigned int dx_size); + void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic); + ++unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data); ++ + #endif /* AQ_RING_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +index 8f0a0d18e711..b008d12e923a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +@@ -181,7 +181,7 @@ int aq_vec_init(struct aq_vec_s *self, const struct aq_hw_ops *aq_hw_ops, + + for (i = 0U, ring = self->ring[0]; + self->tx_rings > i; ++i, ring = self->ring[i]) { +- err = aq_ring_init(&ring[AQ_VEC_TX_ID]); ++ err = aq_ring_init(&ring[AQ_VEC_TX_ID], ATL_RING_TX); + if (err < 0) + goto err_exit; + +@@ -191,7 +191,7 @@ int aq_vec_init(struct aq_vec_s *self, const struct aq_hw_ops *aq_hw_ops, + if (err < 0) + goto err_exit; + +- err = aq_ring_init(&ring[AQ_VEC_RX_ID]); ++ err = aq_ring_init(&ring[AQ_VEC_RX_ID], ATL_RING_RX); + if (err < 0) + goto err_exit; + +@@ -350,55 +350,23 @@ cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self) + return &self->aq_ring_param.affinity_mask; + } + +-static void aq_vec_get_stats(struct aq_vec_s *self, +- const unsigned int tc, +- struct aq_ring_stats_rx_s *stats_rx, +- struct aq_ring_stats_tx_s *stats_tx) ++bool aq_vec_is_valid_tc(struct aq_vec_s *self, const unsigned int tc) + { +- struct aq_ring_s *ring = self->ring[tc]; +- +- if (tc < self->rx_rings) { +- struct aq_ring_stats_rx_s *rx = &ring[AQ_VEC_RX_ID].stats.rx; +- +- stats_rx->packets = rx->packets; +- stats_rx->bytes = rx->bytes; +- stats_rx->errors = rx->errors; +- stats_rx->jumbo_packets = rx->jumbo_packets; +- stats_rx->lro_packets = rx->lro_packets; +- stats_rx->pg_losts = rx->pg_losts; +- stats_rx->pg_flips = rx->pg_flips; +- stats_rx->pg_reuses = rx->pg_reuses; +- } +- +- if (tc < self->tx_rings) { +- struct aq_ring_stats_tx_s *tx = &ring[AQ_VEC_TX_ID].stats.tx; +- +- stats_tx->packets = tx->packets; +- stats_tx->bytes = tx->bytes; +- stats_tx->errors = tx->errors; +- stats_tx->queue_restarts = tx->queue_restarts; +- } ++ return tc < self->rx_rings && tc < self->tx_rings; + } + + unsigned int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data) + { +- struct aq_ring_stats_rx_s stats_rx; +- struct aq_ring_stats_tx_s stats_tx; +- unsigned int count = 0U; +- +- memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s)); +- memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s)); ++ unsigned int count; + +- aq_vec_get_stats(self, tc, &stats_rx, &stats_tx); ++ WARN_ONCE(!aq_vec_is_valid_tc(self, tc), ++ "Invalid tc %u (#rx=%u, #tx=%u)\n", ++ tc, self->rx_rings, self->tx_rings); ++ if (!aq_vec_is_valid_tc(self, tc)) ++ return 0; + +- /* This data should mimic aq_ethtool_queue_stat_names structure +- */ +- data[count] = stats_rx.packets; +- data[++count] = stats_tx.packets; +- data[++count] = stats_tx.queue_restarts; +- data[++count] = stats_rx.jumbo_packets; +- data[++count] = stats_rx.lro_packets; +- data[++count] = stats_rx.errors; ++ count = aq_ring_fill_stats_data(&self->ring[tc][AQ_VEC_RX_ID], data); ++ count += aq_ring_fill_stats_data(&self->ring[tc][AQ_VEC_TX_ID], data + count); + +- return ++count; ++ return count; + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.h b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h +index c079fef80da8..567f3d4b79a2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h +@@ -36,6 +36,7 @@ void aq_vec_ring_free(struct aq_vec_s *self); + int aq_vec_start(struct aq_vec_s *self); + void aq_vec_stop(struct aq_vec_s *self); + cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self); ++bool aq_vec_is_valid_tc(struct aq_vec_s *self, const unsigned int tc); + unsigned int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data); + + #endif /* AQ_VEC_H */ +-- +2.13.6 + diff --git a/SOURCES/0127-netdrv-net-atlantic-use-u64_stats_update_-to-protect.patch b/SOURCES/0127-netdrv-net-atlantic-use-u64_stats_update_-to-protect.patch new file mode 100644 index 0000000..cb1a889 --- /dev/null +++ b/SOURCES/0127-netdrv-net-atlantic-use-u64_stats_update_-to-protect.patch @@ -0,0 +1,234 @@ +From 485a6ea4fe3f045dd713bfdf9b428103106a209e Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:24 -0500 +Subject: [PATCH 127/139] [netdrv] net: atlantic: use u64_stats_update_* to + protect access to 64-bit stats + +Message-id: <1604687916-15087-128-git-send-email-irusskik@redhat.com> +Patchwork-id: 338551 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 127/139] net: atlantic: use u64_stats_update_* to protect access to 64-bit stats +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit d7d8bb9286134bcc57941c38ed2d69c50fc59511 +Author: Mark Starovoytov +Date: Mon Jul 20 21:32:36 2020 +0300 + + net: atlantic: use u64_stats_update_* to protect access to 64-bit stats + + This patch adds u64_stats_update_* usage to protect access to 64-bit stats, + where necessary. + + This is necessary for per-ring stats, because they are updated by the + driver directly, so there is a possibility for a partial read. + + Other stats require no additional protection, e.g.: + * all MACSec stats are fetched directly from HW (under semaphore); + * nic/ndev stats (aq_stats_s) are fetched directly from FW (under mutex). + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 2 ++ + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 46 ++++++++++++++++++++---- + drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 9 +++-- + 3 files changed, 47 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index 116b8891c9c4..ec6aa9bb7dfc 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -782,8 +782,10 @@ int aq_ptp_xmit(struct aq_nic_s *aq_nic, struct sk_buff *skb) + err = aq_nic->aq_hw_ops->hw_ring_tx_xmit(aq_nic->aq_hw, + ring, frags); + if (err >= 0) { ++ u64_stats_update_begin(&ring->stats.tx.syncp); + ++ring->stats.tx.packets; + ring->stats.tx.bytes += skb->len; ++ u64_stats_update_end(&ring->stats.tx.syncp); + } + } else { + err = NETDEV_TX_BUSY; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index fc4e10b064fd..b51ab2dbf6fe 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -70,18 +70,24 @@ static int aq_get_rxpages(struct aq_ring_s *self, struct aq_ring_buff_s *rxbuf, + rxbuf->rxdata.pg_off += AQ_CFG_RX_FRAME_MAX; + if (rxbuf->rxdata.pg_off + AQ_CFG_RX_FRAME_MAX <= + (PAGE_SIZE << order)) { ++ u64_stats_update_begin(&self->stats.rx.syncp); + self->stats.rx.pg_flips++; ++ u64_stats_update_end(&self->stats.rx.syncp); + } else { + /* Buffer exhausted. We have other users and + * should release this page and realloc + */ + aq_free_rxpage(&rxbuf->rxdata, + aq_nic_get_dev(self->aq_nic)); ++ u64_stats_update_begin(&self->stats.rx.syncp); + self->stats.rx.pg_losts++; ++ u64_stats_update_end(&self->stats.rx.syncp); + } + } else { + rxbuf->rxdata.pg_off = 0; ++ u64_stats_update_begin(&self->stats.rx.syncp); + self->stats.rx.pg_reuses++; ++ u64_stats_update_end(&self->stats.rx.syncp); + } + } + +@@ -213,6 +219,11 @@ int aq_ring_init(struct aq_ring_s *self, const enum atl_ring_type ring_type) + self->sw_tail = 0; + self->ring_type = ring_type; + ++ if (self->ring_type == ATL_RING_RX) ++ u64_stats_init(&self->stats.rx.syncp); ++ else ++ u64_stats_init(&self->stats.tx.syncp); ++ + return 0; + } + +@@ -239,7 +250,9 @@ void aq_ring_queue_wake(struct aq_ring_s *ring) + ring->idx))) { + netif_wake_subqueue(ndev, + AQ_NIC_RING2QMAP(ring->aq_nic, ring->idx)); ++ u64_stats_update_begin(&ring->stats.tx.syncp); + ring->stats.tx.queue_restarts++; ++ u64_stats_update_end(&ring->stats.tx.syncp); + } + } + +@@ -281,8 +294,10 @@ bool aq_ring_tx_clean(struct aq_ring_s *self) + } + + if (unlikely(buff->is_eop)) { ++ u64_stats_update_begin(&self->stats.tx.syncp); + ++self->stats.tx.packets; + self->stats.tx.bytes += buff->skb->len; ++ u64_stats_update_end(&self->stats.tx.syncp); + + dev_kfree_skb_any(buff->skb); + } +@@ -302,7 +317,9 @@ static void aq_rx_checksum(struct aq_ring_s *self, + return; + + if (unlikely(buff->is_cso_err)) { ++ u64_stats_update_begin(&self->stats.rx.syncp); + ++self->stats.rx.errors; ++ u64_stats_update_end(&self->stats.rx.syncp); + skb->ip_summed = CHECKSUM_NONE; + return; + } +@@ -372,13 +389,17 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + buff_->is_cleaned = true; + } while (!buff_->is_eop); + ++ u64_stats_update_begin(&self->stats.rx.syncp); + ++self->stats.rx.errors; ++ u64_stats_update_end(&self->stats.rx.syncp); + continue; + } + } + + if (buff->is_error) { ++ u64_stats_update_begin(&self->stats.rx.syncp); + ++self->stats.rx.errors; ++ u64_stats_update_end(&self->stats.rx.syncp); + continue; + } + +@@ -479,8 +500,10 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + : AQ_NIC_RING2QMAP(self->aq_nic, + self->idx)); + ++ u64_stats_update_begin(&self->stats.rx.syncp); + ++self->stats.rx.packets; + self->stats.rx.bytes += skb->len; ++ u64_stats_update_end(&self->stats.rx.syncp); + + napi_gro_receive(napi, skb); + } +@@ -564,18 +587,27 @@ void aq_ring_free(struct aq_ring_s *self) + + unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data) + { +- unsigned int count = 0U; ++ unsigned int count; ++ unsigned int start; + + if (self->ring_type == ATL_RING_RX) { + /* This data should mimic aq_ethtool_queue_rx_stat_names structure */ +- data[count] = self->stats.rx.packets; +- data[++count] = self->stats.rx.jumbo_packets; +- data[++count] = self->stats.rx.lro_packets; +- data[++count] = self->stats.rx.errors; ++ do { ++ count = 0; ++ start = u64_stats_fetch_begin_irq(&self->stats.rx.syncp); ++ data[count] = self->stats.rx.packets; ++ data[++count] = self->stats.rx.jumbo_packets; ++ data[++count] = self->stats.rx.lro_packets; ++ data[++count] = self->stats.rx.errors; ++ } while (u64_stats_fetch_retry_irq(&self->stats.rx.syncp, start)); + } else { + /* This data should mimic aq_ethtool_queue_tx_stat_names structure */ +- data[count] = self->stats.tx.packets; +- data[++count] = self->stats.tx.queue_restarts; ++ do { ++ count = 0; ++ start = u64_stats_fetch_begin_irq(&self->stats.tx.syncp); ++ data[count] = self->stats.tx.packets; ++ data[++count] = self->stats.tx.queue_restarts; ++ } while (u64_stats_fetch_retry_irq(&self->stats.tx.syncp, start)); + } + + return ++count; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +index 0cd761ba47a3..c92c3a0651a9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +@@ -1,7 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_ring.h: Declaration of functions for Rx/Tx rings. */ +@@ -88,6 +89,7 @@ struct __packed aq_ring_buff_s { + }; + + struct aq_ring_stats_rx_s { ++ struct u64_stats_sync syncp; /* must be first */ + u64 errors; + u64 packets; + u64 bytes; +@@ -99,6 +101,7 @@ struct aq_ring_stats_rx_s { + }; + + struct aq_ring_stats_tx_s { ++ struct u64_stats_sync syncp; /* must be first */ + u64 errors; + u64 packets; + u64 bytes; +-- +2.13.6 + diff --git a/SOURCES/0128-netdrv-net-atlantic-additional-per-queue-stats.patch b/SOURCES/0128-netdrv-net-atlantic-additional-per-queue-stats.patch new file mode 100644 index 0000000..dfe9592 --- /dev/null +++ b/SOURCES/0128-netdrv-net-atlantic-additional-per-queue-stats.patch @@ -0,0 +1,133 @@ +From 8b0e108114e05a669dfea6bfdb928a52779e204b Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:25 -0500 +Subject: [PATCH 128/139] [netdrv] net: atlantic: additional per-queue stats + +Message-id: <1604687916-15087-129-git-send-email-irusskik@redhat.com> +Patchwork-id: 338553 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 128/139] net: atlantic: additional per-queue stats +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit aa7e17a3e35a6e3fbf4ab2055a64097efcd09310 +Author: Dmitry Bogdanov +Date: Mon Jul 20 21:32:37 2020 +0300 + + net: atlantic: additional per-queue stats + + This patch adds additional per-queue stats, these could + be useful for debugging and diagnostics. + + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 3 +++ + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 14 ++++++++++++++ + drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 3 +++ + drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 3 +++ + 4 files changed, 23 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 458491ef24b9..4f7a2ff4da85 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -93,6 +93,9 @@ static const char * const aq_ethtool_queue_rx_stat_names[] = { + "%sQueue[%d] InJumboPackets", + "%sQueue[%d] InLroPackets", + "%sQueue[%d] InErrors", ++ "%sQueue[%d] AllocFails", ++ "%sQueue[%d] SkbAllocFails", ++ "%sQueue[%d] Polls", + }; + + static const char * const aq_ethtool_queue_tx_stat_names[] = { +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index b51ab2dbf6fe..4f913658eea4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -94,6 +94,11 @@ static int aq_get_rxpages(struct aq_ring_s *self, struct aq_ring_buff_s *rxbuf, + if (!rxbuf->rxdata.page) { + ret = aq_get_rxpage(&rxbuf->rxdata, order, + aq_nic_get_dev(self->aq_nic)); ++ if (ret) { ++ u64_stats_update_begin(&self->stats.rx.syncp); ++ self->stats.rx.alloc_fails++; ++ u64_stats_update_end(&self->stats.rx.syncp); ++ } + return ret; + } + +@@ -414,6 +419,9 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + skb = build_skb(aq_buf_vaddr(&buff->rxdata), + AQ_CFG_RX_FRAME_MAX); + if (unlikely(!skb)) { ++ u64_stats_update_begin(&self->stats.rx.syncp); ++ self->stats.rx.skb_alloc_fails++; ++ u64_stats_update_end(&self->stats.rx.syncp); + err = -ENOMEM; + goto err_exit; + } +@@ -427,6 +435,9 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + } else { + skb = napi_alloc_skb(napi, AQ_CFG_RX_HDR_SIZE); + if (unlikely(!skb)) { ++ u64_stats_update_begin(&self->stats.rx.syncp); ++ self->stats.rx.skb_alloc_fails++; ++ u64_stats_update_end(&self->stats.rx.syncp); + err = -ENOMEM; + goto err_exit; + } +@@ -599,6 +610,9 @@ unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data) + data[++count] = self->stats.rx.jumbo_packets; + data[++count] = self->stats.rx.lro_packets; + data[++count] = self->stats.rx.errors; ++ data[++count] = self->stats.rx.alloc_fails; ++ data[++count] = self->stats.rx.skb_alloc_fails; ++ data[++count] = self->stats.rx.polls; + } while (u64_stats_fetch_retry_irq(&self->stats.rx.syncp, start)); + } else { + /* This data should mimic aq_ethtool_queue_tx_stat_names structure */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +index c92c3a0651a9..93659e58f1ce 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +@@ -95,6 +95,9 @@ struct aq_ring_stats_rx_s { + u64 bytes; + u64 lro_packets; + u64 jumbo_packets; ++ u64 alloc_fails; ++ u64 skb_alloc_fails; ++ u64 polls; + u64 pg_losts; + u64 pg_flips; + u64 pg_reuses; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +index b008d12e923a..d281322d7dd2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +@@ -45,6 +45,9 @@ static int aq_vec_poll(struct napi_struct *napi, int budget) + } else { + for (i = 0U, ring = self->ring[0]; + self->tx_rings > i; ++i, ring = self->ring[i]) { ++ u64_stats_update_begin(&ring[AQ_VEC_RX_ID].stats.rx.syncp); ++ ring[AQ_VEC_RX_ID].stats.rx.polls++; ++ u64_stats_update_end(&ring[AQ_VEC_RX_ID].stats.rx.syncp); + if (self->aq_hw_ops->hw_ring_tx_head_update) { + err = self->aq_hw_ops->hw_ring_tx_head_update( + self->aq_hw, +-- +2.13.6 + diff --git a/SOURCES/0129-netdrv-net-atlantic-PTP-statistics.patch b/SOURCES/0129-netdrv-net-atlantic-PTP-statistics.patch new file mode 100644 index 0000000..d770b51 --- /dev/null +++ b/SOURCES/0129-netdrv-net-atlantic-PTP-statistics.patch @@ -0,0 +1,273 @@ +From 8610fc76abb8da9be16ef3a36e457b0c19093545 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:26 -0500 +Subject: [PATCH 129/139] [netdrv] net: atlantic: PTP statistics + +Message-id: <1604687916-15087-130-git-send-email-irusskik@redhat.com> +Patchwork-id: 338557 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 129/139] net: atlantic: PTP statistics +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 14b539a3490102750c86a63a8f27a69935e6a84e +Author: Pavel Belous +Date: Mon Jul 20 21:32:38 2020 +0300 + + net: atlantic: PTP statistics + + This patch adds PTP rings statistics. Before that + these were missing from overall stats, hardening debugging + and analysis. + + Signed-off-by: Pavel Belous + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/aq_ethtool.c | 37 +++++++++++++ + drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 60 ++++++++++++++++------ + drivers/net/ethernet/aquantia/atlantic/aq_ptp.h | 27 +++++++++- + 3 files changed, 105 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +index 4f7a2ff4da85..204587980b6a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +@@ -120,6 +120,11 @@ static u32 aq_ethtool_n_stats(struct net_device *ndev) + u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) + + (rx_stat_cnt + tx_stat_cnt) * cfg->vecs * cfg->tcs; + ++#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) ++ n_stats += rx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_RX) + ++ tx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_TX); ++#endif ++ + return n_stats; + } + +@@ -130,6 +135,9 @@ static void aq_ethtool_stats(struct net_device *ndev, + + memset(data, 0, aq_ethtool_n_stats(ndev) * sizeof(u64)); + data = aq_nic_get_stats(aq_nic, data); ++#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) ++ data = aq_ptp_get_stats(aq_nic, data); ++#endif + } + + static void aq_ethtool_get_drvinfo(struct net_device *ndev, +@@ -200,6 +208,35 @@ static void aq_ethtool_get_strings(struct net_device *ndev, + } + } + } ++#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) ++ if (nic->aq_ptp) { ++ const int rx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_RX); ++ const int tx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_TX); ++ unsigned int ptp_ring_idx = ++ aq_ptp_ring_idx(nic->aq_nic_cfg.tc_mode); ++ ++ snprintf(tc_string, 8, "PTP "); ++ ++ for (i = 0; i < max(rx_ring_cnt, tx_ring_cnt); i++) { ++ for (si = 0; si < rx_stat_cnt; si++) { ++ snprintf(p, ETH_GSTRING_LEN, ++ aq_ethtool_queue_rx_stat_names[si], ++ tc_string, ++ i ? PTP_HWST_RING_IDX : ptp_ring_idx); ++ p += ETH_GSTRING_LEN; ++ } ++ if (i >= tx_ring_cnt) ++ continue; ++ for (si = 0; si < tx_stat_cnt; si++) { ++ snprintf(p, ETH_GSTRING_LEN, ++ aq_ethtool_queue_tx_stat_names[si], ++ tc_string, ++ i ? PTP_HWST_RING_IDX : ptp_ring_idx); ++ p += ETH_GSTRING_LEN; ++ } ++ } ++ } ++#endif + break; + } + case ETH_SS_PRIV_FLAGS: +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index ec6aa9bb7dfc..06de19f63287 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -81,6 +81,8 @@ struct aq_ptp_s { + + bool extts_pin_enabled; + u64 last_sync1588_ts; ++ ++ bool a1_ptp; + }; + + struct ptp_tm_offset { +@@ -947,21 +949,6 @@ void aq_ptp_ring_deinit(struct aq_nic_s *aq_nic) + aq_ring_rx_deinit(&aq_ptp->ptp_rx); + } + +-#define PTP_8TC_RING_IDX 8 +-#define PTP_4TC_RING_IDX 16 +-#define PTP_HWST_RING_IDX 31 +- +-/* Index must be 8 (8 TCs) or 16 (4 TCs). +- * It depends on Traffic Class mode. +- */ +-static unsigned int ptp_ring_idx(const enum aq_tc_mode tc_mode) +-{ +- if (tc_mode == AQ_TC_MODE_8TCS) +- return PTP_8TC_RING_IDX; +- +- return PTP_4TC_RING_IDX; +-} +- + int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic) + { + struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; +@@ -973,7 +960,7 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic) + if (!aq_ptp) + return 0; + +- tx_ring_idx = ptp_ring_idx(aq_nic->aq_nic_cfg.tc_mode); ++ tx_ring_idx = aq_ptp_ring_idx(aq_nic->aq_nic_cfg.tc_mode); + + ring = aq_ring_tx_alloc(&aq_ptp->ptp_tx, aq_nic, + tx_ring_idx, &aq_nic->aq_nic_cfg); +@@ -982,7 +969,7 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic) + goto err_exit; + } + +- rx_ring_idx = ptp_ring_idx(aq_nic->aq_nic_cfg.tc_mode); ++ rx_ring_idx = aq_ptp_ring_idx(aq_nic->aq_nic_cfg.tc_mode); + + ring = aq_ring_rx_alloc(&aq_ptp->ptp_rx, aq_nic, + rx_ring_idx, &aq_nic->aq_nic_cfg); +@@ -1174,11 +1161,17 @@ static void aq_ptp_poll_sync_work_cb(struct work_struct *w); + + int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + { ++ bool a1_ptp = ATL_HW_IS_CHIP_FEATURE(aq_nic->aq_hw, ATLANTIC); + struct hw_atl_utils_mbox mbox; + struct ptp_clock *clock; + struct aq_ptp_s *aq_ptp; + int err = 0; + ++ if (!a1_ptp) { ++ aq_nic->aq_ptp = NULL; ++ return 0; ++ } ++ + if (!aq_nic->aq_hw_ops->hw_get_ptp_ts) { + aq_nic->aq_ptp = NULL; + return 0; +@@ -1205,6 +1198,7 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) + } + + aq_ptp->aq_nic = aq_nic; ++ aq_ptp->a1_ptp = a1_ptp; + + spin_lock_init(&aq_ptp->ptp_lock); + spin_lock_init(&aq_ptp->ptp_ring_lock); +@@ -1395,4 +1389,36 @@ static void aq_ptp_poll_sync_work_cb(struct work_struct *w) + schedule_delayed_work(&aq_ptp->poll_sync, timeout); + } + } ++ ++int aq_ptp_get_ring_cnt(struct aq_nic_s *aq_nic, const enum atl_ring_type ring_type) ++{ ++ if (!aq_nic->aq_ptp) ++ return 0; ++ ++ /* Additional RX ring is allocated for PTP HWTS on A1 */ ++ return (aq_nic->aq_ptp->a1_ptp && ring_type == ATL_RING_RX) ? 2 : 1; ++} ++ ++u64 *aq_ptp_get_stats(struct aq_nic_s *aq_nic, u64 *data) ++{ ++ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp; ++ unsigned int count = 0U; ++ ++ if (!aq_ptp) ++ return data; ++ ++ count = aq_ring_fill_stats_data(&aq_ptp->ptp_rx, data); ++ data += count; ++ count = aq_ring_fill_stats_data(&aq_ptp->ptp_tx, data); ++ data += count; ++ ++ if (aq_ptp->a1_ptp) { ++ /* Only Receive ring for HWTS */ ++ count = aq_ring_fill_stats_data(&aq_ptp->hwts_rx, data); ++ data += count; ++ } ++ ++ return data; ++} ++ + #endif +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +index 231906431a48..28ccb7ca2df9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h +@@ -1,6 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* Aquantia Corporation Network Driver +- * Copyright (C) 2014-2019 Aquantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_ptp.h: Declaration of PTP functions. +@@ -10,6 +12,23 @@ + + #include + ++#include "aq_ring.h" ++ ++#define PTP_8TC_RING_IDX 8 ++#define PTP_4TC_RING_IDX 16 ++#define PTP_HWST_RING_IDX 31 ++ ++/* Index must to be 8 (8 TCs) or 16 (4 TCs). ++ * It depends from Traffic Class mode. ++ */ ++static inline unsigned int aq_ptp_ring_idx(const enum aq_tc_mode tc_mode) ++{ ++ if (tc_mode == AQ_TC_MODE_8TCS) ++ return PTP_8TC_RING_IDX; ++ ++ return PTP_4TC_RING_IDX; ++} ++ + #if IS_REACHABLE(CONFIG_PTP_1588_CLOCK) + + /* Common functions */ +@@ -55,6 +74,10 @@ struct ptp_clock *aq_ptp_get_ptp_clock(struct aq_ptp_s *aq_ptp); + + int aq_ptp_link_change(struct aq_nic_s *aq_nic); + ++/* PTP ring statistics */ ++int aq_ptp_get_ring_cnt(struct aq_nic_s *aq_nic, const enum atl_ring_type ring_type); ++u64 *aq_ptp_get_stats(struct aq_nic_s *aq_nic, u64 *data); ++ + #else + + static inline int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec) +-- +2.13.6 + diff --git a/SOURCES/0130-netdrv-net-atlantic-enable-ipv6-support-for-TCP-LSO-.patch b/SOURCES/0130-netdrv-net-atlantic-enable-ipv6-support-for-TCP-LSO-.patch new file mode 100644 index 0000000..5097317 --- /dev/null +++ b/SOURCES/0130-netdrv-net-atlantic-enable-ipv6-support-for-TCP-LSO-.patch @@ -0,0 +1,71 @@ +From c20ec2bb6bd0fafcfbeff285ac2f9989290009d1 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:27 -0500 +Subject: [PATCH 130/139] [netdrv] net: atlantic: enable ipv6 support for TCP + LSO and UDP GSO + +Message-id: <1604687916-15087-131-git-send-email-irusskik@redhat.com> +Patchwork-id: 338554 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 130/139] net: atlantic: enable ipv6 support for TCP LSO and UDP GSO +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 8bd60710852fffe4c32b5b7f84de2a6c19d12971 +Author: Igor Russkikh +Date: Mon Jul 20 21:32:39 2020 +0300 + + net: atlantic: enable ipv6 support for TCP LSO and UDP GSO + + This patch enables ipv6 support for TCP LSO and UDP GSO. + The code itself (aq_nic_map_skb) was ready for this after udp gso feature, + but corresponding NETIF_F_TSO6 wasn't enabled. + + We now have tested both tcp and udp v6 GSO, and enabling them safely. + + Signed-off-by: Igor Russkikh + Signed-off-by: Mark Starovoytov + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 2 +- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 7cb2b863d7ac..697ee932787b 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -355,7 +355,7 @@ void aq_nic_ndev_init(struct aq_nic_s *self) + self->ndev->features = aq_hw_caps->hw_features; + self->ndev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM | + NETIF_F_RXHASH | NETIF_F_SG | +- NETIF_F_LRO | NETIF_F_TSO; ++ NETIF_F_LRO | NETIF_F_TSO | NETIF_F_TSO6; + self->ndev->gso_partial_features = NETIF_F_GSO_UDP_L4; + self->ndev->priv_flags = aq_hw_caps->hw_priv_flags; + self->ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 6569bdcea69d..732b570b40d6 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -40,6 +40,7 @@ + NETIF_F_RXHASH | \ + NETIF_F_SG | \ + NETIF_F_TSO | \ ++ NETIF_F_TSO6 | \ + NETIF_F_LRO | \ + NETIF_F_NTUPLE | \ + NETIF_F_HW_VLAN_CTAG_FILTER | \ +-- +2.13.6 + diff --git a/SOURCES/0131-netdrv-net-atlantic-add-support-for-64-bit-reads-wri.patch b/SOURCES/0131-netdrv-net-atlantic-add-support-for-64-bit-reads-wri.patch new file mode 100644 index 0000000..cfe1c2c --- /dev/null +++ b/SOURCES/0131-netdrv-net-atlantic-add-support-for-64-bit-reads-wri.patch @@ -0,0 +1,177 @@ +From cadf1e919c3bc0dd43d514f27fff497cf61efc80 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:28 -0500 +Subject: [PATCH 131/139] [netdrv] net: atlantic: add support for 64-bit + reads/writes + +Message-id: <1604687916-15087-132-git-send-email-irusskik@redhat.com> +Patchwork-id: 338556 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 131/139] net: atlantic: add support for 64-bit reads/writes +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 1e41b3fee795faa8a67713749a21e60828ae21ad +Author: Pavel Belous +Date: Mon Jul 20 21:32:40 2020 +0300 + + net: atlantic: add support for 64-bit reads/writes + + This patch adds support for 64-bit reads/writes where applicable, e.g. + A2 supports them. + + Signed-off-by: Pavel Belous + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 1 + + .../net/ethernet/aquantia/atlantic/aq_hw_utils.c | 29 ++++++++++++++++++---- + .../net/ethernet/aquantia/atlantic/aq_hw_utils.h | 8 +++--- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 1 + + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 1 + + .../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 1 + + 6 files changed, 33 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index 986f13809ad5..9d0c43325fc3 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -67,6 +67,7 @@ struct aq_hw_caps_s { + u8 rx_rings; + bool flow_control; + bool is_64_dma; ++ bool op64bit; + u32 quirks; + u32 priv_data_len; + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +index 342c5179f846..ae85c0a7d238 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +@@ -1,7 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_hw_utils.c: Definitions of helper functions used across +@@ -9,6 +10,9 @@ + */ + + #include "aq_hw_utils.h" ++ ++#include ++ + #include "aq_hw.h" + #include "aq_nic.h" + +@@ -56,13 +60,28 @@ void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value) + */ + u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg) + { +- u64 value = aq_hw_read_reg(hw, reg); ++ u64 value = U64_MAX; + +- value |= (u64)aq_hw_read_reg(hw, reg + 4) << 32; ++ if (hw->aq_nic_cfg->aq_hw_caps->op64bit) ++ value = readq(hw->mmio + reg); ++ else ++ value = lo_hi_readq(hw->mmio + reg); ++ ++ if (value == U64_MAX && ++ readl(hw->mmio + hw->aq_nic_cfg->aq_hw_caps->hw_alive_check_addr) == U32_MAX) ++ aq_utils_obj_set(&hw->flags, AQ_HW_FLAG_ERR_UNPLUG); + + return value; + } + ++void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value) ++{ ++ if (hw->aq_nic_cfg->aq_hw_caps->op64bit) ++ writeq(value, hw->mmio + reg); ++ else ++ lo_hi_writeq(value, hw->mmio + reg); ++} ++ + int aq_hw_err_from_flags(struct aq_hw_s *hw) + { + int err = 0; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +index 32aa5f2fb840..ffa6e4067c21 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +@@ -1,7 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * aQuantia Corporation Network Driver +- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. + */ + + /* File aq_hw_utils.h: Declaration of helper functions used across hardware +@@ -33,6 +34,7 @@ u32 aq_hw_read_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, u32 shift); + u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value); + u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg); ++void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value); + int aq_hw_err_from_flags(struct aq_hw_s *hw); + int aq_hw_num_tcs(struct aq_hw_s *hw); + int aq_hw_q_per_tc(struct aq_hw_s *hw); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index a312864969af..8f8b90436ced 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -18,6 +18,7 @@ + + #define DEFAULT_A0_BOARD_BASIC_CAPABILITIES \ + .is_64_dma = true, \ ++ .op64bit = false, \ + .msix_irqs = 4U, \ + .irq_mask = ~0U, \ + .vecs = HW_ATL_A0_RSS_MAX, \ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 732b570b40d6..59297e971ade 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -20,6 +20,7 @@ + + #define DEFAULT_B0_BOARD_BASIC_CAPABILITIES \ + .is_64_dma = true, \ ++ .op64bit = false, \ + .msix_irqs = 8U, \ + .irq_mask = ~0U, \ + .vecs = HW_ATL_B0_RSS_MAX, \ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index c65e6daad0e5..92f64048bf69 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -21,6 +21,7 @@ static int hw_atl2_act_rslvr_table_set(struct aq_hw_s *self, u8 location, + + #define DEFAULT_BOARD_BASIC_CAPABILITIES \ + .is_64_dma = true, \ ++ .op64bit = true, \ + .msix_irqs = 8U, \ + .irq_mask = ~0U, \ + .vecs = HW_ATL2_RSS_MAX, \ +-- +2.13.6 + diff --git a/SOURCES/0132-netdrv-net-atlantic-use-U32_MAX-in-aq_hw_utils.c.patch b/SOURCES/0132-netdrv-net-atlantic-use-U32_MAX-in-aq_hw_utils.c.patch new file mode 100644 index 0000000..de41ea0 --- /dev/null +++ b/SOURCES/0132-netdrv-net-atlantic-use-U32_MAX-in-aq_hw_utils.c.patch @@ -0,0 +1,56 @@ +From ff88b058f5c23feb6ed26c83db96d8aa397dce2b Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:29 -0500 +Subject: [PATCH 132/139] [netdrv] net: atlantic: use U32_MAX in aq_hw_utils.c + +Message-id: <1604687916-15087-133-git-send-email-irusskik@redhat.com> +Patchwork-id: 338552 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 132/139] net: atlantic: use U32_MAX in aq_hw_utils.c +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 88bc9cf143a1f34978bcda21114cc81324c9e118 +Author: Mark Starovoytov +Date: Mon Jul 20 21:32:41 2020 +0300 + + net: atlantic: use U32_MAX in aq_hw_utils.c + + This patch replaces magic constant ~0U usage with U32_MAX in aq_hw_utils.c + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +index ae85c0a7d238..1921741f7311 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +@@ -41,9 +41,8 @@ u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg) + { + u32 value = readl(hw->mmio + reg); + +- if ((~0U) == value && +- (~0U) == readl(hw->mmio + +- hw->aq_nic_cfg->aq_hw_caps->hw_alive_check_addr)) ++ if (value == U32_MAX && ++ readl(hw->mmio + hw->aq_nic_cfg->aq_hw_caps->hw_alive_check_addr) == U32_MAX) + aq_utils_obj_set(&hw->flags, AQ_HW_FLAG_ERR_UNPLUG); + + return value; +-- +2.13.6 + diff --git a/SOURCES/0133-netdrv-net-atlantic-use-intermediate-variable-to-imp.patch b/SOURCES/0133-netdrv-net-atlantic-use-intermediate-variable-to-imp.patch new file mode 100644 index 0000000..c6edd56 --- /dev/null +++ b/SOURCES/0133-netdrv-net-atlantic-use-intermediate-variable-to-imp.patch @@ -0,0 +1,108 @@ +From 4ec7dbfa26afe3372c14fb1e5912da447637dd18 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:30 -0500 +Subject: [PATCH 133/139] [netdrv] net: atlantic: use intermediate variable to + improve readability a bit + +Message-id: <1604687916-15087-134-git-send-email-irusskik@redhat.com> +Patchwork-id: 338562 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 133/139] net: atlantic: use intermediate variable to improve readability a bit +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit b98ffe6fa415a6ea5cbc7e8d58dd016e83fe33ea +Author: Nikita Danilov +Date: Mon Jul 20 21:32:42 2020 +0300 + + net: atlantic: use intermediate variable to improve readability a bit + + This patch syncs up hw_atl_a0.c with an out-of-tree driver, where an + intermediate variable was introduced in a couple of functions to + improve the code readability a bit. + + Signed-off-by: Nikita Danilov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 21 ++++++++++----------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index 8f8b90436ced..e1877d520135 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -752,6 +752,7 @@ static int hw_atl_a0_hw_irq_read(struct aq_hw_s *self, u64 *mask) + static int hw_atl_a0_hw_packet_filter_set(struct aq_hw_s *self, + unsigned int packet_filter) + { ++ struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; + unsigned int i = 0U; + + hw_atl_rpfl2promiscuous_mode_en_set(self, +@@ -760,14 +761,13 @@ static int hw_atl_a0_hw_packet_filter_set(struct aq_hw_s *self, + IS_FILTER_ENABLED(IFF_MULTICAST), 0); + hw_atl_rpfl2broadcast_en_set(self, IS_FILTER_ENABLED(IFF_BROADCAST)); + +- self->aq_nic_cfg->is_mc_list_enabled = +- IS_FILTER_ENABLED(IFF_MULTICAST); ++ cfg->is_mc_list_enabled = IS_FILTER_ENABLED(IFF_MULTICAST); + + for (i = HW_ATL_A0_MAC_MIN; i < HW_ATL_A0_MAC_MAX; ++i) + hw_atl_rpfl2_uc_flr_en_set(self, +- (self->aq_nic_cfg->is_mc_list_enabled && +- (i <= self->aq_nic_cfg->mc_list_count)) ? +- 1U : 0U, i); ++ (cfg->is_mc_list_enabled && ++ (i <= cfg->mc_list_count)) ? 1U : 0U, ++ i); + + return aq_hw_err_from_flags(self); + } +@@ -780,19 +780,18 @@ static int hw_atl_a0_hw_multicast_list_set(struct aq_hw_s *self, + [ETH_ALEN], + u32 count) + { ++ struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; + int err = 0; + + if (count > (HW_ATL_A0_MAC_MAX - HW_ATL_A0_MAC_MIN)) { + err = EBADRQC; + goto err_exit; + } +- for (self->aq_nic_cfg->mc_list_count = 0U; +- self->aq_nic_cfg->mc_list_count < count; +- ++self->aq_nic_cfg->mc_list_count) { +- u32 i = self->aq_nic_cfg->mc_list_count; ++ for (cfg->mc_list_count = 0U; cfg->mc_list_count < count; ++cfg->mc_list_count) { ++ u32 i = cfg->mc_list_count; + u32 h = (ar_mac[i][0] << 8) | (ar_mac[i][1]); + u32 l = (ar_mac[i][2] << 24) | (ar_mac[i][3] << 16) | +- (ar_mac[i][4] << 8) | ar_mac[i][5]; ++ (ar_mac[i][4] << 8) | ar_mac[i][5]; + + hw_atl_rpfl2_uc_flr_en_set(self, 0U, HW_ATL_A0_MAC_MIN + i); + +@@ -805,7 +804,7 @@ static int hw_atl_a0_hw_multicast_list_set(struct aq_hw_s *self, + HW_ATL_A0_MAC_MIN + i); + + hw_atl_rpfl2_uc_flr_en_set(self, +- (self->aq_nic_cfg->is_mc_list_enabled), ++ (cfg->is_mc_list_enabled), + HW_ATL_A0_MAC_MIN + i); + } + +-- +2.13.6 + diff --git a/SOURCES/0134-netdrv-net-atlantic-A0-ntuple-filters.patch b/SOURCES/0134-netdrv-net-atlantic-A0-ntuple-filters.patch new file mode 100644 index 0000000..62bf340 --- /dev/null +++ b/SOURCES/0134-netdrv-net-atlantic-A0-ntuple-filters.patch @@ -0,0 +1,196 @@ +From 398e44778a010807ab8fbf413e4d23085114430c Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:31 -0500 +Subject: [PATCH 134/139] [netdrv] net: atlantic: A0 ntuple filters + +Message-id: <1604687916-15087-135-git-send-email-irusskik@redhat.com> +Patchwork-id: 338555 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 134/139] net: atlantic: A0 ntuple filters +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit a89df867ce1a3368015ff6f85ab4a23d2a0aaba1 +Author: Dmitry Bogdanov +Date: Mon Jul 20 21:32:43 2020 +0300 + + net: atlantic: A0 ntuple filters + + This patch adds support for ntuple filters on A0. + + Signed-off-by: Dmitry Bogdanov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 116 ++++++++++++++++----- + 1 file changed, 88 insertions(+), 28 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index e1877d520135..c38a4b8a14cb 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -16,33 +16,35 @@ + #include "hw_atl_llh.h" + #include "hw_atl_a0_internal.h" + +-#define DEFAULT_A0_BOARD_BASIC_CAPABILITIES \ +- .is_64_dma = true, \ +- .op64bit = false, \ +- .msix_irqs = 4U, \ +- .irq_mask = ~0U, \ +- .vecs = HW_ATL_A0_RSS_MAX, \ +- .tcs_max = HW_ATL_A0_TC_MAX, \ +- .rxd_alignment = 1U, \ +- .rxd_size = HW_ATL_A0_RXD_SIZE, \ +- .rxds_max = HW_ATL_A0_MAX_RXD, \ +- .rxds_min = HW_ATL_A0_MIN_RXD, \ +- .txd_alignment = 1U, \ +- .txd_size = HW_ATL_A0_TXD_SIZE, \ +- .txds_max = HW_ATL_A0_MAX_TXD, \ +- .txds_min = HW_ATL_A0_MIN_RXD, \ +- .txhwb_alignment = 4096U, \ +- .tx_rings = HW_ATL_A0_TX_RINGS, \ +- .rx_rings = HW_ATL_A0_RX_RINGS, \ +- .hw_features = NETIF_F_HW_CSUM | \ +- NETIF_F_RXHASH | \ +- NETIF_F_RXCSUM | \ +- NETIF_F_SG | \ +- NETIF_F_TSO, \ +- .hw_priv_flags = IFF_UNICAST_FLT, \ +- .flow_control = true, \ +- .mtu = HW_ATL_A0_MTU_JUMBO, \ +- .mac_regs_count = 88, \ ++#define DEFAULT_A0_BOARD_BASIC_CAPABILITIES \ ++ .is_64_dma = true, \ ++ .op64bit = false, \ ++ .msix_irqs = 4U, \ ++ .irq_mask = ~0U, \ ++ .vecs = HW_ATL_A0_RSS_MAX, \ ++ .tcs_max = HW_ATL_A0_TC_MAX, \ ++ .rxd_alignment = 1U, \ ++ .rxd_size = HW_ATL_A0_RXD_SIZE, \ ++ .rxds_max = HW_ATL_A0_MAX_RXD, \ ++ .rxds_min = HW_ATL_A0_MIN_RXD, \ ++ .txd_alignment = 1U, \ ++ .txd_size = HW_ATL_A0_TXD_SIZE, \ ++ .txds_max = HW_ATL_A0_MAX_TXD, \ ++ .txds_min = HW_ATL_A0_MIN_RXD, \ ++ .txhwb_alignment = 4096U, \ ++ .tx_rings = HW_ATL_A0_TX_RINGS, \ ++ .rx_rings = HW_ATL_A0_RX_RINGS, \ ++ .hw_features = NETIF_F_HW_CSUM | \ ++ NETIF_F_RXHASH | \ ++ NETIF_F_RXCSUM | \ ++ NETIF_F_SG | \ ++ NETIF_F_TSO | \ ++ NETIF_F_NTUPLE | \ ++ NETIF_F_HW_VLAN_CTAG_FILTER, \ ++ .hw_priv_flags = IFF_UNICAST_FLT, \ ++ .flow_control = true, \ ++ .mtu = HW_ATL_A0_MTU_JUMBO, \ ++ .mac_regs_count = 88, \ + .hw_alive_check_addr = 0x10U + + const struct aq_hw_caps_s hw_atl_a0_caps_aqc100 = { +@@ -330,6 +332,7 @@ static int hw_atl_a0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) + err = -EINVAL; + goto err_exit; + } ++ + h = (mac_addr[0] << 8) | (mac_addr[1]); + l = (mac_addr[2] << 24) | (mac_addr[3] << 16) | + (mac_addr[4] << 8) | mac_addr[5]; +@@ -356,7 +359,6 @@ static int hw_atl_a0_hw_init(struct aq_hw_s *self, u8 *mac_addr) + struct aq_nic_cfg_s *aq_nic_cfg = self->aq_nic_cfg; + int err = 0; + +- + hw_atl_a0_hw_init_tx_path(self); + hw_atl_a0_hw_init_rx_path(self); + +@@ -885,6 +887,63 @@ static int hw_atl_a0_hw_ring_rx_stop(struct aq_hw_s *self, + return aq_hw_err_from_flags(self); + } + ++static int hw_atl_a0_hw_fl3l4_clear(struct aq_hw_s *self, ++ struct aq_rx_filter_l3l4 *data) ++{ ++ u8 location = data->location; ++ ++ if (!data->is_ipv6) { ++ hw_atl_rpfl3l4_cmd_clear(self, location); ++ hw_atl_rpf_l4_spd_set(self, 0U, location); ++ hw_atl_rpf_l4_dpd_set(self, 0U, location); ++ hw_atl_rpfl3l4_ipv4_src_addr_clear(self, location); ++ hw_atl_rpfl3l4_ipv4_dest_addr_clear(self, location); ++ } else { ++ int i; ++ ++ for (i = 0; i < HW_ATL_RX_CNT_REG_ADDR_IPV6; ++i) { ++ hw_atl_rpfl3l4_cmd_clear(self, location + i); ++ hw_atl_rpf_l4_spd_set(self, 0U, location + i); ++ hw_atl_rpf_l4_dpd_set(self, 0U, location + i); ++ } ++ hw_atl_rpfl3l4_ipv6_src_addr_clear(self, location); ++ hw_atl_rpfl3l4_ipv6_dest_addr_clear(self, location); ++ } ++ ++ return aq_hw_err_from_flags(self); ++} ++ ++static int hw_atl_a0_hw_fl3l4_set(struct aq_hw_s *self, ++ struct aq_rx_filter_l3l4 *data) ++{ ++ u8 location = data->location; ++ ++ hw_atl_a0_hw_fl3l4_clear(self, data); ++ ++ if (data->cmd) { ++ if (!data->is_ipv6) { ++ hw_atl_rpfl3l4_ipv4_dest_addr_set(self, ++ location, ++ data->ip_dst[0]); ++ hw_atl_rpfl3l4_ipv4_src_addr_set(self, ++ location, ++ data->ip_src[0]); ++ } else { ++ hw_atl_rpfl3l4_ipv6_dest_addr_set(self, ++ location, ++ data->ip_dst); ++ hw_atl_rpfl3l4_ipv6_src_addr_set(self, ++ location, ++ data->ip_src); ++ } ++ } ++ hw_atl_rpf_l4_dpd_set(self, data->p_dst, location); ++ hw_atl_rpf_l4_spd_set(self, data->p_src, location); ++ hw_atl_rpfl3l4_cmd_set(self, location, data->cmd); ++ ++ return aq_hw_err_from_flags(self); ++} ++ + const struct aq_hw_ops hw_atl_ops_a0 = { + .hw_soft_reset = hw_atl_utils_soft_reset, + .hw_prepare = hw_atl_utils_initfw, +@@ -911,6 +970,7 @@ const struct aq_hw_ops hw_atl_ops_a0 = { + .hw_ring_rx_init = hw_atl_a0_hw_ring_rx_init, + .hw_ring_tx_init = hw_atl_a0_hw_ring_tx_init, + .hw_packet_filter_set = hw_atl_a0_hw_packet_filter_set, ++ .hw_filter_l3l4_set = hw_atl_a0_hw_fl3l4_set, + .hw_multicast_list_set = hw_atl_a0_hw_multicast_list_set, + .hw_interrupt_moderation_set = hw_atl_a0_hw_interrupt_moderation_set, + .hw_rss_set = hw_atl_a0_hw_rss_set, +-- +2.13.6 + diff --git a/SOURCES/0135-netdrv-net-atlantic-add-hwmon-getter-for-MAC-tempera.patch b/SOURCES/0135-netdrv-net-atlantic-add-hwmon-getter-for-MAC-tempera.patch new file mode 100644 index 0000000..0cbde8e --- /dev/null +++ b/SOURCES/0135-netdrv-net-atlantic-add-hwmon-getter-for-MAC-tempera.patch @@ -0,0 +1,481 @@ +From 7660c86d26dd31e7426f658c27d42d91f72afbe9 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:32 -0500 +Subject: [PATCH 135/139] [netdrv] net: atlantic: add hwmon getter for MAC + temperature + +Message-id: <1604687916-15087-136-git-send-email-irusskik@redhat.com> +Patchwork-id: 338559 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 135/139] net: atlantic: add hwmon getter for MAC temperature +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 8dcf2ad39fdb2d183b7bd4307c837713e3150b9a +Author: Mark Starovoytov +Date: Mon Jul 20 21:32:44 2020 +0300 + + net: atlantic: add hwmon getter for MAC temperature + + This patch adds the possibility to obtain MAC temperature via hwmon. + On A1 there are two separate temperature sensors. + On A2 there's only one temperature sensor, which is used for reporting + both MAC and PHY temperature. + + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + .../net/ethernet/aquantia/atlantic/aq_drvinfo.c | 62 ++++++++++++++++------ + .../net/ethernet/aquantia/atlantic/aq_drvinfo.h | 10 ++-- + drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 4 ++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 44 +++++++++++++++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 44 +++++++++++++++ + .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 18 +++++++ + .../aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 30 +++++++++++ + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 1 + + .../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 3 +- + .../aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 21 ++++++++ + 10 files changed, 215 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c +index 6da65099047d..d3526cd38f3d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.c +@@ -1,5 +1,9 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* Copyright (C) 2014-2019 aQuantia Corporation. */ ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. ++ */ + + /* File aq_drvinfo.c: Definition of common code for firmware info in sys.*/ + +@@ -12,32 +16,51 @@ + #include + + #include "aq_drvinfo.h" ++#include "aq_nic.h" + + #if IS_REACHABLE(CONFIG_HWMON) ++static const char * const atl_temp_label[] = { ++ "PHY Temperature", ++ "MAC Temperature", ++}; ++ + static int aq_hwmon_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *value) + { + struct aq_nic_s *aq_nic = dev_get_drvdata(dev); ++ int err = 0; + int temp; +- int err; + + if (!aq_nic) + return -EIO; + +- if (type != hwmon_temp) ++ if (type != hwmon_temp || attr != hwmon_temp_input) + return -EOPNOTSUPP; + +- if (!aq_nic->aq_fw_ops->get_phy_temp) +- return -EOPNOTSUPP; ++ switch (channel) { ++ case 0: ++ if (!aq_nic->aq_fw_ops->get_phy_temp) ++ return -EOPNOTSUPP; + +- switch (attr) { +- case hwmon_temp_input: + err = aq_nic->aq_fw_ops->get_phy_temp(aq_nic->aq_hw, &temp); + *value = temp; +- return err; ++ break; ++ case 1: ++ if (!aq_nic->aq_fw_ops->get_mac_temp && ++ !aq_nic->aq_hw_ops->hw_get_mac_temp) ++ return -EOPNOTSUPP; ++ ++ if (aq_nic->aq_fw_ops->get_mac_temp) ++ err = aq_nic->aq_fw_ops->get_mac_temp(aq_nic->aq_hw, &temp); ++ else ++ err = aq_nic->aq_hw_ops->hw_get_mac_temp(aq_nic->aq_hw, &temp); ++ *value = temp; ++ break; + default: + return -EOPNOTSUPP; + } ++ ++ return err; + } + + static int aq_hwmon_read_string(struct device *dev, +@@ -49,28 +72,32 @@ static int aq_hwmon_read_string(struct device *dev, + if (!aq_nic) + return -EIO; + +- if (type != hwmon_temp) ++ if (type != hwmon_temp || attr != hwmon_temp_label) + return -EOPNOTSUPP; + +- if (!aq_nic->aq_fw_ops->get_phy_temp) ++ if (channel < ARRAY_SIZE(atl_temp_label)) ++ *str = atl_temp_label[channel]; ++ else + return -EOPNOTSUPP; + +- switch (attr) { +- case hwmon_temp_label: +- *str = "PHY Temperature"; +- return 0; +- default: +- return -EOPNOTSUPP; +- } ++ return 0; + } + + static umode_t aq_hwmon_is_visible(const void *data, + enum hwmon_sensor_types type, + u32 attr, int channel) + { ++ const struct aq_nic_s *nic = data; ++ + if (type != hwmon_temp) + return 0; + ++ if (channel == 0 && !nic->aq_fw_ops->get_phy_temp) ++ return 0; ++ else if (channel == 1 && !nic->aq_fw_ops->get_mac_temp && ++ !nic->aq_hw_ops->hw_get_mac_temp) ++ return 0; ++ + switch (attr) { + case hwmon_temp_input: + case hwmon_temp_label: +@@ -88,6 +115,7 @@ static const struct hwmon_ops aq_hwmon_ops = { + + static u32 aq_hwmon_temp_config[] = { + HWMON_T_INPUT | HWMON_T_LABEL, ++ HWMON_T_INPUT | HWMON_T_LABEL, + 0, + }; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.h b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.h +index 23a0487893a7..59113a20622a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_drvinfo.h +@@ -1,14 +1,16 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ +-/* Copyright (C) 2014-2017 aQuantia Corporation. */ ++/* Atlantic Network Driver ++ * ++ * Copyright (C) 2014-2019 aQuantia Corporation ++ * Copyright (C) 2019-2020 Marvell International Ltd. ++ */ + + /* File aq_drvinfo.h: Declaration of common code for firmware info in sys.*/ + + #ifndef AQ_DRVINFO_H + #define AQ_DRVINFO_H + +-#include "aq_nic.h" +-#include "aq_hw.h" +-#include "hw_atl/hw_atl_utils.h" ++struct net_device; + + int aq_drvinfo_init(struct net_device *ndev); + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index 9d0c43325fc3..386026f2c9ca 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -334,6 +334,8 @@ struct aq_hw_ops { + int (*hw_set_fc)(struct aq_hw_s *self, u32 fc, u32 tc); + + int (*hw_set_loopback)(struct aq_hw_s *self, u32 mode, bool enable); ++ ++ int (*hw_get_mac_temp)(struct aq_hw_s *self, u32 *temp); + }; + + struct aq_fw_ops { +@@ -356,6 +358,8 @@ struct aq_fw_ops { + + int (*update_stats)(struct aq_hw_s *self); + ++ int (*get_mac_temp)(struct aq_hw_s *self, int *temp); ++ + int (*get_phy_temp)(struct aq_hw_s *self, int *temp); + + u32 (*get_flow_control)(struct aq_hw_s *self, u32 *fcmode); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 59297e971ade..1896c9112bdf 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1600,6 +1600,48 @@ int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable) + return 0; + } + ++static u32 hw_atl_b0_ts_ready_and_latch_high_get(struct aq_hw_s *self) ++{ ++ if (hw_atl_ts_ready_get(self) && hw_atl_ts_ready_latch_high_get(self)) ++ return 1; ++ ++ return 0; ++} ++ ++static int hw_atl_b0_get_mac_temp(struct aq_hw_s *self, u32 *temp) ++{ ++ bool ts_disabled; ++ int err; ++ u32 val; ++ u32 ts; ++ ++ ts_disabled = (hw_atl_ts_power_down_get(self) == 1U); ++ ++ if (ts_disabled) { ++ // Set AFE Temperature Sensor to on (off by default) ++ hw_atl_ts_power_down_set(self, 0U); ++ ++ // Reset internal capacitors, biasing, and counters ++ hw_atl_ts_reset_set(self, 1); ++ hw_atl_ts_reset_set(self, 0); ++ } ++ ++ err = readx_poll_timeout_atomic(hw_atl_b0_ts_ready_and_latch_high_get, ++ self, val, val == 1, 10000U, 500000U); ++ if (err) ++ return err; ++ ++ ts = hw_atl_ts_data_get(self); ++ *temp = ts * ts * 16 / 100000 + 60 * ts - 83410; ++ ++ if (ts_disabled) { ++ // Set AFE Temperature Sensor back to off ++ hw_atl_ts_power_down_set(self, 1U); ++ } ++ ++ return 0; ++} ++ + const struct aq_hw_ops hw_atl_ops_b0 = { + .hw_soft_reset = hw_atl_utils_soft_reset, + .hw_prepare = hw_atl_utils_initfw, +@@ -1656,4 +1698,6 @@ const struct aq_hw_ops hw_atl_ops_b0 = { + .hw_set_offload = hw_atl_b0_hw_offload_set, + .hw_set_loopback = hw_atl_b0_set_loopback, + .hw_set_fc = hw_atl_b0_set_fc, ++ ++ .hw_get_mac_temp = hw_atl_b0_get_mac_temp, + }; +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +index 9c3debae425f..7b67bdd8a258 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +@@ -13,6 +13,50 @@ + #include "hw_atl_llh_internal.h" + #include "../aq_hw_utils.h" + ++void hw_atl_ts_reset_set(struct aq_hw_s *aq_hw, u32 val) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL_TS_RESET_ADR, ++ HW_ATL_TS_RESET_MSK, ++ HW_ATL_TS_RESET_SHIFT, ++ val); ++} ++ ++void hw_atl_ts_power_down_set(struct aq_hw_s *aq_hw, u32 val) ++{ ++ aq_hw_write_reg_bit(aq_hw, HW_ATL_TS_POWER_DOWN_ADR, ++ HW_ATL_TS_POWER_DOWN_MSK, ++ HW_ATL_TS_POWER_DOWN_SHIFT, ++ val); ++} ++ ++u32 hw_atl_ts_power_down_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg_bit(aq_hw, HW_ATL_TS_POWER_DOWN_ADR, ++ HW_ATL_TS_POWER_DOWN_MSK, ++ HW_ATL_TS_POWER_DOWN_SHIFT); ++} ++ ++u32 hw_atl_ts_ready_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg_bit(aq_hw, HW_ATL_TS_READY_ADR, ++ HW_ATL_TS_READY_MSK, ++ HW_ATL_TS_READY_SHIFT); ++} ++ ++u32 hw_atl_ts_ready_latch_high_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg_bit(aq_hw, HW_ATL_TS_READY_LATCH_HIGH_ADR, ++ HW_ATL_TS_READY_LATCH_HIGH_MSK, ++ HW_ATL_TS_READY_LATCH_HIGH_SHIFT); ++} ++ ++u32 hw_atl_ts_data_get(struct aq_hw_s *aq_hw) ++{ ++ return aq_hw_read_reg_bit(aq_hw, HW_ATL_TS_DATA_OUT_ADR, ++ HW_ATL_TS_DATA_OUT_MSK, ++ HW_ATL_TS_DATA_OUT_SHIFT); ++} ++ + /* global */ + void hw_atl_reg_glb_cpu_sem_set(struct aq_hw_s *aq_hw, u32 glb_cpu_sem, + u32 semaphore) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +index f0954711df24..58f5ee0a6214 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +@@ -16,6 +16,24 @@ + + struct aq_hw_s; + ++/* set temperature sense reset */ ++void hw_atl_ts_reset_set(struct aq_hw_s *aq_hw, u32 val); ++ ++/* set temperature sense power down */ ++void hw_atl_ts_power_down_set(struct aq_hw_s *aq_hw, u32 val); ++ ++/* get temperature sense power down */ ++u32 hw_atl_ts_power_down_get(struct aq_hw_s *aq_hw); ++ ++/* get temperature sense ready */ ++u32 hw_atl_ts_ready_get(struct aq_hw_s *aq_hw); ++ ++/* get temperature sense ready latch high */ ++u32 hw_atl_ts_ready_latch_high_get(struct aq_hw_s *aq_hw); ++ ++/* get temperature sense data */ ++u32 hw_atl_ts_data_get(struct aq_hw_s *aq_hw); ++ + /* global */ + + /* set global microprocessor semaphore */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +index ee11cb88325e..4a6467031b9e 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +@@ -12,6 +12,36 @@ + #ifndef HW_ATL_LLH_INTERNAL_H + #define HW_ATL_LLH_INTERNAL_H + ++/* COM Temperature Sense Reset Bitfield Definitions */ ++#define HW_ATL_TS_RESET_ADR 0x00003100 ++#define HW_ATL_TS_RESET_MSK 0x00000004 ++#define HW_ATL_TS_RESET_SHIFT 2 ++#define HW_ATL_TS_RESET_WIDTH 1 ++ ++/* COM Temperature Sense Power Down Bitfield Definitions */ ++#define HW_ATL_TS_POWER_DOWN_ADR 0x00003100 ++#define HW_ATL_TS_POWER_DOWN_MSK 0x00000001 ++#define HW_ATL_TS_POWER_DOWN_SHIFT 0 ++#define HW_ATL_TS_POWER_DOWN_WIDTH 1 ++ ++/* COM Temperature Sense Ready Bitfield Definitions */ ++#define HW_ATL_TS_READY_ADR 0x00003120 ++#define HW_ATL_TS_READY_MSK 0x80000000 ++#define HW_ATL_TS_READY_SHIFT 31 ++#define HW_ATL_TS_READY_WIDTH 1 ++ ++/* COM Temperature Sense Ready Latch High Bitfield Definitions */ ++#define HW_ATL_TS_READY_LATCH_HIGH_ADR 0x00003120 ++#define HW_ATL_TS_READY_LATCH_HIGH_MSK 0x40000000 ++#define HW_ATL_TS_READY_LATCH_HIGH_SHIFT 30 ++#define HW_ATL_TS_READY_LATCH_HIGH_WIDTH 1 ++ ++/* COM Temperature Sense Data Out [B:0] Bitfield Definitions */ ++#define HW_ATL_TS_DATA_OUT_ADR 0x00003120 ++#define HW_ATL_TS_DATA_OUT_MSK 0x00000FFF ++#define HW_ATL_TS_DATA_OUT_SHIFT 0 ++#define HW_ATL_TS_DATA_OUT_WIDTH 12 ++ + /* global microprocessor semaphore definitions + * base address: 0x000003a0 + * parameter: semaphore {s} | stride size 0x4 | range [0, 15] +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index cacab3352cb8..404cbf60d3f2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -1066,6 +1066,7 @@ const struct aq_fw_ops aq_fw_1x_ops = { + .set_state = hw_atl_utils_mpi_set_state, + .update_link_status = hw_atl_utils_mpi_get_link_status, + .update_stats = hw_atl_utils_update_stats, ++ .get_mac_temp = NULL, + .get_phy_temp = NULL, + .set_power = aq_fw1x_set_power, + .set_eee_rate = NULL, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index 92ae60ac5735..90f8c11318a1 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -350,7 +350,7 @@ static int aq_fw2x_get_phy_temp(struct aq_hw_s *self, int *temp) + /* Convert PHY temperature from 1/256 degree Celsius + * to 1/1000 degree Celsius. + */ +- *temp = (temp_res & 0xFFFF) * 1000 / 256; ++ *temp = (int16_t)(temp_res & 0xFFFF) * 1000 / 256; + + return 0; + } +@@ -614,6 +614,7 @@ const struct aq_fw_ops aq_fw_2x_ops = { + .set_state = aq_fw2x_set_state, + .update_link_status = aq_fw2x_update_link_status, + .update_stats = aq_fw2x_update_stats, ++ .get_mac_temp = NULL, + .get_phy_temp = aq_fw2x_get_phy_temp, + .set_power = aq_fw2x_set_power, + .set_eee_rate = aq_fw2x_set_eee_rate, +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +index a8ce9a2c1c51..85628acbcc1d 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +@@ -379,6 +379,25 @@ static int aq_a2_fw_update_stats(struct aq_hw_s *self) + return 0; + } + ++static int aq_a2_fw_get_phy_temp(struct aq_hw_s *self, int *temp) ++{ ++ struct phy_health_monitor_s phy_health_monitor; ++ ++ hw_atl2_shared_buffer_read_safe(self, phy_health_monitor, ++ &phy_health_monitor); ++ ++ *temp = (int8_t)phy_health_monitor.phy_temperature * 1000; ++ return 0; ++} ++ ++static int aq_a2_fw_get_mac_temp(struct aq_hw_s *self, int *temp) ++{ ++ /* There's only one temperature sensor on A2, use it for ++ * both MAC and PHY. ++ */ ++ return aq_a2_fw_get_phy_temp(self, temp); ++} ++ + static int aq_a2_fw_set_eee_rate(struct aq_hw_s *self, u32 speed) + { + struct link_options_s link_options; +@@ -510,6 +529,8 @@ const struct aq_fw_ops aq_a2_fw_ops = { + .set_state = aq_a2_fw_set_state, + .update_link_status = aq_a2_fw_update_link_status, + .update_stats = aq_a2_fw_update_stats, ++ .get_mac_temp = aq_a2_fw_get_mac_temp, ++ .get_phy_temp = aq_a2_fw_get_phy_temp, + .set_eee_rate = aq_a2_fw_set_eee_rate, + .get_eee_rate = aq_a2_fw_get_eee_rate, + .set_flow_control = aq_a2_fw_set_flow_control, +-- +2.13.6 + diff --git a/SOURCES/0136-netdrv-net-atlantic-fix-PTP-on-AQC10X.patch b/SOURCES/0136-netdrv-net-atlantic-fix-PTP-on-AQC10X.patch new file mode 100644 index 0000000..138a995 --- /dev/null +++ b/SOURCES/0136-netdrv-net-atlantic-fix-PTP-on-AQC10X.patch @@ -0,0 +1,66 @@ +From e4d04ac18fe289f30136f43097308773e1bcabfe Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:33 -0500 +Subject: [PATCH 136/139] [netdrv] net: atlantic: fix PTP on AQC10X + +Message-id: <1604687916-15087-137-git-send-email-irusskik@redhat.com> +Patchwork-id: 338563 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 136/139] net: atlantic: fix PTP on AQC10X +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 901f3cc1639e5103a8997f6ab243785d292e2074 +Author: Egor Pomozov +Date: Wed Jul 22 22:09:58 2020 +0300 + + net: atlantic: fix PTP on AQC10X + + This patch fixes PTP on AQC10X. + PTP support on AQC10X requires FW involvement and FW configures the + TPS data arb mode itself. + So we must make sure driver doesn't touch TPS data arb mode on AQC10x + if PTP is enabled. Otherwise, there are no timestamps even though + packets are flowing. + + Fixes: 2deac71ac492a ("net: atlantic: QoS implementation: min_rate") + Signed-off-by: Egor Pomozov + Signed-off-by: Mark Starovoytov + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 1896c9112bdf..16a944707ba9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -373,8 +373,13 @@ static int hw_atl_b0_hw_init_tx_tc_rate_limit(struct aq_hw_s *self) + + /* WSP, if min_rate is set for at least one TC. + * RR otherwise. ++ * ++ * NB! MAC FW sets arb mode itself if PTP is enabled. We shouldn't ++ * overwrite it here in that case. + */ +- hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, min_rate_msk ? 1U : 0U); ++ if (!nic_cfg->is_ptp) ++ hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, min_rate_msk ? 1U : 0U); ++ + /* Data TC Arbiter takes precedence over Descriptor TC Arbiter, + * leave Descriptor TC Arbiter as RR. + */ +-- +2.13.6 + diff --git a/SOURCES/0137-netdrv-net-ethernet-aquantia-Fix-wrong-return-value.patch b/SOURCES/0137-netdrv-net-ethernet-aquantia-Fix-wrong-return-value.patch new file mode 100644 index 0000000..7187a06 --- /dev/null +++ b/SOURCES/0137-netdrv-net-ethernet-aquantia-Fix-wrong-return-value.patch @@ -0,0 +1,56 @@ +From 6ce7ad8a55b386f11e57bb77769011d1610cf314 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:34 -0500 +Subject: [PATCH 137/139] [netdrv] net: ethernet: aquantia: Fix wrong return + value + +Message-id: <1604687916-15087-138-git-send-email-irusskik@redhat.com> +Patchwork-id: 338558 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 137/139] net: ethernet: aquantia: Fix wrong return value +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 0470a48880f8bc42ce26962b79c7b802c5a695ec +Author: Tianjia Zhang +Date: Sun Aug 2 19:15:37 2020 +0800 + + net: ethernet: aquantia: Fix wrong return value + + In function hw_atl_a0_hw_multicast_list_set(), when an invalid + request is encountered, a negative error code should be returned. + + Fixes: bab6de8fd180b ("net: ethernet: aquantia: Atlantic A0 and B0 specific functions") + Cc: David VomLehn + Signed-off-by: Tianjia Zhang + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +index c38a4b8a14cb..611875ef2cd1 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +@@ -786,7 +786,7 @@ static int hw_atl_a0_hw_multicast_list_set(struct aq_hw_s *self, + int err = 0; + + if (count > (HW_ATL_A0_MAC_MAX - HW_ATL_A0_MAC_MIN)) { +- err = EBADRQC; ++ err = -EBADRQC; + goto err_exit; + } + for (cfg->mc_list_count = 0U; cfg->mc_list_count < count; ++cfg->mc_list_count) { +-- +2.13.6 + diff --git a/SOURCES/0138-netdrv-net-atlantic-Use-readx_poll_timeout-for-large.patch b/SOURCES/0138-netdrv-net-atlantic-Use-readx_poll_timeout-for-large.patch new file mode 100644 index 0000000..40cdc01 --- /dev/null +++ b/SOURCES/0138-netdrv-net-atlantic-Use-readx_poll_timeout-for-large.patch @@ -0,0 +1,69 @@ +From 2ed39a7b4fa60db0eb2ecbb0490bb7c79ad07235 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:35 -0500 +Subject: [PATCH 138/139] [netdrv] net: atlantic: Use readx_poll_timeout() for + large timeout + +Message-id: <1604687916-15087-139-git-send-email-irusskik@redhat.com> +Patchwork-id: 338561 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 138/139] net: atlantic: Use readx_poll_timeout() for large timeout +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 9553b62c1dd27df67ab2f52ec8a3bc3501887619 +Author: Sebastian Andrzej Siewior +Date: Tue Aug 18 18:14:39 2020 +0200 + + net: atlantic: Use readx_poll_timeout() for large timeout + + Commit + 8dcf2ad39fdb2 ("net: atlantic: add hwmon getter for MAC temperature") + + implemented a read callback with an udelay(10000U). This fails to + compile on ARM because the delay is >1ms. I doubt that it is needed to + spin for 10ms even if possible on x86. + + >From looking at the code, the context appears to be preemptible so using + usleep() should work and avoid busy spinning. + + Use readx_poll_timeout() in the poll loop. + + Fixes: 8dcf2ad39fdb2 ("net: atlantic: add hwmon getter for MAC temperature") + Cc: Mark Starovoytov + Cc: Igor Russkikh + Signed-off-by: Sebastian Andrzej Siewior + Acked-by: Guenter Roeck + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 16a944707ba9..8941ac4df9e3 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1631,8 +1631,8 @@ static int hw_atl_b0_get_mac_temp(struct aq_hw_s *self, u32 *temp) + hw_atl_ts_reset_set(self, 0); + } + +- err = readx_poll_timeout_atomic(hw_atl_b0_ts_ready_and_latch_high_get, +- self, val, val == 1, 10000U, 500000U); ++ err = readx_poll_timeout(hw_atl_b0_ts_ready_and_latch_high_get, self, ++ val, val == 1, 10000U, 500000U); + if (err) + return err; + +-- +2.13.6 + diff --git a/SOURCES/0139-netdrv-net-atlantic-fix-build-when-object-tree-is-se.patch b/SOURCES/0139-netdrv-net-atlantic-fix-build-when-object-tree-is-se.patch new file mode 100644 index 0000000..d328005 --- /dev/null +++ b/SOURCES/0139-netdrv-net-atlantic-fix-build-when-object-tree-is-se.patch @@ -0,0 +1,59 @@ +From 77a2fb7ae065f914c6c478d974cd60349eeca817 Mon Sep 17 00:00:00 2001 +From: Igor Russkikh +Date: Fri, 6 Nov 2020 18:38:36 -0500 +Subject: [PATCH 139/139] [netdrv] net: atlantic: fix build when object tree is + separate + +Message-id: <1604687916-15087-140-git-send-email-irusskik@redhat.com> +Patchwork-id: 338560 +Patchwork-instance: patchwork +O-Subject: [RHEL8.4 BZ 1857861 139/139] net: atlantic: fix build when object tree is separate +Bugzilla: 1857861 +RH-Acked-by: David Arcari +RH-Acked-by: John Linville +RH-Acked-by: Tony Camuso + +Bugzilla: http://bugzilla.redhat.com/1857861 + +commit 059432495e209279bae12db3d2b0bc8c8fe987bb +Author: Igor Russkikh +Date: Fri Sep 25 23:27:35 2020 +0300 + + net: atlantic: fix build when object tree is separate + + Driver subfolder files refer parent folder includes in an + absolute manner. + + Makefile contains a -I for this, but apparently that does not + work if object tree is separated. + + Adding srctree to fix that. + + Signed-off-by: Igor Russkikh + Signed-off-by: David S. Miller + +Signed-off-by: Igor Russkikh + +Cc: David Arcari +Cc: Igor Russkikh +Signed-off-by: Jan Stancek +--- + drivers/net/ethernet/aquantia/atlantic/Makefile | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile +index 2f5ec1a60be0..6059711823e6 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/Makefile ++++ b/drivers/net/ethernet/aquantia/atlantic/Makefile +@@ -8,6 +8,8 @@ + + obj-$(CONFIG_AQTION) += atlantic.o + ++ccflags-y += -I$(srctree)/$(src) ++ + atlantic-objs := aq_main.o \ + aq_nic.o \ + aq_pci_func.o \ +-- +2.13.6 + diff --git a/SOURCES/9000-add-driver-version.patch b/SOURCES/9000-add-driver-version.patch new file mode 100644 index 0000000..f62c359 --- /dev/null +++ b/SOURCES/9000-add-driver-version.patch @@ -0,0 +1,35 @@ +Index: src/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +=================================================================== +--- src.orig/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h 2021-03-23 01:04:32.444995548 +0100 ++++ src/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h 2021-03-23 01:17:46.434047298 +0100 +@@ -83,5 +83,6 @@ + #define AQ_CFG_DRV_AUTHOR "Marvell" + #define AQ_CFG_DRV_DESC "Marvell (Aquantia) Corporation(R) Network Driver" + #define AQ_CFG_DRV_NAME "atlantic" ++#define AQ_CFG_DRV_VERSION "4.18.0-255.el8-dup8.3" + + #endif /* AQ_CFG_H */ +Index: src/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +=================================================================== +--- src.orig/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c 2021-03-23 01:04:33.059990153 +0100 ++++ src/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c 2021-03-23 01:07:31.717423151 +0100 +@@ -152,6 +152,7 @@ + regs_count = aq_nic_get_regs_count(aq_nic); + + strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver)); ++ strlcat(drvinfo->version, AQ_CFG_DRV_VERSION, sizeof(drvinfo->version)); + + snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), + "%u.%u.%u", firmware_version >> 24, +Index: src/drivers/net/ethernet/aquantia/atlantic/aq_main.c +=================================================================== +--- src.orig/drivers/net/ethernet/aquantia/atlantic/aq_main.c 2021-03-23 01:04:32.946991144 +0100 ++++ src/drivers/net/ethernet/aquantia/atlantic/aq_main.c 2021-03-23 01:07:58.425189589 +0100 +@@ -22,6 +22,7 @@ + #include + + MODULE_LICENSE("GPL v2"); ++MODULE_VERSION(AQ_CFG_DRV_VERSION); + MODULE_AUTHOR(AQ_CFG_DRV_AUTHOR); + MODULE_DESCRIPTION(AQ_CFG_DRV_DESC); + diff --git a/SPECS/kmod-redhat-atlantic.spec b/SPECS/kmod-redhat-atlantic.spec new file mode 100644 index 0000000..1dbd5e3 --- /dev/null +++ b/SPECS/kmod-redhat-atlantic.spec @@ -0,0 +1,576 @@ +%define kmod_name atlantic +%define kmod_vendor redhat +%define kmod_rpm_name kmod-redhat-atlantic +%define kmod_driver_version 4.18.0_255.el8_dup8.3 +%define kmod_driver_epoch %{nil} +%define kmod_rpm_release 1 +%define kmod_kernel_version 4.18.0-240.el8 +%define kmod_kernel_version_min %{nil} +%define kmod_kernel_version_dep %{nil} +%define kmod_kbuild_dir drivers/net/ethernet/aquantia/atlantic +%define kmod_dependencies %{nil} +%define kmod_dist_build_deps %{nil} +%define kmod_build_dependencies %{nil} +%define kmod_provides %{nil} +%define kmod_devel_package 0 +%define kmod_devel_src_paths %{nil} +%define kmod_install_path extra/kmod-redhat-atlantic +%define kernel_pkg kernel +%define kernel_devel_pkg kernel-devel +%define kernel_modules_pkg kernel-modules + +%{!?dist: %define dist .el8_3} +%{!?make_build: %define make_build make} + +%if "%{kmod_kernel_version_dep}" == "" +%define kmod_kernel_version_dep %{kmod_kernel_version} +%endif + +%if "%{kmod_dist_build_deps}" == "" +%if (0%{?rhel} > 7) || (0%{?centos} > 7) +%define kmod_dist_build_deps redhat-rpm-config kernel-abi-whitelists elfutils-libelf-devel kernel-rpm-macros kmod +%else +%define kmod_dist_build_deps redhat-rpm-config kernel-abi-whitelists +%endif +%endif + +Source0: %{kmod_name}-%{kmod_vendor}-%{kmod_driver_version}.tar.bz2 +# Source code patches +Patch0: 0001-netdrv-treewide-Replace-GPLv2-boilerplate-reference-.patch +Patch1: 0002-netdrv-treewide-Replace-GPLv2-boilerplate-reference-.patch +Patch2: 0003-netdrv-net-aquantia-replace-internal-driver-version-.patch +Patch3: 0004-netdrv-net-aquantia-make-all-files-GPL-2.0-only.patch +Patch4: 0005-netdrv-net-aquantia-added-vlan-offload-related-macro.patch +Patch5: 0006-netdrv-net-aquantia-adding-fields-and-device-feature.patch +Patch6: 0007-netdrv-net-aquantia-vlan-offloads-logic-in-datapath.patch +Patch7: 0008-netdrv-net-aquantia-implement-vlan-offload-configura.patch +Patch8: 0009-netdrv-net-aquantia-fix-removal-of-vlan-0.patch +Patch9: 0010-netdrv-net-aquantia-fix-limit-of-vlan-filters.patch +Patch10: 0011-netdrv-net-aquantia-linkstate-irq-should-be-oneshot.patch +Patch11: 0012-netdrv-net-aquantia-fix-out-of-memory-condition-on-r.patch +Patch12: 0013-netdrv-net-aquantia-Fix-aq_vec_isr_legacy-return-val.patch +Patch13: 0014-netdrv-net-aquantia-temperature-retrieval-fix.patch +Patch14: 0015-netdrv-net-aquantia-when-cleaning-hw-cache-it-should.patch +Patch15: 0016-netdrv-net-aquantia-do-not-pass-lro-session-with-inv.patch +Patch16: 0017-netdrv-net-aquantia-correctly-handle-macvlan-and-mul.patch +Patch17: 0018-netdrv-net-aquantia-add-an-error-handling-in-aq_nic_.patch +Patch18: 0019-netdrv-net-aquantia-PTP-skeleton-declarations-and-ca.patch +Patch19: 0020-netdrv-net-aquantia-unify-styling-of-bit-enums.patch +Patch20: 0021-netdrv-net-aquantia-add-basic-ptp_clock-callbacks.patch +Patch21: 0022-netdrv-net-aquantia-add-PTP-rings-infrastructure.patch +Patch22: 0023-netdrv-net-aquantia-styling-fixes-on-ptp-related-fun.patch +Patch23: 0024-netdrv-net-aquantia-implement-data-PTP-datapath.patch +Patch24: 0025-netdrv-net-aquantia-rx-filters-for-ptp.patch +Patch25: 0026-netdrv-net-aquantia-add-support-for-ptp-ioctls.patch +Patch26: 0027-netdrv-net-aquantia-implement-get_ts_info-ethtool.patch +Patch27: 0028-netdrv-net-aquantia-add-support-for-Phy-access.patch +Patch28: 0029-netdrv-net-aquantia-add-support-for-PIN-funcs.patch +Patch29: 0030-netdrv-net-aquantia-fix-var-initialization-warning.patch +Patch30: 0031-netdrv-net-aquantia-fix-warnings-on-endianness.patch +Patch31: 0032-netdrv-net-aquantia-disable-ptp-object-build-if-no-c.patch +Patch32: 0033-netdrv-net-aquantia-fix-spelling-mistake-tx_queus-tx.patch +Patch33: 0034-netdrv-net-aquantia-fix-unintention-integer-overflow.patch +Patch34: 0035-netdrv-net-aquantia-make-two-symbols-be-static.patch +Patch35: 0036-netdrv-net-aquantia-remove-unused-including-linux-ve.patch +Patch36: 0037-netdrv-net-aquantia-fix-error-handling-in-aq_ptp_pol.patch +Patch37: 0038-netdrv-net-aquantia-fix-return-value-check-in-aq_ptp.patch +Patch38: 0039-netdrv-net-atlantic-update-firmware-interface.patch +Patch39: 0040-netdrv-net-atlantic-implement-wake_phy-feature.patch +Patch40: 0041-netdrv-net-atlantic-refactoring-pm-logic.patch +Patch41: 0042-netdrv-net-atlantic-add-msglevel-configuration.patch +Patch42: 0043-netdrv-net-atlantic-adding-ethtool-physical-identifi.patch +Patch43: 0044-netdrv-net-atlantic-add-fw-configuration-memory-area.patch +Patch44: 0045-netdrv-net-atlantic-loopback-tests-via-private-flags.patch +Patch45: 0046-netdrv-net-atlantic-code-style-cleanup.patch +Patch46: 0047-netdrv-net-atlantic-stylistic-renames.patch +Patch47: 0048-netdrv-net-atlantic-update-flow-control-logic.patch +Patch48: 0049-netdrv-net-atlantic-implement-UDP-GSO-offload.patch +Patch49: 0050-netdrv-net-atlantic-change-email-domains-to-Marvell.patch +Patch50: 0051-netdrv-net-atlantic-make-symbol-aq_pm_ops-static.patch +Patch51: 0052-netdrv-net-atlantic-make-function-aq_ethtool_get_pri.patch +Patch52: 0053-netdrv-net-atlantic-Signedness-bug-in-aq_vec_isr_leg.patch +Patch53: 0054-netdrv-net-atlantic-broken-link-status-on-old-fw.patch +Patch54: 0055-netdrv-net-atlantic-loopback-configuration-in-improp.patch +Patch55: 0056-netdrv-net-atlantic-remove-duplicate-entries.patch +Patch56: 0057-netdrv-net-atlantic-checksum-compat-issue.patch +Patch57: 0058-netdrv-net-atlantic-check-rpc-result-and-wait-for-rp.patch +Patch58: 0059-netdrv-net-atlantic-ptp-gpio-adjustments.patch +Patch59: 0060-netdrv-net-atlantic-better-loopback-mode-handling.patch +Patch60: 0061-netdrv-net-atlantic-fix-use-after-free-kasan-warn.patch +Patch61: 0062-netdrv-net-atlantic-fix-potential-error-handling.patch +Patch62: 0063-netdrv-net-atlantic-possible-fault-in-transition-to-.patch +Patch63: 0064-netdrv-net-atlantic-fix-out-of-range-usage-of-active.patch +Patch64: 0065-netdrv-net-aquantia-Delete-module-version.patch +Patch65: 0066-netdrv-net-atlantic-Replace-zero-length-array-with-f.patch +Patch66: 0067-netdrv-net-aquantia-reject-all-unsupported-coalescin.patch +Patch67: 0068-netdrv-net-atlantic-MACSec-offload-statistics-implem.patch +Patch68: 0069-netdrv-aquantia-Fix-the-media-type-of-AQC100-etherne.patch +Patch69: 0070-netdrv-net-atlantic-update-company-name-in-the-drive.patch +Patch70: 0071-netdrv-net-atlantic-add-A2-device-IDs.patch +Patch71: 0072-netdrv-net-atlantic-add-defines-for-10M-and-EEE-100M.patch +Patch72: 0073-netdrv-net-atlantic-add-hw_soft_reset-hw_prepare-to-.patch +Patch73: 0074-netdrv-net-atlantic-simplify-hw_get_fw_version-usage.patch +Patch74: 0075-netdrv-net-atlantic-make-hw_get_regs-optional.patch +Patch75: 0076-netdrv-net-atlantic-move-IS_CHIP_FEATURE-to-aq_hw.h.patch +Patch76: 0077-netdrv-net-atlantic-A2-driver-firmware-interface.patch +Patch77: 0078-netdrv-net-atlantic-minimal-A2-HW-bindings-required-.patch +Patch78: 0079-netdrv-net-atlantic-minimal-A2-fw_ops.patch +Patch79: 0080-netdrv-net-atlantic-A2-hw_ops-skeleton.patch +Patch80: 0081-netdrv-net-atlantic-HW-bindings-for-A2-RFP.patch +Patch81: 0082-netdrv-net-atlantic-add-A2-RPF-hw_ops.patch +Patch82: 0083-netdrv-net-atlantic-HW-bindings-for-basic-A2-init-de.patch +Patch83: 0084-netdrv-net-atlantic-common-functions-needed-for-basi.patch +Patch84: 0085-netdrv-net-atlantic-basic-A2-init-deinit-hw_ops.patch +Patch85: 0086-netdrv-net-atlantic-A2-ingress-egress-hw-configurati.patch +Patch86: 0087-netdrv-net-atlantic-use-__packed-instead-of-the-full.patch +Patch87: 0088-netdrv-net-atlantic-rename-AQ_NIC_RATE_2GS-to-AQ_NIC.patch +Patch88: 0089-netdrv-net-atlantic-remove-TPO2-check-from-A0-code.patch +Patch89: 0090-netdrv-net-atlantic-remove-hw_atl_b0_hw_rss_set-call.patch +Patch90: 0091-netdrv-net-atlantic-remove-check-for-boot-code-survi.patch +Patch91: 0092-netdrv-net-atlantic-unify-MAC-generation.patch +Patch92: 0093-netdrv-net-atlantic-changes-for-multi-TC-support.patch +Patch93: 0094-netdrv-net-atlantic-move-PTP-TC-initialization-to-a-.patch +Patch94: 0095-netdrv-net-atlantic-changes-for-multi-TC-support.patch +Patch95: 0096-netdrv-net-atlantic-QoS-implementation-multi-TC-supp.patch +Patch96: 0097-netdrv-net-atlantic-per-TC-queue-statistics.patch +Patch97: 0098-netdrv-net-atlantic-make-TCVEC2RING-accept-nic_cfg.patch +Patch98: 0099-netdrv-net-atlantic-QoS-implementation-max_rate.patch +Patch99: 0100-netdrv-net-atlantic-automatically-downgrade-the-numb.patch +Patch100: 0101-netdrv-net-atlantic-always-use-random-TC-queue-mappi.patch +Patch101: 0102-netdrv-net-atlantic-change-the-order-of-arguments-fo.patch +Patch102: 0103-netdrv-net-atlantic-QoS-implementation-min_rate.patch +Patch103: 0104-netdrv-net-atlantic-proper-rss_ctrl1-54c0-initializa.patch +Patch104: 0105-netdrv-net-atlantic-A2-half-duplex-support.patch +Patch105: 0106-netdrv-net-atlantic-remove-baseX-usage.patch +Patch106: 0107-netdrv-net-atlantic-A2-EEE-support.patch +Patch107: 0108-netdrv-net-atlantic-A2-flow-control-support.patch +Patch108: 0109-netdrv-net-atlantic-A2-report-link-partner-capabilit.patch +Patch109: 0110-netdrv-net-atlantic-A2-phy-loopback-support.patch +Patch110: 0111-netdrv-net-atlantic-fix-variable-type-in-aq_ethtool_.patch +Patch111: 0112-netdrv-net-atlantic-Replace-ENOTSUPP-usage-to-EOPNOT.patch +Patch112: 0113-netdrv-net-atlantic-make-aq_pci_func_init-static.patch +Patch113: 0114-netdrv-net-atlantic-fix-typo-in-aq_ring_tx_clean.patch +Patch114: 0115-netdrv-net-atlantic-missing-space-in-a-comment-in-aq.patch +Patch115: 0116-netdrv-net-atlantic-add-alignment-checks-in-hw_atl2_.patch +Patch116: 0117-netdrv-net-atlantic-put-ptp-code-under-IS_REACHABLE-.patch +Patch117: 0118-netdrv-net-aquantia-fix-aq_ndev_start_xmit-s-return-.patch +Patch118: 0119-netdrv-net-atlantic-fix-ip-dst-and-ipv6-address-filt.patch +Patch119: 0120-netdrv-net-atlantic-disable-PTP-on-AQC111-AQC112.patch +Patch120: 0121-netdrv-net-atlantic-align-return-value-of-ver_match-.patch +Patch121: 0122-netdrv-net-atlantic-add-support-for-FW-4.x.patch +Patch122: 0123-netdrv-net-atlantic-move-FRAC_PER_NS-to-aq_hw.h.patch +Patch123: 0124-netdrv-net-atlantic-use-simple-assignment-in-_get_st.patch +Patch124: 0125-netdrv-net-atlantic-make-_get_sw_stats-return-count-.patch +Patch125: 0126-netdrv-net-atlantic-split-rx-and-tx-per-queue-stats.patch +Patch126: 0127-netdrv-net-atlantic-use-u64_stats_update_-to-protect.patch +Patch127: 0128-netdrv-net-atlantic-additional-per-queue-stats.patch +Patch128: 0129-netdrv-net-atlantic-PTP-statistics.patch +Patch129: 0130-netdrv-net-atlantic-enable-ipv6-support-for-TCP-LSO-.patch +Patch130: 0131-netdrv-net-atlantic-add-support-for-64-bit-reads-wri.patch +Patch131: 0132-netdrv-net-atlantic-use-U32_MAX-in-aq_hw_utils.c.patch +Patch132: 0133-netdrv-net-atlantic-use-intermediate-variable-to-imp.patch +Patch133: 0134-netdrv-net-atlantic-A0-ntuple-filters.patch +Patch134: 0135-netdrv-net-atlantic-add-hwmon-getter-for-MAC-tempera.patch +Patch135: 0136-netdrv-net-atlantic-fix-PTP-on-AQC10X.patch +Patch136: 0137-netdrv-net-ethernet-aquantia-Fix-wrong-return-value.patch +Patch137: 0138-netdrv-net-atlantic-Use-readx_poll_timeout-for-large.patch +Patch138: 0139-netdrv-net-atlantic-fix-build-when-object-tree-is-se.patch +Patch139: 9000-add-driver-version.patch + +%define findpat %( echo "%""P" ) +%define __find_requires /usr/lib/rpm/redhat/find-requires.ksyms +%define __find_provides /usr/lib/rpm/redhat/find-provides.ksyms %{kmod_name} %{?epoch:%{epoch}:}%{version}-%{release} +%define sbindir %( if [ -d "/sbin" -a \! -h "/sbin" ]; then echo "/sbin"; else echo %{_sbindir}; fi ) +%define dup_state_dir %{_localstatedir}/lib/rpm-state/kmod-dups +%define kver_state_dir %{dup_state_dir}/kver +%define kver_state_file %{kver_state_dir}/%{kmod_kernel_version}.%(arch) +%define dup_module_list %{dup_state_dir}/rpm-kmod-%{kmod_name}-modules + +Name: kmod-redhat-atlantic +Version: %{kmod_driver_version} +Release: %{kmod_rpm_release}%{?dist} +%if "%{kmod_driver_epoch}" != "" +Epoch: %{kmod_driver_epoch} +%endif +Summary: atlantic kernel module for Driver Update Program +Group: System/Kernel +License: GPLv2 +URL: https://www.kernel.org/ +BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) +BuildRequires: %kernel_devel_pkg = %kmod_kernel_version +%if "%{kmod_dist_build_deps}" != "" +BuildRequires: %{kmod_dist_build_deps} +%endif +ExclusiveArch: x86_64 +%global kernel_source() /usr/src/kernels/%{kmod_kernel_version}.$(arch) + +%global _use_internal_dependency_generator 0 +%if "%{?kmod_kernel_version_min}" != "" +Provides: %kernel_modules_pkg >= %{kmod_kernel_version_min}.%{_target_cpu} +%else +Provides: %kernel_modules_pkg = %{kmod_kernel_version_dep}.%{_target_cpu} +%endif +Provides: kmod-%{kmod_name} = %{?epoch:%{epoch}:}%{version}-%{release} +Requires(post): %{sbindir}/weak-modules +Requires(postun): %{sbindir}/weak-modules +Requires: kernel >= 4.18.0-240.el8 + +Requires: kernel < 4.18.0-241.el8 +%if 0 +Requires: firmware(%{kmod_name}) = ENTER_FIRMWARE_VERSION +%endif +%if "%{kmod_build_dependencies}" != "" +BuildRequires: %{kmod_build_dependencies} +%endif +%if "%{kmod_dependencies}" != "" +Requires: %{kmod_dependencies} +%endif +%if "%{kmod_provides}" != "" +Provides: %{kmod_provides} +%endif +# if there are multiple kmods for the same driver from different vendors, +# they should conflict with each other. +Conflicts: kmod-%{kmod_name} + +%description +atlantic kernel module for Driver Update Program + +%if 0 + +%package -n kmod-redhat-atlantic-firmware +Version: ENTER_FIRMWARE_VERSION +Summary: atlantic firmware for Driver Update Program +Provides: firmware(%{kmod_name}) = ENTER_FIRMWARE_VERSION +%if "%{kmod_kernel_version_min}" != "" +Provides: %kernel_modules_pkg >= %{kmod_kernel_version_min}.%{_target_cpu} +%else +Provides: %kernel_modules_pkg = %{kmod_kernel_version_dep}.%{_target_cpu} +%endif +%description -n kmod-redhat-atlantic-firmware +atlantic firmware for Driver Update Program + + +%files -n kmod-redhat-atlantic-firmware +%defattr(644,root,root,755) +%{FIRMWARE_FILES} + +%endif + +# Development package +%if 0%{kmod_devel_package} +%package -n kmod-redhat-atlantic-devel +Version: %{kmod_driver_version} +Requires: kernel >= 4.18.0-240.el8 + +Requires: kernel < 4.18.0-241.el8 +Summary: atlantic development files for Driver Update Program + +%description -n kmod-redhat-atlantic-devel +atlantic development files for Driver Update Program + + +%files -n kmod-redhat-atlantic-devel +%defattr(644,root,root,755) +/lib/modules/%{kmod_rpm_name}-%{kmod_driver_version}/ +%endif + +%post +modules=( $(find /lib/modules/%{kmod_kernel_version}.%(arch)/%{kmod_install_path} | grep '\.ko$') ) +printf '%s\n' "${modules[@]}" | %{sbindir}/weak-modules --add-modules --no-initramfs + +mkdir -p "%{kver_state_dir}" +touch "%{kver_state_file}" + +exit 0 + +%posttrans +# We have to re-implement part of weak-modules here because it doesn't allow +# calling initramfs regeneration separately +if [ -f "%{kver_state_file}" ]; then + kver_base="%{kmod_kernel_version_dep}" + kvers=$(ls -d "/lib/modules/${kver_base%%.*}"*) + + for k_dir in $kvers; do + k="${k_dir#/lib/modules/}" + + tmp_initramfs="/boot/initramfs-$k.tmp" + dst_initramfs="/boot/initramfs-$k.img" + + # The same check as in weak-modules: we assume that the kernel present + # if the symvers file exists. + if [ -e "/boot/symvers-$k.gz" ] || [ -e "$k_dir/symvers.gz" ]; then + /usr/bin/dracut -f "$tmp_initramfs" "$k" || exit 1 + cmp -s "$tmp_initramfs" "$dst_initramfs" + if [ "$?" = 1 ]; then + mv "$tmp_initramfs" "$dst_initramfs" + else + rm -f "$tmp_initramfs" + fi + fi + done + + rm -f "%{kver_state_file}" + rmdir "%{kver_state_dir}" 2> /dev/null +fi + +rmdir "%{dup_state_dir}" 2> /dev/null + +exit 0 + +%preun +if rpm -q --filetriggers kmod 2> /dev/null| grep -q "Trigger for weak-modules call on kmod removal"; then + mkdir -p "%{kver_state_dir}" + touch "%{kver_state_file}" +fi + +mkdir -p "%{dup_state_dir}" +rpm -ql kmod-redhat-atlantic-%{kmod_driver_version}-%{kmod_rpm_release}%{?dist}.$(arch) | \ + grep '\.ko$' > "%{dup_module_list}" + +%postun +if rpm -q --filetriggers kmod 2> /dev/null| grep -q "Trigger for weak-modules call on kmod removal"; then + initramfs_opt="--no-initramfs" +else + initramfs_opt="" +fi + +modules=( $(cat "%{dup_module_list}") ) +rm -f "%{dup_module_list}" +printf '%s\n' "${modules[@]}" | %{sbindir}/weak-modules --remove-modules $initramfs_opt + +rmdir "%{dup_state_dir}" 2> /dev/null + +exit 0 + +%files +%defattr(644,root,root,755) +/lib/modules/%{kmod_kernel_version}.%(arch) +/etc/depmod.d/%{kmod_name}.conf +%doc /usr/share/doc/%{kmod_rpm_name}/greylist.txt + + + +%prep +%setup -n %{kmod_name}-%{kmod_vendor}-%{kmod_driver_version} + +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 +%patch25 -p1 +%patch26 -p1 +%patch27 -p1 +%patch28 -p1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +%patch33 -p1 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 +%patch37 -p1 +%patch38 -p1 +%patch39 -p1 +%patch40 -p1 +%patch41 -p1 +%patch42 -p1 +%patch43 -p1 +%patch44 -p1 +%patch45 -p1 +%patch46 -p1 +%patch47 -p1 +%patch48 -p1 +%patch49 -p1 +%patch50 -p1 +%patch51 -p1 +%patch52 -p1 +%patch53 -p1 +%patch54 -p1 +%patch55 -p1 +%patch56 -p1 +%patch57 -p1 +%patch58 -p1 +%patch59 -p1 +%patch60 -p1 +%patch61 -p1 +%patch62 -p1 +%patch63 -p1 +%patch64 -p1 +%patch65 -p1 +%patch66 -p1 +%patch67 -p1 +%patch68 -p1 +%patch69 -p1 +%patch70 -p1 +%patch71 -p1 +%patch72 -p1 +%patch73 -p1 +%patch74 -p1 +%patch75 -p1 +%patch76 -p1 +%patch77 -p1 +%patch78 -p1 +%patch79 -p1 +%patch80 -p1 +%patch81 -p1 +%patch82 -p1 +%patch83 -p1 +%patch84 -p1 +%patch85 -p1 +%patch86 -p1 +%patch87 -p1 +%patch88 -p1 +%patch89 -p1 +%patch90 -p1 +%patch91 -p1 +%patch92 -p1 +%patch93 -p1 +%patch94 -p1 +%patch95 -p1 +%patch96 -p1 +%patch97 -p1 +%patch98 -p1 +%patch99 -p1 +%patch100 -p1 +%patch101 -p1 +%patch102 -p1 +%patch103 -p1 +%patch104 -p1 +%patch105 -p1 +%patch106 -p1 +%patch107 -p1 +%patch108 -p1 +%patch109 -p1 +%patch110 -p1 +%patch111 -p1 +%patch112 -p1 +%patch113 -p1 +%patch114 -p1 +%patch115 -p1 +%patch116 -p1 +%patch117 -p1 +%patch118 -p1 +%patch119 -p1 +%patch120 -p1 +%patch121 -p1 +%patch122 -p1 +%patch123 -p1 +%patch124 -p1 +%patch125 -p1 +%patch126 -p1 +%patch127 -p1 +%patch128 -p1 +%patch129 -p1 +%patch130 -p1 +%patch131 -p1 +%patch132 -p1 +%patch133 -p1 +%patch134 -p1 +%patch135 -p1 +%patch136 -p1 +%patch137 -p1 +%patch138 -p1 +%patch139 -p1 +set -- * +mkdir source +mv "$@" source/ +mkdir obj + +%build +rm -rf obj +cp -r source obj + +PWD_PATH="$PWD" +%if "%{workaround_no_pwd_rel_path}" != "1" +PWD_PATH=$(realpath --relative-to="%{kernel_source}" . 2>/dev/null || echo "$PWD") +%endif +%{make_build} -C %{kernel_source} V=1 M="$PWD_PATH/obj/%{kmod_kbuild_dir}" \ + NOSTDINC_FLAGS="-I$PWD_PATH/obj/include -I$PWD_PATH/obj/include/uapi %{nil}" \ + EXTRA_CFLAGS="%{nil}" \ + %{nil} +# mark modules executable so that strip-to-file can strip them +find obj/%{kmod_kbuild_dir} -name "*.ko" -type f -exec chmod u+x '{}' + + +whitelist="/lib/modules/kabi-current/kabi_whitelist_%{_target_cpu}" +for modules in $( find obj/%{kmod_kbuild_dir} -name "*.ko" -type f -printf "%{findpat}\n" | sed 's|\.ko$||' | sort -u ) ; do + # update depmod.conf + module_weak_path=$(echo "$modules" | sed 's/[\/]*[^\/]*$//') + if [ -z "$module_weak_path" ]; then + module_weak_path=%{name} + else + module_weak_path=%{name}/$module_weak_path + fi + echo "override $(echo $modules | sed 's/.*\///')" \ + "$(echo "%{kmod_kernel_version_dep}" | + sed 's/\.[^\.]*$//; + s/\([.+?^$\/\\|()\[]\|\]\)/\\\0/g').*" \ + "weak-updates/$module_weak_path" >> source/depmod.conf + + # update greylist + nm -u obj/%{kmod_kbuild_dir}/$modules.ko | sed 's/.*U //' | sed 's/^\.//' | sort -u | while read -r symbol; do + grep -q "^\s*$symbol\$" $whitelist || echo "$symbol" >> source/greylist + done +done +sort -u source/greylist | uniq > source/greylist.txt + +%install +export INSTALL_MOD_PATH=$RPM_BUILD_ROOT +export INSTALL_MOD_DIR=%{kmod_install_path} +PWD_PATH="$PWD" +%if "%{workaround_no_pwd_rel_path}" != "1" +PWD_PATH=$(realpath --relative-to="%{kernel_source}" . 2>/dev/null || echo "$PWD") +%endif +make -C %{kernel_source} modules_install \ + M=$PWD_PATH/obj/%{kmod_kbuild_dir} +# Cleanup unnecessary kernel-generated module dependency files. +find $INSTALL_MOD_PATH/lib/modules -iname 'modules.*' -exec rm {} \; + +install -m 644 -D source/depmod.conf $RPM_BUILD_ROOT/etc/depmod.d/%{kmod_name}.conf +install -m 644 -D source/greylist.txt $RPM_BUILD_ROOT/usr/share/doc/%{kmod_rpm_name}/greylist.txt +%if 0 +%{FIRMWARE_FILES_INSTALL} +%endif +%if 0%{kmod_devel_package} +install -m 644 -D $PWD/obj/%{kmod_kbuild_dir}/Module.symvers $RPM_BUILD_ROOT/lib/modules/%{kmod_rpm_name}-%{kmod_driver_version}/build/Module.symvers + +if [ -n "%{kmod_devel_src_paths}" ]; then + for i in %{kmod_devel_src_paths}; do + mkdir -p "$RPM_BUILD_ROOT/lib/modules/%{kmod_rpm_name}-%{kmod_driver_version}/build/$(dirname "$i")" + cp -rv "$PWD/source/$i" \ + "$RPM_BUILD_ROOT/lib/modules/%{kmod_rpm_name}-%{kmod_driver_version}/build/$i" + done +fi +%endif + + + +%clean +rm -rf $RPM_BUILD_ROOT + +%changelog +* Thu Apr 01 2021 Eugene Syromiatnikov 4.18.0_255.el8_dup8.3-1 +- bfcc924fa05e36abe7a039ac5ec2be581e20c288 +- atlantic kernel module for Driver Update Program +- Resolves: #bz1944615