git: 28497d1445db - stable/13 - if_bnxt: Added support for mgmt interface for passthrough hwrms
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 19 Jan 2023 03:52:23 UTC
The branch stable/13 has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=28497d1445dbf7b5e7a858ada1623920a5a76dd1 commit 28497d1445dbf7b5e7a858ada1623920a5a76dd1 Author: Sumit Saxena <sumit.saxena@broadcom.com> AuthorDate: 2022-11-04 22:40:29 +0000 Commit: Warner Losh <imp@FreeBSD.org> CommitDate: 2023-01-19 01:00:07 +0000 if_bnxt: Added support for mgmt interface for passthrough hwrms Added support for application management interface. There are two types of commands supported: 1. Firmware IOCTLs: These ioctls are meant for firmware consumption. Driver acts as a transport for these. 2. Driver only IOCTLs: These ioctls are meant for driver consumption. Driver will serve these ioctls without sending them down to firmware. Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D36448 (cherry picked from commit 58d84ef87094691bf1ad9608964ec85f120cd34a) --- sys/conf/files | 1 + sys/dev/bnxt/bnxt.h | 13 ++ sys/dev/bnxt/bnxt_hwrm.c | 35 ++++- sys/dev/bnxt/bnxt_hwrm.h | 2 + sys/dev/bnxt/bnxt_mgmt.c | 373 ++++++++++++++++++++++++++++++++++++++++++++++ sys/dev/bnxt/bnxt_mgmt.h | 126 ++++++++++++++++ sys/dev/bnxt/if_bnxt.c | 43 +++++- sys/modules/bnxt/Makefile | 5 +- 8 files changed, 592 insertions(+), 6 deletions(-) diff --git a/sys/conf/files b/sys/conf/files index be8449a92048..d97ad247a7bd 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1397,6 +1397,7 @@ dev/bhnd/siba/siba_erom.c optional siba bhnd dev/bhnd/siba/siba_subr.c optional siba bhnd # dev/bnxt/bnxt_hwrm.c optional bnxt iflib pci +dev/bnxt/bnxt_mgmt.c optional bnxt iflib pci dev/bnxt/bnxt_sysctl.c optional bnxt iflib pci dev/bnxt/bnxt_txrx.c optional bnxt iflib pci dev/bnxt/if_bnxt.c optional bnxt iflib pci diff --git a/sys/dev/bnxt/bnxt.h b/sys/dev/bnxt/bnxt.h index 0d5824722b41..27abccc6b324 100644 --- a/sys/dev/bnxt/bnxt.h +++ b/sys/dev/bnxt/bnxt.h @@ -208,6 +208,7 @@ __FBSDID("$FreeBSD$"); #define BNXT_MIN_FRAME_SIZE 52 /* Frames must be padded to this size for some A0 chips */ +extern char bnxt_driver_version[]; typedef void (*bnxt_doorbell_tx)(void *, uint16_t idx); typedef void (*bnxt_doorbell_rx)(void *, uint16_t idx); typedef void (*bnxt_doorbell_rx_cq)(void *, bool); @@ -648,14 +649,25 @@ struct bnxt_hw_resc { #define BNXT_HWRM_MAX_REQ_LEN (softc->hwrm_max_req_len) +struct bnxt_softc_list { + SLIST_ENTRY(bnxt_softc_list) next; + struct bnxt_softc *softc; +}; + struct bnxt_softc { device_t dev; if_ctx_t ctx; if_softc_ctx_t scctx; if_shared_ctx_t sctx; + uint32_t domain; + uint32_t bus; + uint32_t slot; + uint32_t function; + uint32_t dev_fn; struct ifmedia *media; struct bnxt_ctx_mem_info *ctx_mem; struct bnxt_hw_resc hw_resc; + struct bnxt_softc_list list; struct bnxt_bar_info hwrm_bar; struct bnxt_bar_info doorbell_bar; @@ -788,5 +800,6 @@ struct bnxt_filter_info { /* Function declarations */ void bnxt_report_link(struct bnxt_softc *softc); bool bnxt_check_hwrm_version(struct bnxt_softc *softc); +struct bnxt_softc *bnxt_find_dev(uint32_t domain, uint32_t bus, uint32_t dev_fn, char *name); #endif /* _BNXT_H */ diff --git a/sys/dev/bnxt/bnxt_hwrm.c b/sys/dev/bnxt/bnxt_hwrm.c index 46dd8f34a6c5..c362e01a1f8b 100644 --- a/sys/dev/bnxt/bnxt_hwrm.c +++ b/sys/dev/bnxt/bnxt_hwrm.c @@ -540,6 +540,37 @@ hwrm_func_resc_qcaps_exit: return rc; } +int +bnxt_hwrm_passthrough(struct bnxt_softc *softc, void *req, uint32_t req_len, + void *resp, uint32_t resp_len, uint32_t app_timeout) +{ + int rc = 0; + void *output = (void *)softc->hwrm_cmd_resp.idi_vaddr; + struct input *input = req; + uint32_t old_timeo; + + input->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr); + BNXT_HWRM_LOCK(softc); + old_timeo = softc->hwrm_cmd_timeo; + if (input->req_type == HWRM_NVM_INSTALL_UPDATE) + softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; + else + softc->hwrm_cmd_timeo = max(app_timeout, softc->hwrm_cmd_timeo); + rc = _hwrm_send_message(softc, req, req_len); + softc->hwrm_cmd_timeo = old_timeo; + if (rc) { + device_printf(softc->dev, "%s: %s command failed with rc: 0x%x\n", + __FUNCTION__, GET_HWRM_REQ_TYPE(input->req_type), rc); + goto fail; + } + + memcpy(resp, output, resp_len); +fail: + BNXT_HWRM_UNLOCK(softc); + return rc; +} + + int bnxt_hwrm_ver_get(struct bnxt_softc *softc) { @@ -657,7 +688,6 @@ bnxt_hwrm_ver_get(struct bnxt_softc *softc) softc->ver_info->chip_bond_id = resp->chip_bond_id; softc->ver_info->chip_type = resp->chip_platform_type; - if (resp->hwrm_intf_maj_8b >= 1) { softc->hwrm_max_req_len = le16toh(resp->max_req_win_len); softc->hwrm_max_ext_req_len = le16toh(resp->max_ext_req_len); @@ -666,8 +696,7 @@ bnxt_hwrm_ver_get(struct bnxt_softc *softc) softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout); if (!softc->hwrm_cmd_timeo) softc->hwrm_cmd_timeo = DFLT_HWRM_CMD_TIMEOUT; - - + dev_caps_cfg = le32toh(resp->dev_caps_cfg); if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) && (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED)) diff --git a/sys/dev/bnxt/bnxt_hwrm.h b/sys/dev/bnxt/bnxt_hwrm.h index dde82c0aaff8..5e2be49b643d 100644 --- a/sys/dev/bnxt/bnxt_hwrm.h +++ b/sys/dev/bnxt/bnxt_hwrm.h @@ -129,4 +129,6 @@ int bnxt_hwrm_func_resc_qcaps(struct bnxt_softc *softc, bool all); int bnxt_hwrm_reserve_pf_rings (struct bnxt_softc *softc); void bnxt_hwrm_ring_info_get(struct bnxt_softc *softc, uint8_t ring_type, uint32_t ring_id, uint32_t *prod, uint32_t *); +int bnxt_hwrm_passthrough(struct bnxt_softc *softc, void *req, uint32_t req_len, + void *resp, uint32_t resp_len, uint32_t timeout); #endif diff --git a/sys/dev/bnxt/bnxt_mgmt.c b/sys/dev/bnxt/bnxt_mgmt.c new file mode 100644 index 000000000000..d54d7a2a2fe1 --- /dev/null +++ b/sys/dev/bnxt/bnxt_mgmt.c @@ -0,0 +1,373 @@ +/* + * Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2022 Broadcom, All Rights Reserved. + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bnxt_mgmt.h" +#include "bnxt.h" +#include "bnxt_hwrm.h" +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <sys/endian.h> +#include <sys/lock.h> + +/* Function prototypes */ +static d_open_t bnxt_mgmt_open; +static d_close_t bnxt_mgmt_close; +static d_ioctl_t bnxt_mgmt_ioctl; + +/* Character device entry points */ +static struct cdevsw bnxt_mgmt_cdevsw = { + .d_version = D_VERSION, + .d_open = bnxt_mgmt_open, + .d_close = bnxt_mgmt_close, + .d_ioctl = bnxt_mgmt_ioctl, + .d_name = "bnxt_mgmt", +}; + +/* Global vars */ +static struct cdev *bnxt_mgmt_dev; +struct mtx mgmt_lock; + +MALLOC_DEFINE(M_BNXT, "bnxt_mgmt_buffer", "buffer for bnxt_mgmt module"); + +/* + * This function is called by the kld[un]load(2) system calls to + * determine what actions to take when a module is loaded or unloaded. + */ +static int +bnxt_mgmt_loader(struct module *m, int what, void *arg) +{ + int error = 0; + + switch (what) { + case MOD_LOAD: + error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, + &bnxt_mgmt_dev, + &bnxt_mgmt_cdevsw, + 0, + UID_ROOT, + GID_WHEEL, + 0600, + "bnxt_mgmt"); + if (error != 0) { + printf("%s: %s:%s:%d Failed to create the" + "bnxt_mgmt device node\n", DRIVER_NAME, + __FILE__, __FUNCTION__, __LINE__); + return (error); + } + + mtx_init(&mgmt_lock, "BNXT MGMT Lock", NULL, MTX_DEF); + + break; + case MOD_UNLOAD: + mtx_destroy(&mgmt_lock); + destroy_dev(bnxt_mgmt_dev); + break; + default: + error = EOPNOTSUPP; + break; + } + + return (error); +} + +static int +bnxt_mgmt_process_hwrm(struct cdev *dev, u_long cmd, caddr_t data, + int flag, struct thread *td) +{ + struct bnxt_softc *softc = NULL; + struct bnxt_mgmt_req mgmt_req = {}; + struct bnxt_mgmt_fw_msg msg_temp, *msg, *msg2 = NULL; + struct iflib_dma_info dma_data = {}; + void *user_ptr, *req, *resp; + int ret = 0; + uint16_t num_ind = 0; + + memcpy(&user_ptr, data, sizeof(user_ptr)); + if (copyin(user_ptr, &mgmt_req, sizeof(struct bnxt_mgmt_req))) { + printf("%s: %s:%d Failed to copy data from user\n", + DRIVER_NAME, __FUNCTION__, __LINE__); + return -EFAULT; + } + softc = bnxt_find_dev(mgmt_req.hdr.domain, mgmt_req.hdr.bus, + mgmt_req.hdr.devfn, NULL); + if (!softc) { + printf("%s: %s:%d unable to find softc reference\n", + DRIVER_NAME, __FUNCTION__, __LINE__); + return -ENODEV; + } + + if (copyin((void*)mgmt_req.req.hreq, &msg_temp, sizeof(msg_temp))) { + device_printf(softc->dev, "%s:%d Failed to copy data from user\n", + __FUNCTION__, __LINE__); + return -EFAULT; + } + + if (msg_temp.len_req > BNXT_MGMT_MAX_HWRM_REQ_LENGTH || + msg_temp.len_resp > BNXT_MGMT_MAX_HWRM_RESP_LENGTH) { + device_printf(softc->dev, "%s:%d Invalid length\n", + __FUNCTION__, __LINE__); + return -EINVAL; + } + + if (msg_temp.num_dma_indications > 1) { + device_printf(softc->dev, "%s:%d Max num_dma_indications " + "supported is 1 \n", __FUNCTION__, __LINE__); + return -EINVAL; + } + + req = malloc(msg_temp.len_req, M_BNXT, M_WAITOK | M_ZERO); + if(!req) { + device_printf(softc->dev, "%s:%d Memory allocation failed", + __FUNCTION__, __LINE__); + return -ENOMEM; + } + + resp = malloc(msg_temp.len_resp, M_BNXT, M_WAITOK | M_ZERO); + if(!resp) { + device_printf(softc->dev, "%s:%d Memory allocation failed", + __FUNCTION__, __LINE__); + ret = -ENOMEM; + goto end; + } + + if (copyin((void *)msg_temp.usr_req, req, msg_temp.len_req)) { + device_printf(softc->dev, "%s:%d Failed to copy data from user\n", + __FUNCTION__, __LINE__); + ret = -EFAULT; + goto end; + } + + msg = &msg_temp; + num_ind = msg_temp.num_dma_indications; + if (num_ind) { + int size; + void *dma_ptr; + uint64_t *dmap; + + size = sizeof(struct bnxt_mgmt_fw_msg) + + (num_ind * sizeof(struct dma_info)); + + msg2 = malloc(size, M_BNXT, M_WAITOK | M_ZERO); + if(!msg2) { + device_printf(softc->dev, "%s:%d Memory allocation failed", + __FUNCTION__, __LINE__); + ret = -ENOMEM; + goto end; + } + + if (copyin((void *)mgmt_req.req.hreq, msg2, size)) { + device_printf(softc->dev, "%s:%d Failed to copy" + "data from user\n", __FUNCTION__, __LINE__); + ret = -EFAULT; + goto end; + } + msg = msg2; + + ret = iflib_dma_alloc(softc->ctx, msg->dma[0].length, &dma_data, + BUS_DMA_NOWAIT); + if (ret) { + device_printf(softc->dev, "%s:%d iflib_dma_alloc" + "failed with ret = 0x%x\n", __FUNCTION__, + __LINE__, ret); + ret = -ENOMEM; + goto end; + } + + if (!(msg->dma[0].read_or_write)) { + if (copyin((void *)msg->dma[0].data, + dma_data.idi_vaddr, + msg->dma[0].length)) { + device_printf(softc->dev, "%s:%d Failed to copy" + "data from user\n", __FUNCTION__, + __LINE__); + ret = -EFAULT; + goto end; + } + } + dma_ptr = (void *) ((uint64_t) req + msg->dma[0].offset); + dmap = dma_ptr; + *dmap = htole64(dma_data.idi_paddr); + } + + ret = bnxt_hwrm_passthrough(softc, req, msg->len_req, resp, msg->len_resp, msg->timeout); + if(ret) + goto end; + + if (num_ind) { + if ((msg->dma[0].read_or_write)) { + if (copyout(dma_data.idi_vaddr, + (void *)msg->dma[0].data, + msg->dma[0].length)) { + device_printf(softc->dev, "%s:%d Failed to copy data" + "to user\n", __FUNCTION__, __LINE__); + ret = -EFAULT; + goto end; + } + } + } + + if (copyout(resp, (void *) msg->usr_resp, msg->len_resp)) { + device_printf(softc->dev, "%s:%d Failed to copy response to user\n", + __FUNCTION__, __LINE__); + ret = -EFAULT; + goto end; + } + +end: + if (req) + free(req, M_BNXT); + if (resp) + free(resp, M_BNXT); + if (msg2) + free(msg2, M_BNXT); + if (dma_data.idi_paddr) + iflib_dma_free(&dma_data); + return ret; +} + +static int +bnxt_mgmt_get_dev_info(struct cdev *dev, u_long cmd, caddr_t data, + int flag, struct thread *td) +{ + struct bnxt_softc *softc = NULL; + struct bnxt_dev_info dev_info; + void *user_ptr; + uint32_t dev_sn_lo, dev_sn_hi; + int dev_sn_offset = 0; + char dsn[16]; + uint16_t lnk; + int capreg; + + memcpy(&user_ptr, data, sizeof(user_ptr)); + if (copyin(user_ptr, &dev_info, sizeof(dev_info))) { + printf("%s: %s:%d Failed to copy data from user\n", + DRIVER_NAME, __FUNCTION__, __LINE__); + return -EFAULT; + } + + softc = bnxt_find_dev(0, 0, 0, dev_info.nic_info.dev_name); + if (!softc) { + printf("%s: %s:%d unable to find softc reference\n", + DRIVER_NAME, __FUNCTION__, __LINE__); + return -ENODEV; + } + + strncpy(dev_info.nic_info.driver_version, bnxt_driver_version, 64); + strncpy(dev_info.nic_info.driver_name, device_get_name(softc->dev), 64); + dev_info.pci_info.domain_no = softc->domain; + dev_info.pci_info.bus_no = softc->bus; + dev_info.pci_info.device_no = softc->slot; + dev_info.pci_info.function_no = softc->function; + dev_info.pci_info.vendor_id = pci_get_vendor(softc->dev); + dev_info.pci_info.device_id = pci_get_device(softc->dev); + dev_info.pci_info.sub_system_vendor_id = pci_get_subvendor(softc->dev); + dev_info.pci_info.sub_system_device_id = pci_get_subdevice(softc->dev); + dev_info.pci_info.revision = pci_read_config(softc->dev, PCIR_REVID, 1); + dev_info.pci_info.chip_rev_id = (dev_info.pci_info.device_id << 16); + dev_info.pci_info.chip_rev_id |= dev_info.pci_info.revision; + if (pci_find_extcap(softc->dev, PCIZ_SERNUM, &dev_sn_offset)) { + device_printf(softc->dev, "%s:%d device serial number is not found" + "or not supported\n", __FUNCTION__, __LINE__); + } else { + dev_sn_lo = pci_read_config(softc->dev, dev_sn_offset + 4, 4); + dev_sn_hi = pci_read_config(softc->dev, dev_sn_offset + 8, 4); + snprintf(dsn, sizeof(dsn), "%02x%02x%02x%02x%02x%02x%02x%02x", + (dev_sn_lo & 0x000000FF), + (dev_sn_lo >> 8) & 0x0000FF, + (dev_sn_lo >> 16) & 0x00FF, + (dev_sn_lo >> 24 ) & 0xFF, + (dev_sn_hi & 0x000000FF), + (dev_sn_hi >> 8) & 0x0000FF, + (dev_sn_hi >> 16) & 0x00FF, + (dev_sn_hi >> 24 ) & 0xFF); + strncpy(dev_info.nic_info.device_serial_number, dsn, sizeof(dsn)); + } + + if_t ifp = iflib_get_ifp(softc->ctx); + dev_info.nic_info.mtu = ifp->if_mtu; + memcpy(dev_info.nic_info.mac, softc->func.mac_addr, ETHER_ADDR_LEN); + + if (pci_find_cap(softc->dev, PCIY_EXPRESS, &capreg)) { + device_printf(softc->dev, "%s:%d pci link capability is not found" + "or not supported\n", __FUNCTION__, __LINE__); + } else { + lnk = pci_read_config(softc->dev, capreg + PCIER_LINK_STA, 2); + dev_info.nic_info.pci_link_speed = (lnk & PCIEM_LINK_STA_SPEED); + dev_info.nic_info.pci_link_width = (lnk & PCIEM_LINK_STA_WIDTH) >> 4; + } + + if (copyout(&dev_info, user_ptr, sizeof(dev_info))) { + device_printf(softc->dev, "%s:%d Failed to copy data to user\n", + __FUNCTION__, __LINE__); + return -EFAULT; + } + + return 0; +} + +/* + * IOCTL entry point. + */ +static int +bnxt_mgmt_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, + struct thread *td) +{ + int ret = 0; + + switch(cmd) { + case BNXT_MGMT_OPCODE_GET_DEV_INFO: + ret = bnxt_mgmt_get_dev_info(dev, cmd, data, flag, td); + break; + case BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM: + mtx_lock(&mgmt_lock); + ret = bnxt_mgmt_process_hwrm(dev, cmd, data, flag, td); + mtx_unlock(&mgmt_lock); + break; + default: + printf("%s: Unknown command 0x%lx\n", DRIVER_NAME, cmd); + ret = -EINVAL; + break; + } + + return ret; +} + +static int +bnxt_mgmt_close(struct cdev *dev, int flags, int devtype, struct thread *td) +{ + return (0); +} + +static int +bnxt_mgmt_open(struct cdev *dev, int flags, int devtype, struct thread *td) +{ + return (0); +} + +DEV_MODULE(bnxt_mgmt, bnxt_mgmt_loader, NULL); + diff --git a/sys/dev/bnxt/bnxt_mgmt.h b/sys/dev/bnxt/bnxt_mgmt.h new file mode 100644 index 000000000000..f130ad386809 --- /dev/null +++ b/sys/dev/bnxt/bnxt_mgmt.h @@ -0,0 +1,126 @@ +/* + * Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2022 Broadcom, All Rights Reserved. + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bnxt.h" +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/param.h> +#include <sys/module.h> +#include <sys/kernel.h> +#include <sys/conf.h> +#include <sys/uio.h> +#include <sys/malloc.h> + + +#define DRIVER_NAME "if_bnxt" + +#define BNXT_MGMT_OPCODE_GET_DEV_INFO 0x80000000 +#define BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM 0x80000001 + +#define BNXT_MGMT_MAX_HWRM_REQ_LENGTH HWRM_MAX_REQ_LEN +#define BNXT_MGMT_MAX_HWRM_RESP_LENGTH (512) + +struct bnxt_nic_info { +#define BNXT_MAX_STR 64 + char dev_name[BNXT_MAX_STR]; + char driver_version[BNXT_MAX_STR]; + char driver_name[BNXT_MAX_STR]; + char device_serial_number[64]; + uint32_t mtu; + uint8_t mac[ETHER_ADDR_LEN]; + uint32_t pci_link_speed; + uint32_t pci_link_width; + uint32_t rsvd[4]; +} __packed; + +struct bnxt_pci_info { + uint16_t domain_no; + uint16_t bus_no; + uint16_t device_no; + uint16_t function_no; + uint16_t vendor_id; + uint16_t device_id; + uint16_t sub_system_vendor_id; + uint16_t sub_system_device_id; + uint16_t revision; + uint32_t chip_rev_id; + uint32_t rsvd[2]; +} __packed; + +struct bnxt_dev_info { + struct bnxt_nic_info nic_info; + struct bnxt_pci_info pci_info; +} __packed; + +struct dma_info { + uint64_t data; + uint32_t length; + uint16_t offset; + uint8_t read_or_write; + uint8_t unused; +}; + +struct bnxt_mgmt_fw_msg { + uint64_t usr_req; + uint64_t usr_resp; + uint32_t len_req; + uint32_t len_resp; + uint32_t timeout; + uint32_t num_dma_indications; + struct dma_info dma[0]; +}; + +struct bnxt_mgmt_generic_msg { + uint8_t key; +#define BNXT_LFC_KEY_DOMAIN_NO 1 + uint8_t reserved[3]; + uint32_t value; +}; + +enum bnxt_mgmt_req_type { + BNXT_MGMT_NVM_GET_VAR_REQ = 1, + BNXT_MGMT_NVM_SET_VAR_REQ, + BNXT_MGMT_NVM_FLUSH_REQ, + BNXT_MGMT_GENERIC_HWRM_REQ, +}; + +struct bnxt_mgmt_req_hdr { + uint32_t ver; + uint32_t domain; + uint32_t bus; + uint32_t devfn; + enum bnxt_mgmt_req_type req_type; +}; + +struct bnxt_mgmt_req { + struct bnxt_mgmt_req_hdr hdr; + union { + uint64_t hreq; + } req; +}; + diff --git a/sys/dev/bnxt/if_bnxt.c b/sys/dev/bnxt/if_bnxt.c index 8b26b4d64436..d6cb4d613c96 100644 --- a/sys/dev/bnxt/if_bnxt.c +++ b/sys/dev/bnxt/if_bnxt.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include "bnxt_ioctl.h" #include "bnxt_sysctl.h" #include "hsi_struct_def.h" +#include "bnxt_mgmt.h" /* * PCI Device ID Table @@ -159,6 +160,9 @@ static pci_vendor_info_t bnxt_vendor_info_array[] = * Function prototypes */ +SLIST_HEAD(softc_list, bnxt_softc_list) pf_list; +int bnxt_num_pfs = 0; + static void *bnxt_register(device_t dev); /* Soft queue setup and teardown */ @@ -297,7 +301,7 @@ static driver_t bnxt_iflib_driver = { * iflib shared context */ -#define BNXT_DRIVER_VERSION "1.0.0.2" +#define BNXT_DRIVER_VERSION "2.20.0.1" char bnxt_driver_version[] = BNXT_DRIVER_VERSION; extern struct if_txrx bnxt_txrx; static struct if_shared_ctx bnxt_sctx_init = { @@ -1203,6 +1207,28 @@ static void bnxt_thor_db_nq(void *db_ptr, bool enable_irq) BUS_SPACE_BARRIER_WRITE); } +struct bnxt_softc *bnxt_find_dev(uint32_t domain, uint32_t bus, uint32_t dev_fn, char *dev_name) +{ + struct bnxt_softc_list *sc = NULL; + + SLIST_FOREACH(sc, &pf_list, next) { + /* get the softc reference based on device name */ + if (dev_name && !strncmp(dev_name, iflib_get_ifp(sc->softc->ctx)->if_xname, BNXT_MAX_STR)) { + return sc->softc; + } + /* get the softc reference based on domain,bus,device,function */ + if (!dev_name && + (domain == sc->softc->domain) && + (bus == sc->softc->bus) && + (dev_fn == sc->softc->dev_fn)) { + return sc->softc; + + } + } + + return NULL; +} + /* Device setup and teardown */ static int bnxt_attach_pre(if_ctx_t ctx) @@ -1242,6 +1268,19 @@ bnxt_attach_pre(if_ctx_t ctx) break; } +#define PCI_DEVFN(device, func) ((((device) & 0x1f) << 3) | ((func) & 0x07)) + softc->domain = pci_get_domain(softc->dev); + softc->bus = pci_get_bus(softc->dev); + softc->slot = pci_get_slot(softc->dev); + softc->function = pci_get_function(softc->dev); + softc->dev_fn = PCI_DEVFN(softc->slot, softc->function); + + if (bnxt_num_pfs == 0) + SLIST_INIT(&pf_list); + bnxt_num_pfs++; + softc->list.softc = softc; + SLIST_INSERT_HEAD(&pf_list, &softc->list, next); + pci_enable_busmaster(softc->dev); if (bnxt_pci_mapping(softc)) @@ -1575,6 +1614,8 @@ bnxt_detach(if_ctx_t ctx) struct bnxt_vlan_tag *tmp; int i; + SLIST_REMOVE(&pf_list, &softc->list, bnxt_softc_list, next); + bnxt_num_pfs--; bnxt_wol_config(ctx); bnxt_do_disable_intr(&softc->def_cp_ring); bnxt_free_sysctl_ctx(softc); diff --git a/sys/modules/bnxt/Makefile b/sys/modules/bnxt/Makefile index 861a0b4c4d4a..f27e9934034e 100644 --- a/sys/modules/bnxt/Makefile +++ b/sys/modules/bnxt/Makefile @@ -6,8 +6,9 @@ KMOD = if_bnxt SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h ifdi_if.h SRCS += opt_inet.h opt_inet6.h opt_rss.h SRCS += bnxt_txrx.c if_bnxt.c -SRCS += bnxt_hwrm.c bnxt_hwrm.h -SRCS += bnxt_sysctl.c bnxt_sysctl.h +SRCS += bnxt_hwrm.c +SRCS += bnxt_sysctl.c +SRCS += bnxt_mgmt.c CFLAGS+= -DIFLIB