remove extra parentheses in return statement
[dpdk.git] / drivers / net / e1000 / igb_ethdev.c
index cd7f7c1..4ed5e95 100644 (file)
 #define IGB_8_BIT_MASK   UINT8_MAX
 
 /* Additional timesync values. */
-#define E1000_ETQF_FILTER_1588 3
-#define E1000_TIMINCA_INCVALUE 16000000
-#define E1000_TIMINCA_INIT     ((0x02 << E1000_TIMINCA_16NS_SHIFT) \
-                               | E1000_TIMINCA_INCVALUE)
+#define E1000_CYCLECOUNTER_MASK      0xffffffffffffffffULL
+#define E1000_ETQF_FILTER_1588       3
+#define IGB_82576_TSYNC_SHIFT        16
+#define E1000_INCPERIOD_82576        (1 << E1000_TIMINCA_16NS_SHIFT)
+#define E1000_INCVALUE_82576         (16 << IGB_82576_TSYNC_SHIFT)
 #define E1000_TSAUXC_DISABLE_SYSTIME 0x80000000
 
 static int  eth_igb_configure(struct rte_eth_dev *dev);
@@ -236,6 +237,11 @@ static int igb_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
                                          uint32_t flags);
 static int igb_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
                                          struct timespec *timestamp);
+static int igb_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta);
+static int igb_timesync_read_time(struct rte_eth_dev *dev,
+                                 struct timespec *timestamp);
+static int igb_timesync_write_time(struct rte_eth_dev *dev,
+                                  const struct timespec *timestamp);
 static int eth_igb_rx_queue_intr_enable(struct rte_eth_dev *dev,
                                        uint16_t queue_id);
 static int eth_igb_rx_queue_intr_disable(struct rte_eth_dev *dev,
@@ -349,6 +355,9 @@ static const struct eth_dev_ops eth_igb_ops = {
        .get_eeprom_length    = eth_igb_get_eeprom_length,
        .get_eeprom           = eth_igb_get_eeprom,
        .set_eeprom           = eth_igb_set_eeprom,
+       .timesync_adjust_time = igb_timesync_adjust_time,
+       .timesync_read_time   = igb_timesync_read_time,
+       .timesync_write_time  = igb_timesync_write_time,
 };
 
 /*
@@ -638,8 +647,6 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
 
        pci_dev = eth_dev->pci_dev;
 
-       rte_eth_copy_pci_info(eth_dev, pci_dev);
-
        eth_dev->dev_ops = &eth_igb_ops;
        eth_dev->rx_pkt_burst = &eth_igb_recv_pkts;
        eth_dev->tx_pkt_burst = &eth_igb_xmit_pkts;
@@ -653,6 +660,8 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
                return 0;
        }
 
+       rte_eth_copy_pci_info(eth_dev, pci_dev);
+
        hw->hw_addr= (void *)pci_dev->mem_resource[0].addr;
 
        igb_identify_hardware(eth_dev);
@@ -760,6 +769,13 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
                     eth_dev->data->port_id, pci_dev->id.vendor_id,
                     pci_dev->id.device_id);
 
+       rte_intr_callback_register(&pci_dev->intr_handle,
+                                  eth_igb_interrupt_handler,
+                                  (void *)eth_dev);
+
+       /* enable uio/vfio intr/eventfd mapping */
+       rte_intr_enable(&pci_dev->intr_handle);
+
        /* enable support intr */
        igb_intr_enable(eth_dev);
 
@@ -775,7 +791,7 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev)
 err_late:
        igb_hw_control_release(hw);
 
-       return (error);
+       return error;
 }
 
 static int
@@ -830,6 +846,7 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev)
        struct e1000_hw *hw =
                E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
        int diag;
+       struct ether_addr *perm_addr = (struct ether_addr *)hw->mac.perm_addr;
 
        PMD_INIT_FUNC_TRACE();
 
@@ -882,6 +899,26 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev)
                return -ENOMEM;
        }
 
+       /* Generate a random MAC address, if none was assigned by PF. */
+       if (is_zero_ether_addr(perm_addr)) {
+               eth_random_addr(perm_addr->addr_bytes);
+               diag = e1000_rar_set(hw, perm_addr->addr_bytes, 0);
+               if (diag) {
+                       rte_free(eth_dev->data->mac_addrs);
+                       eth_dev->data->mac_addrs = NULL;
+                       return diag;
+               }
+               PMD_INIT_LOG(INFO, "\tVF MAC address not assigned by Host PF");
+               PMD_INIT_LOG(INFO, "\tAssign randomly generated MAC address "
+                            "%02x:%02x:%02x:%02x:%02x:%02x",
+                            perm_addr->addr_bytes[0],
+                            perm_addr->addr_bytes[1],
+                            perm_addr->addr_bytes[2],
+                            perm_addr->addr_bytes[3],
+                            perm_addr->addr_bytes[4],
+                            perm_addr->addr_bytes[5]);
+       }
+
        /* Copy the permanent MAC address */
        ether_addr_copy((struct ether_addr *) hw->mac.perm_addr,
                        &eth_dev->data->mac_addrs[0]);
@@ -973,7 +1010,7 @@ rte_igbvf_pmd_init(const char *name __rte_unused, const char *params __rte_unuse
        PMD_INIT_FUNC_TRACE();
 
        rte_eth_driver_register(&rte_igbvf_pmd);
-       return (0);
+       return 0;
 }
 
 static int
@@ -1085,6 +1122,9 @@ eth_igb_start(struct rte_eth_dev *dev)
 
        PMD_INIT_FUNC_TRACE();
 
+       /* disable uio/vfio intr/eventfd mapping */
+       rte_intr_disable(intr_handle);
+
        /* Power up the phy. Needed to make the link go Up */
        e1000_power_up_phy(hw);
 
@@ -1106,7 +1146,7 @@ eth_igb_start(struct rte_eth_dev *dev)
        /* Initialize the hardware */
        if (igb_hardware_init(hw)) {
                PMD_INIT_LOG(ERR, "Unable to initialize the hardware");
-               return (-EIO);
+               return -EIO;
        }
        adapter->stopped = 0;
 
@@ -1122,13 +1162,15 @@ eth_igb_start(struct rte_eth_dev *dev)
        igb_pf_host_configure(dev);
 
        /* check and configure queue intr-vector mapping */
-       if (dev->data->dev_conf.intr_conf.rxq != 0)
+       if ((rte_intr_cap_multiple(intr_handle) ||
+            !RTE_ETH_DEV_SRIOV(dev).active) &&
+           dev->data->dev_conf.intr_conf.rxq != 0) {
                intr_vector = dev->data->nb_rx_queues;
+               if (rte_intr_efd_enable(intr_handle, intr_vector))
+                       return -1;
+       }
 
-       if (rte_intr_efd_enable(intr_handle, intr_vector))
-               return -1;
-
-       if (rte_intr_dp_is_en(intr_handle)) {
+       if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
                intr_handle->intr_vec =
                        rte_zmalloc("intr_vec",
                                    dev->data->nb_rx_queues * sizeof(int), 0);
@@ -1221,20 +1263,22 @@ eth_igb_start(struct rte_eth_dev *dev)
        }
        e1000_setup_link(hw);
 
-       /* check if lsc interrupt feature is enabled */
-       if (dev->data->dev_conf.intr_conf.lsc != 0) {
-               if (rte_intr_allow_others(intr_handle)) {
-                       rte_intr_callback_register(intr_handle,
-                                                  eth_igb_interrupt_handler,
-                                                  (void *)dev);
+       if (rte_intr_allow_others(intr_handle)) {
+               /* check if lsc interrupt is enabled */
+               if (dev->data->dev_conf.intr_conf.lsc != 0)
                        eth_igb_lsc_interrupt_setup(dev);
-               } else
+       } else {
+               rte_intr_callback_unregister(intr_handle,
+                                            eth_igb_interrupt_handler,
+                                            (void *)dev);
+               if (dev->data->dev_conf.intr_conf.lsc != 0)
                        PMD_INIT_LOG(INFO, "lsc won't enable because of"
                                     " no intr multiplex\n");
        }
 
        /* check if rxq interrupt is enabled */
-       if (dev->data->dev_conf.intr_conf.rxq != 0)
+       if (dev->data->dev_conf.intr_conf.rxq != 0 &&
+           rte_intr_dp_is_en(intr_handle))
                eth_igb_rxq_interrupt_setup(dev);
 
        /* enable uio/vfio intr/eventfd mapping */
@@ -1245,14 +1289,14 @@ eth_igb_start(struct rte_eth_dev *dev)
 
        PMD_INIT_LOG(DEBUG, "<<");
 
-       return (0);
+       return 0;
 
 error_invalid_config:
        PMD_INIT_LOG(ERR, "Invalid link_speed/link_duplex (%u/%u) for port %u",
                     dev->data->dev_conf.link_speed,
                     dev->data->dev_conf.link_duplex, dev->data->port_id);
        igb_dev_clear_queues(dev);
-       return (-EINVAL);
+       return -EINVAL;
 }
 
 /*********************************************************************
@@ -1327,6 +1371,12 @@ eth_igb_stop(struct rte_eth_dev *dev)
        }
        filter_info->twotuple_mask = 0;
 
+       if (!rte_intr_allow_others(intr_handle))
+               /* resume to the default handler */
+               rte_intr_callback_register(intr_handle,
+                                          eth_igb_interrupt_handler,
+                                          (void *)dev);
+
        /* Clean datapath event and queue/vec mapping */
        rte_intr_efd_disable(intr_handle);
        if (intr_handle->intr_vec != NULL) {
@@ -1439,13 +1489,13 @@ igb_hardware_init(struct e1000_hw *hw)
 
        diag = e1000_init_hw(hw);
        if (diag < 0)
-               return (diag);
+               return diag;
 
        E1000_WRITE_REG(hw, E1000_VET, ETHER_TYPE_VLAN << 16 | ETHER_TYPE_VLAN);
        e1000_get_phy_info(hw);
        e1000_check_for_link(hw);
 
-       return (0);
+       return 0;
 }
 
 /* This function is based on igb_update_stats_counters() in igb/if_igb.c */
@@ -1454,6 +1504,13 @@ igb_read_stats_registers(struct e1000_hw *hw, struct e1000_hw_stats *stats)
 {
        int pause_frames;
 
+       uint64_t old_gprc  = stats->gprc;
+       uint64_t old_gptc  = stats->gptc;
+       uint64_t old_tpr   = stats->tpr;
+       uint64_t old_tpt   = stats->tpt;
+       uint64_t old_rpthc = stats->rpthc;
+       uint64_t old_hgptc = stats->hgptc;
+
        if(hw->phy.media_type == e1000_media_type_copper ||
            (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
                stats->symerrs +=
@@ -1495,10 +1552,13 @@ igb_read_stats_registers(struct e1000_hw *hw, struct e1000_hw_stats *stats)
        /* For the 64-bit byte counters the low dword must be read first. */
        /* Both registers clear on the read of the high dword */
 
+       /* Workaround CRC bytes included in size, take away 4 bytes/packet */
        stats->gorc += E1000_READ_REG(hw, E1000_GORCL);
        stats->gorc += ((uint64_t)E1000_READ_REG(hw, E1000_GORCH) << 32);
+       stats->gorc -= (stats->gprc - old_gprc) * ETHER_CRC_LEN;
        stats->gotc += E1000_READ_REG(hw, E1000_GOTCL);
        stats->gotc += ((uint64_t)E1000_READ_REG(hw, E1000_GOTCH) << 32);
+       stats->gotc -= (stats->gptc - old_gptc) * ETHER_CRC_LEN;
 
        stats->rnbc += E1000_READ_REG(hw, E1000_RNBC);
        stats->ruc += E1000_READ_REG(hw, E1000_RUC);
@@ -1506,13 +1566,16 @@ igb_read_stats_registers(struct e1000_hw *hw, struct e1000_hw_stats *stats)
        stats->roc += E1000_READ_REG(hw, E1000_ROC);
        stats->rjc += E1000_READ_REG(hw, E1000_RJC);
 
+       stats->tpr += E1000_READ_REG(hw, E1000_TPR);
+       stats->tpt += E1000_READ_REG(hw, E1000_TPT);
+
        stats->tor += E1000_READ_REG(hw, E1000_TORL);
        stats->tor += ((uint64_t)E1000_READ_REG(hw, E1000_TORH) << 32);
+       stats->tor -= (stats->tpr - old_tpr) * ETHER_CRC_LEN;
        stats->tot += E1000_READ_REG(hw, E1000_TOTL);
        stats->tot += ((uint64_t)E1000_READ_REG(hw, E1000_TOTH) << 32);
+       stats->tot -= (stats->tpt - old_tpt) * ETHER_CRC_LEN;
 
-       stats->tpr += E1000_READ_REG(hw, E1000_TPR);
-       stats->tpt += E1000_READ_REG(hw, E1000_TPT);
        stats->ptc64 += E1000_READ_REG(hw, E1000_PTC64);
        stats->ptc127 += E1000_READ_REG(hw, E1000_PTC127);
        stats->ptc255 += E1000_READ_REG(hw, E1000_PTC255);
@@ -1545,8 +1608,10 @@ igb_read_stats_registers(struct e1000_hw *hw, struct e1000_hw_stats *stats)
        stats->htcbdpc += E1000_READ_REG(hw, E1000_HTCBDPC);
        stats->hgorc += E1000_READ_REG(hw, E1000_HGORCL);
        stats->hgorc += ((uint64_t)E1000_READ_REG(hw, E1000_HGORCH) << 32);
+       stats->hgorc -= (stats->rpthc - old_rpthc) * ETHER_CRC_LEN;
        stats->hgotc += E1000_READ_REG(hw, E1000_HGOTCL);
        stats->hgotc += ((uint64_t)E1000_READ_REG(hw, E1000_HGOTCH) << 32);
+       stats->hgotc -= (stats->hgptc - old_hgptc) * ETHER_CRC_LEN;
        stats->lenerrs += E1000_READ_REG(hw, E1000_LENERRS);
        stats->scvpc += E1000_READ_REG(hw, E1000_SCVPC);
        stats->hrmpc += E1000_READ_REG(hw, E1000_HRMPC);
@@ -1572,23 +1637,15 @@ eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
                return;
 
        /* Rx Errors */
-       rte_stats->ibadcrc = stats->crcerrs;
-       rte_stats->ibadlen = stats->rlec + stats->ruc + stats->roc;
        rte_stats->imissed = stats->mpc;
-       rte_stats->ierrors = rte_stats->ibadcrc +
-                            rte_stats->ibadlen +
+       rte_stats->ierrors = stats->crcerrs +
+                            stats->rlec + stats->ruc + stats->roc +
                             rte_stats->imissed +
                             stats->rxerrc + stats->algnerrc + stats->cexterr;
 
        /* Tx Errors */
        rte_stats->oerrors = stats->ecol + stats->latecol;
 
-       /* XON/XOFF pause frames */
-       rte_stats->tx_pause_xon  = stats->xontxc;
-       rte_stats->rx_pause_xon  = stats->xonrxc;
-       rte_stats->tx_pause_xoff = stats->xofftxc;
-       rte_stats->rx_pause_xoff = stats->xoffrxc;
-
        rte_stats->ipackets = stats->gprc;
        rte_stats->opackets = stats->gptc;
        rte_stats->ibytes   = stats->gorc;
@@ -2453,7 +2510,7 @@ eth_igb_led_on(struct rte_eth_dev *dev)
        struct e1000_hw *hw;
 
        hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       return (e1000_led_on(hw) == E1000_SUCCESS ? 0 : -ENOTSUP);
+       return e1000_led_on(hw) == E1000_SUCCESS ? 0 : -ENOTSUP;
 }
 
 static int
@@ -2462,7 +2519,7 @@ eth_igb_led_off(struct rte_eth_dev *dev)
        struct e1000_hw *hw;
 
        hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       return (e1000_led_off(hw) == E1000_SUCCESS ? 0 : -ENOTSUP);
+       return e1000_led_off(hw) == E1000_SUCCESS ? 0 : -ENOTSUP;
 }
 
 static int
@@ -2534,7 +2591,7 @@ eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
            (fc_conf->high_water < fc_conf->low_water)) {
                PMD_INIT_LOG(ERR, "e1000 incorrect high/low water value");
                PMD_INIT_LOG(ERR, "high water must <=  0x%x", max_high_water);
-               return (-EINVAL);
+               return -EINVAL;
        }
 
        hw->fc.requested_mode = rte_fcmode_2_e1000_fcmode[fc_conf->mode];
@@ -2564,7 +2621,7 @@ eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
        }
 
        PMD_INIT_LOG(ERR, "e1000_setup_link_generic = 0x%x", err);
-       return (-EIO);
+       return -EIO;
 }
 
 #define E1000_RAH_POOLSEL_SHIFT      (18)
@@ -2776,6 +2833,7 @@ static int igbvf_set_vfta(struct e1000_hw *hw, uint16_t vid, bool on)
 {
        struct e1000_mbx_info *mbx = &hw->mbx;
        uint32_t msgbuf[2];
+       s32 err;
 
        /* After set vlan, vlan strip will also be enabled in igb driver*/
        msgbuf[0] = E1000_VF_SET_VLAN;
@@ -2784,7 +2842,20 @@ static int igbvf_set_vfta(struct e1000_hw *hw, uint16_t vid, bool on)
        if (on)
                msgbuf[0] |= E1000_VF_SET_VLAN_ADD;
 
-       return (mbx->ops.write_posted(hw, msgbuf, 2, 0));
+       err = mbx->ops.write_posted(hw, msgbuf, 2, 0);
+       if (err)
+               goto mbx_err;
+
+       err = mbx->ops.read_posted(hw, msgbuf, 2, 0);
+       if (err)
+               goto mbx_err;
+
+       msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS;
+       if (msgbuf[0] == (E1000_VF_SET_VLAN | E1000_VT_MSGTYPE_NACK))
+               err = -EINVAL;
+
+mbx_err:
+       return err;
 }
 
 static void igbvf_set_vfta_all(struct rte_eth_dev *dev, bool on)
@@ -4165,6 +4236,209 @@ eth_igb_set_mc_addr_list(struct rte_eth_dev *dev,
        return 0;
 }
 
+static uint64_t
+igb_read_systime_cyclecounter(struct rte_eth_dev *dev)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint64_t systime_cycles;
+
+       switch (hw->mac.type) {
+       case e1000_i210:
+       case e1000_i211:
+               /*
+                * Need to read System Time Residue Register to be able
+                * to read the other two registers.
+                */
+               E1000_READ_REG(hw, E1000_SYSTIMR);
+               /* SYSTIMEL stores ns and SYSTIMEH stores seconds. */
+               systime_cycles = (uint64_t)E1000_READ_REG(hw, E1000_SYSTIML);
+               systime_cycles += (uint64_t)E1000_READ_REG(hw, E1000_SYSTIMH)
+                               * NSEC_PER_SEC;
+               break;
+       case e1000_82580:
+       case e1000_i350:
+       case e1000_i354:
+               /*
+                * Need to read System Time Residue Register to be able
+                * to read the other two registers.
+                */
+               E1000_READ_REG(hw, E1000_SYSTIMR);
+               systime_cycles = (uint64_t)E1000_READ_REG(hw, E1000_SYSTIML);
+               /* Only the 8 LSB are valid. */
+               systime_cycles |= (uint64_t)(E1000_READ_REG(hw, E1000_SYSTIMH)
+                               & 0xff) << 32;
+               break;
+       default:
+               systime_cycles = (uint64_t)E1000_READ_REG(hw, E1000_SYSTIML);
+               systime_cycles |= (uint64_t)E1000_READ_REG(hw, E1000_SYSTIMH)
+                               << 32;
+               break;
+       }
+
+       return systime_cycles;
+}
+
+static uint64_t
+igb_read_rx_tstamp_cyclecounter(struct rte_eth_dev *dev)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint64_t rx_tstamp_cycles;
+
+       switch (hw->mac.type) {
+       case e1000_i210:
+       case e1000_i211:
+               /* RXSTMPL stores ns and RXSTMPH stores seconds. */
+               rx_tstamp_cycles = (uint64_t)E1000_READ_REG(hw, E1000_RXSTMPL);
+               rx_tstamp_cycles += (uint64_t)E1000_READ_REG(hw, E1000_RXSTMPH)
+                               * NSEC_PER_SEC;
+               break;
+       case e1000_82580:
+       case e1000_i350:
+       case e1000_i354:
+               rx_tstamp_cycles = (uint64_t)E1000_READ_REG(hw, E1000_RXSTMPL);
+               /* Only the 8 LSB are valid. */
+               rx_tstamp_cycles |= (uint64_t)(E1000_READ_REG(hw, E1000_RXSTMPH)
+                               & 0xff) << 32;
+               break;
+       default:
+               rx_tstamp_cycles = (uint64_t)E1000_READ_REG(hw, E1000_RXSTMPL);
+               rx_tstamp_cycles |= (uint64_t)E1000_READ_REG(hw, E1000_RXSTMPH)
+                               << 32;
+               break;
+       }
+
+       return rx_tstamp_cycles;
+}
+
+static uint64_t
+igb_read_tx_tstamp_cyclecounter(struct rte_eth_dev *dev)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint64_t tx_tstamp_cycles;
+
+       switch (hw->mac.type) {
+       case e1000_i210:
+       case e1000_i211:
+               /* RXSTMPL stores ns and RXSTMPH stores seconds. */
+               tx_tstamp_cycles = (uint64_t)E1000_READ_REG(hw, E1000_TXSTMPL);
+               tx_tstamp_cycles += (uint64_t)E1000_READ_REG(hw, E1000_TXSTMPH)
+                               * NSEC_PER_SEC;
+               break;
+       case e1000_82580:
+       case e1000_i350:
+       case e1000_i354:
+               tx_tstamp_cycles = (uint64_t)E1000_READ_REG(hw, E1000_TXSTMPL);
+               /* Only the 8 LSB are valid. */
+               tx_tstamp_cycles |= (uint64_t)(E1000_READ_REG(hw, E1000_TXSTMPH)
+                               & 0xff) << 32;
+               break;
+       default:
+               tx_tstamp_cycles = (uint64_t)E1000_READ_REG(hw, E1000_TXSTMPL);
+               tx_tstamp_cycles |= (uint64_t)E1000_READ_REG(hw, E1000_TXSTMPH)
+                               << 32;
+               break;
+       }
+
+       return tx_tstamp_cycles;
+}
+
+static void
+igb_start_timecounters(struct rte_eth_dev *dev)
+{
+       struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct e1000_adapter *adapter =
+               (struct e1000_adapter *)dev->data->dev_private;
+       uint32_t incval = 1;
+       uint32_t shift = 0;
+       uint64_t mask = E1000_CYCLECOUNTER_MASK;
+
+       switch (hw->mac.type) {
+       case e1000_82580:
+       case e1000_i350:
+       case e1000_i354:
+               /* 32 LSB bits + 8 MSB bits = 40 bits */
+               mask = (1ULL << 40) - 1;
+               /* fall-through */
+       case e1000_i210:
+       case e1000_i211:
+               /*
+                * Start incrementing the register
+                * used to timestamp PTP packets.
+                */
+               E1000_WRITE_REG(hw, E1000_TIMINCA, incval);
+               break;
+       case e1000_82576:
+               incval = E1000_INCVALUE_82576;
+               shift = IGB_82576_TSYNC_SHIFT;
+               E1000_WRITE_REG(hw, E1000_TIMINCA,
+                               E1000_INCPERIOD_82576 | incval);
+               break;
+       default:
+               /* Not supported */
+               return;
+       }
+
+       memset(&adapter->systime_tc, 0, sizeof(struct rte_timecounter));
+       memset(&adapter->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
+       memset(&adapter->tx_tstamp_tc, 0, sizeof(struct rte_timecounter));
+
+       adapter->systime_tc.cc_mask = mask;
+       adapter->systime_tc.cc_shift = shift;
+       adapter->systime_tc.nsec_mask = (1ULL << shift) - 1;
+
+       adapter->rx_tstamp_tc.cc_mask = mask;
+       adapter->rx_tstamp_tc.cc_shift = shift;
+       adapter->rx_tstamp_tc.nsec_mask = (1ULL << shift) - 1;
+
+       adapter->tx_tstamp_tc.cc_mask = mask;
+       adapter->tx_tstamp_tc.cc_shift = shift;
+       adapter->tx_tstamp_tc.nsec_mask = (1ULL << shift) - 1;
+}
+
+static int
+igb_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta)
+{
+       struct e1000_adapter *adapter =
+                       (struct e1000_adapter *)dev->data->dev_private;
+
+       adapter->systime_tc.nsec += delta;
+       adapter->rx_tstamp_tc.nsec += delta;
+       adapter->tx_tstamp_tc.nsec += delta;
+
+       return 0;
+}
+
+static int
+igb_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts)
+{
+       uint64_t ns;
+       struct e1000_adapter *adapter =
+                       (struct e1000_adapter *)dev->data->dev_private;
+
+       ns = rte_timespec_to_ns(ts);
+
+       /* Set the timecounters to a new value. */
+       adapter->systime_tc.nsec = ns;
+       adapter->rx_tstamp_tc.nsec = ns;
+       adapter->tx_tstamp_tc.nsec = ns;
+
+       return 0;
+}
+
+static int
+igb_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
+{
+       uint64_t ns, systime_cycles;
+       struct e1000_adapter *adapter =
+                       (struct e1000_adapter *)dev->data->dev_private;
+
+       systime_cycles = igb_read_systime_cyclecounter(dev);
+       ns = rte_timecounter_update(&adapter->systime_tc, systime_cycles);
+       *ts = rte_ns_to_timespec(ns);
+
+       return 0;
+}
+
 static int
 igb_timesync_enable(struct rte_eth_dev *dev)
 {
@@ -4172,13 +4446,32 @@ igb_timesync_enable(struct rte_eth_dev *dev)
        uint32_t tsync_ctl;
        uint32_t tsauxc;
 
+       /* Stop the timesync system time. */
+       E1000_WRITE_REG(hw, E1000_TIMINCA, 0x0);
+       /* Reset the timesync system time value. */
+       switch (hw->mac.type) {
+       case e1000_82580:
+       case e1000_i350:
+       case e1000_i354:
+       case e1000_i210:
+       case e1000_i211:
+               E1000_WRITE_REG(hw, E1000_SYSTIMR, 0x0);
+               /* fall-through */
+       case e1000_82576:
+               E1000_WRITE_REG(hw, E1000_SYSTIML, 0x0);
+               E1000_WRITE_REG(hw, E1000_SYSTIMH, 0x0);
+               break;
+       default:
+               /* Not supported. */
+               return -ENOTSUP;
+       }
+
        /* Enable system time for it isn't on by default. */
        tsauxc = E1000_READ_REG(hw, E1000_TSAUXC);
        tsauxc &= ~E1000_TSAUXC_DISABLE_SYSTIME;
        E1000_WRITE_REG(hw, E1000_TSAUXC, tsauxc);
 
-       /* Start incrementing the register used to timestamp PTP packets. */
-       E1000_WRITE_REG(hw, E1000_TIMINCA, E1000_TIMINCA_INIT);
+       igb_start_timecounters(dev);
 
        /* Enable L2 filtering of IEEE1588/802.1AS Ethernet frame types. */
        E1000_WRITE_REG(hw, E1000_ETQF(E1000_ETQF_FILTER_1588),
@@ -4230,19 +4523,19 @@ igb_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
                               uint32_t flags __rte_unused)
 {
        struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct e1000_adapter *adapter =
+                       (struct e1000_adapter *)dev->data->dev_private;
        uint32_t tsync_rxctl;
-       uint32_t rx_stmpl;
-       uint32_t rx_stmph;
+       uint64_t rx_tstamp_cycles;
+       uint64_t ns;
 
        tsync_rxctl = E1000_READ_REG(hw, E1000_TSYNCRXCTL);
        if ((tsync_rxctl & E1000_TSYNCRXCTL_VALID) == 0)
                return -EINVAL;
 
-       rx_stmpl = E1000_READ_REG(hw, E1000_RXSTMPL);
-       rx_stmph = E1000_READ_REG(hw, E1000_RXSTMPH);
-
-       timestamp->tv_sec = (uint64_t)(((uint64_t)rx_stmph << 32) | rx_stmpl);
-       timestamp->tv_nsec = 0;
+       rx_tstamp_cycles = igb_read_rx_tstamp_cyclecounter(dev);
+       ns = rte_timecounter_update(&adapter->rx_tstamp_tc, rx_tstamp_cycles);
+       *timestamp = rte_ns_to_timespec(ns);
 
        return  0;
 }
@@ -4252,19 +4545,19 @@ igb_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
                               struct timespec *timestamp)
 {
        struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct e1000_adapter *adapter =
+                       (struct e1000_adapter *)dev->data->dev_private;
        uint32_t tsync_txctl;
-       uint32_t tx_stmpl;
-       uint32_t tx_stmph;
+       uint64_t tx_tstamp_cycles;
+       uint64_t ns;
 
        tsync_txctl = E1000_READ_REG(hw, E1000_TSYNCTXCTL);
        if ((tsync_txctl & E1000_TSYNCTXCTL_VALID) == 0)
                return -EINVAL;
 
-       tx_stmpl = E1000_READ_REG(hw, E1000_TXSTMPL);
-       tx_stmph = E1000_READ_REG(hw, E1000_TXSTMPH);
-
-       timestamp->tv_sec = (uint64_t)(((uint64_t)tx_stmph << 32) | tx_stmpl);
-       timestamp->tv_nsec = 0;
+       tx_tstamp_cycles = igb_read_tx_tstamp_cyclecounter(dev);
+       ns = rte_timecounter_update(&adapter->tx_tstamp_tc, tx_tstamp_cycles);
+       *timestamp = rte_ns_to_timespec(ns);
 
        return  0;
 }
@@ -4495,7 +4788,10 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
        uint32_t tmpval, regval, intr_mask;
        struct e1000_hw *hw =
                E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       uint32_t vec = 0;
+       uint32_t vec = E1000_MISC_VEC_ID;
+       uint32_t base = E1000_MISC_VEC_ID;
+       uint32_t misc_shift = 0;
+
        struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
 
        /* won't configure msix register if no mapping is done
@@ -4504,6 +4800,11 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
        if (!rte_intr_dp_is_en(intr_handle))
                return;
 
+       if (rte_intr_allow_others(intr_handle)) {
+               vec = base = E1000_RX_VEC_START;
+               misc_shift = 1;
+       }
+
        /* set interrupt vector for other causes */
        if (hw->mac.type == e1000_82575) {
                tmpval = E1000_READ_REG(hw, E1000_CTRL_EXT);
@@ -4532,8 +4833,8 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
                E1000_WRITE_REG(hw, E1000_GPIE, E1000_GPIE_MSIX_MODE |
                                        E1000_GPIE_PBA | E1000_GPIE_EIAME |
                                        E1000_GPIE_NSICR);
-
-               intr_mask = (1 << intr_handle->max_intr) - 1;
+               intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) <<
+                       misc_shift;
                regval = E1000_READ_REG(hw, E1000_EIAC);
                E1000_WRITE_REG(hw, E1000_EIAC, regval | intr_mask);
 
@@ -4547,14 +4848,15 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
        /* use EIAM to auto-mask when MSI-X interrupt
         * is asserted, this saves a register write for every interrupt
         */
-       intr_mask = (1 << intr_handle->nb_efd) - 1;
+       intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) <<
+               misc_shift;
        regval = E1000_READ_REG(hw, E1000_EIAM);
        E1000_WRITE_REG(hw, E1000_EIAM, regval | intr_mask);
 
        for (queue_id = 0; queue_id < dev->data->nb_rx_queues; queue_id++) {
                eth_igb_assign_msix_vector(hw, 0, queue_id, vec);
                intr_handle->intr_vec[queue_id] = vec;
-               if (vec < intr_handle->nb_efd - 1)
+               if (vec < base + intr_handle->nb_efd - 1)
                        vec++;
        }