1*2d1d418eSSumit Saxena /* 2*2d1d418eSSumit Saxena * SPDX-License-Identifier: BSD-2-Clause 3*2d1d418eSSumit Saxena * 4*2d1d418eSSumit Saxena * Copyright (c) 2020-2023, Broadcom Inc. All rights reserved. 5*2d1d418eSSumit Saxena * Support: <fbsd-storage-driver.pdl@broadcom.com> 6*2d1d418eSSumit Saxena * 7*2d1d418eSSumit Saxena * Authors: Sumit Saxena <sumit.saxena@broadcom.com> 8*2d1d418eSSumit Saxena * Chandrakanth Patil <chandrakanth.patil@broadcom.com> 9*2d1d418eSSumit Saxena * 10*2d1d418eSSumit Saxena * Redistribution and use in source and binary forms, with or without 11*2d1d418eSSumit Saxena * modification, are permitted provided that the following conditions are 12*2d1d418eSSumit Saxena * met: 13*2d1d418eSSumit Saxena * 14*2d1d418eSSumit Saxena * 1. Redistributions of source code must retain the above copyright notice, 15*2d1d418eSSumit Saxena * this list of conditions and the following disclaimer. 16*2d1d418eSSumit Saxena * 2. Redistributions in binary form must reproduce the above copyright notice, 17*2d1d418eSSumit Saxena * this list of conditions and the following disclaimer in the documentation and/or other 18*2d1d418eSSumit Saxena * materials provided with the distribution. 19*2d1d418eSSumit Saxena * 3. Neither the name of the Broadcom Inc. nor the names of its contributors 20*2d1d418eSSumit Saxena * may be used to endorse or promote products derived from this software without 21*2d1d418eSSumit Saxena * specific prior written permission. 22*2d1d418eSSumit Saxena * 23*2d1d418eSSumit Saxena * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 24*2d1d418eSSumit Saxena * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25*2d1d418eSSumit Saxena * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26*2d1d418eSSumit Saxena * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 27*2d1d418eSSumit Saxena * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28*2d1d418eSSumit Saxena * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29*2d1d418eSSumit Saxena * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30*2d1d418eSSumit Saxena * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31*2d1d418eSSumit Saxena * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32*2d1d418eSSumit Saxena * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33*2d1d418eSSumit Saxena * POSSIBILITY OF SUCH DAMAGE. 34*2d1d418eSSumit Saxena * 35*2d1d418eSSumit Saxena * The views and conclusions contained in the software and documentation are 36*2d1d418eSSumit Saxena * those of the authors and should not be interpreted as representing 37*2d1d418eSSumit Saxena * official policies,either expressed or implied, of the FreeBSD Project. 38*2d1d418eSSumit Saxena * 39*2d1d418eSSumit Saxena * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 40*2d1d418eSSumit Saxena * 41*2d1d418eSSumit Saxena * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD 42*2d1d418eSSumit Saxena */ 43*2d1d418eSSumit Saxena 44*2d1d418eSSumit Saxena #include "mpi3mr.h" 45*2d1d418eSSumit Saxena #include "mpi3mr_cam.h" 46*2d1d418eSSumit Saxena #include "mpi3mr_app.h" 47*2d1d418eSSumit Saxena 48*2d1d418eSSumit Saxena static int sc_ids; 49*2d1d418eSSumit Saxena static int mpi3mr_pci_probe(device_t); 50*2d1d418eSSumit Saxena static int mpi3mr_pci_attach(device_t); 51*2d1d418eSSumit Saxena static int mpi3mr_pci_detach(device_t); 52*2d1d418eSSumit Saxena static int mpi3mr_pci_suspend(device_t); 53*2d1d418eSSumit Saxena static int mpi3mr_pci_resume(device_t); 54*2d1d418eSSumit Saxena static int mpi3mr_setup_resources(struct mpi3mr_softc *sc); 55*2d1d418eSSumit Saxena static void mpi3mr_release_resources(struct mpi3mr_softc *); 56*2d1d418eSSumit Saxena static void mpi3mr_teardown_irqs(struct mpi3mr_softc *sc); 57*2d1d418eSSumit Saxena 58*2d1d418eSSumit Saxena extern void mpi3mr_watchdog_thread(void *arg); 59*2d1d418eSSumit Saxena 60*2d1d418eSSumit Saxena static device_method_t mpi3mr_methods[] = { 61*2d1d418eSSumit Saxena DEVMETHOD(device_probe, mpi3mr_pci_probe), 62*2d1d418eSSumit Saxena DEVMETHOD(device_attach, mpi3mr_pci_attach), 63*2d1d418eSSumit Saxena DEVMETHOD(device_detach, mpi3mr_pci_detach), 64*2d1d418eSSumit Saxena DEVMETHOD(device_suspend, mpi3mr_pci_suspend), 65*2d1d418eSSumit Saxena DEVMETHOD(device_resume, mpi3mr_pci_resume), 66*2d1d418eSSumit Saxena DEVMETHOD(bus_print_child, bus_generic_print_child), 67*2d1d418eSSumit Saxena DEVMETHOD(bus_driver_added, bus_generic_driver_added), 68*2d1d418eSSumit Saxena { 0, 0 } 69*2d1d418eSSumit Saxena }; 70*2d1d418eSSumit Saxena 71*2d1d418eSSumit Saxena char fmt_os_ver[16]; 72*2d1d418eSSumit Saxena 73*2d1d418eSSumit Saxena SYSCTL_NODE(_hw, OID_AUTO, mpi3mr, CTLFLAG_RD, 0, "MPI3MR Driver Parameters"); 74*2d1d418eSSumit Saxena MALLOC_DEFINE(M_MPI3MR, "mpi3mrbuf", "Buffers for the MPI3MR driver"); 75*2d1d418eSSumit Saxena 76*2d1d418eSSumit Saxena static driver_t mpi3mr_pci_driver = { 77*2d1d418eSSumit Saxena "mpi3mr", 78*2d1d418eSSumit Saxena mpi3mr_methods, 79*2d1d418eSSumit Saxena sizeof(struct mpi3mr_softc) 80*2d1d418eSSumit Saxena }; 81*2d1d418eSSumit Saxena 82*2d1d418eSSumit Saxena struct mpi3mr_ident { 83*2d1d418eSSumit Saxena uint16_t vendor; 84*2d1d418eSSumit Saxena uint16_t device; 85*2d1d418eSSumit Saxena uint16_t subvendor; 86*2d1d418eSSumit Saxena uint16_t subdevice; 87*2d1d418eSSumit Saxena u_int flags; 88*2d1d418eSSumit Saxena const char *desc; 89*2d1d418eSSumit Saxena } mpi3mr_identifiers[] = { 90*2d1d418eSSumit Saxena { MPI3_MFGPAGE_VENDORID_BROADCOM, MPI3_MFGPAGE_DEVID_SAS4116, 91*2d1d418eSSumit Saxena 0xffff, 0xffff, 0, "Broadcom MPIMR 3.0 controller" }, 92*2d1d418eSSumit Saxena }; 93*2d1d418eSSumit Saxena 94*2d1d418eSSumit Saxena DRIVER_MODULE(mpi3mr, pci, mpi3mr_pci_driver, 0, 0); 95*2d1d418eSSumit Saxena MODULE_PNP_INFO("U16:vendor;U16:device;U16:subvendor;U16:subdevice;D:#", pci, 96*2d1d418eSSumit Saxena mpi3mr, mpi3mr_identifiers, nitems(mpi3mr_identifiers) - 1); 97*2d1d418eSSumit Saxena 98*2d1d418eSSumit Saxena MODULE_DEPEND(mpi3mr, cam, 1, 1, 1); 99*2d1d418eSSumit Saxena 100*2d1d418eSSumit Saxena /* 101*2d1d418eSSumit Saxena * mpi3mr_setup_sysctl: setup sysctl values for mpi3mr 102*2d1d418eSSumit Saxena * input: Adapter instance soft state 103*2d1d418eSSumit Saxena * 104*2d1d418eSSumit Saxena * Setup sysctl entries for mpi3mr driver. 105*2d1d418eSSumit Saxena */ 106*2d1d418eSSumit Saxena static void 107*2d1d418eSSumit Saxena mpi3mr_setup_sysctl(struct mpi3mr_softc *sc) 108*2d1d418eSSumit Saxena { 109*2d1d418eSSumit Saxena struct sysctl_ctx_list *sysctl_ctx = NULL; 110*2d1d418eSSumit Saxena struct sysctl_oid *sysctl_tree = NULL; 111*2d1d418eSSumit Saxena char tmpstr[80], tmpstr2[80]; 112*2d1d418eSSumit Saxena 113*2d1d418eSSumit Saxena /* 114*2d1d418eSSumit Saxena * Setup the sysctl variable so the user can change the debug level 115*2d1d418eSSumit Saxena * on the fly. 116*2d1d418eSSumit Saxena */ 117*2d1d418eSSumit Saxena snprintf(tmpstr, sizeof(tmpstr), "MPI3MR controller %d", 118*2d1d418eSSumit Saxena device_get_unit(sc->mpi3mr_dev)); 119*2d1d418eSSumit Saxena snprintf(tmpstr2, sizeof(tmpstr2), "%d", device_get_unit(sc->mpi3mr_dev)); 120*2d1d418eSSumit Saxena 121*2d1d418eSSumit Saxena sysctl_ctx = device_get_sysctl_ctx(sc->mpi3mr_dev); 122*2d1d418eSSumit Saxena if (sysctl_ctx != NULL) 123*2d1d418eSSumit Saxena sysctl_tree = device_get_sysctl_tree(sc->mpi3mr_dev); 124*2d1d418eSSumit Saxena 125*2d1d418eSSumit Saxena if (sysctl_tree == NULL) { 126*2d1d418eSSumit Saxena sysctl_ctx_init(&sc->sysctl_ctx); 127*2d1d418eSSumit Saxena sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, 128*2d1d418eSSumit Saxena SYSCTL_STATIC_CHILDREN(_hw_mpi3mr), OID_AUTO, tmpstr2, 129*2d1d418eSSumit Saxena CTLFLAG_RD, 0, tmpstr); 130*2d1d418eSSumit Saxena if (sc->sysctl_tree == NULL) 131*2d1d418eSSumit Saxena return; 132*2d1d418eSSumit Saxena sysctl_ctx = &sc->sysctl_ctx; 133*2d1d418eSSumit Saxena sysctl_tree = sc->sysctl_tree; 134*2d1d418eSSumit Saxena } 135*2d1d418eSSumit Saxena 136*2d1d418eSSumit Saxena SYSCTL_ADD_STRING(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 137*2d1d418eSSumit Saxena OID_AUTO, "driver_version", CTLFLAG_RD, MPI3MR_DRIVER_VERSION, 138*2d1d418eSSumit Saxena strlen(MPI3MR_DRIVER_VERSION), "driver version"); 139*2d1d418eSSumit Saxena 140*2d1d418eSSumit Saxena SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 141*2d1d418eSSumit Saxena OID_AUTO, "fw_outstanding", CTLFLAG_RD, 142*2d1d418eSSumit Saxena &sc->fw_outstanding.val_rdonly, 0, "FW outstanding commands"); 143*2d1d418eSSumit Saxena 144*2d1d418eSSumit Saxena SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 145*2d1d418eSSumit Saxena OID_AUTO, "io_cmds_highwater", CTLFLAG_RD, 146*2d1d418eSSumit Saxena &sc->io_cmds_highwater, 0, "Max FW outstanding commands"); 147*2d1d418eSSumit Saxena 148*2d1d418eSSumit Saxena SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 149*2d1d418eSSumit Saxena OID_AUTO, "mpi3mr_debug", CTLFLAG_RW, &sc->mpi3mr_debug, 0, 150*2d1d418eSSumit Saxena "Driver debug level"); 151*2d1d418eSSumit Saxena SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 152*2d1d418eSSumit Saxena OID_AUTO, "reset", CTLFLAG_RW, &sc->reset.type, 0, 153*2d1d418eSSumit Saxena "Soft reset(1)/Diag reset(2)"); 154*2d1d418eSSumit Saxena SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), 155*2d1d418eSSumit Saxena OID_AUTO, "iot_enable", CTLFLAG_RW, &sc->iot_enable, 0, 156*2d1d418eSSumit Saxena "IO throttling enable at driver level(for debug purpose)"); 157*2d1d418eSSumit Saxena } 158*2d1d418eSSumit Saxena 159*2d1d418eSSumit Saxena /* 160*2d1d418eSSumit Saxena * mpi3mr_get_tunables: get tunable parameters. 161*2d1d418eSSumit Saxena * input: Adapter instance soft state 162*2d1d418eSSumit Saxena * 163*2d1d418eSSumit Saxena * Get tunable parameters. This will help to debug driver at boot time. 164*2d1d418eSSumit Saxena */ 165*2d1d418eSSumit Saxena static void 166*2d1d418eSSumit Saxena mpi3mr_get_tunables(struct mpi3mr_softc *sc) 167*2d1d418eSSumit Saxena { 168*2d1d418eSSumit Saxena char tmpstr[80]; 169*2d1d418eSSumit Saxena 170*2d1d418eSSumit Saxena sc->mpi3mr_debug = 171*2d1d418eSSumit Saxena (MPI3MR_ERROR | MPI3MR_INFO | MPI3MR_FAULT); 172*2d1d418eSSumit Saxena 173*2d1d418eSSumit Saxena sc->reset_in_progress = 0; 174*2d1d418eSSumit Saxena sc->reset.type = 0; 175*2d1d418eSSumit Saxena sc->iot_enable = 1; 176*2d1d418eSSumit Saxena /* 177*2d1d418eSSumit Saxena * Grab the global variables. 178*2d1d418eSSumit Saxena */ 179*2d1d418eSSumit Saxena TUNABLE_INT_FETCH("hw.mpi3mr.debug_level", &sc->mpi3mr_debug); 180*2d1d418eSSumit Saxena TUNABLE_INT_FETCH("hw.mpi3mr.ctrl_reset", &sc->reset.type); 181*2d1d418eSSumit Saxena TUNABLE_INT_FETCH("hw.mpi3mr.iot_enable", &sc->iot_enable); 182*2d1d418eSSumit Saxena 183*2d1d418eSSumit Saxena /* Grab the unit-instance variables */ 184*2d1d418eSSumit Saxena snprintf(tmpstr, sizeof(tmpstr), "dev.mpi3mr.%d.debug_level", 185*2d1d418eSSumit Saxena device_get_unit(sc->mpi3mr_dev)); 186*2d1d418eSSumit Saxena TUNABLE_INT_FETCH(tmpstr, &sc->mpi3mr_debug); 187*2d1d418eSSumit Saxena 188*2d1d418eSSumit Saxena snprintf(tmpstr, sizeof(tmpstr), "dev.mpi3mr.%d.reset", 189*2d1d418eSSumit Saxena device_get_unit(sc->mpi3mr_dev)); 190*2d1d418eSSumit Saxena TUNABLE_INT_FETCH(tmpstr, &sc->reset.type); 191*2d1d418eSSumit Saxena 192*2d1d418eSSumit Saxena snprintf(tmpstr, sizeof(tmpstr), "dev.mpi3mr.%d.iot_enable", 193*2d1d418eSSumit Saxena device_get_unit(sc->mpi3mr_dev)); 194*2d1d418eSSumit Saxena TUNABLE_INT_FETCH(tmpstr, &sc->iot_enable); 195*2d1d418eSSumit Saxena } 196*2d1d418eSSumit Saxena 197*2d1d418eSSumit Saxena static struct mpi3mr_ident * 198*2d1d418eSSumit Saxena mpi3mr_find_ident(device_t dev) 199*2d1d418eSSumit Saxena { 200*2d1d418eSSumit Saxena struct mpi3mr_ident *m; 201*2d1d418eSSumit Saxena 202*2d1d418eSSumit Saxena for (m = mpi3mr_identifiers; m->vendor != 0; m++) { 203*2d1d418eSSumit Saxena if (m->vendor != pci_get_vendor(dev)) 204*2d1d418eSSumit Saxena continue; 205*2d1d418eSSumit Saxena if (m->device != pci_get_device(dev)) 206*2d1d418eSSumit Saxena continue; 207*2d1d418eSSumit Saxena if ((m->subvendor != 0xffff) && 208*2d1d418eSSumit Saxena (m->subvendor != pci_get_subvendor(dev))) 209*2d1d418eSSumit Saxena continue; 210*2d1d418eSSumit Saxena if ((m->subdevice != 0xffff) && 211*2d1d418eSSumit Saxena (m->subdevice != pci_get_subdevice(dev))) 212*2d1d418eSSumit Saxena continue; 213*2d1d418eSSumit Saxena return (m); 214*2d1d418eSSumit Saxena } 215*2d1d418eSSumit Saxena 216*2d1d418eSSumit Saxena return (NULL); 217*2d1d418eSSumit Saxena } 218*2d1d418eSSumit Saxena 219*2d1d418eSSumit Saxena static int 220*2d1d418eSSumit Saxena mpi3mr_pci_probe(device_t dev) 221*2d1d418eSSumit Saxena { 222*2d1d418eSSumit Saxena static u_int8_t first_ctrl = 1; 223*2d1d418eSSumit Saxena struct mpi3mr_ident *id; 224*2d1d418eSSumit Saxena char raw_os_ver[16]; 225*2d1d418eSSumit Saxena 226*2d1d418eSSumit Saxena if ((id = mpi3mr_find_ident(dev)) != NULL) { 227*2d1d418eSSumit Saxena if (first_ctrl) { 228*2d1d418eSSumit Saxena first_ctrl = 0; 229*2d1d418eSSumit Saxena MPI3MR_OS_VERSION(raw_os_ver, fmt_os_ver); 230*2d1d418eSSumit Saxena printf("mpi3mr: Loading Broadcom mpi3mr driver version: %s OS version: %s\n", 231*2d1d418eSSumit Saxena MPI3MR_DRIVER_VERSION, fmt_os_ver); 232*2d1d418eSSumit Saxena } 233*2d1d418eSSumit Saxena device_set_desc(dev, id->desc); 234*2d1d418eSSumit Saxena device_set_desc(dev, id->desc); 235*2d1d418eSSumit Saxena return (BUS_PROBE_DEFAULT); 236*2d1d418eSSumit Saxena } 237*2d1d418eSSumit Saxena return (ENXIO); 238*2d1d418eSSumit Saxena } 239*2d1d418eSSumit Saxena 240*2d1d418eSSumit Saxena static void 241*2d1d418eSSumit Saxena mpi3mr_release_resources(struct mpi3mr_softc *sc) 242*2d1d418eSSumit Saxena { 243*2d1d418eSSumit Saxena if (sc->mpi3mr_parent_dmat != NULL) { 244*2d1d418eSSumit Saxena bus_dma_tag_destroy(sc->mpi3mr_parent_dmat); 245*2d1d418eSSumit Saxena } 246*2d1d418eSSumit Saxena 247*2d1d418eSSumit Saxena if (sc->mpi3mr_regs_resource != NULL) { 248*2d1d418eSSumit Saxena bus_release_resource(sc->mpi3mr_dev, SYS_RES_MEMORY, 249*2d1d418eSSumit Saxena sc->mpi3mr_regs_rid, sc->mpi3mr_regs_resource); 250*2d1d418eSSumit Saxena } 251*2d1d418eSSumit Saxena } 252*2d1d418eSSumit Saxena 253*2d1d418eSSumit Saxena static int mpi3mr_setup_resources(struct mpi3mr_softc *sc) 254*2d1d418eSSumit Saxena { 255*2d1d418eSSumit Saxena int i; 256*2d1d418eSSumit Saxena device_t dev = sc->mpi3mr_dev; 257*2d1d418eSSumit Saxena 258*2d1d418eSSumit Saxena pci_enable_busmaster(dev); 259*2d1d418eSSumit Saxena 260*2d1d418eSSumit Saxena for (i = 0; i < PCI_MAXMAPS_0; i++) { 261*2d1d418eSSumit Saxena sc->mpi3mr_regs_rid = PCIR_BAR(i); 262*2d1d418eSSumit Saxena 263*2d1d418eSSumit Saxena if ((sc->mpi3mr_regs_resource = bus_alloc_resource_any(dev, 264*2d1d418eSSumit Saxena SYS_RES_MEMORY, &sc->mpi3mr_regs_rid, RF_ACTIVE)) != NULL) 265*2d1d418eSSumit Saxena break; 266*2d1d418eSSumit Saxena } 267*2d1d418eSSumit Saxena 268*2d1d418eSSumit Saxena if (sc->mpi3mr_regs_resource == NULL) { 269*2d1d418eSSumit Saxena mpi3mr_printf(sc, "Cannot allocate PCI registers\n"); 270*2d1d418eSSumit Saxena return (ENXIO); 271*2d1d418eSSumit Saxena } 272*2d1d418eSSumit Saxena 273*2d1d418eSSumit Saxena sc->mpi3mr_btag = rman_get_bustag(sc->mpi3mr_regs_resource); 274*2d1d418eSSumit Saxena sc->mpi3mr_bhandle = rman_get_bushandle(sc->mpi3mr_regs_resource); 275*2d1d418eSSumit Saxena 276*2d1d418eSSumit Saxena /* Allocate the parent DMA tag */ 277*2d1d418eSSumit Saxena if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 278*2d1d418eSSumit Saxena 1, 0, /* algnmnt, boundary */ 279*2d1d418eSSumit Saxena BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ 280*2d1d418eSSumit Saxena BUS_SPACE_MAXADDR, /* highaddr */ 281*2d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 282*2d1d418eSSumit Saxena BUS_SPACE_MAXSIZE_32BIT,/* maxsize */ 283*2d1d418eSSumit Saxena BUS_SPACE_UNRESTRICTED, /* nsegments */ 284*2d1d418eSSumit Saxena BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ 285*2d1d418eSSumit Saxena 0, /* flags */ 286*2d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 287*2d1d418eSSumit Saxena &sc->mpi3mr_parent_dmat)) { 288*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate parent DMA tag\n"); 289*2d1d418eSSumit Saxena return (ENOMEM); 290*2d1d418eSSumit Saxena } 291*2d1d418eSSumit Saxena 292*2d1d418eSSumit Saxena sc->max_msix_vectors = pci_msix_count(dev); 293*2d1d418eSSumit Saxena 294*2d1d418eSSumit Saxena return 0; 295*2d1d418eSSumit Saxena } 296*2d1d418eSSumit Saxena 297*2d1d418eSSumit Saxena static int 298*2d1d418eSSumit Saxena mpi3mr_startup(struct mpi3mr_softc *sc) 299*2d1d418eSSumit Saxena { 300*2d1d418eSSumit Saxena sc->mpi3mr_flags &= ~MPI3MR_FLAGS_PORT_ENABLE_DONE; 301*2d1d418eSSumit Saxena mpi3mr_issue_port_enable(sc, 1); 302*2d1d418eSSumit Saxena return (0); 303*2d1d418eSSumit Saxena } 304*2d1d418eSSumit Saxena 305*2d1d418eSSumit Saxena /* Run through any late-start handlers. */ 306*2d1d418eSSumit Saxena static void 307*2d1d418eSSumit Saxena mpi3mr_ich_startup(void *arg) 308*2d1d418eSSumit Saxena { 309*2d1d418eSSumit Saxena struct mpi3mr_softc *sc; 310*2d1d418eSSumit Saxena 311*2d1d418eSSumit Saxena sc = (struct mpi3mr_softc *)arg; 312*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "%s entry\n", __func__); 313*2d1d418eSSumit Saxena 314*2d1d418eSSumit Saxena mtx_lock(&sc->mpi3mr_mtx); 315*2d1d418eSSumit Saxena 316*2d1d418eSSumit Saxena mpi3mr_startup(sc); 317*2d1d418eSSumit Saxena mtx_unlock(&sc->mpi3mr_mtx); 318*2d1d418eSSumit Saxena 319*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "disestablish config intrhook\n"); 320*2d1d418eSSumit Saxena config_intrhook_disestablish(&sc->mpi3mr_ich); 321*2d1d418eSSumit Saxena sc->mpi3mr_ich.ich_arg = NULL; 322*2d1d418eSSumit Saxena 323*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "%s exit\n", __func__); 324*2d1d418eSSumit Saxena } 325*2d1d418eSSumit Saxena 326*2d1d418eSSumit Saxena /** 327*2d1d418eSSumit Saxena * mpi3mr_ctrl_security_status -Check controller secure status 328*2d1d418eSSumit Saxena * @pdev: PCI device instance 329*2d1d418eSSumit Saxena * 330*2d1d418eSSumit Saxena * Read the Device Serial Number capability from PCI config 331*2d1d418eSSumit Saxena * space and decide whether the controller is secure or not. 332*2d1d418eSSumit Saxena * 333*2d1d418eSSumit Saxena * Return: 0 on success, non-zero on failure. 334*2d1d418eSSumit Saxena */ 335*2d1d418eSSumit Saxena static int 336*2d1d418eSSumit Saxena mpi3mr_ctrl_security_status(device_t dev) 337*2d1d418eSSumit Saxena { 338*2d1d418eSSumit Saxena int dev_serial_num, retval = 0; 339*2d1d418eSSumit Saxena uint32_t cap_data, ctrl_status, debug_status; 340*2d1d418eSSumit Saxena /* Check if Device serial number extended capability is supported */ 341*2d1d418eSSumit Saxena if (pci_find_extcap(dev, PCIZ_SERNUM, &dev_serial_num) != 0) { 342*2d1d418eSSumit Saxena device_printf(dev, 343*2d1d418eSSumit Saxena "PCIZ_SERNUM is not supported\n"); 344*2d1d418eSSumit Saxena return -1; 345*2d1d418eSSumit Saxena } 346*2d1d418eSSumit Saxena 347*2d1d418eSSumit Saxena cap_data = pci_read_config(dev, dev_serial_num + 4, 4); 348*2d1d418eSSumit Saxena 349*2d1d418eSSumit Saxena debug_status = cap_data & MPI3MR_CTLR_SECURE_DBG_STATUS_MASK; 350*2d1d418eSSumit Saxena ctrl_status = cap_data & MPI3MR_CTLR_SECURITY_STATUS_MASK; 351*2d1d418eSSumit Saxena 352*2d1d418eSSumit Saxena switch (ctrl_status) { 353*2d1d418eSSumit Saxena case MPI3MR_INVALID_DEVICE: 354*2d1d418eSSumit Saxena device_printf(dev, 355*2d1d418eSSumit Saxena "Invalid (Non secure) controller is detected: DID: 0x%x: SVID: 0x%x: SDID: 0x%x\n", 356*2d1d418eSSumit Saxena pci_get_device(dev), pci_get_subvendor(dev), 357*2d1d418eSSumit Saxena pci_get_subdevice(dev)); 358*2d1d418eSSumit Saxena retval = -1; 359*2d1d418eSSumit Saxena break; 360*2d1d418eSSumit Saxena case MPI3MR_CONFIG_SECURE_DEVICE: 361*2d1d418eSSumit Saxena if (!debug_status) 362*2d1d418eSSumit Saxena device_printf(dev, "Config secure controller is detected\n"); 363*2d1d418eSSumit Saxena break; 364*2d1d418eSSumit Saxena case MPI3MR_HARD_SECURE_DEVICE: 365*2d1d418eSSumit Saxena device_printf(dev, "Hard secure controller is detected\n"); 366*2d1d418eSSumit Saxena break; 367*2d1d418eSSumit Saxena case MPI3MR_TAMPERED_DEVICE: 368*2d1d418eSSumit Saxena device_printf(dev, 369*2d1d418eSSumit Saxena "Tampered (Non secure) controller is detected: DID: 0x%x: SVID: 0x%x: SDID: 0x%x\n", 370*2d1d418eSSumit Saxena pci_get_device(dev), pci_get_subvendor(dev), 371*2d1d418eSSumit Saxena pci_get_subdevice(dev)); 372*2d1d418eSSumit Saxena retval = -1; 373*2d1d418eSSumit Saxena break; 374*2d1d418eSSumit Saxena default: 375*2d1d418eSSumit Saxena retval = -1; 376*2d1d418eSSumit Saxena break; 377*2d1d418eSSumit Saxena } 378*2d1d418eSSumit Saxena 379*2d1d418eSSumit Saxena if (!retval && debug_status) { 380*2d1d418eSSumit Saxena device_printf(dev, 381*2d1d418eSSumit Saxena "Secure Debug (Non secure) controller is detected: DID: 0x%x: SVID: 0x%x: SDID: 0x%x\n", 382*2d1d418eSSumit Saxena pci_get_device(dev), pci_get_subvendor(dev), 383*2d1d418eSSumit Saxena pci_get_subdevice(dev)); 384*2d1d418eSSumit Saxena retval = -1; 385*2d1d418eSSumit Saxena } 386*2d1d418eSSumit Saxena 387*2d1d418eSSumit Saxena return retval; 388*2d1d418eSSumit Saxena } 389*2d1d418eSSumit Saxena /* 390*2d1d418eSSumit Saxena * mpi3mr_pci_attach - PCI entry point 391*2d1d418eSSumit Saxena * @dev: pointer to device struct 392*2d1d418eSSumit Saxena * 393*2d1d418eSSumit Saxena * This function does the setup of PCI and registers, allocates controller resources, 394*2d1d418eSSumit Saxena * initializes mutexes, linked lists and registers interrupts, CAM and initializes 395*2d1d418eSSumit Saxena * the controller. 396*2d1d418eSSumit Saxena * 397*2d1d418eSSumit Saxena * Return: 0 on success and proper error codes on failure 398*2d1d418eSSumit Saxena */ 399*2d1d418eSSumit Saxena static int 400*2d1d418eSSumit Saxena mpi3mr_pci_attach(device_t dev) 401*2d1d418eSSumit Saxena { 402*2d1d418eSSumit Saxena struct mpi3mr_softc *sc; 403*2d1d418eSSumit Saxena int error; 404*2d1d418eSSumit Saxena 405*2d1d418eSSumit Saxena sc = device_get_softc(dev); 406*2d1d418eSSumit Saxena bzero(sc, sizeof(*sc)); 407*2d1d418eSSumit Saxena sc->mpi3mr_dev = dev; 408*2d1d418eSSumit Saxena 409*2d1d418eSSumit Saxena /* Don't load driver for Non-Secure controllers */ 410*2d1d418eSSumit Saxena if (mpi3mr_ctrl_security_status(dev)) { 411*2d1d418eSSumit Saxena sc->secure_ctrl = false; 412*2d1d418eSSumit Saxena return 0; 413*2d1d418eSSumit Saxena } 414*2d1d418eSSumit Saxena 415*2d1d418eSSumit Saxena sc->secure_ctrl = true; 416*2d1d418eSSumit Saxena 417*2d1d418eSSumit Saxena if ((error = mpi3mr_setup_resources(sc)) != 0) 418*2d1d418eSSumit Saxena goto load_failed; 419*2d1d418eSSumit Saxena 420*2d1d418eSSumit Saxena sc->id = sc_ids++; 421*2d1d418eSSumit Saxena mpi3mr_atomic_set(&sc->fw_outstanding, 0); 422*2d1d418eSSumit Saxena mpi3mr_atomic_set(&sc->pend_ioctls, 0); 423*2d1d418eSSumit Saxena sc->admin_req = NULL; 424*2d1d418eSSumit Saxena sc->admin_reply = NULL; 425*2d1d418eSSumit Saxena sprintf(sc->driver_name, "%s", MPI3MR_DRIVER_NAME); 426*2d1d418eSSumit Saxena sprintf(sc->name, "%s%d", sc->driver_name, sc->id); 427*2d1d418eSSumit Saxena 428*2d1d418eSSumit Saxena sc->mpi3mr_dev = dev; 429*2d1d418eSSumit Saxena mpi3mr_get_tunables(sc); 430*2d1d418eSSumit Saxena 431*2d1d418eSSumit Saxena if ((error = mpi3mr_initialize_ioc(sc, MPI3MR_INIT_TYPE_INIT)) != 0) { 432*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "FW initialization failed\n"); 433*2d1d418eSSumit Saxena goto load_failed; 434*2d1d418eSSumit Saxena } 435*2d1d418eSSumit Saxena 436*2d1d418eSSumit Saxena if ((error = mpi3mr_alloc_requests(sc)) != 0) { 437*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Command frames allocation failed\n"); 438*2d1d418eSSumit Saxena goto load_failed; 439*2d1d418eSSumit Saxena } 440*2d1d418eSSumit Saxena 441*2d1d418eSSumit Saxena if ((error = mpi3mr_cam_attach(sc)) != 0) { 442*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "CAM attach failed\n"); 443*2d1d418eSSumit Saxena goto load_failed; 444*2d1d418eSSumit Saxena } 445*2d1d418eSSumit Saxena 446*2d1d418eSSumit Saxena error = mpi3mr_kproc_create(mpi3mr_watchdog_thread, sc, 447*2d1d418eSSumit Saxena &sc->watchdog_thread, 0, 0, "mpi3mr_watchdog%d", 448*2d1d418eSSumit Saxena device_get_unit(sc->mpi3mr_dev)); 449*2d1d418eSSumit Saxena if (error) { 450*2d1d418eSSumit Saxena device_printf(sc->mpi3mr_dev, "Error %d starting OCR thread\n", error); 451*2d1d418eSSumit Saxena goto load_failed; 452*2d1d418eSSumit Saxena } 453*2d1d418eSSumit Saxena 454*2d1d418eSSumit Saxena sc->mpi3mr_ich.ich_func = mpi3mr_ich_startup; 455*2d1d418eSSumit Saxena sc->mpi3mr_ich.ich_arg = sc; 456*2d1d418eSSumit Saxena if (config_intrhook_establish(&sc->mpi3mr_ich) != 0) { 457*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 458*2d1d418eSSumit Saxena "Cannot establish MPI3MR ICH config hook\n"); 459*2d1d418eSSumit Saxena error = EINVAL; 460*2d1d418eSSumit Saxena } 461*2d1d418eSSumit Saxena 462*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "allocating ioctl dma buffers\n"); 463*2d1d418eSSumit Saxena mpi3mr_alloc_ioctl_dma_memory(sc); 464*2d1d418eSSumit Saxena 465*2d1d418eSSumit Saxena if ((error = mpi3mr_app_attach(sc)) != 0) { 466*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "APP/IOCTL attach failed\n"); 467*2d1d418eSSumit Saxena goto load_failed; 468*2d1d418eSSumit Saxena } 469*2d1d418eSSumit Saxena 470*2d1d418eSSumit Saxena mpi3mr_setup_sysctl(sc); 471*2d1d418eSSumit Saxena 472*2d1d418eSSumit Saxena return 0; 473*2d1d418eSSumit Saxena 474*2d1d418eSSumit Saxena load_failed: 475*2d1d418eSSumit Saxena mpi3mr_cleanup_interrupts(sc); 476*2d1d418eSSumit Saxena mpi3mr_free_mem(sc); 477*2d1d418eSSumit Saxena mpi3mr_app_detach(sc); 478*2d1d418eSSumit Saxena mpi3mr_cam_detach(sc); 479*2d1d418eSSumit Saxena mpi3mr_destory_mtx(sc); 480*2d1d418eSSumit Saxena mpi3mr_release_resources(sc); 481*2d1d418eSSumit Saxena return error; 482*2d1d418eSSumit Saxena } 483*2d1d418eSSumit Saxena 484*2d1d418eSSumit Saxena void mpi3mr_cleanup_interrupts(struct mpi3mr_softc *sc) 485*2d1d418eSSumit Saxena { 486*2d1d418eSSumit Saxena mpi3mr_disable_interrupts(sc); 487*2d1d418eSSumit Saxena 488*2d1d418eSSumit Saxena mpi3mr_teardown_irqs(sc); 489*2d1d418eSSumit Saxena 490*2d1d418eSSumit Saxena if (sc->irq_ctx) { 491*2d1d418eSSumit Saxena free(sc->irq_ctx, M_MPI3MR); 492*2d1d418eSSumit Saxena sc->irq_ctx = NULL; 493*2d1d418eSSumit Saxena } 494*2d1d418eSSumit Saxena 495*2d1d418eSSumit Saxena if (sc->msix_enable) 496*2d1d418eSSumit Saxena pci_release_msi(sc->mpi3mr_dev); 497*2d1d418eSSumit Saxena 498*2d1d418eSSumit Saxena sc->msix_count = 0; 499*2d1d418eSSumit Saxena 500*2d1d418eSSumit Saxena } 501*2d1d418eSSumit Saxena 502*2d1d418eSSumit Saxena int mpi3mr_setup_irqs(struct mpi3mr_softc *sc) 503*2d1d418eSSumit Saxena { 504*2d1d418eSSumit Saxena device_t dev; 505*2d1d418eSSumit Saxena int error; 506*2d1d418eSSumit Saxena int i, rid, initial_rid; 507*2d1d418eSSumit Saxena struct mpi3mr_irq_context *irq_ctx; 508*2d1d418eSSumit Saxena struct irq_info *irq_info; 509*2d1d418eSSumit Saxena 510*2d1d418eSSumit Saxena dev = sc->mpi3mr_dev; 511*2d1d418eSSumit Saxena error = -1; 512*2d1d418eSSumit Saxena 513*2d1d418eSSumit Saxena if (sc->msix_enable) 514*2d1d418eSSumit Saxena initial_rid = 1; 515*2d1d418eSSumit Saxena else 516*2d1d418eSSumit Saxena initial_rid = 0; 517*2d1d418eSSumit Saxena 518*2d1d418eSSumit Saxena for (i = 0; i < sc->msix_count; i++) { 519*2d1d418eSSumit Saxena irq_ctx = &sc->irq_ctx[i]; 520*2d1d418eSSumit Saxena irq_ctx->msix_index = i; 521*2d1d418eSSumit Saxena irq_ctx->sc = sc; 522*2d1d418eSSumit Saxena irq_info = &irq_ctx->irq_info; 523*2d1d418eSSumit Saxena rid = i + initial_rid; 524*2d1d418eSSumit Saxena irq_info->irq_rid = rid; 525*2d1d418eSSumit Saxena irq_info->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 526*2d1d418eSSumit Saxena &irq_info->irq_rid, RF_ACTIVE); 527*2d1d418eSSumit Saxena if (irq_info->irq == NULL) { 528*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 529*2d1d418eSSumit Saxena "Cannot allocate interrupt RID %d\n", rid); 530*2d1d418eSSumit Saxena sc->msix_count = i; 531*2d1d418eSSumit Saxena break; 532*2d1d418eSSumit Saxena } 533*2d1d418eSSumit Saxena error = bus_setup_intr(dev, irq_info->irq, 534*2d1d418eSSumit Saxena INTR_MPSAFE | INTR_TYPE_CAM, NULL, mpi3mr_isr, 535*2d1d418eSSumit Saxena irq_ctx, &irq_info->intrhand); 536*2d1d418eSSumit Saxena if (error) { 537*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 538*2d1d418eSSumit Saxena "Cannot setup interrupt RID %d\n", rid); 539*2d1d418eSSumit Saxena sc->msix_count = i; 540*2d1d418eSSumit Saxena break; 541*2d1d418eSSumit Saxena } 542*2d1d418eSSumit Saxena } 543*2d1d418eSSumit Saxena 544*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Set up %d MSI-x interrupts\n", sc->msix_count); 545*2d1d418eSSumit Saxena 546*2d1d418eSSumit Saxena return (error); 547*2d1d418eSSumit Saxena 548*2d1d418eSSumit Saxena } 549*2d1d418eSSumit Saxena 550*2d1d418eSSumit Saxena static void 551*2d1d418eSSumit Saxena mpi3mr_teardown_irqs(struct mpi3mr_softc *sc) 552*2d1d418eSSumit Saxena { 553*2d1d418eSSumit Saxena struct irq_info *irq_info; 554*2d1d418eSSumit Saxena int i; 555*2d1d418eSSumit Saxena 556*2d1d418eSSumit Saxena for (i = 0; i < sc->msix_count; i++) { 557*2d1d418eSSumit Saxena irq_info = &sc->irq_ctx[i].irq_info; 558*2d1d418eSSumit Saxena if (irq_info->irq != NULL) { 559*2d1d418eSSumit Saxena bus_teardown_intr(sc->mpi3mr_dev, irq_info->irq, 560*2d1d418eSSumit Saxena irq_info->intrhand); 561*2d1d418eSSumit Saxena bus_release_resource(sc->mpi3mr_dev, SYS_RES_IRQ, 562*2d1d418eSSumit Saxena irq_info->irq_rid, irq_info->irq); 563*2d1d418eSSumit Saxena } 564*2d1d418eSSumit Saxena } 565*2d1d418eSSumit Saxena 566*2d1d418eSSumit Saxena } 567*2d1d418eSSumit Saxena 568*2d1d418eSSumit Saxena /* 569*2d1d418eSSumit Saxena * Allocate, but don't assign interrupts early. Doing it before requesting 570*2d1d418eSSumit Saxena * the IOCFacts message informs the firmware that we want to do MSI-X 571*2d1d418eSSumit Saxena * multiqueue. We might not use all of the available messages, but there's 572*2d1d418eSSumit Saxena * no reason to re-alloc if we don't. 573*2d1d418eSSumit Saxena */ 574*2d1d418eSSumit Saxena int 575*2d1d418eSSumit Saxena mpi3mr_alloc_interrupts(struct mpi3mr_softc *sc, U16 setup_one) 576*2d1d418eSSumit Saxena { 577*2d1d418eSSumit Saxena int error, msgs; 578*2d1d418eSSumit Saxena U16 num_queues; 579*2d1d418eSSumit Saxena 580*2d1d418eSSumit Saxena error = 0; 581*2d1d418eSSumit Saxena msgs = 0; 582*2d1d418eSSumit Saxena 583*2d1d418eSSumit Saxena mpi3mr_cleanup_interrupts(sc); 584*2d1d418eSSumit Saxena 585*2d1d418eSSumit Saxena if (setup_one) { 586*2d1d418eSSumit Saxena msgs = 1; 587*2d1d418eSSumit Saxena } else { 588*2d1d418eSSumit Saxena msgs = min(sc->max_msix_vectors, sc->cpu_count); 589*2d1d418eSSumit Saxena num_queues = min(sc->facts.max_op_reply_q, sc->facts.max_op_req_q); 590*2d1d418eSSumit Saxena msgs = min(msgs, num_queues); 591*2d1d418eSSumit Saxena 592*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Supported MSI-x count: %d " 593*2d1d418eSSumit Saxena " CPU count: %d Requested MSI-x count: %d\n", 594*2d1d418eSSumit Saxena sc->max_msix_vectors, 595*2d1d418eSSumit Saxena sc->cpu_count, msgs); 596*2d1d418eSSumit Saxena } 597*2d1d418eSSumit Saxena 598*2d1d418eSSumit Saxena if (msgs != 0) { 599*2d1d418eSSumit Saxena error = pci_alloc_msix(sc->mpi3mr_dev, &msgs); 600*2d1d418eSSumit Saxena if (error) { 601*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 602*2d1d418eSSumit Saxena "Could not allocate MSI-x interrupts Error: %x\n", error); 603*2d1d418eSSumit Saxena goto out_failed; 604*2d1d418eSSumit Saxena } else 605*2d1d418eSSumit Saxena sc->msix_enable = 1; 606*2d1d418eSSumit Saxena } 607*2d1d418eSSumit Saxena 608*2d1d418eSSumit Saxena sc->msix_count = msgs; 609*2d1d418eSSumit Saxena sc->irq_ctx = malloc(sizeof(struct mpi3mr_irq_context) * msgs, 610*2d1d418eSSumit Saxena M_MPI3MR, M_NOWAIT | M_ZERO); 611*2d1d418eSSumit Saxena 612*2d1d418eSSumit Saxena if (!sc->irq_ctx) { 613*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot alloc memory for interrupt info\n"); 614*2d1d418eSSumit Saxena error = -1; 615*2d1d418eSSumit Saxena goto out_failed; 616*2d1d418eSSumit Saxena } 617*2d1d418eSSumit Saxena 618*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "Allocated %d MSI-x interrupts\n", msgs); 619*2d1d418eSSumit Saxena 620*2d1d418eSSumit Saxena return error; 621*2d1d418eSSumit Saxena out_failed: 622*2d1d418eSSumit Saxena mpi3mr_cleanup_interrupts(sc); 623*2d1d418eSSumit Saxena return (error); 624*2d1d418eSSumit Saxena } 625*2d1d418eSSumit Saxena 626*2d1d418eSSumit Saxena static int 627*2d1d418eSSumit Saxena mpi3mr_pci_detach(device_t dev) 628*2d1d418eSSumit Saxena { 629*2d1d418eSSumit Saxena struct mpi3mr_softc *sc; 630*2d1d418eSSumit Saxena int i = 0; 631*2d1d418eSSumit Saxena 632*2d1d418eSSumit Saxena sc = device_get_softc(dev); 633*2d1d418eSSumit Saxena 634*2d1d418eSSumit Saxena if (!sc->secure_ctrl) 635*2d1d418eSSumit Saxena return 0; 636*2d1d418eSSumit Saxena 637*2d1d418eSSumit Saxena sc->mpi3mr_flags |= MPI3MR_FLAGS_SHUTDOWN; 638*2d1d418eSSumit Saxena 639*2d1d418eSSumit Saxena if (sc->sysctl_tree != NULL) 640*2d1d418eSSumit Saxena sysctl_ctx_free(&sc->sysctl_ctx); 641*2d1d418eSSumit Saxena 642*2d1d418eSSumit Saxena if (sc->watchdog_thread_active) 643*2d1d418eSSumit Saxena wakeup(&sc->watchdog_chan); 644*2d1d418eSSumit Saxena 645*2d1d418eSSumit Saxena while (sc->reset_in_progress && (i < PEND_IOCTLS_COMP_WAIT_TIME)) { 646*2d1d418eSSumit Saxena i++; 647*2d1d418eSSumit Saxena if (!(i % 5)) { 648*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 649*2d1d418eSSumit Saxena "[%2d]waiting for reset to be finished from %s\n", i, __func__); 650*2d1d418eSSumit Saxena } 651*2d1d418eSSumit Saxena pause("mpi3mr_shutdown", hz); 652*2d1d418eSSumit Saxena } 653*2d1d418eSSumit Saxena 654*2d1d418eSSumit Saxena i = 0; 655*2d1d418eSSumit Saxena while (sc->watchdog_thread_active && (i < 180)) { 656*2d1d418eSSumit Saxena i++; 657*2d1d418eSSumit Saxena if (!(i % 5)) { 658*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 659*2d1d418eSSumit Saxena "[%2d]waiting for " 660*2d1d418eSSumit Saxena "mpi3mr_reset thread to quit reset %d\n", i, 661*2d1d418eSSumit Saxena sc->watchdog_thread_active); 662*2d1d418eSSumit Saxena } 663*2d1d418eSSumit Saxena pause("mpi3mr_shutdown", hz); 664*2d1d418eSSumit Saxena } 665*2d1d418eSSumit Saxena 666*2d1d418eSSumit Saxena i = 0; 667*2d1d418eSSumit Saxena while (mpi3mr_atomic_read(&sc->pend_ioctls) && (i < 180)) { 668*2d1d418eSSumit Saxena i++; 669*2d1d418eSSumit Saxena if (!(i % 5)) { 670*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 671*2d1d418eSSumit Saxena "[%2d]waiting for IOCTL to be finished from %s\n", i, __func__); 672*2d1d418eSSumit Saxena } 673*2d1d418eSSumit Saxena pause("mpi3mr_shutdown", hz); 674*2d1d418eSSumit Saxena } 675*2d1d418eSSumit Saxena 676*2d1d418eSSumit Saxena mpi3mr_cleanup_ioc(sc); 677*2d1d418eSSumit Saxena mpi3mr_cleanup_event_taskq(sc); 678*2d1d418eSSumit Saxena mpi3mr_app_detach(sc); 679*2d1d418eSSumit Saxena mpi3mr_cam_detach(sc); 680*2d1d418eSSumit Saxena mpi3mr_cleanup_interrupts(sc); 681*2d1d418eSSumit Saxena mpi3mr_destory_mtx(sc); 682*2d1d418eSSumit Saxena mpi3mr_free_mem(sc); 683*2d1d418eSSumit Saxena mpi3mr_release_resources(sc); 684*2d1d418eSSumit Saxena sc_ids--; 685*2d1d418eSSumit Saxena return (0); 686*2d1d418eSSumit Saxena } 687*2d1d418eSSumit Saxena 688*2d1d418eSSumit Saxena static int 689*2d1d418eSSumit Saxena mpi3mr_pci_suspend(device_t dev) 690*2d1d418eSSumit Saxena { 691*2d1d418eSSumit Saxena return (EINVAL); 692*2d1d418eSSumit Saxena } 693*2d1d418eSSumit Saxena 694*2d1d418eSSumit Saxena static int 695*2d1d418eSSumit Saxena mpi3mr_pci_resume(device_t dev) 696*2d1d418eSSumit Saxena { 697*2d1d418eSSumit Saxena return (EINVAL); 698*2d1d418eSSumit Saxena } 699