/** * i40evf_set_itr_per_queue - set ITR values for specific queue * @adapter: the VF adapter struct to set values for * @ec: coalesce settings from ethtool * @queue: the queue to modify * * Change the ITR settings for a specific queue. **/ static void i40evf_set_itr_per_queue(struct i40evf_adapter *adapter, struct ethtool_coalesce *ec, int queue) { struct i40e_ring *rx_ring = &adapter->rx_rings[queue]; struct i40e_ring *tx_ring = &adapter->tx_rings[queue]; struct i40e_q_vector *q_vector; rx_ring->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs); tx_ring->itr_setting = ITR_REG_ALIGN(ec->tx_coalesce_usecs); rx_ring->itr_setting |= I40E_ITR_DYNAMIC; if (!ec->use_adaptive_rx_coalesce) rx_ring->itr_setting ^= I40E_ITR_DYNAMIC; tx_ring->itr_setting |= I40E_ITR_DYNAMIC; if (!ec->use_adaptive_tx_coalesce) tx_ring->itr_setting ^= I40E_ITR_DYNAMIC; q_vector = rx_ring->q_vector; q_vector->rx.target_itr = ITR_TO_REG(rx_ring->itr_setting); q_vector = tx_ring->q_vector; q_vector->tx.target_itr = ITR_TO_REG(tx_ring->itr_setting); /* The interrupt handler itself will take care of programming * the Tx and Rx ITR values based on the values we have entered * into the q_vector, no need to write the values now. */ }
static int i40e_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_q_vector *q_vector; struct i40e_vsi *vsi = np->vsi; struct i40e_pf *pf = vsi->back; struct i40e_hw *hw = &pf->hw; u16 vector; int i; if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq) vsi->work_limit = ec->tx_max_coalesced_frames_irq; switch (ec->rx_coalesce_usecs) { case 0: vsi->rx_itr_setting = 0; break; case 1: vsi->rx_itr_setting = (I40E_ITR_DYNAMIC | ITR_REG_TO_USEC(I40E_ITR_RX_DEF)); break; default: if ((ec->rx_coalesce_usecs < (I40E_MIN_ITR << 1)) || (ec->rx_coalesce_usecs > (I40E_MAX_ITR << 1))) return -EINVAL; vsi->rx_itr_setting = ec->rx_coalesce_usecs; break; } switch (ec->tx_coalesce_usecs) { case 0: vsi->tx_itr_setting = 0; break; case 1: vsi->tx_itr_setting = (I40E_ITR_DYNAMIC | ITR_REG_TO_USEC(I40E_ITR_TX_DEF)); break; default: if ((ec->tx_coalesce_usecs < (I40E_MIN_ITR << 1)) || (ec->tx_coalesce_usecs > (I40E_MAX_ITR << 1))) return -EINVAL; vsi->tx_itr_setting = ec->tx_coalesce_usecs; break; } vector = vsi->base_vector; for (i = 0; i < vsi->num_q_vectors; i++, vector++) { q_vector = vsi->q_vectors[i]; q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting); wr32(hw, I40E_PFINT_ITRN(0, vector - 1), q_vector->rx.itr); q_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting); wr32(hw, I40E_PFINT_ITRN(1, vector - 1), q_vector->tx.itr); i40e_flush(hw); } return 0; }
/** * i40evf_set_coalesce - Set interrupt coalescing settings * @netdev: network interface device structure * @ec: ethtool coalesce structure * * Change current coalescing settings. **/ static int i40evf_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { struct i40evf_adapter *adapter = netdev_priv(netdev); struct i40e_hw *hw = &adapter->hw; struct i40e_vsi *vsi = &adapter->vsi; struct i40e_q_vector *q_vector; int i; if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq) vsi->work_limit = ec->tx_max_coalesced_frames_irq; if ((ec->rx_coalesce_usecs >= (I40E_MIN_ITR << 1)) && (ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1))) vsi->rx_itr_setting = ec->rx_coalesce_usecs; else return -EINVAL; if ((ec->tx_coalesce_usecs >= (I40E_MIN_ITR << 1)) && (ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1))) vsi->tx_itr_setting = ec->tx_coalesce_usecs; else if (ec->use_adaptive_tx_coalesce) vsi->tx_itr_setting = (I40E_ITR_DYNAMIC | ITR_REG_TO_USEC(I40E_ITR_RX_DEF)); else return -EINVAL; if (ec->use_adaptive_rx_coalesce) vsi->rx_itr_setting |= I40E_ITR_DYNAMIC; else vsi->rx_itr_setting &= ~I40E_ITR_DYNAMIC; if (ec->use_adaptive_tx_coalesce) vsi->tx_itr_setting |= I40E_ITR_DYNAMIC; else vsi->tx_itr_setting &= ~I40E_ITR_DYNAMIC; for (i = 0; i < adapter->num_msix_vectors - NONQ_VECS; i++) { q_vector = &adapter->q_vectors[i]; q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting); wr32(hw, I40E_VFINT_ITRN1(0, i), q_vector->rx.itr); q_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting); wr32(hw, I40E_VFINT_ITRN1(1, i), q_vector->tx.itr); i40e_flush(hw); } return 0; }