X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fixgbe%2Fixgbe_ethdev.c;h=f143fb1d8bd57189243989cd83aca86b1ec07c80;hb=0198848a47f5216f3fe43782b90b2e2a4fb6bda4;hp=b7a60b16a7368ea97d1ceb1aee85b929c29e9e5f;hpb=8208e85a2240f252965424253caeb8664c1a7bac;p=dpdk.git diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c index b7a60b16a7..f143fb1d8b 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -68,6 +68,9 @@ #include "ixgbe_ethdev.h" #include "ixgbe_bypass.h" #include "ixgbe_rxtx.h" +#include "base/ixgbe_type.h" +#include "base/ixgbe_phy.h" +#include "ixgbe_regs.h" /* * High threshold controlling when to start sending XOFF frames. Must be at @@ -91,6 +94,7 @@ #define IXGBE_MMW_SIZE_DEFAULT 0x4 #define IXGBE_MMW_SIZE_JUMBO_FRAME 0x14 +#define IXGBE_MAX_RING_DESC 4096 /* replicate define from rxtx */ /* * Default values for RX/TX configuration @@ -118,6 +122,12 @@ #define IXGBE_HKEY_MAX_INDEX 10 +/* Additional timesync values. */ +#define IXGBE_TIMINCA_16NS_SHIFT 24 +#define IXGBE_TIMINCA_INCVALUE 16000000 +#define IXGBE_TIMINCA_INIT ((0x02 << IXGBE_TIMINCA_16NS_SHIFT) \ + | IXGBE_TIMINCA_INCVALUE) + static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev); static int ixgbe_dev_configure(struct rte_eth_dev *dev); static int ixgbe_dev_start(struct rte_eth_dev *dev); @@ -181,6 +191,8 @@ static void ixgbe_dev_interrupt_delayed_handler(void *param); static void ixgbe_add_rar(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t pool); static void ixgbe_remove_rar(struct rte_eth_dev *dev, uint32_t index); +static void ixgbe_set_default_mac_addr(struct rte_eth_dev *dev, + struct ether_addr *mac_addr); static void ixgbe_dcb_init(struct ixgbe_hw *hw,struct ixgbe_dcb_config *dcb_config); /* For Virtual Function support */ @@ -225,6 +237,8 @@ static void ixgbevf_add_mac_addr(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t pool); static void ixgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index); +static void ixgbevf_set_default_mac_addr(struct rte_eth_dev *dev, + struct ether_addr *mac_addr); static int ixgbe_syn_filter_set(struct rte_eth_dev *dev, struct rte_eth_syn_filter *filter, bool add); @@ -263,6 +277,27 @@ static int ixgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *mc_addr_set, uint32_t nb_mc_addr); +static int ixgbe_get_reg_length(struct rte_eth_dev *dev); +static int ixgbe_get_regs(struct rte_eth_dev *dev, + struct rte_dev_reg_info *regs); +static int ixgbe_get_eeprom_length(struct rte_eth_dev *dev); +static int ixgbe_get_eeprom(struct rte_eth_dev *dev, + struct rte_dev_eeprom_info *eeprom); +static int ixgbe_set_eeprom(struct rte_eth_dev *dev, + struct rte_dev_eeprom_info *eeprom); + +static int ixgbevf_get_reg_length(struct rte_eth_dev *dev); +static int ixgbevf_get_regs(struct rte_eth_dev *dev, + struct rte_dev_reg_info *regs); + +static int ixgbe_timesync_enable(struct rte_eth_dev *dev); +static int ixgbe_timesync_disable(struct rte_eth_dev *dev); +static int ixgbe_timesync_read_rx_timestamp(struct rte_eth_dev *dev, + struct timespec *timestamp, + uint32_t flags); +static int ixgbe_timesync_read_tx_timestamp(struct rte_eth_dev *dev, + struct timespec *timestamp); + /* * Define VF Stats MACRO for Non "cleared on read" register */ @@ -361,6 +396,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = { .priority_flow_ctrl_set = ixgbe_priority_flow_ctrl_set, .mac_addr_add = ixgbe_add_rar, .mac_addr_remove = ixgbe_remove_rar, + .mac_addr_set = ixgbe_set_default_mac_addr, .uc_hash_table_set = ixgbe_uc_hash_table_set, .uc_all_hash_table_set = ixgbe_uc_all_hash_table_set, .mirror_rule_set = ixgbe_mirror_rule_set, @@ -388,6 +424,15 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = { .rss_hash_conf_get = ixgbe_dev_rss_hash_conf_get, .filter_ctrl = ixgbe_dev_filter_ctrl, .set_mc_addr_list = ixgbe_dev_set_mc_addr_list, + .timesync_enable = ixgbe_timesync_enable, + .timesync_disable = ixgbe_timesync_disable, + .timesync_read_rx_timestamp = ixgbe_timesync_read_rx_timestamp, + .timesync_read_tx_timestamp = ixgbe_timesync_read_tx_timestamp, + .get_reg_length = ixgbe_get_reg_length, + .get_reg = ixgbe_get_regs, + .get_eeprom_length = ixgbe_get_eeprom_length, + .get_eeprom = ixgbe_get_eeprom, + .set_eeprom = ixgbe_set_eeprom, }; /* @@ -414,6 +459,9 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = { .mac_addr_add = ixgbevf_add_mac_addr, .mac_addr_remove = ixgbevf_remove_mac_addr, .set_mc_addr_list = ixgbe_dev_set_mc_addr_list, + .mac_addr_set = ixgbevf_set_default_mac_addr, + .get_reg_length = ixgbevf_get_reg_length, + .get_reg = ixgbevf_get_regs, }; /** @@ -848,6 +896,9 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev) return -EIO; } + /* Reset the hw statistics */ + ixgbe_dev_stats_reset(eth_dev); + /* disable interrupt */ ixgbe_disable_intr(hw); @@ -1020,6 +1071,9 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev) /* init_mailbox_params */ hw->mbx.ops.init_params(hw); + /* Reset the hw statistics */ + ixgbevf_dev_stats_reset(eth_dev); + /* Disable the interrupts for VF */ ixgbevf_intr_disable(hw); @@ -2552,8 +2606,6 @@ ixgbe_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); - if (fc_conf->autoneg != !hw->fc.disable_fc_autoneg) - return -ENOTSUP; rx_buf_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)); PMD_INIT_LOG(DEBUG, "Rx packet buffer size = 0x%x", rx_buf_size); @@ -2574,6 +2626,7 @@ ixgbe_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) hw->fc.high_water[0] = fc_conf->high_water; hw->fc.low_water[0] = fc_conf->low_water; hw->fc.send_xon = fc_conf->send_xon; + hw->fc.disable_fc_autoneg = !fc_conf->autoneg; err = ixgbe_fc_enable(hw); @@ -2905,6 +2958,14 @@ ixgbe_remove_rar(struct rte_eth_dev *dev, uint32_t index) ixgbe_clear_rar(hw, index); } +static void +ixgbe_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr) +{ + ixgbe_remove_rar(dev, 0); + + ixgbe_add_rar(dev, addr, 0, 0); +} + static int ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) { @@ -3762,6 +3823,14 @@ ixgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index) } } +static void +ixgbevf_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + hw->mac.ops.set_rar(hw, 0, (void *)addr, 0, 0); +} + #define MAC_TYPE_FILTER_SUP(type) do {\ if ((type) != ixgbe_mac_82599EB && (type) != ixgbe_mac_X540 &&\ (type) != ixgbe_mac_X550)\ @@ -4502,8 +4571,8 @@ ixgbe_dev_addr_list_itr(__attribute__((unused)) struct ixgbe_hw *hw, static int ixgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev, - struct ether_addr *mc_addr_set, - uint32_t nb_mc_addr) + struct ether_addr *mc_addr_set, + uint32_t nb_mc_addr) { struct ixgbe_hw *hw; u8 *mc_addr_list; @@ -4514,6 +4583,238 @@ ixgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev, ixgbe_dev_addr_list_itr, TRUE); } +static int +ixgbe_timesync_enable(struct rte_eth_dev *dev) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t tsync_ctl; + uint32_t tsauxc; + + /* Enable system time for platforms where it isn't on by default. */ + tsauxc = IXGBE_READ_REG(hw, IXGBE_TSAUXC); + tsauxc &= ~IXGBE_TSAUXC_DISABLE_SYSTIME; + IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc); + + /* Start incrementing the register used to timestamp PTP packets. */ + IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, IXGBE_TIMINCA_INIT); + + /* Enable L2 filtering of IEEE1588/802.1AS Ethernet frame types. */ + IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588), + (ETHER_TYPE_1588 | + IXGBE_ETQF_FILTER_EN | + IXGBE_ETQF_1588)); + + /* Enable timestamping of received PTP packets. */ + tsync_ctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); + tsync_ctl |= IXGBE_TSYNCRXCTL_ENABLED; + IXGBE_WRITE_REG(hw, IXGBE_TSYNCRXCTL, tsync_ctl); + + /* Enable timestamping of transmitted PTP packets. */ + tsync_ctl = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL); + tsync_ctl |= IXGBE_TSYNCTXCTL_ENABLED; + IXGBE_WRITE_REG(hw, IXGBE_TSYNCTXCTL, tsync_ctl); + + return 0; +} + +static int +ixgbe_timesync_disable(struct rte_eth_dev *dev) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t tsync_ctl; + + /* Disable timestamping of transmitted PTP packets. */ + tsync_ctl = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL); + tsync_ctl &= ~IXGBE_TSYNCTXCTL_ENABLED; + IXGBE_WRITE_REG(hw, IXGBE_TSYNCTXCTL, tsync_ctl); + + /* Disable timestamping of received PTP packets. */ + tsync_ctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); + tsync_ctl &= ~IXGBE_TSYNCRXCTL_ENABLED; + IXGBE_WRITE_REG(hw, IXGBE_TSYNCRXCTL, tsync_ctl); + + /* Disable L2 filtering of IEEE1588/802.1AS Ethernet frame types. */ + IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588), 0); + + /* Stop incrementating the System Time registers. */ + IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, 0); + + return 0; +} + +static int +ixgbe_timesync_read_rx_timestamp(struct rte_eth_dev *dev, + struct timespec *timestamp, + uint32_t flags __rte_unused) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t tsync_rxctl; + uint32_t rx_stmpl; + uint32_t rx_stmph; + + tsync_rxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); + if ((tsync_rxctl & IXGBE_TSYNCRXCTL_VALID) == 0) + return -EINVAL; + + rx_stmpl = IXGBE_READ_REG(hw, IXGBE_RXSTMPL); + rx_stmph = IXGBE_READ_REG(hw, IXGBE_RXSTMPH); + + timestamp->tv_sec = (uint64_t)(((uint64_t)rx_stmph << 32) | rx_stmpl); + timestamp->tv_nsec = 0; + + return 0; +} + +static int +ixgbe_timesync_read_tx_timestamp(struct rte_eth_dev *dev, + struct timespec *timestamp) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t tsync_txctl; + uint32_t tx_stmpl; + uint32_t tx_stmph; + + tsync_txctl = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL); + if ((tsync_txctl & IXGBE_TSYNCTXCTL_VALID) == 0) + return -EINVAL; + + tx_stmpl = IXGBE_READ_REG(hw, IXGBE_TXSTMPL); + tx_stmph = IXGBE_READ_REG(hw, IXGBE_TXSTMPH); + + timestamp->tv_sec = (uint64_t)(((uint64_t)tx_stmph << 32) | tx_stmpl); + timestamp->tv_nsec = 0; + + return 0; +} + +static int +ixgbe_get_reg_length(struct rte_eth_dev *dev) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int count = 0; + int g_ind = 0; + const struct reg_info *reg_group; + const struct reg_info **reg_set = (hw->mac.type == ixgbe_mac_82598EB) ? + ixgbe_regs_mac_82598EB : ixgbe_regs_others; + + while ((reg_group = reg_set[g_ind++])) + count += ixgbe_regs_group_count(reg_group); + + return count; +} + +static int +ixgbevf_get_reg_length(struct rte_eth_dev *dev __rte_unused) +{ + int count = 0; + int g_ind = 0; + const struct reg_info *reg_group; + + while ((reg_group = ixgbevf_regs[g_ind++])) + count += ixgbe_regs_group_count(reg_group); + + return count; +} + +static int +ixgbe_get_regs(struct rte_eth_dev *dev, + struct rte_dev_reg_info *regs) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t *data = regs->data; + int g_ind = 0; + int count = 0; + const struct reg_info *reg_group; + const struct reg_info **reg_set = (hw->mac.type == ixgbe_mac_82598EB) ? + ixgbe_regs_mac_82598EB : ixgbe_regs_others; + + /* Support only full register dump */ + if ((regs->length == 0) || + (regs->length == (uint32_t)ixgbe_get_reg_length(dev))) { + regs->version = hw->mac.type << 24 | hw->revision_id << 16 | + hw->device_id; + while ((reg_group = reg_set[g_ind++])) + count += ixgbe_read_regs_group(dev, &data[count], + reg_group); + return 0; + } + + return -ENOTSUP; +} + +static int +ixgbevf_get_regs(struct rte_eth_dev *dev, + struct rte_dev_reg_info *regs) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t *data = regs->data; + int g_ind = 0; + int count = 0; + const struct reg_info *reg_group; + + /* Support only full register dump */ + if ((regs->length == 0) || + (regs->length == (uint32_t)ixgbevf_get_reg_length(dev))) { + regs->version = hw->mac.type << 24 | hw->revision_id << 16 | + hw->device_id; + while ((reg_group = ixgbevf_regs[g_ind++])) + count += ixgbe_read_regs_group(dev, &data[count], + reg_group); + return 0; + } + + return -ENOTSUP; +} + +static int +ixgbe_get_eeprom_length(struct rte_eth_dev *dev) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + /* Return unit is byte count */ + return hw->eeprom.word_size * 2; +} + +static int +ixgbe_get_eeprom(struct rte_eth_dev *dev, + struct rte_dev_eeprom_info *in_eeprom) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct ixgbe_eeprom_info *eeprom = &hw->eeprom; + uint16_t *data = in_eeprom->data; + int first, length; + + first = in_eeprom->offset >> 1; + length = in_eeprom->length >> 1; + if ((first >= hw->eeprom.word_size) || + ((first + length) >= hw->eeprom.word_size)) + return -EINVAL; + + in_eeprom->magic = hw->vendor_id | (hw->device_id << 16); + + return eeprom->ops.read_buffer(hw, first, length, data); +} + +static int +ixgbe_set_eeprom(struct rte_eth_dev *dev, + struct rte_dev_eeprom_info *in_eeprom) +{ + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct ixgbe_eeprom_info *eeprom = &hw->eeprom; + uint16_t *data = in_eeprom->data; + int first, length; + + first = in_eeprom->offset >> 1; + length = in_eeprom->length >> 1; + if ((first >= hw->eeprom.word_size) || + ((first + length) >= hw->eeprom.word_size)) + return -EINVAL; + + in_eeprom->magic = hw->vendor_id | (hw->device_id << 16); + + return eeprom->ops.write_buffer(hw, first, length, data); +} + static struct rte_driver rte_ixgbe_driver = { .type = PMD_PDEV, .init = rte_ixgbe_pmd_init,