提交 eec7e295 编写于 作者: D David S. Miller

Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue

Jeff Kirsher says:

====================
100GbE Intel Wired LAN Driver Updates 2019-03-26

This series contains more updates to the ice driver only.

Jeremiah provides his first patch to the Linux kernel to clean up
un-necessary newlines in driver log messages.

Mitch updates the ice driver to use existing status codes in the iavf
driver so that when errors occur, it will not report nonsensical
results.  Adds support for VF admin queue interrupts by programming the
VPINT_MBX_CTL register array.

Brett adds a check for a bit that we set while preparing for a reset, to
ensure we are prepared to do a proper reset.  Also implemented PCI error
handling operations.  Went through and audited the hot path with pahole
and made modifications based on the results since 2 structures were
taking up more space than necessary due to cache alignment issues.
Fixed an issue where when flow control was disabled, the state of flow
control was being displayed as "Unknown".

Anirudh fixes adaptive interrupt moderation changes by adding code that
was missed, that should have been added in the initial patch to add that
support.  Cleaned up a function prototype that was never implemented.
Did additional code cleanup by removing unneeded braces and redundant
code comments.

Akeem fixes an issue that occurs when the VF is attempting to remove the
default LAN/MAC address, which is programmed by the administrator by
updating the error message to explicitly say that the VF cannot change
the MAC programmed by the PF.

Preethi fixes the driver to not fall into the error path when a added
filter already exists, but instead continue to process the rest of the
function and add appropriate checks after adding MAC filters.
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
......@@ -294,19 +294,25 @@ struct ice_vsi {
/* struct that defines an interrupt vector */
struct ice_q_vector {
struct ice_vsi *vsi;
cpumask_t affinity_mask;
struct napi_struct napi;
struct ice_ring_container rx;
struct ice_ring_container tx;
struct irq_affinity_notify affinity_notify;
u16 v_idx; /* index in the vsi->q_vector array. */
u8 num_ring_tx; /* total number of Tx rings in vector */
u8 num_ring_rx; /* total number of Rx rings in vector */
char name[ICE_INT_NAME_STR_LEN];
u8 num_ring_tx; /* total number of Tx rings in vector */
u8 itr_countdown; /* when 0 should adjust adaptive ITR */
/* in usecs, need to use ice_intrl_to_usecs_reg() before writing this
* value to the device
*/
u8 intrl;
struct napi_struct napi;
struct ice_ring_container rx;
struct ice_ring_container tx;
cpumask_t affinity_mask;
struct irq_affinity_notify affinity_notify;
char name[ICE_INT_NAME_STR_LEN];
} ____cacheline_internodealigned_in_smp;
enum ice_pf_flags {
......
......@@ -178,6 +178,8 @@
#define VPINT_ALLOC_PCI_LAST_S 12
#define VPINT_ALLOC_PCI_LAST_M ICE_M(0x7FF, 12)
#define VPINT_ALLOC_PCI_VALID_M BIT(31)
#define VPINT_MBX_CTL(_VSI) (0x0016A000 + ((_VSI) * 4))
#define VPINT_MBX_CTL_CAUSE_ENA_M BIT(30)
#define GLLAN_RCTL_0 0x002941F8
#define QRX_CONTEXT(_i, _QRX) (0x00280000 + ((_i) * 8192 + (_QRX) * 4))
#define QRX_CTRL(_QRX) (0x00120000 + ((_QRX) * 4))
......
......@@ -342,12 +342,12 @@ enum ice_tx_desc_cmd_bits {
ICE_TX_DESC_CMD_EOP = 0x0001,
ICE_TX_DESC_CMD_RS = 0x0002,
ICE_TX_DESC_CMD_IL2TAG1 = 0x0008,
ICE_TX_DESC_CMD_IIPT_IPV6 = 0x0020, /* 2 BITS */
ICE_TX_DESC_CMD_IIPT_IPV4 = 0x0040, /* 2 BITS */
ICE_TX_DESC_CMD_IIPT_IPV4_CSUM = 0x0060, /* 2 BITS */
ICE_TX_DESC_CMD_L4T_EOFT_TCP = 0x0100, /* 2 BITS */
ICE_TX_DESC_CMD_L4T_EOFT_SCTP = 0x0200, /* 2 BITS */
ICE_TX_DESC_CMD_L4T_EOFT_UDP = 0x0300, /* 2 BITS */
ICE_TX_DESC_CMD_IIPT_IPV6 = 0x0020,
ICE_TX_DESC_CMD_IIPT_IPV4 = 0x0040,
ICE_TX_DESC_CMD_IIPT_IPV4_CSUM = 0x0060,
ICE_TX_DESC_CMD_L4T_EOFT_TCP = 0x0100,
ICE_TX_DESC_CMD_L4T_EOFT_SCTP = 0x0200,
ICE_TX_DESC_CMD_L4T_EOFT_UDP = 0x0300,
};
#define ICE_TXD_QW1_OFFSET_S 16
......
......@@ -608,11 +608,10 @@ static int __ice_vsi_get_qs_sc(struct ice_qs_cfg *qs_cfg)
/**
* __ice_vsi_get_qs - helper function for assigning queues from PF to VSI
* @qs_cfg: gathered variables needed for PF->VSI queues assignment
* @qs_cfg: gathered variables needed for pf->vsi queues assignment
*
* This is an internal function for assigning queues from the PF to VSI and
* initially tries to find contiguous space. If it is not successful to find
* contiguous space, then it tries with the scatter approach.
* This function first tries to find contiguous space. If it is not successful,
* it tries with the scatter approach.
*
* Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap
*/
......@@ -1820,7 +1819,6 @@ ice_cfg_itr(struct ice_hw *hw, struct ice_q_vector *q_vector, u16 vector)
rc->target_itr = ITR_TO_REG(rc->itr_setting);
rc->next_update = jiffies + 1;
rc->current_itr = rc->target_itr;
rc->latency_range = ICE_LOW_LATENCY;
wr32(hw, GLINT_ITR(rc->itr_idx, vector),
ITR_REG_ALIGN(rc->current_itr) >> ICE_ITR_GRAN_S);
}
......@@ -1835,7 +1833,6 @@ ice_cfg_itr(struct ice_hw *hw, struct ice_q_vector *q_vector, u16 vector)
rc->target_itr = ITR_TO_REG(rc->itr_setting);
rc->next_update = jiffies + 1;
rc->current_itr = rc->target_itr;
rc->latency_range = ICE_LOW_LATENCY;
wr32(hw, GLINT_ITR(rc->itr_idx, vector),
ITR_REG_ALIGN(rc->current_itr) >> ICE_ITR_GRAN_S);
}
......
......@@ -70,8 +70,6 @@ void ice_vsi_free_rx_rings(struct ice_vsi *vsi);
void ice_vsi_free_tx_rings(struct ice_vsi *vsi);
int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc);
int ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena);
#endif /* !_ICE_LIB_H_ */
......@@ -260,7 +260,11 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
/* Add mac addresses in the sync list */
status = ice_add_mac(hw, &vsi->tmp_sync_list);
ice_free_fltr_list(dev, &vsi->tmp_sync_list);
if (status) {
/* If filter is added successfully or already exists, do not go into
* 'if' condition and report it as error. Instead continue processing
* rest of the function.
*/
if (status && status != ICE_ERR_ALREADY_EXISTS) {
netdev_err(netdev, "Failed to add MAC filters\n");
/* If there is no more space for new umac filters, vsi
* should go into promiscuous mode. There should be some
......@@ -403,6 +407,10 @@ ice_prepare_for_reset(struct ice_pf *pf)
{
struct ice_hw *hw = &pf->hw;
/* already prepared for reset */
if (test_bit(__ICE_PREPARED_FOR_RESET, pf->state))
return;
/* Notify VFs of impending reset */
if (ice_check_sq_alive(hw, &hw->mailboxq))
ice_vc_notify_reset(pf);
......@@ -486,8 +494,7 @@ static void ice_reset_subtask(struct ice_pf *pf)
/* return if no valid reset type requested */
if (reset_type == ICE_RESET_INVAL)
return;
if (!test_bit(__ICE_PREPARED_FOR_RESET, pf->state))
ice_prepare_for_reset(pf);
ice_prepare_for_reset(pf);
/* make sure we are ready to rebuild */
if (ice_check_reset(&pf->hw)) {
......@@ -588,6 +595,9 @@ void ice_print_link_msg(struct ice_vsi *vsi, bool isup)
case ICE_FC_RX_PAUSE:
fc = "RX";
break;
case ICE_FC_NONE:
fc = "None";
break;
default:
fc = "Unknown";
break;
......@@ -1001,6 +1011,18 @@ static void ice_service_task_stop(struct ice_pf *pf)
clear_bit(__ICE_SERVICE_SCHED, pf->state);
}
/**
* ice_service_task_restart - restart service task and schedule works
* @pf: board private structure
*
* This function is needed for suspend and resume works (e.g WoL scenario)
*/
static void ice_service_task_restart(struct ice_pf *pf)
{
clear_bit(__ICE_SERVICE_DIS, pf->state);
ice_service_task_schedule(pf);
}
/**
* ice_service_timer - timer callback to schedule service task
* @t: pointer to timer_list
......@@ -2392,6 +2414,136 @@ static void ice_remove(struct pci_dev *pdev)
pci_disable_pcie_error_reporting(pdev);
}
/**
* ice_pci_err_detected - warning that PCI error has been detected
* @pdev: PCI device information struct
* @err: the type of PCI error
*
* Called to warn that something happened on the PCI bus and the error handling
* is in progress. Allows the driver to gracefully prepare/handle PCI errors.
*/
static pci_ers_result_t
ice_pci_err_detected(struct pci_dev *pdev, enum pci_channel_state err)
{
struct ice_pf *pf = pci_get_drvdata(pdev);
if (!pf) {
dev_err(&pdev->dev, "%s: unrecoverable device error %d\n",
__func__, err);
return PCI_ERS_RESULT_DISCONNECT;
}
if (!test_bit(__ICE_SUSPENDED, pf->state)) {
ice_service_task_stop(pf);
if (!test_bit(__ICE_PREPARED_FOR_RESET, pf->state)) {
set_bit(__ICE_PFR_REQ, pf->state);
ice_prepare_for_reset(pf);
}
}
return PCI_ERS_RESULT_NEED_RESET;
}
/**
* ice_pci_err_slot_reset - a PCI slot reset has just happened
* @pdev: PCI device information struct
*
* Called to determine if the driver can recover from the PCI slot reset by
* using a register read to determine if the device is recoverable.
*/
static pci_ers_result_t ice_pci_err_slot_reset(struct pci_dev *pdev)
{
struct ice_pf *pf = pci_get_drvdata(pdev);
pci_ers_result_t result;
int err;
u32 reg;
err = pci_enable_device_mem(pdev);
if (err) {
dev_err(&pdev->dev,
"Cannot re-enable PCI device after reset, error %d\n",
err);
result = PCI_ERS_RESULT_DISCONNECT;
} else {
pci_set_master(pdev);
pci_restore_state(pdev);
pci_save_state(pdev);
pci_wake_from_d3(pdev, false);
/* Check for life */
reg = rd32(&pf->hw, GLGEN_RTRIG);
if (!reg)
result = PCI_ERS_RESULT_RECOVERED;
else
result = PCI_ERS_RESULT_DISCONNECT;
}
err = pci_cleanup_aer_uncorrect_error_status(pdev);
if (err)
dev_dbg(&pdev->dev,
"pci_cleanup_aer_uncorrect_error_status failed, error %d\n",
err);
/* non-fatal, continue */
return result;
}
/**
* ice_pci_err_resume - restart operations after PCI error recovery
* @pdev: PCI device information struct
*
* Called to allow the driver to bring things back up after PCI error and/or
* reset recovery have finished
*/
static void ice_pci_err_resume(struct pci_dev *pdev)
{
struct ice_pf *pf = pci_get_drvdata(pdev);
if (!pf) {
dev_err(&pdev->dev,
"%s failed, device is unrecoverable\n", __func__);
return;
}
if (test_bit(__ICE_SUSPENDED, pf->state)) {
dev_dbg(&pdev->dev, "%s failed to resume normal operations!\n",
__func__);
return;
}
ice_do_reset(pf, ICE_RESET_PFR);
ice_service_task_restart(pf);
mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period));
}
/**
* ice_pci_err_reset_prepare - prepare device driver for PCI reset
* @pdev: PCI device information struct
*/
static void ice_pci_err_reset_prepare(struct pci_dev *pdev)
{
struct ice_pf *pf = pci_get_drvdata(pdev);
if (!test_bit(__ICE_SUSPENDED, pf->state)) {
ice_service_task_stop(pf);
if (!test_bit(__ICE_PREPARED_FOR_RESET, pf->state)) {
set_bit(__ICE_PFR_REQ, pf->state);
ice_prepare_for_reset(pf);
}
}
}
/**
* ice_pci_err_reset_done - PCI reset done, device driver reset can begin
* @pdev: PCI device information struct
*/
static void ice_pci_err_reset_done(struct pci_dev *pdev)
{
ice_pci_err_resume(pdev);
}
/* ice_pci_tbl - PCI Device ID Table
*
* Wildcard entries (PCI_ANY_ID) should come last
......@@ -2409,12 +2561,21 @@ static const struct pci_device_id ice_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, ice_pci_tbl);
static const struct pci_error_handlers ice_pci_err_handler = {
.error_detected = ice_pci_err_detected,
.slot_reset = ice_pci_err_slot_reset,
.reset_prepare = ice_pci_err_reset_prepare,
.reset_done = ice_pci_err_reset_done,
.resume = ice_pci_err_resume
};
static struct pci_driver ice_driver = {
.name = KBUILD_MODNAME,
.id_table = ice_pci_tbl,
.probe = ice_probe,
.remove = ice_remove,
.sriov_configure = ice_sriov_configure,
.err_handler = &ice_pci_err_handler
};
/**
......
......@@ -968,9 +968,8 @@ static void
ice_receive_skb(struct ice_ring *rx_ring, struct sk_buff *skb, u16 vlan_tag)
{
if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
(vlan_tag & VLAN_VID_MASK)) {
(vlan_tag & VLAN_VID_MASK))
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
}
napi_gro_receive(&rx_ring->q_vector->napi, skb);
}
......@@ -1097,18 +1096,257 @@ static int ice_clean_rx_irq(struct ice_ring *rx_ring, int budget)
return failure ? budget : (int)total_rx_pkts;
}
static unsigned int ice_itr_divisor(struct ice_port_info *pi)
{
switch (pi->phy.link_info.link_speed) {
case ICE_AQ_LINK_SPEED_40GB:
return ICE_ITR_ADAPTIVE_MIN_INC * 1024;
case ICE_AQ_LINK_SPEED_25GB:
case ICE_AQ_LINK_SPEED_20GB:
return ICE_ITR_ADAPTIVE_MIN_INC * 512;
case ICE_AQ_LINK_SPEED_100MB:
return ICE_ITR_ADAPTIVE_MIN_INC * 32;
default:
return ICE_ITR_ADAPTIVE_MIN_INC * 256;
}
}
/**
* ice_update_itr - update the adaptive ITR value based on statistics
* @q_vector: structure containing interrupt and ring information
* @rc: structure containing ring performance data
*
* Stores a new ITR value based on packets and byte
* counts during the last interrupt. The advantage of per interrupt
* computation is faster updates and more accurate ITR for the current
* traffic pattern. Constants in this function were computed
* based on theoretical maximum wire speed and thresholds were set based
* on testing data as well as attempting to minimize response time
* while increasing bulk throughput.
*/
static void
ice_update_itr(struct ice_q_vector *q_vector, struct ice_ring_container *rc)
{
unsigned int avg_wire_size, packets, bytes, itr;
unsigned long next_update = jiffies;
bool container_is_rx;
if (!rc->ring || !ITR_IS_DYNAMIC(rc->itr_setting))
return;
/* If itr_countdown is set it means we programmed an ITR within
* the last 4 interrupt cycles. This has a side effect of us
* potentially firing an early interrupt. In order to work around
* this we need to throw out any data received for a few
* interrupts following the update.
*/
if (q_vector->itr_countdown) {
itr = rc->target_itr;
goto clear_counts;
}
container_is_rx = (&q_vector->rx == rc);
/* For Rx we want to push the delay up and default to low latency.
* for Tx we want to pull the delay down and default to high latency.
*/
itr = container_is_rx ?
ICE_ITR_ADAPTIVE_MIN_USECS | ICE_ITR_ADAPTIVE_LATENCY :
ICE_ITR_ADAPTIVE_MAX_USECS | ICE_ITR_ADAPTIVE_LATENCY;
/* If we didn't update within up to 1 - 2 jiffies we can assume
* that either packets are coming in so slow there hasn't been
* any work, or that there is so much work that NAPI is dealing
* with interrupt moderation and we don't need to do anything.
*/
if (time_after(next_update, rc->next_update))
goto clear_counts;
packets = rc->total_pkts;
bytes = rc->total_bytes;
if (container_is_rx) {
/* If Rx there are 1 to 4 packets and bytes are less than
* 9000 assume insufficient data to use bulk rate limiting
* approach unless Tx is already in bulk rate limiting. We
* are likely latency driven.
*/
if (packets && packets < 4 && bytes < 9000 &&
(q_vector->tx.target_itr & ICE_ITR_ADAPTIVE_LATENCY)) {
itr = ICE_ITR_ADAPTIVE_LATENCY;
goto adjust_by_size;
}
} else if (packets < 4) {
/* If we have Tx and Rx ITR maxed and Tx ITR is running in
* bulk mode and we are receiving 4 or fewer packets just
* reset the ITR_ADAPTIVE_LATENCY bit for latency mode so
* that the Rx can relax.
*/
if (rc->target_itr == ICE_ITR_ADAPTIVE_MAX_USECS &&
(q_vector->rx.target_itr & ICE_ITR_MASK) ==
ICE_ITR_ADAPTIVE_MAX_USECS)
goto clear_counts;
} else if (packets > 32) {
/* If we have processed over 32 packets in a single interrupt
* for Tx assume we need to switch over to "bulk" mode.
*/
rc->target_itr &= ~ICE_ITR_ADAPTIVE_LATENCY;
}
/* We have no packets to actually measure against. This means
* either one of the other queues on this vector is active or
* we are a Tx queue doing TSO with too high of an interrupt rate.
*
* Between 4 and 56 we can assume that our current interrupt delay
* is only slightly too low. As such we should increase it by a small
* fixed amount.
*/
if (packets < 56) {
itr = rc->target_itr + ICE_ITR_ADAPTIVE_MIN_INC;
if ((itr & ICE_ITR_MASK) > ICE_ITR_ADAPTIVE_MAX_USECS) {
itr &= ICE_ITR_ADAPTIVE_LATENCY;
itr += ICE_ITR_ADAPTIVE_MAX_USECS;
}
goto clear_counts;
}
if (packets <= 256) {
itr = min(q_vector->tx.current_itr, q_vector->rx.current_itr);
itr &= ICE_ITR_MASK;
/* Between 56 and 112 is our "goldilocks" zone where we are
* working out "just right". Just report that our current
* ITR is good for us.
*/
if (packets <= 112)
goto clear_counts;
/* If packet count is 128 or greater we are likely looking
* at a slight overrun of the delay we want. Try halving
* our delay to see if that will cut the number of packets
* in half per interrupt.
*/
itr >>= 1;
itr &= ICE_ITR_MASK;
if (itr < ICE_ITR_ADAPTIVE_MIN_USECS)
itr = ICE_ITR_ADAPTIVE_MIN_USECS;
goto clear_counts;
}
/* The paths below assume we are dealing with a bulk ITR since
* number of packets is greater than 256. We are just going to have
* to compute a value and try to bring the count under control,
* though for smaller packet sizes there isn't much we can do as
* NAPI polling will likely be kicking in sooner rather than later.
*/
itr = ICE_ITR_ADAPTIVE_BULK;
adjust_by_size:
/* If packet counts are 256 or greater we can assume we have a gross
* overestimation of what the rate should be. Instead of trying to fine
* tune it just use the formula below to try and dial in an exact value
* gives the current packet size of the frame.
*/
avg_wire_size = bytes / packets;
/* The following is a crude approximation of:
* wmem_default / (size + overhead) = desired_pkts_per_int
* rate / bits_per_byte / (size + ethernet overhead) = pkt_rate
* (desired_pkt_rate / pkt_rate) * usecs_per_sec = ITR value
*
* Assuming wmem_default is 212992 and overhead is 640 bytes per
* packet, (256 skb, 64 headroom, 320 shared info), we can reduce the
* formula down to
*
* (170 * (size + 24)) / (size + 640) = ITR
*
* We first do some math on the packet size and then finally bitshift
* by 8 after rounding up. We also have to account for PCIe link speed
* difference as ITR scales based on this.
*/
if (avg_wire_size <= 60) {
/* Start at 250k ints/sec */
avg_wire_size = 4096;
} else if (avg_wire_size <= 380) {
/* 250K ints/sec to 60K ints/sec */
avg_wire_size *= 40;
avg_wire_size += 1696;
} else if (avg_wire_size <= 1084) {
/* 60K ints/sec to 36K ints/sec */
avg_wire_size *= 15;
avg_wire_size += 11452;
} else if (avg_wire_size <= 1980) {
/* 36K ints/sec to 30K ints/sec */
avg_wire_size *= 5;
avg_wire_size += 22420;
} else {
/* plateau at a limit of 30K ints/sec */
avg_wire_size = 32256;
}
/* If we are in low latency mode halve our delay which doubles the
* rate to somewhere between 100K to 16K ints/sec
*/
if (itr & ICE_ITR_ADAPTIVE_LATENCY)
avg_wire_size >>= 1;
/* Resultant value is 256 times larger than it needs to be. This
* gives us room to adjust the value as needed to either increase
* or decrease the value based on link speeds of 10G, 2.5G, 1G, etc.
*
* Use addition as we have already recorded the new latency flag
* for the ITR value.
*/
itr += DIV_ROUND_UP(avg_wire_size,
ice_itr_divisor(q_vector->vsi->port_info)) *
ICE_ITR_ADAPTIVE_MIN_INC;
if ((itr & ICE_ITR_MASK) > ICE_ITR_ADAPTIVE_MAX_USECS) {
itr &= ICE_ITR_ADAPTIVE_LATENCY;
itr += ICE_ITR_ADAPTIVE_MAX_USECS;
}
clear_counts:
/* write back value */
rc->target_itr = itr;
/* next update should occur within next jiffy */
rc->next_update = next_update + 1;
rc->total_bytes = 0;
rc->total_pkts = 0;
}
/**
* ice_buildreg_itr - build value for writing to the GLINT_DYN_CTL register
* @itr_idx: interrupt throttling index
* @reg_itr: interrupt throttling value adjusted based on ITR granularity
* @itr: interrupt throttling value in usecs
*/
static u32 ice_buildreg_itr(int itr_idx, u16 reg_itr)
static u32 ice_buildreg_itr(u16 itr_idx, u16 itr)
{
/* The itr value is reported in microseconds, and the register value is
* recorded in 2 microsecond units. For this reason we only need to
* shift by the GLINT_DYN_CTL_INTERVAL_S - ICE_ITR_GRAN_S to apply this
* granularity as a shift instead of division. The mask makes sure the
* ITR value is never odd so we don't accidentally write into the field
* prior to the ITR field.
*/
itr &= ICE_ITR_MASK;
return GLINT_DYN_CTL_INTENA_M | GLINT_DYN_CTL_CLEARPBA_M |
(itr_idx << GLINT_DYN_CTL_ITR_INDX_S) |
(reg_itr << GLINT_DYN_CTL_INTERVAL_S);
(itr << (GLINT_DYN_CTL_INTERVAL_S - ICE_ITR_GRAN_S));
}
/* The act of updating the ITR will cause it to immediately trigger. In order
* to prevent this from throwing off adaptive update statistics we defer the
* update so that it can only happen so often. So after either Tx or Rx are
* updated we make the adaptive scheme wait until either the ITR completely
* expires via the next_update expiration or we have been through at least
* 3 interrupts.
*/
#define ITR_COUNTDOWN_START 3
/**
* ice_update_ena_itr - Update ITR and re-enable MSIX interrupt
* @vsi: the VSI associated with the q_vector
......@@ -1117,10 +1355,14 @@ static u32 ice_buildreg_itr(int itr_idx, u16 reg_itr)
static void
ice_update_ena_itr(struct ice_vsi *vsi, struct ice_q_vector *q_vector)
{
struct ice_hw *hw = &vsi->back->hw;
struct ice_ring_container *rc;
struct ice_ring_container *tx = &q_vector->tx;
struct ice_ring_container *rx = &q_vector->rx;
u32 itr_val;
/* This will do nothing if dynamic updates are not enabled */
ice_update_itr(q_vector, tx);
ice_update_itr(q_vector, rx);
/* This block of logic allows us to get away with only updating
* one ITR value with each interrupt. The idea is to perform a
* pseudo-lazy update with the following criteria.
......@@ -1129,35 +1371,36 @@ ice_update_ena_itr(struct ice_vsi *vsi, struct ice_q_vector *q_vector)
* 2. If we must reduce an ITR that is given highest priority.
* 3. We then give priority to increasing ITR based on amount.
*/
if (q_vector->rx.target_itr < q_vector->rx.current_itr) {
rc = &q_vector->rx;
if (rx->target_itr < rx->current_itr) {
/* Rx ITR needs to be reduced, this is highest priority */
itr_val = ice_buildreg_itr(rc->itr_idx, rc->target_itr);
rc->current_itr = rc->target_itr;
} else if ((q_vector->tx.target_itr < q_vector->tx.current_itr) ||
((q_vector->rx.target_itr - q_vector->rx.current_itr) <
(q_vector->tx.target_itr - q_vector->tx.current_itr))) {
rc = &q_vector->tx;
itr_val = ice_buildreg_itr(rx->itr_idx, rx->target_itr);
rx->current_itr = rx->target_itr;
q_vector->itr_countdown = ITR_COUNTDOWN_START;
} else if ((tx->target_itr < tx->current_itr) ||
((rx->target_itr - rx->current_itr) <
(tx->target_itr - tx->current_itr))) {
/* Tx ITR needs to be reduced, this is second priority
* Tx ITR needs to be increased more than Rx, fourth priority
*/
itr_val = ice_buildreg_itr(rc->itr_idx, rc->target_itr);
rc->current_itr = rc->target_itr;
} else if (q_vector->rx.current_itr != q_vector->rx.target_itr) {
rc = &q_vector->rx;
itr_val = ice_buildreg_itr(tx->itr_idx, tx->target_itr);
tx->current_itr = tx->target_itr;
q_vector->itr_countdown = ITR_COUNTDOWN_START;
} else if (rx->current_itr != rx->target_itr) {
/* Rx ITR needs to be increased, third priority */
itr_val = ice_buildreg_itr(rc->itr_idx, rc->target_itr);
rc->current_itr = rc->target_itr;
itr_val = ice_buildreg_itr(rx->itr_idx, rx->target_itr);
rx->current_itr = rx->target_itr;
q_vector->itr_countdown = ITR_COUNTDOWN_START;
} else {
/* Still have to re-enable the interrupts */
itr_val = ice_buildreg_itr(ICE_ITR_NONE, 0);
if (q_vector->itr_countdown)
q_vector->itr_countdown--;
}
if (!test_bit(__ICE_DOWN, vsi->state)) {
int vector = vsi->hw_base_vector + q_vector->v_idx;
wr32(hw, GLINT_DYN_CTL(vector), itr_val);
}
if (!test_bit(__ICE_DOWN, vsi->state))
wr32(&vsi->back->hw,
GLINT_DYN_CTL(vsi->hw_base_vector + q_vector->v_idx),
itr_val);
}
/**
......
......@@ -128,11 +128,17 @@ enum ice_rx_dtype {
#define ICE_ITR_DYNAMIC 0x8000 /* used as flag for itr_setting */
#define ITR_IS_DYNAMIC(setting) (!!((setting) & ICE_ITR_DYNAMIC))
#define ITR_TO_REG(setting) ((setting) & ~ICE_ITR_DYNAMIC)
#define ICE_ITR_GRAN_S 1 /* Assume ITR granularity is 2us */
#define ICE_ITR_GRAN_S 1 /* ITR granularity is always 2us */
#define ICE_ITR_GRAN_US BIT(ICE_ITR_GRAN_S)
#define ICE_ITR_MASK 0x1FFE /* ITR register value alignment mask */
#define ITR_REG_ALIGN(setting) __ALIGN_MASK(setting, ~ICE_ITR_MASK)
#define ICE_ITR_ADAPTIVE_MIN_INC 0x0002
#define ICE_ITR_ADAPTIVE_MIN_USECS 0x0002
#define ICE_ITR_ADAPTIVE_MAX_USECS 0x00FA
#define ICE_ITR_ADAPTIVE_LATENCY 0x8000
#define ICE_ITR_ADAPTIVE_BULK 0x0000
#define ICE_DFLT_INTRL 0
/* Legacy or Advanced Mode Queue */
......@@ -178,21 +184,13 @@ struct ice_ring {
u16 next_to_alloc;
} ____cacheline_internodealigned_in_smp;
enum ice_latency_range {
ICE_LOWEST_LATENCY = 0,
ICE_LOW_LATENCY = 1,
ICE_BULK_LATENCY = 2,
ICE_ULTRA_LATENCY = 3,
};
struct ice_ring_container {
/* head of linked-list of rings */
struct ice_ring *ring;
unsigned long next_update; /* jiffies value of next queue update */
unsigned int total_bytes; /* total bytes processed this int */
unsigned int total_pkts; /* total packets processed this int */
enum ice_latency_range latency_range;
int itr_idx; /* index in the interrupt vector */
u16 itr_idx; /* index in the interrupt vector */
u16 target_itr; /* value in usecs divided by the hw->itr_gran */
u16 current_itr; /* value in usecs divided by the hw->itr_gran */
/* high bit set means dynamic ITR, rest is used to store user
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册