/* forward decls */
 static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector);
-static void ixgbevf_write_eitr(struct ixgbevf_adapter *adapter, int v_idx,
-                              u32 itr_reg);
 
 static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw,
                                           struct ixgbevf_ring *rx_ring,
 }
 
 static inline void ixgbevf_irq_enable_queues(struct ixgbevf_adapter *adapter,
-                                            u64 qmask)
+                                            u32 qmask)
 {
-       u32 mask;
        struct ixgbe_hw *hw = &adapter->hw;
 
-       mask = (qmask & 0xFFFFFFFF);
-       IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
+       IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, qmask);
 }
 
 static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
 static void ixgbevf_configure_msix(struct ixgbevf_adapter *adapter)
 {
        struct ixgbevf_q_vector *q_vector;
-       struct ixgbe_hw *hw = &adapter->hw;
        int q_vectors, v_idx;
-       u32 mask;
 
        q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+       adapter->eims_enable_mask = 0;
 
        /*
         * Populate the IVAR table and set the ITR values to the
                ixgbevf_for_each_ring(ring, q_vector->tx)
                        ixgbevf_set_ivar(adapter, 1, ring->reg_idx, v_idx);
 
-               /* if this is a tx only vector halve the interrupt rate */
-               if (q_vector->tx.ring && !q_vector->rx.ring)
-                       q_vector->eitr = (adapter->eitr_param >> 1);
-               else if (q_vector->rx.ring)
-                       /* rx only */
-                       q_vector->eitr = adapter->eitr_param;
+               if (q_vector->tx.ring && !q_vector->rx.ring) {
+                       /* tx only vector */
+                       if (adapter->tx_itr_setting == 1)
+                               q_vector->itr = IXGBE_10K_ITR;
+                       else
+                               q_vector->itr = adapter->tx_itr_setting;
+               } else {
+                       /* rx or rx/tx vector */
+                       if (adapter->rx_itr_setting == 1)
+                               q_vector->itr = IXGBE_20K_ITR;
+                       else
+                               q_vector->itr = adapter->rx_itr_setting;
+               }
+
+               /* add q_vector eims value to global eims_enable_mask */
+               adapter->eims_enable_mask |= 1 << v_idx;
 
-               ixgbevf_write_eitr(adapter, v_idx, q_vector->eitr);
+               ixgbevf_write_eitr(q_vector);
        }
 
        ixgbevf_set_ivar(adapter, -1, 1, v_idx);
-
-       /* set up to autoclear timer, and the vectors */
-       mask = IXGBE_EIMS_ENABLE_MASK;
-       mask &= ~IXGBE_EIMS_OTHER;
-       IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, mask);
+       /* setup eims_other and add value to global eims_enable_mask */
+       adapter->eims_other = 1 << v_idx;
+       adapter->eims_enable_mask |= adapter->eims_other;
 }
 
 enum latency_range {
 
 /**
  * ixgbevf_update_itr - update the dynamic ITR value based on statistics
- * @adapter: pointer to adapter
- * @eitr: eitr setting (ints per sec) to give last timeslice
- * @itr_setting: current throttle rate in ints/second
- * @packets: the number of packets during this measurement interval
- * @bytes: the number of bytes during this measurement interval
+ * @q_vector: structure containing interrupt and ring information
+ * @ring_container: 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
  *      on testing data as well as attempting to minimize response time
  *      while increasing bulk throughput.
  **/
-static u8 ixgbevf_update_itr(struct ixgbevf_adapter *adapter,
-                            u32 eitr, u8 itr_setting,
-                            int packets, int bytes)
+static void ixgbevf_update_itr(struct ixgbevf_q_vector *q_vector,
+                              struct ixgbevf_ring_container *ring_container)
 {
-       unsigned int retval = itr_setting;
+       int bytes = ring_container->total_bytes;
+       int packets = ring_container->total_packets;
        u32 timepassed_us;
        u64 bytes_perint;
+       u8 itr_setting = ring_container->itr;
 
        if (packets == 0)
-               goto update_itr_done;
-
+               return;
 
        /* simple throttlerate management
         *    0-20MB/s lowest (100000 ints/s)
         *  100-1249MB/s bulk (8000 ints/s)
         */
        /* what was last interrupt timeslice? */
-       timepassed_us = 1000000/eitr;
+       timepassed_us = q_vector->itr >> 2;
        bytes_perint = bytes / timepassed_us; /* bytes/usec */
 
        switch (itr_setting) {
        case lowest_latency:
                if (bytes_perint > 10)
-                       retval = low_latency;
+                       itr_setting = low_latency;
                break;
        case low_latency:
                if (bytes_perint > 20)
-                       retval = bulk_latency;
+                       itr_setting = bulk_latency;
                else if (bytes_perint <= 10)
-                       retval = lowest_latency;
+                       itr_setting = lowest_latency;
                break;
        case bulk_latency:
                if (bytes_perint <= 20)
-                       retval = low_latency;
+                       itr_setting = low_latency;
                break;
        }
 
-update_itr_done:
-       return retval;
+       /* clear work counters since we have the values we need */
+       ring_container->total_bytes = 0;
+       ring_container->total_packets = 0;
+
+       /* write updated itr to ring container */
+       ring_container->itr = itr_setting;
 }
 
 /**
  * ixgbevf_write_eitr - write VTEITR register in hardware specific way
- * @adapter: pointer to adapter struct
- * @v_idx: vector index into q_vector array
- * @itr_reg: new value to be written in *register* format, not ints/s
+ * @q_vector: structure containing interrupt and ring information
  *
  * This function is made to be called by ethtool and by the driver
  * when it needs to update VTEITR registers at runtime.  Hardware
  * specific quirks/differences are taken care of here.
  */
-static void ixgbevf_write_eitr(struct ixgbevf_adapter *adapter, int v_idx,
-                              u32 itr_reg)
+void ixgbevf_write_eitr(struct ixgbevf_q_vector *q_vector)
 {
+       struct ixgbevf_adapter *adapter = q_vector->adapter;
        struct ixgbe_hw *hw = &adapter->hw;
-
-       itr_reg = EITR_INTS_PER_SEC_TO_REG(itr_reg);
+       int v_idx = q_vector->v_idx;
+       u32 itr_reg = q_vector->itr & IXGBE_MAX_EITR;
 
        /*
         * set the WDIS bit to not clear the timer bits and cause an
 
 static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector)
 {
-       struct ixgbevf_adapter *adapter = q_vector->adapter;
-       u32 new_itr;
-       u8 current_itr, ret_itr;
-       int v_idx = q_vector->v_idx;
-       struct ixgbevf_ring *rx_ring, *tx_ring;
-
-       ixgbevf_for_each_ring(tx_ring, q_vector->tx) {
-               ret_itr = ixgbevf_update_itr(adapter, q_vector->eitr,
-                                            q_vector->tx.itr,
-                                            tx_ring->total_packets,
-                                            tx_ring->total_bytes);
-               /* if the result for this queue would decrease interrupt
-                * rate for this vector then use that result */
-               q_vector->tx.itr = ((q_vector->tx.itr > ret_itr) ?
-                                   q_vector->tx.itr - 1 : ret_itr);
-       }
-
-       ixgbevf_for_each_ring(rx_ring, q_vector->rx) {
-               ret_itr = ixgbevf_update_itr(adapter, q_vector->eitr,
-                                            q_vector->rx.itr,
-                                            rx_ring->total_packets,
-                                            rx_ring->total_bytes);
-               /* if the result for this queue would decrease interrupt
-                * rate for this vector then use that result */
-               q_vector->rx.itr = ((q_vector->rx.itr > ret_itr) ?
-                                   q_vector->rx.itr - 1 : ret_itr);
-       }
+       u32 new_itr = q_vector->itr;
+       u8 current_itr;
+
+       ixgbevf_update_itr(q_vector, &q_vector->tx);
+       ixgbevf_update_itr(q_vector, &q_vector->rx);
 
        current_itr = max(q_vector->rx.itr, q_vector->tx.itr);
 
        switch (current_itr) {
        /* counts and packets in update_itr are dependent on these numbers */
        case lowest_latency:
-               new_itr = 100000;
+               new_itr = IXGBE_100K_ITR;
                break;
        case low_latency:
-               new_itr = 20000; /* aka hwitr = ~200 */
+               new_itr = IXGBE_20K_ITR;
                break;
        case bulk_latency:
        default:
-               new_itr = 8000;
+               new_itr = IXGBE_8K_ITR;
                break;
        }
 
-       if (new_itr != q_vector->eitr) {
-               u32 itr_reg;
-
-               /* save the algorithm value here, not the smoothed one */
-               q_vector->eitr = new_itr;
+       if (new_itr != q_vector->itr) {
                /* do an exponential smoothing */
-               new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
-               itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr);
-               ixgbevf_write_eitr(adapter, v_idx, itr_reg);
+               new_itr = (10 * new_itr * q_vector->itr) /
+                         ((9 * new_itr) + q_vector->itr);
+
+               /* save the algorithm value here */
+               q_vector->itr = new_itr;
+
+               ixgbevf_write_eitr(q_vector);
        }
 }
 
 {
        struct ixgbevf_adapter *adapter = data;
        struct ixgbe_hw *hw = &adapter->hw;
-       u32 eicr;
        u32 msg;
        bool got_ack = false;
 
-       eicr = IXGBE_READ_REG(hw, IXGBE_VTEICS);
-       IXGBE_WRITE_REG(hw, IXGBE_VTEICR, eicr);
-
        if (!hw->mbx.ops.check_for_ack(hw))
                got_ack = true;
 
        if (got_ack)
                hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK;
 
+       IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, adapter->eims_other);
+
        return IRQ_HANDLED;
 }
 
 static irqreturn_t ixgbevf_msix_clean_rings(int irq, void *data)
 {
        struct ixgbevf_q_vector *q_vector = data;
-       struct ixgbevf_adapter  *adapter = q_vector->adapter;
-       struct ixgbe_hw *hw = &adapter->hw;
 
-       /* disable interrupts on this vector only */
-       IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, 1 << q_vector->v_idx);
+       /* EIAM disabled interrupts (on this vector) for us */
        if (q_vector->rx.ring || q_vector->tx.ring)
                napi_schedule(&q_vector->napi);
 
                q_vector->tx.ring = NULL;
                q_vector->rx.count = 0;
                q_vector->tx.count = 0;
-               q_vector->eitr = adapter->eitr_param;
        }
 }
 
  **/
 static inline void ixgbevf_irq_disable(struct ixgbevf_adapter *adapter)
 {
-       int i;
        struct ixgbe_hw *hw = &adapter->hw;
+       int i;
 
+       IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, 0);
        IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, ~0);
+       IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, 0);
 
        IXGBE_WRITE_FLUSH(hw);
 
  * ixgbevf_irq_enable - Enable default interrupt generation settings
  * @adapter: board private structure
  **/
-static inline void ixgbevf_irq_enable(struct ixgbevf_adapter *adapter,
-                                     bool queues, bool flush)
+static inline void ixgbevf_irq_enable(struct ixgbevf_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       u32 mask;
-       u64 qmask;
-
-       mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
-       qmask = ~0;
-
-       IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
-
-       if (queues)
-               ixgbevf_irq_enable_queues(adapter, qmask);
 
-       if (flush)
-               IXGBE_WRITE_FLUSH(hw);
+       IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, adapter->eims_enable_mask);
+       IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, adapter->eims_enable_mask);
+       IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, adapter->eims_enable_mask);
 }
 
 /**
        /* clear any pending interrupts, may auto mask */
        IXGBE_READ_REG(hw, IXGBE_VTEICR);
 
-       ixgbevf_irq_enable(adapter, true, true);
+       ixgbevf_irq_enable(adapter);
 }
 
 /**
                        goto err_out;
                q_vector->adapter = adapter;
                q_vector->v_idx = q_idx;
-               q_vector->eitr = adapter->eitr_param;
                netif_napi_add(adapter->netdev, &q_vector->napi,
                               ixgbevf_poll, 64);
                adapter->q_vector[q_idx] = q_vector;
        }
 
        /* Enable dynamic interrupt throttling rates */
-       adapter->eitr_param = 20000;
-       adapter->itr_setting = 1;
+       adapter->rx_itr_setting = 1;
+       adapter->tx_itr_setting = 1;
 
        /* set default ring sizes */
        adapter->tx_ring_count = IXGBEVF_DEFAULT_TXD;
 {
        struct ixgbevf_adapter *adapter = (struct ixgbevf_adapter *)data;
        struct ixgbe_hw *hw = &adapter->hw;
-       u64 eics = 0;
+       u32 eics = 0;
        int i;
 
        /*
        for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
                struct ixgbevf_q_vector *qv = adapter->q_vector[i];
                if (qv->rx.ring || qv->tx.ring)
-                       eics |= (1 << i);
+                       eics |= 1 << i;
        }
 
-       IXGBE_WRITE_REG(hw, IXGBE_VTEICS, (u32)eics);
+       IXGBE_WRITE_REG(hw, IXGBE_VTEICS, eics);
 
 watchdog_short_circuit:
        schedule_work(&adapter->watchdog_task);
        if (err)
                goto err_req_irq;
 
-       ixgbevf_irq_enable(adapter, true, true);
+       ixgbevf_irq_enable(adapter);
 
        return 0;