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/qlxgbe/ql_os.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2013-2016 Qlogic Corporation
    5  * All rights reserved.
    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  *
   11  *  1. Redistributions of source code must retain the above copyright
   12  *     notice, this list of conditions and the following disclaimer.
   13  *  2. Redistributions in binary form must reproduce the above copyright
   14  *     notice, this list of conditions and the following disclaimer in the
   15  *     documentation and/or other materials provided with the distribution.
   16  *
   17  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   18  *  and ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   21  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   22  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   25  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27  *  POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 /*
   31  * File: ql_os.c
   32  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD$");
   37 
   38 #include "ql_os.h"
   39 #include "ql_hw.h"
   40 #include "ql_def.h"
   41 #include "ql_inline.h"
   42 #include "ql_ver.h"
   43 #include "ql_glbl.h"
   44 #include "ql_dbg.h"
   45 #include <sys/smp.h>
   46 
   47 /*
   48  * Some PCI Configuration Space Related Defines
   49  */
   50 
   51 #ifndef PCI_VENDOR_QLOGIC
   52 #define PCI_VENDOR_QLOGIC       0x1077
   53 #endif
   54 
   55 #ifndef PCI_PRODUCT_QLOGIC_ISP8030
   56 #define PCI_PRODUCT_QLOGIC_ISP8030      0x8030
   57 #endif
   58 
   59 #define PCI_QLOGIC_ISP8030 \
   60         ((PCI_PRODUCT_QLOGIC_ISP8030 << 16) | PCI_VENDOR_QLOGIC)
   61 
   62 /*
   63  * static functions
   64  */
   65 static int qla_alloc_parent_dma_tag(qla_host_t *ha);
   66 static void qla_free_parent_dma_tag(qla_host_t *ha);
   67 static int qla_alloc_xmt_bufs(qla_host_t *ha);
   68 static void qla_free_xmt_bufs(qla_host_t *ha);
   69 static int qla_alloc_rcv_bufs(qla_host_t *ha);
   70 static void qla_free_rcv_bufs(qla_host_t *ha);
   71 static void qla_clear_tx_buf(qla_host_t *ha, qla_tx_buf_t *txb);
   72 
   73 static void qla_init_ifnet(device_t dev, qla_host_t *ha);
   74 static int qla_sysctl_get_link_status(SYSCTL_HANDLER_ARGS);
   75 static void qla_release(qla_host_t *ha);
   76 static void qla_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs,
   77                 int error);
   78 static void qla_stop(qla_host_t *ha);
   79 static void qla_get_peer(qla_host_t *ha);
   80 static void qla_error_recovery(void *context, int pending);
   81 static void qla_async_event(void *context, int pending);
   82 static void qla_stats(void *context, int pending);
   83 static int qla_send(qla_host_t *ha, struct mbuf **m_headp, uint32_t txr_idx,
   84                 uint32_t iscsi_pdu);
   85 
   86 /*
   87  * Hooks to the Operating Systems
   88  */
   89 static int qla_pci_probe (device_t);
   90 static int qla_pci_attach (device_t);
   91 static int qla_pci_detach (device_t);
   92 
   93 static void qla_init(void *arg);
   94 static int qla_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
   95 static int qla_media_change(struct ifnet *ifp);
   96 static void qla_media_status(struct ifnet *ifp, struct ifmediareq *ifmr);
   97 
   98 static int qla_transmit(struct ifnet *ifp, struct mbuf  *mp);
   99 static void qla_qflush(struct ifnet *ifp);
  100 static int qla_alloc_tx_br(qla_host_t *ha, qla_tx_fp_t *tx_fp);
  101 static void qla_free_tx_br(qla_host_t *ha, qla_tx_fp_t *tx_fp);
  102 static int qla_create_fp_taskqueues(qla_host_t *ha);
  103 static void qla_destroy_fp_taskqueues(qla_host_t *ha);
  104 static void qla_drain_fp_taskqueues(qla_host_t *ha);
  105 
  106 static device_method_t qla_pci_methods[] = {
  107         /* Device interface */
  108         DEVMETHOD(device_probe, qla_pci_probe),
  109         DEVMETHOD(device_attach, qla_pci_attach),
  110         DEVMETHOD(device_detach, qla_pci_detach),
  111         { 0, 0 }
  112 };
  113 
  114 static driver_t qla_pci_driver = {
  115         "ql", qla_pci_methods, sizeof (qla_host_t),
  116 };
  117 
  118 DRIVER_MODULE(qla83xx, pci, qla_pci_driver, 0, 0);
  119 
  120 MODULE_DEPEND(qla83xx, pci, 1, 1, 1);
  121 MODULE_DEPEND(qla83xx, ether, 1, 1, 1);
  122 
  123 MALLOC_DEFINE(M_QLA83XXBUF, "qla83xxbuf", "Buffers for qla83xx driver");
  124 
  125 #define QL_STD_REPLENISH_THRES          0
  126 #define QL_JUMBO_REPLENISH_THRES        32
  127 
  128 static char dev_str[64];
  129 static char ver_str[64];
  130 
  131 /*
  132  * Name:        qla_pci_probe
  133  * Function:    Validate the PCI device to be a QLA80XX device
  134  */
  135 static int
  136 qla_pci_probe(device_t dev)
  137 {
  138         switch ((pci_get_device(dev) << 16) | (pci_get_vendor(dev))) {
  139         case PCI_QLOGIC_ISP8030:
  140                 snprintf(dev_str, sizeof(dev_str), "%s v%d.%d.%d",
  141                         "Qlogic ISP 83xx PCI CNA Adapter-Ethernet Function",
  142                         QLA_VERSION_MAJOR, QLA_VERSION_MINOR,
  143                         QLA_VERSION_BUILD);
  144                 snprintf(ver_str, sizeof(ver_str), "v%d.%d.%d",
  145                         QLA_VERSION_MAJOR, QLA_VERSION_MINOR,
  146                         QLA_VERSION_BUILD);
  147                 device_set_desc(dev, dev_str);
  148                 break;
  149         default:
  150                 return (ENXIO);
  151         }
  152 
  153         if (bootverbose)
  154                 printf("%s: %s\n ", __func__, dev_str);
  155 
  156         return (BUS_PROBE_DEFAULT);
  157 }
  158 
  159 static void
  160 qla_add_sysctls(qla_host_t *ha)
  161 {
  162         device_t dev = ha->pci_dev;
  163 
  164         SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev),
  165                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  166                 OID_AUTO, "version", CTLFLAG_RD,
  167                 ver_str, 0, "Driver Version");
  168 
  169         SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev),
  170                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  171                 OID_AUTO, "fw_version", CTLFLAG_RD,
  172                 ha->fw_ver_str, 0, "firmware version");
  173 
  174         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
  175             SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
  176             "link_status", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 
  177             (void *)ha, 0, qla_sysctl_get_link_status, "I", "Link Status");
  178 
  179         ha->dbg_level = 0;
  180         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
  181                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  182                 OID_AUTO, "debug", CTLFLAG_RW,
  183                 &ha->dbg_level, ha->dbg_level, "Debug Level");
  184 
  185         ha->enable_minidump = 1;
  186         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
  187                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  188                 OID_AUTO, "enable_minidump", CTLFLAG_RW,
  189                 &ha->enable_minidump, ha->enable_minidump,
  190                 "Minidump retrival prior to error recovery "
  191                 "is enabled only when this is set");
  192 
  193         ha->enable_driverstate_dump = 1;
  194         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
  195                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  196                 OID_AUTO, "enable_driverstate_dump", CTLFLAG_RW,
  197                 &ha->enable_driverstate_dump, ha->enable_driverstate_dump,
  198                 "Driver State retrival prior to error recovery "
  199                 "is enabled only when this is set");
  200 
  201         ha->enable_error_recovery = 1;
  202         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
  203                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  204                 OID_AUTO, "enable_error_recovery", CTLFLAG_RW,
  205                 &ha->enable_error_recovery, ha->enable_error_recovery,
  206                 "when set error recovery is enabled on fatal errors "
  207                 "otherwise the port is turned offline");
  208 
  209         ha->ms_delay_after_init = 1000;
  210         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
  211                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  212                 OID_AUTO, "ms_delay_after_init", CTLFLAG_RW,
  213                 &ha->ms_delay_after_init, ha->ms_delay_after_init,
  214                 "millisecond delay after hw_init");
  215 
  216         ha->std_replenish = QL_STD_REPLENISH_THRES;
  217         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
  218                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  219                 OID_AUTO, "std_replenish", CTLFLAG_RW,
  220                 &ha->std_replenish, ha->std_replenish,
  221                 "Threshold for Replenishing Standard Frames");
  222 
  223         SYSCTL_ADD_QUAD(device_get_sysctl_ctx(dev),
  224                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  225                 OID_AUTO, "ipv4_lro",
  226                 CTLFLAG_RD, &ha->ipv4_lro,
  227                 "number of ipv4 lro completions");
  228 
  229         SYSCTL_ADD_QUAD(device_get_sysctl_ctx(dev),
  230                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  231                 OID_AUTO, "ipv6_lro",
  232                 CTLFLAG_RD, &ha->ipv6_lro,
  233                 "number of ipv6 lro completions");
  234 
  235         SYSCTL_ADD_QUAD(device_get_sysctl_ctx(dev),
  236                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  237                 OID_AUTO, "tx_tso_frames",
  238                 CTLFLAG_RD, &ha->tx_tso_frames,
  239                 "number of Tx TSO Frames");
  240 
  241         SYSCTL_ADD_QUAD(device_get_sysctl_ctx(dev),
  242                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  243                 OID_AUTO, "hw_vlan_tx_frames",
  244                 CTLFLAG_RD, &ha->hw_vlan_tx_frames,
  245                 "number of Tx VLAN Frames");
  246 
  247         SYSCTL_ADD_QUAD(device_get_sysctl_ctx(dev),
  248                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
  249                 OID_AUTO, "hw_lock_failed",
  250                 CTLFLAG_RD, &ha->hw_lock_failed,
  251                 "number of hw_lock failures");
  252 
  253         return;
  254 }
  255 
  256 static void
  257 qla_watchdog(void *arg)
  258 {
  259         qla_host_t *ha = arg;
  260         struct ifnet *ifp;
  261 
  262         ifp = ha->ifp;
  263 
  264         if (ha->qla_watchdog_exit) {
  265                 ha->qla_watchdog_exited = 1;
  266                 return;
  267         }
  268         ha->qla_watchdog_exited = 0;
  269 
  270         if (!ha->qla_watchdog_pause) {
  271                 if (!ha->offline &&
  272                         (ql_hw_check_health(ha) || ha->qla_initiate_recovery ||
  273                         (ha->msg_from_peer == QL_PEER_MSG_RESET))) {
  274                         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
  275                         ql_update_link_state(ha);
  276 
  277                         if (ha->enable_error_recovery) {
  278                                 ha->qla_watchdog_paused = 1;
  279                                 ha->qla_watchdog_pause = 1;
  280                                 ha->err_inject = 0;
  281                                 device_printf(ha->pci_dev,
  282                                         "%s: taskqueue_enqueue(err_task) \n",
  283                                         __func__);
  284                                 taskqueue_enqueue(ha->err_tq, &ha->err_task);
  285                         } else {
  286                                 if (ifp != NULL)
  287                                         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
  288                                 ha->offline = 1;
  289                         }
  290                         return;
  291 
  292                 } else {
  293                         if (ha->qla_interface_up) {
  294                                 ha->watchdog_ticks++;
  295 
  296                                 if (ha->watchdog_ticks > 1000)
  297                                         ha->watchdog_ticks = 0;
  298 
  299                                 if (!ha->watchdog_ticks && QL_RUNNING(ifp)) {
  300                                         taskqueue_enqueue(ha->stats_tq,
  301                                                 &ha->stats_task);
  302                                 }
  303 
  304                                 if (ha->async_event) {
  305                                         taskqueue_enqueue(ha->async_event_tq,
  306                                                 &ha->async_event_task);
  307                                 }
  308                         }
  309                         ha->qla_watchdog_paused = 0;
  310                 }
  311         } else {
  312                 ha->qla_watchdog_paused = 1;
  313         }
  314 
  315         callout_reset(&ha->tx_callout, QLA_WATCHDOG_CALLOUT_TICKS,
  316                 qla_watchdog, ha);
  317 }
  318 
  319 /*
  320  * Name:        qla_pci_attach
  321  * Function:    attaches the device to the operating system
  322  */
  323 static int
  324 qla_pci_attach(device_t dev)
  325 {
  326         qla_host_t *ha = NULL;
  327         uint32_t rsrc_len;
  328         int i;
  329         uint32_t num_rcvq = 0;
  330 
  331         if ((ha = device_get_softc(dev)) == NULL) {
  332                 device_printf(dev, "cannot get softc\n");
  333                 return (ENOMEM);
  334         }
  335 
  336         memset(ha, 0, sizeof (qla_host_t));
  337 
  338         if (pci_get_device(dev) != PCI_PRODUCT_QLOGIC_ISP8030) {
  339                 device_printf(dev, "device is not ISP8030\n");
  340                 return (ENXIO);
  341         }
  342 
  343         ha->pci_func = pci_get_function(dev) & 0x1;
  344 
  345         ha->pci_dev = dev;
  346 
  347         pci_enable_busmaster(dev);
  348 
  349         ha->reg_rid = PCIR_BAR(0);
  350         ha->pci_reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &ha->reg_rid,
  351                                 RF_ACTIVE);
  352 
  353         if (ha->pci_reg == NULL) {
  354                 device_printf(dev, "unable to map any ports\n");
  355                 goto qla_pci_attach_err;
  356         }
  357 
  358         rsrc_len = (uint32_t) bus_get_resource_count(dev, SYS_RES_MEMORY,
  359                                         ha->reg_rid);
  360 
  361         mtx_init(&ha->hw_lock, "qla83xx_hw_lock", MTX_NETWORK_LOCK, MTX_DEF);
  362         mtx_init(&ha->sp_log_lock, "qla83xx_sp_log_lock", MTX_NETWORK_LOCK, MTX_DEF);
  363         ha->flags.lock_init = 1;
  364 
  365         qla_add_sysctls(ha);
  366 
  367         ha->hw.num_sds_rings = MAX_SDS_RINGS;
  368         ha->hw.num_rds_rings = MAX_RDS_RINGS;
  369         ha->hw.num_tx_rings = NUM_TX_RINGS;
  370 
  371         ha->reg_rid1 = PCIR_BAR(2);
  372         ha->pci_reg1 = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  373                         &ha->reg_rid1, RF_ACTIVE);
  374 
  375         ha->msix_count = pci_msix_count(dev);
  376 
  377         if (ha->msix_count < 1 ) {
  378                 device_printf(dev, "%s: msix_count[%d] not enough\n", __func__,
  379                         ha->msix_count);
  380                 goto qla_pci_attach_err;
  381         }
  382 
  383         if (ha->msix_count < (ha->hw.num_sds_rings + 1)) {
  384                 ha->hw.num_sds_rings = ha->msix_count - 1;
  385         }
  386 
  387         QL_DPRINT2(ha, (dev, "%s: ha %p pci_func 0x%x rsrc_count 0x%08x"
  388                 " msix_count 0x%x pci_reg %p pci_reg1 %p\n", __func__, ha,
  389                 ha->pci_func, rsrc_len, ha->msix_count, ha->pci_reg,
  390                 ha->pci_reg1));
  391 
  392         /* initialize hardware */
  393         if (ql_init_hw(ha)) {
  394                 device_printf(dev, "%s: ql_init_hw failed\n", __func__);
  395                 goto qla_pci_attach_err;
  396         }
  397 
  398         device_printf(dev, "%s: firmware[%d.%d.%d.%d]\n", __func__,
  399                 ha->fw_ver_major, ha->fw_ver_minor, ha->fw_ver_sub,
  400                 ha->fw_ver_build);
  401         snprintf(ha->fw_ver_str, sizeof(ha->fw_ver_str), "%d.%d.%d.%d",
  402                         ha->fw_ver_major, ha->fw_ver_minor, ha->fw_ver_sub,
  403                         ha->fw_ver_build);
  404 
  405         if (qla_get_nic_partition(ha, NULL, &num_rcvq)) {
  406                 device_printf(dev, "%s: qla_get_nic_partition failed\n",
  407                         __func__);
  408                 goto qla_pci_attach_err;
  409         }
  410         device_printf(dev, "%s: ha %p pci_func 0x%x rsrc_count 0x%08x"
  411                 " msix_count 0x%x pci_reg %p pci_reg1 %p num_rcvq = %d\n",
  412                 __func__, ha, ha->pci_func, rsrc_len, ha->msix_count,
  413                 ha->pci_reg, ha->pci_reg1, num_rcvq);
  414 
  415         if ((ha->msix_count  < 64) || (num_rcvq != 32)) {
  416                 if (ha->hw.num_sds_rings > 15) {
  417                         ha->hw.num_sds_rings = 15;
  418                 }
  419         }
  420 
  421         ha->hw.num_rds_rings = ha->hw.num_sds_rings;
  422         ha->hw.num_tx_rings = ha->hw.num_sds_rings;
  423 
  424 #ifdef QL_ENABLE_ISCSI_TLV
  425         ha->hw.num_tx_rings = ha->hw.num_sds_rings * 2;
  426 #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
  427 
  428         ql_hw_add_sysctls(ha);
  429 
  430         ha->msix_count = ha->hw.num_sds_rings + 1;
  431 
  432         if (pci_alloc_msix(dev, &ha->msix_count)) {
  433                 device_printf(dev, "%s: pci_alloc_msi[%d] failed\n", __func__,
  434                         ha->msix_count);
  435                 ha->msix_count = 0;
  436                 goto qla_pci_attach_err;
  437         }
  438 
  439         ha->mbx_irq_rid = 1;
  440         ha->mbx_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
  441                                 &ha->mbx_irq_rid,
  442                                 (RF_ACTIVE | RF_SHAREABLE));
  443         if (ha->mbx_irq == NULL) {
  444                 device_printf(dev, "could not allocate mbx interrupt\n");
  445                 goto qla_pci_attach_err;
  446         }
  447         if (bus_setup_intr(dev, ha->mbx_irq, (INTR_TYPE_NET | INTR_MPSAFE),
  448                 NULL, ql_mbx_isr, ha, &ha->mbx_handle)) {
  449                 device_printf(dev, "could not setup mbx interrupt\n");
  450                 goto qla_pci_attach_err;
  451         }
  452 
  453         for (i = 0; i < ha->hw.num_sds_rings; i++) {
  454                 ha->irq_vec[i].sds_idx = i;
  455                 ha->irq_vec[i].ha = ha;
  456                 ha->irq_vec[i].irq_rid = 2 + i;
  457 
  458                 ha->irq_vec[i].irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
  459                                 &ha->irq_vec[i].irq_rid,
  460                                 (RF_ACTIVE | RF_SHAREABLE));
  461 
  462                 if (ha->irq_vec[i].irq == NULL) {
  463                         device_printf(dev, "could not allocate interrupt\n");
  464                         goto qla_pci_attach_err;
  465                 }
  466                 if (bus_setup_intr(dev, ha->irq_vec[i].irq,
  467                         (INTR_TYPE_NET | INTR_MPSAFE),
  468                         NULL, ql_isr, &ha->irq_vec[i],
  469                         &ha->irq_vec[i].handle)) {
  470                         device_printf(dev, "could not setup interrupt\n");
  471                         goto qla_pci_attach_err;
  472                 }
  473 
  474                 ha->tx_fp[i].ha = ha;
  475                 ha->tx_fp[i].txr_idx = i;
  476 
  477                 if (qla_alloc_tx_br(ha, &ha->tx_fp[i])) {
  478                         device_printf(dev, "%s: could not allocate tx_br[%d]\n",
  479                                 __func__, i);
  480                         goto qla_pci_attach_err;
  481                 }
  482         }
  483 
  484         if (qla_create_fp_taskqueues(ha) != 0)
  485                 goto qla_pci_attach_err;
  486 
  487         printf("%s: mp__ncpus %d sds %d rds %d msi-x %d\n", __func__, mp_ncpus,
  488                 ha->hw.num_sds_rings, ha->hw.num_rds_rings, ha->msix_count);
  489 
  490         ql_read_mac_addr(ha);
  491 
  492         /* allocate parent dma tag */
  493         if (qla_alloc_parent_dma_tag(ha)) {
  494                 device_printf(dev, "%s: qla_alloc_parent_dma_tag failed\n",
  495                         __func__);
  496                 goto qla_pci_attach_err;
  497         }
  498 
  499         /* alloc all dma buffers */
  500         if (ql_alloc_dma(ha)) {
  501                 device_printf(dev, "%s: ql_alloc_dma failed\n", __func__);
  502                 goto qla_pci_attach_err;
  503         }
  504         qla_get_peer(ha);
  505 
  506         if (ql_minidump_init(ha) != 0) {
  507                 device_printf(dev, "%s: ql_minidump_init failed\n", __func__);
  508                 goto qla_pci_attach_err;
  509         }
  510         ql_alloc_drvr_state_buffer(ha);
  511         ql_alloc_sp_log_buffer(ha);
  512         /* create the o.s ethernet interface */
  513         qla_init_ifnet(dev, ha);
  514 
  515         ha->flags.qla_watchdog_active = 1;
  516         ha->qla_watchdog_pause = 0;
  517 
  518         callout_init(&ha->tx_callout, TRUE);
  519         ha->flags.qla_callout_init = 1;
  520 
  521         /* create ioctl device interface */
  522         if (ql_make_cdev(ha)) {
  523                 device_printf(dev, "%s: ql_make_cdev failed\n", __func__);
  524                 goto qla_pci_attach_err;
  525         }
  526 
  527         callout_reset(&ha->tx_callout, QLA_WATCHDOG_CALLOUT_TICKS,
  528                 qla_watchdog, ha);
  529 
  530         TASK_INIT(&ha->err_task, 0, qla_error_recovery, ha);
  531         ha->err_tq = taskqueue_create("qla_errq", M_NOWAIT,
  532                         taskqueue_thread_enqueue, &ha->err_tq);
  533         taskqueue_start_threads(&ha->err_tq, 1, PI_NET, "%s errq",
  534                 device_get_nameunit(ha->pci_dev));
  535 
  536         TASK_INIT(&ha->async_event_task, 0, qla_async_event, ha);
  537         ha->async_event_tq = taskqueue_create("qla_asyncq", M_NOWAIT,
  538                         taskqueue_thread_enqueue, &ha->async_event_tq);
  539         taskqueue_start_threads(&ha->async_event_tq, 1, PI_NET, "%s asyncq",
  540                 device_get_nameunit(ha->pci_dev));
  541 
  542         TASK_INIT(&ha->stats_task, 0, qla_stats, ha);
  543         ha->stats_tq = taskqueue_create("qla_statsq", M_NOWAIT,
  544                         taskqueue_thread_enqueue, &ha->stats_tq);
  545         taskqueue_start_threads(&ha->stats_tq, 1, PI_NET, "%s taskq",
  546                 device_get_nameunit(ha->pci_dev));
  547 
  548         QL_DPRINT2(ha, (dev, "%s: exit 0\n", __func__));
  549         return (0);
  550 
  551 qla_pci_attach_err:
  552 
  553         qla_release(ha);
  554 
  555         if (ha->flags.lock_init) {
  556                 mtx_destroy(&ha->hw_lock);
  557                 mtx_destroy(&ha->sp_log_lock);
  558         }
  559 
  560         QL_DPRINT2(ha, (dev, "%s: exit ENXIO\n", __func__));
  561         return (ENXIO);
  562 }
  563 
  564 /*
  565  * Name:        qla_pci_detach
  566  * Function:    Unhooks the device from the operating system
  567  */
  568 static int
  569 qla_pci_detach(device_t dev)
  570 {
  571         qla_host_t *ha = NULL;
  572         struct ifnet *ifp;
  573 
  574         if ((ha = device_get_softc(dev)) == NULL) {
  575                 device_printf(dev, "cannot get softc\n");
  576                 return (ENOMEM);
  577         }
  578 
  579         QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
  580 
  581         ifp = ha->ifp;
  582 
  583         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
  584         QLA_LOCK(ha, __func__, -1, 0);
  585 
  586         ha->qla_detach_active = 1;
  587         qla_stop(ha);
  588 
  589         qla_release(ha);
  590 
  591         QLA_UNLOCK(ha, __func__);
  592 
  593         if (ha->flags.lock_init) {
  594                 mtx_destroy(&ha->hw_lock);
  595                 mtx_destroy(&ha->sp_log_lock);
  596         }
  597 
  598         QL_DPRINT2(ha, (dev, "%s: exit\n", __func__));
  599 
  600         return (0);
  601 }
  602 
  603 /*
  604  * SYSCTL Related Callbacks
  605  */
  606 static int
  607 qla_sysctl_get_link_status(SYSCTL_HANDLER_ARGS)
  608 {
  609         int err, ret = 0;
  610         qla_host_t *ha;
  611 
  612         err = sysctl_handle_int(oidp, &ret, 0, req);
  613 
  614         if (err || !req->newptr)
  615                 return (err);
  616 
  617         if (ret == 1) {
  618                 ha = (qla_host_t *)arg1;
  619                 ql_hw_link_status(ha);
  620         }
  621         return (err);
  622 }
  623 
  624 /*
  625  * Name:        qla_release
  626  * Function:    Releases the resources allocated for the device
  627  */
  628 static void
  629 qla_release(qla_host_t *ha)
  630 {
  631         device_t dev;
  632         int i;
  633 
  634         dev = ha->pci_dev;
  635 
  636         if (ha->async_event_tq) {
  637                 taskqueue_drain_all(ha->async_event_tq);
  638                 taskqueue_free(ha->async_event_tq);
  639         }
  640 
  641         if (ha->err_tq) {
  642                 taskqueue_drain_all(ha->err_tq);
  643                 taskqueue_free(ha->err_tq);
  644         }
  645 
  646         if (ha->stats_tq) {
  647                 taskqueue_drain_all(ha->stats_tq);
  648                 taskqueue_free(ha->stats_tq);
  649         }
  650 
  651         ql_del_cdev(ha);
  652 
  653         if (ha->flags.qla_watchdog_active) {
  654                 ha->qla_watchdog_exit = 1;
  655 
  656                 while (ha->qla_watchdog_exited == 0)
  657                         qla_mdelay(__func__, 1);
  658         }
  659 
  660         if (ha->flags.qla_callout_init)
  661                 callout_stop(&ha->tx_callout);
  662 
  663         if (ha->ifp != NULL)
  664                 ether_ifdetach(ha->ifp);
  665 
  666         ql_free_drvr_state_buffer(ha);
  667         ql_free_sp_log_buffer(ha);
  668         ql_free_dma(ha); 
  669         qla_free_parent_dma_tag(ha);
  670 
  671         if (ha->mbx_handle)
  672                 (void)bus_teardown_intr(dev, ha->mbx_irq, ha->mbx_handle);
  673 
  674         if (ha->mbx_irq)
  675                 (void) bus_release_resource(dev, SYS_RES_IRQ, ha->mbx_irq_rid,
  676                                 ha->mbx_irq);
  677 
  678         for (i = 0; i < ha->hw.num_sds_rings; i++) {
  679                 if (ha->irq_vec[i].handle) {
  680                         (void)bus_teardown_intr(dev, ha->irq_vec[i].irq,
  681                                         ha->irq_vec[i].handle);
  682                 }
  683                         
  684                 if (ha->irq_vec[i].irq) {
  685                         (void)bus_release_resource(dev, SYS_RES_IRQ,
  686                                 ha->irq_vec[i].irq_rid,
  687                                 ha->irq_vec[i].irq);
  688                 }
  689 
  690                 qla_free_tx_br(ha, &ha->tx_fp[i]);
  691         }
  692         qla_destroy_fp_taskqueues(ha);
  693 
  694         if (ha->msix_count)
  695                 pci_release_msi(dev);
  696 
  697         if (ha->pci_reg)
  698                 (void) bus_release_resource(dev, SYS_RES_MEMORY, ha->reg_rid,
  699                                 ha->pci_reg);
  700 
  701         if (ha->pci_reg1)
  702                 (void) bus_release_resource(dev, SYS_RES_MEMORY, ha->reg_rid1,
  703                                 ha->pci_reg1);
  704 
  705         return;
  706 }
  707 
  708 /*
  709  * DMA Related Functions
  710  */
  711 
  712 static void
  713 qla_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
  714 {
  715         *((bus_addr_t *)arg) = 0;
  716 
  717         if (error) {
  718                 printf("%s: bus_dmamap_load failed (%d)\n", __func__, error);
  719                 return;
  720         }
  721 
  722         *((bus_addr_t *)arg) = segs[0].ds_addr;
  723 
  724         return;
  725 }
  726 
  727 int
  728 ql_alloc_dmabuf(qla_host_t *ha, qla_dma_t *dma_buf)
  729 {
  730         int             ret = 0;
  731         device_t        dev;
  732         bus_addr_t      b_addr;
  733 
  734         dev = ha->pci_dev;
  735 
  736         QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
  737 
  738         ret = bus_dma_tag_create(
  739                         ha->parent_tag,/* parent */
  740                         dma_buf->alignment,
  741                         ((bus_size_t)(1ULL << 32)),/* boundary */
  742                         BUS_SPACE_MAXADDR,      /* lowaddr */
  743                         BUS_SPACE_MAXADDR,      /* highaddr */
  744                         NULL, NULL,             /* filter, filterarg */
  745                         dma_buf->size,          /* maxsize */
  746                         1,                      /* nsegments */
  747                         dma_buf->size,          /* maxsegsize */
  748                         0,                      /* flags */
  749                         NULL, NULL,             /* lockfunc, lockarg */
  750                         &dma_buf->dma_tag);
  751 
  752         if (ret) {
  753                 device_printf(dev, "%s: could not create dma tag\n", __func__);
  754                 goto ql_alloc_dmabuf_exit;
  755         }
  756         ret = bus_dmamem_alloc(dma_buf->dma_tag,
  757                         (void **)&dma_buf->dma_b,
  758                         (BUS_DMA_ZERO | BUS_DMA_COHERENT | BUS_DMA_NOWAIT),
  759                         &dma_buf->dma_map);
  760         if (ret) {
  761                 bus_dma_tag_destroy(dma_buf->dma_tag);
  762                 device_printf(dev, "%s: bus_dmamem_alloc failed\n", __func__);
  763                 goto ql_alloc_dmabuf_exit;
  764         }
  765 
  766         ret = bus_dmamap_load(dma_buf->dma_tag,
  767                         dma_buf->dma_map,
  768                         dma_buf->dma_b,
  769                         dma_buf->size,
  770                         qla_dmamap_callback,
  771                         &b_addr, BUS_DMA_NOWAIT);
  772 
  773         if (ret || !b_addr) {
  774                 bus_dma_tag_destroy(dma_buf->dma_tag);
  775                 bus_dmamem_free(dma_buf->dma_tag, dma_buf->dma_b,
  776                         dma_buf->dma_map);
  777                 ret = -1;
  778                 goto ql_alloc_dmabuf_exit;
  779         }
  780 
  781         dma_buf->dma_addr = b_addr;
  782 
  783 ql_alloc_dmabuf_exit:
  784         QL_DPRINT2(ha, (dev, "%s: exit ret 0x%08x tag %p map %p b %p sz 0x%x\n",
  785                 __func__, ret, (void *)dma_buf->dma_tag,
  786                 (void *)dma_buf->dma_map, (void *)dma_buf->dma_b,
  787                 dma_buf->size));
  788 
  789         return ret;
  790 }
  791 
  792 void
  793 ql_free_dmabuf(qla_host_t *ha, qla_dma_t *dma_buf)
  794 {
  795         bus_dmamap_unload(dma_buf->dma_tag, dma_buf->dma_map); 
  796         bus_dmamem_free(dma_buf->dma_tag, dma_buf->dma_b, dma_buf->dma_map);
  797         bus_dma_tag_destroy(dma_buf->dma_tag);
  798 }
  799 
  800 static int
  801 qla_alloc_parent_dma_tag(qla_host_t *ha)
  802 {
  803         int             ret;
  804         device_t        dev;
  805 
  806         dev = ha->pci_dev;
  807 
  808         /*
  809          * Allocate parent DMA Tag
  810          */
  811         ret = bus_dma_tag_create(
  812                         bus_get_dma_tag(dev),   /* parent */
  813                         1,((bus_size_t)(1ULL << 32)),/* alignment, boundary */
  814                         BUS_SPACE_MAXADDR,      /* lowaddr */
  815                         BUS_SPACE_MAXADDR,      /* highaddr */
  816                         NULL, NULL,             /* filter, filterarg */
  817                         BUS_SPACE_MAXSIZE_32BIT,/* maxsize */
  818                         0,                      /* nsegments */
  819                         BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
  820                         0,                      /* flags */
  821                         NULL, NULL,             /* lockfunc, lockarg */
  822                         &ha->parent_tag);
  823 
  824         if (ret) {
  825                 device_printf(dev, "%s: could not create parent dma tag\n",
  826                         __func__);
  827                 return (-1);
  828         }
  829 
  830         ha->flags.parent_tag = 1;
  831 
  832         return (0);
  833 }
  834 
  835 static void
  836 qla_free_parent_dma_tag(qla_host_t *ha)
  837 {
  838         if (ha->flags.parent_tag) {
  839                 bus_dma_tag_destroy(ha->parent_tag);
  840                 ha->flags.parent_tag = 0;
  841         }
  842 }
  843 
  844 /*
  845  * Name: qla_init_ifnet
  846  * Function: Creates the Network Device Interface and Registers it with the O.S
  847  */
  848 
  849 static void
  850 qla_init_ifnet(device_t dev, qla_host_t *ha)
  851 {
  852         struct ifnet *ifp;
  853 
  854         QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
  855 
  856         ifp = ha->ifp = if_alloc(IFT_ETHER);
  857 
  858         if (ifp == NULL)
  859                 panic("%s: cannot if_alloc()\n", device_get_nameunit(dev));
  860 
  861         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
  862 
  863         ifp->if_baudrate = IF_Gbps(10);
  864         ifp->if_capabilities = IFCAP_LINKSTATE;
  865         ifp->if_mtu = ETHERMTU;
  866 
  867         ifp->if_init = qla_init;
  868         ifp->if_softc = ha;
  869         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  870         ifp->if_ioctl = qla_ioctl;
  871 
  872         ifp->if_transmit = qla_transmit;
  873         ifp->if_qflush = qla_qflush;
  874 
  875         IFQ_SET_MAXLEN(&ifp->if_snd, qla_get_ifq_snd_maxlen(ha));
  876         ifp->if_snd.ifq_drv_maxlen = qla_get_ifq_snd_maxlen(ha);
  877         IFQ_SET_READY(&ifp->if_snd);
  878 
  879         ha->max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
  880 
  881         ether_ifattach(ifp, qla_get_mac_addr(ha));
  882 
  883         ifp->if_capabilities |= IFCAP_HWCSUM |
  884                                 IFCAP_TSO4 |
  885                                 IFCAP_TSO6 |
  886                                 IFCAP_JUMBO_MTU |
  887                                 IFCAP_VLAN_HWTAGGING |
  888                                 IFCAP_VLAN_MTU |
  889                                 IFCAP_VLAN_HWTSO |
  890                                 IFCAP_LRO;
  891 
  892         ifp->if_capenable = ifp->if_capabilities;
  893 
  894         ifp->if_hdrlen = sizeof(struct ether_vlan_header);
  895 
  896         ifmedia_init(&ha->media, IFM_IMASK, qla_media_change, qla_media_status);
  897 
  898         ifmedia_add(&ha->media, (IFM_ETHER | qla_get_optics(ha) | IFM_FDX), 0,
  899                 NULL);
  900         ifmedia_add(&ha->media, (IFM_ETHER | IFM_AUTO), 0, NULL);
  901 
  902         ifmedia_set(&ha->media, (IFM_ETHER | IFM_AUTO));
  903 
  904         QL_DPRINT2(ha, (dev, "%s: exit\n", __func__));
  905 
  906         return;
  907 }
  908 
  909 static void
  910 qla_init_locked(qla_host_t *ha)
  911 {
  912         struct ifnet *ifp = ha->ifp;
  913 
  914         ql_sp_log(ha, 14, 0, 0, 0, 0, 0, 0);
  915 
  916         qla_stop(ha);
  917 
  918         if (qla_alloc_xmt_bufs(ha) != 0) 
  919                 return;
  920 
  921         qla_confirm_9kb_enable(ha);
  922 
  923         if (qla_alloc_rcv_bufs(ha) != 0)
  924                 return;
  925 
  926         bcopy(IF_LLADDR(ha->ifp), ha->hw.mac_addr, ETHER_ADDR_LEN);
  927 
  928         ifp->if_hwassist = CSUM_TCP | CSUM_UDP | CSUM_TSO;
  929         ifp->if_hwassist |= CSUM_TCP_IPV6 | CSUM_UDP_IPV6;
  930 
  931         ha->stop_rcv = 0;
  932         if (ql_init_hw_if(ha) == 0) {
  933                 ifp = ha->ifp;
  934                 ifp->if_drv_flags |= IFF_DRV_RUNNING;
  935                 ha->hw_vlan_tx_frames = 0;
  936                 ha->tx_tso_frames = 0;
  937                 ha->qla_interface_up = 1;
  938                 ql_update_link_state(ha);
  939         } else {
  940                 if (ha->hw.sp_log_stop_events & Q8_SP_LOG_STOP_IF_START_FAILURE)
  941                         ha->hw.sp_log_stop = -1;
  942         }
  943 
  944         ha->qla_watchdog_pause = 0;
  945 
  946         return;
  947 }
  948 
  949 static void
  950 qla_init(void *arg)
  951 {
  952         qla_host_t *ha;
  953 
  954         ha = (qla_host_t *)arg;
  955 
  956         QL_DPRINT2(ha, (ha->pci_dev, "%s: enter\n", __func__));
  957 
  958         if (QLA_LOCK(ha, __func__, -1, 0) != 0)
  959                 return;
  960 
  961         qla_init_locked(ha);
  962 
  963         QLA_UNLOCK(ha, __func__);
  964 
  965         QL_DPRINT2(ha, (ha->pci_dev, "%s: exit\n", __func__));
  966 }
  967 
  968 static u_int
  969 qla_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int mcnt)
  970 {
  971         uint8_t *mta = arg;
  972 
  973         if (mcnt == Q8_MAX_NUM_MULTICAST_ADDRS)
  974                 return (0);
  975 
  976         bcopy(LLADDR(sdl), &mta[mcnt * Q8_MAC_ADDR_LEN], Q8_MAC_ADDR_LEN);
  977 
  978         return (1);
  979 }
  980 
  981 static int
  982 qla_set_multi(qla_host_t *ha, uint32_t add_multi)
  983 {
  984         uint8_t mta[Q8_MAX_NUM_MULTICAST_ADDRS * Q8_MAC_ADDR_LEN];
  985         int mcnt = 0;
  986         struct ifnet *ifp = ha->ifp;
  987         int ret = 0;
  988 
  989         mcnt = if_foreach_llmaddr(ifp, qla_copy_maddr, mta);
  990 
  991         if (QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT,
  992                 QLA_LOCK_NO_SLEEP) != 0)
  993                 return (-1);
  994 
  995         ql_sp_log(ha, 12, 4, ifp->if_drv_flags,
  996                 (ifp->if_drv_flags & IFF_DRV_RUNNING),
  997                 add_multi, (uint32_t)mcnt, 0);
  998 
  999         if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 1000                 if (!add_multi) {
 1001                         ret = qla_hw_del_all_mcast(ha);
 1002 
 1003                         if (ret)
 1004                                 device_printf(ha->pci_dev,
 1005                                         "%s: qla_hw_del_all_mcast() failed\n",
 1006                                 __func__);
 1007                 }
 1008 
 1009                 if (!ret)
 1010                         ret = ql_hw_set_multi(ha, mta, mcnt, 1);
 1011         }
 1012 
 1013         QLA_UNLOCK(ha, __func__);
 1014 
 1015         return (ret);
 1016 }
 1017 
 1018 static int
 1019 qla_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 1020 {
 1021         int ret = 0;
 1022         struct ifreq *ifr = (struct ifreq *)data;
 1023 #ifdef INET
 1024         struct ifaddr *ifa = (struct ifaddr *)data;
 1025 #endif
 1026         qla_host_t *ha;
 1027 
 1028         ha = (qla_host_t *)ifp->if_softc;
 1029         if (ha->offline || ha->qla_initiate_recovery)
 1030                 return (ret);
 1031 
 1032         switch (cmd) {
 1033         case SIOCSIFADDR:
 1034                 QL_DPRINT4(ha, (ha->pci_dev, "%s: SIOCSIFADDR (0x%lx)\n",
 1035                         __func__, cmd));
 1036 
 1037 #ifdef INET
 1038                 if (ifa->ifa_addr->sa_family == AF_INET) {
 1039                         ret = QLA_LOCK(ha, __func__,
 1040                                         QLA_LOCK_DEFAULT_MS_TIMEOUT,
 1041                                         QLA_LOCK_NO_SLEEP);
 1042                         if (ret)
 1043                                 break;
 1044 
 1045                         ifp->if_flags |= IFF_UP;
 1046 
 1047                         ql_sp_log(ha, 8, 3, ifp->if_drv_flags,
 1048                                 (ifp->if_drv_flags & IFF_DRV_RUNNING),
 1049                                 ntohl(IA_SIN(ifa)->sin_addr.s_addr), 0, 0);
 1050 
 1051                         if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
 1052                                 qla_init_locked(ha);
 1053                         }
 1054 
 1055                         QLA_UNLOCK(ha, __func__);
 1056                         QL_DPRINT4(ha, (ha->pci_dev,
 1057                                 "%s: SIOCSIFADDR (0x%lx) ipv4 [0x%08x]\n",
 1058                                 __func__, cmd,
 1059                                 ntohl(IA_SIN(ifa)->sin_addr.s_addr)));
 1060 
 1061                         arp_ifinit(ifp, ifa);
 1062                         break;
 1063                 }
 1064 #endif
 1065                 ether_ioctl(ifp, cmd, data);
 1066                 break;
 1067 
 1068         case SIOCSIFMTU:
 1069                 QL_DPRINT4(ha, (ha->pci_dev, "%s: SIOCSIFMTU (0x%lx)\n",
 1070                         __func__, cmd));
 1071 
 1072                 if (ifr->ifr_mtu > QLA_MAX_MTU) {
 1073                         ret = EINVAL;
 1074                 } else {
 1075                         ret = QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT,
 1076                                         QLA_LOCK_NO_SLEEP);
 1077 
 1078                         if (ret)
 1079                                 break;
 1080 
 1081                         ifp->if_mtu = ifr->ifr_mtu;
 1082                         ha->max_frame_size =
 1083                                 ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
 1084 
 1085                         ql_sp_log(ha, 9, 4, ifp->if_drv_flags,
 1086                                 (ifp->if_drv_flags & IFF_DRV_RUNNING),
 1087                                 ha->max_frame_size, ifp->if_mtu, 0);
 1088 
 1089                         if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 1090                                 qla_init_locked(ha);
 1091                         }
 1092 
 1093                         if (ifp->if_mtu > ETHERMTU)
 1094                                 ha->std_replenish = QL_JUMBO_REPLENISH_THRES;
 1095                         else
 1096                                 ha->std_replenish = QL_STD_REPLENISH_THRES;
 1097                                 
 1098 
 1099                         QLA_UNLOCK(ha, __func__);
 1100                 }
 1101 
 1102                 break;
 1103 
 1104         case SIOCSIFFLAGS:
 1105                 QL_DPRINT4(ha, (ha->pci_dev, "%s: SIOCSIFFLAGS (0x%lx)\n",
 1106                         __func__, cmd));
 1107 
 1108                 ret = QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT,
 1109                                 QLA_LOCK_NO_SLEEP);
 1110 
 1111                 if (ret)
 1112                         break;
 1113 
 1114                 ql_sp_log(ha, 10, 4, ifp->if_drv_flags,
 1115                         (ifp->if_drv_flags & IFF_DRV_RUNNING),
 1116                         ha->if_flags, ifp->if_flags, 0);
 1117 
 1118                 if (ifp->if_flags & IFF_UP) {
 1119                         ha->max_frame_size = ifp->if_mtu +
 1120                                         ETHER_HDR_LEN + ETHER_CRC_LEN;
 1121                         qla_init_locked(ha);
 1122                                                 
 1123                         if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 1124                                 if ((ifp->if_flags ^ ha->if_flags) &
 1125                                         IFF_PROMISC) {
 1126                                         ret = ql_set_promisc(ha);
 1127                                 } else if ((ifp->if_flags ^ ha->if_flags) &
 1128                                         IFF_ALLMULTI) {
 1129                                         ret = ql_set_allmulti(ha);
 1130                                 }
 1131                         }
 1132                 } else {
 1133                         if (ifp->if_drv_flags & IFF_DRV_RUNNING)
 1134                                 qla_stop(ha);
 1135                         ha->if_flags = ifp->if_flags;
 1136                 }
 1137 
 1138                 QLA_UNLOCK(ha, __func__);
 1139                 break;
 1140 
 1141         case SIOCADDMULTI:
 1142                 QL_DPRINT4(ha, (ha->pci_dev,
 1143                         "%s: %s (0x%lx)\n", __func__, "SIOCADDMULTI", cmd));
 1144 
 1145                 if (qla_set_multi(ha, 1))
 1146                         ret = EINVAL;
 1147                 break;
 1148 
 1149         case SIOCDELMULTI:
 1150                 QL_DPRINT4(ha, (ha->pci_dev,
 1151                         "%s: %s (0x%lx)\n", __func__, "SIOCDELMULTI", cmd));
 1152 
 1153                 if (qla_set_multi(ha, 0))
 1154                         ret = EINVAL;
 1155                 break;
 1156 
 1157         case SIOCSIFMEDIA:
 1158         case SIOCGIFMEDIA:
 1159                 QL_DPRINT4(ha, (ha->pci_dev,
 1160                         "%s: SIOCSIFMEDIA/SIOCGIFMEDIA (0x%lx)\n",
 1161                         __func__, cmd));
 1162                 ret = ifmedia_ioctl(ifp, ifr, &ha->media, cmd);
 1163                 break;
 1164 
 1165         case SIOCSIFCAP:
 1166         {
 1167                 int mask = ifr->ifr_reqcap ^ ifp->if_capenable;
 1168 
 1169                 QL_DPRINT4(ha, (ha->pci_dev, "%s: SIOCSIFCAP (0x%lx)\n",
 1170                         __func__, cmd));
 1171 
 1172                 if (mask & IFCAP_HWCSUM)
 1173                         ifp->if_capenable ^= IFCAP_HWCSUM;
 1174                 if (mask & IFCAP_TSO4)
 1175                         ifp->if_capenable ^= IFCAP_TSO4;
 1176                 if (mask & IFCAP_TSO6)
 1177                         ifp->if_capenable ^= IFCAP_TSO6;
 1178                 if (mask & IFCAP_VLAN_HWTAGGING)
 1179                         ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
 1180                 if (mask & IFCAP_VLAN_HWTSO)
 1181                         ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
 1182                 if (mask & IFCAP_LRO)
 1183                         ifp->if_capenable ^= IFCAP_LRO;
 1184 
 1185                 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 1186                         ret = QLA_LOCK(ha, __func__, QLA_LOCK_DEFAULT_MS_TIMEOUT,
 1187                                 QLA_LOCK_NO_SLEEP);
 1188 
 1189                         if (ret)
 1190                                 break;
 1191 
 1192                         ql_sp_log(ha, 11, 4, ifp->if_drv_flags,
 1193                                 (ifp->if_drv_flags & IFF_DRV_RUNNING),
 1194                                 mask, ifp->if_capenable, 0);
 1195 
 1196                         qla_init_locked(ha);
 1197 
 1198                         QLA_UNLOCK(ha, __func__);
 1199                 }
 1200                 VLAN_CAPABILITIES(ifp);
 1201                 break;
 1202         }
 1203 
 1204         default:
 1205                 QL_DPRINT4(ha, (ha->pci_dev, "%s: default (0x%lx)\n",
 1206                         __func__, cmd));
 1207                 ret = ether_ioctl(ifp, cmd, data);
 1208                 break;
 1209         }
 1210 
 1211         return (ret);
 1212 }
 1213 
 1214 static int
 1215 qla_media_change(struct ifnet *ifp)
 1216 {
 1217         qla_host_t *ha;
 1218         struct ifmedia *ifm;
 1219         int ret = 0;
 1220 
 1221         ha = (qla_host_t *)ifp->if_softc;
 1222 
 1223         QL_DPRINT2(ha, (ha->pci_dev, "%s: enter\n", __func__));
 1224 
 1225         ifm = &ha->media;
 1226 
 1227         if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
 1228                 ret = EINVAL;
 1229 
 1230         QL_DPRINT2(ha, (ha->pci_dev, "%s: exit\n", __func__));
 1231 
 1232         return (ret);
 1233 }
 1234 
 1235 static void
 1236 qla_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
 1237 {
 1238         qla_host_t *ha;
 1239 
 1240         ha = (qla_host_t *)ifp->if_softc;
 1241 
 1242         QL_DPRINT2(ha, (ha->pci_dev, "%s: enter\n", __func__));
 1243 
 1244         ifmr->ifm_status = IFM_AVALID;
 1245         ifmr->ifm_active = IFM_ETHER;
 1246 
 1247         ql_update_link_state(ha);
 1248         if (ha->hw.link_up) {
 1249                 ifmr->ifm_status |= IFM_ACTIVE;
 1250                 ifmr->ifm_active |= (IFM_FDX | qla_get_optics(ha));
 1251         }
 1252 
 1253         QL_DPRINT2(ha, (ha->pci_dev, "%s: exit (%s)\n", __func__,\
 1254                 (ha->hw.link_up ? "link_up" : "link_down")));
 1255 
 1256         return;
 1257 }
 1258 
 1259 static int
 1260 qla_send(qla_host_t *ha, struct mbuf **m_headp, uint32_t txr_idx,
 1261         uint32_t iscsi_pdu)
 1262 {
 1263         bus_dma_segment_t       segs[QLA_MAX_SEGMENTS];
 1264         bus_dmamap_t            map;
 1265         int                     nsegs;
 1266         int                     ret = -1;
 1267         uint32_t                tx_idx;
 1268         struct mbuf             *m_head = *m_headp;
 1269 
 1270         QL_DPRINT8(ha, (ha->pci_dev, "%s: enter\n", __func__));
 1271 
 1272         tx_idx = ha->hw.tx_cntxt[txr_idx].txr_next;
 1273 
 1274         if ((NULL != ha->tx_ring[txr_idx].tx_buf[tx_idx].m_head) ||
 1275                 (QL_ERR_INJECT(ha, INJCT_TXBUF_MBUF_NON_NULL))){
 1276                 QL_ASSERT(ha, 0, ("%s [%d]: txr_idx = %d tx_idx = %d "\
 1277                         "mbuf = %p\n", __func__, __LINE__, txr_idx, tx_idx,\
 1278                         ha->tx_ring[txr_idx].tx_buf[tx_idx].m_head));
 1279 
 1280                 device_printf(ha->pci_dev, "%s [%d]: txr_idx = %d tx_idx = %d "
 1281                         "mbuf = %p\n", __func__, __LINE__, txr_idx, tx_idx,
 1282                         ha->tx_ring[txr_idx].tx_buf[tx_idx].m_head);
 1283 
 1284                 if (m_head)
 1285                         m_freem(m_head);
 1286                 *m_headp = NULL;
 1287                 QL_INITIATE_RECOVERY(ha);
 1288                 return (ret);
 1289         }
 1290 
 1291         map = ha->tx_ring[txr_idx].tx_buf[tx_idx].map;
 1292 
 1293         ret = bus_dmamap_load_mbuf_sg(ha->tx_tag, map, m_head, segs, &nsegs,
 1294                         BUS_DMA_NOWAIT);
 1295 
 1296         if (ret == EFBIG) {
 1297                 struct mbuf *m;
 1298 
 1299                 QL_DPRINT8(ha, (ha->pci_dev, "%s: EFBIG [%d]\n", __func__,
 1300                         m_head->m_pkthdr.len));
 1301 
 1302                 m = m_defrag(m_head, M_NOWAIT);
 1303                 if (m == NULL) {
 1304                         ha->err_tx_defrag++;
 1305                         m_freem(m_head);
 1306                         *m_headp = NULL;
 1307                         device_printf(ha->pci_dev,
 1308                                 "%s: m_defrag() = NULL [%d]\n",
 1309                                 __func__, ret);
 1310                         return (ENOBUFS);
 1311                 }
 1312                 m_head = m;
 1313                 *m_headp = m_head;
 1314 
 1315                 if ((ret = bus_dmamap_load_mbuf_sg(ha->tx_tag, map, m_head,
 1316                                         segs, &nsegs, BUS_DMA_NOWAIT))) {
 1317                         ha->err_tx_dmamap_load++;
 1318 
 1319                         device_printf(ha->pci_dev,
 1320                                 "%s: bus_dmamap_load_mbuf_sg failed0[%d, %d]\n",
 1321                                 __func__, ret, m_head->m_pkthdr.len);
 1322 
 1323                         if (ret != ENOMEM) {
 1324                                 m_freem(m_head);
 1325                                 *m_headp = NULL;
 1326                         }
 1327                         return (ret);
 1328                 }
 1329 
 1330         } else if (ret) {
 1331                 ha->err_tx_dmamap_load++;
 1332 
 1333                 device_printf(ha->pci_dev,
 1334                         "%s: bus_dmamap_load_mbuf_sg failed1[%d, %d]\n",
 1335                         __func__, ret, m_head->m_pkthdr.len);
 1336 
 1337                 if (ret != ENOMEM) {
 1338                         m_freem(m_head);
 1339                         *m_headp = NULL;
 1340                 }
 1341                 return (ret);
 1342         }
 1343 
 1344         QL_ASSERT(ha, (nsegs != 0), ("qla_send: empty packet"));
 1345 
 1346         bus_dmamap_sync(ha->tx_tag, map, BUS_DMASYNC_PREWRITE);
 1347 
 1348         if (!(ret = ql_hw_send(ha, segs, nsegs, tx_idx, m_head, txr_idx,
 1349                                 iscsi_pdu))) {
 1350                 ha->tx_ring[txr_idx].count++;
 1351                 if (iscsi_pdu)
 1352                         ha->tx_ring[txr_idx].iscsi_pkt_count++;
 1353                 ha->tx_ring[txr_idx].tx_buf[tx_idx].m_head = m_head;
 1354         } else {
 1355                 bus_dmamap_unload(ha->tx_tag, map); 
 1356                 if (ret == EINVAL) {
 1357                         if (m_head)
 1358                                 m_freem(m_head);
 1359                         *m_headp = NULL;
 1360                 }
 1361         }
 1362 
 1363         QL_DPRINT8(ha, (ha->pci_dev, "%s: exit\n", __func__));
 1364         return (ret);
 1365 }
 1366 
 1367 static int
 1368 qla_alloc_tx_br(qla_host_t *ha, qla_tx_fp_t *fp)
 1369 {
 1370         snprintf(fp->tx_mtx_name, sizeof(fp->tx_mtx_name),
 1371                 "qla%d_fp%d_tx_mq_lock", ha->pci_func, fp->txr_idx);
 1372 
 1373         mtx_init(&fp->tx_mtx, fp->tx_mtx_name, NULL, MTX_DEF);
 1374 
 1375         fp->tx_br = buf_ring_alloc(NUM_TX_DESCRIPTORS, M_DEVBUF,
 1376                                    M_NOWAIT, &fp->tx_mtx);
 1377         if (fp->tx_br == NULL) {
 1378             QL_DPRINT1(ha, (ha->pci_dev, "buf_ring_alloc failed for "
 1379                 " fp[%d, %d]\n", ha->pci_func, fp->txr_idx));
 1380             return (-ENOMEM);
 1381         }
 1382         return 0;
 1383 }
 1384 
 1385 static void
 1386 qla_free_tx_br(qla_host_t *ha, qla_tx_fp_t *fp)
 1387 {
 1388         struct mbuf *mp;
 1389         struct ifnet *ifp = ha->ifp;
 1390 
 1391         if (mtx_initialized(&fp->tx_mtx)) {
 1392                 if (fp->tx_br != NULL) {
 1393                         mtx_lock(&fp->tx_mtx);
 1394 
 1395                         while ((mp = drbr_dequeue(ifp, fp->tx_br)) != NULL) {
 1396                                 m_freem(mp);
 1397                         }
 1398 
 1399                         mtx_unlock(&fp->tx_mtx);
 1400 
 1401                         buf_ring_free(fp->tx_br, M_DEVBUF);
 1402                         fp->tx_br = NULL;
 1403                 }
 1404                 mtx_destroy(&fp->tx_mtx);
 1405         }
 1406         return;
 1407 }
 1408 
 1409 static void
 1410 qla_fp_taskqueue(void *context, int pending)
 1411 {
 1412         qla_tx_fp_t *fp;
 1413         qla_host_t *ha;
 1414         struct ifnet *ifp;
 1415         struct mbuf  *mp = NULL;
 1416         int ret = 0;
 1417         uint32_t txr_idx;
 1418         uint32_t iscsi_pdu = 0;
 1419         uint32_t rx_pkts_left = -1;
 1420 
 1421         fp = context;
 1422 
 1423         if (fp == NULL)
 1424                 return;
 1425 
 1426         ha = (qla_host_t *)fp->ha;
 1427 
 1428         ifp = ha->ifp;
 1429 
 1430         txr_idx = fp->txr_idx;
 1431 
 1432         mtx_lock(&fp->tx_mtx);
 1433 
 1434         if (!(ifp->if_drv_flags & IFF_DRV_RUNNING) || (!ha->hw.link_up)) {
 1435                 mtx_unlock(&fp->tx_mtx);
 1436                 goto qla_fp_taskqueue_exit;
 1437         }
 1438 
 1439         while (rx_pkts_left && !ha->stop_rcv &&
 1440                 (ifp->if_drv_flags & IFF_DRV_RUNNING) && ha->hw.link_up) {
 1441                 rx_pkts_left = ql_rcv_isr(ha, fp->txr_idx, 64);
 1442 
 1443 #ifdef QL_ENABLE_ISCSI_TLV
 1444                 ql_hw_tx_done_locked(ha, fp->txr_idx);
 1445                 ql_hw_tx_done_locked(ha, (fp->txr_idx + (ha->hw.num_tx_rings >> 1)));
 1446 #else
 1447                 ql_hw_tx_done_locked(ha, fp->txr_idx);
 1448 #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
 1449 
 1450                 mp = drbr_peek(ifp, fp->tx_br);
 1451 
 1452                 while (mp != NULL) {
 1453                         if (M_HASHTYPE_GET(mp) != M_HASHTYPE_NONE) {
 1454 #ifdef QL_ENABLE_ISCSI_TLV
 1455                                 if (ql_iscsi_pdu(ha, mp) == 0) {
 1456                                         txr_idx = txr_idx +
 1457                                                 (ha->hw.num_tx_rings >> 1);
 1458                                         iscsi_pdu = 1;
 1459                                 } else {
 1460                                         iscsi_pdu = 0;
 1461                                         txr_idx = fp->txr_idx;
 1462                                 }
 1463 #endif /* #ifdef QL_ENABLE_ISCSI_TLV */
 1464                         }
 1465 
 1466                         ret = qla_send(ha, &mp, txr_idx, iscsi_pdu);
 1467 
 1468                         if (ret) {
 1469                                 if (mp != NULL)
 1470                                         drbr_putback(ifp, fp->tx_br, mp);
 1471                                 else {
 1472                                         drbr_advance(ifp, fp->tx_br);
 1473                                 }
 1474 
 1475                                 mtx_unlock(&fp->tx_mtx);
 1476 
 1477                                 goto qla_fp_taskqueue_exit0;
 1478                         } else {
 1479                                 drbr_advance(ifp, fp->tx_br);
 1480                         }
 1481 
 1482                         /* Send a copy of the frame to the BPF listener */
 1483                         ETHER_BPF_MTAP(ifp, mp);
 1484 
 1485                         if (((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) ||
 1486                                 (!ha->hw.link_up))
 1487                                 break;
 1488 
 1489                         mp = drbr_peek(ifp, fp->tx_br);
 1490                 }
 1491         }
 1492         mtx_unlock(&fp->tx_mtx);
 1493 
 1494         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
 1495                 goto qla_fp_taskqueue_exit;
 1496 
 1497 qla_fp_taskqueue_exit0:
 1498 
 1499         if (rx_pkts_left || ((mp != NULL) && ret)) {
 1500                 taskqueue_enqueue(fp->fp_taskqueue, &fp->fp_task);
 1501         } else {
 1502                 if (!ha->stop_rcv) {
 1503                         QL_ENABLE_INTERRUPTS(ha, fp->txr_idx);
 1504                 }
 1505         }
 1506 
 1507 qla_fp_taskqueue_exit:
 1508 
 1509         QL_DPRINT2(ha, (ha->pci_dev, "%s: exit ret = %d\n", __func__, ret));
 1510         return;
 1511 }
 1512 
 1513 static int
 1514 qla_create_fp_taskqueues(qla_host_t *ha)
 1515 {
 1516         int     i;
 1517         uint8_t tq_name[32];
 1518 
 1519         for (i = 0; i < ha->hw.num_sds_rings; i++) {
 1520                 qla_tx_fp_t *fp = &ha->tx_fp[i];
 1521 
 1522                 bzero(tq_name, sizeof (tq_name));
 1523                 snprintf(tq_name, sizeof (tq_name), "ql_fp_tq_%d", i);
 1524 
 1525                 NET_TASK_INIT(&fp->fp_task, 0, qla_fp_taskqueue, fp);
 1526 
 1527                 fp->fp_taskqueue = taskqueue_create_fast(tq_name, M_NOWAIT,
 1528                                         taskqueue_thread_enqueue,
 1529                                         &fp->fp_taskqueue);
 1530 
 1531                 if (fp->fp_taskqueue == NULL)
 1532                         return (-1);
 1533 
 1534                 taskqueue_start_threads(&fp->fp_taskqueue, 1, PI_NET, "%s",
 1535                         tq_name);
 1536 
 1537                 QL_DPRINT1(ha, (ha->pci_dev, "%s: %p\n", __func__,
 1538                         fp->fp_taskqueue));
 1539         }
 1540 
 1541         return (0);
 1542 }
 1543 
 1544 static void
 1545 qla_destroy_fp_taskqueues(qla_host_t *ha)
 1546 {
 1547         int     i;
 1548 
 1549         for (i = 0; i < ha->hw.num_sds_rings; i++) {
 1550                 qla_tx_fp_t *fp = &ha->tx_fp[i];
 1551 
 1552                 if (fp->fp_taskqueue != NULL) {
 1553                         taskqueue_drain_all(fp->fp_taskqueue);
 1554                         taskqueue_free(fp->fp_taskqueue);
 1555                         fp->fp_taskqueue = NULL;
 1556                 }
 1557         }
 1558         return;
 1559 }
 1560 
 1561 static void
 1562 qla_drain_fp_taskqueues(qla_host_t *ha)
 1563 {
 1564         int     i;
 1565 
 1566         for (i = 0; i < ha->hw.num_sds_rings; i++) {
 1567                 qla_tx_fp_t *fp = &ha->tx_fp[i];
 1568 
 1569                 if (fp->fp_taskqueue != NULL) {
 1570                         taskqueue_drain_all(fp->fp_taskqueue);
 1571                 }
 1572         }
 1573         return;
 1574 }
 1575 
 1576 static int
 1577 qla_transmit(struct ifnet *ifp, struct mbuf  *mp)
 1578 {
 1579         qla_host_t *ha = (qla_host_t *)ifp->if_softc;
 1580         qla_tx_fp_t *fp;
 1581         int rss_id = 0;
 1582         int ret = 0;
 1583 
 1584         QL_DPRINT2(ha, (ha->pci_dev, "%s: enter\n", __func__));
 1585 
 1586 #if __FreeBSD_version >= 1100000
 1587         if (M_HASHTYPE_GET(mp) != M_HASHTYPE_NONE)
 1588 #else
 1589         if (mp->m_flags & M_FLOWID)
 1590 #endif
 1591                 rss_id = (mp->m_pkthdr.flowid & Q8_RSS_IND_TBL_MAX_IDX) %
 1592                                         ha->hw.num_sds_rings;
 1593         fp = &ha->tx_fp[rss_id];
 1594 
 1595         if (fp->tx_br == NULL) {
 1596                 ret = EINVAL;
 1597                 goto qla_transmit_exit;
 1598         }
 1599 
 1600         if (mp != NULL) {
 1601                 ret = drbr_enqueue(ifp, fp->tx_br, mp);
 1602         }
 1603 
 1604         if (fp->fp_taskqueue != NULL)
 1605                 taskqueue_enqueue(fp->fp_taskqueue, &fp->fp_task);
 1606 
 1607         ret = 0;
 1608 
 1609 qla_transmit_exit:
 1610 
 1611         QL_DPRINT2(ha, (ha->pci_dev, "%s: exit ret = %d\n", __func__, ret));
 1612         return ret;
 1613 }
 1614 
 1615 static void
 1616 qla_qflush(struct ifnet *ifp)
 1617 {
 1618         int                     i;
 1619         qla_tx_fp_t             *fp;
 1620         struct mbuf             *mp;
 1621         qla_host_t              *ha;
 1622 
 1623         ha = (qla_host_t *)ifp->if_softc;
 1624 
 1625         QL_DPRINT2(ha, (ha->pci_dev, "%s: enter\n", __func__));
 1626 
 1627         for (i = 0; i < ha->hw.num_sds_rings; i++) {
 1628                 fp = &ha->tx_fp[i];
 1629 
 1630                 if (fp == NULL)
 1631                         continue;
 1632 
 1633                 if (fp->tx_br) {
 1634                         mtx_lock(&fp->tx_mtx);
 1635 
 1636                         while ((mp = drbr_dequeue(ifp, fp->tx_br)) != NULL) {
 1637                                 m_freem(mp);
 1638                         }
 1639                         mtx_unlock(&fp->tx_mtx);
 1640                 }
 1641         }
 1642         QL_DPRINT2(ha, (ha->pci_dev, "%s: exit\n", __func__));
 1643 
 1644         return;
 1645 }
 1646 
 1647 static void
 1648 qla_stop(qla_host_t *ha)
 1649 {
 1650         struct ifnet *ifp = ha->ifp;
 1651         int i = 0;
 1652 
 1653         ql_sp_log(ha, 13, 0, 0, 0, 0, 0, 0);
 1654 
 1655         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 1656         ha->qla_watchdog_pause = 1;
 1657 
 1658         for (i = 0; i < ha->hw.num_sds_rings; i++) {
 1659                 qla_tx_fp_t *fp;
 1660 
 1661                 fp = &ha->tx_fp[i];
 1662 
 1663                 if (fp == NULL)
 1664                         continue;
 1665 
 1666                 if (fp->tx_br != NULL) {
 1667                         mtx_lock(&fp->tx_mtx);
 1668                         mtx_unlock(&fp->tx_mtx);
 1669                 }
 1670         }
 1671 
 1672         while (!ha->qla_watchdog_paused)
 1673                 qla_mdelay(__func__, 1);
 1674 
 1675         ha->qla_interface_up = 0;
 1676 
 1677         qla_drain_fp_taskqueues(ha);
 1678 
 1679         ql_del_hw_if(ha);
 1680 
 1681         qla_free_xmt_bufs(ha);
 1682         qla_free_rcv_bufs(ha);
 1683 
 1684         return;
 1685 }
 1686 
 1687 /*
 1688  * Buffer Management Functions for Transmit and Receive Rings
 1689  */
 1690 static int
 1691 qla_alloc_xmt_bufs(qla_host_t *ha)
 1692 {
 1693         int ret = 0;
 1694         uint32_t i, j;
 1695         qla_tx_buf_t *txb;
 1696 
 1697         if (bus_dma_tag_create(NULL,    /* parent */
 1698                 1, 0,    /* alignment, bounds */
 1699                 BUS_SPACE_MAXADDR,       /* lowaddr */
 1700                 BUS_SPACE_MAXADDR,       /* highaddr */
 1701                 NULL, NULL,      /* filter, filterarg */
 1702                 QLA_MAX_TSO_FRAME_SIZE,     /* maxsize */
 1703                 QLA_MAX_SEGMENTS,        /* nsegments */
 1704                 PAGE_SIZE,        /* maxsegsize */
 1705                 BUS_DMA_ALLOCNOW,        /* flags */
 1706                 NULL,    /* lockfunc */
 1707                 NULL,    /* lockfuncarg */
 1708                 &ha->tx_tag)) {
 1709                 device_printf(ha->pci_dev, "%s: tx_tag alloc failed\n",
 1710                         __func__);
 1711                 return (ENOMEM);
 1712         }
 1713 
 1714         for (i = 0; i < ha->hw.num_tx_rings; i++) {
 1715                 bzero((void *)ha->tx_ring[i].tx_buf,
 1716                         (sizeof(qla_tx_buf_t) * NUM_TX_DESCRIPTORS));
 1717         }
 1718 
 1719         for (j = 0; j < ha->hw.num_tx_rings; j++) {
 1720                 for (i = 0; i < NUM_TX_DESCRIPTORS; i++) {
 1721                         txb = &ha->tx_ring[j].tx_buf[i];
 1722 
 1723                         if ((ret = bus_dmamap_create(ha->tx_tag,
 1724                                         BUS_DMA_NOWAIT, &txb->map))) {
 1725                                 ha->err_tx_dmamap_create++;
 1726                                 device_printf(ha->pci_dev,
 1727                                         "%s: bus_dmamap_create failed[%d]\n",
 1728                                         __func__, ret);
 1729 
 1730                                 qla_free_xmt_bufs(ha);
 1731 
 1732                                 return (ret);
 1733                         }
 1734                 }
 1735         }
 1736 
 1737         return 0;
 1738 }
 1739 
 1740 /*
 1741  * Release mbuf after it sent on the wire
 1742  */
 1743 static void
 1744 qla_clear_tx_buf(qla_host_t *ha, qla_tx_buf_t *txb)
 1745 {
 1746         QL_DPRINT2(ha, (ha->pci_dev, "%s: enter\n", __func__));
 1747 
 1748         if (txb->m_head) {
 1749                 bus_dmamap_sync(ha->tx_tag, txb->map,
 1750                         BUS_DMASYNC_POSTWRITE);
 1751 
 1752                 bus_dmamap_unload(ha->tx_tag, txb->map);
 1753 
 1754                 m_freem(txb->m_head);
 1755                 txb->m_head = NULL;
 1756 
 1757                 bus_dmamap_destroy(ha->tx_tag, txb->map);
 1758                 txb->map = NULL;
 1759         }
 1760 
 1761         if (txb->map) {
 1762                 bus_dmamap_unload(ha->tx_tag, txb->map);
 1763                 bus_dmamap_destroy(ha->tx_tag, txb->map);
 1764                 txb->map = NULL;
 1765         }
 1766 
 1767         QL_DPRINT2(ha, (ha->pci_dev, "%s: exit\n", __func__));
 1768 }
 1769 
 1770 static void
 1771 qla_free_xmt_bufs(qla_host_t *ha)
 1772 {
 1773         int             i, j;
 1774 
 1775         for (j = 0; j < ha->hw.num_tx_rings; j++) {
 1776                 for (i = 0; i < NUM_TX_DESCRIPTORS; i++)
 1777                         qla_clear_tx_buf(ha, &ha->tx_ring[j].tx_buf[i]);
 1778         }
 1779 
 1780         if (ha->tx_tag != NULL) {
 1781                 bus_dma_tag_destroy(ha->tx_tag);
 1782                 ha->tx_tag = NULL;
 1783         }
 1784 
 1785         for (i = 0; i < ha->hw.num_tx_rings; i++) {
 1786                 bzero((void *)ha->tx_ring[i].tx_buf,
 1787                         (sizeof(qla_tx_buf_t) * NUM_TX_DESCRIPTORS));
 1788         }
 1789         return;
 1790 }
 1791 
 1792 static int
 1793 qla_alloc_rcv_std(qla_host_t *ha)
 1794 {
 1795         int             i, j, k, r, ret = 0;
 1796         qla_rx_buf_t    *rxb;
 1797         qla_rx_ring_t   *rx_ring;
 1798 
 1799         for (r = 0; r < ha->hw.num_rds_rings; r++) {
 1800                 rx_ring = &ha->rx_ring[r];
 1801 
 1802                 for (i = 0; i < NUM_RX_DESCRIPTORS; i++) {
 1803                         rxb = &rx_ring->rx_buf[i];
 1804 
 1805                         ret = bus_dmamap_create(ha->rx_tag, BUS_DMA_NOWAIT,
 1806                                         &rxb->map);
 1807 
 1808                         if (ret) {
 1809                                 device_printf(ha->pci_dev,
 1810                                         "%s: dmamap[%d, %d] failed\n",
 1811                                         __func__, r, i);
 1812 
 1813                                 for (k = 0; k < r; k++) {
 1814                                         for (j = 0; j < NUM_RX_DESCRIPTORS;
 1815                                                 j++) {
 1816                                                 rxb = &ha->rx_ring[k].rx_buf[j];
 1817                                                 bus_dmamap_destroy(ha->rx_tag,
 1818                                                         rxb->map);
 1819                                         }
 1820                                 }
 1821 
 1822                                 for (j = 0; j < i; j++) {
 1823                                         bus_dmamap_destroy(ha->rx_tag,
 1824                                                 rx_ring->rx_buf[j].map);
 1825                                 }
 1826                                 goto qla_alloc_rcv_std_err;
 1827                         }
 1828                 }
 1829         }
 1830 
 1831         qla_init_hw_rcv_descriptors(ha);
 1832 
 1833         for (r = 0; r < ha->hw.num_rds_rings; r++) {
 1834                 rx_ring = &ha->rx_ring[r];
 1835 
 1836                 for (i = 0; i < NUM_RX_DESCRIPTORS; i++) {
 1837                         rxb = &rx_ring->rx_buf[i];
 1838                         rxb->handle = i;
 1839                         if (!(ret = ql_get_mbuf(ha, rxb, NULL))) {
 1840                                 /*
 1841                                  * set the physical address in the
 1842                                  * corresponding descriptor entry in the
 1843                                  * receive ring/queue for the hba 
 1844                                  */
 1845                                 qla_set_hw_rcv_desc(ha, r, i, rxb->handle,
 1846                                         rxb->paddr,
 1847                                         (rxb->m_head)->m_pkthdr.len);
 1848                         } else {
 1849                                 device_printf(ha->pci_dev,
 1850                                         "%s: ql_get_mbuf [%d, %d] failed\n",
 1851                                         __func__, r, i);
 1852                                 bus_dmamap_destroy(ha->rx_tag, rxb->map);
 1853                                 goto qla_alloc_rcv_std_err;
 1854                         }
 1855                 }
 1856         }
 1857         return 0;
 1858 
 1859 qla_alloc_rcv_std_err:
 1860         return (-1);
 1861 }
 1862 
 1863 static void
 1864 qla_free_rcv_std(qla_host_t *ha)
 1865 {
 1866         int             i, r;
 1867         qla_rx_buf_t    *rxb;
 1868 
 1869         for (r = 0; r < ha->hw.num_rds_rings; r++) {
 1870                 for (i = 0; i < NUM_RX_DESCRIPTORS; i++) {
 1871                         rxb = &ha->rx_ring[r].rx_buf[i];
 1872                         if (rxb->m_head != NULL) {
 1873                                 bus_dmamap_unload(ha->rx_tag, rxb->map);
 1874                                 bus_dmamap_destroy(ha->rx_tag, rxb->map);
 1875                                 m_freem(rxb->m_head);
 1876                                 rxb->m_head = NULL;
 1877                         }
 1878                 }
 1879         }
 1880         return;
 1881 }
 1882 
 1883 static int
 1884 qla_alloc_rcv_bufs(qla_host_t *ha)
 1885 {
 1886         int             i, ret = 0;
 1887 
 1888         if (bus_dma_tag_create(NULL,    /* parent */
 1889                         1, 0,    /* alignment, bounds */
 1890                         BUS_SPACE_MAXADDR,       /* lowaddr */
 1891                         BUS_SPACE_MAXADDR,       /* highaddr */
 1892                         NULL, NULL,      /* filter, filterarg */
 1893                         MJUM9BYTES,     /* maxsize */
 1894                         1,        /* nsegments */
 1895                         MJUM9BYTES,        /* maxsegsize */
 1896                         BUS_DMA_ALLOCNOW,        /* flags */
 1897                         NULL,    /* lockfunc */
 1898                         NULL,    /* lockfuncarg */
 1899                         &ha->rx_tag)) {
 1900                 device_printf(ha->pci_dev, "%s: rx_tag alloc failed\n",
 1901                         __func__);
 1902 
 1903                 return (ENOMEM);
 1904         }
 1905 
 1906         bzero((void *)ha->rx_ring, (sizeof(qla_rx_ring_t) * MAX_RDS_RINGS));
 1907 
 1908         for (i = 0; i < ha->hw.num_sds_rings; i++) {
 1909                 ha->hw.sds[i].sdsr_next = 0;
 1910                 ha->hw.sds[i].rxb_free = NULL;
 1911                 ha->hw.sds[i].rx_free = 0;
 1912         }
 1913 
 1914         ret = qla_alloc_rcv_std(ha);
 1915 
 1916         return (ret);
 1917 }
 1918 
 1919 static void
 1920 qla_free_rcv_bufs(qla_host_t *ha)
 1921 {
 1922         int             i;
 1923 
 1924         qla_free_rcv_std(ha);
 1925 
 1926         if (ha->rx_tag != NULL) {
 1927                 bus_dma_tag_destroy(ha->rx_tag);
 1928                 ha->rx_tag = NULL;
 1929         }
 1930 
 1931         bzero((void *)ha->rx_ring, (sizeof(qla_rx_ring_t) * MAX_RDS_RINGS));
 1932 
 1933         for (i = 0; i < ha->hw.num_sds_rings; i++) {
 1934                 ha->hw.sds[i].sdsr_next = 0;
 1935                 ha->hw.sds[i].rxb_free = NULL;
 1936                 ha->hw.sds[i].rx_free = 0;
 1937         }
 1938 
 1939         return;
 1940 }
 1941 
 1942 int
 1943 ql_get_mbuf(qla_host_t *ha, qla_rx_buf_t *rxb, struct mbuf *nmp)
 1944 {
 1945         register struct mbuf *mp = nmp;
 1946         int                     ret = 0;
 1947         uint32_t                offset;
 1948         bus_dma_segment_t       segs[1];
 1949         int                     nsegs, mbuf_size;
 1950 
 1951         QL_DPRINT2(ha, (ha->pci_dev, "%s: enter\n", __func__));
 1952 
 1953         if (ha->hw.enable_9kb)
 1954                 mbuf_size = MJUM9BYTES;
 1955         else
 1956                 mbuf_size = MCLBYTES;
 1957 
 1958         if (mp == NULL) {
 1959                 if (QL_ERR_INJECT(ha, INJCT_M_GETCL_M_GETJCL_FAILURE))
 1960                         return(-1);
 1961 
 1962                 if (ha->hw.enable_9kb)
 1963                         mp = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, mbuf_size);
 1964                 else
 1965                         mp = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
 1966 
 1967                 if (mp == NULL) {
 1968                         ha->err_m_getcl++;
 1969                         ret = ENOBUFS;
 1970                         device_printf(ha->pci_dev,
 1971                                         "%s: m_getcl failed\n", __func__);
 1972                         goto exit_ql_get_mbuf;
 1973                 }
 1974                 mp->m_len = mp->m_pkthdr.len = mbuf_size;
 1975         } else {
 1976                 mp->m_len = mp->m_pkthdr.len = mbuf_size;
 1977                 mp->m_data = mp->m_ext.ext_buf;
 1978                 mp->m_next = NULL;
 1979         }
 1980 
 1981         offset = (uint32_t)((unsigned long long)mp->m_data & 0x7ULL);
 1982         if (offset) {
 1983                 offset = 8 - offset;
 1984                 m_adj(mp, offset);
 1985         }
 1986 
 1987         /*
 1988          * Using memory from the mbuf cluster pool, invoke the bus_dma
 1989          * machinery to arrange the memory mapping.
 1990          */
 1991         ret = bus_dmamap_load_mbuf_sg(ha->rx_tag, rxb->map,
 1992                         mp, segs, &nsegs, BUS_DMA_NOWAIT);
 1993         rxb->paddr = segs[0].ds_addr;
 1994 
 1995         if (ret || !rxb->paddr || (nsegs != 1)) {
 1996                 m_free(mp);
 1997                 rxb->m_head = NULL;
 1998                 device_printf(ha->pci_dev,
 1999                         "%s: bus_dmamap_load failed[%d, 0x%016llx, %d]\n",
 2000                         __func__, ret, (long long unsigned int)rxb->paddr,
 2001                         nsegs);
 2002                 ret = -1;
 2003                 goto exit_ql_get_mbuf;
 2004         }
 2005         rxb->m_head = mp;
 2006         bus_dmamap_sync(ha->rx_tag, rxb->map, BUS_DMASYNC_PREREAD);
 2007 
 2008 exit_ql_get_mbuf:
 2009         QL_DPRINT2(ha, (ha->pci_dev, "%s: exit ret = 0x%08x\n", __func__, ret));
 2010         return (ret);
 2011 }
 2012 
 2013 static void
 2014 qla_get_peer(qla_host_t *ha)
 2015 {
 2016         device_t *peers;
 2017         int count, i, slot;
 2018         int my_slot = pci_get_slot(ha->pci_dev);
 2019 
 2020         if (device_get_children(device_get_parent(ha->pci_dev), &peers, &count))
 2021                 return;
 2022 
 2023         for (i = 0; i < count; i++) {
 2024                 slot = pci_get_slot(peers[i]);
 2025 
 2026                 if ((slot >= 0) && (slot == my_slot) &&
 2027                         (pci_get_device(peers[i]) ==
 2028                                 pci_get_device(ha->pci_dev))) {
 2029                         if (ha->pci_dev != peers[i]) 
 2030                                 ha->peer_dev = peers[i];
 2031                 }
 2032         }
 2033 }
 2034 
 2035 static void
 2036 qla_send_msg_to_peer(qla_host_t *ha, uint32_t msg_to_peer)
 2037 {
 2038         qla_host_t *ha_peer;
 2039 
 2040         if (ha->peer_dev) {
 2041                 if ((ha_peer = device_get_softc(ha->peer_dev)) != NULL) {
 2042                         ha_peer->msg_from_peer = msg_to_peer;
 2043                 }
 2044         }
 2045 }
 2046 
 2047 void
 2048 qla_set_error_recovery(qla_host_t *ha)
 2049 {
 2050         struct ifnet *ifp = ha->ifp;
 2051 
 2052         if (!cold && ha->enable_error_recovery) {
 2053                 if (ifp)
 2054                         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 2055                 ha->qla_initiate_recovery = 1;
 2056         } else
 2057                 ha->offline = 1;
 2058         return;
 2059 }
 2060 
 2061 static void
 2062 qla_error_recovery(void *context, int pending)
 2063 {
 2064         qla_host_t *ha = context;
 2065         uint32_t msecs_100 = 400;
 2066         struct ifnet *ifp = ha->ifp;
 2067         int i = 0;
 2068 
 2069         device_printf(ha->pci_dev, "%s: enter\n", __func__);
 2070         ha->hw.imd_compl = 1;
 2071 
 2072         taskqueue_drain_all(ha->stats_tq);
 2073         taskqueue_drain_all(ha->async_event_tq);
 2074 
 2075         if (QLA_LOCK(ha, __func__, -1, 0) != 0)
 2076                 return;
 2077 
 2078         device_printf(ha->pci_dev, "%s: ts_usecs = %ld start\n",
 2079                 __func__, qla_get_usec_timestamp());
 2080 
 2081         if (ha->qla_interface_up) {
 2082                 qla_mdelay(__func__, 300);
 2083 
 2084                 //ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 2085 
 2086                 for (i = 0; i < ha->hw.num_sds_rings; i++) {
 2087                         qla_tx_fp_t *fp;
 2088 
 2089                         fp = &ha->tx_fp[i];
 2090 
 2091                         if (fp == NULL)
 2092                                 continue;
 2093 
 2094                         if (fp->tx_br != NULL) {
 2095                                 mtx_lock(&fp->tx_mtx);
 2096                                 mtx_unlock(&fp->tx_mtx);
 2097                         }
 2098                 }
 2099         }
 2100 
 2101         qla_drain_fp_taskqueues(ha);
 2102 
 2103         if ((ha->pci_func & 0x1) == 0) {
 2104                 if (!ha->msg_from_peer) {
 2105                         qla_send_msg_to_peer(ha, QL_PEER_MSG_RESET);
 2106 
 2107                         while ((ha->msg_from_peer != QL_PEER_MSG_ACK) &&
 2108                                 msecs_100--)
 2109                                 qla_mdelay(__func__, 100);
 2110                 }
 2111 
 2112                 ha->msg_from_peer = 0;
 2113 
 2114                 if (ha->enable_minidump)
 2115                         ql_minidump(ha);
 2116 
 2117                 if (ha->enable_driverstate_dump)
 2118                         ql_capture_drvr_state(ha);
 2119 
 2120                 if (ql_init_hw(ha)) {
 2121                         device_printf(ha->pci_dev,
 2122                                 "%s: ts_usecs = %ld exit: ql_init_hw failed\n",
 2123                                 __func__, qla_get_usec_timestamp());
 2124                         ha->offline = 1;
 2125                         goto qla_error_recovery_exit;
 2126                 }
 2127                         
 2128                 if (ha->qla_interface_up) {
 2129                         qla_free_xmt_bufs(ha);
 2130                         qla_free_rcv_bufs(ha);
 2131                 }
 2132 
 2133                 if (!QL_ERR_INJECT(ha, INJCT_PEER_PORT_FAILURE_ERR_RECOVERY))
 2134                         qla_send_msg_to_peer(ha, QL_PEER_MSG_ACK);
 2135 
 2136         } else {
 2137                 if (ha->msg_from_peer == QL_PEER_MSG_RESET) {
 2138                         ha->msg_from_peer = 0;
 2139 
 2140                         if (!QL_ERR_INJECT(ha, INJCT_PEER_PORT_FAILURE_ERR_RECOVERY))
 2141                                 qla_send_msg_to_peer(ha, QL_PEER_MSG_ACK);
 2142                 } else {
 2143                         qla_send_msg_to_peer(ha, QL_PEER_MSG_RESET);
 2144                 }
 2145 
 2146                 while ((ha->msg_from_peer != QL_PEER_MSG_ACK)  && msecs_100--)
 2147                         qla_mdelay(__func__, 100);
 2148                 ha->msg_from_peer = 0;
 2149 
 2150                 if (ha->enable_driverstate_dump)
 2151                         ql_capture_drvr_state(ha);
 2152 
 2153                 if (msecs_100 == 0) {
 2154                         device_printf(ha->pci_dev,
 2155                                 "%s: ts_usecs = %ld exit: QL_PEER_MSG_ACK not received\n",
 2156                                 __func__, qla_get_usec_timestamp());
 2157                         ha->offline = 1;
 2158                         goto qla_error_recovery_exit;
 2159                 }
 2160 
 2161                 if (ql_init_hw(ha)) {
 2162                         device_printf(ha->pci_dev,
 2163                                 "%s: ts_usecs = %ld exit: ql_init_hw failed\n",
 2164                                 __func__, qla_get_usec_timestamp());
 2165                         ha->offline = 1;
 2166                         goto qla_error_recovery_exit;
 2167                 }
 2168 
 2169                 if (ha->qla_interface_up) {
 2170                         qla_free_xmt_bufs(ha);
 2171                         qla_free_rcv_bufs(ha);
 2172                 }
 2173         }
 2174 
 2175         qla_mdelay(__func__, ha->ms_delay_after_init);
 2176 
 2177         *((uint32_t *)&ha->hw.flags) = 0;
 2178         ha->qla_initiate_recovery = 0;
 2179 
 2180         if (ha->qla_interface_up) {
 2181                 if (qla_alloc_xmt_bufs(ha) != 0) {
 2182                         ha->offline = 1;
 2183                         goto qla_error_recovery_exit;
 2184                 }
 2185 
 2186                 qla_confirm_9kb_enable(ha);
 2187 
 2188                 if (qla_alloc_rcv_bufs(ha) != 0) {
 2189                         ha->offline = 1;
 2190                         goto qla_error_recovery_exit;
 2191                 }
 2192 
 2193                 ha->stop_rcv = 0;
 2194 
 2195                 if (ql_init_hw_if(ha) == 0) {
 2196                         ifp = ha->ifp;
 2197                         ifp->if_drv_flags |= IFF_DRV_RUNNING;
 2198                         ha->qla_watchdog_pause = 0;
 2199                         ql_update_link_state(ha);
 2200                 } else {
 2201                         ha->offline = 1;
 2202 
 2203                         if (ha->hw.sp_log_stop_events &
 2204                                 Q8_SP_LOG_STOP_IF_START_FAILURE)
 2205                                 ha->hw.sp_log_stop = -1;
 2206                 }
 2207         } else {
 2208                 ha->qla_watchdog_pause = 0;
 2209         }
 2210 
 2211 qla_error_recovery_exit:
 2212 
 2213         if (ha->offline ) {
 2214                 device_printf(ha->pci_dev, "%s: ts_usecs = %ld port offline\n",
 2215                         __func__, qla_get_usec_timestamp());
 2216                 if (ha->hw.sp_log_stop_events &
 2217                         Q8_SP_LOG_STOP_ERR_RECOVERY_FAILURE)
 2218                         ha->hw.sp_log_stop = -1;
 2219         }
 2220 
 2221         QLA_UNLOCK(ha, __func__);
 2222 
 2223         if (!ha->offline)
 2224                 callout_reset(&ha->tx_callout, QLA_WATCHDOG_CALLOUT_TICKS,
 2225                         qla_watchdog, ha);
 2226 
 2227         device_printf(ha->pci_dev,
 2228                 "%s: ts_usecs = %ld exit\n",
 2229                 __func__, qla_get_usec_timestamp());
 2230         return;
 2231 }
 2232 
 2233 static void
 2234 qla_async_event(void *context, int pending)
 2235 {
 2236         qla_host_t *ha = context;
 2237 
 2238         if (QLA_LOCK(ha, __func__, -1, 0) != 0)
 2239                 return;
 2240 
 2241         if (ha->async_event) {
 2242                 ha->async_event = 0;
 2243                 qla_hw_async_event(ha);
 2244         }
 2245 
 2246         QLA_UNLOCK(ha, __func__);
 2247 
 2248         return;
 2249 }
 2250 
 2251 static void
 2252 qla_stats(void *context, int pending)
 2253 {
 2254         qla_host_t *ha;
 2255 
 2256         ha = context;
 2257 
 2258         ql_get_stats(ha);
 2259 
 2260         return;
 2261 }

Cache object: 3f5958b3def4472ffb9239f539ee434c


[ 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.