Skip to content

Commit 6096dae

Browse files
agerasymanguy11
authored andcommitted
ice: clear stale Tx queue settings before configuring
The iAVF driver uses 3 virtchnl op codes to communicate with the PF regarding the VF Tx queues: * VIRTCHNL_OP_CONFIG_VSI_QUEUES configures the hardware and firmware logic for the Tx queues * VIRTCHNL_OP_ENABLE_QUEUES configures the queue interrupts * VIRTCHNL_OP_DISABLE_QUEUES disables the queue interrupts and Tx rings. There is a bug in the iAVF driver due to the race condition between VF reset request and shutdown being executed in parallel. This leads to a break in logic and VIRTCHNL_OP_DISABLE_QUEUES is not being sent. If this occurs, the PF driver never cleans up the Tx queues. This results in leaving behind stale Tx queue settings in the hardware and firmware. The most obvious outcome is that upon the next VIRTCHNL_OP_CONFIG_VSI_QUEUES, the PF will fail to program the Tx scheduler node due to a lack of space. We need to protect ICE driver against such situation. To fix this, make sure we clear existing stale settings out when handling VIRTCHNL_OP_CONFIG_VSI_QUEUES. This ensures we remove the previous settings. Calling ice_vf_vsi_dis_single_txq should be safe as it will do nothing if the queue is not configured. The function already handles the case when the Tx queue is not currently configured and exits with a 0 return in that case. Fixes: 7ad1544 ("ice: Refactor VIRTCHNL_OP_CONFIG_VSI_QUEUES handling") Signed-off-by: Jacob Keller <[email protected]> Signed-off-by: Anatolii Gerasymenko <[email protected]> Tested-by: Konrad Jankowski <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent 486b9ee commit 6096dae

File tree

1 file changed

+50
-18
lines changed

1 file changed

+50
-18
lines changed

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

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,13 +1307,52 @@ static int ice_vc_ena_qs_msg(struct ice_vf *vf, u8 *msg)
13071307
NULL, 0);
13081308
}
13091309

1310+
/**
1311+
* ice_vf_vsi_dis_single_txq - disable a single Tx queue
1312+
* @vf: VF to disable queue for
1313+
* @vsi: VSI for the VF
1314+
* @q_id: VF relative (0-based) queue ID
1315+
*
1316+
* Attempt to disable the Tx queue passed in. If the Tx queue was successfully
1317+
* disabled then clear q_id bit in the enabled queues bitmap and return
1318+
* success. Otherwise return error.
1319+
*/
1320+
static int
1321+
ice_vf_vsi_dis_single_txq(struct ice_vf *vf, struct ice_vsi *vsi, u16 q_id)
1322+
{
1323+
struct ice_txq_meta txq_meta = { 0 };
1324+
struct ice_tx_ring *ring;
1325+
int err;
1326+
1327+
if (!test_bit(q_id, vf->txq_ena))
1328+
dev_dbg(ice_pf_to_dev(vsi->back), "Queue %u on VSI %u is not enabled, but stopping it anyway\n",
1329+
q_id, vsi->vsi_num);
1330+
1331+
ring = vsi->tx_rings[q_id];
1332+
if (!ring)
1333+
return -EINVAL;
1334+
1335+
ice_fill_txq_meta(vsi, ring, &txq_meta);
1336+
1337+
err = ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, vf->vf_id, ring, &txq_meta);
1338+
if (err) {
1339+
dev_err(ice_pf_to_dev(vsi->back), "Failed to stop Tx ring %d on VSI %d\n",
1340+
q_id, vsi->vsi_num);
1341+
return err;
1342+
}
1343+
1344+
/* Clear enabled queues flag */
1345+
clear_bit(q_id, vf->txq_ena);
1346+
1347+
return 0;
1348+
}
1349+
13101350
/**
13111351
* ice_vc_dis_qs_msg
13121352
* @vf: pointer to the VF info
13131353
* @msg: pointer to the msg buffer
13141354
*
1315-
* called from the VF to disable all or specific
1316-
* queue(s)
1355+
* called from the VF to disable all or specific queue(s)
13171356
*/
13181357
static int ice_vc_dis_qs_msg(struct ice_vf *vf, u8 *msg)
13191358
{
@@ -1350,30 +1389,15 @@ static int ice_vc_dis_qs_msg(struct ice_vf *vf, u8 *msg)
13501389
q_map = vqs->tx_queues;
13511390

13521391
for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) {
1353-
struct ice_tx_ring *ring = vsi->tx_rings[vf_q_id];
1354-
struct ice_txq_meta txq_meta = { 0 };
1355-
13561392
if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) {
13571393
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
13581394
goto error_param;
13591395
}
13601396

1361-
if (!test_bit(vf_q_id, vf->txq_ena))
1362-
dev_dbg(ice_pf_to_dev(vsi->back), "Queue %u on VSI %u is not enabled, but stopping it anyway\n",
1363-
vf_q_id, vsi->vsi_num);
1364-
1365-
ice_fill_txq_meta(vsi, ring, &txq_meta);
1366-
1367-
if (ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, vf->vf_id,
1368-
ring, &txq_meta)) {
1369-
dev_err(ice_pf_to_dev(vsi->back), "Failed to stop Tx ring %d on VSI %d\n",
1370-
vf_q_id, vsi->vsi_num);
1397+
if (ice_vf_vsi_dis_single_txq(vf, vsi, vf_q_id)) {
13711398
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
13721399
goto error_param;
13731400
}
1374-
1375-
/* Clear enabled queues flag */
1376-
clear_bit(vf_q_id, vf->txq_ena);
13771401
}
13781402
}
13791403

@@ -1622,6 +1646,14 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
16221646
if (qpi->txq.ring_len > 0) {
16231647
vsi->tx_rings[i]->dma = qpi->txq.dma_ring_addr;
16241648
vsi->tx_rings[i]->count = qpi->txq.ring_len;
1649+
1650+
/* Disable any existing queue first */
1651+
if (ice_vf_vsi_dis_single_txq(vf, vsi, q_idx)) {
1652+
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1653+
goto error_param;
1654+
}
1655+
1656+
/* Configure a queue with the requested settings */
16251657
if (ice_vsi_cfg_single_txq(vsi, vsi->tx_rings, q_idx)) {
16261658
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
16271659
goto error_param;

0 commit comments

Comments
 (0)