1 2d1d418eSSumit Saxena /*
2 2d1d418eSSumit Saxena * SPDX-License-Identifier: BSD-2-Clause
3 2d1d418eSSumit Saxena *
4 *945c3ce4SChandrakanth patil * Copyright (c) 2020-2024, 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 2f2da217SChuck Silvers { 0 }
93 2d1d418eSSumit Saxena };
94 2d1d418eSSumit Saxena
95 2d1d418eSSumit Saxena DRIVER_MODULE(mpi3mr, pci, mpi3mr_pci_driver, 0, 0);
96 2d1d418eSSumit Saxena MODULE_PNP_INFO("U16:vendor;U16:device;U16:subvendor;U16:subdevice;D:#", pci,
97 2d1d418eSSumit Saxena mpi3mr, mpi3mr_identifiers, nitems(mpi3mr_identifiers) - 1);
98 2d1d418eSSumit Saxena
99 2d1d418eSSumit Saxena MODULE_DEPEND(mpi3mr, cam, 1, 1, 1);
100 2d1d418eSSumit Saxena
101 2d1d418eSSumit Saxena /*
102 2d1d418eSSumit Saxena * mpi3mr_setup_sysctl: setup sysctl values for mpi3mr
103 2d1d418eSSumit Saxena * input: Adapter instance soft state
104 2d1d418eSSumit Saxena *
105 2d1d418eSSumit Saxena * Setup sysctl entries for mpi3mr driver.
106 2d1d418eSSumit Saxena */
107 2d1d418eSSumit Saxena static void
mpi3mr_setup_sysctl(struct mpi3mr_softc * sc)108 2d1d418eSSumit Saxena mpi3mr_setup_sysctl(struct mpi3mr_softc *sc)
109 2d1d418eSSumit Saxena {
110 2d1d418eSSumit Saxena struct sysctl_ctx_list *sysctl_ctx = NULL;
111 2d1d418eSSumit Saxena struct sysctl_oid *sysctl_tree = NULL;
112 2d1d418eSSumit Saxena char tmpstr[80], tmpstr2[80];
113 2d1d418eSSumit Saxena
114 2d1d418eSSumit Saxena /*
115 2d1d418eSSumit Saxena * Setup the sysctl variable so the user can change the debug level
116 2d1d418eSSumit Saxena * on the fly.
117 2d1d418eSSumit Saxena */
118 2d1d418eSSumit Saxena snprintf(tmpstr, sizeof(tmpstr), "MPI3MR controller %d",
119 2d1d418eSSumit Saxena device_get_unit(sc->mpi3mr_dev));
120 2d1d418eSSumit Saxena snprintf(tmpstr2, sizeof(tmpstr2), "%d", device_get_unit(sc->mpi3mr_dev));
121 2d1d418eSSumit Saxena
122 2d1d418eSSumit Saxena sysctl_ctx = device_get_sysctl_ctx(sc->mpi3mr_dev);
123 2d1d418eSSumit Saxena if (sysctl_ctx != NULL)
124 2d1d418eSSumit Saxena sysctl_tree = device_get_sysctl_tree(sc->mpi3mr_dev);
125 2d1d418eSSumit Saxena
126 2d1d418eSSumit Saxena if (sysctl_tree == NULL) {
127 2d1d418eSSumit Saxena sysctl_ctx_init(&sc->sysctl_ctx);
128 2d1d418eSSumit Saxena sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
129 2d1d418eSSumit Saxena SYSCTL_STATIC_CHILDREN(_hw_mpi3mr), OID_AUTO, tmpstr2,
130 2d1d418eSSumit Saxena CTLFLAG_RD, 0, tmpstr);
131 2d1d418eSSumit Saxena if (sc->sysctl_tree == NULL)
132 2d1d418eSSumit Saxena return;
133 2d1d418eSSumit Saxena sysctl_ctx = &sc->sysctl_ctx;
134 2d1d418eSSumit Saxena sysctl_tree = sc->sysctl_tree;
135 2d1d418eSSumit Saxena }
136 2d1d418eSSumit Saxena
137 2d1d418eSSumit Saxena SYSCTL_ADD_STRING(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
138 2d1d418eSSumit Saxena OID_AUTO, "driver_version", CTLFLAG_RD, MPI3MR_DRIVER_VERSION,
139 2d1d418eSSumit Saxena strlen(MPI3MR_DRIVER_VERSION), "driver version");
140 2d1d418eSSumit Saxena
141 2d1d418eSSumit Saxena SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
142 2d1d418eSSumit Saxena OID_AUTO, "fw_outstanding", CTLFLAG_RD,
143 2d1d418eSSumit Saxena &sc->fw_outstanding.val_rdonly, 0, "FW outstanding commands");
144 2d1d418eSSumit Saxena
145 2d1d418eSSumit Saxena SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
146 2d1d418eSSumit Saxena OID_AUTO, "io_cmds_highwater", CTLFLAG_RD,
147 2d1d418eSSumit Saxena &sc->io_cmds_highwater, 0, "Max FW outstanding commands");
148 2d1d418eSSumit Saxena
149 28a27434SWarner Losh SYSCTL_ADD_STRING(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
150 28a27434SWarner Losh OID_AUTO, "firmware_version", CTLFLAG_RD, sc->fw_version,
151 28a27434SWarner Losh strlen(sc->fw_version), "firmware version");
152 28a27434SWarner Losh
153 2d1d418eSSumit Saxena SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
154 2d1d418eSSumit Saxena OID_AUTO, "mpi3mr_debug", CTLFLAG_RW, &sc->mpi3mr_debug, 0,
155 2d1d418eSSumit Saxena "Driver debug level");
156 2d1d418eSSumit Saxena SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
157 2d1d418eSSumit Saxena OID_AUTO, "reset", CTLFLAG_RW, &sc->reset.type, 0,
158 2d1d418eSSumit Saxena "Soft reset(1)/Diag reset(2)");
159 2d1d418eSSumit Saxena SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
160 2d1d418eSSumit Saxena OID_AUTO, "iot_enable", CTLFLAG_RW, &sc->iot_enable, 0,
161 2d1d418eSSumit Saxena "IO throttling enable at driver level(for debug purpose)");
162 2d1d418eSSumit Saxena }
163 2d1d418eSSumit Saxena
164 2d1d418eSSumit Saxena /*
165 2d1d418eSSumit Saxena * mpi3mr_get_tunables: get tunable parameters.
166 2d1d418eSSumit Saxena * input: Adapter instance soft state
167 2d1d418eSSumit Saxena *
168 2d1d418eSSumit Saxena * Get tunable parameters. This will help to debug driver at boot time.
169 2d1d418eSSumit Saxena */
170 2d1d418eSSumit Saxena static void
mpi3mr_get_tunables(struct mpi3mr_softc * sc)171 2d1d418eSSumit Saxena mpi3mr_get_tunables(struct mpi3mr_softc *sc)
172 2d1d418eSSumit Saxena {
173 2d1d418eSSumit Saxena char tmpstr[80];
174 2d1d418eSSumit Saxena
175 2d1d418eSSumit Saxena sc->mpi3mr_debug =
176 2d1d418eSSumit Saxena (MPI3MR_ERROR | MPI3MR_INFO | MPI3MR_FAULT);
177 2d1d418eSSumit Saxena
178 2d1d418eSSumit Saxena sc->reset_in_progress = 0;
179 2d1d418eSSumit Saxena sc->reset.type = 0;
180 2d1d418eSSumit Saxena sc->iot_enable = 1;
181 2d1d418eSSumit Saxena /*
182 2d1d418eSSumit Saxena * Grab the global variables.
183 2d1d418eSSumit Saxena */
184 2d1d418eSSumit Saxena TUNABLE_INT_FETCH("hw.mpi3mr.debug_level", &sc->mpi3mr_debug);
185 2d1d418eSSumit Saxena TUNABLE_INT_FETCH("hw.mpi3mr.ctrl_reset", &sc->reset.type);
186 2d1d418eSSumit Saxena TUNABLE_INT_FETCH("hw.mpi3mr.iot_enable", &sc->iot_enable);
187 2d1d418eSSumit Saxena
188 2d1d418eSSumit Saxena /* Grab the unit-instance variables */
189 2d1d418eSSumit Saxena snprintf(tmpstr, sizeof(tmpstr), "dev.mpi3mr.%d.debug_level",
190 2d1d418eSSumit Saxena device_get_unit(sc->mpi3mr_dev));
191 2d1d418eSSumit Saxena TUNABLE_INT_FETCH(tmpstr, &sc->mpi3mr_debug);
192 2d1d418eSSumit Saxena
193 2d1d418eSSumit Saxena snprintf(tmpstr, sizeof(tmpstr), "dev.mpi3mr.%d.reset",
194 2d1d418eSSumit Saxena device_get_unit(sc->mpi3mr_dev));
195 2d1d418eSSumit Saxena TUNABLE_INT_FETCH(tmpstr, &sc->reset.type);
196 2d1d418eSSumit Saxena
197 2d1d418eSSumit Saxena snprintf(tmpstr, sizeof(tmpstr), "dev.mpi3mr.%d.iot_enable",
198 2d1d418eSSumit Saxena device_get_unit(sc->mpi3mr_dev));
199 2d1d418eSSumit Saxena TUNABLE_INT_FETCH(tmpstr, &sc->iot_enable);
200 2d1d418eSSumit Saxena }
201 2d1d418eSSumit Saxena
202 2d1d418eSSumit Saxena static struct mpi3mr_ident *
mpi3mr_find_ident(device_t dev)203 2d1d418eSSumit Saxena mpi3mr_find_ident(device_t dev)
204 2d1d418eSSumit Saxena {
205 2d1d418eSSumit Saxena struct mpi3mr_ident *m;
206 2d1d418eSSumit Saxena
207 2d1d418eSSumit Saxena for (m = mpi3mr_identifiers; m->vendor != 0; m++) {
208 2d1d418eSSumit Saxena if (m->vendor != pci_get_vendor(dev))
209 2d1d418eSSumit Saxena continue;
210 2d1d418eSSumit Saxena if (m->device != pci_get_device(dev))
211 2d1d418eSSumit Saxena continue;
212 2d1d418eSSumit Saxena if ((m->subvendor != 0xffff) &&
213 2d1d418eSSumit Saxena (m->subvendor != pci_get_subvendor(dev)))
214 2d1d418eSSumit Saxena continue;
215 2d1d418eSSumit Saxena if ((m->subdevice != 0xffff) &&
216 2d1d418eSSumit Saxena (m->subdevice != pci_get_subdevice(dev)))
217 2d1d418eSSumit Saxena continue;
218 2d1d418eSSumit Saxena return (m);
219 2d1d418eSSumit Saxena }
220 2d1d418eSSumit Saxena
221 2d1d418eSSumit Saxena return (NULL);
222 2d1d418eSSumit Saxena }
223 2d1d418eSSumit Saxena
224 2d1d418eSSumit Saxena static int
mpi3mr_pci_probe(device_t dev)225 2d1d418eSSumit Saxena mpi3mr_pci_probe(device_t dev)
226 2d1d418eSSumit Saxena {
227 2d1d418eSSumit Saxena static u_int8_t first_ctrl = 1;
228 2d1d418eSSumit Saxena struct mpi3mr_ident *id;
229 2d1d418eSSumit Saxena char raw_os_ver[16];
230 2d1d418eSSumit Saxena
231 2d1d418eSSumit Saxena if ((id = mpi3mr_find_ident(dev)) != NULL) {
232 2d1d418eSSumit Saxena if (first_ctrl) {
233 2d1d418eSSumit Saxena first_ctrl = 0;
234 2d1d418eSSumit Saxena MPI3MR_OS_VERSION(raw_os_ver, fmt_os_ver);
235 2d1d418eSSumit Saxena printf("mpi3mr: Loading Broadcom mpi3mr driver version: %s OS version: %s\n",
236 2d1d418eSSumit Saxena MPI3MR_DRIVER_VERSION, fmt_os_ver);
237 2d1d418eSSumit Saxena }
238 2d1d418eSSumit Saxena device_set_desc(dev, id->desc);
239 2d1d418eSSumit Saxena device_set_desc(dev, id->desc);
240 2d1d418eSSumit Saxena return (BUS_PROBE_DEFAULT);
241 2d1d418eSSumit Saxena }
242 2d1d418eSSumit Saxena return (ENXIO);
243 2d1d418eSSumit Saxena }
244 2d1d418eSSumit Saxena
245 2d1d418eSSumit Saxena static void
mpi3mr_release_resources(struct mpi3mr_softc * sc)246 2d1d418eSSumit Saxena mpi3mr_release_resources(struct mpi3mr_softc *sc)
247 2d1d418eSSumit Saxena {
248 2d1d418eSSumit Saxena if (sc->mpi3mr_parent_dmat != NULL) {
249 2d1d418eSSumit Saxena bus_dma_tag_destroy(sc->mpi3mr_parent_dmat);
250 2d1d418eSSumit Saxena }
251 2d1d418eSSumit Saxena
252 2d1d418eSSumit Saxena if (sc->mpi3mr_regs_resource != NULL) {
253 2d1d418eSSumit Saxena bus_release_resource(sc->mpi3mr_dev, SYS_RES_MEMORY,
254 2d1d418eSSumit Saxena sc->mpi3mr_regs_rid, sc->mpi3mr_regs_resource);
255 2d1d418eSSumit Saxena }
256 2d1d418eSSumit Saxena }
257 2d1d418eSSumit Saxena
mpi3mr_setup_resources(struct mpi3mr_softc * sc)258 2d1d418eSSumit Saxena static int mpi3mr_setup_resources(struct mpi3mr_softc *sc)
259 2d1d418eSSumit Saxena {
260 489eee0dSAlexander Motin bus_dma_template_t t;
261 2d1d418eSSumit Saxena int i;
262 2d1d418eSSumit Saxena device_t dev = sc->mpi3mr_dev;
263 2d1d418eSSumit Saxena
264 2d1d418eSSumit Saxena pci_enable_busmaster(dev);
265 2d1d418eSSumit Saxena
266 2d1d418eSSumit Saxena for (i = 0; i < PCI_MAXMAPS_0; i++) {
267 2d1d418eSSumit Saxena sc->mpi3mr_regs_rid = PCIR_BAR(i);
268 2d1d418eSSumit Saxena
269 2d1d418eSSumit Saxena if ((sc->mpi3mr_regs_resource = bus_alloc_resource_any(dev,
270 2d1d418eSSumit Saxena SYS_RES_MEMORY, &sc->mpi3mr_regs_rid, RF_ACTIVE)) != NULL)
271 2d1d418eSSumit Saxena break;
272 2d1d418eSSumit Saxena }
273 2d1d418eSSumit Saxena
274 2d1d418eSSumit Saxena if (sc->mpi3mr_regs_resource == NULL) {
275 2d1d418eSSumit Saxena mpi3mr_printf(sc, "Cannot allocate PCI registers\n");
276 2d1d418eSSumit Saxena return (ENXIO);
277 2d1d418eSSumit Saxena }
278 2d1d418eSSumit Saxena
279 2d1d418eSSumit Saxena sc->mpi3mr_btag = rman_get_bustag(sc->mpi3mr_regs_resource);
280 2d1d418eSSumit Saxena sc->mpi3mr_bhandle = rman_get_bushandle(sc->mpi3mr_regs_resource);
281 2d1d418eSSumit Saxena
282 91d96135SWarner Losh /*
283 91d96135SWarner Losh * XXX Perhaps we should move this to after we read iocfacts and use
284 91d96135SWarner Losh * that to create the proper parent tag. However, to get the iocfacts
285 91d96135SWarner Losh * we need to have a dmatag for both the admin queue and the iocfacts
286 91d96135SWarner Losh * DMA transfer. So for now, we just create a 'no restriction' tag and
287 91d96135SWarner Losh * use sc->dma_loaddr for all the other tag_create calls to get the
288 91d96135SWarner Losh * right value. It would be nice if one could retroactively adjust a
289 91d96135SWarner Losh * created tag. The Linux driver effectively does this by setting the
290 91d96135SWarner Losh * dma_mask on the device.
291 91d96135SWarner Losh */
292 2d1d418eSSumit Saxena /* Allocate the parent DMA tag */
293 489eee0dSAlexander Motin bus_dma_template_init(&t, bus_get_dma_tag(dev));
294 489eee0dSAlexander Motin if (bus_dma_template_tag(&t, &sc->mpi3mr_parent_dmat)) {
295 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate parent DMA tag\n");
296 2d1d418eSSumit Saxena return (ENOMEM);
297 2d1d418eSSumit Saxena }
298 2d1d418eSSumit Saxena
299 2d1d418eSSumit Saxena sc->max_msix_vectors = pci_msix_count(dev);
300 2d1d418eSSumit Saxena
301 2d1d418eSSumit Saxena return 0;
302 2d1d418eSSumit Saxena }
303 2d1d418eSSumit Saxena
304 2d1d418eSSumit Saxena static int
mpi3mr_startup(struct mpi3mr_softc * sc)305 2d1d418eSSumit Saxena mpi3mr_startup(struct mpi3mr_softc *sc)
306 2d1d418eSSumit Saxena {
307 2d1d418eSSumit Saxena sc->mpi3mr_flags &= ~MPI3MR_FLAGS_PORT_ENABLE_DONE;
308 2d1d418eSSumit Saxena mpi3mr_issue_port_enable(sc, 1);
309 2d1d418eSSumit Saxena return (0);
310 2d1d418eSSumit Saxena }
311 2d1d418eSSumit Saxena
312 2d1d418eSSumit Saxena /* Run through any late-start handlers. */
313 2d1d418eSSumit Saxena static void
mpi3mr_ich_startup(void * arg)314 2d1d418eSSumit Saxena mpi3mr_ich_startup(void *arg)
315 2d1d418eSSumit Saxena {
316 2d1d418eSSumit Saxena struct mpi3mr_softc *sc;
317 7e02c707SSumit Saxena int error;
318 2d1d418eSSumit Saxena
319 2d1d418eSSumit Saxena sc = (struct mpi3mr_softc *)arg;
320 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "%s entry\n", __func__);
321 2d1d418eSSumit Saxena
322 2d1d418eSSumit Saxena mtx_lock(&sc->mpi3mr_mtx);
323 2d1d418eSSumit Saxena
324 2d1d418eSSumit Saxena mpi3mr_startup(sc);
325 7e02c707SSumit Saxena
326 2d1d418eSSumit Saxena mtx_unlock(&sc->mpi3mr_mtx);
327 2d1d418eSSumit Saxena
328 7e02c707SSumit Saxena error = mpi3mr_kproc_create(mpi3mr_watchdog_thread, sc,
329 7e02c707SSumit Saxena &sc->watchdog_thread, 0, 0, "mpi3mr_watchdog%d",
330 7e02c707SSumit Saxena device_get_unit(sc->mpi3mr_dev));
331 7e02c707SSumit Saxena
332 7e02c707SSumit Saxena if (error)
333 7e02c707SSumit Saxena device_printf(sc->mpi3mr_dev, "Error %d starting OCR thread\n", error);
334 7e02c707SSumit Saxena
335 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "disestablish config intrhook\n");
336 2d1d418eSSumit Saxena config_intrhook_disestablish(&sc->mpi3mr_ich);
337 2d1d418eSSumit Saxena sc->mpi3mr_ich.ich_arg = NULL;
338 2d1d418eSSumit Saxena
339 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "%s exit\n", __func__);
340 2d1d418eSSumit Saxena }
341 2d1d418eSSumit Saxena
342 2d1d418eSSumit Saxena /**
343 2d1d418eSSumit Saxena * mpi3mr_ctrl_security_status -Check controller secure status
344 2d1d418eSSumit Saxena * @pdev: PCI device instance
345 2d1d418eSSumit Saxena *
346 2d1d418eSSumit Saxena * Read the Device Serial Number capability from PCI config
347 2d1d418eSSumit Saxena * space and decide whether the controller is secure or not.
348 2d1d418eSSumit Saxena *
349 2d1d418eSSumit Saxena * Return: 0 on success, non-zero on failure.
350 2d1d418eSSumit Saxena */
351 2d1d418eSSumit Saxena static int
mpi3mr_ctrl_security_status(device_t dev)352 2d1d418eSSumit Saxena mpi3mr_ctrl_security_status(device_t dev)
353 2d1d418eSSumit Saxena {
354 2d1d418eSSumit Saxena int dev_serial_num, retval = 0;
355 2d1d418eSSumit Saxena uint32_t cap_data, ctrl_status, debug_status;
356 2d1d418eSSumit Saxena /* Check if Device serial number extended capability is supported */
357 2d1d418eSSumit Saxena if (pci_find_extcap(dev, PCIZ_SERNUM, &dev_serial_num) != 0) {
358 2d1d418eSSumit Saxena device_printf(dev,
359 2d1d418eSSumit Saxena "PCIZ_SERNUM is not supported\n");
360 2d1d418eSSumit Saxena return -1;
361 2d1d418eSSumit Saxena }
362 2d1d418eSSumit Saxena
363 2d1d418eSSumit Saxena cap_data = pci_read_config(dev, dev_serial_num + 4, 4);
364 2d1d418eSSumit Saxena
365 2d1d418eSSumit Saxena debug_status = cap_data & MPI3MR_CTLR_SECURE_DBG_STATUS_MASK;
366 2d1d418eSSumit Saxena ctrl_status = cap_data & MPI3MR_CTLR_SECURITY_STATUS_MASK;
367 2d1d418eSSumit Saxena
368 2d1d418eSSumit Saxena switch (ctrl_status) {
369 2d1d418eSSumit Saxena case MPI3MR_INVALID_DEVICE:
370 2d1d418eSSumit Saxena device_printf(dev,
371 2d1d418eSSumit Saxena "Invalid (Non secure) controller is detected: DID: 0x%x: SVID: 0x%x: SDID: 0x%x\n",
372 2d1d418eSSumit Saxena pci_get_device(dev), pci_get_subvendor(dev),
373 2d1d418eSSumit Saxena pci_get_subdevice(dev));
374 2d1d418eSSumit Saxena retval = -1;
375 2d1d418eSSumit Saxena break;
376 2d1d418eSSumit Saxena case MPI3MR_CONFIG_SECURE_DEVICE:
377 2d1d418eSSumit Saxena if (!debug_status)
378 2d1d418eSSumit Saxena device_printf(dev, "Config secure controller is detected\n");
379 2d1d418eSSumit Saxena break;
380 2d1d418eSSumit Saxena case MPI3MR_HARD_SECURE_DEVICE:
381 2d1d418eSSumit Saxena device_printf(dev, "Hard secure controller is detected\n");
382 2d1d418eSSumit Saxena break;
383 2d1d418eSSumit Saxena case MPI3MR_TAMPERED_DEVICE:
384 2d1d418eSSumit Saxena device_printf(dev,
385 2d1d418eSSumit Saxena "Tampered (Non secure) controller is detected: DID: 0x%x: SVID: 0x%x: SDID: 0x%x\n",
386 2d1d418eSSumit Saxena pci_get_device(dev), pci_get_subvendor(dev),
387 2d1d418eSSumit Saxena pci_get_subdevice(dev));
388 2d1d418eSSumit Saxena retval = -1;
389 2d1d418eSSumit Saxena break;
390 2d1d418eSSumit Saxena default:
391 2d1d418eSSumit Saxena retval = -1;
392 2d1d418eSSumit Saxena break;
393 2d1d418eSSumit Saxena }
394 2d1d418eSSumit Saxena
395 2d1d418eSSumit Saxena if (!retval && debug_status) {
396 2d1d418eSSumit Saxena device_printf(dev,
397 2d1d418eSSumit Saxena "Secure Debug (Non secure) controller is detected: DID: 0x%x: SVID: 0x%x: SDID: 0x%x\n",
398 2d1d418eSSumit Saxena pci_get_device(dev), pci_get_subvendor(dev),
399 2d1d418eSSumit Saxena pci_get_subdevice(dev));
400 2d1d418eSSumit Saxena retval = -1;
401 2d1d418eSSumit Saxena }
402 2d1d418eSSumit Saxena
403 2d1d418eSSumit Saxena return retval;
404 2d1d418eSSumit Saxena }
405 2d1d418eSSumit Saxena /*
406 2d1d418eSSumit Saxena * mpi3mr_pci_attach - PCI entry point
407 2d1d418eSSumit Saxena * @dev: pointer to device struct
408 2d1d418eSSumit Saxena *
409 2d1d418eSSumit Saxena * This function does the setup of PCI and registers, allocates controller resources,
410 2d1d418eSSumit Saxena * initializes mutexes, linked lists and registers interrupts, CAM and initializes
411 2d1d418eSSumit Saxena * the controller.
412 2d1d418eSSumit Saxena *
413 2d1d418eSSumit Saxena * Return: 0 on success and proper error codes on failure
414 2d1d418eSSumit Saxena */
415 2d1d418eSSumit Saxena static int
mpi3mr_pci_attach(device_t dev)416 2d1d418eSSumit Saxena mpi3mr_pci_attach(device_t dev)
417 2d1d418eSSumit Saxena {
418 2d1d418eSSumit Saxena struct mpi3mr_softc *sc;
419 2d1d418eSSumit Saxena int error;
420 2d1d418eSSumit Saxena
421 2d1d418eSSumit Saxena sc = device_get_softc(dev);
422 2d1d418eSSumit Saxena bzero(sc, sizeof(*sc));
423 2d1d418eSSumit Saxena sc->mpi3mr_dev = dev;
424 2d1d418eSSumit Saxena
425 2d1d418eSSumit Saxena /* Don't load driver for Non-Secure controllers */
426 2d1d418eSSumit Saxena if (mpi3mr_ctrl_security_status(dev)) {
427 2d1d418eSSumit Saxena sc->secure_ctrl = false;
428 2d1d418eSSumit Saxena return 0;
429 2d1d418eSSumit Saxena }
430 2d1d418eSSumit Saxena
431 2d1d418eSSumit Saxena sc->secure_ctrl = true;
432 2d1d418eSSumit Saxena
433 2d1d418eSSumit Saxena if ((error = mpi3mr_setup_resources(sc)) != 0)
434 2d1d418eSSumit Saxena goto load_failed;
435 2d1d418eSSumit Saxena
436 2d1d418eSSumit Saxena sc->id = sc_ids++;
437 2d1d418eSSumit Saxena mpi3mr_atomic_set(&sc->fw_outstanding, 0);
438 2d1d418eSSumit Saxena mpi3mr_atomic_set(&sc->pend_ioctls, 0);
439 2d1d418eSSumit Saxena sc->admin_req = NULL;
440 2d1d418eSSumit Saxena sc->admin_reply = NULL;
441 2d1d418eSSumit Saxena sprintf(sc->driver_name, "%s", MPI3MR_DRIVER_NAME);
442 2d1d418eSSumit Saxena sprintf(sc->name, "%s%d", sc->driver_name, sc->id);
443 2d1d418eSSumit Saxena
444 2d1d418eSSumit Saxena sc->mpi3mr_dev = dev;
445 2d1d418eSSumit Saxena mpi3mr_get_tunables(sc);
446 2d1d418eSSumit Saxena
447 2d1d418eSSumit Saxena if ((error = mpi3mr_initialize_ioc(sc, MPI3MR_INIT_TYPE_INIT)) != 0) {
448 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "FW initialization failed\n");
449 2d1d418eSSumit Saxena goto load_failed;
450 2d1d418eSSumit Saxena }
451 2d1d418eSSumit Saxena
452 2d1d418eSSumit Saxena if ((error = mpi3mr_alloc_requests(sc)) != 0) {
453 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Command frames allocation failed\n");
454 2d1d418eSSumit Saxena goto load_failed;
455 2d1d418eSSumit Saxena }
456 2d1d418eSSumit Saxena
457 2d1d418eSSumit Saxena if ((error = mpi3mr_cam_attach(sc)) != 0) {
458 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "CAM attach failed\n");
459 2d1d418eSSumit Saxena goto load_failed;
460 2d1d418eSSumit Saxena }
461 2d1d418eSSumit Saxena
462 2d1d418eSSumit Saxena sc->mpi3mr_ich.ich_func = mpi3mr_ich_startup;
463 2d1d418eSSumit Saxena sc->mpi3mr_ich.ich_arg = sc;
464 2d1d418eSSumit Saxena if (config_intrhook_establish(&sc->mpi3mr_ich) != 0) {
465 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR,
466 2d1d418eSSumit Saxena "Cannot establish MPI3MR ICH config hook\n");
467 2d1d418eSSumit Saxena error = EINVAL;
468 2d1d418eSSumit Saxena }
469 2d1d418eSSumit Saxena
470 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "allocating ioctl dma buffers\n");
471 2d1d418eSSumit Saxena mpi3mr_alloc_ioctl_dma_memory(sc);
472 2d1d418eSSumit Saxena
473 2d1d418eSSumit Saxena if ((error = mpi3mr_app_attach(sc)) != 0) {
474 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "APP/IOCTL attach failed\n");
475 2d1d418eSSumit Saxena goto load_failed;
476 2d1d418eSSumit Saxena }
477 2d1d418eSSumit Saxena
478 2d1d418eSSumit Saxena mpi3mr_setup_sysctl(sc);
479 2d1d418eSSumit Saxena
480 2d1d418eSSumit Saxena return 0;
481 2d1d418eSSumit Saxena
482 2d1d418eSSumit Saxena load_failed:
483 2d1d418eSSumit Saxena mpi3mr_cleanup_interrupts(sc);
484 2d1d418eSSumit Saxena mpi3mr_free_mem(sc);
485 2d1d418eSSumit Saxena mpi3mr_app_detach(sc);
486 2d1d418eSSumit Saxena mpi3mr_cam_detach(sc);
487 2d1d418eSSumit Saxena mpi3mr_destory_mtx(sc);
488 2d1d418eSSumit Saxena mpi3mr_release_resources(sc);
489 2d1d418eSSumit Saxena return error;
490 2d1d418eSSumit Saxena }
491 2d1d418eSSumit Saxena
mpi3mr_cleanup_interrupts(struct mpi3mr_softc * sc)492 2d1d418eSSumit Saxena void mpi3mr_cleanup_interrupts(struct mpi3mr_softc *sc)
493 2d1d418eSSumit Saxena {
494 2d1d418eSSumit Saxena mpi3mr_disable_interrupts(sc);
495 2d1d418eSSumit Saxena
496 2d1d418eSSumit Saxena mpi3mr_teardown_irqs(sc);
497 2d1d418eSSumit Saxena
498 2d1d418eSSumit Saxena if (sc->irq_ctx) {
499 2d1d418eSSumit Saxena free(sc->irq_ctx, M_MPI3MR);
500 2d1d418eSSumit Saxena sc->irq_ctx = NULL;
501 2d1d418eSSumit Saxena }
502 2d1d418eSSumit Saxena
503 2d1d418eSSumit Saxena if (sc->msix_enable)
504 2d1d418eSSumit Saxena pci_release_msi(sc->mpi3mr_dev);
505 2d1d418eSSumit Saxena
506 2d1d418eSSumit Saxena sc->msix_count = 0;
507 2d1d418eSSumit Saxena
508 2d1d418eSSumit Saxena }
509 2d1d418eSSumit Saxena
mpi3mr_setup_irqs(struct mpi3mr_softc * sc)510 2d1d418eSSumit Saxena int mpi3mr_setup_irqs(struct mpi3mr_softc *sc)
511 2d1d418eSSumit Saxena {
512 2d1d418eSSumit Saxena device_t dev;
513 2d1d418eSSumit Saxena int error;
514 2d1d418eSSumit Saxena int i, rid, initial_rid;
515 2d1d418eSSumit Saxena struct mpi3mr_irq_context *irq_ctx;
516 2d1d418eSSumit Saxena struct irq_info *irq_info;
517 2d1d418eSSumit Saxena
518 2d1d418eSSumit Saxena dev = sc->mpi3mr_dev;
519 2d1d418eSSumit Saxena error = -1;
520 2d1d418eSSumit Saxena
521 2d1d418eSSumit Saxena if (sc->msix_enable)
522 2d1d418eSSumit Saxena initial_rid = 1;
523 2d1d418eSSumit Saxena else
524 2d1d418eSSumit Saxena initial_rid = 0;
525 2d1d418eSSumit Saxena
526 2d1d418eSSumit Saxena for (i = 0; i < sc->msix_count; i++) {
527 2d1d418eSSumit Saxena irq_ctx = &sc->irq_ctx[i];
528 2d1d418eSSumit Saxena irq_ctx->msix_index = i;
529 2d1d418eSSumit Saxena irq_ctx->sc = sc;
530 2d1d418eSSumit Saxena irq_info = &irq_ctx->irq_info;
531 2d1d418eSSumit Saxena rid = i + initial_rid;
532 2d1d418eSSumit Saxena irq_info->irq_rid = rid;
533 2d1d418eSSumit Saxena irq_info->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
534 2d1d418eSSumit Saxena &irq_info->irq_rid, RF_ACTIVE);
535 2d1d418eSSumit Saxena if (irq_info->irq == NULL) {
536 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR,
537 2d1d418eSSumit Saxena "Cannot allocate interrupt RID %d\n", rid);
538 2d1d418eSSumit Saxena sc->msix_count = i;
539 2d1d418eSSumit Saxena break;
540 2d1d418eSSumit Saxena }
541 2d1d418eSSumit Saxena error = bus_setup_intr(dev, irq_info->irq,
542 2d1d418eSSumit Saxena INTR_MPSAFE | INTR_TYPE_CAM, NULL, mpi3mr_isr,
543 2d1d418eSSumit Saxena irq_ctx, &irq_info->intrhand);
544 2d1d418eSSumit Saxena if (error) {
545 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR,
546 2d1d418eSSumit Saxena "Cannot setup interrupt RID %d\n", rid);
547 2d1d418eSSumit Saxena sc->msix_count = i;
548 2d1d418eSSumit Saxena break;
549 2d1d418eSSumit Saxena }
550 2d1d418eSSumit Saxena }
551 2d1d418eSSumit Saxena
552 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Set up %d MSI-x interrupts\n", sc->msix_count);
553 2d1d418eSSumit Saxena
554 2d1d418eSSumit Saxena return (error);
555 2d1d418eSSumit Saxena
556 2d1d418eSSumit Saxena }
557 2d1d418eSSumit Saxena
558 2d1d418eSSumit Saxena static void
mpi3mr_teardown_irqs(struct mpi3mr_softc * sc)559 2d1d418eSSumit Saxena mpi3mr_teardown_irqs(struct mpi3mr_softc *sc)
560 2d1d418eSSumit Saxena {
561 2d1d418eSSumit Saxena struct irq_info *irq_info;
562 2d1d418eSSumit Saxena int i;
563 2d1d418eSSumit Saxena
564 2d1d418eSSumit Saxena for (i = 0; i < sc->msix_count; i++) {
565 2d1d418eSSumit Saxena irq_info = &sc->irq_ctx[i].irq_info;
566 2d1d418eSSumit Saxena if (irq_info->irq != NULL) {
567 2d1d418eSSumit Saxena bus_teardown_intr(sc->mpi3mr_dev, irq_info->irq,
568 2d1d418eSSumit Saxena irq_info->intrhand);
569 2d1d418eSSumit Saxena bus_release_resource(sc->mpi3mr_dev, SYS_RES_IRQ,
570 2d1d418eSSumit Saxena irq_info->irq_rid, irq_info->irq);
571 2d1d418eSSumit Saxena }
572 2d1d418eSSumit Saxena }
573 2d1d418eSSumit Saxena
574 2d1d418eSSumit Saxena }
575 2d1d418eSSumit Saxena
576 2d1d418eSSumit Saxena /*
577 2d1d418eSSumit Saxena * Allocate, but don't assign interrupts early. Doing it before requesting
578 2d1d418eSSumit Saxena * the IOCFacts message informs the firmware that we want to do MSI-X
579 2d1d418eSSumit Saxena * multiqueue. We might not use all of the available messages, but there's
580 2d1d418eSSumit Saxena * no reason to re-alloc if we don't.
581 2d1d418eSSumit Saxena */
582 2d1d418eSSumit Saxena int
mpi3mr_alloc_interrupts(struct mpi3mr_softc * sc,U16 setup_one)583 2d1d418eSSumit Saxena mpi3mr_alloc_interrupts(struct mpi3mr_softc *sc, U16 setup_one)
584 2d1d418eSSumit Saxena {
585 2d1d418eSSumit Saxena int error, msgs;
586 2d1d418eSSumit Saxena U16 num_queues;
587 2d1d418eSSumit Saxena
588 2d1d418eSSumit Saxena error = 0;
589 2d1d418eSSumit Saxena msgs = 0;
590 2d1d418eSSumit Saxena
591 2d1d418eSSumit Saxena mpi3mr_cleanup_interrupts(sc);
592 2d1d418eSSumit Saxena
593 2d1d418eSSumit Saxena if (setup_one) {
594 2d1d418eSSumit Saxena msgs = 1;
595 2d1d418eSSumit Saxena } else {
596 2d1d418eSSumit Saxena msgs = min(sc->max_msix_vectors, sc->cpu_count);
597 2d1d418eSSumit Saxena num_queues = min(sc->facts.max_op_reply_q, sc->facts.max_op_req_q);
598 2d1d418eSSumit Saxena msgs = min(msgs, num_queues);
599 2d1d418eSSumit Saxena
600 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Supported MSI-x count: %d "
601 2d1d418eSSumit Saxena " CPU count: %d Requested MSI-x count: %d\n",
602 2d1d418eSSumit Saxena sc->max_msix_vectors,
603 2d1d418eSSumit Saxena sc->cpu_count, msgs);
604 2d1d418eSSumit Saxena }
605 2d1d418eSSumit Saxena
606 2d1d418eSSumit Saxena if (msgs != 0) {
607 2d1d418eSSumit Saxena error = pci_alloc_msix(sc->mpi3mr_dev, &msgs);
608 2d1d418eSSumit Saxena if (error) {
609 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR,
610 2d1d418eSSumit Saxena "Could not allocate MSI-x interrupts Error: %x\n", error);
611 2d1d418eSSumit Saxena goto out_failed;
612 2d1d418eSSumit Saxena } else
613 2d1d418eSSumit Saxena sc->msix_enable = 1;
614 2d1d418eSSumit Saxena }
615 2d1d418eSSumit Saxena
616 2d1d418eSSumit Saxena sc->msix_count = msgs;
617 2d1d418eSSumit Saxena sc->irq_ctx = malloc(sizeof(struct mpi3mr_irq_context) * msgs,
618 2d1d418eSSumit Saxena M_MPI3MR, M_NOWAIT | M_ZERO);
619 2d1d418eSSumit Saxena
620 2d1d418eSSumit Saxena if (!sc->irq_ctx) {
621 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot alloc memory for interrupt info\n");
622 2d1d418eSSumit Saxena error = -1;
623 2d1d418eSSumit Saxena goto out_failed;
624 2d1d418eSSumit Saxena }
625 2d1d418eSSumit Saxena
626 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "Allocated %d MSI-x interrupts\n", msgs);
627 2d1d418eSSumit Saxena
628 2d1d418eSSumit Saxena return error;
629 2d1d418eSSumit Saxena out_failed:
630 2d1d418eSSumit Saxena mpi3mr_cleanup_interrupts(sc);
631 2d1d418eSSumit Saxena return (error);
632 2d1d418eSSumit Saxena }
633 2d1d418eSSumit Saxena
634 2d1d418eSSumit Saxena static int
mpi3mr_pci_detach(device_t dev)635 2d1d418eSSumit Saxena mpi3mr_pci_detach(device_t dev)
636 2d1d418eSSumit Saxena {
637 2d1d418eSSumit Saxena struct mpi3mr_softc *sc;
638 2d1d418eSSumit Saxena int i = 0;
639 2d1d418eSSumit Saxena
640 2d1d418eSSumit Saxena sc = device_get_softc(dev);
641 2d1d418eSSumit Saxena
642 2d1d418eSSumit Saxena if (!sc->secure_ctrl)
643 2d1d418eSSumit Saxena return 0;
644 2d1d418eSSumit Saxena
645 2d1d418eSSumit Saxena
646 2d1d418eSSumit Saxena if (sc->sysctl_tree != NULL)
647 2d1d418eSSumit Saxena sysctl_ctx_free(&sc->sysctl_ctx);
648 2d1d418eSSumit Saxena
649 7c491309SWarner Losh mtx_lock(&sc->reset_mutex);
650 7c491309SWarner Losh sc->mpi3mr_flags |= MPI3MR_FLAGS_SHUTDOWN;
651 2d1d418eSSumit Saxena if (sc->watchdog_thread_active)
652 2d1d418eSSumit Saxena wakeup(&sc->watchdog_chan);
653 7c491309SWarner Losh mtx_unlock(&sc->reset_mutex);
654 2d1d418eSSumit Saxena
655 2d1d418eSSumit Saxena while (sc->reset_in_progress && (i < PEND_IOCTLS_COMP_WAIT_TIME)) {
656 2d1d418eSSumit Saxena i++;
657 2d1d418eSSumit Saxena if (!(i % 5)) {
658 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO,
659 2d1d418eSSumit Saxena "[%2d]waiting for reset to be finished from %s\n", i, __func__);
660 2d1d418eSSumit Saxena }
661 2d1d418eSSumit Saxena pause("mpi3mr_shutdown", hz);
662 2d1d418eSSumit Saxena }
663 2d1d418eSSumit Saxena
664 2d1d418eSSumit Saxena i = 0;
665 2d1d418eSSumit Saxena while (sc->watchdog_thread_active && (i < 180)) {
666 2d1d418eSSumit Saxena i++;
667 2d1d418eSSumit Saxena if (!(i % 5)) {
668 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO,
669 2d1d418eSSumit Saxena "[%2d]waiting for "
670 2d1d418eSSumit Saxena "mpi3mr_reset thread to quit reset %d\n", i,
671 2d1d418eSSumit Saxena sc->watchdog_thread_active);
672 2d1d418eSSumit Saxena }
673 2d1d418eSSumit Saxena pause("mpi3mr_shutdown", hz);
674 2d1d418eSSumit Saxena }
675 2d1d418eSSumit Saxena
676 2d1d418eSSumit Saxena i = 0;
677 2d1d418eSSumit Saxena while (mpi3mr_atomic_read(&sc->pend_ioctls) && (i < 180)) {
678 2d1d418eSSumit Saxena i++;
679 2d1d418eSSumit Saxena if (!(i % 5)) {
680 2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO,
681 2d1d418eSSumit Saxena "[%2d]waiting for IOCTL to be finished from %s\n", i, __func__);
682 2d1d418eSSumit Saxena }
683 2d1d418eSSumit Saxena pause("mpi3mr_shutdown", hz);
684 2d1d418eSSumit Saxena }
685 2d1d418eSSumit Saxena
686 2d1d418eSSumit Saxena mpi3mr_cleanup_ioc(sc);
687 2d1d418eSSumit Saxena mpi3mr_cleanup_event_taskq(sc);
688 2d1d418eSSumit Saxena mpi3mr_app_detach(sc);
689 2d1d418eSSumit Saxena mpi3mr_cam_detach(sc);
690 2d1d418eSSumit Saxena mpi3mr_cleanup_interrupts(sc);
691 2d1d418eSSumit Saxena mpi3mr_destory_mtx(sc);
692 2d1d418eSSumit Saxena mpi3mr_free_mem(sc);
693 2d1d418eSSumit Saxena mpi3mr_release_resources(sc);
694 2d1d418eSSumit Saxena sc_ids--;
695 2d1d418eSSumit Saxena return (0);
696 2d1d418eSSumit Saxena }
697 2d1d418eSSumit Saxena
698 2d1d418eSSumit Saxena static int
mpi3mr_pci_suspend(device_t dev)699 2d1d418eSSumit Saxena mpi3mr_pci_suspend(device_t dev)
700 2d1d418eSSumit Saxena {
701 2d1d418eSSumit Saxena return (EINVAL);
702 2d1d418eSSumit Saxena }
703 2d1d418eSSumit Saxena
704 2d1d418eSSumit Saxena static int
mpi3mr_pci_resume(device_t dev)705 2d1d418eSSumit Saxena mpi3mr_pci_resume(device_t dev)
706 2d1d418eSSumit Saxena {
707 2d1d418eSSumit Saxena return (EINVAL);
708 2d1d418eSSumit Saxena }
709