Commit c768e490 authored by Jacob Keller's avatar Jacob Keller Committed by Jeff Kirsher

i40e: factor out queue control from i40e_vsi_control_(tx|rx)

A future patch will need to be able to handle controlling queues without
waiting until all VSIs are handled. Factor out the direct queue
modification so that we can easily re-use this code. The result is also
a bit easier to read since we don't embed multiple single-letter loop
counters.

Change-ID: Id923cbfa43127b1c24d8ed4f809b1012c736d9ac
Signed-off-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 024b05f4
......@@ -3919,6 +3919,8 @@ static void i40e_netpoll(struct net_device *netdev)
}
#endif
#define I40E_QTX_ENA_WAIT_COUNT 50
/**
* i40e_pf_txq_wait - Wait for a PF's Tx queue to be enabled or disabled
* @pf: the PF being configured
......@@ -3948,6 +3950,50 @@ static int i40e_pf_txq_wait(struct i40e_pf *pf, int pf_q, bool enable)
return 0;
}
/**
* i40e_control_tx_q - Start or stop a particular Tx queue
* @pf: the PF structure
* @pf_q: the PF queue to configure
* @enable: start or stop the queue
*
* This function enables or disables a single queue. Note that any delay
* required after the operation is expected to be handled by the caller of
* this function.
**/
static void i40e_control_tx_q(struct i40e_pf *pf, int pf_q, bool enable)
{
struct i40e_hw *hw = &pf->hw;
u32 tx_reg;
int i;
/* warn the TX unit of coming changes */
i40e_pre_tx_queue_cfg(&pf->hw, pf_q, enable);
if (!enable)
usleep_range(10, 20);
for (i = 0; i < I40E_QTX_ENA_WAIT_COUNT; i++) {
tx_reg = rd32(hw, I40E_QTX_ENA(pf_q));
if (((tx_reg >> I40E_QTX_ENA_QENA_REQ_SHIFT) & 1) ==
((tx_reg >> I40E_QTX_ENA_QENA_STAT_SHIFT) & 1))
break;
usleep_range(1000, 2000);
}
/* Skip if the queue is already in the requested state */
if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK))
return;
/* turn on/off the queue */
if (enable) {
wr32(hw, I40E_QTX_HEAD(pf_q), 0);
tx_reg |= I40E_QTX_ENA_QENA_REQ_MASK;
} else {
tx_reg &= ~I40E_QTX_ENA_QENA_REQ_MASK;
}
wr32(hw, I40E_QTX_ENA(pf_q), tx_reg);
}
/**
* i40e_vsi_control_tx - Start or stop a VSI's rings
* @vsi: the VSI being configured
......@@ -3956,39 +4002,13 @@ static int i40e_pf_txq_wait(struct i40e_pf *pf, int pf_q, bool enable)
static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
{
struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
int i, j, pf_q, ret = 0;
u32 tx_reg;
int i, pf_q, ret = 0;
pf_q = vsi->base_queue;
for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
i40e_control_tx_q(pf, pf_q, enable);
/* warn the TX unit of coming changes */
i40e_pre_tx_queue_cfg(&pf->hw, pf_q, enable);
if (!enable)
usleep_range(10, 20);
for (j = 0; j < 50; j++) {
tx_reg = rd32(hw, I40E_QTX_ENA(pf_q));
if (((tx_reg >> I40E_QTX_ENA_QENA_REQ_SHIFT) & 1) ==
((tx_reg >> I40E_QTX_ENA_QENA_STAT_SHIFT) & 1))
break;
usleep_range(1000, 2000);
}
/* Skip if the queue is already in the requested state */
if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK))
continue;
/* turn on/off the queue */
if (enable) {
wr32(hw, I40E_QTX_HEAD(pf_q), 0);
tx_reg |= I40E_QTX_ENA_QENA_REQ_MASK;
} else {
tx_reg &= ~I40E_QTX_ENA_QENA_REQ_MASK;
}
wr32(hw, I40E_QTX_ENA(pf_q), tx_reg);
/* No waiting for the Tx queue to disable */
/* Don't wait to disable when port Tx is suspended */
if (!enable && test_bit(__I40E_PORT_TX_SUSPENDED, &pf->state))
continue;
......@@ -4034,6 +4054,43 @@ static int i40e_pf_rxq_wait(struct i40e_pf *pf, int pf_q, bool enable)
return 0;
}
/**
* i40e_control_rx_q - Start or stop a particular Rx queue
* @pf: the PF structure
* @pf_q: the PF queue to configure
* @enable: start or stop the queue
*
* This function enables or disables a single queue. Note that any delay
* required after the operation is expected to be handled by the caller of
* this function.
**/
static void i40e_control_rx_q(struct i40e_pf *pf, int pf_q, bool enable)
{
struct i40e_hw *hw = &pf->hw;
u32 rx_reg;
int i;
for (i = 0; i < I40E_QTX_ENA_WAIT_COUNT; i++) {
rx_reg = rd32(hw, I40E_QRX_ENA(pf_q));
if (((rx_reg >> I40E_QRX_ENA_QENA_REQ_SHIFT) & 1) ==
((rx_reg >> I40E_QRX_ENA_QENA_STAT_SHIFT) & 1))
break;
usleep_range(1000, 2000);
}
/* Skip if the queue is already in the requested state */
if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK))
return;
/* turn on/off the queue */
if (enable)
rx_reg |= I40E_QRX_ENA_QENA_REQ_MASK;
else
rx_reg &= ~I40E_QRX_ENA_QENA_REQ_MASK;
wr32(hw, I40E_QRX_ENA(pf_q), rx_reg);
}
/**
* i40e_vsi_control_rx - Start or stop a VSI's rings
* @vsi: the VSI being configured
......@@ -4042,31 +4099,13 @@ static int i40e_pf_rxq_wait(struct i40e_pf *pf, int pf_q, bool enable)
static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable)
{
struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
int i, j, pf_q, ret = 0;
u32 rx_reg;
int i, pf_q, ret = 0;
pf_q = vsi->base_queue;
for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
for (j = 0; j < 50; j++) {
rx_reg = rd32(hw, I40E_QRX_ENA(pf_q));
if (((rx_reg >> I40E_QRX_ENA_QENA_REQ_SHIFT) & 1) ==
((rx_reg >> I40E_QRX_ENA_QENA_STAT_SHIFT) & 1))
break;
usleep_range(1000, 2000);
}
i40e_control_rx_q(pf, pf_q, enable);
/* Skip if the queue is already in the requested state */
if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK))
continue;
/* turn on/off the queue */
if (enable)
rx_reg |= I40E_QRX_ENA_QENA_REQ_MASK;
else
rx_reg &= ~I40E_QRX_ENA_QENA_REQ_MASK;
wr32(hw, I40E_QRX_ENA(pf_q), rx_reg);
/* No waiting for the Tx queue to disable */
/* Don't wait to disable when port Tx is suspended */
if (!enable && test_bit(__I40E_PORT_TX_SUSPENDED, &pf->state))
continue;
......
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