|
|
|
@@ -310,11 +310,12 @@ static int i40e_put_lump(struct i40e_lump_tracking *pile, u16 index, u16 id)
|
|
|
|
|
**/
|
|
|
|
|
struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < pf->num_alloc_vsi; i++)
|
|
|
|
|
if (pf->vsi[i] && (pf->vsi[i]->id == id))
|
|
|
|
|
return pf->vsi[i];
|
|
|
|
|
i40e_pf_for_each_vsi(pf, i, vsi)
|
|
|
|
|
if (vsi->id == id)
|
|
|
|
|
return vsi;
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
@@ -552,24 +553,19 @@ void i40e_vsi_reset_stats(struct i40e_vsi *vsi)
|
|
|
|
|
**/
|
|
|
|
|
void i40e_pf_reset_stats(struct i40e_pf *pf)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_veb *veb;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
memset(&pf->stats, 0, sizeof(pf->stats));
|
|
|
|
|
memset(&pf->stats_offsets, 0, sizeof(pf->stats_offsets));
|
|
|
|
|
pf->stat_offsets_loaded = false;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < I40E_MAX_VEB; i++) {
|
|
|
|
|
if (pf->veb[i]) {
|
|
|
|
|
memset(&pf->veb[i]->stats, 0,
|
|
|
|
|
sizeof(pf->veb[i]->stats));
|
|
|
|
|
memset(&pf->veb[i]->stats_offsets, 0,
|
|
|
|
|
sizeof(pf->veb[i]->stats_offsets));
|
|
|
|
|
memset(&pf->veb[i]->tc_stats, 0,
|
|
|
|
|
sizeof(pf->veb[i]->tc_stats));
|
|
|
|
|
memset(&pf->veb[i]->tc_stats_offsets, 0,
|
|
|
|
|
sizeof(pf->veb[i]->tc_stats_offsets));
|
|
|
|
|
pf->veb[i]->stat_offsets_loaded = false;
|
|
|
|
|
}
|
|
|
|
|
i40e_pf_for_each_veb(pf, i, veb) {
|
|
|
|
|
memset(&veb->stats, 0, sizeof(veb->stats));
|
|
|
|
|
memset(&veb->stats_offsets, 0, sizeof(veb->stats_offsets));
|
|
|
|
|
memset(&veb->tc_stats, 0, sizeof(veb->tc_stats));
|
|
|
|
|
memset(&veb->tc_stats_offsets, 0, sizeof(veb->tc_stats_offsets));
|
|
|
|
|
veb->stat_offsets_loaded = false;
|
|
|
|
|
}
|
|
|
|
|
pf->hw_csum_rx_error = 0;
|
|
|
|
|
}
|
|
|
|
@@ -2879,6 +2875,7 @@ err_no_memory_locked:
|
|
|
|
|
**/
|
|
|
|
|
static void i40e_sync_filters_subtask(struct i40e_pf *pf)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
int v;
|
|
|
|
|
|
|
|
|
|
if (!pf)
|
|
|
|
@@ -2890,11 +2887,10 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (v = 0; v < pf->num_alloc_vsi; v++) {
|
|
|
|
|
if (pf->vsi[v] &&
|
|
|
|
|
(pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED) &&
|
|
|
|
|
!test_bit(__I40E_VSI_RELEASING, pf->vsi[v]->state)) {
|
|
|
|
|
int ret = i40e_sync_vsi_filters(pf->vsi[v]);
|
|
|
|
|
i40e_pf_for_each_vsi(pf, v, vsi) {
|
|
|
|
|
if ((vsi->flags & I40E_VSI_FLAG_FILTER_CHANGED) &&
|
|
|
|
|
!test_bit(__I40E_VSI_RELEASING, vsi->state)) {
|
|
|
|
|
int ret = i40e_sync_vsi_filters(vsi);
|
|
|
|
|
|
|
|
|
|
if (ret) {
|
|
|
|
|
/* come back and try again later */
|
|
|
|
@@ -5166,6 +5162,7 @@ static void i40e_reset_interrupt_capability(struct i40e_pf *pf)
|
|
|
|
|
**/
|
|
|
|
|
static void i40e_clear_interrupt_scheme(struct i40e_pf *pf)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (test_bit(__I40E_MISC_IRQ_REQUESTED, pf->state))
|
|
|
|
@@ -5175,9 +5172,10 @@ static void i40e_clear_interrupt_scheme(struct i40e_pf *pf)
|
|
|
|
|
I40E_IWARP_IRQ_PILE_ID);
|
|
|
|
|
|
|
|
|
|
i40e_put_lump(pf->irq_pile, 0, I40E_PILE_VALID_BIT-1);
|
|
|
|
|
for (i = 0; i < pf->num_alloc_vsi; i++)
|
|
|
|
|
if (pf->vsi[i])
|
|
|
|
|
i40e_vsi_free_q_vectors(pf->vsi[i]);
|
|
|
|
|
|
|
|
|
|
i40e_pf_for_each_vsi(pf, i, vsi)
|
|
|
|
|
i40e_vsi_free_q_vectors(vsi);
|
|
|
|
|
|
|
|
|
|
i40e_reset_interrupt_capability(pf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -5274,12 +5272,11 @@ static void i40e_unquiesce_vsi(struct i40e_vsi *vsi)
|
|
|
|
|
**/
|
|
|
|
|
static void i40e_pf_quiesce_all_vsi(struct i40e_pf *pf)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
int v;
|
|
|
|
|
|
|
|
|
|
for (v = 0; v < pf->num_alloc_vsi; v++) {
|
|
|
|
|
if (pf->vsi[v])
|
|
|
|
|
i40e_quiesce_vsi(pf->vsi[v]);
|
|
|
|
|
}
|
|
|
|
|
i40e_pf_for_each_vsi(pf, v, vsi)
|
|
|
|
|
i40e_quiesce_vsi(vsi);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@@ -5288,12 +5285,11 @@ static void i40e_pf_quiesce_all_vsi(struct i40e_pf *pf)
|
|
|
|
|
**/
|
|
|
|
|
static void i40e_pf_unquiesce_all_vsi(struct i40e_pf *pf)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
int v;
|
|
|
|
|
|
|
|
|
|
for (v = 0; v < pf->num_alloc_vsi; v++) {
|
|
|
|
|
if (pf->vsi[v])
|
|
|
|
|
i40e_unquiesce_vsi(pf->vsi[v]);
|
|
|
|
|
}
|
|
|
|
|
i40e_pf_for_each_vsi(pf, v, vsi)
|
|
|
|
|
i40e_unquiesce_vsi(vsi);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@@ -5354,14 +5350,13 @@ wait_rx:
|
|
|
|
|
**/
|
|
|
|
|
static int i40e_pf_wait_queues_disabled(struct i40e_pf *pf)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
int v, ret = 0;
|
|
|
|
|
|
|
|
|
|
for (v = 0; v < pf->num_alloc_vsi; v++) {
|
|
|
|
|
if (pf->vsi[v]) {
|
|
|
|
|
ret = i40e_vsi_wait_queues_disabled(pf->vsi[v]);
|
|
|
|
|
if (ret)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
i40e_pf_for_each_vsi(pf, v, vsi) {
|
|
|
|
|
ret = i40e_vsi_wait_queues_disabled(vsi);
|
|
|
|
|
if (ret)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
@@ -6778,32 +6773,29 @@ out:
|
|
|
|
|
**/
|
|
|
|
|
static void i40e_dcb_reconfigure(struct i40e_pf *pf)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
struct i40e_veb *veb;
|
|
|
|
|
u8 tc_map = 0;
|
|
|
|
|
int ret;
|
|
|
|
|
u8 v;
|
|
|
|
|
int v;
|
|
|
|
|
|
|
|
|
|
/* Enable the TCs available on PF to all VEBs */
|
|
|
|
|
tc_map = i40e_pf_get_tc_map(pf);
|
|
|
|
|
if (tc_map == I40E_DEFAULT_TRAFFIC_CLASS)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (v = 0; v < I40E_MAX_VEB; v++) {
|
|
|
|
|
if (!pf->veb[v])
|
|
|
|
|
continue;
|
|
|
|
|
ret = i40e_veb_config_tc(pf->veb[v], tc_map);
|
|
|
|
|
i40e_pf_for_each_veb(pf, v, veb) {
|
|
|
|
|
ret = i40e_veb_config_tc(veb, tc_map);
|
|
|
|
|
if (ret) {
|
|
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
|
|
"Failed configuring TC for VEB seid=%d\n",
|
|
|
|
|
pf->veb[v]->seid);
|
|
|
|
|
veb->seid);
|
|
|
|
|
/* Will try to configure as many components */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Update each VSI */
|
|
|
|
|
for (v = 0; v < pf->num_alloc_vsi; v++) {
|
|
|
|
|
if (!pf->vsi[v])
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
i40e_pf_for_each_vsi(pf, v, vsi) {
|
|
|
|
|
/* - Enable all TCs for the LAN VSI
|
|
|
|
|
* - For all others keep them at TC0 for now
|
|
|
|
|
*/
|
|
|
|
@@ -6812,17 +6804,17 @@ static void i40e_dcb_reconfigure(struct i40e_pf *pf)
|
|
|
|
|
else
|
|
|
|
|
tc_map = I40E_DEFAULT_TRAFFIC_CLASS;
|
|
|
|
|
|
|
|
|
|
ret = i40e_vsi_config_tc(pf->vsi[v], tc_map);
|
|
|
|
|
ret = i40e_vsi_config_tc(vsi, tc_map);
|
|
|
|
|
if (ret) {
|
|
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
|
|
"Failed configuring TC for VSI seid=%d\n",
|
|
|
|
|
pf->vsi[v]->seid);
|
|
|
|
|
vsi->seid);
|
|
|
|
|
/* Will try to configure as many components */
|
|
|
|
|
} else {
|
|
|
|
|
/* Re-configure VSI vectors based on updated TC map */
|
|
|
|
|
i40e_vsi_map_rings_to_vectors(pf->vsi[v]);
|
|
|
|
|
if (pf->vsi[v]->netdev)
|
|
|
|
|
i40e_dcbnl_set_all(pf->vsi[v]);
|
|
|
|
|
i40e_vsi_map_rings_to_vectors(vsi);
|
|
|
|
|
if (vsi->netdev)
|
|
|
|
|
i40e_dcbnl_set_all(vsi);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -9257,7 +9249,9 @@ int i40e_close(struct net_device *netdev)
|
|
|
|
|
**/
|
|
|
|
|
void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags, bool lock_acquired)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
u32 val;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* do the biggest reset indicated */
|
|
|
|
|
if (reset_flags & BIT_ULL(__I40E_GLOBAL_RESET_REQUESTED)) {
|
|
|
|
@@ -9313,29 +9307,20 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags, bool lock_acquired)
|
|
|
|
|
"FW LLDP is enabled\n");
|
|
|
|
|
|
|
|
|
|
} else if (reset_flags & BIT_ULL(__I40E_REINIT_REQUESTED)) {
|
|
|
|
|
int v;
|
|
|
|
|
|
|
|
|
|
/* Find the VSI(s) that requested a re-init */
|
|
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
|
|
"VSI reinit requested\n");
|
|
|
|
|
for (v = 0; v < pf->num_alloc_vsi; v++) {
|
|
|
|
|
struct i40e_vsi *vsi = pf->vsi[v];
|
|
|
|
|
dev_info(&pf->pdev->dev, "VSI reinit requested\n");
|
|
|
|
|
|
|
|
|
|
if (vsi != NULL &&
|
|
|
|
|
test_and_clear_bit(__I40E_VSI_REINIT_REQUESTED,
|
|
|
|
|
i40e_pf_for_each_vsi(pf, i, vsi) {
|
|
|
|
|
if (test_and_clear_bit(__I40E_VSI_REINIT_REQUESTED,
|
|
|
|
|
vsi->state))
|
|
|
|
|
i40e_vsi_reinit_locked(pf->vsi[v]);
|
|
|
|
|
i40e_vsi_reinit_locked(vsi);
|
|
|
|
|
}
|
|
|
|
|
} else if (reset_flags & BIT_ULL(__I40E_DOWN_REQUESTED)) {
|
|
|
|
|
int v;
|
|
|
|
|
|
|
|
|
|
/* Find the VSI(s) that needs to be brought down */
|
|
|
|
|
dev_info(&pf->pdev->dev, "VSI down requested\n");
|
|
|
|
|
for (v = 0; v < pf->num_alloc_vsi; v++) {
|
|
|
|
|
struct i40e_vsi *vsi = pf->vsi[v];
|
|
|
|
|
|
|
|
|
|
if (vsi != NULL &&
|
|
|
|
|
test_and_clear_bit(__I40E_VSI_DOWN_REQUESTED,
|
|
|
|
|
i40e_pf_for_each_vsi(pf, i, vsi) {
|
|
|
|
|
if (test_and_clear_bit(__I40E_VSI_DOWN_REQUESTED,
|
|
|
|
|
vsi->state)) {
|
|
|
|
|
set_bit(__I40E_VSI_DOWN, vsi->state);
|
|
|
|
|
i40e_down(vsi);
|
|
|
|
@@ -9888,6 +9873,7 @@ static void i40e_vsi_link_event(struct i40e_vsi *vsi, bool link_up)
|
|
|
|
|
**/
|
|
|
|
|
static void i40e_veb_link_event(struct i40e_veb *veb, bool link_up)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
struct i40e_pf *pf;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
@@ -9895,15 +9881,10 @@ static void i40e_veb_link_event(struct i40e_veb *veb, bool link_up)
|
|
|
|
|
return;
|
|
|
|
|
pf = veb->pf;
|
|
|
|
|
|
|
|
|
|
/* depth first... */
|
|
|
|
|
for (i = 0; i < I40E_MAX_VEB; i++)
|
|
|
|
|
if (pf->veb[i] && (pf->veb[i]->uplink_seid == veb->seid))
|
|
|
|
|
i40e_veb_link_event(pf->veb[i], link_up);
|
|
|
|
|
|
|
|
|
|
/* ... now the local VSIs */
|
|
|
|
|
for (i = 0; i < pf->num_alloc_vsi; i++)
|
|
|
|
|
if (pf->vsi[i] && (pf->vsi[i]->uplink_seid == veb->seid))
|
|
|
|
|
i40e_vsi_link_event(pf->vsi[i], link_up);
|
|
|
|
|
/* Send link event to contained VSIs */
|
|
|
|
|
i40e_pf_for_each_vsi(pf, i, vsi)
|
|
|
|
|
if (vsi->uplink_seid == veb->seid)
|
|
|
|
|
i40e_vsi_link_event(vsi, link_up);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@@ -9995,6 +9976,8 @@ static void i40e_link_event(struct i40e_pf *pf)
|
|
|
|
|
**/
|
|
|
|
|
static void i40e_watchdog_subtask(struct i40e_pf *pf)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
struct i40e_veb *veb;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* if interface is down do nothing */
|
|
|
|
@@ -10015,15 +9998,14 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)
|
|
|
|
|
/* Update the stats for active netdevs so the network stack
|
|
|
|
|
* can look at updated numbers whenever it cares to
|
|
|
|
|
*/
|
|
|
|
|
for (i = 0; i < pf->num_alloc_vsi; i++)
|
|
|
|
|
if (pf->vsi[i] && pf->vsi[i]->netdev)
|
|
|
|
|
i40e_update_stats(pf->vsi[i]);
|
|
|
|
|
i40e_pf_for_each_vsi(pf, i, vsi)
|
|
|
|
|
if (vsi->netdev)
|
|
|
|
|
i40e_update_stats(vsi);
|
|
|
|
|
|
|
|
|
|
if (test_bit(I40E_FLAG_VEB_STATS_ENA, pf->flags)) {
|
|
|
|
|
/* Update the stats for the active switching components */
|
|
|
|
|
for (i = 0; i < I40E_MAX_VEB; i++)
|
|
|
|
|
if (pf->veb[i])
|
|
|
|
|
i40e_update_veb_stats(pf->veb[i]);
|
|
|
|
|
i40e_pf_for_each_veb(pf, i, veb)
|
|
|
|
|
i40e_update_veb_stats(veb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i40e_ptp_rx_hang(pf);
|
|
|
|
@@ -10368,89 +10350,84 @@ static void i40e_config_bridge_mode(struct i40e_veb *veb)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* i40e_reconstitute_veb - rebuild the VEB and anything connected to it
|
|
|
|
|
* i40e_reconstitute_veb - rebuild the VEB and VSIs connected to it
|
|
|
|
|
* @veb: pointer to the VEB instance
|
|
|
|
|
*
|
|
|
|
|
* This is a recursive function that first builds the attached VSIs then
|
|
|
|
|
* recurses in to build the next layer of VEB. We track the connections
|
|
|
|
|
* through our own index numbers because the seid's from the HW could
|
|
|
|
|
* change across the reset.
|
|
|
|
|
* This is a function that builds the attached VSIs. We track the connections
|
|
|
|
|
* through our own index numbers because the seid's from the HW could change
|
|
|
|
|
* across the reset.
|
|
|
|
|
**/
|
|
|
|
|
static int i40e_reconstitute_veb(struct i40e_veb *veb)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_vsi *ctl_vsi = NULL;
|
|
|
|
|
struct i40e_pf *pf = veb->pf;
|
|
|
|
|
int v, veb_idx;
|
|
|
|
|
int ret;
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
int v, ret;
|
|
|
|
|
|
|
|
|
|
/* build VSI that owns this VEB, temporarily attached to base VEB */
|
|
|
|
|
for (v = 0; v < pf->num_alloc_vsi && !ctl_vsi; v++) {
|
|
|
|
|
if (pf->vsi[v] &&
|
|
|
|
|
pf->vsi[v]->veb_idx == veb->idx &&
|
|
|
|
|
pf->vsi[v]->flags & I40E_VSI_FLAG_VEB_OWNER) {
|
|
|
|
|
ctl_vsi = pf->vsi[v];
|
|
|
|
|
break;
|
|
|
|
|
/* As we do not maintain PV (port virtualizer) switch element then
|
|
|
|
|
* there can be only one non-floating VEB that have uplink to MAC SEID
|
|
|
|
|
* and its control VSI is the main one.
|
|
|
|
|
*/
|
|
|
|
|
if (WARN_ON(veb->uplink_seid && veb->uplink_seid != pf->mac_seid)) {
|
|
|
|
|
dev_err(&pf->pdev->dev,
|
|
|
|
|
"Invalid uplink SEID for VEB %d\n", veb->idx);
|
|
|
|
|
return -ENOENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (veb->uplink_seid == pf->mac_seid) {
|
|
|
|
|
/* Check that the LAN VSI has VEB owning flag set */
|
|
|
|
|
ctl_vsi = pf->vsi[pf->lan_vsi];
|
|
|
|
|
|
|
|
|
|
if (WARN_ON(ctl_vsi->veb_idx != veb->idx ||
|
|
|
|
|
!(ctl_vsi->flags & I40E_VSI_FLAG_VEB_OWNER))) {
|
|
|
|
|
dev_err(&pf->pdev->dev,
|
|
|
|
|
"Invalid control VSI for VEB %d\n", veb->idx);
|
|
|
|
|
return -ENOENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add the control VSI to switch */
|
|
|
|
|
ret = i40e_add_vsi(ctl_vsi);
|
|
|
|
|
if (ret) {
|
|
|
|
|
dev_err(&pf->pdev->dev,
|
|
|
|
|
"Rebuild of owner VSI for VEB %d failed: %d\n",
|
|
|
|
|
veb->idx, ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i40e_vsi_reset_stats(ctl_vsi);
|
|
|
|
|
}
|
|
|
|
|
if (!ctl_vsi) {
|
|
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
|
|
"missing owner VSI for veb_idx %d\n", veb->idx);
|
|
|
|
|
ret = -ENOENT;
|
|
|
|
|
goto end_reconstitute;
|
|
|
|
|
}
|
|
|
|
|
if (ctl_vsi != pf->vsi[pf->lan_vsi])
|
|
|
|
|
ctl_vsi->uplink_seid = pf->vsi[pf->lan_vsi]->uplink_seid;
|
|
|
|
|
ret = i40e_add_vsi(ctl_vsi);
|
|
|
|
|
if (ret) {
|
|
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
|
|
"rebuild of veb_idx %d owner VSI failed: %d\n",
|
|
|
|
|
veb->idx, ret);
|
|
|
|
|
goto end_reconstitute;
|
|
|
|
|
}
|
|
|
|
|
i40e_vsi_reset_stats(ctl_vsi);
|
|
|
|
|
|
|
|
|
|
/* create the VEB in the switch and move the VSI onto the VEB */
|
|
|
|
|
ret = i40e_add_veb(veb, ctl_vsi);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto end_reconstitute;
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
if (test_bit(I40E_FLAG_VEB_MODE_ENA, pf->flags))
|
|
|
|
|
veb->bridge_mode = BRIDGE_MODE_VEB;
|
|
|
|
|
else
|
|
|
|
|
veb->bridge_mode = BRIDGE_MODE_VEPA;
|
|
|
|
|
i40e_config_bridge_mode(veb);
|
|
|
|
|
if (veb->uplink_seid) {
|
|
|
|
|
if (test_bit(I40E_FLAG_VEB_MODE_ENA, pf->flags))
|
|
|
|
|
veb->bridge_mode = BRIDGE_MODE_VEB;
|
|
|
|
|
else
|
|
|
|
|
veb->bridge_mode = BRIDGE_MODE_VEPA;
|
|
|
|
|
i40e_config_bridge_mode(veb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* create the remaining VSIs attached to this VEB */
|
|
|
|
|
for (v = 0; v < pf->num_alloc_vsi; v++) {
|
|
|
|
|
if (!pf->vsi[v] || pf->vsi[v] == ctl_vsi)
|
|
|
|
|
i40e_pf_for_each_vsi(pf, v, vsi) {
|
|
|
|
|
if (vsi == ctl_vsi)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (pf->vsi[v]->veb_idx == veb->idx) {
|
|
|
|
|
struct i40e_vsi *vsi = pf->vsi[v];
|
|
|
|
|
|
|
|
|
|
if (vsi->veb_idx == veb->idx) {
|
|
|
|
|
vsi->uplink_seid = veb->seid;
|
|
|
|
|
ret = i40e_add_vsi(vsi);
|
|
|
|
|
if (ret) {
|
|
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
|
|
"rebuild of vsi_idx %d failed: %d\n",
|
|
|
|
|
v, ret);
|
|
|
|
|
goto end_reconstitute;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
i40e_vsi_reset_stats(vsi);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* create any VEBs attached to this VEB - RECURSION */
|
|
|
|
|
for (veb_idx = 0; veb_idx < I40E_MAX_VEB; veb_idx++) {
|
|
|
|
|
if (pf->veb[veb_idx] && pf->veb[veb_idx]->veb_idx == veb->idx) {
|
|
|
|
|
pf->veb[veb_idx]->uplink_seid = veb->seid;
|
|
|
|
|
ret = i40e_reconstitute_veb(pf->veb[veb_idx]);
|
|
|
|
|
if (ret)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
end_reconstitute:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -10718,6 +10695,7 @@ static void i40e_clean_xps_state(struct i40e_vsi *vsi)
|
|
|
|
|
static void i40e_prep_for_reset(struct i40e_pf *pf)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_hw *hw = &pf->hw;
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
int ret = 0;
|
|
|
|
|
u32 v;
|
|
|
|
|
|
|
|
|
@@ -10732,11 +10710,9 @@ static void i40e_prep_for_reset(struct i40e_pf *pf)
|
|
|
|
|
/* quiesce the VSIs and their queues that are not already DOWN */
|
|
|
|
|
i40e_pf_quiesce_all_vsi(pf);
|
|
|
|
|
|
|
|
|
|
for (v = 0; v < pf->num_alloc_vsi; v++) {
|
|
|
|
|
if (pf->vsi[v]) {
|
|
|
|
|
i40e_clean_xps_state(pf->vsi[v]);
|
|
|
|
|
pf->vsi[v]->seid = 0;
|
|
|
|
|
}
|
|
|
|
|
i40e_pf_for_each_vsi(pf, v, vsi) {
|
|
|
|
|
i40e_clean_xps_state(vsi);
|
|
|
|
|
vsi->seid = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i40e_shutdown_adminq(&pf->hw);
|
|
|
|
@@ -10850,6 +10826,7 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
|
|
|
|
|
const bool is_recovery_mode_reported = i40e_check_recovery_mode(pf);
|
|
|
|
|
struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
|
|
|
|
|
struct i40e_hw *hw = &pf->hw;
|
|
|
|
|
struct i40e_veb *veb;
|
|
|
|
|
int ret;
|
|
|
|
|
u32 val;
|
|
|
|
|
int v;
|
|
|
|
@@ -10991,35 +10968,29 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
|
|
|
|
|
*/
|
|
|
|
|
if (vsi->uplink_seid != pf->mac_seid) {
|
|
|
|
|
dev_dbg(&pf->pdev->dev, "attempting to rebuild switch\n");
|
|
|
|
|
/* find the one VEB connected to the MAC, and find orphans */
|
|
|
|
|
for (v = 0; v < I40E_MAX_VEB; v++) {
|
|
|
|
|
if (!pf->veb[v])
|
|
|
|
|
|
|
|
|
|
/* Rebuild VEBs */
|
|
|
|
|
i40e_pf_for_each_veb(pf, v, veb) {
|
|
|
|
|
ret = i40e_reconstitute_veb(veb);
|
|
|
|
|
if (!ret)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (pf->veb[v]->uplink_seid == pf->mac_seid ||
|
|
|
|
|
pf->veb[v]->uplink_seid == 0) {
|
|
|
|
|
ret = i40e_reconstitute_veb(pf->veb[v]);
|
|
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* If Main VEB failed, we're in deep doodoo,
|
|
|
|
|
* so give up rebuilding the switch and set up
|
|
|
|
|
* for minimal rebuild of PF VSI.
|
|
|
|
|
* If orphan failed, we'll report the error
|
|
|
|
|
* but try to keep going.
|
|
|
|
|
*/
|
|
|
|
|
if (pf->veb[v]->uplink_seid == pf->mac_seid) {
|
|
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
|
|
"rebuild of switch failed: %d, will try to set up simple PF connection\n",
|
|
|
|
|
ret);
|
|
|
|
|
vsi->uplink_seid = pf->mac_seid;
|
|
|
|
|
break;
|
|
|
|
|
} else if (pf->veb[v]->uplink_seid == 0) {
|
|
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
|
|
"rebuild of orphan VEB failed: %d\n",
|
|
|
|
|
ret);
|
|
|
|
|
}
|
|
|
|
|
/* If Main VEB failed, we're in deep doodoo,
|
|
|
|
|
* so give up rebuilding the switch and set up
|
|
|
|
|
* for minimal rebuild of PF VSI.
|
|
|
|
|
* If orphan failed, we'll report the error
|
|
|
|
|
* but try to keep going.
|
|
|
|
|
*/
|
|
|
|
|
if (veb->uplink_seid == pf->mac_seid) {
|
|
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
|
|
"rebuild of switch failed: %d, will try to set up simple PF connection\n",
|
|
|
|
|
ret);
|
|
|
|
|
vsi->uplink_seid = pf->mac_seid;
|
|
|
|
|
break;
|
|
|
|
|
} else if (veb->uplink_seid == 0) {
|
|
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
|
|
"rebuild of orphan VEB failed: %d\n",
|
|
|
|
|
ret);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -12098,6 +12069,7 @@ static int i40e_init_interrupt_scheme(struct i40e_pf *pf)
|
|
|
|
|
*/
|
|
|
|
|
static int i40e_restore_interrupt_scheme(struct i40e_pf *pf)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
int err, i;
|
|
|
|
|
|
|
|
|
|
/* We cleared the MSI and MSI-X flags when disabling the old interrupt
|
|
|
|
@@ -12114,13 +12086,12 @@ static int i40e_restore_interrupt_scheme(struct i40e_pf *pf)
|
|
|
|
|
/* Now that we've re-acquired IRQs, we need to remap the vectors and
|
|
|
|
|
* rings together again.
|
|
|
|
|
*/
|
|
|
|
|
for (i = 0; i < pf->num_alloc_vsi; i++) {
|
|
|
|
|
if (pf->vsi[i]) {
|
|
|
|
|
err = i40e_vsi_alloc_q_vectors(pf->vsi[i]);
|
|
|
|
|
if (err)
|
|
|
|
|
goto err_unwind;
|
|
|
|
|
i40e_vsi_map_rings_to_vectors(pf->vsi[i]);
|
|
|
|
|
}
|
|
|
|
|
i40e_pf_for_each_vsi(pf, i, vsi) {
|
|
|
|
|
err = i40e_vsi_alloc_q_vectors(vsi);
|
|
|
|
|
if (err)
|
|
|
|
|
goto err_unwind;
|
|
|
|
|
|
|
|
|
|
i40e_vsi_map_rings_to_vectors(vsi);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = i40e_setup_misc_vector(pf);
|
|
|
|
@@ -13122,19 +13093,16 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev,
|
|
|
|
|
struct i40e_netdev_priv *np = netdev_priv(dev);
|
|
|
|
|
struct i40e_vsi *vsi = np->vsi;
|
|
|
|
|
struct i40e_pf *pf = vsi->back;
|
|
|
|
|
struct i40e_veb *veb = NULL;
|
|
|
|
|
struct nlattr *attr, *br_spec;
|
|
|
|
|
int i, rem;
|
|
|
|
|
struct i40e_veb *veb;
|
|
|
|
|
int rem;
|
|
|
|
|
|
|
|
|
|
/* Only for PF VSI for now */
|
|
|
|
|
if (vsi->seid != pf->vsi[pf->lan_vsi]->seid)
|
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
|
|
/* Find the HW bridge for PF VSI */
|
|
|
|
|
for (i = 0; i < I40E_MAX_VEB && !veb; i++) {
|
|
|
|
|
if (pf->veb[i] && pf->veb[i]->seid == vsi->uplink_seid)
|
|
|
|
|
veb = pf->veb[i];
|
|
|
|
|
}
|
|
|
|
|
veb = i40e_pf_get_veb_by_seid(pf, vsi->uplink_seid);
|
|
|
|
|
|
|
|
|
|
br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
|
|
|
|
|
if (!br_spec)
|
|
|
|
@@ -13199,19 +13167,14 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
|
|
|
|
struct i40e_netdev_priv *np = netdev_priv(dev);
|
|
|
|
|
struct i40e_vsi *vsi = np->vsi;
|
|
|
|
|
struct i40e_pf *pf = vsi->back;
|
|
|
|
|
struct i40e_veb *veb = NULL;
|
|
|
|
|
int i;
|
|
|
|
|
struct i40e_veb *veb;
|
|
|
|
|
|
|
|
|
|
/* Only for PF VSI for now */
|
|
|
|
|
if (vsi->seid != pf->vsi[pf->lan_vsi]->seid)
|
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
|
|
/* Find the HW bridge for the PF VSI */
|
|
|
|
|
for (i = 0; i < I40E_MAX_VEB && !veb; i++) {
|
|
|
|
|
if (pf->veb[i] && pf->veb[i]->seid == vsi->uplink_seid)
|
|
|
|
|
veb = pf->veb[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
veb = i40e_pf_get_veb_by_seid(pf, vsi->uplink_seid);
|
|
|
|
|
if (!veb)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
@@ -14145,7 +14108,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_mac_filter *f;
|
|
|
|
|
struct hlist_node *h;
|
|
|
|
|
struct i40e_veb *veb = NULL;
|
|
|
|
|
struct i40e_veb *veb;
|
|
|
|
|
struct i40e_pf *pf;
|
|
|
|
|
u16 uplink_seid;
|
|
|
|
|
int i, n, bkt;
|
|
|
|
@@ -14209,29 +14172,28 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
|
|
|
|
|
|
|
|
|
|
/* If this was the last thing on the VEB, except for the
|
|
|
|
|
* controlling VSI, remove the VEB, which puts the controlling
|
|
|
|
|
* VSI onto the next level down in the switch.
|
|
|
|
|
* VSI onto the uplink port.
|
|
|
|
|
*
|
|
|
|
|
* Well, okay, there's one more exception here: don't remove
|
|
|
|
|
* the orphan VEBs yet. We'll wait for an explicit remove request
|
|
|
|
|
* the floating VEBs yet. We'll wait for an explicit remove request
|
|
|
|
|
* from up the network stack.
|
|
|
|
|
*/
|
|
|
|
|
for (n = 0, i = 0; i < pf->num_alloc_vsi; i++) {
|
|
|
|
|
if (pf->vsi[i] &&
|
|
|
|
|
pf->vsi[i]->uplink_seid == uplink_seid &&
|
|
|
|
|
(pf->vsi[i]->flags & I40E_VSI_FLAG_VEB_OWNER) == 0) {
|
|
|
|
|
n++; /* count the VSIs */
|
|
|
|
|
}
|
|
|
|
|
veb = i40e_pf_get_veb_by_seid(pf, uplink_seid);
|
|
|
|
|
if (veb && veb->uplink_seid) {
|
|
|
|
|
n = 0;
|
|
|
|
|
|
|
|
|
|
/* Count non-controlling VSIs present on the VEB */
|
|
|
|
|
i40e_pf_for_each_vsi(pf, i, vsi)
|
|
|
|
|
if (vsi->uplink_seid == uplink_seid &&
|
|
|
|
|
(vsi->flags & I40E_VSI_FLAG_VEB_OWNER) == 0)
|
|
|
|
|
n++;
|
|
|
|
|
|
|
|
|
|
/* If there is no VSI except the control one then release
|
|
|
|
|
* the VEB and put the control VSI onto VEB uplink.
|
|
|
|
|
*/
|
|
|
|
|
if (!n)
|
|
|
|
|
i40e_veb_release(veb);
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < I40E_MAX_VEB; i++) {
|
|
|
|
|
if (!pf->veb[i])
|
|
|
|
|
continue;
|
|
|
|
|
if (pf->veb[i]->uplink_seid == uplink_seid)
|
|
|
|
|
n++; /* count the VEBs */
|
|
|
|
|
if (pf->veb[i]->seid == uplink_seid)
|
|
|
|
|
veb = pf->veb[i];
|
|
|
|
|
}
|
|
|
|
|
if (n == 0 && veb && veb->uplink_seid != 0)
|
|
|
|
|
i40e_veb_release(veb);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@@ -14389,8 +14351,8 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
|
|
|
|
|
struct i40e_vsi *vsi = NULL;
|
|
|
|
|
struct i40e_veb *veb = NULL;
|
|
|
|
|
u16 alloc_queue_pairs;
|
|
|
|
|
int ret, i;
|
|
|
|
|
int v_idx;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
/* The requested uplink_seid must be either
|
|
|
|
|
* - the PF's port seid
|
|
|
|
@@ -14405,21 +14367,9 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
|
|
|
|
|
*
|
|
|
|
|
* Find which uplink_seid we were given and create a new VEB if needed
|
|
|
|
|
*/
|
|
|
|
|
for (i = 0; i < I40E_MAX_VEB; i++) {
|
|
|
|
|
if (pf->veb[i] && pf->veb[i]->seid == uplink_seid) {
|
|
|
|
|
veb = pf->veb[i];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
veb = i40e_pf_get_veb_by_seid(pf, uplink_seid);
|
|
|
|
|
if (!veb && uplink_seid != pf->mac_seid) {
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < pf->num_alloc_vsi; i++) {
|
|
|
|
|
if (pf->vsi[i] && pf->vsi[i]->seid == uplink_seid) {
|
|
|
|
|
vsi = pf->vsi[i];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
vsi = i40e_pf_get_vsi_by_seid(pf, uplink_seid);
|
|
|
|
|
if (!vsi) {
|
|
|
|
|
dev_info(&pf->pdev->dev, "no such uplink_seid %d\n",
|
|
|
|
|
uplink_seid);
|
|
|
|
@@ -14448,10 +14398,7 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
|
|
|
|
|
}
|
|
|
|
|
i40e_config_bridge_mode(veb);
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < I40E_MAX_VEB && !veb; i++) {
|
|
|
|
|
if (pf->veb[i] && pf->veb[i]->seid == vsi->uplink_seid)
|
|
|
|
|
veb = pf->veb[i];
|
|
|
|
|
}
|
|
|
|
|
veb = i40e_pf_get_veb_by_seid(pf, vsi->uplink_seid);
|
|
|
|
|
if (!veb) {
|
|
|
|
|
dev_info(&pf->pdev->dev, "couldn't add VEB\n");
|
|
|
|
|
return NULL;
|
|
|
|
@@ -14681,29 +14628,24 @@ static void i40e_switch_branch_release(struct i40e_veb *branch)
|
|
|
|
|
struct i40e_pf *pf = branch->pf;
|
|
|
|
|
u16 branch_seid = branch->seid;
|
|
|
|
|
u16 veb_idx = branch->idx;
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
struct i40e_veb *veb;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* release any VEBs on this VEB - RECURSION */
|
|
|
|
|
for (i = 0; i < I40E_MAX_VEB; i++) {
|
|
|
|
|
if (!pf->veb[i])
|
|
|
|
|
continue;
|
|
|
|
|
if (pf->veb[i]->uplink_seid == branch->seid)
|
|
|
|
|
i40e_switch_branch_release(pf->veb[i]);
|
|
|
|
|
}
|
|
|
|
|
i40e_pf_for_each_veb(pf, i, veb)
|
|
|
|
|
if (veb->uplink_seid == branch->seid)
|
|
|
|
|
i40e_switch_branch_release(veb);
|
|
|
|
|
|
|
|
|
|
/* Release the VSIs on this VEB, but not the owner VSI.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: Removing the last VSI on a VEB has the SIDE EFFECT of removing
|
|
|
|
|
* the VEB itself, so don't use (*branch) after this loop.
|
|
|
|
|
*/
|
|
|
|
|
for (i = 0; i < pf->num_alloc_vsi; i++) {
|
|
|
|
|
if (!pf->vsi[i])
|
|
|
|
|
continue;
|
|
|
|
|
if (pf->vsi[i]->uplink_seid == branch_seid &&
|
|
|
|
|
(pf->vsi[i]->flags & I40E_VSI_FLAG_VEB_OWNER) == 0) {
|
|
|
|
|
i40e_vsi_release(pf->vsi[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
i40e_pf_for_each_vsi(pf, i, vsi)
|
|
|
|
|
if (vsi->uplink_seid == branch_seid &&
|
|
|
|
|
(vsi->flags & I40E_VSI_FLAG_VEB_OWNER) == 0)
|
|
|
|
|
i40e_vsi_release(vsi);
|
|
|
|
|
|
|
|
|
|
/* There's one corner case where the VEB might not have been
|
|
|
|
|
* removed, so double check it here and remove it if needed.
|
|
|
|
@@ -14741,38 +14683,35 @@ static void i40e_veb_clear(struct i40e_veb *veb)
|
|
|
|
|
**/
|
|
|
|
|
void i40e_veb_release(struct i40e_veb *veb)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_vsi *vsi = NULL;
|
|
|
|
|
struct i40e_vsi *vsi, *vsi_it;
|
|
|
|
|
struct i40e_pf *pf;
|
|
|
|
|
int i, n = 0;
|
|
|
|
|
|
|
|
|
|
pf = veb->pf;
|
|
|
|
|
|
|
|
|
|
/* find the remaining VSI and check for extras */
|
|
|
|
|
for (i = 0; i < pf->num_alloc_vsi; i++) {
|
|
|
|
|
if (pf->vsi[i] && pf->vsi[i]->uplink_seid == veb->seid) {
|
|
|
|
|
i40e_pf_for_each_vsi(pf, i, vsi_it)
|
|
|
|
|
if (vsi_it->uplink_seid == veb->seid) {
|
|
|
|
|
if (vsi_it->flags & I40E_VSI_FLAG_VEB_OWNER)
|
|
|
|
|
vsi = vsi_it;
|
|
|
|
|
n++;
|
|
|
|
|
vsi = pf->vsi[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (n != 1) {
|
|
|
|
|
|
|
|
|
|
/* Floating VEB has to be empty and regular one must have
|
|
|
|
|
* single owner VSI.
|
|
|
|
|
*/
|
|
|
|
|
if ((veb->uplink_seid && n != 1) || (!veb->uplink_seid && n != 0)) {
|
|
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
|
|
"can't remove VEB %d with %d VSIs left\n",
|
|
|
|
|
veb->seid, n);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* move the remaining VSI to uplink veb */
|
|
|
|
|
vsi->flags &= ~I40E_VSI_FLAG_VEB_OWNER;
|
|
|
|
|
/* For regular VEB move the owner VSI to uplink port */
|
|
|
|
|
if (veb->uplink_seid) {
|
|
|
|
|
vsi->flags &= ~I40E_VSI_FLAG_VEB_OWNER;
|
|
|
|
|
vsi->uplink_seid = veb->uplink_seid;
|
|
|
|
|
if (veb->uplink_seid == pf->mac_seid)
|
|
|
|
|
vsi->veb_idx = I40E_NO_VEB;
|
|
|
|
|
else
|
|
|
|
|
vsi->veb_idx = veb->veb_idx;
|
|
|
|
|
} else {
|
|
|
|
|
/* floating VEB */
|
|
|
|
|
vsi->uplink_seid = pf->vsi[pf->lan_vsi]->uplink_seid;
|
|
|
|
|
vsi->veb_idx = pf->vsi[pf->lan_vsi]->veb_idx;
|
|
|
|
|
vsi->veb_idx = I40E_NO_VEB;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i40e_aq_delete_element(&pf->hw, veb->seid, NULL);
|
|
|
|
@@ -14790,8 +14729,8 @@ static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi)
|
|
|
|
|
bool enable_stats = !!test_bit(I40E_FLAG_VEB_STATS_ENA, pf->flags);
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
ret = i40e_aq_add_veb(&pf->hw, veb->uplink_seid, vsi->seid,
|
|
|
|
|
veb->enabled_tc, false,
|
|
|
|
|
ret = i40e_aq_add_veb(&pf->hw, veb->uplink_seid, vsi ? vsi->seid : 0,
|
|
|
|
|
veb->enabled_tc, vsi ? false : true,
|
|
|
|
|
&veb->seid, enable_stats, NULL);
|
|
|
|
|
|
|
|
|
|
/* get a VEB from the hardware */
|
|
|
|
@@ -14823,9 +14762,11 @@ static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi)
|
|
|
|
|
return -ENOENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vsi->uplink_seid = veb->seid;
|
|
|
|
|
vsi->veb_idx = veb->idx;
|
|
|
|
|
vsi->flags |= I40E_VSI_FLAG_VEB_OWNER;
|
|
|
|
|
if (vsi) {
|
|
|
|
|
vsi->uplink_seid = veb->seid;
|
|
|
|
|
vsi->veb_idx = veb->idx;
|
|
|
|
|
vsi->flags |= I40E_VSI_FLAG_VEB_OWNER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@@ -14850,8 +14791,9 @@ struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags,
|
|
|
|
|
u16 uplink_seid, u16 vsi_seid,
|
|
|
|
|
u8 enabled_tc)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_veb *veb, *uplink_veb = NULL;
|
|
|
|
|
int vsi_idx, veb_idx;
|
|
|
|
|
struct i40e_vsi *vsi = NULL;
|
|
|
|
|
struct i40e_veb *veb;
|
|
|
|
|
int veb_idx;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
/* if one seid is 0, the other must be 0 to create a floating relay */
|
|
|
|
@@ -14864,26 +14806,11 @@ struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* make sure there is such a vsi and uplink */
|
|
|
|
|
for (vsi_idx = 0; vsi_idx < pf->num_alloc_vsi; vsi_idx++)
|
|
|
|
|
if (pf->vsi[vsi_idx] && pf->vsi[vsi_idx]->seid == vsi_seid)
|
|
|
|
|
break;
|
|
|
|
|
if (vsi_idx == pf->num_alloc_vsi && vsi_seid != 0) {
|
|
|
|
|
dev_info(&pf->pdev->dev, "vsi seid %d not found\n",
|
|
|
|
|
vsi_seid);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (uplink_seid && uplink_seid != pf->mac_seid) {
|
|
|
|
|
for (veb_idx = 0; veb_idx < I40E_MAX_VEB; veb_idx++) {
|
|
|
|
|
if (pf->veb[veb_idx] &&
|
|
|
|
|
pf->veb[veb_idx]->seid == uplink_seid) {
|
|
|
|
|
uplink_veb = pf->veb[veb_idx];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!uplink_veb) {
|
|
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
|
|
"uplink seid %d not found\n", uplink_seid);
|
|
|
|
|
if (vsi_seid) {
|
|
|
|
|
vsi = i40e_pf_get_vsi_by_seid(pf, vsi_seid);
|
|
|
|
|
if (!vsi) {
|
|
|
|
|
dev_err(&pf->pdev->dev, "vsi seid %d not found\n",
|
|
|
|
|
vsi_seid);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -14895,14 +14822,14 @@ struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags,
|
|
|
|
|
veb = pf->veb[veb_idx];
|
|
|
|
|
veb->flags = flags;
|
|
|
|
|
veb->uplink_seid = uplink_seid;
|
|
|
|
|
veb->veb_idx = (uplink_veb ? uplink_veb->idx : I40E_NO_VEB);
|
|
|
|
|
veb->enabled_tc = (enabled_tc ? enabled_tc : 0x1);
|
|
|
|
|
|
|
|
|
|
/* create the VEB in the switch */
|
|
|
|
|
ret = i40e_add_veb(veb, pf->vsi[vsi_idx]);
|
|
|
|
|
ret = i40e_add_veb(veb, vsi);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto err_veb;
|
|
|
|
|
if (vsi_idx == pf->lan_vsi)
|
|
|
|
|
|
|
|
|
|
if (vsi && vsi->idx == pf->lan_vsi)
|
|
|
|
|
pf->lan_veb = veb->idx;
|
|
|
|
|
|
|
|
|
|
return veb;
|
|
|
|
@@ -14930,6 +14857,7 @@ static void i40e_setup_pf_switch_element(struct i40e_pf *pf,
|
|
|
|
|
u16 uplink_seid = le16_to_cpu(ele->uplink_seid);
|
|
|
|
|
u8 element_type = ele->element_type;
|
|
|
|
|
u16 seid = le16_to_cpu(ele->seid);
|
|
|
|
|
struct i40e_veb *veb;
|
|
|
|
|
|
|
|
|
|
if (printconfig)
|
|
|
|
|
dev_info(&pf->pdev->dev,
|
|
|
|
@@ -14948,13 +14876,10 @@ static void i40e_setup_pf_switch_element(struct i40e_pf *pf,
|
|
|
|
|
int v;
|
|
|
|
|
|
|
|
|
|
/* find existing or else empty VEB */
|
|
|
|
|
for (v = 0; v < I40E_MAX_VEB; v++) {
|
|
|
|
|
if (pf->veb[v] && (pf->veb[v]->seid == seid)) {
|
|
|
|
|
pf->lan_veb = v;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (pf->lan_veb >= I40E_MAX_VEB) {
|
|
|
|
|
veb = i40e_pf_get_veb_by_seid(pf, seid);
|
|
|
|
|
if (veb) {
|
|
|
|
|
pf->lan_veb = veb->idx;
|
|
|
|
|
} else {
|
|
|
|
|
v = i40e_veb_mem_alloc(pf);
|
|
|
|
|
if (v < 0)
|
|
|
|
|
break;
|
|
|
|
@@ -14967,7 +14892,6 @@ static void i40e_setup_pf_switch_element(struct i40e_pf *pf,
|
|
|
|
|
pf->veb[pf->lan_veb]->seid = seid;
|
|
|
|
|
pf->veb[pf->lan_veb]->uplink_seid = pf->mac_seid;
|
|
|
|
|
pf->veb[pf->lan_veb]->pf = pf;
|
|
|
|
|
pf->veb[pf->lan_veb]->veb_idx = I40E_NO_VEB;
|
|
|
|
|
break;
|
|
|
|
|
case I40E_SWITCH_ELEMENT_TYPE_VSI:
|
|
|
|
|
if (num_reported != 1)
|
|
|
|
@@ -15630,6 +15554,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
|
|
#ifdef CONFIG_I40E_DCB
|
|
|
|
|
enum i40e_get_fw_lldp_status_resp lldp_status;
|
|
|
|
|
#endif /* CONFIG_I40E_DCB */
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
struct i40e_pf *pf;
|
|
|
|
|
struct i40e_hw *hw;
|
|
|
|
|
u16 wol_nvm_bits;
|
|
|
|
@@ -15640,7 +15565,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
|
|
#endif /* CONFIG_I40E_DCB */
|
|
|
|
|
int err;
|
|
|
|
|
u32 val;
|
|
|
|
|
u32 i;
|
|
|
|
|
|
|
|
|
|
err = pci_enable_device_mem(pdev);
|
|
|
|
|
if (err)
|
|
|
|
@@ -15990,12 +15914,9 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
|
|
INIT_LIST_HEAD(&pf->vsi[pf->lan_vsi]->ch_list);
|
|
|
|
|
|
|
|
|
|
/* if FDIR VSI was set up, start it now */
|
|
|
|
|
for (i = 0; i < pf->num_alloc_vsi; i++) {
|
|
|
|
|
if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) {
|
|
|
|
|
i40e_vsi_open(pf->vsi[i]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
vsi = i40e_find_vsi_by_type(pf, I40E_VSI_FDIR);
|
|
|
|
|
if (vsi)
|
|
|
|
|
i40e_vsi_open(vsi);
|
|
|
|
|
|
|
|
|
|
/* The driver only wants link up/down and module qualification
|
|
|
|
|
* reports from firmware. Note the negative logic.
|
|
|
|
@@ -16241,6 +16162,8 @@ static void i40e_remove(struct pci_dev *pdev)
|
|
|
|
|
{
|
|
|
|
|
struct i40e_pf *pf = pci_get_drvdata(pdev);
|
|
|
|
|
struct i40e_hw *hw = &pf->hw;
|
|
|
|
|
struct i40e_vsi *vsi;
|
|
|
|
|
struct i40e_veb *veb;
|
|
|
|
|
int ret_code;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
@@ -16298,24 +16221,19 @@ static void i40e_remove(struct pci_dev *pdev)
|
|
|
|
|
/* If there is a switch structure or any orphans, remove them.
|
|
|
|
|
* This will leave only the PF's VSI remaining.
|
|
|
|
|
*/
|
|
|
|
|
for (i = 0; i < I40E_MAX_VEB; i++) {
|
|
|
|
|
if (!pf->veb[i])
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (pf->veb[i]->uplink_seid == pf->mac_seid ||
|
|
|
|
|
pf->veb[i]->uplink_seid == 0)
|
|
|
|
|
i40e_switch_branch_release(pf->veb[i]);
|
|
|
|
|
}
|
|
|
|
|
i40e_pf_for_each_veb(pf, i, veb)
|
|
|
|
|
if (veb->uplink_seid == pf->mac_seid ||
|
|
|
|
|
veb->uplink_seid == 0)
|
|
|
|
|
i40e_switch_branch_release(veb);
|
|
|
|
|
|
|
|
|
|
/* Now we can shutdown the PF's VSIs, just before we kill
|
|
|
|
|
* adminq and hmc.
|
|
|
|
|
*/
|
|
|
|
|
for (i = pf->num_alloc_vsi; i--;)
|
|
|
|
|
if (pf->vsi[i]) {
|
|
|
|
|
i40e_vsi_close(pf->vsi[i]);
|
|
|
|
|
i40e_vsi_release(pf->vsi[i]);
|
|
|
|
|
pf->vsi[i] = NULL;
|
|
|
|
|
}
|
|
|
|
|
i40e_pf_for_each_vsi(pf, i, vsi) {
|
|
|
|
|
i40e_vsi_close(vsi);
|
|
|
|
|
i40e_vsi_release(vsi);
|
|
|
|
|
pf->vsi[i] = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i40e_cloud_filter_exit(pf);
|
|
|
|
|
|
|
|
|
@@ -16352,18 +16270,17 @@ unmap:
|
|
|
|
|
/* Clear all dynamic memory lists of rings, q_vectors, and VSIs */
|
|
|
|
|
rtnl_lock();
|
|
|
|
|
i40e_clear_interrupt_scheme(pf);
|
|
|
|
|
for (i = 0; i < pf->num_alloc_vsi; i++) {
|
|
|
|
|
if (pf->vsi[i]) {
|
|
|
|
|
if (!test_bit(__I40E_RECOVERY_MODE, pf->state))
|
|
|
|
|
i40e_vsi_clear_rings(pf->vsi[i]);
|
|
|
|
|
i40e_vsi_clear(pf->vsi[i]);
|
|
|
|
|
pf->vsi[i] = NULL;
|
|
|
|
|
}
|
|
|
|
|
i40e_pf_for_each_vsi(pf, i, vsi) {
|
|
|
|
|
if (!test_bit(__I40E_RECOVERY_MODE, pf->state))
|
|
|
|
|
i40e_vsi_clear_rings(vsi);
|
|
|
|
|
|
|
|
|
|
i40e_vsi_clear(vsi);
|
|
|
|
|
pf->vsi[i] = NULL;
|
|
|
|
|
}
|
|
|
|
|
rtnl_unlock();
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < I40E_MAX_VEB; i++) {
|
|
|
|
|
kfree(pf->veb[i]);
|
|
|
|
|
i40e_pf_for_each_veb(pf, i, veb) {
|
|
|
|
|
kfree(veb);
|
|
|
|
|
pf->veb[i] = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|