X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fe1000%2Figb_ethdev.c;h=045fc6343f181902c2f83b5c6698efbd7224137c;hb=09419f235e099ecb265a590778fe64a685a2a241;hp=2cb115cd06d1522dd4aff9e81a0612c123212574;hpb=fe685de2b1b6b922cf9ecc107534bafa1741184b;p=dpdk.git diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c index 2cb115cd06..045fc6343f 100644 --- a/drivers/net/e1000/igb_ethdev.c +++ b/drivers/net/e1000/igb_ethdev.c @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,13 +61,14 @@ * Default values for port configuration */ #define IGB_DEFAULT_RX_FREE_THRESH 32 -#define IGB_DEFAULT_RX_PTHRESH 8 + +#define IGB_DEFAULT_RX_PTHRESH ((hw->mac.type == e1000_i354) ? 12 : 8) #define IGB_DEFAULT_RX_HTHRESH 8 -#define IGB_DEFAULT_RX_WTHRESH 0 +#define IGB_DEFAULT_RX_WTHRESH ((hw->mac.type == e1000_82576) ? 1 : 4) -#define IGB_DEFAULT_TX_PTHRESH 32 -#define IGB_DEFAULT_TX_HTHRESH 0 -#define IGB_DEFAULT_TX_WTHRESH 0 +#define IGB_DEFAULT_TX_PTHRESH ((hw->mac.type == e1000_i354) ? 20 : 8) +#define IGB_DEFAULT_TX_HTHRESH 1 +#define IGB_DEFAULT_TX_WTHRESH ((hw->mac.type == e1000_82576) ? 1 : 16) #define IGB_HKEY_MAX_INDEX 10 @@ -78,10 +79,11 @@ #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); @@ -102,6 +104,7 @@ static void eth_igb_stats_reset(struct rte_eth_dev *dev); static void eth_igb_xstats_reset(struct rte_eth_dev *dev); static void eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); +static const uint32_t *eth_igb_supported_ptypes_get(struct rte_eth_dev *dev); static void eth_igbvf_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static int eth_igb_flow_ctrl_get(struct rte_eth_dev *dev, @@ -124,7 +127,9 @@ static int eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); -static void eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid_id); +static int eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, + enum rte_vlan_type vlan_type, + uint16_t tpid_id); static void eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask); static void igb_vlan_hw_filter_enable(struct rte_eth_dev *dev); @@ -151,6 +156,10 @@ static int igbvf_dev_configure(struct rte_eth_dev *dev); static int igbvf_dev_start(struct rte_eth_dev *dev); static void igbvf_dev_stop(struct rte_eth_dev *dev); static void igbvf_dev_close(struct rte_eth_dev *dev); +static void igbvf_promiscuous_enable(struct rte_eth_dev *dev); +static void igbvf_promiscuous_disable(struct rte_eth_dev *dev); +static void igbvf_allmulticast_enable(struct rte_eth_dev *dev); +static void igbvf_allmulticast_disable(struct rte_eth_dev *dev); static int eth_igbvf_link_update(struct e1000_hw *hw); static void eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats); @@ -236,6 +245,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, @@ -313,6 +327,7 @@ static const struct eth_dev_ops eth_igb_ops = { .stats_reset = eth_igb_stats_reset, .xstats_reset = eth_igb_xstats_reset, .dev_infos_get = eth_igb_infos_get, + .dev_supported_ptypes_get = eth_igb_supported_ptypes_get, .mtu_set = eth_igb_mtu_set, .vlan_filter_set = eth_igb_vlan_filter_set, .vlan_tpid_set = eth_igb_vlan_tpid_set, @@ -349,6 +364,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, }; /* @@ -360,6 +378,10 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = { .dev_start = igbvf_dev_start, .dev_stop = igbvf_dev_stop, .dev_close = igbvf_dev_close, + .promiscuous_enable = igbvf_promiscuous_enable, + .promiscuous_disable = igbvf_promiscuous_disable, + .allmulticast_enable = igbvf_allmulticast_enable, + .allmulticast_disable = igbvf_allmulticast_disable, .link_update = eth_igb_link_update, .stats_get = eth_igbvf_stats_get, .xstats_get = eth_igbvf_xstats_get, @@ -367,6 +389,7 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = { .xstats_reset = eth_igbvf_stats_reset, .vlan_filter_set = igbvf_vlan_filter_set, .dev_infos_get = eth_igbvf_infos_get, + .dev_supported_ptypes_get = eth_igb_supported_ptypes_get, .rx_queue_setup = eth_igb_rx_queue_setup, .rx_queue_release = eth_igb_rx_queue_release, .tx_queue_setup = eth_igb_tx_queue_setup, @@ -638,8 +661,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 = ð_igb_ops; eth_dev->rx_pkt_burst = ð_igb_recv_pkts; eth_dev->tx_pkt_burst = ð_igb_xmit_pkts; @@ -653,6 +674,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); @@ -782,7 +805,7 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev) err_late: igb_hw_control_release(hw); - return (error); + return error; } static int @@ -837,6 +860,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(); @@ -889,6 +913,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, ð_dev->data->mac_addrs[0]); @@ -980,7 +1024,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 @@ -1092,6 +1136,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); @@ -1113,7 +1160,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; @@ -1256,14 +1303,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; } /********************************************************************* @@ -1456,13 +1503,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 */ @@ -1471,6 +1518,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 += @@ -1512,10 +1566,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); @@ -1523,13 +1580,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); @@ -1562,8 +1622,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); @@ -1589,23 +1651,14 @@ 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->imissed + + rte_stats->ierrors = stats->crcerrs + + stats->rlec + stats->ruc + stats->roc + 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; @@ -1870,6 +1923,33 @@ eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) dev_info->tx_desc_lim = tx_desc_lim; } +static const uint32_t * +eth_igb_supported_ptypes_get(struct rte_eth_dev *dev) +{ + static const uint32_t ptypes[] = { + /* refers to igb_rxd_pkt_info_to_pkt_type() */ + RTE_PTYPE_L2_ETHER, + RTE_PTYPE_L3_IPV4, + RTE_PTYPE_L3_IPV4_EXT, + RTE_PTYPE_L3_IPV6, + RTE_PTYPE_L3_IPV6_EXT, + RTE_PTYPE_L4_TCP, + RTE_PTYPE_L4_UDP, + RTE_PTYPE_L4_SCTP, + RTE_PTYPE_TUNNEL_IP, + RTE_PTYPE_INNER_L3_IPV6, + RTE_PTYPE_INNER_L3_IPV6_EXT, + RTE_PTYPE_INNER_L4_TCP, + RTE_PTYPE_INNER_L4_UDP, + RTE_PTYPE_UNKNOWN + }; + + if (dev->rx_pkt_burst == eth_igb_recv_pkts || + dev->rx_pkt_burst == eth_igb_recv_scattered_pkts) + return ptypes; + return NULL; +} + static void eth_igbvf_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { @@ -1979,11 +2059,11 @@ eth_igb_link_update(struct rte_eth_dev *dev, int wait_to_complete) if (link_check) { hw->mac.ops.get_link_up_info(hw, &link.link_speed, &link.link_duplex); - link.link_status = 1; + link.link_status = ETH_LINK_UP; } else if (!link_check) { link.link_speed = 0; link.link_duplex = 0; - link.link_status = 0; + link.link_status = ETH_LINK_DOWN; } rte_igb_dev_atomic_write_link_status(dev, &link); @@ -2144,15 +2224,28 @@ eth_igb_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) return 0; } -static void -eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid) +static int +eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, + enum rte_vlan_type vlan_type, + uint16_t tpid) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); - uint32_t reg = ETHER_TYPE_VLAN ; + uint32_t reg = ETHER_TYPE_VLAN; + int ret = 0; + + switch (vlan_type) { + case ETH_VLAN_TYPE_INNER: + reg |= (tpid << 16); + E1000_WRITE_REG(hw, E1000_VET, reg); + break; + default: + ret = -EINVAL; + PMD_DRV_LOG(ERR, "Unsupported vlan type %d\n", vlan_type); + break; + } - reg |= (tpid << 16); - E1000_WRITE_REG(hw, E1000_VET, reg); + return ret; } static void @@ -2470,7 +2563,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 @@ -2479,7 +2572,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 @@ -2551,7 +2644,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]; @@ -2581,7 +2674,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) @@ -2779,6 +2872,7 @@ igbvf_dev_close(struct rte_eth_dev *dev) struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_adapter *adapter = E1000_DEV_PRIVATE(dev->data->dev_private); + struct ether_addr addr; PMD_INIT_FUNC_TRACE(); @@ -2787,12 +2881,63 @@ igbvf_dev_close(struct rte_eth_dev *dev) igbvf_dev_stop(dev); adapter->stopped = 1; igb_dev_free_queues(dev); + + /** + * reprogram the RAR with a zero mac address, + * to ensure that the VF traffic goes to the PF + * after stop, close and detach of the VF. + **/ + + memset(&addr, 0, sizeof(addr)); + igbvf_default_mac_addr_set(dev, &addr); +} + +static void +igbvf_promiscuous_enable(struct rte_eth_dev *dev) +{ + struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + /* Set both unicast and multicast promisc */ + e1000_promisc_set_vf(hw, e1000_promisc_enabled); +} + +static void +igbvf_promiscuous_disable(struct rte_eth_dev *dev) +{ + struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + /* If in allmulticast mode leave multicast promisc */ + if (dev->data->all_multicast == 1) + e1000_promisc_set_vf(hw, e1000_promisc_multicast); + else + e1000_promisc_set_vf(hw, e1000_promisc_disabled); +} + +static void +igbvf_allmulticast_enable(struct rte_eth_dev *dev) +{ + struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + /* In promiscuous mode multicast promisc already set */ + if (dev->data->promiscuous == 0) + e1000_promisc_set_vf(hw, e1000_promisc_multicast); +} + +static void +igbvf_allmulticast_disable(struct rte_eth_dev *dev) +{ + struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + /* In promiscuous mode leave multicast promisc enabled */ + if (dev->data->promiscuous == 0) + e1000_promisc_set_vf(hw, e1000_promisc_disabled); } 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; @@ -2801,7 +2946,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) @@ -4182,6 +4340,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) { @@ -4189,13 +4550,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), @@ -4247,19 +4627,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; } @@ -4269,19 +4649,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; }