From: Pavel Belous <pavel.bel...@aquantia.com> Start, stop and reset are all done via hw_atl layer. Link interrupt configuration is also done here.
Signed-off-by: Igor Russkikh <igor.russk...@aquantia.com> Signed-off-by: Pavel Belous <pavel.bel...@aquantia.com> --- drivers/net/atlantic/atl_ethdev.c | 196 ++++++++++++++++++++++++++++++++++++-- drivers/net/atlantic/atl_ethdev.h | 8 ++ drivers/net/atlantic/atl_types.h | 4 + 3 files changed, 201 insertions(+), 7 deletions(-) diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c index 5728d9037d72..afb2972ffcc2 100644 --- a/drivers/net/atlantic/atl_ethdev.c +++ b/drivers/net/atlantic/atl_ethdev.c @@ -6,6 +6,11 @@ #include "atl_ethdev.h" #include "atl_common.h" +#include "atl_hw_regs.h" +#include "atl_logs.h" +#include "hw_atl/hw_atl_llh.h" +#include "hw_atl/hw_atl_b0.h" +#include "hw_atl/hw_atl_b0_internal.h" static int eth_atl_dev_init(struct rte_eth_dev *eth_dev); static int eth_atl_dev_uninit(struct rte_eth_dev *eth_dev); @@ -16,6 +21,13 @@ static void atl_dev_stop(struct rte_eth_dev *dev); static void atl_dev_close(struct rte_eth_dev *dev); static int atl_dev_reset(struct rte_eth_dev *dev); +static int atl_fw_version_get(struct rte_eth_dev *dev, char *fw_version, + size_t fw_size); + +static void atl_dev_info_get(struct rte_eth_dev *dev, + struct rte_eth_dev_info *dev_info); + + static int eth_atl_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, struct rte_pci_device *pci_dev); static int eth_atl_pci_remove(struct rte_pci_device *pci_dev); @@ -66,17 +78,103 @@ static const struct eth_dev_ops atl_eth_dev_ops = { .dev_stop = atl_dev_stop, .dev_close = atl_dev_close, .dev_reset = atl_dev_reset, + + .fw_version_get = atl_fw_version_get, + .dev_infos_get = atl_dev_info_get, }; +static inline int32_t +atl_reset_hw(struct aq_hw_s *hw) +{ + return hw_atl_b0_hw_reset(hw); +} + +static void +atl_print_adapter_info(struct aq_hw_s *hw __rte_unused) +{ + PMD_INIT_LOG(DEBUG, "FW version: %u.%u.%u", + hw->fw_ver_actual >> 24, + (hw->fw_ver_actual >> 16) & 0xFF, + hw->fw_ver_actual & 0xFFFF); + PMD_INIT_LOG(DEBUG, "Driver version: %s", ATL_PMD_DRIVER_VERSION); +} + static int -eth_atl_dev_init(struct rte_eth_dev *eth_dev __rte_unused) +eth_atl_dev_init(struct rte_eth_dev *eth_dev) { - return 0; + struct atl_adapter *adapter = + (struct atl_adapter *)eth_dev->data->dev_private; + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); + int err = 0; + + PMD_INIT_FUNC_TRACE(); + + eth_dev->dev_ops = &atl_eth_dev_ops; + + /* For secondary processes, the primary process has done all the work */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return 0; + + rte_eth_copy_pci_info(eth_dev, pci_dev); + + /* Vendor and Device ID need to be set before init of shared code */ + hw->device_id = pci_dev->id.device_id; + hw->vendor_id = pci_dev->id.vendor_id; + hw->mmio = (void *)pci_dev->mem_resource[0].addr; + + /* Hardware configuration - hardcode */ + adapter->hw_cfg.is_lro = false; + adapter->hw_cfg.wol = false; + + hw->aq_nic_cfg = &adapter->hw_cfg; + + /* Allocate memory for storing MAC addresses */ + eth_dev->data->mac_addrs = rte_zmalloc("atlantic", ETHER_ADDR_LEN, 0); + if (eth_dev->data->mac_addrs == NULL) { + PMD_INIT_LOG(ERR, "MAC Malloc failed"); + return -ENOMEM; + } + + err = hw_atl_utils_initfw(hw, &hw->aq_fw_ops); + if (err) + return err; + + /* Copy the permanent MAC address */ + if (hw->aq_fw_ops->get_mac_permanent(hw, + (u8 *)ð_dev->data->mac_addrs[0]) != 0) + return -EINVAL; + + return err; } static int -eth_atl_dev_uninit(struct rte_eth_dev *eth_dev __rte_unused) +eth_atl_dev_uninit(struct rte_eth_dev *eth_dev) { + struct aq_hw_s *hw; + + PMD_INIT_FUNC_TRACE(); + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return -EPERM; + + hw = ATL_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); + + if (hw->adapter_stopped == 0) + atl_dev_close(eth_dev); + + eth_dev->dev_ops = NULL; + + rte_free(eth_dev->data->mac_addrs); + eth_dev->data->mac_addrs = NULL; + + rte_free(eth_dev->data->hash_mac_addrs); + eth_dev->data->hash_mac_addrs = NULL; + +#ifdef RTE_LIBRTE_SECURITY + rte_free(eth_dev->security_ctx); +#endif + return 0; } @@ -105,25 +203,62 @@ atl_dev_configure(struct rte_eth_dev *dev __rte_unused) * It returns 0 on success. */ static int -atl_dev_start(struct rte_eth_dev *dev __rte_unused) +atl_dev_start(struct rte_eth_dev *dev) { - return 0; + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int status; + int err; + + PMD_INIT_FUNC_TRACE(); + + /* stop adapter */ + hw->adapter_stopped = 0; + + /* reinitialize adapter + * this calls reset and start + */ + status = atl_reset_hw(hw); + if (status != 0) + return -1; + + err = hw_atl_b0_hw_init(hw, (uint8_t *)dev->data->mac_addrs); + + hw_atl_b0_hw_start(hw); + + atl_print_adapter_info(hw); + + return err; } /* * Stop device: disable rx and tx functions to allow for reconfiguring. */ static void -atl_dev_stop(struct rte_eth_dev *dev __rte_unused) +atl_dev_stop(struct rte_eth_dev *dev) { + struct aq_hw_s *hw = + ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + /* reset the NIC */ + atl_reset_hw(hw); + hw->adapter_stopped = 0; + } /* * Reset and stop device. */ static void -atl_dev_close(struct rte_eth_dev *dev __rte_unused) +atl_dev_close(struct rte_eth_dev *dev) { + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + PMD_INIT_FUNC_TRACE(); + + atl_reset_hw(hw); + + atl_dev_stop(dev); + hw->adapter_stopped = 1; } static int @@ -140,6 +275,53 @@ atl_dev_reset(struct rte_eth_dev *dev) return ret; } +static int +atl_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size) +{ + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t fw_ver = 0; + unsigned int ret = 0; + + ret = hw_atl_utils_get_fw_version(hw, &fw_ver); + if (ret) + return 0; + + ret = snprintf(fw_version, fw_size, "%u.%u.%u", fw_ver >> 24, + (fw_ver >> 16) & 0xFFU, fw_ver & 0xFFFFU); + + ret += 1; /* add string null-terminator */ + + if (fw_size < ret) + return ret; + + return 0; +} + +static void +atl_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) +{ + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + + dev_info->max_vfs = pci_dev->max_vfs; + + dev_info->max_hash_mac_addrs = 0; + dev_info->max_vmdq_pools = 0; + dev_info->vmdq_queue_num = 0; +} + RTE_PMD_REGISTER_PCI(net_atlantic, rte_atl_pmd); RTE_PMD_REGISTER_PCI_TABLE(net_atlantic, pci_id_atl_map); RTE_PMD_REGISTER_KMOD_DEP(net_atlantic, "* igb_uio | uio_pci_generic"); + +RTE_INIT(atl_init_log); +static void +atl_init_log(void) +{ + atl_logtype_init = rte_log_register("pmd.atlantic.init"); + if (atl_logtype_init >= 0) + rte_log_set_level(atl_logtype_init, RTE_LOG_DEBUG); + atl_logtype_driver = rte_log_register("pmd.atlantic.driver"); + if (atl_logtype_driver >= 0) + rte_log_set_level(atl_logtype_driver, RTE_LOG_DEBUG); +} + diff --git a/drivers/net/atlantic/atl_ethdev.h b/drivers/net/atlantic/atl_ethdev.h index ae87517560de..0b5db79e1c22 100644 --- a/drivers/net/atlantic/atl_ethdev.h +++ b/drivers/net/atlantic/atl_ethdev.h @@ -6,10 +6,18 @@ #define _ATLANTIC_ETHDEV_H_ #include <rte_tm_driver.h> +#include "atl_types.h" +#include "hw_atl/hw_atl_utils.h" + +#define ATL_DEV_PRIVATE_TO_HW(adapter) \ + (&((struct atl_adapter *)adapter)->hw) + /* * Structure to store private data for each driver instance (for each port). */ struct atl_adapter { + struct aq_hw_s hw; + struct aq_hw_cfg_s hw_cfg; }; #endif /* _ATLANTIC_ETHDEV_H_ */ diff --git a/drivers/net/atlantic/atl_types.h b/drivers/net/atlantic/atl_types.h index 8185a86e1733..85f768ce7d93 100644 --- a/drivers/net/atlantic/atl_types.h +++ b/drivers/net/atlantic/atl_types.h @@ -83,6 +83,10 @@ struct aq_hw_cfg_s { }; struct aq_hw_s { + u16 device_id; + u16 vendor_id; + bool adapter_stopped; + u8 rbl_enabled:1; struct aq_hw_cfg_s *aq_nic_cfg; const struct aq_fw_ops *aq_fw_ops; -- 2.7.4