Skip to content

Commit 3579aa8

Browse files
dmertmananguy11
authored andcommitted
ice: update reset path for SRIOV LAG support
Add code to rebuild the LAG resources when rebuilding the state of the interface after a reset. Also added in a function for building per-queue information into the buffer used to configure VF queues for LAG fail-over. This improves code reuse. Due to differences in timing per interface for recovering from a reset, add in the ability to retry on non-local dependencies where needed. Reviewed-by: Daniel Machon <daniel.machon@microchip.com> Signed-off-by: Dave Ertman <david.m.ertman@intel.com> Tested-by: Sujai Buvaneswaran <sujai.buvaneswaran@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
1 parent ab2ed5d commit 3579aa8

File tree

3 files changed

+244
-4
lines changed

3 files changed

+244
-4
lines changed

drivers/net/ethernet/intel/ice/ice_lag.c

Lines changed: 228 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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
*/
965966
static void
966967
ice_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+
}

drivers/net/ethernet/intel/ice/ice_lag.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ enum ice_lag_role {
1616

1717
#define ICE_LAG_INVALID_PORT 0xFF
1818

19+
#define ICE_LAG_RESET_RETRIES 5
20+
1921
struct ice_pf;
2022
struct ice_vf;
2123

@@ -59,4 +61,5 @@ struct ice_lag_work {
5961
void ice_lag_move_new_vf_nodes(struct ice_vf *vf);
6062
int ice_init_lag(struct ice_pf *pf);
6163
void ice_deinit_lag(struct ice_pf *pf);
64+
void ice_lag_rebuild(struct ice_pf *pf);
6265
#endif /* _ICE_LAG_H_ */

drivers/net/ethernet/intel/ice/ice_main.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,11 @@ static void ice_do_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
636636

637637
dev_dbg(dev, "reset_type 0x%x requested\n", reset_type);
638638

639+
if (pf->lag && pf->lag->bonded && reset_type == ICE_RESET_PFR) {
640+
dev_dbg(dev, "PFR on a bonded interface, promoting to CORER\n");
641+
reset_type = ICE_RESET_CORER;
642+
}
643+
639644
ice_prepare_for_reset(pf, reset_type);
640645

641646
/* trigger the reset */
@@ -719,8 +724,13 @@ static void ice_reset_subtask(struct ice_pf *pf)
719724
}
720725

721726
/* No pending resets to finish processing. Check for new resets */
722-
if (test_bit(ICE_PFR_REQ, pf->state))
727+
if (test_bit(ICE_PFR_REQ, pf->state)) {
723728
reset_type = ICE_RESET_PFR;
729+
if (pf->lag && pf->lag->bonded) {
730+
dev_dbg(ice_pf_to_dev(pf), "PFR on a bonded interface, promoting to CORER\n");
731+
reset_type = ICE_RESET_CORER;
732+
}
733+
}
724734
if (test_bit(ICE_CORER_REQ, pf->state))
725735
reset_type = ICE_RESET_CORER;
726736
if (test_bit(ICE_GLOBR_REQ, pf->state))
@@ -7373,6 +7383,8 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
73737383
clear_bit(ICE_RESET_FAILED, pf->state);
73747384

73757385
ice_plug_aux_dev(pf);
7386+
if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG))
7387+
ice_lag_rebuild(pf);
73767388
return;
73777389

73787390
err_vsi_rebuild:

0 commit comments

Comments
 (0)