The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/bnxt/bnxt_mgmt.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Broadcom NetXtreme-C/E network driver.
    3  *
    4  * Copyright (c) 2022 Broadcom, All Rights Reserved.
    5  * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
   17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
   20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   26  * THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include "bnxt_mgmt.h" 
   30 #include "bnxt.h"
   31 #include "bnxt_hwrm.h" 
   32 #include <dev/pci/pcireg.h>
   33 #include <dev/pci/pcivar.h>
   34 #include <sys/endian.h>
   35 #include <sys/lock.h>
   36 
   37 /* Function prototypes */
   38 static d_open_t      bnxt_mgmt_open;
   39 static d_close_t     bnxt_mgmt_close;
   40 static d_ioctl_t     bnxt_mgmt_ioctl;
   41 
   42 /* Character device entry points */
   43 static struct cdevsw bnxt_mgmt_cdevsw = {
   44         .d_version = D_VERSION,
   45         .d_open = bnxt_mgmt_open,
   46         .d_close = bnxt_mgmt_close,
   47         .d_ioctl = bnxt_mgmt_ioctl,
   48         .d_name = "bnxt_mgmt",
   49 };
   50 
   51 /* Global vars */
   52 static struct cdev *bnxt_mgmt_dev;
   53 struct mtx              mgmt_lock;
   54 
   55 MALLOC_DEFINE(M_BNXT, "bnxt_mgmt_buffer", "buffer for bnxt_mgmt module");
   56 
   57 /*
   58  * This function is called by the kld[un]load(2) system calls to
   59  * determine what actions to take when a module is loaded or unloaded.
   60  */
   61 static int
   62 bnxt_mgmt_loader(struct module *m, int what, void *arg)
   63 {
   64         int error = 0;
   65 
   66         switch (what) {
   67         case MOD_LOAD:
   68                 error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
   69                     &bnxt_mgmt_dev,
   70                     &bnxt_mgmt_cdevsw,
   71                     0,
   72                     UID_ROOT,
   73                     GID_WHEEL,
   74                     0600,
   75                     "bnxt_mgmt");
   76                 if (error != 0) {
   77                         printf("%s: %s:%s:%d Failed to create the"
   78                                "bnxt_mgmt device node\n", DRIVER_NAME,
   79                                __FILE__, __FUNCTION__, __LINE__);
   80                         return (error);
   81                 }
   82 
   83                 mtx_init(&mgmt_lock, "BNXT MGMT Lock", NULL, MTX_DEF);
   84 
   85                 break;
   86         case MOD_UNLOAD:
   87                 mtx_destroy(&mgmt_lock);
   88                 destroy_dev(bnxt_mgmt_dev);
   89                 break;
   90         default:
   91                 error = EOPNOTSUPP;
   92                 break;
   93         }
   94 
   95         return (error);
   96 }
   97 
   98 static int
   99 bnxt_mgmt_process_hwrm(struct cdev *dev, u_long cmd, caddr_t data,
  100                        int flag, struct thread *td)
  101 {
  102         struct bnxt_softc *softc = NULL;
  103         struct bnxt_mgmt_req mgmt_req = {};
  104         struct bnxt_mgmt_fw_msg msg_temp, *msg, *msg2 = NULL;
  105         struct iflib_dma_info dma_data = {};
  106         void *user_ptr, *req, *resp;
  107         int ret = 0;
  108         uint16_t num_ind = 0;
  109 
  110         memcpy(&user_ptr, data, sizeof(user_ptr));
  111         if (copyin(user_ptr, &mgmt_req, sizeof(struct bnxt_mgmt_req))) {        
  112                 printf("%s: %s:%d Failed to copy data from user\n",
  113                         DRIVER_NAME, __FUNCTION__, __LINE__);
  114                 return -EFAULT;
  115         }
  116         softc = bnxt_find_dev(mgmt_req.hdr.domain, mgmt_req.hdr.bus,
  117                               mgmt_req.hdr.devfn, NULL);
  118         if (!softc) {
  119                 printf("%s: %s:%d unable to find softc reference\n",
  120                         DRIVER_NAME, __FUNCTION__, __LINE__);
  121                 return -ENODEV;
  122         }
  123 
  124         if (copyin((void*)mgmt_req.req.hreq, &msg_temp, sizeof(msg_temp))) {
  125                 device_printf(softc->dev, "%s:%d Failed to copy data from user\n",
  126                               __FUNCTION__, __LINE__);
  127                 return -EFAULT;
  128         }
  129 
  130         if (msg_temp.len_req > BNXT_MGMT_MAX_HWRM_REQ_LENGTH ||
  131                         msg_temp.len_resp > BNXT_MGMT_MAX_HWRM_RESP_LENGTH) {
  132                 device_printf(softc->dev, "%s:%d Invalid length\n", 
  133                               __FUNCTION__, __LINE__);
  134                 return -EINVAL;
  135         }
  136 
  137         if (msg_temp.num_dma_indications > 1) {
  138                 device_printf(softc->dev, "%s:%d Max num_dma_indications "
  139                               "supported is 1 \n", __FUNCTION__, __LINE__);
  140                 return -EINVAL;
  141         }
  142 
  143         req = malloc(msg_temp.len_req, M_BNXT, M_WAITOK | M_ZERO);
  144         if(!req) {
  145                 device_printf(softc->dev, "%s:%d Memory allocation failed",
  146                               __FUNCTION__, __LINE__);
  147                 return -ENOMEM;
  148         }
  149         
  150         resp = malloc(msg_temp.len_resp, M_BNXT, M_WAITOK | M_ZERO);
  151         if(!resp) {
  152                 device_printf(softc->dev, "%s:%d Memory allocation failed",
  153                               __FUNCTION__, __LINE__);
  154                 ret = -ENOMEM;
  155                 goto end;
  156         }
  157 
  158         if (copyin((void *)msg_temp.usr_req, req, msg_temp.len_req)) {
  159                 device_printf(softc->dev, "%s:%d Failed to copy data from user\n",
  160                               __FUNCTION__, __LINE__);
  161                 ret = -EFAULT;
  162                 goto end;
  163         }
  164 
  165         msg = &msg_temp;
  166         num_ind = msg_temp.num_dma_indications;
  167         if (num_ind) {
  168                 int size;
  169                 void *dma_ptr;
  170                 uint64_t *dmap;
  171 
  172                 size = sizeof(struct bnxt_mgmt_fw_msg) + 
  173                              (num_ind * sizeof(struct dma_info));
  174 
  175                 msg2 = malloc(size, M_BNXT, M_WAITOK | M_ZERO);
  176                 if(!msg2) {
  177                         device_printf(softc->dev, "%s:%d Memory allocation failed",
  178                                       __FUNCTION__, __LINE__);
  179                         ret = -ENOMEM;
  180                         goto end;
  181                 }
  182 
  183                 if (copyin((void *)mgmt_req.req.hreq, msg2, size)) { 
  184                         device_printf(softc->dev, "%s:%d Failed to copy"
  185                                       "data from user\n", __FUNCTION__, __LINE__);
  186                         ret = -EFAULT;
  187                         goto end;
  188                 }
  189                 msg = msg2;
  190                 
  191                 ret = iflib_dma_alloc(softc->ctx, msg->dma[0].length, &dma_data,
  192                                     BUS_DMA_NOWAIT);
  193                 if (ret) {
  194                         device_printf(softc->dev, "%s:%d iflib_dma_alloc"
  195                                       "failed with ret = 0x%x\n", __FUNCTION__,
  196                                       __LINE__, ret);
  197                         ret = -ENOMEM;
  198                         goto end;
  199                 }
  200 
  201                 if (!(msg->dma[0].read_or_write)) {
  202                         if (copyin((void *)msg->dma[0].data, 
  203                                    dma_data.idi_vaddr, 
  204                                    msg->dma[0].length)) {
  205                                 device_printf(softc->dev, "%s:%d Failed to copy"
  206                                               "data from user\n", __FUNCTION__,
  207                                               __LINE__);
  208                                 ret = -EFAULT;
  209                                 goto end;
  210                         }
  211                 }
  212                 dma_ptr = (void *) ((uint64_t) req + msg->dma[0].offset);
  213                 dmap = dma_ptr;
  214                 *dmap = htole64(dma_data.idi_paddr);
  215         }
  216                 
  217         ret = bnxt_hwrm_passthrough(softc, req, msg->len_req, resp, msg->len_resp, msg->timeout);
  218         if(ret)
  219                 goto end;
  220         
  221         if (num_ind) {
  222                 if ((msg->dma[0].read_or_write)) {
  223                         if (copyout(dma_data.idi_vaddr, 
  224                                     (void *)msg->dma[0].data, 
  225                                     msg->dma[0].length)) {
  226                                 device_printf(softc->dev, "%s:%d Failed to copy data"
  227                                               "to user\n", __FUNCTION__, __LINE__);
  228                                 ret = -EFAULT;
  229                                 goto end;
  230                         }
  231                 }
  232         }
  233         
  234         if (copyout(resp, (void *) msg->usr_resp, msg->len_resp)) {
  235                 device_printf(softc->dev, "%s:%d Failed to copy response to user\n",
  236                               __FUNCTION__, __LINE__);
  237                 ret = -EFAULT;
  238                 goto end;
  239         }
  240 
  241 end:
  242         if (req)
  243                 free(req, M_BNXT);
  244         if (resp)
  245                 free(resp, M_BNXT);
  246         if (msg2)
  247                 free(msg2, M_BNXT);
  248         if (dma_data.idi_paddr)
  249                 iflib_dma_free(&dma_data);
  250         return ret;
  251 }
  252 
  253 static int
  254 bnxt_mgmt_get_dev_info(struct cdev *dev, u_long cmd, caddr_t data,
  255                        int flag, struct thread *td)
  256 {
  257         struct bnxt_softc *softc = NULL;
  258         struct bnxt_dev_info dev_info;
  259         void *user_ptr;
  260         uint32_t dev_sn_lo, dev_sn_hi;
  261         int dev_sn_offset = 0;
  262         char dsn[16];
  263         uint16_t lnk;
  264         int capreg;
  265 
  266         memcpy(&user_ptr, data, sizeof(user_ptr));
  267         if (copyin(user_ptr, &dev_info, sizeof(dev_info))) {
  268                 printf("%s: %s:%d Failed to copy data from user\n",
  269                         DRIVER_NAME, __FUNCTION__, __LINE__);
  270                 return -EFAULT;
  271         }
  272         
  273         softc = bnxt_find_dev(0, 0, 0, dev_info.nic_info.dev_name);
  274         if (!softc) {
  275                 printf("%s: %s:%d unable to find softc reference\n",
  276                         DRIVER_NAME, __FUNCTION__, __LINE__);
  277                 return -ENODEV;
  278         }
  279 
  280         strncpy(dev_info.nic_info.driver_version, bnxt_driver_version, 64);
  281         strncpy(dev_info.nic_info.driver_name, device_get_name(softc->dev), 64);
  282         dev_info.pci_info.domain_no = softc->domain;
  283         dev_info.pci_info.bus_no = softc->bus;
  284         dev_info.pci_info.device_no = softc->slot;
  285         dev_info.pci_info.function_no = softc->function;
  286         dev_info.pci_info.vendor_id = pci_get_vendor(softc->dev);
  287         dev_info.pci_info.device_id = pci_get_device(softc->dev);
  288         dev_info.pci_info.sub_system_vendor_id = pci_get_subvendor(softc->dev);
  289         dev_info.pci_info.sub_system_device_id = pci_get_subdevice(softc->dev);
  290         dev_info.pci_info.revision = pci_read_config(softc->dev, PCIR_REVID, 1);
  291         dev_info.pci_info.chip_rev_id = (dev_info.pci_info.device_id << 16);
  292         dev_info.pci_info.chip_rev_id |= dev_info.pci_info.revision;
  293         if (pci_find_extcap(softc->dev, PCIZ_SERNUM, &dev_sn_offset)) {
  294                 device_printf(softc->dev, "%s:%d device serial number is not found"
  295                               "or not supported\n", __FUNCTION__, __LINE__);
  296         } else {
  297                 dev_sn_lo = pci_read_config(softc->dev, dev_sn_offset + 4, 4);
  298                 dev_sn_hi = pci_read_config(softc->dev, dev_sn_offset + 8, 4);
  299                 snprintf(dsn, sizeof(dsn), "%02x%02x%02x%02x%02x%02x%02x%02x",
  300                          (dev_sn_lo & 0x000000FF),
  301                          (dev_sn_lo >> 8) & 0x0000FF,
  302                          (dev_sn_lo >> 16) & 0x00FF,
  303                          (dev_sn_lo >> 24 ) & 0xFF,
  304                          (dev_sn_hi & 0x000000FF),
  305                          (dev_sn_hi >> 8) & 0x0000FF,
  306                          (dev_sn_hi >> 16) & 0x00FF,
  307                          (dev_sn_hi >> 24 ) & 0xFF);
  308                 strncpy(dev_info.nic_info.device_serial_number, dsn, sizeof(dsn));
  309         }
  310         
  311         if_t ifp = iflib_get_ifp(softc->ctx);
  312         dev_info.nic_info.mtu = if_getmtu(ifp);
  313         memcpy(dev_info.nic_info.mac, softc->func.mac_addr, ETHER_ADDR_LEN);
  314         
  315         if (pci_find_cap(softc->dev, PCIY_EXPRESS, &capreg)) {
  316                 device_printf(softc->dev, "%s:%d pci link capability is not found"
  317                               "or not supported\n", __FUNCTION__, __LINE__);
  318         } else {
  319                 lnk = pci_read_config(softc->dev, capreg + PCIER_LINK_STA, 2);
  320                 dev_info.nic_info.pci_link_speed = (lnk & PCIEM_LINK_STA_SPEED);
  321                 dev_info.nic_info.pci_link_width = (lnk & PCIEM_LINK_STA_WIDTH) >> 4;
  322         }
  323         
  324         if (copyout(&dev_info, user_ptr, sizeof(dev_info))) {
  325                 device_printf(softc->dev, "%s:%d Failed to copy data to user\n",
  326                               __FUNCTION__, __LINE__);
  327                 return -EFAULT;
  328         }
  329 
  330         return 0;
  331 }
  332 
  333 /*
  334  * IOCTL entry point.
  335  */
  336 static int
  337 bnxt_mgmt_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
  338                 struct thread *td)
  339 {
  340         int ret = 0;
  341         
  342         switch(cmd) {
  343         case BNXT_MGMT_OPCODE_GET_DEV_INFO:
  344                 ret = bnxt_mgmt_get_dev_info(dev, cmd, data, flag, td);
  345                 break;
  346         case BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM:
  347                 mtx_lock(&mgmt_lock);
  348                 ret = bnxt_mgmt_process_hwrm(dev, cmd, data, flag, td); 
  349                 mtx_unlock(&mgmt_lock);
  350                 break;
  351         default:
  352                 printf("%s: Unknown command 0x%lx\n", DRIVER_NAME, cmd);
  353                 ret = -EINVAL;
  354                 break;
  355         }
  356 
  357         return ret;             
  358 }
  359 
  360 static int
  361 bnxt_mgmt_close(struct cdev *dev, int flags, int devtype, struct thread *td)
  362 {
  363         return (0);
  364 }
  365 
  366 static int
  367 bnxt_mgmt_open(struct cdev *dev, int flags, int devtype, struct thread *td)
  368 {
  369         return (0);
  370 }
  371 
  372 DEV_MODULE(bnxt_mgmt, bnxt_mgmt_loader, NULL);
  373 

Cache object: 7e9323e50849138cc09b6289d01618c2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.