12e21a3efSScott Long /*- 2eebd9d53SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3718cf2ccSPedro F. Giffuni * 42e21a3efSScott Long * Copyright (c) 2006 IronPort Systems 52e21a3efSScott Long * All rights reserved. 62e21a3efSScott Long * 72e21a3efSScott Long * Redistribution and use in source and binary forms, with or without 82e21a3efSScott Long * modification, are permitted provided that the following conditions 92e21a3efSScott Long * are met: 102e21a3efSScott Long * 1. Redistributions of source code must retain the above copyright 112e21a3efSScott Long * notice, this list of conditions and the following disclaimer. 122e21a3efSScott Long * 2. Redistributions in binary form must reproduce the above copyright 132e21a3efSScott Long * notice, this list of conditions and the following disclaimer in the 142e21a3efSScott Long * documentation and/or other materials provided with the distribution. 152e21a3efSScott Long * 162e21a3efSScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 172e21a3efSScott Long * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 182e21a3efSScott Long * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 192e21a3efSScott Long * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 202e21a3efSScott Long * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 212e21a3efSScott Long * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 222e21a3efSScott Long * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 232e21a3efSScott Long * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 242e21a3efSScott Long * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 252e21a3efSScott Long * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 262e21a3efSScott Long * SUCH DAMAGE. 272e21a3efSScott Long */ 28610f2ef3SScott Long /*- 29610f2ef3SScott Long * Copyright (c) 2007 LSI Corp. 30610f2ef3SScott Long * Copyright (c) 2007 Rajesh Prabhakaran. 31610f2ef3SScott Long * All rights reserved. 32610f2ef3SScott Long * 33610f2ef3SScott Long * Redistribution and use in source and binary forms, with or without 34610f2ef3SScott Long * modification, are permitted provided that the following conditions 35610f2ef3SScott Long * are met: 36610f2ef3SScott Long * 1. Redistributions of source code must retain the above copyright 37610f2ef3SScott Long * notice, this list of conditions and the following disclaimer. 38610f2ef3SScott Long * 2. Redistributions in binary form must reproduce the above copyright 39610f2ef3SScott Long * notice, this list of conditions and the following disclaimer in the 40610f2ef3SScott Long * documentation and/or other materials provided with the distribution. 41610f2ef3SScott Long * 42610f2ef3SScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 43610f2ef3SScott Long * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44610f2ef3SScott Long * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45610f2ef3SScott Long * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 46610f2ef3SScott Long * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47610f2ef3SScott Long * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 48610f2ef3SScott Long * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49610f2ef3SScott Long * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 50610f2ef3SScott Long * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 51610f2ef3SScott Long * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52610f2ef3SScott Long * SUCH DAMAGE. 53610f2ef3SScott Long */ 542e21a3efSScott Long 552e21a3efSScott Long #include <sys/cdefs.h> 562e21a3efSScott Long /* PCI/PCI-X/PCIe bus interface for the LSI MegaSAS controllers */ 572e21a3efSScott Long 582e21a3efSScott Long #include "opt_mfi.h" 592e21a3efSScott Long 602e21a3efSScott Long #include <sys/param.h> 61e2e050c8SConrad Meyer #include <sys/bio.h> 622e21a3efSScott Long #include <sys/bus.h> 632e21a3efSScott Long #include <sys/conf.h> 64e2e050c8SConrad Meyer #include <sys/eventhandler.h> 65e2e050c8SConrad Meyer #include <sys/kernel.h> 66e2e050c8SConrad Meyer #include <sys/lock.h> 67e2e050c8SConrad Meyer #include <sys/module.h> 682e21a3efSScott Long #include <sys/malloc.h> 69e2e050c8SConrad Meyer #include <sys/mutex.h> 70e2e050c8SConrad Meyer #include <sys/selinfo.h> 71d1c5fc76SJohn Baldwin #include <sys/sysctl.h> 72e2e050c8SConrad Meyer #include <sys/systm.h> 73741367d5SDoug Ambrisko #include <sys/uio.h> 742e21a3efSScott Long 752e21a3efSScott Long #include <machine/bus.h> 762e21a3efSScott Long #include <machine/resource.h> 772e21a3efSScott Long #include <sys/rman.h> 782e21a3efSScott Long 792e21a3efSScott Long #include <dev/pci/pcireg.h> 802e21a3efSScott Long #include <dev/pci/pcivar.h> 812e21a3efSScott Long 822e21a3efSScott Long #include <dev/mfi/mfireg.h> 832e21a3efSScott Long #include <dev/mfi/mfi_ioctl.h> 842e21a3efSScott Long #include <dev/mfi/mfivar.h> 852e21a3efSScott Long 862e21a3efSScott Long static int mfi_pci_probe(device_t); 872e21a3efSScott Long static int mfi_pci_attach(device_t); 882e21a3efSScott Long static int mfi_pci_detach(device_t); 892e21a3efSScott Long static int mfi_pci_suspend(device_t); 902e21a3efSScott Long static int mfi_pci_resume(device_t); 912e21a3efSScott Long static void mfi_pci_free(struct mfi_softc *); 922e21a3efSScott Long 932e21a3efSScott Long static device_method_t mfi_methods[] = { 942e21a3efSScott Long DEVMETHOD(device_probe, mfi_pci_probe), 952e21a3efSScott Long DEVMETHOD(device_attach, mfi_pci_attach), 962e21a3efSScott Long DEVMETHOD(device_detach, mfi_pci_detach), 972e21a3efSScott Long DEVMETHOD(device_suspend, mfi_pci_suspend), 982e21a3efSScott Long DEVMETHOD(device_resume, mfi_pci_resume), 994b7ec270SMarius Strobl 1004b7ec270SMarius Strobl DEVMETHOD_END 1012e21a3efSScott Long }; 1022e21a3efSScott Long 1032e21a3efSScott Long static driver_t mfi_pci_driver = { 1042e21a3efSScott Long "mfi", 1052e21a3efSScott Long mfi_methods, 1062e21a3efSScott Long sizeof(struct mfi_softc) 1072e21a3efSScott Long }; 1082e21a3efSScott Long 109a6ba0fd6SDoug Ambrisko static int mfi_msi = 1; 110d1c5fc76SJohn Baldwin SYSCTL_INT(_hw_mfi, OID_AUTO, msi, CTLFLAG_RDTUN, &mfi_msi, 0, 111d1c5fc76SJohn Baldwin "Enable use of MSI interrupts"); 112d1c5fc76SJohn Baldwin 113af3b2549SHans Petter Selasky static int mfi_mrsas_enable; 11496f9425fSDoug Ambrisko SYSCTL_INT(_hw_mfi, OID_AUTO, mrsas_enable, CTLFLAG_RDTUN, &mfi_mrsas_enable, 115e0dcb9b6SEd Maste 0, "Allow mrsas to take newer cards"); 11696f9425fSDoug Ambrisko 1172e21a3efSScott Long struct mfi_ident { 1182e21a3efSScott Long uint16_t vendor; 1192e21a3efSScott Long uint16_t device; 1202e21a3efSScott Long uint16_t subvendor; 1212e21a3efSScott Long uint16_t subdevice; 1222e21a3efSScott Long int flags; 1232e21a3efSScott Long const char *desc; 1242e21a3efSScott Long } mfi_identifiers[] = { 1256ad638acSWojciech Macek {0x1000, 0x005b, 0x1028, 0x1fc9, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS, "Dell PERC H840 Adapter"}, 12696f9425fSDoug Ambrisko {0x1000, 0x005b, 0x1028, 0x1f2d, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS, "Dell PERC H810 Adapter"}, 12796f9425fSDoug Ambrisko {0x1000, 0x005b, 0x1028, 0x1f30, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS, "Dell PERC H710 Embedded"}, 12896f9425fSDoug Ambrisko {0x1000, 0x005b, 0x1028, 0x1f31, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS, "Dell PERC H710P Adapter"}, 12996f9425fSDoug Ambrisko {0x1000, 0x005b, 0x1028, 0x1f33, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS, "Dell PERC H710P Mini (blades)"}, 13096f9425fSDoug Ambrisko {0x1000, 0x005b, 0x1028, 0x1f34, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS, "Dell PERC H710P Mini (monolithics)"}, 13196f9425fSDoug Ambrisko {0x1000, 0x005b, 0x1028, 0x1f35, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS, "Dell PERC H710 Adapter"}, 13296f9425fSDoug Ambrisko {0x1000, 0x005b, 0x1028, 0x1f37, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS, "Dell PERC H710 Mini (blades)"}, 13396f9425fSDoug Ambrisko {0x1000, 0x005b, 0x1028, 0x1f38, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS, "Dell PERC H710 Mini (monolithics)"}, 13496f9425fSDoug Ambrisko {0x1000, 0x005b, 0x8086, 0x9265, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS, "Intel (R) RAID Controller RS25DB080"}, 13596f9425fSDoug Ambrisko {0x1000, 0x005b, 0x8086, 0x9285, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS, "Intel (R) RAID Controller RS25NB008"}, 13696f9425fSDoug Ambrisko {0x1000, 0x005b, 0xffff, 0xffff, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS, "ThunderBolt"}, 1373b8ad66eSMark Johnston {0x1000, 0x005d, 0xffff, 0xffff, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS| MFI_FLAGS_INVADER, "Invader"}, 1383b8ad66eSMark Johnston {0x1000, 0x005f, 0xffff, 0xffff, MFI_FLAGS_SKINNY| MFI_FLAGS_TBOLT| MFI_FLAGS_MRSAS| MFI_FLAGS_FURY, "Fury"}, 1394844f5c0SDoug Ambrisko {0x1000, 0x0060, 0x1028, 0xffff, MFI_FLAGS_1078, "Dell PERC 6"}, 140610f2ef3SScott Long {0x1000, 0x0060, 0xffff, 0xffff, MFI_FLAGS_1078, "LSI MegaSAS 1078"}, 1410d9a4ef3SDoug Ambrisko {0x1000, 0x0071, 0xffff, 0xffff, MFI_FLAGS_SKINNY, "Drake Skinny"}, 1420d9a4ef3SDoug Ambrisko {0x1000, 0x0073, 0xffff, 0xffff, MFI_FLAGS_SKINNY, "Drake Skinny"}, 1432997859fSDoug Ambrisko {0x1000, 0x0078, 0xffff, 0xffff, MFI_FLAGS_GEN2, "LSI MegaSAS Gen2"}, 144d205405cSDoug Ambrisko {0x1000, 0x0079, 0x1028, 0x1f15, MFI_FLAGS_GEN2, "Dell PERC H800 Adapter"}, 145d205405cSDoug Ambrisko {0x1000, 0x0079, 0x1028, 0x1f16, MFI_FLAGS_GEN2, "Dell PERC H700 Adapter"}, 146d205405cSDoug Ambrisko {0x1000, 0x0079, 0x1028, 0x1f17, MFI_FLAGS_GEN2, "Dell PERC H700 Integrated"}, 147d205405cSDoug Ambrisko {0x1000, 0x0079, 0x1028, 0x1f18, MFI_FLAGS_GEN2, "Dell PERC H700 Modular"}, 148bd97b1f4SDoug Ambrisko {0x1000, 0x0079, 0x1028, 0x1f19, MFI_FLAGS_GEN2, "Dell PERC H700"}, 1490d9a4ef3SDoug Ambrisko {0x1000, 0x0079, 0x1028, 0x1f1a, MFI_FLAGS_GEN2, "Dell PERC H800 Proto Adapter"}, 150bd97b1f4SDoug Ambrisko {0x1000, 0x0079, 0x1028, 0x1f1b, MFI_FLAGS_GEN2, "Dell PERC H800"}, 151216d58bbSDoug Ambrisko {0x1000, 0x0079, 0x1028, 0xffff, MFI_FLAGS_GEN2, "Dell PERC Gen2"}, 152fa1e6ef4SDoug Ambrisko {0x1000, 0x0079, 0xffff, 0xffff, MFI_FLAGS_GEN2, "LSI MegaSAS Gen2"}, 153fa1e6ef4SDoug Ambrisko {0x1000, 0x007c, 0xffff, 0xffff, MFI_FLAGS_1078, "LSI MegaSAS 1078"}, 1542997859fSDoug Ambrisko {0x1000, 0x0411, 0xffff, 0xffff, MFI_FLAGS_1064R, "LSI MegaSAS 1064R"}, /* Brocton IOP */ 1552997859fSDoug Ambrisko {0x1000, 0x0413, 0xffff, 0xffff, MFI_FLAGS_1064R, "LSI MegaSAS 1064R"}, /* Verde ZCR */ 1562997859fSDoug Ambrisko {0x1028, 0x0015, 0xffff, 0xffff, MFI_FLAGS_1064R, "Dell PERC 5/i"}, 1572e21a3efSScott Long {0, 0, 0, 0, 0, NULL} 1582e21a3efSScott Long }; 1592e21a3efSScott Long 160354f6c1cSJohn Baldwin DRIVER_MODULE(mfi, pci, mfi_pci_driver, 0, 0); 1610dc34160SWarner Losh MODULE_PNP_INFO("U16:vendor;U16:device;U16:subvendor;U16:subdevice", pci, mfi, 1620dc34160SWarner Losh mfi_identifiers, nitems(mfi_identifiers) - 1); 1630dc34160SWarner Losh MODULE_VERSION(mfi, 1); 1640dc34160SWarner Losh 1652e21a3efSScott Long static struct mfi_ident * 1662e21a3efSScott Long mfi_find_ident(device_t dev) 1672e21a3efSScott Long { 1682e21a3efSScott Long struct mfi_ident *m; 1692e21a3efSScott Long 1702e21a3efSScott Long for (m = mfi_identifiers; m->vendor != 0; m++) { 1712e21a3efSScott Long if ((m->vendor == pci_get_vendor(dev)) && 1722e21a3efSScott Long (m->device == pci_get_device(dev)) && 1732e21a3efSScott Long ((m->subvendor == pci_get_subvendor(dev)) || 1742e21a3efSScott Long (m->subvendor == 0xffff)) && 1752e21a3efSScott Long ((m->subdevice == pci_get_subdevice(dev)) || 1762e21a3efSScott Long (m->subdevice == 0xffff))) 1772e21a3efSScott Long return (m); 1782e21a3efSScott Long } 1792e21a3efSScott Long 1802e21a3efSScott Long return (NULL); 1812e21a3efSScott Long } 1822e21a3efSScott Long 1832e21a3efSScott Long static int 1842e21a3efSScott Long mfi_pci_probe(device_t dev) 1852e21a3efSScott Long { 1862e21a3efSScott Long struct mfi_ident *id; 1872e21a3efSScott Long 1882e21a3efSScott Long if ((id = mfi_find_ident(dev)) != NULL) { 1892e21a3efSScott Long device_set_desc(dev, id->desc); 19096f9425fSDoug Ambrisko 19196f9425fSDoug Ambrisko /* give priority to mrsas if tunable set */ 19296f9425fSDoug Ambrisko if ((id->flags & MFI_FLAGS_MRSAS) && mfi_mrsas_enable) 19396f9425fSDoug Ambrisko return (BUS_PROBE_LOW_PRIORITY); 19496f9425fSDoug Ambrisko else 1952e21a3efSScott Long return (BUS_PROBE_DEFAULT); 1962e21a3efSScott Long } 1972e21a3efSScott Long return (ENXIO); 1982e21a3efSScott Long } 1992e21a3efSScott Long 2002e21a3efSScott Long static int 2012e21a3efSScott Long mfi_pci_attach(device_t dev) 2022e21a3efSScott Long { 2032e21a3efSScott Long struct mfi_softc *sc; 2042e21a3efSScott Long struct mfi_ident *m; 205d1c5fc76SJohn Baldwin int count, error; 2062e21a3efSScott Long 2072e21a3efSScott Long sc = device_get_softc(dev); 2082e21a3efSScott Long bzero(sc, sizeof(*sc)); 2092e21a3efSScott Long sc->mfi_dev = dev; 210fa1e6ef4SDoug Ambrisko m = mfi_find_ident(dev); 211fa1e6ef4SDoug Ambrisko sc->mfi_flags = m->flags; 2122e21a3efSScott Long 213c68534f1SScott Long /* Ensure busmastering is enabled */ 214c68534f1SScott Long pci_enable_busmaster(dev); 2152e21a3efSScott Long 2162e21a3efSScott Long /* Allocate PCI registers */ 217fa1e6ef4SDoug Ambrisko if ((sc->mfi_flags & MFI_FLAGS_1064R) || 218fa1e6ef4SDoug Ambrisko (sc->mfi_flags & MFI_FLAGS_1078)) { 219fa1e6ef4SDoug Ambrisko /* 1068/1078: Memory mapped BAR is at offset 0x10 */ 2202e21a3efSScott Long sc->mfi_regs_rid = PCIR_BAR(0); 2210d9a4ef3SDoug Ambrisko } 2220d9a4ef3SDoug Ambrisko else if ((sc->mfi_flags & MFI_FLAGS_GEN2) || 2230d9a4ef3SDoug Ambrisko (sc->mfi_flags & MFI_FLAGS_SKINNY) || 2240d9a4ef3SDoug Ambrisko (sc->mfi_flags & MFI_FLAGS_TBOLT)) { 2250d9a4ef3SDoug Ambrisko /* Gen2/Skinny: Memory mapped BAR is at offset 0x14 */ 226fa1e6ef4SDoug Ambrisko sc->mfi_regs_rid = PCIR_BAR(1); 227fa1e6ef4SDoug Ambrisko } 2282e21a3efSScott Long if ((sc->mfi_regs_resource = bus_alloc_resource_any(sc->mfi_dev, 2292e21a3efSScott Long SYS_RES_MEMORY, &sc->mfi_regs_rid, RF_ACTIVE)) == NULL) { 2302e21a3efSScott Long device_printf(dev, "Cannot allocate PCI registers\n"); 2312e21a3efSScott Long return (ENXIO); 2322e21a3efSScott Long } 2332e21a3efSScott Long sc->mfi_btag = rman_get_bustag(sc->mfi_regs_resource); 2342e21a3efSScott Long sc->mfi_bhandle = rman_get_bushandle(sc->mfi_regs_resource); 2352e21a3efSScott Long 2362e21a3efSScott Long error = ENOMEM; 2372e21a3efSScott Long 2382e21a3efSScott Long /* Allocate parent DMA tag */ 239b6f97155SScott Long if (bus_dma_tag_create( bus_get_dma_tag(dev), /* PCI parent */ 2402e21a3efSScott Long 1, 0, /* algnmnt, boundary */ 2412e21a3efSScott Long BUS_SPACE_MAXADDR, /* lowaddr */ 2422e21a3efSScott Long BUS_SPACE_MAXADDR, /* highaddr */ 2432e21a3efSScott Long NULL, NULL, /* filter, filterarg */ 2442e21a3efSScott Long BUS_SPACE_MAXSIZE_32BIT,/* maxsize */ 2452e21a3efSScott Long BUS_SPACE_UNRESTRICTED, /* nsegments */ 2462e21a3efSScott Long BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ 2472e21a3efSScott Long 0, /* flags */ 2482e21a3efSScott Long NULL, NULL, /* lockfunc, lockarg */ 2492e21a3efSScott Long &sc->mfi_parent_dmat)) { 2502e21a3efSScott Long device_printf(dev, "Cannot allocate parent DMA tag\n"); 2512e21a3efSScott Long goto out; 2522e21a3efSScott Long } 2532e21a3efSScott Long 254d1c5fc76SJohn Baldwin /* Allocate IRQ resource. */ 255d1c5fc76SJohn Baldwin sc->mfi_irq_rid = 0; 256d1c5fc76SJohn Baldwin count = 1; 257d1c5fc76SJohn Baldwin if (mfi_msi && pci_alloc_msi(sc->mfi_dev, &count) == 0) { 258d1c5fc76SJohn Baldwin device_printf(sc->mfi_dev, "Using MSI\n"); 259d1c5fc76SJohn Baldwin sc->mfi_irq_rid = 1; 260d1c5fc76SJohn Baldwin } 261d1c5fc76SJohn Baldwin if ((sc->mfi_irq = bus_alloc_resource_any(sc->mfi_dev, SYS_RES_IRQ, 262d1c5fc76SJohn Baldwin &sc->mfi_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 263d1c5fc76SJohn Baldwin device_printf(sc->mfi_dev, "Cannot allocate interrupt\n"); 264d1c5fc76SJohn Baldwin error = EINVAL; 265d1c5fc76SJohn Baldwin goto out; 266d1c5fc76SJohn Baldwin } 267d1c5fc76SJohn Baldwin 2682e21a3efSScott Long error = mfi_attach(sc); 2692e21a3efSScott Long out: 2702e21a3efSScott Long if (error) { 2712e21a3efSScott Long mfi_free(sc); 2722e21a3efSScott Long mfi_pci_free(sc); 2732e21a3efSScott Long } 2742e21a3efSScott Long 2752e21a3efSScott Long return (error); 2762e21a3efSScott Long } 2772e21a3efSScott Long 2782e21a3efSScott Long static int 2792e21a3efSScott Long mfi_pci_detach(device_t dev) 2802e21a3efSScott Long { 2812e21a3efSScott Long struct mfi_softc *sc; 282*d174ffcaSJohn Baldwin int error; 2832e21a3efSScott Long 2842e21a3efSScott Long sc = device_get_softc(dev); 2852e21a3efSScott Long 2868ec5c98bSJohn Baldwin sx_xlock(&sc->mfi_config_lock); 287ddfae47bSScott Long mtx_lock(&sc->mfi_io_lock); 288ddfae47bSScott Long if ((sc->mfi_flags & MFI_FLAGS_OPEN) != 0) { 289ddfae47bSScott Long mtx_unlock(&sc->mfi_io_lock); 290cde586a7SJohn Baldwin sx_xunlock(&sc->mfi_config_lock); 2912e21a3efSScott Long return (EBUSY); 292ddfae47bSScott Long } 2938ec5c98bSJohn Baldwin sc->mfi_detaching = 1; 2948ec5c98bSJohn Baldwin mtx_unlock(&sc->mfi_io_lock); 2952e21a3efSScott Long 296*d174ffcaSJohn Baldwin error = bus_generic_detach(sc->mfi_dev); 297*d174ffcaSJohn Baldwin if (error != 0) { 2988ec5c98bSJohn Baldwin sx_xunlock(&sc->mfi_config_lock); 2990d9a4ef3SDoug Ambrisko return error; 300ddfae47bSScott Long } 3018ec5c98bSJohn Baldwin sx_xunlock(&sc->mfi_config_lock); 3022e21a3efSScott Long 3032e21a3efSScott Long EVENTHANDLER_DEREGISTER(shutdown_final, sc->mfi_eh); 3042e21a3efSScott Long 3052e21a3efSScott Long mfi_shutdown(sc); 3062e21a3efSScott Long mfi_free(sc); 3072e21a3efSScott Long mfi_pci_free(sc); 3082e21a3efSScott Long return (0); 3092e21a3efSScott Long } 3102e21a3efSScott Long 3112e21a3efSScott Long static void 3122e21a3efSScott Long mfi_pci_free(struct mfi_softc *sc) 3132e21a3efSScott Long { 3142e21a3efSScott Long 3152e21a3efSScott Long if (sc->mfi_regs_resource != NULL) { 3162e21a3efSScott Long bus_release_resource(sc->mfi_dev, SYS_RES_MEMORY, 3172e21a3efSScott Long sc->mfi_regs_rid, sc->mfi_regs_resource); 3182e21a3efSScott Long } 319d1c5fc76SJohn Baldwin if (sc->mfi_irq_rid != 0) 320d1c5fc76SJohn Baldwin pci_release_msi(sc->mfi_dev); 3212e21a3efSScott Long 3222e21a3efSScott Long return; 3232e21a3efSScott Long } 3242e21a3efSScott Long 3252e21a3efSScott Long static int 3262e21a3efSScott Long mfi_pci_suspend(device_t dev) 3272e21a3efSScott Long { 3282e21a3efSScott Long 3292e21a3efSScott Long return (EINVAL); 3302e21a3efSScott Long } 3312e21a3efSScott Long 3322e21a3efSScott Long static int 3332e21a3efSScott Long mfi_pci_resume(device_t dev) 3342e21a3efSScott Long { 3352e21a3efSScott Long 3362e21a3efSScott Long return (EINVAL); 3372e21a3efSScott Long } 338