@@ -961,6 +961,7 @@ static void ice_lag_link_unlink(struct ice_lag *lag, void *ptr)
961961 * @link: Is this a linking activity
962962 *
963963 * If link is false, then primary_swid should be expected to not be valid
964+ * This function should never be called in interrupt context.
964965 */
965966static void
966967ice_lag_set_swid (u16 primary_swid , struct ice_lag * local_lag ,
@@ -970,7 +971,7 @@ ice_lag_set_swid(u16 primary_swid, struct ice_lag *local_lag,
970971 struct ice_aqc_set_port_params * cmd ;
971972 struct ice_aq_desc desc ;
972973 u16 buf_len , swid ;
973- int status ;
974+ int status , i ;
974975
975976 buf_len = struct_size (buf , elem , 1 );
976977 buf = kzalloc (buf_len , GFP_KERNEL );
@@ -1021,15 +1022,28 @@ ice_lag_set_swid(u16 primary_swid, struct ice_lag *local_lag,
10211022 ice_fill_dflt_direct_cmd_desc (& desc , ice_aqc_opc_set_port_params );
10221023
10231024 cmd -> swid = cpu_to_le16 (ICE_AQC_PORT_SWID_VALID | swid );
1024- status = ice_aq_send_cmd (& local_lag -> pf -> hw , & desc , NULL , 0 , NULL );
1025+ /* If this is happening in reset context, it is possible that the
1026+ * primary interface has not finished setting its SWID to SHARED
1027+ * yet. Allow retries to account for this timing issue between
1028+ * interfaces.
1029+ */
1030+ for (i = 0 ; i < ICE_LAG_RESET_RETRIES ; i ++ ) {
1031+ status = ice_aq_send_cmd (& local_lag -> pf -> hw , & desc , NULL , 0 ,
1032+ NULL );
1033+ if (!status )
1034+ break ;
1035+
1036+ usleep_range (1000 , 2000 );
1037+ }
1038+
10251039 if (status )
10261040 dev_err (ice_pf_to_dev (local_lag -> pf ), "Error setting SWID in port params %d\n" ,
10271041 status );
10281042}
10291043
10301044/**
10311045 * ice_lag_primary_swid - set/clear the SHARED attrib of primary's SWID
1032- * @lag: primary interfaces lag struct
1046+ * @lag: primary interface's lag struct
10331047 * @link: is this a linking activity
10341048 *
10351049 * Implement setting primary SWID as shared using 0x020B
@@ -1772,6 +1786,135 @@ static int ice_create_lag_recipe(struct ice_hw *hw, u16 *rid,
17721786 return err ;
17731787}
17741788
1789+ /**
1790+ * ice_lag_move_vf_nodes_tc_sync - move a VF's nodes for a tc during reset
1791+ * @lag: primary interfaces lag struct
1792+ * @dest_hw: HW struct for destination's interface
1793+ * @vsi_num: VSI index in PF space
1794+ * @tc: traffic class to move
1795+ */
1796+ static void
1797+ ice_lag_move_vf_nodes_tc_sync (struct ice_lag * lag , struct ice_hw * dest_hw ,
1798+ u16 vsi_num , u8 tc )
1799+ {
1800+ u16 numq , valq , buf_size , num_moved , qbuf_size ;
1801+ struct device * dev = ice_pf_to_dev (lag -> pf );
1802+ struct ice_aqc_cfg_txqs_buf * qbuf ;
1803+ struct ice_aqc_move_elem * buf ;
1804+ struct ice_sched_node * n_prt ;
1805+ __le32 teid , parent_teid ;
1806+ struct ice_vsi_ctx * ctx ;
1807+ struct ice_hw * hw ;
1808+ u32 tmp_teid ;
1809+
1810+ hw = & lag -> pf -> hw ;
1811+ ctx = ice_get_vsi_ctx (hw , vsi_num );
1812+ if (!ctx ) {
1813+ dev_warn (dev , "LAG rebuild failed after reset due to VSI Context failure\n" );
1814+ return ;
1815+ }
1816+
1817+ if (!ctx -> sched .vsi_node [tc ])
1818+ return ;
1819+
1820+ numq = ctx -> num_lan_q_entries [tc ];
1821+ teid = ctx -> sched .vsi_node [tc ]-> info .node_teid ;
1822+ tmp_teid = le32_to_cpu (teid );
1823+ parent_teid = ctx -> sched .vsi_node [tc ]-> info .parent_teid ;
1824+
1825+ if (!tmp_teid || !numq )
1826+ return ;
1827+
1828+ if (ice_sched_suspend_resume_elems (hw , 1 , & tmp_teid , true))
1829+ dev_dbg (dev , "Problem suspending traffic during reset rebuild\n" );
1830+
1831+ /* reconfig queues for new port */
1832+ qbuf_size = struct_size (qbuf , queue_info , numq );
1833+ qbuf = kzalloc (qbuf_size , GFP_KERNEL );
1834+ if (!qbuf ) {
1835+ dev_warn (dev , "Failure allocating VF queue recfg buffer for reset rebuild\n" );
1836+ goto resume_sync ;
1837+ }
1838+
1839+ /* add the per queue info for the reconfigure command buffer */
1840+ valq = ice_lag_qbuf_recfg (hw , qbuf , vsi_num , numq , tc );
1841+ if (!valq ) {
1842+ dev_warn (dev , "Failure to reconfig queues for LAG reset rebuild\n" );
1843+ goto sync_none ;
1844+ }
1845+
1846+ if (ice_aq_cfg_lan_txq (hw , qbuf , qbuf_size , numq , hw -> port_info -> lport ,
1847+ dest_hw -> port_info -> lport , NULL )) {
1848+ dev_warn (dev , "Failure to configure queues for LAG reset rebuild\n" );
1849+ goto sync_qerr ;
1850+ }
1851+
1852+ sync_none :
1853+ kfree (qbuf );
1854+
1855+ /* find parent in destination tree */
1856+ n_prt = ice_lag_get_sched_parent (dest_hw , tc );
1857+ if (!n_prt )
1858+ goto resume_sync ;
1859+
1860+ /* Move node to new parent */
1861+ buf_size = struct_size (buf , teid , 1 );
1862+ buf = kzalloc (buf_size , GFP_KERNEL );
1863+ if (!buf ) {
1864+ dev_warn (dev , "Failure to alloc for VF node move in reset rebuild\n" );
1865+ goto resume_sync ;
1866+ }
1867+
1868+ buf -> hdr .src_parent_teid = parent_teid ;
1869+ buf -> hdr .dest_parent_teid = n_prt -> info .node_teid ;
1870+ buf -> hdr .num_elems = cpu_to_le16 (1 );
1871+ buf -> hdr .mode = ICE_AQC_MOVE_ELEM_MODE_KEEP_OWN ;
1872+ buf -> teid [0 ] = teid ;
1873+
1874+ if (ice_aq_move_sched_elems (& lag -> pf -> hw , 1 , buf , buf_size , & num_moved ,
1875+ NULL ))
1876+ dev_warn (dev , "Failure to move VF nodes for LAG reset rebuild\n" );
1877+ else
1878+ ice_sched_update_parent (n_prt , ctx -> sched .vsi_node [tc ]);
1879+
1880+ kfree (buf );
1881+ goto resume_sync ;
1882+
1883+ sync_qerr :
1884+ kfree (qbuf );
1885+
1886+ resume_sync :
1887+ if (ice_sched_suspend_resume_elems (hw , 1 , & tmp_teid , false))
1888+ dev_warn (dev , "Problem restarting traffic for LAG node reset rebuild\n" );
1889+ }
1890+
1891+ /**
1892+ * ice_lag_move_vf_nodes_sync - move vf nodes to active interface
1893+ * @lag: primary interfaces lag struct
1894+ * @dest_hw: lport value for currently active port
1895+ *
1896+ * This function is used in a reset context, outside of event handling,
1897+ * to move the VF nodes to the secondary interface when that interface
1898+ * is the active interface during a reset rebuild
1899+ */
1900+ static void
1901+ ice_lag_move_vf_nodes_sync (struct ice_lag * lag , struct ice_hw * dest_hw )
1902+ {
1903+ struct ice_pf * pf ;
1904+ int i , tc ;
1905+
1906+ if (!lag -> primary || !dest_hw )
1907+ return ;
1908+
1909+ pf = lag -> pf ;
1910+ ice_for_each_vsi (pf , i )
1911+ if (pf -> vsi [i ] && (pf -> vsi [i ]-> type == ICE_VSI_VF ||
1912+ pf -> vsi [i ]-> type == ICE_VSI_SWITCHDEV_CTRL ))
1913+ ice_for_each_traffic_class (tc )
1914+ ice_lag_move_vf_nodes_tc_sync (lag , dest_hw , i ,
1915+ tc );
1916+ }
1917+
17751918/**
17761919 * ice_init_lag - initialize support for LAG
17771920 * @pf: PF struct
@@ -1873,3 +2016,85 @@ void ice_deinit_lag(struct ice_pf *pf)
18732016
18742017 pf -> lag = NULL ;
18752018}
2019+
2020+ /**
2021+ * ice_lag_rebuild - rebuild lag resources after reset
2022+ * @pf: pointer to local pf struct
2023+ *
2024+ * PF resets are promoted to CORER resets when interface in an aggregate. This
2025+ * means that we need to rebuild the PF resources for the interface. Since
2026+ * this will happen outside the normal event processing, need to acquire the lag
2027+ * lock.
2028+ *
2029+ * This function will also evaluate the VF resources if this is the primary
2030+ * interface.
2031+ */
2032+ void ice_lag_rebuild (struct ice_pf * pf )
2033+ {
2034+ struct ice_lag_netdev_list ndlist ;
2035+ struct ice_lag * lag , * prim_lag ;
2036+ struct list_head * tmp , * n ;
2037+ u8 act_port , loc_port ;
2038+
2039+ if (!pf -> lag || !pf -> lag -> bonded )
2040+ return ;
2041+
2042+ mutex_lock (& pf -> lag_mutex );
2043+
2044+ lag = pf -> lag ;
2045+ if (lag -> primary ) {
2046+ prim_lag = lag ;
2047+ } else {
2048+ struct ice_lag_netdev_list * nl ;
2049+ struct net_device * tmp_nd ;
2050+
2051+ INIT_LIST_HEAD (& ndlist .node );
2052+ rcu_read_lock ();
2053+ for_each_netdev_in_bond_rcu (lag -> upper_netdev , tmp_nd ) {
2054+ nl = kzalloc (sizeof (* nl ), GFP_KERNEL );
2055+ if (!nl )
2056+ break ;
2057+
2058+ nl -> netdev = tmp_nd ;
2059+ list_add (& nl -> node , & ndlist .node );
2060+ }
2061+ rcu_read_unlock ();
2062+ lag -> netdev_head = & ndlist .node ;
2063+ prim_lag = ice_lag_find_primary (lag );
2064+ }
2065+
2066+ if (!prim_lag ) {
2067+ dev_dbg (ice_pf_to_dev (pf ), "No primary interface in aggregate, can't rebuild\n" );
2068+ goto lag_rebuild_out ;
2069+ }
2070+
2071+ act_port = prim_lag -> active_port ;
2072+ loc_port = lag -> pf -> hw .port_info -> lport ;
2073+
2074+ /* configure SWID for this port */
2075+ if (lag -> primary ) {
2076+ ice_lag_primary_swid (lag , true);
2077+ } else {
2078+ ice_lag_set_swid (prim_lag -> pf -> hw .port_info -> sw_id , lag , true);
2079+ ice_lag_add_prune_list (prim_lag , pf );
2080+ if (act_port == loc_port )
2081+ ice_lag_move_vf_nodes_sync (prim_lag , & pf -> hw );
2082+ }
2083+
2084+ ice_lag_cfg_cp_fltr (lag , true);
2085+
2086+ if (lag -> pf_rule_id )
2087+ if (ice_lag_cfg_dflt_fltr (lag , true))
2088+ dev_err (ice_pf_to_dev (pf ), "Error adding default VSI rule in rebuild\n" );
2089+
2090+ ice_clear_rdma_cap (pf );
2091+ lag_rebuild_out :
2092+ list_for_each_safe (tmp , n , & ndlist .node ) {
2093+ struct ice_lag_netdev_list * entry ;
2094+
2095+ entry = list_entry (tmp , struct ice_lag_netdev_list , node );
2096+ list_del (& entry -> node );
2097+ kfree (entry );
2098+ }
2099+ mutex_unlock (& pf -> lag_mutex );
2100+ }
0 commit comments