Skip to content

Commit

Permalink
Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git…
Browse files Browse the repository at this point in the history
…/tnguy/net-

queue

Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2021-11-17

This series contains updates to i40e driver only.

Eryk adds accounting for VLAN header in packet size when VF port VLAN is
configured. He also fixes TC queue distribution when the user has changed
queue counts as well as for configuration of VF ADQ which caused dropped
packets.

Michal adds tracking for when a VSI is being released to prevent null
pointer dereference when managing filters.

Karen ensures PF successfully initiates VF requested reset which could
cause a call trace otherwise.

Jedrzej moves validation of channel queue value earlier to prevent
partial configuration when the value is invalid.

Grzegorz corrects the reported error when adding filter fails.
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Nov 18, 2021
2 parents 5f9c55c + 5aff430 commit 4e5d212
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 136 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/i40e/i40e.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ enum i40e_vsi_state_t {
__I40E_VSI_OVERFLOW_PROMISC,
__I40E_VSI_REINIT_REQUESTED,
__I40E_VSI_DOWN_REQUESTED,
__I40E_VSI_RELEASING,
/* This must be last as it determines the size of the BITMAP */
__I40E_VSI_STATE_SIZE__,
};
Expand Down Expand Up @@ -1247,6 +1248,7 @@ void i40e_ptp_restore_hw_time(struct i40e_pf *pf);
void i40e_ptp_init(struct i40e_pf *pf);
void i40e_ptp_stop(struct i40e_pf *pf);
int i40e_ptp_alloc_pins(struct i40e_pf *pf);
int i40e_update_adq_vsi_queues(struct i40e_vsi *vsi, int vsi_offset);
int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi);
i40e_status i40e_get_partition_bw_setting(struct i40e_pf *pf);
i40e_status i40e_set_partition_bw_setting(struct i40e_pf *pf);
Expand Down
160 changes: 104 additions & 56 deletions drivers/net/ethernet/intel/i40e/i40e_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1790,20 +1790,41 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
bool is_add)
{
struct i40e_pf *pf = vsi->back;
u16 num_tc_qps = 0;
u16 sections = 0;
u8 netdev_tc = 0;
u16 numtc = 1;
u16 qcount;
u8 offset;
u16 qmap;
int i;
u16 num_tc_qps = 0;

sections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID;
offset = 0;
/* zero out queue mapping, it will get updated on the end of the function */
memset(ctxt->info.queue_mapping, 0, sizeof(ctxt->info.queue_mapping));

if (vsi->type == I40E_VSI_MAIN) {
/* This code helps add more queue to the VSI if we have
* more cores than RSS can support, the higher cores will
* be served by ATR or other filters. Furthermore, the
* non-zero req_queue_pairs says that user requested a new
* queue count via ethtool's set_channels, so use this
* value for queues distribution across traffic classes
*/
if (vsi->req_queue_pairs > 0)
vsi->num_queue_pairs = vsi->req_queue_pairs;
else if (pf->flags & I40E_FLAG_MSIX_ENABLED)
vsi->num_queue_pairs = pf->num_lan_msix;
}

/* Number of queues per enabled TC */
num_tc_qps = vsi->alloc_queue_pairs;
if (vsi->type == I40E_VSI_MAIN ||
(vsi->type == I40E_VSI_SRIOV && vsi->num_queue_pairs != 0))
num_tc_qps = vsi->num_queue_pairs;
else
num_tc_qps = vsi->alloc_queue_pairs;

if (enabled_tc && (vsi->back->flags & I40E_FLAG_DCB_ENABLED)) {
/* Find numtc from enabled TC bitmap */
for (i = 0, numtc = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
Expand Down Expand Up @@ -1881,15 +1902,11 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
}
ctxt->info.tc_mapping[i] = cpu_to_le16(qmap);
}

/* Set actual Tx/Rx queue pairs */
vsi->num_queue_pairs = offset;
if ((vsi->type == I40E_VSI_MAIN) && (numtc == 1)) {
if (vsi->req_queue_pairs > 0)
vsi->num_queue_pairs = vsi->req_queue_pairs;
else if (pf->flags & I40E_FLAG_MSIX_ENABLED)
vsi->num_queue_pairs = pf->num_lan_msix;
}
/* Do not change previously set num_queue_pairs for PFs and VFs*/
if ((vsi->type == I40E_VSI_MAIN && numtc != 1) ||
(vsi->type == I40E_VSI_SRIOV && vsi->num_queue_pairs == 0) ||
(vsi->type != I40E_VSI_MAIN && vsi->type != I40E_VSI_SRIOV))
vsi->num_queue_pairs = offset;

/* Scheduler section valid can only be set for ADD VSI */
if (is_add) {
Expand Down Expand Up @@ -2623,7 +2640,8 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf)

for (v = 0; v < pf->num_alloc_vsi; v++) {
if (pf->vsi[v] &&
(pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED)) {
(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]);

if (ret) {
Expand Down Expand Up @@ -5426,6 +5444,58 @@ static void i40e_vsi_update_queue_map(struct i40e_vsi *vsi,
sizeof(vsi->info.tc_mapping));
}

/**
* i40e_update_adq_vsi_queues - update queue mapping for ADq VSI
* @vsi: the VSI being reconfigured
* @vsi_offset: offset from main VF VSI
*/
int i40e_update_adq_vsi_queues(struct i40e_vsi *vsi, int vsi_offset)
{
struct i40e_vsi_context ctxt = {};
struct i40e_pf *pf;
struct i40e_hw *hw;
int ret;

if (!vsi)
return I40E_ERR_PARAM;
pf = vsi->back;
hw = &pf->hw;

ctxt.seid = vsi->seid;
ctxt.pf_num = hw->pf_id;
ctxt.vf_num = vsi->vf_id + hw->func_caps.vf_base_id + vsi_offset;
ctxt.uplink_seid = vsi->uplink_seid;
ctxt.connection_type = I40E_AQ_VSI_CONN_TYPE_NORMAL;
ctxt.flags = I40E_AQ_VSI_TYPE_VF;
ctxt.info = vsi->info;

i40e_vsi_setup_queue_map(vsi, &ctxt, vsi->tc_config.enabled_tc,
false);
if (vsi->reconfig_rss) {
vsi->rss_size = min_t(int, pf->alloc_rss_size,
vsi->num_queue_pairs);
ret = i40e_vsi_config_rss(vsi);
if (ret) {
dev_info(&pf->pdev->dev, "Failed to reconfig rss for num_queues\n");
return ret;
}
vsi->reconfig_rss = false;
}

ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
if (ret) {
dev_info(&pf->pdev->dev, "Update vsi config failed, err %s aq_err %s\n",
i40e_stat_str(hw, ret),
i40e_aq_str(hw, hw->aq.asq_last_status));
return ret;
}
/* update the local VSI info with updated queue map */
i40e_vsi_update_queue_map(vsi, &ctxt);
vsi->info.valid_sections = 0;

return ret;
}

/**
* i40e_vsi_config_tc - Configure VSI Tx Scheduler for given TC map
* @vsi: VSI to be configured
Expand Down Expand Up @@ -5716,24 +5786,6 @@ static void i40e_remove_queue_channels(struct i40e_vsi *vsi)
INIT_LIST_HEAD(&vsi->ch_list);
}

/**
* i40e_is_any_channel - channel exist or not
* @vsi: ptr to VSI to which channels are associated with
*
* Returns true or false if channel(s) exist for associated VSI or not
**/
static bool i40e_is_any_channel(struct i40e_vsi *vsi)
{
struct i40e_channel *ch, *ch_tmp;

list_for_each_entry_safe(ch, ch_tmp, &vsi->ch_list, list) {
if (ch->initialized)
return true;
}

return false;
}

/**
* i40e_get_max_queues_for_channel
* @vsi: ptr to VSI to which channels are associated with
Expand Down Expand Up @@ -6240,26 +6292,15 @@ int i40e_create_queue_channel(struct i40e_vsi *vsi,
/* By default we are in VEPA mode, if this is the first VF/VMDq
* VSI to be added switch to VEB mode.
*/
if ((!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) ||
(!i40e_is_any_channel(vsi))) {
if (!is_power_of_2(vsi->tc_config.tc_info[0].qcount)) {
dev_dbg(&pf->pdev->dev,
"Failed to create channel. Override queues (%u) not power of 2\n",
vsi->tc_config.tc_info[0].qcount);
return -EINVAL;
}

if (!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) {
pf->flags |= I40E_FLAG_VEB_MODE_ENABLED;
if (!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) {
pf->flags |= I40E_FLAG_VEB_MODE_ENABLED;

if (vsi->type == I40E_VSI_MAIN) {
if (pf->flags & I40E_FLAG_TC_MQPRIO)
i40e_do_reset(pf, I40E_PF_RESET_FLAG,
true);
else
i40e_do_reset_safe(pf,
I40E_PF_RESET_FLAG);
}
if (vsi->type == I40E_VSI_MAIN) {
if (pf->flags & I40E_FLAG_TC_MQPRIO)
i40e_do_reset(pf, I40E_PF_RESET_FLAG, true);
else
i40e_do_reset_safe(pf, I40E_PF_RESET_FLAG);
}
/* now onwards for main VSI, number of queues will be value
* of TC0's queue count
Expand Down Expand Up @@ -7912,12 +7953,20 @@ static int i40e_setup_tc(struct net_device *netdev, void *type_data)
vsi->seid);
need_reset = true;
goto exit;
} else {
dev_info(&vsi->back->pdev->dev,
"Setup channel (id:%u) utilizing num_queues %d\n",
vsi->seid, vsi->tc_config.tc_info[0].qcount);
} else if (enabled_tc &&
(!is_power_of_2(vsi->tc_config.tc_info[0].qcount))) {
netdev_info(netdev,
"Failed to create channel. Override queues (%u) not power of 2\n",
vsi->tc_config.tc_info[0].qcount);
ret = -EINVAL;
need_reset = true;
goto exit;
}

dev_info(&vsi->back->pdev->dev,
"Setup channel (id:%u) utilizing num_queues %d\n",
vsi->seid, vsi->tc_config.tc_info[0].qcount);

if (pf->flags & I40E_FLAG_TC_MQPRIO) {
if (vsi->mqprio_qopt.max_rate[0]) {
u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0];
Expand Down Expand Up @@ -8482,9 +8531,8 @@ static int i40e_configure_clsflower(struct i40e_vsi *vsi,
err = i40e_add_del_cloud_filter(vsi, filter, true);

if (err) {
dev_err(&pf->pdev->dev,
"Failed to add cloud filter, err %s\n",
i40e_stat_str(&pf->hw, err));
dev_err(&pf->pdev->dev, "Failed to add cloud filter, err %d\n",
err);
goto err;
}

Expand Down Expand Up @@ -13771,7 +13819,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
dev_info(&pf->pdev->dev, "Can't remove PF VSI\n");
return -ENODEV;
}

set_bit(__I40E_VSI_RELEASING, vsi->state);
uplink_seid = vsi->uplink_seid;
if (vsi->type != I40E_VSI_SRIOV) {
if (vsi->netdev_registered) {
Expand Down
Loading

0 comments on commit 4e5d212

Please sign in to comment.