提交 65662a8d 编写于 作者: A Arkadiusz Kubalewski 提交者: 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: NAleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: NArkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Tested-by: NTony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: NTony Nguyen <anthony.l.nguyen@intel.com>
上级 9f42f674
...@@ -4454,11 +4454,10 @@ int i40e_control_wait_tx_q(int seid, struct i40e_pf *pf, int pf_q, ...@@ -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 * @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; struct i40e_pf *pf = vsi->back;
int i, pf_q, ret = 0; int i, pf_q, ret = 0;
...@@ -4467,7 +4466,7 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable) ...@@ -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++) { for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
ret = i40e_control_wait_tx_q(vsi->seid, pf, ret = i40e_control_wait_tx_q(vsi->seid, pf,
pf_q, pf_q,
false /*is xdp*/, enable); false /*is xdp*/, true);
if (ret) if (ret)
break; break;
...@@ -4476,7 +4475,7 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable) ...@@ -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, ret = i40e_control_wait_tx_q(vsi->seid, pf,
pf_q + vsi->alloc_queue_pairs, pf_q + vsi->alloc_queue_pairs,
true /*is xdp*/, enable); true /*is xdp*/, true);
if (ret) if (ret)
break; break;
} }
...@@ -4574,32 +4573,25 @@ int i40e_control_wait_rx_q(struct i40e_pf *pf, int pf_q, bool enable) ...@@ -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 * @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; struct i40e_pf *pf = vsi->back;
int i, pf_q, ret = 0; int i, pf_q, ret = 0;
pf_q = vsi->base_queue; pf_q = vsi->base_queue;
for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) { 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) { if (ret) {
dev_info(&pf->pdev->dev, dev_info(&pf->pdev->dev,
"VSI seid %d Rx ring %d %sable timeout\n", "VSI seid %d Rx ring %d enable timeout\n",
vsi->seid, pf_q, (enable ? "en" : "dis")); vsi->seid, pf_q);
break; 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; return ret;
} }
...@@ -4612,29 +4604,47 @@ int i40e_vsi_start_rings(struct i40e_vsi *vsi) ...@@ -4612,29 +4604,47 @@ int i40e_vsi_start_rings(struct i40e_vsi *vsi)
int ret = 0; int ret = 0;
/* do rx first for enable and last for disable */ /* do rx first for enable and last for disable */
ret = i40e_vsi_control_rx(vsi, true); ret = i40e_vsi_enable_rx(vsi);
if (ret) if (ret)
return ret; return ret;
ret = i40e_vsi_control_tx(vsi, true); ret = i40e_vsi_enable_tx(vsi);
return ret; return ret;
} }
#define I40E_DISABLE_TX_GAP_MSEC 50
/** /**
* i40e_vsi_stop_rings - Stop a VSI's rings * i40e_vsi_stop_rings - Stop a VSI's rings
* @vsi: the VSI being configured * @vsi: the VSI being configured
**/ **/
void i40e_vsi_stop_rings(struct i40e_vsi *vsi) 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 */ /* When port TX is suspended, don't wait */
if (test_bit(__I40E_PORT_SUSPENDED, vsi->back->state)) if (test_bit(__I40E_PORT_SUSPENDED, vsi->back->state))
return i40e_vsi_stop_rings_no_wait(vsi); return i40e_vsi_stop_rings_no_wait(vsi);
/* do rx first for enable and last for disable q_end = vsi->base_queue + vsi->num_queue_pairs;
* Ignore return value, we need to shutdown whatever we can for (pf_q = vsi->base_queue; pf_q < q_end; pf_q++)
*/ i40e_pre_tx_queue_cfg(&pf->hw, (u32)pf_q, false);
i40e_vsi_control_tx(vsi, false);
i40e_vsi_control_rx(vsi, 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% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册