diff mbox series

[iwl-next,v6,02/10] ice: Add driver support for firmware changes for LAG

Message ID 20230517230028.321350-3-david.m.ertman@intel.com
State Changes Requested
Headers show
Series ice: Implement support for SRIOV + LAG | expand

Commit Message

Dave Ertman May 17, 2023, 11 p.m. UTC
Add the defines, fields, and detection code for FW support of LAG for
SRIOV.  Also exposes some previously static functions to allow access
in the lag code.

Clean up code that is unused or not needed for LAG support.  Also add
a ordered workqueue for processing LAG events.

Signed-off-by: Dave Ertman <david.m.ertman@intel.com>
---
 drivers/net/ethernet/intel/ice/ice.h          |  5 ++
 .../net/ethernet/intel/ice/ice_adminq_cmd.h   |  3 ++
 drivers/net/ethernet/intel/ice/ice_common.c   |  9 +++-
 drivers/net/ethernet/intel/ice/ice_lag.c      | 53 ++++++++++---------
 drivers/net/ethernet/intel/ice/ice_lib.c      |  2 +-
 drivers/net/ethernet/intel/ice/ice_lib.h      |  1 +
 drivers/net/ethernet/intel/ice/ice_main.c     | 12 +++++
 drivers/net/ethernet/intel/ice/ice_type.h     |  2 +
 8 files changed, 59 insertions(+), 28 deletions(-)

Comments

kernel test robot May 18, 2023, 4:33 a.m. UTC | #1
Hi Dave,

kernel test robot noticed the following build warnings:

[auto build test WARNING on tnguy-next-queue/dev-queue]

url:    https://github.com/intel-lab-lkp/linux/commits/Dave-Ertman/ice-Correctly-initialize-queue-context-values/20230518-070823
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue.git dev-queue
patch link:    https://lore.kernel.org/r/20230517230028.321350-3-david.m.ertman%40intel.com
patch subject: [Intel-wired-lan] [PATCH iwl-next v6 02/10] ice: Add driver support for firmware changes for LAG
config: i386-randconfig-a013
compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project f28c006a5895fc0e329fe15fead81e37457cb1d1)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/f417c72c01f3210959baa45e51dd59cc7be16688
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Dave-Ertman/ice-Correctly-initialize-queue-context-values/20230518-070823
        git checkout f417c72c01f3210959baa45e51dd59cc7be16688
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/net/ethernet/intel/ice/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202305181101.gCbJ4JDT-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/net/ethernet/intel/ice/ice_common.c:2255:31: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand]
                   caps->sriov_lag = !!(number && ICE_AQC_BIT_SRIOV_LAG);
                                               ^  ~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ice/ice_common.c:2255:31: note: use '&' for a bitwise operation
                   caps->sriov_lag = !!(number && ICE_AQC_BIT_SRIOV_LAG);
                                               ^~
                                               &
   drivers/net/ethernet/intel/ice/ice_common.c:2255:31: note: remove constant to silence this warning
                   caps->sriov_lag = !!(number && ICE_AQC_BIT_SRIOV_LAG);
                                              ~^~~~~~~~~~~~~~~~~~~~~~~~
   1 warning generated.


vim +2255 drivers/net/ethernet/intel/ice/ice_common.c

  2132	
  2133	/**
  2134	 * ice_parse_common_caps - parse common device/function capabilities
  2135	 * @hw: pointer to the HW struct
  2136	 * @caps: pointer to common capabilities structure
  2137	 * @elem: the capability element to parse
  2138	 * @prefix: message prefix for tracing capabilities
  2139	 *
  2140	 * Given a capability element, extract relevant details into the common
  2141	 * capability structure.
  2142	 *
  2143	 * Returns: true if the capability matches one of the common capability ids,
  2144	 * false otherwise.
  2145	 */
  2146	static bool
  2147	ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
  2148			      struct ice_aqc_list_caps_elem *elem, const char *prefix)
  2149	{
  2150		u32 logical_id = le32_to_cpu(elem->logical_id);
  2151		u32 phys_id = le32_to_cpu(elem->phys_id);
  2152		u32 number = le32_to_cpu(elem->number);
  2153		u16 cap = le16_to_cpu(elem->cap);
  2154		bool found = true;
  2155	
  2156		switch (cap) {
  2157		case ICE_AQC_CAPS_VALID_FUNCTIONS:
  2158			caps->valid_functions = number;
  2159			ice_debug(hw, ICE_DBG_INIT, "%s: valid_functions (bitmap) = %d\n", prefix,
  2160				  caps->valid_functions);
  2161			break;
  2162		case ICE_AQC_CAPS_SRIOV:
  2163			caps->sr_iov_1_1 = (number == 1);
  2164			ice_debug(hw, ICE_DBG_INIT, "%s: sr_iov_1_1 = %d\n", prefix,
  2165				  caps->sr_iov_1_1);
  2166			break;
  2167		case ICE_AQC_CAPS_DCB:
  2168			caps->dcb = (number == 1);
  2169			caps->active_tc_bitmap = logical_id;
  2170			caps->maxtc = phys_id;
  2171			ice_debug(hw, ICE_DBG_INIT, "%s: dcb = %d\n", prefix, caps->dcb);
  2172			ice_debug(hw, ICE_DBG_INIT, "%s: active_tc_bitmap = %d\n", prefix,
  2173				  caps->active_tc_bitmap);
  2174			ice_debug(hw, ICE_DBG_INIT, "%s: maxtc = %d\n", prefix, caps->maxtc);
  2175			break;
  2176		case ICE_AQC_CAPS_RSS:
  2177			caps->rss_table_size = number;
  2178			caps->rss_table_entry_width = logical_id;
  2179			ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_size = %d\n", prefix,
  2180				  caps->rss_table_size);
  2181			ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_entry_width = %d\n", prefix,
  2182				  caps->rss_table_entry_width);
  2183			break;
  2184		case ICE_AQC_CAPS_RXQS:
  2185			caps->num_rxq = number;
  2186			caps->rxq_first_id = phys_id;
  2187			ice_debug(hw, ICE_DBG_INIT, "%s: num_rxq = %d\n", prefix,
  2188				  caps->num_rxq);
  2189			ice_debug(hw, ICE_DBG_INIT, "%s: rxq_first_id = %d\n", prefix,
  2190				  caps->rxq_first_id);
  2191			break;
  2192		case ICE_AQC_CAPS_TXQS:
  2193			caps->num_txq = number;
  2194			caps->txq_first_id = phys_id;
  2195			ice_debug(hw, ICE_DBG_INIT, "%s: num_txq = %d\n", prefix,
  2196				  caps->num_txq);
  2197			ice_debug(hw, ICE_DBG_INIT, "%s: txq_first_id = %d\n", prefix,
  2198				  caps->txq_first_id);
  2199			break;
  2200		case ICE_AQC_CAPS_MSIX:
  2201			caps->num_msix_vectors = number;
  2202			caps->msix_vector_first_id = phys_id;
  2203			ice_debug(hw, ICE_DBG_INIT, "%s: num_msix_vectors = %d\n", prefix,
  2204				  caps->num_msix_vectors);
  2205			ice_debug(hw, ICE_DBG_INIT, "%s: msix_vector_first_id = %d\n", prefix,
  2206				  caps->msix_vector_first_id);
  2207			break;
  2208		case ICE_AQC_CAPS_PENDING_NVM_VER:
  2209			caps->nvm_update_pending_nvm = true;
  2210			ice_debug(hw, ICE_DBG_INIT, "%s: update_pending_nvm\n", prefix);
  2211			break;
  2212		case ICE_AQC_CAPS_PENDING_OROM_VER:
  2213			caps->nvm_update_pending_orom = true;
  2214			ice_debug(hw, ICE_DBG_INIT, "%s: update_pending_orom\n", prefix);
  2215			break;
  2216		case ICE_AQC_CAPS_PENDING_NET_VER:
  2217			caps->nvm_update_pending_netlist = true;
  2218			ice_debug(hw, ICE_DBG_INIT, "%s: update_pending_netlist\n", prefix);
  2219			break;
  2220		case ICE_AQC_CAPS_NVM_MGMT:
  2221			caps->nvm_unified_update =
  2222				(number & ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT) ?
  2223				true : false;
  2224			ice_debug(hw, ICE_DBG_INIT, "%s: nvm_unified_update = %d\n", prefix,
  2225				  caps->nvm_unified_update);
  2226			break;
  2227		case ICE_AQC_CAPS_RDMA:
  2228			caps->rdma = (number == 1);
  2229			ice_debug(hw, ICE_DBG_INIT, "%s: rdma = %d\n", prefix, caps->rdma);
  2230			break;
  2231		case ICE_AQC_CAPS_MAX_MTU:
  2232			caps->max_mtu = number;
  2233			ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n",
  2234				  prefix, caps->max_mtu);
  2235			break;
  2236		case ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE:
  2237			caps->pcie_reset_avoidance = (number > 0);
  2238			ice_debug(hw, ICE_DBG_INIT,
  2239				  "%s: pcie_reset_avoidance = %d\n", prefix,
  2240				  caps->pcie_reset_avoidance);
  2241			break;
  2242		case ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT:
  2243			caps->reset_restrict_support = (number == 1);
  2244			ice_debug(hw, ICE_DBG_INIT,
  2245				  "%s: reset_restrict_support = %d\n", prefix,
  2246				  caps->reset_restrict_support);
  2247			break;
  2248		case ICE_AQC_CAPS_TX_SCHED_TOPO_COMP_MODE:
  2249			caps->tx_sched_topo_comp_mode_en = (number == 1);
  2250			break;
  2251		case ICE_AQC_CAPS_FW_LAG_SUPPORT:
  2252			caps->roce_lag = !!(number && ICE_AQC_BIT_ROCEV2_LAG);
  2253			ice_debug(hw, ICE_DBG_INIT, "%s: roce_lag = %d\n",
  2254				  prefix, caps->roce_lag);
> 2255			caps->sriov_lag = !!(number && ICE_AQC_BIT_SRIOV_LAG);
  2256			ice_debug(hw, ICE_DBG_INIT, "%s: sriov_lag = %d\n",
  2257				  prefix, caps->sriov_lag);
  2258			break;
  2259		default:
  2260			/* Not one of the recognized common capabilities */
  2261			found = false;
  2262		}
  2263	
  2264		return found;
  2265	}
  2266
Romanowski, Rafal Feb. 26, 2024, 9:38 a.m. UTC | #2
> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of
> kernel test robot
> Sent: Thursday, May 18, 2023 6:34 AM
> To: Ertman, David M <david.m.ertman@intel.com>; intel-wired-
> lan@lists.osuosl.org
> Cc: llvm@lists.linux.dev; oe-kbuild-all@lists.linux.dev
> Subject: Re: [Intel-wired-lan] [PATCH iwl-next v6 02/10] ice: Add driver
> support for firmware changes for LAG
> 
> Hi Dave,
> 
> kernel test robot noticed the following build warnings:
> 
> [auto build test WARNING on tnguy-next-queue/dev-queue]
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Dave-Ertman/ice-
> Correctly-initialize-queue-context-values/20230518-070823
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue.git
> dev-queue
> patch link:    https://lore.kernel.org/r/20230517230028.321350-3-
> david.m.ertman%40intel.com
> patch subject: [Intel-wired-lan] [PATCH iwl-next v6 02/10] ice: Add driver
> support for firmware changes for LAG
> config: i386-randconfig-a013
> compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project
> f28c006a5895fc0e329fe15fead81e37457cb1d1)
> reproduce (this is a W=1 build):
>         wget https://raw.githubusercontent.com/intel/lkp-
> tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # https://github.com/intel-lab-
> lkp/linux/commit/f417c72c01f3210959baa45e51dd59cc7be16688
>         git remote add linux-review https://github.com/intel-lab-lkp/linux
>         git fetch --no-tags linux-review Dave-Ertman/ice-Correctly-initialize-
> queue-context-values/20230518-070823
>         git checkout f417c72c01f3210959baa45e51dd59cc7be16688
>         # save the config file
>         mkdir build_dir && cp config build_dir/.config
>         COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross
> W=1 O=build_dir ARCH=i386 olddefconfig
>         COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross
> W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/net/ethernet/intel/ice/
> 
> If you fix the issue, kindly add following tag where applicable
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202305181101.gCbJ4JDT-
> lkp@intel.com/
> 
> All warnings (new ones prefixed by >>):
> 
> >> drivers/net/ethernet/intel/ice/ice_common.c:2255:31: warning: use of
> logical '&&' with constant operand [-Wconstant-logical-operand]
>                    caps->sriov_lag = !!(number && ICE_AQC_BIT_SRIOV_LAG);
>                                                ^  ~~~~~~~~~~~~~~~~~~~~~
>    drivers/net/ethernet/intel/ice/ice_common.c:2255:31: note: use '&' for a
> bitwise operation
>                    caps->sriov_lag = !!(number && ICE_AQC_BIT_SRIOV_LAG);
>                                                ^~
>                                                &
>    drivers/net/ethernet/intel/ice/ice_common.c:2255:31: note: remove
> constant to silence this warning
>                    caps->sriov_lag = !!(number && ICE_AQC_BIT_SRIOV_LAG);
>                                               ~^~~~~~~~~~~~~~~~~~~~~~~~
>    1 warning generated.
> 
> 
> vim +2255 drivers/net/ethernet/intel/ice/ice_common.c
> 
>   2132
>   2133	/**
>   2134	 * ice_parse_common_caps - parse common device/function
> capabilities
>   2135	 * @hw: pointer to the HW struct
>   2136	 * @caps: pointer to common capabilities structure
>   2137	 * @elem: the capability element to parse
>   2138	 * @prefix: message prefix for tracing capabilities
>   2139	 *
>   2140	 * Given a capability element, extract relevant details into the common
>   2141	 * capability structure.
>   2142	 *
>   2143	 * Returns: true if the capability matches one of the common capability
> ids,
>   2144	 * false otherwise.
>   2145	 */
>   2146	static bool
>   2147	ice_parse_common_caps(struct ice_hw *hw, struct
> ice_hw_common_caps *caps,
>   2148			      struct ice_aqc_list_caps_elem *elem, const char
> *prefix)
>   2149	{
>   2150		u32 logical_id = le32_to_cpu(elem->logical_id);
>   2151		u32 phys_id = le32_to_cpu(elem->phys_id);
>   2152		u32 number = le32_to_cpu(elem->number);
>   2153		u16 cap = le16_to_cpu(elem->cap);
>   2154		bool found = true;
>   2155
>   2156		switch (cap) {
>   2157		case ICE_AQC_CAPS_VALID_FUNCTIONS:
>   2158			caps->valid_functions = number;
>   2159			ice_debug(hw, ICE_DBG_INIT, "%s: valid_functions
> (bitmap) = %d\n", prefix,
>   2160				  caps->valid_functions);
>   2161			break;
>   2162		case ICE_AQC_CAPS_SRIOV:
>   2163			caps->sr_iov_1_1 = (number == 1);
>   2164			ice_debug(hw, ICE_DBG_INIT, "%s: sr_iov_1_1 =
> %d\n", prefix,
>   2165				  caps->sr_iov_1_1);
>   2166			break;
>   2167		case ICE_AQC_CAPS_DCB:
>   2168			caps->dcb = (number == 1);
>   2169			caps->active_tc_bitmap = logical_id;
>   2170			caps->maxtc = phys_id;
>   2171			ice_debug(hw, ICE_DBG_INIT, "%s: dcb = %d\n",
> prefix, caps->dcb);
>   2172			ice_debug(hw, ICE_DBG_INIT, "%s: active_tc_bitmap =
> %d\n", prefix,
>   2173				  caps->active_tc_bitmap);
>   2174			ice_debug(hw, ICE_DBG_INIT, "%s: maxtc = %d\n",
> prefix, caps->maxtc);
>   2175			break;
>   2176		case ICE_AQC_CAPS_RSS:
>   2177			caps->rss_table_size = number;
>   2178			caps->rss_table_entry_width = logical_id;
>   2179			ice_debug(hw, ICE_DBG_INIT, "%s: rss_table_size =
> %d\n", prefix,
>   2180				  caps->rss_table_size);
>   2181			ice_debug(hw, ICE_DBG_INIT, "%s:
> rss_table_entry_width = %d\n", prefix,
>   2182				  caps->rss_table_entry_width);
>   2183			break;
>   2184		case ICE_AQC_CAPS_RXQS:
>   2185			caps->num_rxq = number;
>   2186			caps->rxq_first_id = phys_id;
>   2187			ice_debug(hw, ICE_DBG_INIT, "%s: num_rxq = %d\n",
> prefix,
>   2188				  caps->num_rxq);
>   2189			ice_debug(hw, ICE_DBG_INIT, "%s: rxq_first_id =
> %d\n", prefix,
>   2190				  caps->rxq_first_id);
>   2191			break;
>   2192		case ICE_AQC_CAPS_TXQS:
>   2193			caps->num_txq = number;
>   2194			caps->txq_first_id = phys_id;
>   2195			ice_debug(hw, ICE_DBG_INIT, "%s: num_txq = %d\n",
> prefix,
>   2196				  caps->num_txq);
>   2197			ice_debug(hw, ICE_DBG_INIT, "%s: txq_first_id =
> %d\n", prefix,
>   2198				  caps->txq_first_id);
>   2199			break;
>   2200		case ICE_AQC_CAPS_MSIX:
>   2201			caps->num_msix_vectors = number;
>   2202			caps->msix_vector_first_id = phys_id;
>   2203			ice_debug(hw, ICE_DBG_INIT, "%s: num_msix_vectors
> = %d\n", prefix,
>   2204				  caps->num_msix_vectors);
>   2205			ice_debug(hw, ICE_DBG_INIT, "%s:
> msix_vector_first_id = %d\n", prefix,
>   2206				  caps->msix_vector_first_id);
>   2207			break;
>   2208		case ICE_AQC_CAPS_PENDING_NVM_VER:
>   2209			caps->nvm_update_pending_nvm = true;
>   2210			ice_debug(hw, ICE_DBG_INIT, "%s:
> update_pending_nvm\n", prefix);
>   2211			break;
>   2212		case ICE_AQC_CAPS_PENDING_OROM_VER:
>   2213			caps->nvm_update_pending_orom = true;
>   2214			ice_debug(hw, ICE_DBG_INIT, "%s:
> update_pending_orom\n", prefix);
>   2215			break;
>   2216		case ICE_AQC_CAPS_PENDING_NET_VER:
>   2217			caps->nvm_update_pending_netlist = true;
>   2218			ice_debug(hw, ICE_DBG_INIT, "%s:
> update_pending_netlist\n", prefix);
>   2219			break;
>   2220		case ICE_AQC_CAPS_NVM_MGMT:
>   2221			caps->nvm_unified_update =
>   2222				(number &
> ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT) ?
>   2223				true : false;
>   2224			ice_debug(hw, ICE_DBG_INIT, "%s:
> nvm_unified_update = %d\n", prefix,
>   2225				  caps->nvm_unified_update);
>   2226			break;
>   2227		case ICE_AQC_CAPS_RDMA:
>   2228			caps->rdma = (number == 1);
>   2229			ice_debug(hw, ICE_DBG_INIT, "%s: rdma = %d\n",
> prefix, caps->rdma);
>   2230			break;
>   2231		case ICE_AQC_CAPS_MAX_MTU:
>   2232			caps->max_mtu = number;
>   2233			ice_debug(hw, ICE_DBG_INIT, "%s: max_mtu = %d\n",
>   2234				  prefix, caps->max_mtu);
>   2235			break;
>   2236		case ICE_AQC_CAPS_PCIE_RESET_AVOIDANCE:
>   2237			caps->pcie_reset_avoidance = (number > 0);
>   2238			ice_debug(hw, ICE_DBG_INIT,
>   2239				  "%s: pcie_reset_avoidance = %d\n", prefix,
>   2240				  caps->pcie_reset_avoidance);
>   2241			break;
>   2242		case ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT:
>   2243			caps->reset_restrict_support = (number == 1);
>   2244			ice_debug(hw, ICE_DBG_INIT,
>   2245				  "%s: reset_restrict_support = %d\n", prefix,
>   2246				  caps->reset_restrict_support);
>   2247			break;
>   2248		case ICE_AQC_CAPS_TX_SCHED_TOPO_COMP_MODE:
>   2249			caps->tx_sched_topo_comp_mode_en = (number ==
> 1);
>   2250			break;
>   2251		case ICE_AQC_CAPS_FW_LAG_SUPPORT:
>   2252			caps->roce_lag = !!(number &&
> ICE_AQC_BIT_ROCEV2_LAG);
>   2253			ice_debug(hw, ICE_DBG_INIT, "%s: roce_lag = %d\n",
>   2254				  prefix, caps->roce_lag);
> > 2255			caps->sriov_lag = !!(number &&
> ICE_AQC_BIT_SRIOV_LAG);
>   2256			ice_debug(hw, ICE_DBG_INIT, "%s: sriov_lag = %d\n",
>   2257				  prefix, caps->sriov_lag);
>   2258			break;
>   2259		default:
>   2260			/* Not one of the recognized common capabilities */
>   2261			found = false;
>   2262		}
>   2263
>   2264		return found;
>   2265	}
>   2266
> 
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki


Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
diff mbox series

Patch

diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index b4bca1d964a9..7a2f93c0c3f2 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -200,6 +200,8 @@  enum ice_feature {
 	ICE_F_PTP_EXTTS,
 	ICE_F_SMA_CTRL,
 	ICE_F_GNSS,
+	ICE_F_ROCE_LAG,
+	ICE_F_SRIOV_LAG,
 	ICE_F_MAX
 };
 
@@ -560,6 +562,7 @@  struct ice_pf {
 	struct mutex sw_mutex;		/* lock for protecting VSI alloc flow */
 	struct mutex tc_mutex;		/* lock to protect TC changes */
 	struct mutex adev_mutex;	/* lock to protect aux device access */
+	struct mutex lag_mutex;		/* protect ice_lag struct in PF */
 	u32 msg_enable;
 	struct ice_ptp ptp;
 	struct gnss_serial *gnss_serial;
@@ -629,6 +632,8 @@  struct ice_pf {
 	struct ice_agg_node vf_agg_node[ICE_MAX_VF_AGG_NODES];
 };
 
+extern struct workqueue_struct *ice_lag_wq;
+
 struct ice_netdev_priv {
 	struct ice_vsi *vsi;
 	struct ice_repr *repr;
diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
index 8a624cef0eb0..05ae65f1dd27 100644
--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
@@ -121,6 +121,9 @@  struct ice_aqc_list_caps_elem {
 #define ICE_AQC_CAPS_POST_UPDATE_RESET_RESTRICT		0x0077
 #define ICE_AQC_CAPS_NVM_MGMT				0x0080
 #define ICE_AQC_CAPS_TX_SCHED_TOPO_COMP_MODE		0x0085
+#define ICE_AQC_CAPS_FW_LAG_SUPPORT			0x0092
+#define ICE_AQC_BIT_ROCEV2_LAG				0x01
+#define ICE_AQC_BIT_SRIOV_LAG				0x02
 
 	u8 major_ver;
 	u8 minor_ver;
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index 23a9f169bc71..3a3538c002ae 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -2248,7 +2248,14 @@  ice_parse_common_caps(struct ice_hw *hw, struct ice_hw_common_caps *caps,
 	case ICE_AQC_CAPS_TX_SCHED_TOPO_COMP_MODE:
 		caps->tx_sched_topo_comp_mode_en = (number == 1);
 		break;
-
+	case ICE_AQC_CAPS_FW_LAG_SUPPORT:
+		caps->roce_lag = !!(number && ICE_AQC_BIT_ROCEV2_LAG);
+		ice_debug(hw, ICE_DBG_INIT, "%s: roce_lag = %d\n",
+			  prefix, caps->roce_lag);
+		caps->sriov_lag = !!(number && ICE_AQC_BIT_SRIOV_LAG);
+		ice_debug(hw, ICE_DBG_INIT, "%s: sriov_lag = %d\n",
+			  prefix, caps->sriov_lag);
+		break;
 	default:
 		/* Not one of the recognized common capabilities */
 		found = false;
diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c
index 5a7753bda324..73bfc5cd8b37 100644
--- a/drivers/net/ethernet/intel/ice/ice_lag.c
+++ b/drivers/net/ethernet/intel/ice/ice_lag.c
@@ -4,8 +4,12 @@ 
 /* Link Aggregation code */
 
 #include "ice.h"
+#include "ice_lib.h"
 #include "ice_lag.h"
 
+#define ICE_LAG_RES_SHARED	BIT(14)
+#define ICE_LAG_RES_VALID	BIT(15)
+
 /**
  * ice_lag_set_primary - set PF LAG state as Primary
  * @lag: LAG info struct
@@ -225,6 +229,26 @@  static void ice_lag_unregister(struct ice_lag *lag, struct net_device *netdev)
 	lag->role = ICE_LAG_NONE;
 }
 
+/**
+ * ice_lag_check_nvm_support - Check for NVM support for LAG
+ * @pf: PF struct
+ */
+static void ice_lag_check_nvm_support(struct ice_pf *pf)
+{
+	struct ice_hw_dev_caps *caps;
+
+	caps = &pf->hw.dev_caps;
+	if (caps->common_cap.roce_lag)
+		ice_set_feature_support(pf, ICE_F_ROCE_LAG);
+	else
+		ice_clear_feature_support(pf, ICE_F_ROCE_LAG);
+
+	if (caps->common_cap.sriov_lag)
+		ice_set_feature_support(pf, ICE_F_SRIOV_LAG);
+	else
+		ice_clear_feature_support(pf, ICE_F_SRIOV_LAG);
+}
+
 /**
  * ice_lag_changeupper_event - handle LAG changeupper event
  * @lag: LAG info struct
@@ -264,26 +288,6 @@  static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr)
 	ice_display_lag_info(lag);
 }
 
-/**
- * ice_lag_changelower_event - handle LAG changelower event
- * @lag: LAG info struct
- * @ptr: opaque data pointer
- *
- * ptr to be cast to netdev_notifier_changelowerstate_info
- */
-static void ice_lag_changelower_event(struct ice_lag *lag, void *ptr)
-{
-	struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
-
-	if (netdev != lag->netdev)
-		return;
-
-	netdev_dbg(netdev, "bonding info\n");
-
-	if (!netif_is_lag_port(netdev))
-		netdev_dbg(netdev, "CHANGELOWER rcvd, but netdev not in LAG. Bail\n");
-}
-
 /**
  * ice_lag_event_handler - handle LAG events from netdev
  * @notif_blk: notifier block registered by this netdev
@@ -310,9 +314,6 @@  ice_lag_event_handler(struct notifier_block *notif_blk, unsigned long event,
 	case NETDEV_CHANGEUPPER:
 		ice_lag_changeupper_event(lag, ptr);
 		break;
-	case NETDEV_CHANGELOWERSTATE:
-		ice_lag_changelower_event(lag, ptr);
-		break;
 	case NETDEV_BONDING_INFO:
 		ice_lag_info_event(lag, ptr);
 		break;
@@ -379,6 +380,8 @@  int ice_init_lag(struct ice_pf *pf)
 	struct ice_vsi *vsi;
 	int err;
 
+	ice_lag_check_nvm_support(pf);
+
 	pf->lag = kzalloc(sizeof(*lag), GFP_KERNEL);
 	if (!pf->lag)
 		return -ENOMEM;
@@ -435,9 +438,7 @@  void ice_deinit_lag(struct ice_pf *pf)
 	if (lag->pf)
 		ice_unregister_lag_handler(lag);
 
-	dev_put(lag->upper_netdev);
-
-	dev_put(lag->peer_netdev);
+	flush_workqueue(ice_lag_wq);
 
 	kfree(lag);
 
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index 5ddb95d1073a..7b98655ceeeb 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -4011,7 +4011,7 @@  bool ice_is_feature_supported(struct ice_pf *pf, enum ice_feature f)
  * @pf: pointer to the struct ice_pf instance
  * @f: feature enum to set
  */
-static void ice_set_feature_support(struct ice_pf *pf, enum ice_feature f)
+void ice_set_feature_support(struct ice_pf *pf, enum ice_feature f)
 {
 	if (f < 0 || f >= ICE_F_MAX)
 		return;
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
index e985766e6bb5..d35fb628d7c6 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_lib.h
@@ -162,6 +162,7 @@  int ice_vsi_del_vlan_zero(struct ice_vsi *vsi);
 bool ice_vsi_has_non_zero_vlans(struct ice_vsi *vsi);
 u16 ice_vsi_num_non_zero_vlans(struct ice_vsi *vsi);
 bool ice_is_feature_supported(struct ice_pf *pf, enum ice_feature f);
+void ice_set_feature_support(struct ice_pf *pf, enum ice_feature f);
 void ice_clear_feature_support(struct ice_pf *pf, enum ice_feature f);
 void ice_init_feature_support(struct ice_pf *pf);
 bool ice_vsi_is_rx_queue_active(struct ice_vsi *vsi);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index b0d1e6116eb9..7030b2e54d2b 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -64,6 +64,7 @@  struct device *ice_hw_to_dev(struct ice_hw *hw)
 }
 
 static struct workqueue_struct *ice_wq;
+struct workqueue_struct *ice_lag_wq;
 static const struct net_device_ops ice_netdev_safe_mode_ops;
 static const struct net_device_ops ice_netdev_ops;
 
@@ -3780,6 +3781,7 @@  u16 ice_get_avail_rxq_count(struct ice_pf *pf)
 static void ice_deinit_pf(struct ice_pf *pf)
 {
 	ice_service_task_stop(pf);
+	mutex_destroy(&pf->lag_mutex);
 	mutex_destroy(&pf->adev_mutex);
 	mutex_destroy(&pf->sw_mutex);
 	mutex_destroy(&pf->tc_mutex);
@@ -3860,6 +3862,7 @@  static int ice_init_pf(struct ice_pf *pf)
 	mutex_init(&pf->sw_mutex);
 	mutex_init(&pf->tc_mutex);
 	mutex_init(&pf->adev_mutex);
+	mutex_init(&pf->lag_mutex);
 
 	INIT_HLIST_HEAD(&pf->aq_wait_list);
 	spin_lock_init(&pf->aq_wait_lock);
@@ -5640,10 +5643,18 @@  static int __init ice_module_init(void)
 		return -ENOMEM;
 	}
 
+	ice_lag_wq = alloc_ordered_workqueue("ice_lag_wq", 0);
+	if (!ice_lag_wq) {
+		pr_err("Failed to create LAG workqueue\n");
+		destroy_workqueue(ice_wq);
+		return -ENOMEM;
+	}
+
 	status = pci_register_driver(&ice_driver);
 	if (status) {
 		pr_err("failed to register PCI driver, err %d\n", status);
 		destroy_workqueue(ice_wq);
+		destroy_workqueue(ice_lag_wq);
 	}
 
 	return status;
@@ -5660,6 +5671,7 @@  static void __exit ice_module_exit(void)
 {
 	pci_unregister_driver(&ice_driver);
 	destroy_workqueue(ice_wq);
+	destroy_workqueue(ice_lag_wq);
 	pr_info("module unloaded\n");
 }
 module_exit(ice_module_exit);
diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
index 5602695243a8..460ec75f162b 100644
--- a/drivers/net/ethernet/intel/ice/ice_type.h
+++ b/drivers/net/ethernet/intel/ice/ice_type.h
@@ -277,6 +277,8 @@  struct ice_hw_common_caps {
 	u8 dcb;
 	u8 ieee_1588;
 	u8 rdma;
+	u8 roce_lag;
+	u8 sriov_lag;
 
 	bool nvm_update_pending_nvm;
 	bool nvm_update_pending_orom;