1*fd501800SSascha Wildner /*-
2*fd501800SSascha Wildner * Copyright (c) 2011-2015 LSI Corp.
3*fd501800SSascha Wildner * Copyright (c) 2013-2016 Avago Technologies
4*fd501800SSascha Wildner * All rights reserved.
5*fd501800SSascha Wildner *
6*fd501800SSascha Wildner * Redistribution and use in source and binary forms, with or without
7*fd501800SSascha Wildner * modification, are permitted provided that the following conditions
8*fd501800SSascha Wildner * are met:
9*fd501800SSascha Wildner * 1. Redistributions of source code must retain the above copyright
10*fd501800SSascha Wildner * notice, this list of conditions and the following disclaimer.
11*fd501800SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
12*fd501800SSascha Wildner * notice, this list of conditions and the following disclaimer in the
13*fd501800SSascha Wildner * documentation and/or other materials provided with the distribution.
14*fd501800SSascha Wildner *
15*fd501800SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*fd501800SSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*fd501800SSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*fd501800SSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*fd501800SSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*fd501800SSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*fd501800SSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*fd501800SSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*fd501800SSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*fd501800SSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*fd501800SSascha Wildner * SUCH DAMAGE.
26*fd501800SSascha Wildner *
27*fd501800SSascha Wildner * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
28*fd501800SSascha Wildner *
29*fd501800SSascha Wildner * $FreeBSD: head/sys/dev/mpr/mpr_config.c 322364 2017-08-10 14:59:17Z ken $
30*fd501800SSascha Wildner */
31*fd501800SSascha Wildner
32*fd501800SSascha Wildner /* TODO Move headers to mprvar */
33*fd501800SSascha Wildner #include <sys/types.h>
34*fd501800SSascha Wildner #include <sys/param.h>
35*fd501800SSascha Wildner #include <sys/lock.h>
36*fd501800SSascha Wildner #include <sys/systm.h>
37*fd501800SSascha Wildner #include <sys/kernel.h>
38*fd501800SSascha Wildner #include <sys/malloc.h>
39*fd501800SSascha Wildner #include <sys/kthread.h>
40*fd501800SSascha Wildner #include <sys/taskqueue.h>
41*fd501800SSascha Wildner #include <sys/bus.h>
42*fd501800SSascha Wildner #include <sys/endian.h>
43*fd501800SSascha Wildner #include <sys/sysctl.h>
44*fd501800SSascha Wildner #include <sys/eventhandler.h>
45*fd501800SSascha Wildner #include <sys/uio.h>
46*fd501800SSascha Wildner #include <dev/raid/mpr/mpi/mpi2_type.h>
47*fd501800SSascha Wildner #include <dev/raid/mpr/mpi/mpi2.h>
48*fd501800SSascha Wildner #include <dev/raid/mpr/mpi/mpi2_ioc.h>
49*fd501800SSascha Wildner #include <dev/raid/mpr/mpi/mpi2_sas.h>
50*fd501800SSascha Wildner #include <dev/raid/mpr/mpi/mpi2_pci.h>
51*fd501800SSascha Wildner #include <dev/raid/mpr/mpi/mpi2_cnfg.h>
52*fd501800SSascha Wildner #include <dev/raid/mpr/mpi/mpi2_init.h>
53*fd501800SSascha Wildner #include <dev/raid/mpr/mpi/mpi2_tool.h>
54*fd501800SSascha Wildner #include <dev/raid/mpr/mpr_ioctl.h>
55*fd501800SSascha Wildner #include <dev/raid/mpr/mprvar.h>
56*fd501800SSascha Wildner
57*fd501800SSascha Wildner /**
58*fd501800SSascha Wildner * mpr_config_get_ioc_pg8 - obtain ioc page 8
59*fd501800SSascha Wildner * @sc: per adapter object
60*fd501800SSascha Wildner * @mpi_reply: reply mf payload returned from firmware
61*fd501800SSascha Wildner * @config_page: contents of the config page
62*fd501800SSascha Wildner * Context: sleep.
63*fd501800SSascha Wildner *
64*fd501800SSascha Wildner * Returns 0 for success, non-zero for failure.
65*fd501800SSascha Wildner */
66*fd501800SSascha Wildner int
mpr_config_get_ioc_pg8(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2IOCPage8_t * config_page)67*fd501800SSascha Wildner mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
68*fd501800SSascha Wildner Mpi2IOCPage8_t *config_page)
69*fd501800SSascha Wildner {
70*fd501800SSascha Wildner MPI2_CONFIG_REQUEST *request;
71*fd501800SSascha Wildner MPI2_CONFIG_REPLY *reply = NULL; /* XXX swildner: warning fix */
72*fd501800SSascha Wildner struct mpr_command *cm;
73*fd501800SSascha Wildner MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
74*fd501800SSascha Wildner int error = 0;
75*fd501800SSascha Wildner u16 ioc_status;
76*fd501800SSascha Wildner
77*fd501800SSascha Wildner mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
78*fd501800SSascha Wildner
79*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
80*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
81*fd501800SSascha Wildner __LINE__);
82*fd501800SSascha Wildner error = EBUSY;
83*fd501800SSascha Wildner goto out;
84*fd501800SSascha Wildner }
85*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
86*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
87*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
88*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
89*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
90*fd501800SSascha Wildner request->Header.PageNumber = 8;
91*fd501800SSascha Wildner request->Header.PageLength = request->Header.PageVersion = 0;
92*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
93*fd501800SSascha Wildner cm->cm_data = NULL;
94*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
95*fd501800SSascha Wildner if (cm != NULL)
96*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
97*fd501800SSascha Wildner if (error || (reply == NULL)) {
98*fd501800SSascha Wildner /* FIXME */
99*fd501800SSascha Wildner /*
100*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
101*fd501800SSascha Wildner * reset
102*fd501800SSascha Wildner */
103*fd501800SSascha Wildner kprintf("%s: request for header completed with error %d",
104*fd501800SSascha Wildner __func__, error);
105*fd501800SSascha Wildner error = ENXIO;
106*fd501800SSascha Wildner goto out;
107*fd501800SSascha Wildner }
108*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
109*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
110*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
111*fd501800SSascha Wildner /* FIXME */
112*fd501800SSascha Wildner /*
113*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
114*fd501800SSascha Wildner * reset
115*fd501800SSascha Wildner */
116*fd501800SSascha Wildner kprintf("%s: header read with error; iocstatus = 0x%x\n",
117*fd501800SSascha Wildner __func__, ioc_status);
118*fd501800SSascha Wildner error = ENXIO;
119*fd501800SSascha Wildner goto out;
120*fd501800SSascha Wildner }
121*fd501800SSascha Wildner /* We have to do free and alloc for the reply-free and reply-post
122*fd501800SSascha Wildner * counters to match - Need to review the reply FIFO handling.
123*fd501800SSascha Wildner */
124*fd501800SSascha Wildner mpr_free_command(sc, cm);
125*fd501800SSascha Wildner
126*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
127*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
128*fd501800SSascha Wildner __LINE__);
129*fd501800SSascha Wildner error = EBUSY;
130*fd501800SSascha Wildner goto out;
131*fd501800SSascha Wildner }
132*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
133*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
134*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
135*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
136*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
137*fd501800SSascha Wildner request->Header.PageNumber = 8;
138*fd501800SSascha Wildner request->Header.PageVersion = mpi_reply->Header.PageVersion;
139*fd501800SSascha Wildner request->Header.PageLength = mpi_reply->Header.PageLength;
140*fd501800SSascha Wildner cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
141*fd501800SSascha Wildner cm->cm_sge = &request->PageBufferSGE;
142*fd501800SSascha Wildner cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
143*fd501800SSascha Wildner cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
144*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
145*fd501800SSascha Wildner page = kmalloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
146*fd501800SSascha Wildner if (!page) {
147*fd501800SSascha Wildner kprintf("%s: page alloc failed\n", __func__);
148*fd501800SSascha Wildner error = ENOMEM;
149*fd501800SSascha Wildner goto out;
150*fd501800SSascha Wildner }
151*fd501800SSascha Wildner cm->cm_data = page;
152*fd501800SSascha Wildner
153*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
154*fd501800SSascha Wildner if (cm != NULL)
155*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
156*fd501800SSascha Wildner if (error || (reply == NULL)) {
157*fd501800SSascha Wildner /* FIXME */
158*fd501800SSascha Wildner /*
159*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
160*fd501800SSascha Wildner * reset
161*fd501800SSascha Wildner */
162*fd501800SSascha Wildner kprintf("%s: request for page completed with error %d",
163*fd501800SSascha Wildner __func__, error);
164*fd501800SSascha Wildner error = ENXIO;
165*fd501800SSascha Wildner goto out;
166*fd501800SSascha Wildner }
167*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
168*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
169*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
170*fd501800SSascha Wildner /* FIXME */
171*fd501800SSascha Wildner /*
172*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
173*fd501800SSascha Wildner * reset
174*fd501800SSascha Wildner */
175*fd501800SSascha Wildner kprintf("%s: page read with error; iocstatus = 0x%x\n",
176*fd501800SSascha Wildner __func__, ioc_status);
177*fd501800SSascha Wildner error = ENXIO;
178*fd501800SSascha Wildner goto out;
179*fd501800SSascha Wildner }
180*fd501800SSascha Wildner bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
181*fd501800SSascha Wildner
182*fd501800SSascha Wildner out:
183*fd501800SSascha Wildner kfree(page, M_MPR);
184*fd501800SSascha Wildner if (cm)
185*fd501800SSascha Wildner mpr_free_command(sc, cm);
186*fd501800SSascha Wildner return (error);
187*fd501800SSascha Wildner }
188*fd501800SSascha Wildner
189*fd501800SSascha Wildner /**
190*fd501800SSascha Wildner * mpr_config_get_iounit_pg8 - obtain iounit page 8
191*fd501800SSascha Wildner * @sc: per adapter object
192*fd501800SSascha Wildner * @mpi_reply: reply mf payload returned from firmware
193*fd501800SSascha Wildner * @config_page: contents of the config page
194*fd501800SSascha Wildner * Context: sleep.
195*fd501800SSascha Wildner *
196*fd501800SSascha Wildner * Returns 0 for success, non-zero for failure.
197*fd501800SSascha Wildner */
198*fd501800SSascha Wildner int
mpr_config_get_iounit_pg8(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2IOUnitPage8_t * config_page)199*fd501800SSascha Wildner mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
200*fd501800SSascha Wildner Mpi2IOUnitPage8_t *config_page)
201*fd501800SSascha Wildner {
202*fd501800SSascha Wildner MPI2_CONFIG_REQUEST *request;
203*fd501800SSascha Wildner MPI2_CONFIG_REPLY *reply = NULL; /* XXX swildner: warning fix */
204*fd501800SSascha Wildner struct mpr_command *cm;
205*fd501800SSascha Wildner MPI2_CONFIG_PAGE_IO_UNIT_8 *page = NULL;
206*fd501800SSascha Wildner int error = 0;
207*fd501800SSascha Wildner u16 ioc_status;
208*fd501800SSascha Wildner
209*fd501800SSascha Wildner mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
210*fd501800SSascha Wildner
211*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
212*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
213*fd501800SSascha Wildner __LINE__);
214*fd501800SSascha Wildner error = EBUSY;
215*fd501800SSascha Wildner goto out;
216*fd501800SSascha Wildner }
217*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
218*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
219*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
220*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
221*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
222*fd501800SSascha Wildner request->Header.PageNumber = 8;
223*fd501800SSascha Wildner request->Header.PageLength = request->Header.PageVersion = 0;
224*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
225*fd501800SSascha Wildner cm->cm_data = NULL;
226*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
227*fd501800SSascha Wildner if (cm != NULL)
228*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
229*fd501800SSascha Wildner if (error || (reply == NULL)) {
230*fd501800SSascha Wildner /* FIXME */
231*fd501800SSascha Wildner /*
232*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
233*fd501800SSascha Wildner * reset
234*fd501800SSascha Wildner */
235*fd501800SSascha Wildner kprintf("%s: request for header completed with error %d",
236*fd501800SSascha Wildner __func__, error);
237*fd501800SSascha Wildner error = ENXIO;
238*fd501800SSascha Wildner goto out;
239*fd501800SSascha Wildner }
240*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
241*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
242*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
243*fd501800SSascha Wildner /* FIXME */
244*fd501800SSascha Wildner /*
245*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
246*fd501800SSascha Wildner * reset
247*fd501800SSascha Wildner */
248*fd501800SSascha Wildner kprintf("%s: header read with error; iocstatus = 0x%x\n",
249*fd501800SSascha Wildner __func__, ioc_status);
250*fd501800SSascha Wildner error = ENXIO;
251*fd501800SSascha Wildner goto out;
252*fd501800SSascha Wildner }
253*fd501800SSascha Wildner /* We have to do free and alloc for the reply-free and reply-post
254*fd501800SSascha Wildner * counters to match - Need to review the reply FIFO handling.
255*fd501800SSascha Wildner */
256*fd501800SSascha Wildner mpr_free_command(sc, cm);
257*fd501800SSascha Wildner
258*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
259*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
260*fd501800SSascha Wildner __LINE__);
261*fd501800SSascha Wildner error = EBUSY;
262*fd501800SSascha Wildner goto out;
263*fd501800SSascha Wildner }
264*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
265*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
266*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
267*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
268*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
269*fd501800SSascha Wildner request->Header.PageNumber = 8;
270*fd501800SSascha Wildner request->Header.PageVersion = mpi_reply->Header.PageVersion;
271*fd501800SSascha Wildner request->Header.PageLength = mpi_reply->Header.PageLength;
272*fd501800SSascha Wildner cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
273*fd501800SSascha Wildner cm->cm_sge = &request->PageBufferSGE;
274*fd501800SSascha Wildner cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
275*fd501800SSascha Wildner cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
276*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
277*fd501800SSascha Wildner page = kmalloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
278*fd501800SSascha Wildner if (!page) {
279*fd501800SSascha Wildner kprintf("%s: page alloc failed\n", __func__);
280*fd501800SSascha Wildner error = ENOMEM;
281*fd501800SSascha Wildner goto out;
282*fd501800SSascha Wildner }
283*fd501800SSascha Wildner cm->cm_data = page;
284*fd501800SSascha Wildner
285*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
286*fd501800SSascha Wildner if (cm != NULL)
287*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
288*fd501800SSascha Wildner if (error || (reply == NULL)) {
289*fd501800SSascha Wildner /* FIXME */
290*fd501800SSascha Wildner /*
291*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
292*fd501800SSascha Wildner * reset
293*fd501800SSascha Wildner */
294*fd501800SSascha Wildner kprintf("%s: request for page completed with error %d",
295*fd501800SSascha Wildner __func__, error);
296*fd501800SSascha Wildner error = ENXIO;
297*fd501800SSascha Wildner goto out;
298*fd501800SSascha Wildner }
299*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
300*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
301*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
302*fd501800SSascha Wildner /* FIXME */
303*fd501800SSascha Wildner /*
304*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
305*fd501800SSascha Wildner * reset
306*fd501800SSascha Wildner */
307*fd501800SSascha Wildner kprintf("%s: page read with error; iocstatus = 0x%x\n",
308*fd501800SSascha Wildner __func__, ioc_status);
309*fd501800SSascha Wildner error = ENXIO;
310*fd501800SSascha Wildner goto out;
311*fd501800SSascha Wildner }
312*fd501800SSascha Wildner bcopy(page, config_page, MIN(cm->cm_length,
313*fd501800SSascha Wildner (sizeof(Mpi2IOUnitPage8_t))));
314*fd501800SSascha Wildner
315*fd501800SSascha Wildner out:
316*fd501800SSascha Wildner kfree(page, M_MPR);
317*fd501800SSascha Wildner if (cm)
318*fd501800SSascha Wildner mpr_free_command(sc, cm);
319*fd501800SSascha Wildner return (error);
320*fd501800SSascha Wildner }
321*fd501800SSascha Wildner
322*fd501800SSascha Wildner /**
323*fd501800SSascha Wildner * mpr_base_static_config_pages - static start of day config pages.
324*fd501800SSascha Wildner * @sc: per adapter object
325*fd501800SSascha Wildner *
326*fd501800SSascha Wildner * Return nothing.
327*fd501800SSascha Wildner */
328*fd501800SSascha Wildner void
mpr_base_static_config_pages(struct mpr_softc * sc)329*fd501800SSascha Wildner mpr_base_static_config_pages(struct mpr_softc *sc)
330*fd501800SSascha Wildner {
331*fd501800SSascha Wildner Mpi2ConfigReply_t mpi_reply;
332*fd501800SSascha Wildner int retry;
333*fd501800SSascha Wildner
334*fd501800SSascha Wildner retry = 0;
335*fd501800SSascha Wildner while (mpr_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
336*fd501800SSascha Wildner retry++;
337*fd501800SSascha Wildner if (retry > 5) {
338*fd501800SSascha Wildner /* We need to Handle this situation */
339*fd501800SSascha Wildner /*FIXME*/
340*fd501800SSascha Wildner break;
341*fd501800SSascha Wildner }
342*fd501800SSascha Wildner }
343*fd501800SSascha Wildner retry = 0;
344*fd501800SSascha Wildner while (mpr_config_get_iounit_pg8(sc, &mpi_reply, &sc->iounit_pg8)) {
345*fd501800SSascha Wildner retry++;
346*fd501800SSascha Wildner if (retry > 5) {
347*fd501800SSascha Wildner /* We need to Handle this situation */
348*fd501800SSascha Wildner /*FIXME*/
349*fd501800SSascha Wildner break;
350*fd501800SSascha Wildner }
351*fd501800SSascha Wildner }
352*fd501800SSascha Wildner }
353*fd501800SSascha Wildner
354*fd501800SSascha Wildner /**
355*fd501800SSascha Wildner * mpr_config_get_dpm_pg0 - obtain driver persistent mapping page0
356*fd501800SSascha Wildner * @sc: per adapter object
357*fd501800SSascha Wildner * @mpi_reply: reply mf payload returned from firmware
358*fd501800SSascha Wildner * @config_page: contents of the config page
359*fd501800SSascha Wildner * @sz: size of buffer passed in config_page
360*fd501800SSascha Wildner * Context: sleep.
361*fd501800SSascha Wildner *
362*fd501800SSascha Wildner * Returns 0 for success, non-zero for failure.
363*fd501800SSascha Wildner */
364*fd501800SSascha Wildner int
mpr_config_get_dpm_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2DriverMappingPage0_t * config_page,u16 sz)365*fd501800SSascha Wildner mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
366*fd501800SSascha Wildner Mpi2DriverMappingPage0_t *config_page, u16 sz)
367*fd501800SSascha Wildner {
368*fd501800SSascha Wildner MPI2_CONFIG_REQUEST *request;
369*fd501800SSascha Wildner MPI2_CONFIG_REPLY *reply = NULL; /* XXX swildner: warning fix */
370*fd501800SSascha Wildner struct mpr_command *cm;
371*fd501800SSascha Wildner Mpi2DriverMappingPage0_t *page = NULL;
372*fd501800SSascha Wildner int error = 0;
373*fd501800SSascha Wildner u16 ioc_status;
374*fd501800SSascha Wildner
375*fd501800SSascha Wildner mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
376*fd501800SSascha Wildner
377*fd501800SSascha Wildner memset(config_page, 0, sz);
378*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
379*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
380*fd501800SSascha Wildner __LINE__);
381*fd501800SSascha Wildner error = EBUSY;
382*fd501800SSascha Wildner goto out;
383*fd501800SSascha Wildner }
384*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
385*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
386*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
387*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
388*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
389*fd501800SSascha Wildner request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
390*fd501800SSascha Wildner request->Header.PageNumber = 0;
391*fd501800SSascha Wildner request->ExtPageLength = request->Header.PageVersion = 0;
392*fd501800SSascha Wildner request->PageAddress = sc->max_dpm_entries <<
393*fd501800SSascha Wildner MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
394*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
395*fd501800SSascha Wildner cm->cm_data = NULL;
396*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
397*fd501800SSascha Wildner if (cm != NULL)
398*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
399*fd501800SSascha Wildner if (error || (reply == NULL)) {
400*fd501800SSascha Wildner /* FIXME */
401*fd501800SSascha Wildner /*
402*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
403*fd501800SSascha Wildner * reset
404*fd501800SSascha Wildner */
405*fd501800SSascha Wildner kprintf("%s: request for header completed with error %d",
406*fd501800SSascha Wildner __func__, error);
407*fd501800SSascha Wildner error = ENXIO;
408*fd501800SSascha Wildner goto out;
409*fd501800SSascha Wildner }
410*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
411*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
412*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
413*fd501800SSascha Wildner /* FIXME */
414*fd501800SSascha Wildner /*
415*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
416*fd501800SSascha Wildner * reset
417*fd501800SSascha Wildner */
418*fd501800SSascha Wildner kprintf("%s: header read with error; iocstatus = 0x%x\n",
419*fd501800SSascha Wildner __func__, ioc_status);
420*fd501800SSascha Wildner error = ENXIO;
421*fd501800SSascha Wildner goto out;
422*fd501800SSascha Wildner }
423*fd501800SSascha Wildner /* We have to do free and alloc for the reply-free and reply-post
424*fd501800SSascha Wildner * counters to match - Need to review the reply FIFO handling.
425*fd501800SSascha Wildner */
426*fd501800SSascha Wildner mpr_free_command(sc, cm);
427*fd501800SSascha Wildner
428*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
429*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
430*fd501800SSascha Wildner __LINE__);
431*fd501800SSascha Wildner error = EBUSY;
432*fd501800SSascha Wildner goto out;
433*fd501800SSascha Wildner }
434*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
435*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
436*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
437*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
438*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
439*fd501800SSascha Wildner request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
440*fd501800SSascha Wildner request->Header.PageNumber = 0;
441*fd501800SSascha Wildner request->Header.PageVersion = mpi_reply->Header.PageVersion;
442*fd501800SSascha Wildner request->PageAddress = sc->max_dpm_entries <<
443*fd501800SSascha Wildner MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
444*fd501800SSascha Wildner request->ExtPageLength = mpi_reply->ExtPageLength;
445*fd501800SSascha Wildner cm->cm_length = le16toh(request->ExtPageLength) * 4;
446*fd501800SSascha Wildner cm->cm_sge = &request->PageBufferSGE;
447*fd501800SSascha Wildner cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
448*fd501800SSascha Wildner cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
449*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
450*fd501800SSascha Wildner page = kmalloc(cm->cm_length, M_MPR, M_ZERO|M_NOWAIT);
451*fd501800SSascha Wildner if (!page) {
452*fd501800SSascha Wildner kprintf("%s: page alloc failed\n", __func__);
453*fd501800SSascha Wildner error = ENOMEM;
454*fd501800SSascha Wildner goto out;
455*fd501800SSascha Wildner }
456*fd501800SSascha Wildner cm->cm_data = page;
457*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
458*fd501800SSascha Wildner if (cm != NULL)
459*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
460*fd501800SSascha Wildner if (error || (reply == NULL)) {
461*fd501800SSascha Wildner /* FIXME */
462*fd501800SSascha Wildner /*
463*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
464*fd501800SSascha Wildner * reset
465*fd501800SSascha Wildner */
466*fd501800SSascha Wildner kprintf("%s: request for page completed with error %d",
467*fd501800SSascha Wildner __func__, error);
468*fd501800SSascha Wildner error = ENXIO;
469*fd501800SSascha Wildner goto out;
470*fd501800SSascha Wildner }
471*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
472*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
473*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
474*fd501800SSascha Wildner /* FIXME */
475*fd501800SSascha Wildner /*
476*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
477*fd501800SSascha Wildner * reset
478*fd501800SSascha Wildner */
479*fd501800SSascha Wildner kprintf("%s: page read with error; iocstatus = 0x%x\n",
480*fd501800SSascha Wildner __func__, ioc_status);
481*fd501800SSascha Wildner error = ENXIO;
482*fd501800SSascha Wildner goto out;
483*fd501800SSascha Wildner }
484*fd501800SSascha Wildner bcopy(page, config_page, MIN(cm->cm_length, sz));
485*fd501800SSascha Wildner out:
486*fd501800SSascha Wildner kfree(page, M_MPR);
487*fd501800SSascha Wildner if (cm)
488*fd501800SSascha Wildner mpr_free_command(sc, cm);
489*fd501800SSascha Wildner return (error);
490*fd501800SSascha Wildner }
491*fd501800SSascha Wildner
492*fd501800SSascha Wildner /**
493*fd501800SSascha Wildner * mpr_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
494*fd501800SSascha Wildner * @sc: per adapter object
495*fd501800SSascha Wildner * @mpi_reply: reply mf payload returned from firmware
496*fd501800SSascha Wildner * @config_page: contents of the config page
497*fd501800SSascha Wildner * @entry_idx: entry index in DPM Page0 to be modified
498*fd501800SSascha Wildner * Context: sleep.
499*fd501800SSascha Wildner *
500*fd501800SSascha Wildner * Returns 0 for success, non-zero for failure.
501*fd501800SSascha Wildner */
502*fd501800SSascha Wildner
mpr_config_set_dpm_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2DriverMappingPage0_t * config_page,u16 entry_idx)503*fd501800SSascha Wildner int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
504*fd501800SSascha Wildner Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
505*fd501800SSascha Wildner {
506*fd501800SSascha Wildner MPI2_CONFIG_REQUEST *request;
507*fd501800SSascha Wildner MPI2_CONFIG_REPLY *reply = NULL; /* XXX swildner: warning fix */
508*fd501800SSascha Wildner struct mpr_command *cm;
509*fd501800SSascha Wildner MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
510*fd501800SSascha Wildner int error = 0;
511*fd501800SSascha Wildner u16 ioc_status;
512*fd501800SSascha Wildner
513*fd501800SSascha Wildner mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
514*fd501800SSascha Wildner
515*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
516*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
517*fd501800SSascha Wildner __LINE__);
518*fd501800SSascha Wildner error = EBUSY;
519*fd501800SSascha Wildner goto out;
520*fd501800SSascha Wildner }
521*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
522*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
523*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
524*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
525*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
526*fd501800SSascha Wildner request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
527*fd501800SSascha Wildner request->Header.PageNumber = 0;
528*fd501800SSascha Wildner request->ExtPageLength = request->Header.PageVersion = 0;
529*fd501800SSascha Wildner /* We can remove below two lines ????*/
530*fd501800SSascha Wildner request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
531*fd501800SSascha Wildner request->PageAddress |= htole16(entry_idx);
532*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
533*fd501800SSascha Wildner cm->cm_data = NULL;
534*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
535*fd501800SSascha Wildner if (cm != NULL)
536*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
537*fd501800SSascha Wildner if (error || (reply == NULL)) {
538*fd501800SSascha Wildner /* FIXME */
539*fd501800SSascha Wildner /*
540*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
541*fd501800SSascha Wildner * reset
542*fd501800SSascha Wildner */
543*fd501800SSascha Wildner kprintf("%s: request for header completed with error %d",
544*fd501800SSascha Wildner __func__, error);
545*fd501800SSascha Wildner error = ENXIO;
546*fd501800SSascha Wildner goto out;
547*fd501800SSascha Wildner }
548*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
549*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
550*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
551*fd501800SSascha Wildner /* FIXME */
552*fd501800SSascha Wildner /*
553*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
554*fd501800SSascha Wildner * reset
555*fd501800SSascha Wildner */
556*fd501800SSascha Wildner kprintf("%s: header read with error; iocstatus = 0x%x\n",
557*fd501800SSascha Wildner __func__, ioc_status);
558*fd501800SSascha Wildner error = ENXIO;
559*fd501800SSascha Wildner goto out;
560*fd501800SSascha Wildner }
561*fd501800SSascha Wildner /* We have to do free and alloc for the reply-free and reply-post
562*fd501800SSascha Wildner * counters to match - Need to review the reply FIFO handling.
563*fd501800SSascha Wildner */
564*fd501800SSascha Wildner mpr_free_command(sc, cm);
565*fd501800SSascha Wildner
566*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
567*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
568*fd501800SSascha Wildner __LINE__);
569*fd501800SSascha Wildner error = EBUSY;
570*fd501800SSascha Wildner goto out;
571*fd501800SSascha Wildner }
572*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
573*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
574*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
575*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
576*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
577*fd501800SSascha Wildner request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
578*fd501800SSascha Wildner request->Header.PageNumber = 0;
579*fd501800SSascha Wildner request->Header.PageVersion = mpi_reply->Header.PageVersion;
580*fd501800SSascha Wildner request->ExtPageLength = mpi_reply->ExtPageLength;
581*fd501800SSascha Wildner request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
582*fd501800SSascha Wildner request->PageAddress |= htole16(entry_idx);
583*fd501800SSascha Wildner cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
584*fd501800SSascha Wildner cm->cm_sge = &request->PageBufferSGE;
585*fd501800SSascha Wildner cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
586*fd501800SSascha Wildner cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT;
587*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
588*fd501800SSascha Wildner page = kmalloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
589*fd501800SSascha Wildner if (!page) {
590*fd501800SSascha Wildner kprintf("%s: page alloc failed\n", __func__);
591*fd501800SSascha Wildner error = ENOMEM;
592*fd501800SSascha Wildner goto out;
593*fd501800SSascha Wildner }
594*fd501800SSascha Wildner bcopy(config_page, page, MIN(cm->cm_length,
595*fd501800SSascha Wildner (sizeof(Mpi2DriverMappingPage0_t))));
596*fd501800SSascha Wildner cm->cm_data = page;
597*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
598*fd501800SSascha Wildner if (cm != NULL)
599*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
600*fd501800SSascha Wildner if (error || (reply == NULL)) {
601*fd501800SSascha Wildner /* FIXME */
602*fd501800SSascha Wildner /*
603*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
604*fd501800SSascha Wildner * reset
605*fd501800SSascha Wildner */
606*fd501800SSascha Wildner kprintf("%s: request to write page completed with error %d",
607*fd501800SSascha Wildner __func__, error);
608*fd501800SSascha Wildner error = ENXIO;
609*fd501800SSascha Wildner goto out;
610*fd501800SSascha Wildner }
611*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
612*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
613*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
614*fd501800SSascha Wildner /* FIXME */
615*fd501800SSascha Wildner /*
616*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
617*fd501800SSascha Wildner * reset
618*fd501800SSascha Wildner */
619*fd501800SSascha Wildner kprintf("%s: page written with error; iocstatus = 0x%x\n",
620*fd501800SSascha Wildner __func__, ioc_status);
621*fd501800SSascha Wildner error = ENXIO;
622*fd501800SSascha Wildner goto out;
623*fd501800SSascha Wildner }
624*fd501800SSascha Wildner out:
625*fd501800SSascha Wildner kfree(page, M_MPR);
626*fd501800SSascha Wildner if (cm)
627*fd501800SSascha Wildner mpr_free_command(sc, cm);
628*fd501800SSascha Wildner return (error);
629*fd501800SSascha Wildner }
630*fd501800SSascha Wildner
631*fd501800SSascha Wildner /**
632*fd501800SSascha Wildner * mpr_config_get_sas_device_pg0 - obtain sas device page 0
633*fd501800SSascha Wildner * @sc: per adapter object
634*fd501800SSascha Wildner * @mpi_reply: reply mf payload returned from firmware
635*fd501800SSascha Wildner * @config_page: contents of the config page
636*fd501800SSascha Wildner * @form: GET_NEXT_HANDLE or HANDLE
637*fd501800SSascha Wildner * @handle: device handle
638*fd501800SSascha Wildner * Context: sleep.
639*fd501800SSascha Wildner *
640*fd501800SSascha Wildner * Returns 0 for success, non-zero for failure.
641*fd501800SSascha Wildner */
642*fd501800SSascha Wildner int
mpr_config_get_sas_device_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2SasDevicePage0_t * config_page,u32 form,u16 handle)643*fd501800SSascha Wildner mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
644*fd501800SSascha Wildner *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
645*fd501800SSascha Wildner {
646*fd501800SSascha Wildner MPI2_CONFIG_REQUEST *request;
647*fd501800SSascha Wildner MPI2_CONFIG_REPLY *reply = NULL; /* XXX swildner: warning fix */
648*fd501800SSascha Wildner struct mpr_command *cm;
649*fd501800SSascha Wildner Mpi2SasDevicePage0_t *page = NULL;
650*fd501800SSascha Wildner int error = 0;
651*fd501800SSascha Wildner u16 ioc_status;
652*fd501800SSascha Wildner
653*fd501800SSascha Wildner mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
654*fd501800SSascha Wildner
655*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
656*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
657*fd501800SSascha Wildner __LINE__);
658*fd501800SSascha Wildner error = EBUSY;
659*fd501800SSascha Wildner goto out;
660*fd501800SSascha Wildner }
661*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
662*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
663*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
664*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
665*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
666*fd501800SSascha Wildner request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
667*fd501800SSascha Wildner request->Header.PageNumber = 0;
668*fd501800SSascha Wildner request->ExtPageLength = request->Header.PageVersion = 0;
669*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
670*fd501800SSascha Wildner cm->cm_data = NULL;
671*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
672*fd501800SSascha Wildner if (cm != NULL)
673*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
674*fd501800SSascha Wildner if (error || (reply == NULL)) {
675*fd501800SSascha Wildner /* FIXME */
676*fd501800SSascha Wildner /*
677*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
678*fd501800SSascha Wildner * reset
679*fd501800SSascha Wildner */
680*fd501800SSascha Wildner kprintf("%s: request for header completed with error %d",
681*fd501800SSascha Wildner __func__, error);
682*fd501800SSascha Wildner error = ENXIO;
683*fd501800SSascha Wildner goto out;
684*fd501800SSascha Wildner }
685*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
686*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
687*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
688*fd501800SSascha Wildner /* FIXME */
689*fd501800SSascha Wildner /*
690*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
691*fd501800SSascha Wildner * reset
692*fd501800SSascha Wildner */
693*fd501800SSascha Wildner kprintf("%s: header read with error; iocstatus = 0x%x\n",
694*fd501800SSascha Wildner __func__, ioc_status);
695*fd501800SSascha Wildner error = ENXIO;
696*fd501800SSascha Wildner goto out;
697*fd501800SSascha Wildner }
698*fd501800SSascha Wildner /* We have to do free and alloc for the reply-free and reply-post
699*fd501800SSascha Wildner * counters to match - Need to review the reply FIFO handling.
700*fd501800SSascha Wildner */
701*fd501800SSascha Wildner mpr_free_command(sc, cm);
702*fd501800SSascha Wildner
703*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
704*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
705*fd501800SSascha Wildner __LINE__);
706*fd501800SSascha Wildner error = EBUSY;
707*fd501800SSascha Wildner goto out;
708*fd501800SSascha Wildner }
709*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
710*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
711*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
712*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
713*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
714*fd501800SSascha Wildner request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
715*fd501800SSascha Wildner request->Header.PageNumber = 0;
716*fd501800SSascha Wildner request->Header.PageVersion = mpi_reply->Header.PageVersion;
717*fd501800SSascha Wildner request->ExtPageLength = mpi_reply->ExtPageLength;
718*fd501800SSascha Wildner request->PageAddress = htole32(form | handle);
719*fd501800SSascha Wildner cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
720*fd501800SSascha Wildner cm->cm_sge = &request->PageBufferSGE;
721*fd501800SSascha Wildner cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
722*fd501800SSascha Wildner cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
723*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
724*fd501800SSascha Wildner page = kmalloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
725*fd501800SSascha Wildner if (!page) {
726*fd501800SSascha Wildner kprintf("%s: page alloc failed\n", __func__);
727*fd501800SSascha Wildner error = ENOMEM;
728*fd501800SSascha Wildner goto out;
729*fd501800SSascha Wildner }
730*fd501800SSascha Wildner cm->cm_data = page;
731*fd501800SSascha Wildner
732*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
733*fd501800SSascha Wildner if (cm != NULL)
734*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
735*fd501800SSascha Wildner if (error || (reply == NULL)) {
736*fd501800SSascha Wildner /* FIXME */
737*fd501800SSascha Wildner /*
738*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
739*fd501800SSascha Wildner * reset
740*fd501800SSascha Wildner */
741*fd501800SSascha Wildner kprintf("%s: request for page completed with error %d",
742*fd501800SSascha Wildner __func__, error);
743*fd501800SSascha Wildner error = ENXIO;
744*fd501800SSascha Wildner goto out;
745*fd501800SSascha Wildner }
746*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
747*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
748*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
749*fd501800SSascha Wildner /* FIXME */
750*fd501800SSascha Wildner /*
751*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
752*fd501800SSascha Wildner * reset
753*fd501800SSascha Wildner */
754*fd501800SSascha Wildner kprintf("%s: page read with error; iocstatus = 0x%x\n",
755*fd501800SSascha Wildner __func__, ioc_status);
756*fd501800SSascha Wildner error = ENXIO;
757*fd501800SSascha Wildner goto out;
758*fd501800SSascha Wildner }
759*fd501800SSascha Wildner bcopy(page, config_page, MIN(cm->cm_length,
760*fd501800SSascha Wildner sizeof(Mpi2SasDevicePage0_t)));
761*fd501800SSascha Wildner out:
762*fd501800SSascha Wildner kfree(page, M_MPR);
763*fd501800SSascha Wildner if (cm)
764*fd501800SSascha Wildner mpr_free_command(sc, cm);
765*fd501800SSascha Wildner return (error);
766*fd501800SSascha Wildner }
767*fd501800SSascha Wildner
768*fd501800SSascha Wildner /**
769*fd501800SSascha Wildner * mpr_config_get_pcie_device_pg0 - obtain PCIe device page 0
770*fd501800SSascha Wildner * @sc: per adapter object
771*fd501800SSascha Wildner * @mpi_reply: reply mf payload returned from firmware
772*fd501800SSascha Wildner * @config_page: contents of the config page
773*fd501800SSascha Wildner * @form: GET_NEXT_HANDLE or HANDLE
774*fd501800SSascha Wildner * @handle: device handle
775*fd501800SSascha Wildner * Context: sleep.
776*fd501800SSascha Wildner *
777*fd501800SSascha Wildner * Returns 0 for success, non-zero for failure.
778*fd501800SSascha Wildner */
779*fd501800SSascha Wildner int
mpr_config_get_pcie_device_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi26PCIeDevicePage0_t * config_page,u32 form,u16 handle)780*fd501800SSascha Wildner mpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
781*fd501800SSascha Wildner *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, u32 form, u16 handle)
782*fd501800SSascha Wildner {
783*fd501800SSascha Wildner MPI2_CONFIG_REQUEST *request;
784*fd501800SSascha Wildner MPI2_CONFIG_REPLY *reply = NULL; /* XXX swildner: warning fix */
785*fd501800SSascha Wildner struct mpr_command *cm;
786*fd501800SSascha Wildner Mpi26PCIeDevicePage0_t *page = NULL;
787*fd501800SSascha Wildner int error = 0;
788*fd501800SSascha Wildner u16 ioc_status;
789*fd501800SSascha Wildner
790*fd501800SSascha Wildner mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
791*fd501800SSascha Wildner
792*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
793*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
794*fd501800SSascha Wildner __LINE__);
795*fd501800SSascha Wildner error = EBUSY;
796*fd501800SSascha Wildner goto out;
797*fd501800SSascha Wildner }
798*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
799*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
800*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
801*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
802*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
803*fd501800SSascha Wildner request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
804*fd501800SSascha Wildner request->Header.PageNumber = 0;
805*fd501800SSascha Wildner request->ExtPageLength = request->Header.PageVersion = 0;
806*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
807*fd501800SSascha Wildner cm->cm_data = NULL;
808*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
809*fd501800SSascha Wildner if (cm != NULL)
810*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
811*fd501800SSascha Wildner if (error || (reply == NULL)) {
812*fd501800SSascha Wildner /* FIXME */
813*fd501800SSascha Wildner /*
814*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
815*fd501800SSascha Wildner * reset
816*fd501800SSascha Wildner */
817*fd501800SSascha Wildner kprintf("%s: request for header completed with error %d",
818*fd501800SSascha Wildner __func__, error);
819*fd501800SSascha Wildner error = ENXIO;
820*fd501800SSascha Wildner goto out;
821*fd501800SSascha Wildner }
822*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
823*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
824*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
825*fd501800SSascha Wildner /* FIXME */
826*fd501800SSascha Wildner /*
827*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
828*fd501800SSascha Wildner * reset
829*fd501800SSascha Wildner */
830*fd501800SSascha Wildner kprintf("%s: header read with error; iocstatus = 0x%x\n",
831*fd501800SSascha Wildner __func__, ioc_status);
832*fd501800SSascha Wildner error = ENXIO;
833*fd501800SSascha Wildner goto out;
834*fd501800SSascha Wildner }
835*fd501800SSascha Wildner /* We have to do free and alloc for the reply-free and reply-post
836*fd501800SSascha Wildner * counters to match - Need to review the reply FIFO handling.
837*fd501800SSascha Wildner */
838*fd501800SSascha Wildner mpr_free_command(sc, cm);
839*fd501800SSascha Wildner
840*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
841*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
842*fd501800SSascha Wildner __LINE__);
843*fd501800SSascha Wildner error = EBUSY;
844*fd501800SSascha Wildner goto out;
845*fd501800SSascha Wildner }
846*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
847*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
848*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
849*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
850*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
851*fd501800SSascha Wildner request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
852*fd501800SSascha Wildner request->Header.PageNumber = 0;
853*fd501800SSascha Wildner request->Header.PageVersion = mpi_reply->Header.PageVersion;
854*fd501800SSascha Wildner request->ExtPageLength = mpi_reply->ExtPageLength;
855*fd501800SSascha Wildner request->PageAddress = htole32(form | handle);
856*fd501800SSascha Wildner cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
857*fd501800SSascha Wildner cm->cm_sge = &request->PageBufferSGE;
858*fd501800SSascha Wildner cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
859*fd501800SSascha Wildner cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
860*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
861*fd501800SSascha Wildner page = kmalloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
862*fd501800SSascha Wildner if (!page) {
863*fd501800SSascha Wildner kprintf("%s: page alloc failed\n", __func__);
864*fd501800SSascha Wildner error = ENOMEM;
865*fd501800SSascha Wildner goto out;
866*fd501800SSascha Wildner }
867*fd501800SSascha Wildner cm->cm_data = page;
868*fd501800SSascha Wildner
869*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
870*fd501800SSascha Wildner if (cm != NULL)
871*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
872*fd501800SSascha Wildner if (error || (reply == NULL)) {
873*fd501800SSascha Wildner /* FIXME */
874*fd501800SSascha Wildner /*
875*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
876*fd501800SSascha Wildner * reset
877*fd501800SSascha Wildner */
878*fd501800SSascha Wildner kprintf("%s: request for page completed with error %d",
879*fd501800SSascha Wildner __func__, error);
880*fd501800SSascha Wildner error = ENXIO;
881*fd501800SSascha Wildner goto out;
882*fd501800SSascha Wildner }
883*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
884*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
885*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
886*fd501800SSascha Wildner /* FIXME */
887*fd501800SSascha Wildner /*
888*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
889*fd501800SSascha Wildner * reset
890*fd501800SSascha Wildner */
891*fd501800SSascha Wildner kprintf("%s: page read with error; iocstatus = 0x%x\n",
892*fd501800SSascha Wildner __func__, ioc_status);
893*fd501800SSascha Wildner error = ENXIO;
894*fd501800SSascha Wildner goto out;
895*fd501800SSascha Wildner }
896*fd501800SSascha Wildner bcopy(page, config_page, MIN(cm->cm_length,
897*fd501800SSascha Wildner sizeof(Mpi26PCIeDevicePage0_t)));
898*fd501800SSascha Wildner out:
899*fd501800SSascha Wildner kfree(page, M_MPR);
900*fd501800SSascha Wildner if (cm)
901*fd501800SSascha Wildner mpr_free_command(sc, cm);
902*fd501800SSascha Wildner return (error);
903*fd501800SSascha Wildner }
904*fd501800SSascha Wildner
905*fd501800SSascha Wildner /**
906*fd501800SSascha Wildner * mpr_config_get_pcie_device_pg2 - obtain PCIe device page 2
907*fd501800SSascha Wildner * @sc: per adapter object
908*fd501800SSascha Wildner * @mpi_reply: reply mf payload returned from firmware
909*fd501800SSascha Wildner * @config_page: contents of the config page
910*fd501800SSascha Wildner * @form: GET_NEXT_HANDLE or HANDLE
911*fd501800SSascha Wildner * @handle: device handle
912*fd501800SSascha Wildner * Context: sleep.
913*fd501800SSascha Wildner *
914*fd501800SSascha Wildner * Returns 0 for success, non-zero for failure.
915*fd501800SSascha Wildner */
916*fd501800SSascha Wildner int
mpr_config_get_pcie_device_pg2(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi26PCIeDevicePage2_t * config_page,u32 form,u16 handle)917*fd501800SSascha Wildner mpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t
918*fd501800SSascha Wildner *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, u32 form, u16 handle)
919*fd501800SSascha Wildner {
920*fd501800SSascha Wildner MPI2_CONFIG_REQUEST *request;
921*fd501800SSascha Wildner MPI2_CONFIG_REPLY *reply = NULL; /* XXX swildner: warning fix */
922*fd501800SSascha Wildner struct mpr_command *cm;
923*fd501800SSascha Wildner Mpi26PCIeDevicePage2_t *page = NULL;
924*fd501800SSascha Wildner int error = 0;
925*fd501800SSascha Wildner u16 ioc_status;
926*fd501800SSascha Wildner
927*fd501800SSascha Wildner mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
928*fd501800SSascha Wildner
929*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
930*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
931*fd501800SSascha Wildner __LINE__);
932*fd501800SSascha Wildner error = EBUSY;
933*fd501800SSascha Wildner goto out;
934*fd501800SSascha Wildner }
935*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
936*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
937*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
938*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
939*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
940*fd501800SSascha Wildner request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
941*fd501800SSascha Wildner request->Header.PageNumber = 2;
942*fd501800SSascha Wildner request->ExtPageLength = request->Header.PageVersion = 0;
943*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
944*fd501800SSascha Wildner cm->cm_data = NULL;
945*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
946*fd501800SSascha Wildner if (cm != NULL)
947*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
948*fd501800SSascha Wildner if (error || (reply == NULL)) {
949*fd501800SSascha Wildner /* FIXME */
950*fd501800SSascha Wildner /*
951*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
952*fd501800SSascha Wildner * reset
953*fd501800SSascha Wildner */
954*fd501800SSascha Wildner kprintf("%s: request for header completed with error %d",
955*fd501800SSascha Wildner __func__, error);
956*fd501800SSascha Wildner error = ENXIO;
957*fd501800SSascha Wildner goto out;
958*fd501800SSascha Wildner }
959*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
960*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
961*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
962*fd501800SSascha Wildner /* FIXME */
963*fd501800SSascha Wildner /*
964*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
965*fd501800SSascha Wildner * reset
966*fd501800SSascha Wildner */
967*fd501800SSascha Wildner kprintf("%s: header read with error; iocstatus = 0x%x\n",
968*fd501800SSascha Wildner __func__, ioc_status);
969*fd501800SSascha Wildner error = ENXIO;
970*fd501800SSascha Wildner goto out;
971*fd501800SSascha Wildner }
972*fd501800SSascha Wildner /* We have to do free and alloc for the reply-free and reply-post
973*fd501800SSascha Wildner * counters to match - Need to review the reply FIFO handling.
974*fd501800SSascha Wildner */
975*fd501800SSascha Wildner mpr_free_command(sc, cm);
976*fd501800SSascha Wildner
977*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
978*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
979*fd501800SSascha Wildner __LINE__);
980*fd501800SSascha Wildner error = EBUSY;
981*fd501800SSascha Wildner goto out;
982*fd501800SSascha Wildner }
983*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
984*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
985*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
986*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
987*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
988*fd501800SSascha Wildner request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
989*fd501800SSascha Wildner request->Header.PageNumber = 2;
990*fd501800SSascha Wildner request->Header.PageVersion = mpi_reply->Header.PageVersion;
991*fd501800SSascha Wildner request->ExtPageLength = mpi_reply->ExtPageLength;
992*fd501800SSascha Wildner request->PageAddress = htole32(form | handle);
993*fd501800SSascha Wildner cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
994*fd501800SSascha Wildner cm->cm_sge = &request->PageBufferSGE;
995*fd501800SSascha Wildner cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
996*fd501800SSascha Wildner cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
997*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
998*fd501800SSascha Wildner page = kmalloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
999*fd501800SSascha Wildner if (!page) {
1000*fd501800SSascha Wildner kprintf("%s: page alloc failed\n", __func__);
1001*fd501800SSascha Wildner error = ENOMEM;
1002*fd501800SSascha Wildner goto out;
1003*fd501800SSascha Wildner }
1004*fd501800SSascha Wildner cm->cm_data = page;
1005*fd501800SSascha Wildner
1006*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1007*fd501800SSascha Wildner if (cm != NULL)
1008*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1009*fd501800SSascha Wildner if (error || (reply == NULL)) {
1010*fd501800SSascha Wildner /* FIXME */
1011*fd501800SSascha Wildner /*
1012*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
1013*fd501800SSascha Wildner * reset
1014*fd501800SSascha Wildner */
1015*fd501800SSascha Wildner kprintf("%s: request for page completed with error %d",
1016*fd501800SSascha Wildner __func__, error);
1017*fd501800SSascha Wildner error = ENXIO;
1018*fd501800SSascha Wildner goto out;
1019*fd501800SSascha Wildner }
1020*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1021*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1022*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1023*fd501800SSascha Wildner /* FIXME */
1024*fd501800SSascha Wildner /*
1025*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
1026*fd501800SSascha Wildner * reset
1027*fd501800SSascha Wildner */
1028*fd501800SSascha Wildner kprintf("%s: page read with error; iocstatus = 0x%x\n",
1029*fd501800SSascha Wildner __func__, ioc_status);
1030*fd501800SSascha Wildner error = ENXIO;
1031*fd501800SSascha Wildner goto out;
1032*fd501800SSascha Wildner }
1033*fd501800SSascha Wildner bcopy(page, config_page, MIN(cm->cm_length,
1034*fd501800SSascha Wildner sizeof(Mpi26PCIeDevicePage2_t)));
1035*fd501800SSascha Wildner out:
1036*fd501800SSascha Wildner kfree(page, M_MPR);
1037*fd501800SSascha Wildner if (cm)
1038*fd501800SSascha Wildner mpr_free_command(sc, cm);
1039*fd501800SSascha Wildner return (error);
1040*fd501800SSascha Wildner }
1041*fd501800SSascha Wildner
1042*fd501800SSascha Wildner /**
1043*fd501800SSascha Wildner * mpr_config_get_bios_pg3 - obtain BIOS page 3
1044*fd501800SSascha Wildner * @sc: per adapter object
1045*fd501800SSascha Wildner * @mpi_reply: reply mf payload returned from firmware
1046*fd501800SSascha Wildner * @config_page: contents of the config page
1047*fd501800SSascha Wildner * Context: sleep.
1048*fd501800SSascha Wildner *
1049*fd501800SSascha Wildner * Returns 0 for success, non-zero for failure.
1050*fd501800SSascha Wildner */
1051*fd501800SSascha Wildner int
mpr_config_get_bios_pg3(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2BiosPage3_t * config_page)1052*fd501800SSascha Wildner mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1053*fd501800SSascha Wildner Mpi2BiosPage3_t *config_page)
1054*fd501800SSascha Wildner {
1055*fd501800SSascha Wildner MPI2_CONFIG_REQUEST *request;
1056*fd501800SSascha Wildner MPI2_CONFIG_REPLY *reply = NULL; /* XXX swildner: warning fix */
1057*fd501800SSascha Wildner struct mpr_command *cm;
1058*fd501800SSascha Wildner Mpi2BiosPage3_t *page = NULL;
1059*fd501800SSascha Wildner int error = 0;
1060*fd501800SSascha Wildner u16 ioc_status;
1061*fd501800SSascha Wildner
1062*fd501800SSascha Wildner mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1063*fd501800SSascha Wildner
1064*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
1065*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
1066*fd501800SSascha Wildner __LINE__);
1067*fd501800SSascha Wildner error = EBUSY;
1068*fd501800SSascha Wildner goto out;
1069*fd501800SSascha Wildner }
1070*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1071*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1072*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
1073*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1074*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1075*fd501800SSascha Wildner request->Header.PageNumber = 3;
1076*fd501800SSascha Wildner request->Header.PageLength = request->Header.PageVersion = 0;
1077*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1078*fd501800SSascha Wildner cm->cm_data = NULL;
1079*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1080*fd501800SSascha Wildner if (cm != NULL)
1081*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1082*fd501800SSascha Wildner if (error || (reply == NULL)) {
1083*fd501800SSascha Wildner /* FIXME */
1084*fd501800SSascha Wildner /*
1085*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
1086*fd501800SSascha Wildner * reset
1087*fd501800SSascha Wildner */
1088*fd501800SSascha Wildner kprintf("%s: request for header completed with error %d",
1089*fd501800SSascha Wildner __func__, error);
1090*fd501800SSascha Wildner error = ENXIO;
1091*fd501800SSascha Wildner goto out;
1092*fd501800SSascha Wildner }
1093*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1094*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1095*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1096*fd501800SSascha Wildner /* FIXME */
1097*fd501800SSascha Wildner /*
1098*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
1099*fd501800SSascha Wildner * reset
1100*fd501800SSascha Wildner */
1101*fd501800SSascha Wildner kprintf("%s: header read with error; iocstatus = 0x%x\n",
1102*fd501800SSascha Wildner __func__, ioc_status);
1103*fd501800SSascha Wildner error = ENXIO;
1104*fd501800SSascha Wildner goto out;
1105*fd501800SSascha Wildner }
1106*fd501800SSascha Wildner /* We have to do free and alloc for the reply-free and reply-post
1107*fd501800SSascha Wildner * counters to match - Need to review the reply FIFO handling.
1108*fd501800SSascha Wildner */
1109*fd501800SSascha Wildner mpr_free_command(sc, cm);
1110*fd501800SSascha Wildner
1111*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
1112*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
1113*fd501800SSascha Wildner __LINE__);
1114*fd501800SSascha Wildner error = EBUSY;
1115*fd501800SSascha Wildner goto out;
1116*fd501800SSascha Wildner }
1117*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1118*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1119*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
1120*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1121*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1122*fd501800SSascha Wildner request->Header.PageNumber = 3;
1123*fd501800SSascha Wildner request->Header.PageVersion = mpi_reply->Header.PageVersion;
1124*fd501800SSascha Wildner request->Header.PageLength = mpi_reply->Header.PageLength;
1125*fd501800SSascha Wildner cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1126*fd501800SSascha Wildner cm->cm_sge = &request->PageBufferSGE;
1127*fd501800SSascha Wildner cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1128*fd501800SSascha Wildner cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1129*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1130*fd501800SSascha Wildner page = kmalloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1131*fd501800SSascha Wildner if (!page) {
1132*fd501800SSascha Wildner kprintf("%s: page alloc failed\n", __func__);
1133*fd501800SSascha Wildner error = ENOMEM;
1134*fd501800SSascha Wildner goto out;
1135*fd501800SSascha Wildner }
1136*fd501800SSascha Wildner cm->cm_data = page;
1137*fd501800SSascha Wildner
1138*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1139*fd501800SSascha Wildner if (cm != NULL)
1140*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1141*fd501800SSascha Wildner if (error || (reply == NULL)) {
1142*fd501800SSascha Wildner /* FIXME */
1143*fd501800SSascha Wildner /*
1144*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
1145*fd501800SSascha Wildner * reset
1146*fd501800SSascha Wildner */
1147*fd501800SSascha Wildner kprintf("%s: request for page completed with error %d",
1148*fd501800SSascha Wildner __func__, error);
1149*fd501800SSascha Wildner error = ENXIO;
1150*fd501800SSascha Wildner goto out;
1151*fd501800SSascha Wildner }
1152*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1153*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1154*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1155*fd501800SSascha Wildner /* FIXME */
1156*fd501800SSascha Wildner /*
1157*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
1158*fd501800SSascha Wildner * reset
1159*fd501800SSascha Wildner */
1160*fd501800SSascha Wildner kprintf("%s: page read with error; iocstatus = 0x%x\n",
1161*fd501800SSascha Wildner __func__, ioc_status);
1162*fd501800SSascha Wildner error = ENXIO;
1163*fd501800SSascha Wildner goto out;
1164*fd501800SSascha Wildner }
1165*fd501800SSascha Wildner bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1166*fd501800SSascha Wildner out:
1167*fd501800SSascha Wildner kfree(page, M_MPR);
1168*fd501800SSascha Wildner if (cm)
1169*fd501800SSascha Wildner mpr_free_command(sc, cm);
1170*fd501800SSascha Wildner return (error);
1171*fd501800SSascha Wildner }
1172*fd501800SSascha Wildner
1173*fd501800SSascha Wildner /**
1174*fd501800SSascha Wildner * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0
1175*fd501800SSascha Wildner * @sc: per adapter object
1176*fd501800SSascha Wildner * @mpi_reply: reply mf payload returned from firmware
1177*fd501800SSascha Wildner * @config_page: contents of the config page
1178*fd501800SSascha Wildner * @page_address: form and handle value used to get page
1179*fd501800SSascha Wildner * Context: sleep.
1180*fd501800SSascha Wildner *
1181*fd501800SSascha Wildner * Returns 0 for success, non-zero for failure.
1182*fd501800SSascha Wildner */
1183*fd501800SSascha Wildner int
mpr_config_get_raid_volume_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage0_t * config_page,u32 page_address)1184*fd501800SSascha Wildner mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
1185*fd501800SSascha Wildner *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1186*fd501800SSascha Wildner {
1187*fd501800SSascha Wildner MPI2_CONFIG_REQUEST *request;
1188*fd501800SSascha Wildner MPI2_CONFIG_REPLY *reply = NULL;
1189*fd501800SSascha Wildner struct mpr_command *cm;
1190*fd501800SSascha Wildner Mpi2RaidVolPage0_t *page = NULL;
1191*fd501800SSascha Wildner int error = 0;
1192*fd501800SSascha Wildner u16 ioc_status;
1193*fd501800SSascha Wildner
1194*fd501800SSascha Wildner mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1195*fd501800SSascha Wildner
1196*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
1197*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
1198*fd501800SSascha Wildner __LINE__);
1199*fd501800SSascha Wildner error = EBUSY;
1200*fd501800SSascha Wildner goto out;
1201*fd501800SSascha Wildner }
1202*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1203*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1204*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
1205*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1206*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1207*fd501800SSascha Wildner request->Header.PageNumber = 0;
1208*fd501800SSascha Wildner request->Header.PageLength = request->Header.PageVersion = 0;
1209*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1210*fd501800SSascha Wildner cm->cm_data = NULL;
1211*fd501800SSascha Wildner
1212*fd501800SSascha Wildner /*
1213*fd501800SSascha Wildner * This page must be polled because the IOC isn't ready yet when this
1214*fd501800SSascha Wildner * page is needed.
1215*fd501800SSascha Wildner */
1216*fd501800SSascha Wildner error = mpr_request_polled(sc, &cm);
1217*fd501800SSascha Wildner if (cm != NULL)
1218*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1219*fd501800SSascha Wildner if (error || (reply == NULL)) {
1220*fd501800SSascha Wildner /* FIXME */
1221*fd501800SSascha Wildner /* If the poll returns error then we need to do diag reset */
1222*fd501800SSascha Wildner kprintf("%s: poll for header completed with error %d",
1223*fd501800SSascha Wildner __func__, error);
1224*fd501800SSascha Wildner error = ENXIO;
1225*fd501800SSascha Wildner goto out;
1226*fd501800SSascha Wildner }
1227*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1228*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1229*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1230*fd501800SSascha Wildner /* FIXME */
1231*fd501800SSascha Wildner /* If the poll returns error then we need to do diag reset */
1232*fd501800SSascha Wildner kprintf("%s: header read with error; iocstatus = 0x%x\n",
1233*fd501800SSascha Wildner __func__, ioc_status);
1234*fd501800SSascha Wildner error = ENXIO;
1235*fd501800SSascha Wildner goto out;
1236*fd501800SSascha Wildner }
1237*fd501800SSascha Wildner /* We have to do free and alloc for the reply-free and reply-post
1238*fd501800SSascha Wildner * counters to match - Need to review the reply FIFO handling.
1239*fd501800SSascha Wildner */
1240*fd501800SSascha Wildner mpr_free_command(sc, cm);
1241*fd501800SSascha Wildner
1242*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
1243*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
1244*fd501800SSascha Wildner __LINE__);
1245*fd501800SSascha Wildner error = EBUSY;
1246*fd501800SSascha Wildner goto out;
1247*fd501800SSascha Wildner }
1248*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1249*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1250*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
1251*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1252*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1253*fd501800SSascha Wildner request->Header.PageNumber = 0;
1254*fd501800SSascha Wildner request->Header.PageLength = mpi_reply->Header.PageLength;
1255*fd501800SSascha Wildner request->Header.PageVersion = mpi_reply->Header.PageVersion;
1256*fd501800SSascha Wildner request->PageAddress = page_address;
1257*fd501800SSascha Wildner cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1258*fd501800SSascha Wildner cm->cm_sge = &request->PageBufferSGE;
1259*fd501800SSascha Wildner cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1260*fd501800SSascha Wildner cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1261*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1262*fd501800SSascha Wildner page = kmalloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1263*fd501800SSascha Wildner if (!page) {
1264*fd501800SSascha Wildner kprintf("%s: page alloc failed\n", __func__);
1265*fd501800SSascha Wildner error = ENOMEM;
1266*fd501800SSascha Wildner goto out;
1267*fd501800SSascha Wildner }
1268*fd501800SSascha Wildner cm->cm_data = page;
1269*fd501800SSascha Wildner
1270*fd501800SSascha Wildner /*
1271*fd501800SSascha Wildner * This page must be polled because the IOC isn't ready yet when this
1272*fd501800SSascha Wildner * page is needed.
1273*fd501800SSascha Wildner */
1274*fd501800SSascha Wildner error = mpr_request_polled(sc, &cm);
1275*fd501800SSascha Wildner if (cm != NULL)
1276*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1277*fd501800SSascha Wildner if (error || (reply == NULL)) {
1278*fd501800SSascha Wildner /* FIXME */
1279*fd501800SSascha Wildner /* If the poll returns error then we need to do diag reset */
1280*fd501800SSascha Wildner kprintf("%s: poll for page completed with error %d",
1281*fd501800SSascha Wildner __func__, error);
1282*fd501800SSascha Wildner error = ENXIO;
1283*fd501800SSascha Wildner goto out;
1284*fd501800SSascha Wildner }
1285*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1286*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1287*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1288*fd501800SSascha Wildner /* FIXME */
1289*fd501800SSascha Wildner /* If the poll returns error then we need to do diag reset */
1290*fd501800SSascha Wildner kprintf("%s: page read with error; iocstatus = 0x%x\n",
1291*fd501800SSascha Wildner __func__, ioc_status);
1292*fd501800SSascha Wildner error = ENXIO;
1293*fd501800SSascha Wildner goto out;
1294*fd501800SSascha Wildner }
1295*fd501800SSascha Wildner bcopy(page, config_page, cm->cm_length);
1296*fd501800SSascha Wildner out:
1297*fd501800SSascha Wildner kfree(page, M_MPR);
1298*fd501800SSascha Wildner if (cm)
1299*fd501800SSascha Wildner mpr_free_command(sc, cm);
1300*fd501800SSascha Wildner return (error);
1301*fd501800SSascha Wildner }
1302*fd501800SSascha Wildner
1303*fd501800SSascha Wildner /**
1304*fd501800SSascha Wildner * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1
1305*fd501800SSascha Wildner * @sc: per adapter object
1306*fd501800SSascha Wildner * @mpi_reply: reply mf payload returned from firmware
1307*fd501800SSascha Wildner * @config_page: contents of the config page
1308*fd501800SSascha Wildner * @form: GET_NEXT_HANDLE or HANDLE
1309*fd501800SSascha Wildner * @handle: volume handle
1310*fd501800SSascha Wildner * Context: sleep.
1311*fd501800SSascha Wildner *
1312*fd501800SSascha Wildner * Returns 0 for success, non-zero for failure.
1313*fd501800SSascha Wildner */
1314*fd501800SSascha Wildner int
mpr_config_get_raid_volume_pg1(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage1_t * config_page,u32 form,u16 handle)1315*fd501800SSascha Wildner mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t
1316*fd501800SSascha Wildner *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1317*fd501800SSascha Wildner {
1318*fd501800SSascha Wildner MPI2_CONFIG_REQUEST *request;
1319*fd501800SSascha Wildner MPI2_CONFIG_REPLY *reply = NULL; /* XXX swildner: warning fix */
1320*fd501800SSascha Wildner struct mpr_command *cm;
1321*fd501800SSascha Wildner Mpi2RaidVolPage1_t *page = NULL;
1322*fd501800SSascha Wildner int error = 0;
1323*fd501800SSascha Wildner u16 ioc_status;
1324*fd501800SSascha Wildner
1325*fd501800SSascha Wildner mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1326*fd501800SSascha Wildner
1327*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
1328*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
1329*fd501800SSascha Wildner __LINE__);
1330*fd501800SSascha Wildner error = EBUSY;
1331*fd501800SSascha Wildner goto out;
1332*fd501800SSascha Wildner }
1333*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1334*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1335*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
1336*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1337*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1338*fd501800SSascha Wildner request->Header.PageNumber = 1;
1339*fd501800SSascha Wildner request->Header.PageLength = request->Header.PageVersion = 0;
1340*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1341*fd501800SSascha Wildner cm->cm_data = NULL;
1342*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1343*fd501800SSascha Wildner if (cm != NULL)
1344*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1345*fd501800SSascha Wildner if (error || (reply == NULL)) {
1346*fd501800SSascha Wildner /* FIXME */
1347*fd501800SSascha Wildner /*
1348*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
1349*fd501800SSascha Wildner * reset
1350*fd501800SSascha Wildner */
1351*fd501800SSascha Wildner kprintf("%s: request for header completed with error %d",
1352*fd501800SSascha Wildner __func__, error);
1353*fd501800SSascha Wildner error = ENXIO;
1354*fd501800SSascha Wildner goto out;
1355*fd501800SSascha Wildner }
1356*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1357*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1358*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1359*fd501800SSascha Wildner /* FIXME */
1360*fd501800SSascha Wildner /*
1361*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
1362*fd501800SSascha Wildner * reset
1363*fd501800SSascha Wildner */
1364*fd501800SSascha Wildner kprintf("%s: header read with error; iocstatus = 0x%x\n",
1365*fd501800SSascha Wildner __func__, ioc_status);
1366*fd501800SSascha Wildner error = ENXIO;
1367*fd501800SSascha Wildner goto out;
1368*fd501800SSascha Wildner }
1369*fd501800SSascha Wildner /* We have to do free and alloc for the reply-free and reply-post
1370*fd501800SSascha Wildner * counters to match - Need to review the reply FIFO handling.
1371*fd501800SSascha Wildner */
1372*fd501800SSascha Wildner mpr_free_command(sc, cm);
1373*fd501800SSascha Wildner
1374*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
1375*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
1376*fd501800SSascha Wildner __LINE__);
1377*fd501800SSascha Wildner error = EBUSY;
1378*fd501800SSascha Wildner goto out;
1379*fd501800SSascha Wildner }
1380*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1381*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1382*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
1383*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1384*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1385*fd501800SSascha Wildner request->Header.PageNumber = 1;
1386*fd501800SSascha Wildner request->Header.PageLength = mpi_reply->Header.PageLength;
1387*fd501800SSascha Wildner request->Header.PageVersion = mpi_reply->Header.PageVersion;
1388*fd501800SSascha Wildner request->PageAddress = htole32(form | handle);
1389*fd501800SSascha Wildner cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1390*fd501800SSascha Wildner cm->cm_sge = &request->PageBufferSGE;
1391*fd501800SSascha Wildner cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1392*fd501800SSascha Wildner cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1393*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1394*fd501800SSascha Wildner page = kmalloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1395*fd501800SSascha Wildner if (!page) {
1396*fd501800SSascha Wildner kprintf("%s: page alloc failed\n", __func__);
1397*fd501800SSascha Wildner error = ENOMEM;
1398*fd501800SSascha Wildner goto out;
1399*fd501800SSascha Wildner }
1400*fd501800SSascha Wildner cm->cm_data = page;
1401*fd501800SSascha Wildner
1402*fd501800SSascha Wildner error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1403*fd501800SSascha Wildner if (cm != NULL)
1404*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1405*fd501800SSascha Wildner if (error || (reply == NULL)) {
1406*fd501800SSascha Wildner /* FIXME */
1407*fd501800SSascha Wildner /*
1408*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
1409*fd501800SSascha Wildner * reset
1410*fd501800SSascha Wildner */
1411*fd501800SSascha Wildner kprintf("%s: request for page completed with error %d",
1412*fd501800SSascha Wildner __func__, error);
1413*fd501800SSascha Wildner error = ENXIO;
1414*fd501800SSascha Wildner goto out;
1415*fd501800SSascha Wildner }
1416*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1417*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1418*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1419*fd501800SSascha Wildner /* FIXME */
1420*fd501800SSascha Wildner /*
1421*fd501800SSascha Wildner * If the request returns an error then we need to do a diag
1422*fd501800SSascha Wildner * reset
1423*fd501800SSascha Wildner */
1424*fd501800SSascha Wildner kprintf("%s: page read with error; iocstatus = 0x%x\n",
1425*fd501800SSascha Wildner __func__, ioc_status);
1426*fd501800SSascha Wildner error = ENXIO;
1427*fd501800SSascha Wildner goto out;
1428*fd501800SSascha Wildner }
1429*fd501800SSascha Wildner bcopy(page, config_page, MIN(cm->cm_length,
1430*fd501800SSascha Wildner sizeof(Mpi2RaidVolPage1_t)));
1431*fd501800SSascha Wildner out:
1432*fd501800SSascha Wildner kfree(page, M_MPR);
1433*fd501800SSascha Wildner if (cm)
1434*fd501800SSascha Wildner mpr_free_command(sc, cm);
1435*fd501800SSascha Wildner return (error);
1436*fd501800SSascha Wildner }
1437*fd501800SSascha Wildner
1438*fd501800SSascha Wildner /**
1439*fd501800SSascha Wildner * mpr_config_get_volume_wwid - returns wwid given the volume handle
1440*fd501800SSascha Wildner * @sc: per adapter object
1441*fd501800SSascha Wildner * @volume_handle: volume handle
1442*fd501800SSascha Wildner * @wwid: volume wwid
1443*fd501800SSascha Wildner * Context: sleep.
1444*fd501800SSascha Wildner *
1445*fd501800SSascha Wildner * Returns 0 for success, non-zero for failure.
1446*fd501800SSascha Wildner */
1447*fd501800SSascha Wildner int
mpr_config_get_volume_wwid(struct mpr_softc * sc,u16 volume_handle,u64 * wwid)1448*fd501800SSascha Wildner mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid)
1449*fd501800SSascha Wildner {
1450*fd501800SSascha Wildner Mpi2ConfigReply_t mpi_reply;
1451*fd501800SSascha Wildner Mpi2RaidVolPage1_t raid_vol_pg1;
1452*fd501800SSascha Wildner
1453*fd501800SSascha Wildner *wwid = 0;
1454*fd501800SSascha Wildner if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1455*fd501800SSascha Wildner MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1456*fd501800SSascha Wildner *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1457*fd501800SSascha Wildner raid_vol_pg1.WWID.Low);
1458*fd501800SSascha Wildner return 0;
1459*fd501800SSascha Wildner } else
1460*fd501800SSascha Wildner return -1;
1461*fd501800SSascha Wildner }
1462*fd501800SSascha Wildner
1463*fd501800SSascha Wildner /**
1464*fd501800SSascha Wildner * mpr_config_get_pd_pg0 - obtain raid phys disk page 0
1465*fd501800SSascha Wildner * @sc: per adapter object
1466*fd501800SSascha Wildner * @mpi_reply: reply mf payload returned from firmware
1467*fd501800SSascha Wildner * @config_page: contents of the config page
1468*fd501800SSascha Wildner * @page_address: form and handle value used to get page
1469*fd501800SSascha Wildner * Context: sleep.
1470*fd501800SSascha Wildner *
1471*fd501800SSascha Wildner * Returns 0 for success, non-zero for failure.
1472*fd501800SSascha Wildner */
1473*fd501800SSascha Wildner int
mpr_config_get_raid_pd_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidPhysDiskPage0_t * config_page,u32 page_address)1474*fd501800SSascha Wildner mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1475*fd501800SSascha Wildner Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1476*fd501800SSascha Wildner {
1477*fd501800SSascha Wildner MPI2_CONFIG_REQUEST *request;
1478*fd501800SSascha Wildner MPI2_CONFIG_REPLY *reply = NULL;
1479*fd501800SSascha Wildner struct mpr_command *cm;
1480*fd501800SSascha Wildner Mpi2RaidPhysDiskPage0_t *page = NULL;
1481*fd501800SSascha Wildner int error = 0;
1482*fd501800SSascha Wildner u16 ioc_status;
1483*fd501800SSascha Wildner
1484*fd501800SSascha Wildner mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1485*fd501800SSascha Wildner
1486*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
1487*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
1488*fd501800SSascha Wildner __LINE__);
1489*fd501800SSascha Wildner error = EBUSY;
1490*fd501800SSascha Wildner goto out;
1491*fd501800SSascha Wildner }
1492*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1493*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1494*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
1495*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1496*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1497*fd501800SSascha Wildner request->Header.PageNumber = 0;
1498*fd501800SSascha Wildner request->Header.PageLength = request->Header.PageVersion = 0;
1499*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1500*fd501800SSascha Wildner cm->cm_data = NULL;
1501*fd501800SSascha Wildner
1502*fd501800SSascha Wildner /*
1503*fd501800SSascha Wildner * This page must be polled because the IOC isn't ready yet when this
1504*fd501800SSascha Wildner * page is needed.
1505*fd501800SSascha Wildner */
1506*fd501800SSascha Wildner error = mpr_request_polled(sc, &cm);
1507*fd501800SSascha Wildner if (cm != NULL)
1508*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1509*fd501800SSascha Wildner if (error || (reply == NULL)) {
1510*fd501800SSascha Wildner /* FIXME */
1511*fd501800SSascha Wildner /* If the poll returns error then we need to do diag reset */
1512*fd501800SSascha Wildner kprintf("%s: poll for header completed with error %d",
1513*fd501800SSascha Wildner __func__, error);
1514*fd501800SSascha Wildner error = ENXIO;
1515*fd501800SSascha Wildner goto out;
1516*fd501800SSascha Wildner }
1517*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1518*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1519*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1520*fd501800SSascha Wildner /* FIXME */
1521*fd501800SSascha Wildner /* If the poll returns error then we need to do diag reset */
1522*fd501800SSascha Wildner kprintf("%s: header read with error; iocstatus = 0x%x\n",
1523*fd501800SSascha Wildner __func__, ioc_status);
1524*fd501800SSascha Wildner error = ENXIO;
1525*fd501800SSascha Wildner goto out;
1526*fd501800SSascha Wildner }
1527*fd501800SSascha Wildner /* We have to do free and alloc for the reply-free and reply-post
1528*fd501800SSascha Wildner * counters to match - Need to review the reply FIFO handling.
1529*fd501800SSascha Wildner */
1530*fd501800SSascha Wildner mpr_free_command(sc, cm);
1531*fd501800SSascha Wildner
1532*fd501800SSascha Wildner if ((cm = mpr_alloc_command(sc)) == NULL) {
1533*fd501800SSascha Wildner kprintf("%s: command alloc failed @ line %d\n", __func__,
1534*fd501800SSascha Wildner __LINE__);
1535*fd501800SSascha Wildner error = EBUSY;
1536*fd501800SSascha Wildner goto out;
1537*fd501800SSascha Wildner }
1538*fd501800SSascha Wildner request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1539*fd501800SSascha Wildner bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1540*fd501800SSascha Wildner request->Function = MPI2_FUNCTION_CONFIG;
1541*fd501800SSascha Wildner request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1542*fd501800SSascha Wildner request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1543*fd501800SSascha Wildner request->Header.PageNumber = 0;
1544*fd501800SSascha Wildner request->Header.PageLength = mpi_reply->Header.PageLength;
1545*fd501800SSascha Wildner request->Header.PageVersion = mpi_reply->Header.PageVersion;
1546*fd501800SSascha Wildner request->PageAddress = page_address;
1547*fd501800SSascha Wildner cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1548*fd501800SSascha Wildner cm->cm_sge = &request->PageBufferSGE;
1549*fd501800SSascha Wildner cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1550*fd501800SSascha Wildner cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1551*fd501800SSascha Wildner cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1552*fd501800SSascha Wildner page = kmalloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1553*fd501800SSascha Wildner if (!page) {
1554*fd501800SSascha Wildner kprintf("%s: page alloc failed\n", __func__);
1555*fd501800SSascha Wildner error = ENOMEM;
1556*fd501800SSascha Wildner goto out;
1557*fd501800SSascha Wildner }
1558*fd501800SSascha Wildner cm->cm_data = page;
1559*fd501800SSascha Wildner
1560*fd501800SSascha Wildner /*
1561*fd501800SSascha Wildner * This page must be polled because the IOC isn't ready yet when this
1562*fd501800SSascha Wildner * page is needed.
1563*fd501800SSascha Wildner */
1564*fd501800SSascha Wildner error = mpr_request_polled(sc, &cm);
1565*fd501800SSascha Wildner if (cm != NULL)
1566*fd501800SSascha Wildner reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1567*fd501800SSascha Wildner if (error || (reply == NULL)) {
1568*fd501800SSascha Wildner /* FIXME */
1569*fd501800SSascha Wildner /* If the poll returns error then we need to do diag reset */
1570*fd501800SSascha Wildner kprintf("%s: poll for page completed with error %d",
1571*fd501800SSascha Wildner __func__, error);
1572*fd501800SSascha Wildner error = ENXIO;
1573*fd501800SSascha Wildner goto out;
1574*fd501800SSascha Wildner }
1575*fd501800SSascha Wildner ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1576*fd501800SSascha Wildner bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1577*fd501800SSascha Wildner if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1578*fd501800SSascha Wildner /* FIXME */
1579*fd501800SSascha Wildner /* If the poll returns error then we need to do diag reset */
1580*fd501800SSascha Wildner kprintf("%s: page read with error; iocstatus = 0x%x\n",
1581*fd501800SSascha Wildner __func__, ioc_status);
1582*fd501800SSascha Wildner error = ENXIO;
1583*fd501800SSascha Wildner goto out;
1584*fd501800SSascha Wildner }
1585*fd501800SSascha Wildner bcopy(page, config_page, MIN(cm->cm_length,
1586*fd501800SSascha Wildner sizeof(Mpi2RaidPhysDiskPage0_t)));
1587*fd501800SSascha Wildner out:
1588*fd501800SSascha Wildner kfree(page, M_MPR);
1589*fd501800SSascha Wildner if (cm)
1590*fd501800SSascha Wildner mpr_free_command(sc, cm);
1591*fd501800SSascha Wildner return (error);
1592*fd501800SSascha Wildner }
1593