Commit 65662a8d authored by Arkadiusz Kubalewski's avatar Arkadiusz Kubalewski Committed by Tony Nguyen

i40e: Fix logic of disabling queues

Correct the message flow between driver and firmware when disabling
queues.

Previously in case of PF reset (due to required reinit after reconfig),
the error like: "VSI seid 397 Tx ring 60 disable timeout" could show up
occasionally. The error was not a real issue of hardware or firmware,
it was caused by wrong sequence of messages invoked by the driver.

Fixes: 41c445ff ("i40e: main driver core")
Signed-off-by: default avatarAleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: default avatarArkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Tested-by: default avatarTony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 9f42f674
......@@ -4454,11 +4454,10 @@ int i40e_control_wait_tx_q(int seid, struct i40e_pf *pf, int pf_q,
}
/**
* i40e_vsi_control_tx - Start or stop a VSI's rings
* i40e_vsi_enable_tx - Start a VSI's rings
* @vsi: the VSI being configured
* @enable: start or stop the rings
**/
static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
static int i40e_vsi_enable_tx(struct i40e_vsi *vsi)
{
struct i40e_pf *pf = vsi->back;
int i, pf_q, ret = 0;
......@@ -4467,7 +4466,7 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
ret = i40e_control_wait_tx_q(vsi->seid, pf,
pf_q,
false /*is xdp*/, enable);
false /*is xdp*/, true);
if (ret)
break;
......@@ -4476,7 +4475,7 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
ret = i40e_control_wait_tx_q(vsi->seid, pf,
pf_q + vsi->alloc_queue_pairs,
true /*is xdp*/, enable);
true /*is xdp*/, true);
if (ret)
break;
}
......@@ -4574,32 +4573,25 @@ int i40e_control_wait_rx_q(struct i40e_pf *pf, int pf_q, bool enable)
}
/**
* i40e_vsi_control_rx - Start or stop a VSI's rings
* i40e_vsi_enable_rx - Start a VSI's rings
* @vsi: the VSI being configured
* @enable: start or stop the rings
**/
static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable)
static int i40e_vsi_enable_rx(struct i40e_vsi *vsi)
{
struct i40e_pf *pf = vsi->back;
int i, pf_q, ret = 0;
pf_q = vsi->base_queue;
for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
ret = i40e_control_wait_rx_q(pf, pf_q, enable);
ret = i40e_control_wait_rx_q(pf, pf_q, true);
if (ret) {
dev_info(&pf->pdev->dev,
"VSI seid %d Rx ring %d %sable timeout\n",
vsi->seid, pf_q, (enable ? "en" : "dis"));
"VSI seid %d Rx ring %d enable timeout\n",
vsi->seid, pf_q);
break;
}
}
/* Due to HW errata, on Rx disable only, the register can indicate done
* before it really is. Needs 50ms to be sure
*/
if (!enable)
mdelay(50);
return ret;
}
......@@ -4612,29 +4604,47 @@ int i40e_vsi_start_rings(struct i40e_vsi *vsi)
int ret = 0;
/* do rx first for enable and last for disable */
ret = i40e_vsi_control_rx(vsi, true);
ret = i40e_vsi_enable_rx(vsi);
if (ret)
return ret;
ret = i40e_vsi_control_tx(vsi, true);
ret = i40e_vsi_enable_tx(vsi);
return ret;
}
#define I40E_DISABLE_TX_GAP_MSEC 50
/**
* i40e_vsi_stop_rings - Stop a VSI's rings
* @vsi: the VSI being configured
**/
void i40e_vsi_stop_rings(struct i40e_vsi *vsi)
{
struct i40e_pf *pf = vsi->back;
int pf_q, err, q_end;
/* When port TX is suspended, don't wait */
if (test_bit(__I40E_PORT_SUSPENDED, vsi->back->state))
return i40e_vsi_stop_rings_no_wait(vsi);
/* do rx first for enable and last for disable
* Ignore return value, we need to shutdown whatever we can
*/
i40e_vsi_control_tx(vsi, false);
i40e_vsi_control_rx(vsi, false);
q_end = vsi->base_queue + vsi->num_queue_pairs;
for (pf_q = vsi->base_queue; pf_q < q_end; pf_q++)
i40e_pre_tx_queue_cfg(&pf->hw, (u32)pf_q, false);
for (pf_q = vsi->base_queue; pf_q < q_end; pf_q++) {
err = i40e_control_wait_rx_q(pf, pf_q, false);
if (err)
dev_info(&pf->pdev->dev,
"VSI seid %d Rx ring %d dissable timeout\n",
vsi->seid, pf_q);
}
msleep(I40E_DISABLE_TX_GAP_MSEC);
pf_q = vsi->base_queue;
for (pf_q = vsi->base_queue; pf_q < q_end; pf_q++)
wr32(&pf->hw, I40E_QTX_ENA(pf_q), 0);
i40e_vsi_wait_queues_disabled(vsi);
}
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment