Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 69e5d27a authored by Jedrzej Jagielski's avatar Jedrzej Jagielski Committed by Greg Kroah-Hartman
Browse files

i40e: Fix creation of first queue by omitting it if is not power of two



[ Upstream commit 2e6d218c1ec6fb9cd70693b78134cbc35ae0b5a9 ]

Reject TCs creation with proper message if the first queue
assignment is not equal to the power of two.
The first queue number was checked too late in the second queue
iteration, if second queue was configured at all. Now if first queue value
is not a power of two, then trying to create qdisc will be rejected.

Fixes: 8f88b303 ("i40e: Add infrastructure for queue channel support")
Signed-off-by: default avatarGrzegorz Szczurek <grzegorzx.szczurek@intel.com>
Signed-off-by: default avatarJedrzej Jagielski <jedrzej.jagielski@intel.com>
Tested-by: default avatarTony Brelinski <tony.brelinski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 5564e912
Loading
Loading
Loading
Loading
+19 −40
Original line number Diff line number Diff line
@@ -5731,24 +5731,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
@@ -6256,26 +6238,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 (vsi->type == I40E_VSI_MAIN) {
			if (pf->flags & I40E_FLAG_TC_MQPRIO)
					i40e_do_reset(pf, I40E_PF_RESET_FLAG,
						      true);
				i40e_do_reset(pf, I40E_PF_RESET_FLAG, true);
			else
					i40e_do_reset_safe(pf,
							   I40E_PF_RESET_FLAG);
			}
				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
@@ -7567,11 +7538,19 @@ static int i40e_setup_tc(struct net_device *netdev, void *type_data)
			    vsi->seid);
		need_reset = true;
		goto exit;
	} else {
	} 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]) {