Move init() cleanup into uninit() function Fix .dev_private_size Add require hwrm calls: bnxt_hwrm_func_driver_register() bnxt_hwrm_func_driver_unregister()
Signed-off-by: Stephen Hurd <stephen.hurd at broadcom.com> Reviewed-by: Ajit Kumar Khaparde <ajit.khaparde at broadcom.com> --- drivers/net/bnxt/bnxt.h | 1 + drivers/net/bnxt/bnxt_ethdev.c | 48 ++++-- drivers/net/bnxt/bnxt_hwrm.c | 50 ++++++ drivers/net/bnxt/bnxt_hwrm.h | 3 + drivers/net/bnxt/hsi_struct_def_dpdk.h | 277 ++++++++++++++++++++++++++++++++- 5 files changed, 359 insertions(+), 20 deletions(-) diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h index 0f816ed..ebddeab 100644 --- a/drivers/net/bnxt/bnxt.h +++ b/drivers/net/bnxt/bnxt.h @@ -91,6 +91,7 @@ struct bnxt { struct rte_pci_device *pdev; uint32_t flags; +#define BNXT_FLAG_REGISTERED (1<<0) #define BNXT_FLAG_VF (1<<1) #define BNXT_PF(bp) (!((bp)->flags & BNXT_FLAG_VF)) #define BNXT_VF(bp) ((bp)->flags & BNXT_FLAG_VF) diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c index a74cc6c..07519df 100644 --- a/drivers/net/bnxt/bnxt_ethdev.c +++ b/drivers/net/bnxt/bnxt_ethdev.c @@ -52,20 +52,12 @@ static struct rte_pci_id bnxt_pci_id_map[] = { {.device_id = 0}, }; -static void bnxt_dev_close_op(struct rte_eth_dev *eth_dev) -{ - struct bnxt *bp = (struct bnxt *)eth_dev->data->dev_private; - - rte_free(eth_dev->data->mac_addrs); - bnxt_free_hwrm_resources(bp); -} - /* * Initialization */ static struct eth_dev_ops bnxt_dev_ops = { - .dev_close = bnxt_dev_close_op, +0 }; static bool bnxt_vf_pciid(uint16_t id) @@ -123,7 +115,8 @@ bnxt_dev_init(struct rte_eth_dev *eth_dev) eth_dev->pci_dev->addr.function < 4) { RTE_LOG(ERR, PMD, "Function not enabled %x:\n", eth_dev->pci_dev->addr.function); - return -ENOMEM; + rc = -ENOMEM; + goto error; } rte_eth_copy_pci_info(eth_dev, eth_dev->pci_dev); @@ -148,11 +141,11 @@ bnxt_dev_init(struct rte_eth_dev *eth_dev) if (rc) { RTE_LOG(ERR, PMD, "hwrm resource allocation failure rc: %x\n", rc); - goto error; + goto error_free; } rc = bnxt_hwrm_ver_get(bp); if (rc) - goto error; + goto error_free; bnxt_hwrm_queue_qportcfg(bp); /* Get the MAX capabilities for this function */ @@ -177,17 +170,38 @@ bnxt_dev_init(struct rte_eth_dev *eth_dev) memcpy(bp->mac_addr, bp->vf.mac_addr, sizeof(bp->mac_addr)); memcpy(ð_dev->data->mac_addrs[0], bp->mac_addr, ETHER_ADDR_LEN); - return -EPERM; + rc = bnxt_hwrm_func_driver_register(bp, 0, + bp->pf.vf_req_fwd); + if (rc) { + RTE_LOG(ERR, PMD, + "Failed to register driver"); + rc = -EBUSY; + goto error_free; + } + + RTE_LOG(INFO, PMD, + DRV_MODULE_NAME " found at mem %" PRIx64 ", node addr %pM\n", + eth_dev->pci_dev->mem_resource[0].phys_addr, + eth_dev->pci_dev->mem_resource[0].addr); + + return 0; error_free: - bnxt_dev_close_op(eth_dev); + eth_dev->driver->eth_dev_uninit(eth_dev); error: return rc; } static int -bnxt_dev_uninit(struct rte_eth_dev *eth_dev __rte_unused) { - return 0; +bnxt_dev_uninit(struct rte_eth_dev *eth_dev) { + struct bnxt *bp = eth_dev->data->dev_private; + int rc; + + if (eth_dev->data->mac_addrs) + rte_free(eth_dev->data->mac_addrs); + rc = bnxt_hwrm_func_driver_unregister(bp, 0); + bnxt_free_hwrm_resources(bp); + return rc; } static struct eth_driver bnxt_rte_pmd = { @@ -198,7 +212,7 @@ static struct eth_driver bnxt_rte_pmd = { }, .eth_dev_init = bnxt_dev_init, .eth_dev_uninit = bnxt_dev_uninit, - .dev_private_size = 32 /* this must be non-zero apparently */, + .dev_private_size = sizeof(struct bnxt), }; static int bnxt_rte_pmd_init(const char *name, const char *params __rte_unused) diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c index 5b66721..398f0f5 100644 --- a/drivers/net/bnxt/bnxt_hwrm.c +++ b/drivers/net/bnxt/bnxt_hwrm.c @@ -36,6 +36,7 @@ #include <rte_cycles.h> #include <rte_malloc.h> #include <rte_memzone.h> +#include <rte_version.h> #include "bnxt.h" #include "bnxt_hwrm.h" @@ -178,6 +179,34 @@ int bnxt_hwrm_func_qcaps(struct bnxt *bp) return rc; } +int bnxt_hwrm_func_driver_register(struct bnxt *bp, uint32_t flags, + uint32_t *vf_req_fwd) +{ + int rc; + struct hwrm_func_drv_rgtr_input req = {.req_type = 0 }; + struct hwrm_func_drv_rgtr_output *resp = bp->hwrm_cmd_resp_addr; + + if (bp->flags & BNXT_FLAG_REGISTERED) + return 0; + + HWRM_PREP(req, FUNC_DRV_RGTR, -1, resp); + req.flags = flags; + req.enables = HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER; + req.ver_maj = RTE_VER_YEAR; + req.ver_min = RTE_VER_MONTH; + req.ver_upd = RTE_VER_MINOR; + + memcpy(req.vf_req_fwd, vf_req_fwd, sizeof(req.vf_req_fwd)); + + rc = bnxt_hwrm_send_message(bp, &req, sizeof(req)); + + HWRM_CHECK_RESULT; + + bp->flags |= BNXT_FLAG_REGISTERED; + + return rc; +} + int bnxt_hwrm_ver_get(struct bnxt *bp) { int rc = 0; @@ -264,6 +293,27 @@ error: return rc; } +int bnxt_hwrm_func_driver_unregister(struct bnxt *bp, uint32_t flags) +{ + int rc; + struct hwrm_func_drv_unrgtr_input req = {.req_type = 0 }; + struct hwrm_func_drv_unrgtr_output *resp = bp->hwrm_cmd_resp_addr; + + if (!(bp->flags & BNXT_FLAG_REGISTERED)) + return 0; + + HWRM_PREP(req, FUNC_DRV_UNRGTR, -1, resp); + req.flags = flags; + + rc = bnxt_hwrm_send_message(bp, &req, sizeof(req)); + + HWRM_CHECK_RESULT; + + bp->flags &= ~BNXT_FLAG_REGISTERED; + + return rc; +} + int bnxt_hwrm_queue_qportcfg(struct bnxt *bp) { int rc = 0; diff --git a/drivers/net/bnxt/bnxt_hwrm.h b/drivers/net/bnxt/bnxt_hwrm.h index e35e8c0..6f2e445 100644 --- a/drivers/net/bnxt/bnxt_hwrm.h +++ b/drivers/net/bnxt/bnxt_hwrm.h @@ -41,7 +41,10 @@ #define HWRM_SEQ_ID_INVALID -1U +int bnxt_hwrm_func_driver_register(struct bnxt *bp, uint32_t flags, + uint32_t *vf_req_fwd); int bnxt_hwrm_func_qcaps(struct bnxt *bp); +int bnxt_hwrm_func_driver_unregister(struct bnxt *bp, uint32_t flags); int bnxt_hwrm_queue_qportcfg(struct bnxt *bp); diff --git a/drivers/net/bnxt/hsi_struct_def_dpdk.h b/drivers/net/bnxt/hsi_struct_def_dpdk.h index 1667927..be3ed0f 100644 --- a/drivers/net/bnxt/hsi_struct_def_dpdk.h +++ b/drivers/net/bnxt/hsi_struct_def_dpdk.h @@ -50,9 +50,11 @@ /* * Request types */ -#define HWRM_VER_GET (UINT32_C(0x0)) -#define HWRM_FUNC_QCAPS (UINT32_C(0x15)) -#define HWRM_QUEUE_QPORTCFG (UINT32_C(0x30)) +#define HWRM_VER_GET (UINT32_C(0x0)) +#define HWRM_FUNC_QCAPS (UINT32_C(0x15)) +#define HWRM_FUNC_DRV_UNRGTR (UINT32_C(0x1a)) +#define HWRM_FUNC_DRV_RGTR (UINT32_C(0x1d)) +#define HWRM_QUEUE_QPORTCFG (UINT32_C(0x30)) /* * Note: The Hardware Resource Manager (HWRM) manages various hardware resources @@ -951,4 +953,273 @@ struct hwrm_queue_qportcfg_output { uint8_t valid; } __attribute__((packed)); +/* hwrm_func_drv_rgtr */ +/* + * Description: This command is used by the function driver to register its + * information with the HWRM. A function driver shall implement this command. A + * function driver shall use this command during the driver initialization right + * after the HWRM version discovery and default ring resources allocation. + */ + +/* Input (80 bytes) */ +struct hwrm_func_drv_rgtr_input { + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t req_type; + + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t cmpl_ring; + + /* This value indicates the command sequence number. */ + uint16_t seq_id; + + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint16_t target_id; + + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint64_t resp_addr; + + /* + * When this bit is '1', the function driver is requesting all requests + * from its children VF drivers to be forwarded to itself. This flag can + * only be set by the PF driver. If a VF driver sets this flag, it + * should be ignored by the HWRM. + */ + #define HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_FWD_ALL_MODE UINT32_C(0x1) + /* + * When this bit is '1', the function is requesting none of the requests + * from its children VF drivers to be forwarded to itself. This flag can + * only be set by the PF driver. If a VF driver sets this flag, it + * should be ignored by the HWRM. + */ + #define HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_FWD_NONE_MODE UINT32_C(0x2) + uint32_t flags; + + /* This bit must be '1' for the os_type field to be configured. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE UINT32_C(0x1) + /* This bit must be '1' for the ver field to be configured. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER UINT32_C(0x2) + /* This bit must be '1' for the timestamp field to be configured. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_TIMESTAMP UINT32_C(0x4) + /* This bit must be '1' for the vf_req_fwd field to be configured. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VF_REQ_FWD UINT32_C(0x8) + /* + * This bit must be '1' for the async_event_fwd field to be configured. + */ + #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD \ + UINT32_C(0x10) + uint32_t enables; + + /* This value indicates the type of OS. */ + /* Unknown */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_UNKNOWN \ + (UINT32_C(0x0) << 0) + /* Other OS not listed below. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_OTHER \ + (UINT32_C(0x1) << 0) + /* MSDOS OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_MSDOS \ + (UINT32_C(0xe) << 0) + /* Windows OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_WINDOWS \ + (UINT32_C(0x12) << 0) + /* Solaris OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_SOLARIS \ + (UINT32_C(0x1d) << 0) + /* Linux OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_LINUX \ + (UINT32_C(0x24) << 0) + /* FreeBSD OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD \ + (UINT32_C(0x2a) << 0) + /* VMware ESXi OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_ESXI \ + (UINT32_C(0x68) << 0) + /* Microsoft Windows 8 64-bit OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_WIN864 \ + (UINT32_C(0x73) << 0) + /* Microsoft Windows Server 2012 R2 OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_WIN2012R2 \ + (UINT32_C(0x74) << 0) + uint16_t os_type; + + /* This is the major version of the driver. */ + uint8_t ver_maj; + + /* This is the minor version of the driver. */ + uint8_t ver_min; + + /* This is the update version of the driver. */ + uint8_t ver_upd; + + uint8_t unused_0; + uint16_t unused_1; + + /* + * This is a 32-bit timestamp provided by the driver for keep alive. The + * timestamp is in multiples of 1ms. + */ + uint32_t timestamp; + + uint32_t unused_2; + + /* + * This is a 256-bit bit mask provided by the PF driver for letting the + * HWRM know what commands issued by the VF driver to the HWRM should be + * forwarded to the PF driver. Nth bit refers to the Nth req_type. + * Setting Nth bit to 1 indicates that requests from the VF driver with + * req_type equal to N shall be forwarded to the parent PF driver. This + * field is not valid for the VF driver. + */ + uint32_t vf_req_fwd[8]; + + /* + * This is a 256-bit bit mask provided by the function driver (PF or VF + * driver) to indicate the list of asynchronous event completions to be + * forwarded. Nth bit refers to the Nth event_id. Setting Nth bit to 1 + * by the function driver shall result in the HWRM forwarding + * asynchronous event completion with event_id equal to N. If all bits + * are set to 0 (value of 0), then the HWRM shall not forward any + * asynchronous event completion to this function driver. + */ + uint32_t async_event_fwd[8]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_drv_rgtr_output { + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t error_code; + + /* This field returns the type of original request. */ + uint16_t req_type; + + /* This field provides original sequence number of the command. */ + uint16_t seq_id; + + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t resp_len; + + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ + uint8_t valid; +} __attribute__((packed)); + +/* hwrm_func_drv_unrgtr */ +/* + * Description: This command is used by the function driver to un register with + * the HWRM. A function driver shall implement this command. A function driver + * shall use this command during the driver unloading. + */ +/* Input (24 bytes) */ + +struct hwrm_func_drv_unrgtr_input { + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t req_type; + + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t cmpl_ring; + + /* This value indicates the command sequence number. */ + uint16_t seq_id; + + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint16_t target_id; + + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint64_t resp_addr; + + /* + * When this bit is '1', the function driver is notifying the HWRM to + * prepare for the shutdown. + */ + #define HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN \ + UINT32_C(0x1) + uint32_t flags; + + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ +struct hwrm_func_drv_unrgtr_output { + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t error_code; + + /* This field returns the type of original request. */ + uint16_t req_type; + + /* This field provides original sequence number of the command. */ + uint16_t seq_id; + + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t resp_len; + + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ + uint8_t valid; +} __attribute__((packed)); + #endif -- 1.9.1