+ ns = rte_timespec_to_ns(ts);
+ /* Set the timecounters to a new value. */
+ ptp->tc.nsec = ns;
+
+ return 0;
+}
+
+static int
+bnxt_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
+{
+ struct bnxt *bp = dev->data->dev_private;
+ struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+ uint64_t ns, systime_cycles = 0;
+ int rc = 0;
+
+ if (!ptp)
+ return 0;
+
+ if (BNXT_CHIP_THOR(bp))
+ rc = bnxt_hwrm_port_ts_query(bp, BNXT_PTP_FLAGS_CURRENT_TIME,
+ &systime_cycles);
+ else
+ systime_cycles = bnxt_cc_read(bp);
+
+ ns = rte_timecounter_update(&ptp->tc, systime_cycles);
+ *ts = rte_ns_to_timespec(ns);
+
+ return rc;
+}
+static int
+bnxt_timesync_enable(struct rte_eth_dev *dev)
+{
+ struct bnxt *bp = dev->data->dev_private;
+ struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+ uint32_t shift = 0;
+ int rc;
+
+ if (!ptp)
+ return 0;
+
+ ptp->rx_filter = 1;
+ ptp->tx_tstamp_en = 1;
+ ptp->rxctl = BNXT_PTP_MSG_EVENTS;
+
+ rc = bnxt_hwrm_ptp_cfg(bp);
+ if (rc)
+ return rc;
+
+ memset(&ptp->tc, 0, sizeof(struct rte_timecounter));
+ memset(&ptp->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
+ memset(&ptp->tx_tstamp_tc, 0, sizeof(struct rte_timecounter));
+
+ ptp->tc.cc_mask = BNXT_CYCLECOUNTER_MASK;
+ ptp->tc.cc_shift = shift;
+ ptp->tc.nsec_mask = (1ULL << shift) - 1;
+
+ ptp->rx_tstamp_tc.cc_mask = BNXT_CYCLECOUNTER_MASK;
+ ptp->rx_tstamp_tc.cc_shift = shift;
+ ptp->rx_tstamp_tc.nsec_mask = (1ULL << shift) - 1;
+
+ ptp->tx_tstamp_tc.cc_mask = BNXT_CYCLECOUNTER_MASK;
+ ptp->tx_tstamp_tc.cc_shift = shift;
+ ptp->tx_tstamp_tc.nsec_mask = (1ULL << shift) - 1;
+
+ if (!BNXT_CHIP_THOR(bp))
+ bnxt_map_ptp_regs(bp);
+
+ return 0;
+}
+
+static int
+bnxt_timesync_disable(struct rte_eth_dev *dev)
+{
+ struct bnxt *bp = dev->data->dev_private;
+ struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+
+ if (!ptp)
+ return 0;
+
+ ptp->rx_filter = 0;
+ ptp->tx_tstamp_en = 0;
+ ptp->rxctl = 0;
+
+ bnxt_hwrm_ptp_cfg(bp);
+
+ if (!BNXT_CHIP_THOR(bp))
+ bnxt_unmap_ptp_regs(bp);
+
+ return 0;
+}
+
+static int
+bnxt_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
+ struct timespec *timestamp,
+ uint32_t flags __rte_unused)
+{
+ struct bnxt *bp = dev->data->dev_private;
+ struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+ uint64_t rx_tstamp_cycles = 0;
+ uint64_t ns;
+
+ if (!ptp)
+ return 0;
+
+ if (BNXT_CHIP_THOR(bp))
+ rx_tstamp_cycles = ptp->rx_timestamp;
+ else
+ bnxt_get_rx_ts(bp, &rx_tstamp_cycles);
+
+ ns = rte_timecounter_update(&ptp->rx_tstamp_tc, rx_tstamp_cycles);
+ *timestamp = rte_ns_to_timespec(ns);
+ return 0;
+}
+
+static int
+bnxt_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
+ struct timespec *timestamp)
+{
+ struct bnxt *bp = dev->data->dev_private;
+ struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+ uint64_t tx_tstamp_cycles = 0;
+ uint64_t ns;
+ int rc = 0;
+
+ if (!ptp)
+ return 0;
+
+ if (BNXT_CHIP_THOR(bp))
+ rc = bnxt_hwrm_port_ts_query(bp, BNXT_PTP_FLAGS_PATH_TX,
+ &tx_tstamp_cycles);
+ else
+ rc = bnxt_get_tx_ts(bp, &tx_tstamp_cycles);
+
+ ns = rte_timecounter_update(&ptp->tx_tstamp_tc, tx_tstamp_cycles);
+ *timestamp = rte_ns_to_timespec(ns);
+
+ return rc;
+}
+
+static int
+bnxt_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta)
+{
+ struct bnxt *bp = dev->data->dev_private;
+ struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+
+ if (!ptp)
+ return 0;
+
+ ptp->tc.nsec += delta;
+
+ return 0;
+}
+
+static int
+bnxt_get_eeprom_length_op(struct rte_eth_dev *dev)
+{
+ struct bnxt *bp = dev->data->dev_private;
+ int rc;
+ uint32_t dir_entries;
+ uint32_t entry_length;
+
+ rc = is_bnxt_in_error(bp);
+ if (rc)
+ return rc;
+
+ PMD_DRV_LOG(INFO, PCI_PRI_FMT "\n",
+ bp->pdev->addr.domain, bp->pdev->addr.bus,
+ bp->pdev->addr.devid, bp->pdev->addr.function);
+
+ rc = bnxt_hwrm_nvm_get_dir_info(bp, &dir_entries, &entry_length);
+ if (rc != 0)
+ return rc;
+
+ return dir_entries * entry_length;
+}
+
+static int
+bnxt_get_eeprom_op(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *in_eeprom)
+{
+ struct bnxt *bp = dev->data->dev_private;
+ uint32_t index;
+ uint32_t offset;
+ int rc;
+
+ rc = is_bnxt_in_error(bp);
+ if (rc)
+ return rc;
+
+ PMD_DRV_LOG(INFO, PCI_PRI_FMT " in_eeprom->offset = %d len = %d\n",
+ bp->pdev->addr.domain, bp->pdev->addr.bus,
+ bp->pdev->addr.devid, bp->pdev->addr.function,
+ in_eeprom->offset, in_eeprom->length);
+
+ if (in_eeprom->offset == 0) /* special offset value to get directory */
+ return bnxt_get_nvram_directory(bp, in_eeprom->length,
+ in_eeprom->data);
+
+ index = in_eeprom->offset >> 24;
+ offset = in_eeprom->offset & 0xffffff;
+
+ if (index != 0)
+ return bnxt_hwrm_get_nvram_item(bp, index - 1, offset,
+ in_eeprom->length, in_eeprom->data);
+
+ return 0;
+}
+
+static bool bnxt_dir_type_is_ape_bin_format(uint16_t dir_type)
+{
+ switch (dir_type) {
+ case BNX_DIR_TYPE_CHIMP_PATCH:
+ case BNX_DIR_TYPE_BOOTCODE:
+ case BNX_DIR_TYPE_BOOTCODE_2:
+ case BNX_DIR_TYPE_APE_FW:
+ case BNX_DIR_TYPE_APE_PATCH:
+ case BNX_DIR_TYPE_KONG_FW:
+ case BNX_DIR_TYPE_KONG_PATCH:
+ case BNX_DIR_TYPE_BONO_FW:
+ case BNX_DIR_TYPE_BONO_PATCH:
+ /* FALLTHROUGH */
+ return true;
+ }
+
+ return false;
+}
+
+static bool bnxt_dir_type_is_other_exec_format(uint16_t dir_type)
+{
+ switch (dir_type) {
+ case BNX_DIR_TYPE_AVS:
+ case BNX_DIR_TYPE_EXP_ROM_MBA:
+ case BNX_DIR_TYPE_PCIE:
+ case BNX_DIR_TYPE_TSCF_UCODE:
+ case BNX_DIR_TYPE_EXT_PHY:
+ case BNX_DIR_TYPE_CCM:
+ case BNX_DIR_TYPE_ISCSI_BOOT:
+ case BNX_DIR_TYPE_ISCSI_BOOT_IPV6:
+ case BNX_DIR_TYPE_ISCSI_BOOT_IPV4N6:
+ /* FALLTHROUGH */
+ return true;
+ }
+
+ return false;
+}
+
+static bool bnxt_dir_type_is_executable(uint16_t dir_type)
+{
+ return bnxt_dir_type_is_ape_bin_format(dir_type) ||
+ bnxt_dir_type_is_other_exec_format(dir_type);
+}
+
+static int
+bnxt_set_eeprom_op(struct rte_eth_dev *dev,
+ struct rte_dev_eeprom_info *in_eeprom)
+{
+ struct bnxt *bp = dev->data->dev_private;
+ uint8_t index, dir_op;
+ uint16_t type, ext, ordinal, attr;
+ int rc;
+
+ rc = is_bnxt_in_error(bp);
+ if (rc)
+ return rc;
+
+ PMD_DRV_LOG(INFO, PCI_PRI_FMT " in_eeprom->offset = %d len = %d\n",
+ bp->pdev->addr.domain, bp->pdev->addr.bus,
+ bp->pdev->addr.devid, bp->pdev->addr.function,
+ in_eeprom->offset, in_eeprom->length);
+
+ if (!BNXT_PF(bp)) {
+ PMD_DRV_LOG(ERR, "NVM write not supported from a VF\n");
+ return -EINVAL;
+ }
+
+ type = in_eeprom->magic >> 16;
+
+ if (type == 0xffff) { /* special value for directory operations */
+ index = in_eeprom->magic & 0xff;
+ dir_op = in_eeprom->magic >> 8;
+ if (index == 0)
+ return -EINVAL;
+ switch (dir_op) {
+ case 0x0e: /* erase */
+ if (in_eeprom->offset != ~in_eeprom->magic)
+ return -EINVAL;
+ return bnxt_hwrm_erase_nvram_directory(bp, index - 1);
+ default:
+ return -EINVAL;
+ }
+ }
+
+ /* Create or re-write an NVM item: */
+ if (bnxt_dir_type_is_executable(type) == true)
+ return -EOPNOTSUPP;
+ ext = in_eeprom->magic & 0xffff;
+ ordinal = in_eeprom->offset >> 16;
+ attr = in_eeprom->offset & 0xffff;
+
+ return bnxt_hwrm_flash_nvram(bp, type, ordinal, ext, attr,
+ in_eeprom->data, in_eeprom->length);
+}
+
+/*
+ * Initialization
+ */
+
+static const struct eth_dev_ops bnxt_dev_ops = {
+ .dev_infos_get = bnxt_dev_info_get_op,
+ .dev_close = bnxt_dev_close_op,
+ .dev_configure = bnxt_dev_configure_op,
+ .dev_start = bnxt_dev_start_op,
+ .dev_stop = bnxt_dev_stop_op,
+ .dev_set_link_up = bnxt_dev_set_link_up_op,
+ .dev_set_link_down = bnxt_dev_set_link_down_op,
+ .stats_get = bnxt_stats_get_op,
+ .stats_reset = bnxt_stats_reset_op,
+ .rx_queue_setup = bnxt_rx_queue_setup_op,
+ .rx_queue_release = bnxt_rx_queue_release_op,
+ .tx_queue_setup = bnxt_tx_queue_setup_op,
+ .tx_queue_release = bnxt_tx_queue_release_op,
+ .rx_queue_intr_enable = bnxt_rx_queue_intr_enable_op,
+ .rx_queue_intr_disable = bnxt_rx_queue_intr_disable_op,
+ .reta_update = bnxt_reta_update_op,
+ .reta_query = bnxt_reta_query_op,
+ .rss_hash_update = bnxt_rss_hash_update_op,
+ .rss_hash_conf_get = bnxt_rss_hash_conf_get_op,
+ .link_update = bnxt_link_update_op,
+ .promiscuous_enable = bnxt_promiscuous_enable_op,
+ .promiscuous_disable = bnxt_promiscuous_disable_op,
+ .allmulticast_enable = bnxt_allmulticast_enable_op,
+ .allmulticast_disable = bnxt_allmulticast_disable_op,
+ .mac_addr_add = bnxt_mac_addr_add_op,
+ .mac_addr_remove = bnxt_mac_addr_remove_op,
+ .flow_ctrl_get = bnxt_flow_ctrl_get_op,
+ .flow_ctrl_set = bnxt_flow_ctrl_set_op,
+ .udp_tunnel_port_add = bnxt_udp_tunnel_port_add_op,
+ .udp_tunnel_port_del = bnxt_udp_tunnel_port_del_op,
+ .vlan_filter_set = bnxt_vlan_filter_set_op,
+ .vlan_offload_set = bnxt_vlan_offload_set_op,
+ .vlan_tpid_set = bnxt_vlan_tpid_set_op,
+ .vlan_pvid_set = bnxt_vlan_pvid_set_op,
+ .mtu_set = bnxt_mtu_set_op,
+ .mac_addr_set = bnxt_set_default_mac_addr_op,
+ .xstats_get = bnxt_dev_xstats_get_op,
+ .xstats_get_names = bnxt_dev_xstats_get_names_op,
+ .xstats_reset = bnxt_dev_xstats_reset_op,
+ .fw_version_get = bnxt_fw_version_get,
+ .set_mc_addr_list = bnxt_dev_set_mc_addr_list_op,
+ .rxq_info_get = bnxt_rxq_info_get_op,
+ .txq_info_get = bnxt_txq_info_get_op,
+ .rx_burst_mode_get = bnxt_rx_burst_mode_get,
+ .tx_burst_mode_get = bnxt_tx_burst_mode_get,
+ .dev_led_on = bnxt_dev_led_on_op,
+ .dev_led_off = bnxt_dev_led_off_op,
+ .rx_queue_start = bnxt_rx_queue_start,
+ .rx_queue_stop = bnxt_rx_queue_stop,
+ .tx_queue_start = bnxt_tx_queue_start,
+ .tx_queue_stop = bnxt_tx_queue_stop,
+ .filter_ctrl = bnxt_filter_ctrl_op,
+ .dev_supported_ptypes_get = bnxt_dev_supported_ptypes_get_op,
+ .get_eeprom_length = bnxt_get_eeprom_length_op,
+ .get_eeprom = bnxt_get_eeprom_op,
+ .set_eeprom = bnxt_set_eeprom_op,
+ .timesync_enable = bnxt_timesync_enable,
+ .timesync_disable = bnxt_timesync_disable,
+ .timesync_read_time = bnxt_timesync_read_time,
+ .timesync_write_time = bnxt_timesync_write_time,
+ .timesync_adjust_time = bnxt_timesync_adjust_time,
+ .timesync_read_rx_timestamp = bnxt_timesync_read_rx_timestamp,
+ .timesync_read_tx_timestamp = bnxt_timesync_read_tx_timestamp,
+};
+
+static uint32_t bnxt_map_reset_regs(struct bnxt *bp, uint32_t reg)
+{
+ uint32_t offset;
+
+ /* Only pre-map the reset GRC registers using window 3 */
+ rte_write32(reg & 0xfffff000, (uint8_t *)bp->bar0 +
+ BNXT_GRCPF_REG_WINDOW_BASE_OUT + 8);
+
+ offset = BNXT_GRCP_WINDOW_3_BASE + (reg & 0xffc);
+
+ return offset;
+}
+
+int bnxt_map_fw_health_status_regs(struct bnxt *bp)
+{
+ struct bnxt_error_recovery_info *info = bp->recovery_info;
+ uint32_t reg_base = 0xffffffff;
+ int i;
+
+ /* Only pre-map the monitoring GRC registers using window 2 */
+ for (i = 0; i < BNXT_FW_STATUS_REG_CNT; i++) {
+ uint32_t reg = info->status_regs[i];
+
+ if (BNXT_FW_STATUS_REG_TYPE(reg) != BNXT_FW_STATUS_REG_TYPE_GRC)
+ continue;
+
+ if (reg_base == 0xffffffff)
+ reg_base = reg & 0xfffff000;
+ if ((reg & 0xfffff000) != reg_base)
+ return -ERANGE;
+
+ /* Use mask 0xffc as the Lower 2 bits indicates
+ * address space location
+ */
+ info->mapped_status_regs[i] = BNXT_GRCP_WINDOW_2_BASE +
+ (reg & 0xffc);
+ }
+
+ if (reg_base == 0xffffffff)
+ return 0;
+
+ rte_write32(reg_base, (uint8_t *)bp->bar0 +
+ BNXT_GRCPF_REG_WINDOW_BASE_OUT + 4);
+
+ return 0;
+}
+
+static void bnxt_write_fw_reset_reg(struct bnxt *bp, uint32_t index)
+{
+ struct bnxt_error_recovery_info *info = bp->recovery_info;
+ uint32_t delay = info->delay_after_reset[index];
+ uint32_t val = info->reset_reg_val[index];
+ uint32_t reg = info->reset_reg[index];
+ uint32_t type, offset;
+
+ type = BNXT_FW_STATUS_REG_TYPE(reg);
+ offset = BNXT_FW_STATUS_REG_OFF(reg);
+
+ switch (type) {
+ case BNXT_FW_STATUS_REG_TYPE_CFG:
+ rte_pci_write_config(bp->pdev, &val, sizeof(val), offset);