|
@@ -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;
|
|
|
|