xref: /dragonfly/sys/dev/raid/mpr/mpr_user.c (revision 030b0c8c4cf27c560ccec70410c8e21934ae677d)
1 /*-
2  * Copyright (c) 2008 Yahoo!, Inc.
3  * All rights reserved.
4  * Written by: John Baldwin <jhb@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the author nor the names of any co-contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface
31  */
32 /*-
33  * Copyright (c) 2011-2015 LSI Corp.
34  * Copyright (c) 2013-2016 Avago Technologies
35  * All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  *
46  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
47  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
50  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56  * SUCH DAMAGE.
57  *
58  * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
59  *
60  * $FreeBSD: head/sys/dev/mpr/mpr_user.c 332122 2018-04-06 17:35:35Z brooks $
61  */
62 
63 /* TODO Move headers to mprvar */
64 #include <sys/types.h>
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/kernel.h>
68 #include <sys/module.h>
69 #include <sys/bus.h>
70 #include <sys/conf.h>
71 #include <sys/bio.h>
72 #include <sys/malloc.h>
73 #include <sys/uio.h>
74 #include <sys/sysctl.h>
75 #include <sys/ioccom.h>
76 #include <sys/endian.h>
77 #include <sys/queue.h>
78 #include <sys/kthread.h>
79 #include <sys/taskqueue.h>
80 #include <sys/proc.h>
81 #include <sys/sysent.h>
82 #include <sys/device.h>
83 #include <sys/eventhandler.h>
84 
85 #include <sys/rman.h>
86 
87 #include <bus/cam/cam.h>
88 #include <bus/cam/cam_ccb.h>
89 
90 #include <dev/raid/mpr/mpi/mpi2_type.h>
91 #include <dev/raid/mpr/mpi/mpi2.h>
92 #include <dev/raid/mpr/mpi/mpi2_ioc.h>
93 #include <dev/raid/mpr/mpi/mpi2_cnfg.h>
94 #include <dev/raid/mpr/mpi/mpi2_init.h>
95 #include <dev/raid/mpr/mpi/mpi2_tool.h>
96 #include <dev/raid/mpr/mpi/mpi2_pci.h>
97 #include <dev/raid/mpr/mpr_ioctl.h>
98 #include <dev/raid/mpr/mprvar.h>
99 #include <dev/raid/mpr/mpr_table.h>
100 #include <dev/raid/mpr/mpr_sas.h>
101 #include <bus/pci/pcivar.h>
102 #include <bus/pci/pcireg.h>
103 
104 static d_open_t               mpr_open;
105 static d_close_t    mpr_close;
106 static d_ioctl_t    mpr_ioctl_devsw;
107 
108 static struct dev_ops mpr_ops = {
109           { "mpr", 0, D_MPSAFE },
110           .d_open = mpr_open,
111           .d_close =          mpr_close,
112           .d_ioctl =          mpr_ioctl_devsw,
113 };
114 
115 typedef int (mpr_user_f)(struct mpr_command *, struct mpr_usr_command *);
116 static mpr_user_f   mpi_pre_ioc_facts;
117 static mpr_user_f   mpi_pre_port_facts;
118 static mpr_user_f   mpi_pre_fw_download;
119 static mpr_user_f   mpi_pre_fw_upload;
120 static mpr_user_f   mpi_pre_sata_passthrough;
121 static mpr_user_f   mpi_pre_smp_passthrough;
122 static mpr_user_f   mpi_pre_config;
123 static mpr_user_f   mpi_pre_sas_io_unit_control;
124 
125 static int mpr_user_read_cfg_header(struct mpr_softc *,
126     struct mpr_cfg_page_req *);
127 static int mpr_user_read_cfg_page(struct mpr_softc *,
128     struct mpr_cfg_page_req *, void *);
129 static int mpr_user_read_extcfg_header(struct mpr_softc *,
130     struct mpr_ext_cfg_page_req *);
131 static int mpr_user_read_extcfg_page(struct mpr_softc *,
132     struct mpr_ext_cfg_page_req *, void *);
133 static int mpr_user_write_cfg_page(struct mpr_softc *,
134     struct mpr_cfg_page_req *, void *);
135 static int mpr_user_setup_request(struct mpr_command *,
136     struct mpr_usr_command *);
137 static int mpr_user_command(struct mpr_softc *, struct mpr_usr_command *);
138 
139 static int mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data);
140 static void mpr_user_get_adapter_data(struct mpr_softc *sc,
141     mpr_adapter_data_t *data);
142 static void mpr_user_read_pci_info(struct mpr_softc *sc, mpr_pci_info_t *data);
143 static uint8_t mpr_get_fw_diag_buffer_number(struct mpr_softc *sc,
144     uint32_t unique_id);
145 static int mpr_post_fw_diag_buffer(struct mpr_softc *sc,
146     mpr_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code);
147 static int mpr_release_fw_diag_buffer(struct mpr_softc *sc,
148     mpr_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
149     uint32_t diag_type);
150 static int mpr_diag_register(struct mpr_softc *sc,
151     mpr_fw_diag_register_t *diag_register, uint32_t *return_code);
152 static int mpr_diag_unregister(struct mpr_softc *sc,
153     mpr_fw_diag_unregister_t *diag_unregister, uint32_t *return_code);
154 static int mpr_diag_query(struct mpr_softc *sc, mpr_fw_diag_query_t *diag_query,
155     uint32_t *return_code);
156 static int mpr_diag_read_buffer(struct mpr_softc *sc,
157     mpr_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
158     uint32_t *return_code);
159 static int mpr_diag_release(struct mpr_softc *sc,
160     mpr_fw_diag_release_t *diag_release, uint32_t *return_code);
161 static int mpr_do_diag_action(struct mpr_softc *sc, uint32_t action,
162     uint8_t *diag_action, uint32_t length, uint32_t *return_code);
163 static int mpr_user_diag_action(struct mpr_softc *sc, mpr_diag_action_t *data);
164 static void mpr_user_event_query(struct mpr_softc *sc, mpr_event_query_t *data);
165 static void mpr_user_event_enable(struct mpr_softc *sc,
166     mpr_event_enable_t *data);
167 static int mpr_user_event_report(struct mpr_softc *sc,
168     mpr_event_report_t *data);
169 static int mpr_user_reg_access(struct mpr_softc *sc, mpr_reg_access_t *data);
170 static int mpr_user_btdh(struct mpr_softc *sc, mpr_btdh_mapping_t *data);
171 
172 static MALLOC_DEFINE(M_MPRUSER, "mpr_user", "Buffers for mpr(4) ioctls");
173 
174 /* Macros from compat/freebsd32/freebsd32.h */
175 #define   PTRIN(v)  (void *)(uintptr_t)(v)
176 #define   PTROUT(v) (uint32_t)(uintptr_t)(v)
177 
178 #define   CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0)
179 #define   PTRIN_CP(src,dst,fld)                                       \
180           do { (dst).fld = PTRIN((src).fld); } while (0)
181 #define   PTROUT_CP(src,dst,fld) \
182           do { (dst).fld = PTROUT((src).fld); } while (0)
183 
184 /*
185  * MPI functions that support IEEE SGLs for SAS3.
186  */
187 static uint8_t ieee_sgl_func_list[] = {
188           MPI2_FUNCTION_SCSI_IO_REQUEST,
189           MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH,
190           MPI2_FUNCTION_SMP_PASSTHROUGH,
191           MPI2_FUNCTION_SATA_PASSTHROUGH,
192           MPI2_FUNCTION_FW_UPLOAD,
193           MPI2_FUNCTION_FW_DOWNLOAD,
194           MPI2_FUNCTION_TARGET_ASSIST,
195           MPI2_FUNCTION_TARGET_STATUS_SEND,
196           MPI2_FUNCTION_TOOLBOX
197 };
198 
199 int
mpr_attach_user(struct mpr_softc * sc)200 mpr_attach_user(struct mpr_softc *sc)
201 {
202           int unit;
203 
204           unit = device_get_unit(sc->mpr_dev);
205           sc->mpr_cdev = make_dev(&mpr_ops, unit, UID_ROOT, GID_OPERATOR, 0640,
206               "mpr%d", unit);
207 
208           if (sc->mpr_cdev == NULL)
209                     return (ENOMEM);
210 
211           sc->mpr_cdev->si_drv1 = sc;
212           return (0);
213 }
214 
215 void
mpr_detach_user(struct mpr_softc * sc)216 mpr_detach_user(struct mpr_softc *sc)
217 {
218 
219           /* XXX: do a purge of pending requests? */
220           if (sc->mpr_cdev != NULL)
221                     destroy_dev(sc->mpr_cdev);
222 }
223 
224 static int
mpr_open(struct dev_open_args * ap)225 mpr_open(struct dev_open_args *ap)
226 {
227 
228           return (0);
229 }
230 
231 static int
mpr_close(struct dev_close_args * ap)232 mpr_close(struct dev_close_args *ap)
233 {
234 
235           return (0);
236 }
237 
238 static int
mpr_user_read_cfg_header(struct mpr_softc * sc,struct mpr_cfg_page_req * page_req)239 mpr_user_read_cfg_header(struct mpr_softc *sc,
240     struct mpr_cfg_page_req *page_req)
241 {
242           MPI2_CONFIG_PAGE_HEADER *hdr;
243           struct mpr_config_params params;
244           int           error;
245 
246           hdr = &params.hdr.Struct;
247           params.action = MPI2_CONFIG_ACTION_PAGE_HEADER;
248           params.page_address = le32toh(page_req->page_address);
249           hdr->PageVersion = 0;
250           hdr->PageLength = 0;
251           hdr->PageNumber = page_req->header.PageNumber;
252           hdr->PageType = page_req->header.PageType;
253           params.buffer = NULL;
254           params.length = 0;
255           params.callback = NULL;
256 
257           if ((error = mpr_read_config_page(sc, &params)) != 0) {
258                     /*
259                      * Leave the request. Without resetting the chip, it's
260                      * still owned by it and we'll just get into trouble
261                      * freeing it now. Mark it as abandoned so that if it
262                      * shows up later it can be freed.
263                      */
264                     mpr_printf(sc, "read_cfg_header timed out\n");
265                     return (ETIMEDOUT);
266           }
267 
268           page_req->ioc_status = htole16(params.status);
269           if ((page_req->ioc_status & MPI2_IOCSTATUS_MASK) ==
270               MPI2_IOCSTATUS_SUCCESS) {
271                     bcopy(hdr, &page_req->header, sizeof(page_req->header));
272           }
273 
274           return (0);
275 }
276 
277 static int
mpr_user_read_cfg_page(struct mpr_softc * sc,struct mpr_cfg_page_req * page_req,void * buf)278 mpr_user_read_cfg_page(struct mpr_softc *sc, struct mpr_cfg_page_req *page_req,
279     void *buf)
280 {
281           MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr;
282           struct mpr_config_params params;
283           int             error;
284 
285           reqhdr = buf;
286           hdr = &params.hdr.Struct;
287           hdr->PageVersion = reqhdr->PageVersion;
288           hdr->PageLength = reqhdr->PageLength;
289           hdr->PageNumber = reqhdr->PageNumber;
290           hdr->PageType = reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK;
291           params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
292           params.page_address = le32toh(page_req->page_address);
293           params.buffer = buf;
294           params.length = le32toh(page_req->len);
295           params.callback = NULL;
296 
297           if ((error = mpr_read_config_page(sc, &params)) != 0) {
298                     mpr_printf(sc, "mpr_user_read_cfg_page timed out\n");
299                     return (ETIMEDOUT);
300           }
301 
302           page_req->ioc_status = htole16(params.status);
303           return (0);
304 }
305 
306 static int
mpr_user_read_extcfg_header(struct mpr_softc * sc,struct mpr_ext_cfg_page_req * ext_page_req)307 mpr_user_read_extcfg_header(struct mpr_softc *sc,
308     struct mpr_ext_cfg_page_req *ext_page_req)
309 {
310           MPI2_CONFIG_EXTENDED_PAGE_HEADER *hdr;
311           struct mpr_config_params params;
312           int           error;
313 
314           hdr = &params.hdr.Ext;
315           params.action = MPI2_CONFIG_ACTION_PAGE_HEADER;
316           hdr->PageVersion = ext_page_req->header.PageVersion;
317           hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
318           hdr->ExtPageLength = 0;
319           hdr->PageNumber = ext_page_req->header.PageNumber;
320           hdr->ExtPageType = ext_page_req->header.ExtPageType;
321           params.page_address = le32toh(ext_page_req->page_address);
322           params.buffer = NULL;
323           params.length = 0;
324           params.callback = NULL;
325 
326           if ((error = mpr_read_config_page(sc, &params)) != 0) {
327                     /*
328                      * Leave the request. Without resetting the chip, it's
329                      * still owned by it and we'll just get into trouble
330                      * freeing it now. Mark it as abandoned so that if it
331                      * shows up later it can be freed.
332                      */
333                     mpr_printf(sc, "mpr_user_read_extcfg_header timed out\n");
334                     return (ETIMEDOUT);
335           }
336 
337           ext_page_req->ioc_status = htole16(params.status);
338           if ((ext_page_req->ioc_status & MPI2_IOCSTATUS_MASK) ==
339               MPI2_IOCSTATUS_SUCCESS) {
340                     ext_page_req->header.PageVersion = hdr->PageVersion;
341                     ext_page_req->header.PageNumber = hdr->PageNumber;
342                     ext_page_req->header.PageType = hdr->PageType;
343                     ext_page_req->header.ExtPageLength = hdr->ExtPageLength;
344                     ext_page_req->header.ExtPageType = hdr->ExtPageType;
345           }
346 
347           return (0);
348 }
349 
350 static int
mpr_user_read_extcfg_page(struct mpr_softc * sc,struct mpr_ext_cfg_page_req * ext_page_req,void * buf)351 mpr_user_read_extcfg_page(struct mpr_softc *sc,
352     struct mpr_ext_cfg_page_req *ext_page_req, void *buf)
353 {
354           MPI2_CONFIG_EXTENDED_PAGE_HEADER *reqhdr, *hdr;
355           struct mpr_config_params params;
356           int error;
357 
358           reqhdr = buf;
359           hdr = &params.hdr.Ext;
360           params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
361           params.page_address = le32toh(ext_page_req->page_address);
362           hdr->PageVersion = reqhdr->PageVersion;
363           hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
364           hdr->PageNumber = reqhdr->PageNumber;
365           hdr->ExtPageType = reqhdr->ExtPageType;
366           hdr->ExtPageLength = reqhdr->ExtPageLength;
367           params.buffer = buf;
368           params.length = le32toh(ext_page_req->len);
369           params.callback = NULL;
370 
371           if ((error = mpr_read_config_page(sc, &params)) != 0) {
372                     mpr_printf(sc, "mpr_user_read_extcfg_page timed out\n");
373                     return (ETIMEDOUT);
374           }
375 
376           ext_page_req->ioc_status = htole16(params.status);
377           return (0);
378 }
379 
380 static int
mpr_user_write_cfg_page(struct mpr_softc * sc,struct mpr_cfg_page_req * page_req,void * buf)381 mpr_user_write_cfg_page(struct mpr_softc *sc,
382     struct mpr_cfg_page_req *page_req, void *buf)
383 {
384           MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr;
385           struct mpr_config_params params;
386           u_int           hdr_attr;
387           int             error;
388 
389           reqhdr = buf;
390           hdr = &params.hdr.Struct;
391           hdr_attr = reqhdr->PageType & MPI2_CONFIG_PAGEATTR_MASK;
392           if (hdr_attr != MPI2_CONFIG_PAGEATTR_CHANGEABLE &&
393               hdr_attr != MPI2_CONFIG_PAGEATTR_PERSISTENT) {
394                     mpr_printf(sc, "page type 0x%x not changeable\n",
395                               reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK);
396                     return (EINVAL);
397           }
398 
399           /*
400            * There isn't any point in restoring stripped out attributes
401            * if you then mask them going down to issue the request.
402            */
403 
404           hdr->PageVersion = reqhdr->PageVersion;
405           hdr->PageLength = reqhdr->PageLength;
406           hdr->PageNumber = reqhdr->PageNumber;
407           hdr->PageType = reqhdr->PageType;
408           params.action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
409           params.page_address = le32toh(page_req->page_address);
410           params.buffer = buf;
411           params.length = le32toh(page_req->len);
412           params.callback = NULL;
413 
414           if ((error = mpr_write_config_page(sc, &params)) != 0) {
415                     mpr_printf(sc, "mpr_write_cfg_page timed out\n");
416                     return (ETIMEDOUT);
417           }
418 
419           page_req->ioc_status = htole16(params.status);
420           return (0);
421 }
422 
423 void
mpr_init_sge(struct mpr_command * cm,void * req,void * sge)424 mpr_init_sge(struct mpr_command *cm, void *req, void *sge)
425 {
426           int off, space;
427 
428           space = (int)cm->cm_sc->reqframesz;
429           off = (uintptr_t)sge - (uintptr_t)req;
430 
431           KASSERT(off < space, ("bad pointers %p %p, off %d, space %d",
432             req, sge, off, space));
433 
434           cm->cm_sge = sge;
435           cm->cm_sglsize = space - off;
436 }
437 
438 /*
439  * Prepare the mpr_command for an IOC_FACTS request.
440  */
441 static int
mpi_pre_ioc_facts(struct mpr_command * cm,struct mpr_usr_command * cmd)442 mpi_pre_ioc_facts(struct mpr_command *cm, struct mpr_usr_command *cmd)
443 {
444           MPI2_IOC_FACTS_REQUEST *req = (void *)cm->cm_req;
445           MPI2_IOC_FACTS_REPLY *rpl;
446 
447           if (cmd->req_len != sizeof *req)
448                     return (EINVAL);
449           if (cmd->rpl_len != sizeof *rpl)
450                     return (EINVAL);
451 
452           cm->cm_sge = NULL;
453           cm->cm_sglsize = 0;
454           return (0);
455 }
456 
457 /*
458  * Prepare the mpr_command for a PORT_FACTS request.
459  */
460 static int
mpi_pre_port_facts(struct mpr_command * cm,struct mpr_usr_command * cmd)461 mpi_pre_port_facts(struct mpr_command *cm, struct mpr_usr_command *cmd)
462 {
463           MPI2_PORT_FACTS_REQUEST *req = (void *)cm->cm_req;
464           MPI2_PORT_FACTS_REPLY *rpl;
465 
466           if (cmd->req_len != sizeof *req)
467                     return (EINVAL);
468           if (cmd->rpl_len != sizeof *rpl)
469                     return (EINVAL);
470 
471           cm->cm_sge = NULL;
472           cm->cm_sglsize = 0;
473           return (0);
474 }
475 
476 /*
477  * Prepare the mpr_command for a FW_DOWNLOAD request.
478  */
479 static int
mpi_pre_fw_download(struct mpr_command * cm,struct mpr_usr_command * cmd)480 mpi_pre_fw_download(struct mpr_command *cm, struct mpr_usr_command *cmd)
481 {
482           MPI25_FW_DOWNLOAD_REQUEST *req = (void *)cm->cm_req;
483           MPI2_FW_DOWNLOAD_REPLY *rpl;
484           int error;
485 
486           if (cmd->req_len != sizeof *req)
487                     return (EINVAL);
488           if (cmd->rpl_len != sizeof *rpl)
489                     return (EINVAL);
490 
491           if (cmd->len == 0)
492                     return (EINVAL);
493 
494           error = copyin(cmd->buf, cm->cm_data, cmd->len);
495           if (error != 0)
496                     return (error);
497 
498           mpr_init_sge(cm, req, &req->SGL);
499 
500           /*
501            * For now, the F/W image must be provided in a single request.
502            */
503           if ((req->MsgFlags & MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT) == 0)
504                     return (EINVAL);
505           if (req->TotalImageSize != cmd->len)
506                     return (EINVAL);
507 
508           req->ImageOffset = 0;
509           req->ImageSize = cmd->len;
510 
511           cm->cm_flags |= MPR_CM_FLAGS_DATAOUT;
512 
513           return (mpr_push_ieee_sge(cm, &req->SGL, 0));
514 }
515 
516 /*
517  * Prepare the mpr_command for a FW_UPLOAD request.
518  */
519 static int
mpi_pre_fw_upload(struct mpr_command * cm,struct mpr_usr_command * cmd)520 mpi_pre_fw_upload(struct mpr_command *cm, struct mpr_usr_command *cmd)
521 {
522           MPI25_FW_UPLOAD_REQUEST *req = (void *)cm->cm_req;
523           MPI2_FW_UPLOAD_REPLY *rpl;
524 
525           if (cmd->req_len != sizeof *req)
526                     return (EINVAL);
527           if (cmd->rpl_len != sizeof *rpl)
528                     return (EINVAL);
529 
530           mpr_init_sge(cm, req, &req->SGL);
531           if (cmd->len == 0) {
532                     /* Perhaps just asking what the size of the fw is? */
533                     return (0);
534           }
535 
536           req->ImageOffset = 0;
537           req->ImageSize = cmd->len;
538 
539           cm->cm_flags |= MPR_CM_FLAGS_DATAIN;
540 
541           return (mpr_push_ieee_sge(cm, &req->SGL, 0));
542 }
543 
544 /*
545  * Prepare the mpr_command for a SATA_PASSTHROUGH request.
546  */
547 static int
mpi_pre_sata_passthrough(struct mpr_command * cm,struct mpr_usr_command * cmd)548 mpi_pre_sata_passthrough(struct mpr_command *cm, struct mpr_usr_command *cmd)
549 {
550           MPI2_SATA_PASSTHROUGH_REQUEST *req = (void *)cm->cm_req;
551           MPI2_SATA_PASSTHROUGH_REPLY *rpl;
552 
553           if (cmd->req_len != sizeof *req)
554                     return (EINVAL);
555           if (cmd->rpl_len != sizeof *rpl)
556                     return (EINVAL);
557 
558           mpr_init_sge(cm, req, &req->SGL);
559           return (0);
560 }
561 
562 /*
563  * Prepare the mpr_command for a SMP_PASSTHROUGH request.
564  */
565 static int
mpi_pre_smp_passthrough(struct mpr_command * cm,struct mpr_usr_command * cmd)566 mpi_pre_smp_passthrough(struct mpr_command *cm, struct mpr_usr_command *cmd)
567 {
568           MPI2_SMP_PASSTHROUGH_REQUEST *req = (void *)cm->cm_req;
569           MPI2_SMP_PASSTHROUGH_REPLY *rpl;
570 
571           if (cmd->req_len != sizeof *req)
572                     return (EINVAL);
573           if (cmd->rpl_len != sizeof *rpl)
574                     return (EINVAL);
575 
576           mpr_init_sge(cm, req, &req->SGL);
577           return (0);
578 }
579 
580 /*
581  * Prepare the mpr_command for a CONFIG request.
582  */
583 static int
mpi_pre_config(struct mpr_command * cm,struct mpr_usr_command * cmd)584 mpi_pre_config(struct mpr_command *cm, struct mpr_usr_command *cmd)
585 {
586           MPI2_CONFIG_REQUEST *req = (void *)cm->cm_req;
587           MPI2_CONFIG_REPLY *rpl;
588 
589           if (cmd->req_len != sizeof *req)
590                     return (EINVAL);
591           if (cmd->rpl_len != sizeof *rpl)
592                     return (EINVAL);
593 
594           mpr_init_sge(cm, req, &req->PageBufferSGE);
595           return (0);
596 }
597 
598 /*
599  * Prepare the mpr_command for a SAS_IO_UNIT_CONTROL request.
600  */
601 static int
mpi_pre_sas_io_unit_control(struct mpr_command * cm,struct mpr_usr_command * cmd)602 mpi_pre_sas_io_unit_control(struct mpr_command *cm,
603                                    struct mpr_usr_command *cmd)
604 {
605 
606           cm->cm_sge = NULL;
607           cm->cm_sglsize = 0;
608           return (0);
609 }
610 
611 /*
612  * A set of functions to prepare an mpr_command for the various
613  * supported requests.
614  */
615 struct mpr_user_func {
616           U8                  Function;
617           mpr_user_f          *f_pre;
618 } mpr_user_func_list[] = {
619           { MPI2_FUNCTION_IOC_FACTS,              mpi_pre_ioc_facts },
620           { MPI2_FUNCTION_PORT_FACTS,             mpi_pre_port_facts },
621           { MPI2_FUNCTION_FW_DOWNLOAD,            mpi_pre_fw_download },
622           { MPI2_FUNCTION_FW_UPLOAD,              mpi_pre_fw_upload },
623           { MPI2_FUNCTION_SATA_PASSTHROUGH,       mpi_pre_sata_passthrough },
624           { MPI2_FUNCTION_SMP_PASSTHROUGH,        mpi_pre_smp_passthrough},
625           { MPI2_FUNCTION_CONFIG,                           mpi_pre_config},
626           { MPI2_FUNCTION_SAS_IO_UNIT_CONTROL,    mpi_pre_sas_io_unit_control },
627           { 0xFF,                                           NULL } /* list end */
628 };
629 
630 static int
mpr_user_setup_request(struct mpr_command * cm,struct mpr_usr_command * cmd)631 mpr_user_setup_request(struct mpr_command *cm, struct mpr_usr_command *cmd)
632 {
633           MPI2_REQUEST_HEADER *hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
634           struct mpr_user_func *f;
635 
636           for (f = mpr_user_func_list; f->f_pre != NULL; f++) {
637                     if (hdr->Function == f->Function)
638                               return (f->f_pre(cm, cmd));
639           }
640           return (EINVAL);
641 }
642 
643 static int
mpr_user_command(struct mpr_softc * sc,struct mpr_usr_command * cmd)644 mpr_user_command(struct mpr_softc *sc, struct mpr_usr_command *cmd)
645 {
646           MPI2_REQUEST_HEADER *hdr;
647           MPI2_DEFAULT_REPLY *rpl = NULL;
648           void *buf = NULL;
649           struct mpr_command *cm = NULL;
650           int err = 0;
651           int sz;
652 
653           mpr_lock(sc);
654           cm = mpr_alloc_command(sc);
655 
656           if (cm == NULL) {
657                     mpr_printf(sc, "%s: no mpr requests\n", __func__);
658                     err = ENOMEM;
659                     goto RetFree;
660           }
661           mpr_unlock(sc);
662 
663           hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
664 
665           mpr_dprint(sc, MPR_USER, "%s: req %p %d  rpl %p %d\n", __func__,
666               cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len);
667 
668           if (cmd->req_len > (int)sc->reqframesz) {
669                     err = EINVAL;
670                     goto RetFreeUnlocked;
671           }
672           err = copyin(cmd->req, hdr, cmd->req_len);
673           if (err != 0)
674                     goto RetFreeUnlocked;
675 
676           mpr_dprint(sc, MPR_USER, "%s: Function %02X MsgFlags %02X\n", __func__,
677               hdr->Function, hdr->MsgFlags);
678 
679           if (cmd->len > 0) {
680                     buf = kmalloc(cmd->len, M_MPRUSER, M_WAITOK|M_ZERO);
681                     cm->cm_data = buf;
682                     cm->cm_length = cmd->len;
683           } else {
684                     cm->cm_data = NULL;
685                     cm->cm_length = 0;
686           }
687 
688           cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE;
689           cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
690 
691           err = mpr_user_setup_request(cm, cmd);
692           if (err == EINVAL) {
693                     mpr_printf(sc, "%s: unsupported parameter or unsupported "
694                         "function in request (function = 0x%X)\n", __func__,
695                         hdr->Function);
696           }
697           if (err != 0)
698                     goto RetFreeUnlocked;
699 
700           mpr_lock(sc);
701           err = mpr_wait_command(sc, &cm, 30, CAN_SLEEP);
702 
703           if (err || (cm == NULL)) {
704                     mpr_printf(sc, "%s: invalid request: error %d\n",
705                         __func__, err);
706                     goto RetFree;
707           }
708 
709           if (cm != NULL)
710                     rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
711           if (rpl != NULL)
712                     sz = rpl->MsgLength * 4;
713           else
714                     sz = 0;
715 
716           if (sz > cmd->rpl_len) {
717                     mpr_printf(sc, "%s: user reply buffer (%d) smaller than "
718                         "returned buffer (%d)\n", __func__, cmd->rpl_len, sz);
719                     sz = cmd->rpl_len;
720           }
721 
722           mpr_unlock(sc);
723           copyout(rpl, cmd->rpl, sz);
724           if (buf != NULL)
725                     copyout(buf, cmd->buf, cmd->len);
726           mpr_dprint(sc, MPR_USER, "%s: reply size %d\n", __func__, sz);
727 
728 RetFreeUnlocked:
729           mpr_lock(sc);
730 RetFree:
731           if (cm != NULL)
732                     mpr_free_command(sc, cm);
733           mpr_unlock(sc);
734           if (buf != NULL)
735                     kfree(buf, M_MPRUSER);
736           return (err);
737 }
738 
739 static int
mpr_user_pass_thru(struct mpr_softc * sc,mpr_pass_thru_t * data)740 mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
741 {
742           MPI2_REQUEST_HEADER *hdr, tmphdr;
743           MPI2_DEFAULT_REPLY  *rpl;
744           Mpi26NVMeEncapsulatedErrorReply_t *nvme_error_reply = NULL;
745           Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request = NULL;
746           struct mpr_command  *cm = NULL;
747           int                           i, err = 0, dir = 0, sz;
748           uint8_t                       tool, function = 0;
749           u_int                         sense_len;
750           struct mprsas_target          *targ = NULL;
751 
752           /*
753            * Only allow one passthru command at a time.  Use the MPR_FLAGS_BUSY
754            * bit to denote that a passthru is being processed.
755            */
756           mpr_lock(sc);
757           if (sc->mpr_flags & MPR_FLAGS_BUSY) {
758                     mpr_dprint(sc, MPR_USER, "%s: Only one passthru command "
759                         "allowed at a single time.", __func__);
760                     mpr_unlock(sc);
761                     return (EBUSY);
762           }
763           sc->mpr_flags |= MPR_FLAGS_BUSY;
764           mpr_unlock(sc);
765 
766           /*
767            * Do some validation on data direction.  Valid cases are:
768            *    1) DataSize is 0 and direction is NONE
769            *    2) DataSize is non-zero and one of:
770            *        a) direction is READ or
771            *        b) direction is WRITE or
772            *        c) direction is BOTH and DataOutSize is non-zero
773            * If valid and the direction is BOTH, change the direction to READ.
774            * if valid and the direction is not BOTH, make sure DataOutSize is 0.
775            */
776           if (((data->DataSize == 0) &&
777               (data->DataDirection == MPR_PASS_THRU_DIRECTION_NONE)) ||
778               ((data->DataSize != 0) &&
779               ((data->DataDirection == MPR_PASS_THRU_DIRECTION_READ) ||
780               (data->DataDirection == MPR_PASS_THRU_DIRECTION_WRITE) ||
781               ((data->DataDirection == MPR_PASS_THRU_DIRECTION_BOTH) &&
782               (data->DataOutSize != 0))))) {
783                     if (data->DataDirection == MPR_PASS_THRU_DIRECTION_BOTH)
784                               data->DataDirection = MPR_PASS_THRU_DIRECTION_READ;
785                     else
786                               data->DataOutSize = 0;
787           } else
788                     return (EINVAL);
789 
790           mpr_dprint(sc, MPR_USER, "%s: req 0x%jx %d  rpl 0x%jx %d "
791               "data in 0x%jx %d data out 0x%jx %d data dir %d\n", __func__,
792               data->PtrRequest, data->RequestSize, data->PtrReply,
793               data->ReplySize, data->PtrData, data->DataSize,
794               data->PtrDataOut, data->DataOutSize, data->DataDirection);
795 
796           /*
797            * copy in the header so we know what we're dealing with before we
798            * commit to allocating a command for it.
799            */
800           err = copyin(PTRIN(data->PtrRequest), &tmphdr, data->RequestSize);
801           if (err != 0)
802                     goto RetFreeUnlocked;
803 
804           if (data->RequestSize > (int)sc->reqframesz) {
805                     err = EINVAL;
806                     goto RetFreeUnlocked;
807           }
808 
809           function = tmphdr.Function;
810           mpr_dprint(sc, MPR_USER, "%s: Function %02X MsgFlags %02X\n", __func__,
811               function, tmphdr.MsgFlags);
812 
813           /*
814            * Handle a passthru TM request.
815            */
816           if (function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
817                     MPI2_SCSI_TASK_MANAGE_REQUEST *task;
818 
819                     mpr_lock(sc);
820                     cm = mprsas_alloc_tm(sc);
821                     if (cm == NULL) {
822                               err = EINVAL;
823                               goto Ret;
824                     }
825 
826                     /* Copy the header in.  Only a small fixup is needed. */
827                     task = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
828                     bcopy(&tmphdr, task, data->RequestSize);
829                     task->TaskMID = cm->cm_desc.Default.SMID;
830 
831                     cm->cm_data = NULL;
832                     cm->cm_desc.HighPriority.RequestFlags =
833                         MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
834                     cm->cm_complete = NULL;
835                     cm->cm_complete_data = NULL;
836 
837                     targ = mprsas_find_target_by_handle(sc->sassc, 0,
838                         task->DevHandle);
839                     if (targ == NULL) {
840                               mpr_dprint(sc, MPR_INFO,
841                                  "%s %d : invalid handle for requested TM 0x%x \n",
842                                  __func__, __LINE__, task->DevHandle);
843                               err = 1;
844                     } else {
845                               mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD);
846                               err = mpr_wait_command(sc, &cm, 30, CAN_SLEEP);
847                     }
848 
849                     if (err != 0) {
850                               err = EIO;
851                               mpr_dprint(sc, MPR_FAULT, "%s: task management failed",
852                                   __func__);
853                     }
854                     /*
855                      * Copy the reply data and sense data to user space.
856                      */
857                     if ((cm != NULL) && (cm->cm_reply != NULL)) {
858                               rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
859                               sz = rpl->MsgLength * 4;
860 
861                               if (sz > data->ReplySize) {
862                                         mpr_printf(sc, "%s: user reply buffer (%d) "
863                                             "smaller than returned buffer (%d)\n",
864                                             __func__, data->ReplySize, sz);
865                               }
866                               mpr_unlock(sc);
867                               copyout(cm->cm_reply, PTRIN(data->PtrReply),
868                                   data->ReplySize);
869                               mpr_lock(sc);
870                     }
871                     mprsas_free_tm(sc, cm);
872                     goto Ret;
873           }
874 
875           mpr_lock(sc);
876           cm = mpr_alloc_command(sc);
877 
878           if (cm == NULL) {
879                     mpr_printf(sc, "%s: no mpr requests\n", __func__);
880                     err = ENOMEM;
881                     goto Ret;
882           }
883           mpr_unlock(sc);
884 
885           hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
886           bcopy(&tmphdr, hdr, data->RequestSize);
887 
888           /*
889            * Do some checking to make sure the IOCTL request contains a valid
890            * request.  Then set the SGL info.
891            */
892           mpr_init_sge(cm, hdr, (void *)((uint8_t *)hdr + data->RequestSize));
893 
894           /*
895            * Set up for read, write or both.  From check above, DataOutSize will
896            * be 0 if direction is READ or WRITE, but it will have some non-zero
897            * value if the direction is BOTH.  So, just use the biggest size to get
898            * the cm_data buffer size.  If direction is BOTH, 2 SGLs need to be set
899            * up; the first is for the request and the second will contain the
900            * response data. cm_out_len needs to be set here and this will be used
901            * when the SGLs are set up.
902            */
903           cm->cm_data = NULL;
904           cm->cm_length = MAX(data->DataSize, data->DataOutSize);
905           cm->cm_out_len = data->DataOutSize;
906           cm->cm_flags = 0;
907           if (cm->cm_length != 0) {
908                     cm->cm_data = kmalloc(cm->cm_length, M_MPRUSER, M_WAITOK |
909                         M_ZERO);
910                     cm->cm_flags = MPR_CM_FLAGS_DATAIN;
911                     if (data->DataOutSize) {
912                               cm->cm_flags |= MPR_CM_FLAGS_DATAOUT;
913                               err = copyin(PTRIN(data->PtrDataOut),
914                                   cm->cm_data, data->DataOutSize);
915                     } else if (data->DataDirection ==
916                         MPR_PASS_THRU_DIRECTION_WRITE) {
917                               cm->cm_flags = MPR_CM_FLAGS_DATAOUT;
918                               err = copyin(PTRIN(data->PtrData),
919                                   cm->cm_data, data->DataSize);
920                     }
921                     if (err != 0)
922                               mpr_dprint(sc, MPR_FAULT, "%s: failed to copy IOCTL "
923                                   "data from user space\n", __func__);
924           }
925           /*
926            * Set this flag only if processing a command that does not need an
927            * IEEE SGL.  The CLI Tool within the Toolbox uses IEEE SGLs, so clear
928            * the flag only for that tool if processing a Toolbox function.
929            */
930           cm->cm_flags |= MPR_CM_FLAGS_SGE_SIMPLE;
931           for (i = 0; i < sizeof (ieee_sgl_func_list); i++) {
932                     if (function == ieee_sgl_func_list[i]) {
933                               if (function == MPI2_FUNCTION_TOOLBOX)
934                               {
935                                         tool = (uint8_t)hdr->FunctionDependent1;
936                                         if (tool != MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL)
937                                                   break;
938                               }
939                               cm->cm_flags &= ~MPR_CM_FLAGS_SGE_SIMPLE;
940                               break;
941                     }
942           }
943           cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
944 
945           if (function == MPI2_FUNCTION_NVME_ENCAPSULATED) {
946                     nvme_encap_request =
947                         (Mpi26NVMeEncapsulatedRequest_t *)cm->cm_req;
948                     cm->cm_desc.Default.RequestFlags =
949                         MPI26_REQ_DESCRIPT_FLAGS_PCIE_ENCAPSULATED;
950 
951                     /*
952                      * Get the Physical Address of the sense buffer.
953                      * Save the user's Error Response buffer address and use that
954                      *   field to hold the sense buffer address.
955                      * Clear the internal sense buffer, which will potentially hold
956                      *   the Completion Queue Entry on return, or 0 if no Entry.
957                      * Build the PRPs and set direction bits.
958                      * Send the request.
959                      */
960                     cm->nvme_error_response =
961                         (uint64_t *)(uintptr_t)(((uint64_t)nvme_encap_request->
962                         ErrorResponseBaseAddress.High << 32) |
963                         (uint64_t)nvme_encap_request->
964                         ErrorResponseBaseAddress.Low);
965                     nvme_encap_request->ErrorResponseBaseAddress.High =
966                         htole32((uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32));
967                     nvme_encap_request->ErrorResponseBaseAddress.Low =
968                         htole32(cm->cm_sense_busaddr);
969                     memset(cm->cm_sense, 0, NVME_ERROR_RESPONSE_SIZE);
970                     mpr_build_nvme_prp(sc, cm, nvme_encap_request, cm->cm_data,
971                         data->DataSize, data->DataOutSize);
972           }
973 
974           /*
975            * Set up Sense buffer and SGL offset for IO passthru.  SCSI IO request
976            * uses SCSI IO or Fast Path SCSI IO descriptor.
977            */
978           if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
979               (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
980                     MPI2_SCSI_IO_REQUEST          *scsi_io_req;
981 
982                     scsi_io_req = (MPI2_SCSI_IO_REQUEST *)hdr;
983                     /*
984                      * Put SGE for data and data_out buffer at the end of
985                      * scsi_io_request message header (64 bytes in total).
986                      * Following above SGEs, the residual space will be used by
987                      * sense data.
988                      */
989                     scsi_io_req->SenseBufferLength = (uint8_t)(data->RequestSize -
990                         64);
991                     scsi_io_req->SenseBufferLowAddress =
992                         htole32(cm->cm_sense_busaddr);
993 
994                     /*
995                      * Set SGLOffset0 value.  This is the number of dwords that SGL
996                      * is offset from the beginning of MPI2_SCSI_IO_REQUEST struct.
997                      */
998                     scsi_io_req->SGLOffset0 = 24;
999 
1000                     /*
1001                      * Setup descriptor info.  RAID passthrough must use the
1002                      * default request descriptor which is already set, so if this
1003                      * is a SCSI IO request, change the descriptor to SCSI IO or
1004                      * Fast Path SCSI IO.  Also, if this is a SCSI IO request,
1005                      * handle the reply in the mprsas_scsio_complete function.
1006                      */
1007                     if (function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
1008                               targ = mprsas_find_target_by_handle(sc->sassc, 0,
1009                                   scsi_io_req->DevHandle);
1010 
1011                               if (!targ) {
1012                                         kprintf("No Target found for handle %d\n",
1013                                             scsi_io_req->DevHandle);
1014                                         err = EINVAL;
1015                                         goto RetFreeUnlocked;
1016                               }
1017 
1018                               if (targ->scsi_req_desc_type ==
1019                                   MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO) {
1020                                         cm->cm_desc.FastPathSCSIIO.RequestFlags =
1021                                             MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
1022                                         if (!sc->atomic_desc_capable) {
1023                                                   cm->cm_desc.FastPathSCSIIO.DevHandle =
1024                                                       scsi_io_req->DevHandle;
1025                                         }
1026                                         scsi_io_req->IoFlags |=
1027                                             MPI25_SCSIIO_IOFLAGS_FAST_PATH;
1028                               } else {
1029                                         cm->cm_desc.SCSIIO.RequestFlags =
1030                                             MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
1031                                         if (!sc->atomic_desc_capable) {
1032                                                   cm->cm_desc.SCSIIO.DevHandle =
1033                                                       scsi_io_req->DevHandle;
1034                                         }
1035                               }
1036 
1037                               /*
1038                                * Make sure the DevHandle is not 0 because this is a
1039                                * likely error.
1040                                */
1041                               if (scsi_io_req->DevHandle == 0) {
1042                                         err = EINVAL;
1043                                         goto RetFreeUnlocked;
1044                               }
1045                     }
1046           }
1047 
1048           mpr_lock(sc);
1049 
1050           err = mpr_wait_command(sc, &cm, 30, CAN_SLEEP);
1051 
1052           if (err || (cm == NULL)) {
1053                     mpr_printf(sc, "%s: invalid request: error %d\n", __func__,
1054                         err);
1055                     goto RetFree;
1056           }
1057 
1058           /*
1059            * Sync the DMA data, if any.  Then copy the data to user space.
1060            */
1061           if (cm->cm_data != NULL) {
1062                     if (cm->cm_flags & MPR_CM_FLAGS_DATAIN)
1063                               dir = BUS_DMASYNC_POSTREAD;
1064                     else if (cm->cm_flags & MPR_CM_FLAGS_DATAOUT)
1065                               dir = BUS_DMASYNC_POSTWRITE;
1066                     bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir);
1067                     bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap);
1068 
1069                     if (cm->cm_flags & MPR_CM_FLAGS_DATAIN) {
1070                               mpr_unlock(sc);
1071                               err = copyout(cm->cm_data,
1072                                   PTRIN(data->PtrData), data->DataSize);
1073                               mpr_lock(sc);
1074                               if (err != 0)
1075                                         mpr_dprint(sc, MPR_FAULT, "%s: failed to copy "
1076                                             "IOCTL data to user space\n", __func__);
1077                     }
1078           }
1079 
1080           /*
1081            * Copy the reply data and sense data to user space.
1082            */
1083           if (cm->cm_reply != NULL) {
1084                     rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
1085                     sz = rpl->MsgLength * 4;
1086 
1087                     if (sz > data->ReplySize) {
1088                               mpr_printf(sc, "%s: user reply buffer (%d) smaller "
1089                                   "than returned buffer (%d)\n", __func__,
1090                                   data->ReplySize, sz);
1091                     }
1092                     mpr_unlock(sc);
1093                     copyout(cm->cm_reply, PTRIN(data->PtrReply), data->ReplySize);
1094                     mpr_lock(sc);
1095 
1096                     if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
1097                         (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
1098                               if (((MPI2_SCSI_IO_REPLY *)rpl)->SCSIState &
1099                                   MPI2_SCSI_STATE_AUTOSENSE_VALID) {
1100                                         sense_len =
1101                                             MIN((le32toh(((MPI2_SCSI_IO_REPLY *)rpl)->
1102                                             SenseCount)), sizeof(struct
1103                                             scsi_sense_data));
1104                                         mpr_unlock(sc);
1105                                         copyout(cm->cm_sense, cm->cm_req + 64,
1106                                             sense_len);
1107                                         mpr_lock(sc);
1108                               }
1109                     }
1110 
1111                     /*
1112                      * Copy out the NVMe Error Reponse to user. The Error Response
1113                      * buffer is given by the user, but a sense buffer is used to
1114                      * get that data from the IOC. The user's
1115                      * ErrorResponseBaseAddress is saved in the
1116                      * 'nvme_error_response' field before the command because that
1117                      * field is set to a sense buffer. When the command is
1118                      * complete, the Error Response data from the IOC is copied to
1119                      * that user address after it is checked for validity.
1120                      * Also note that 'sense' buffers are not defined for
1121                      * NVMe commands. Sense terminalogy is only used here so that
1122                      * the same IOCTL structure and sense buffers can be used for
1123                      * NVMe.
1124                      */
1125                     if (function == MPI2_FUNCTION_NVME_ENCAPSULATED) {
1126                               if (cm->nvme_error_response == NULL) {
1127                                         mpr_dprint(sc, MPR_INFO, "NVMe Error Response "
1128                                             "buffer is NULL. Response data will not be "
1129                                             "returned.\n");
1130                                         mpr_unlock(sc);
1131                                         goto RetFreeUnlocked;
1132                               }
1133 
1134                               nvme_error_reply =
1135                                   (Mpi26NVMeEncapsulatedErrorReply_t *)cm->cm_reply;
1136                               sz = MIN(le32toh(nvme_error_reply->ErrorResponseCount),
1137                                   NVME_ERROR_RESPONSE_SIZE);
1138                               mpr_unlock(sc);
1139                               copyout(cm->cm_sense, cm->nvme_error_response, sz);
1140                               mpr_lock(sc);
1141                     }
1142           }
1143           mpr_unlock(sc);
1144 
1145 RetFreeUnlocked:
1146           mpr_lock(sc);
1147 
1148 RetFree:
1149           if (cm != NULL) {
1150                     if (cm->cm_data)
1151                               kfree(cm->cm_data, M_MPRUSER);
1152                     mpr_free_command(sc, cm);
1153           }
1154 Ret:
1155           sc->mpr_flags &= ~MPR_FLAGS_BUSY;
1156           mpr_unlock(sc);
1157 
1158           return (err);
1159 }
1160 
1161 static void
mpr_user_get_adapter_data(struct mpr_softc * sc,mpr_adapter_data_t * data)1162 mpr_user_get_adapter_data(struct mpr_softc *sc, mpr_adapter_data_t *data)
1163 {
1164           Mpi2ConfigReply_t   mpi_reply;
1165           Mpi2BiosPage3_t               config_page;
1166 
1167           /*
1168            * Use the PCI interface functions to get the Bus, Device, and Function
1169            * information.
1170            */
1171           data->PciInformation.u.bits.BusNumber = pci_get_bus(sc->mpr_dev);
1172           data->PciInformation.u.bits.DeviceNumber = pci_get_slot(sc->mpr_dev);
1173           data->PciInformation.u.bits.FunctionNumber =
1174               pci_get_function(sc->mpr_dev);
1175 
1176           /*
1177            * Get the FW version that should already be saved in IOC Facts.
1178            */
1179           data->MpiFirmwareVersion = sc->facts->FWVersion.Word;
1180 
1181           /*
1182            * General device info.
1183            */
1184           if (sc->mpr_flags & MPR_FLAGS_GEN35_IOC)
1185                     data->AdapterType = MPRIOCTL_ADAPTER_TYPE_SAS35;
1186           else
1187                     data->AdapterType = MPRIOCTL_ADAPTER_TYPE_SAS3;
1188           data->PCIDeviceHwId = pci_get_device(sc->mpr_dev);
1189           data->PCIDeviceHwRev = pci_read_config(sc->mpr_dev, PCIR_REVID, 1);
1190           data->SubSystemId = pci_get_subdevice(sc->mpr_dev);
1191           data->SubsystemVendorId = pci_get_subvendor(sc->mpr_dev);
1192 
1193           /*
1194            * Get the driver version.
1195            */
1196           strcpy((char *)&data->DriverVersion[0], MPR_DRIVER_VERSION);
1197 
1198           /*
1199            * Need to get BIOS Config Page 3 for the BIOS Version.
1200            */
1201           data->BiosVersion = 0;
1202           mpr_lock(sc);
1203           if (mpr_config_get_bios_pg3(sc, &mpi_reply, &config_page))
1204                     kprintf("%s: Error while retrieving BIOS Version\n", __func__);
1205           else
1206                     data->BiosVersion = config_page.BiosVersion;
1207           mpr_unlock(sc);
1208 }
1209 
1210 static void
mpr_user_read_pci_info(struct mpr_softc * sc,mpr_pci_info_t * data)1211 mpr_user_read_pci_info(struct mpr_softc *sc, mpr_pci_info_t *data)
1212 {
1213           int       i;
1214 
1215           /*
1216            * Use the PCI interface functions to get the Bus, Device, and Function
1217            * information.
1218            */
1219           data->BusNumber = pci_get_bus(sc->mpr_dev);
1220           data->DeviceNumber = pci_get_slot(sc->mpr_dev);
1221           data->FunctionNumber = pci_get_function(sc->mpr_dev);
1222 
1223           /*
1224            * Now get the interrupt vector and the pci header.  The vector can
1225            * only be 0 right now.  The header is the first 256 bytes of config
1226            * space.
1227            */
1228           data->InterruptVector = 0;
1229           for (i = 0; i < sizeof (data->PciHeader); i++) {
1230                     data->PciHeader[i] = pci_read_config(sc->mpr_dev, i, 1);
1231           }
1232 }
1233 
1234 static uint8_t
mpr_get_fw_diag_buffer_number(struct mpr_softc * sc,uint32_t unique_id)1235 mpr_get_fw_diag_buffer_number(struct mpr_softc *sc, uint32_t unique_id)
1236 {
1237           uint8_t   index;
1238 
1239           for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
1240                     if (sc->fw_diag_buffer_list[index].unique_id == unique_id) {
1241                               return (index);
1242                     }
1243           }
1244 
1245           return (MPR_FW_DIAGNOSTIC_UID_NOT_FOUND);
1246 }
1247 
1248 static int
mpr_post_fw_diag_buffer(struct mpr_softc * sc,mpr_fw_diagnostic_buffer_t * pBuffer,uint32_t * return_code)1249 mpr_post_fw_diag_buffer(struct mpr_softc *sc,
1250     mpr_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code)
1251 {
1252           MPI2_DIAG_BUFFER_POST_REQUEST *req;
1253           MPI2_DIAG_BUFFER_POST_REPLY   *reply;
1254           struct mpr_command            *cm = NULL;
1255           int                                     i, status;
1256 
1257           /*
1258            * If buffer is not enabled, just leave.
1259            */
1260           *return_code = MPR_FW_DIAG_ERROR_POST_FAILED;
1261           if (!pBuffer->enabled) {
1262                     return (MPR_DIAG_FAILURE);
1263           }
1264 
1265           /*
1266            * Clear some flags initially.
1267            */
1268           pBuffer->force_release = FALSE;
1269           pBuffer->valid_data = FALSE;
1270           pBuffer->owned_by_firmware = FALSE;
1271 
1272           /*
1273            * Get a command.
1274            */
1275           cm = mpr_alloc_command(sc);
1276           if (cm == NULL) {
1277                     mpr_printf(sc, "%s: no mpr requests\n", __func__);
1278                     return (MPR_DIAG_FAILURE);
1279           }
1280 
1281           /*
1282            * Build the request for releasing the FW Diag Buffer and send it.
1283            */
1284           req = (MPI2_DIAG_BUFFER_POST_REQUEST *)cm->cm_req;
1285           req->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
1286           req->BufferType = pBuffer->buffer_type;
1287           req->ExtendedType = pBuffer->extended_type;
1288           req->BufferLength = pBuffer->size;
1289           for (i = 0; i < (sizeof(req->ProductSpecific) / 4); i++)
1290                     req->ProductSpecific[i] = pBuffer->product_specific[i];
1291           mpr_from_u64(sc->fw_diag_busaddr, &req->BufferAddress);
1292           cm->cm_data = NULL;
1293           cm->cm_length = 0;
1294           cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1295           cm->cm_complete_data = NULL;
1296 
1297           /*
1298            * Send command synchronously.
1299            */
1300           status = mpr_wait_command(sc, &cm, 30, CAN_SLEEP);
1301           if (status || (cm == NULL)) {
1302                     mpr_printf(sc, "%s: invalid request: error %d\n", __func__,
1303                         status);
1304                     status = MPR_DIAG_FAILURE;
1305                     goto done;
1306           }
1307 
1308           /*
1309            * Process POST reply.
1310            */
1311           reply = (MPI2_DIAG_BUFFER_POST_REPLY *)cm->cm_reply;
1312           if (reply == NULL) {
1313                     mpr_printf(sc, "%s: reply is NULL, probably due to "
1314                         "reinitialization", __func__);
1315                     status = MPR_DIAG_FAILURE;
1316                     goto done;
1317           }
1318 
1319           if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
1320               MPI2_IOCSTATUS_SUCCESS) {
1321                     status = MPR_DIAG_FAILURE;
1322                     mpr_dprint(sc, MPR_FAULT, "%s: post of FW  Diag Buffer failed "
1323                         "with IOCStatus = 0x%x, IOCLogInfo = 0x%x and "
1324                         "TransferLength = 0x%x\n", __func__,
1325                         le16toh(reply->IOCStatus), le32toh(reply->IOCLogInfo),
1326                         le32toh(reply->TransferLength));
1327                     goto done;
1328           }
1329 
1330           /*
1331            * Post was successful.
1332            */
1333           pBuffer->valid_data = TRUE;
1334           pBuffer->owned_by_firmware = TRUE;
1335           *return_code = MPR_FW_DIAG_ERROR_SUCCESS;
1336           status = MPR_DIAG_SUCCESS;
1337 
1338 done:
1339           if (cm != NULL)
1340                     mpr_free_command(sc, cm);
1341           return (status);
1342 }
1343 
1344 static int
mpr_release_fw_diag_buffer(struct mpr_softc * sc,mpr_fw_diagnostic_buffer_t * pBuffer,uint32_t * return_code,uint32_t diag_type)1345 mpr_release_fw_diag_buffer(struct mpr_softc *sc,
1346     mpr_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
1347     uint32_t diag_type)
1348 {
1349           MPI2_DIAG_RELEASE_REQUEST     *req;
1350           MPI2_DIAG_RELEASE_REPLY                 *reply;
1351           struct mpr_command            *cm = NULL;
1352           int                                     status;
1353 
1354           /*
1355            * If buffer is not enabled, just leave.
1356            */
1357           *return_code = MPR_FW_DIAG_ERROR_RELEASE_FAILED;
1358           if (!pBuffer->enabled) {
1359                     mpr_dprint(sc, MPR_USER, "%s: This buffer type is not "
1360                         "supported by the IOC", __func__);
1361                     return (MPR_DIAG_FAILURE);
1362           }
1363 
1364           /*
1365            * Clear some flags initially.
1366            */
1367           pBuffer->force_release = FALSE;
1368           pBuffer->valid_data = FALSE;
1369           pBuffer->owned_by_firmware = FALSE;
1370 
1371           /*
1372            * Get a command.
1373            */
1374           cm = mpr_alloc_command(sc);
1375           if (cm == NULL) {
1376                     mpr_printf(sc, "%s: no mpr requests\n", __func__);
1377                     return (MPR_DIAG_FAILURE);
1378           }
1379 
1380           /*
1381            * Build the request for releasing the FW Diag Buffer and send it.
1382            */
1383           req = (MPI2_DIAG_RELEASE_REQUEST *)cm->cm_req;
1384           req->Function = MPI2_FUNCTION_DIAG_RELEASE;
1385           req->BufferType = pBuffer->buffer_type;
1386           cm->cm_data = NULL;
1387           cm->cm_length = 0;
1388           cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1389           cm->cm_complete_data = NULL;
1390 
1391           /*
1392            * Send command synchronously.
1393            */
1394           status = mpr_wait_command(sc, &cm, 30, CAN_SLEEP);
1395           if (status || (cm == NULL)) {
1396                     mpr_printf(sc, "%s: invalid request: error %d\n", __func__,
1397                         status);
1398                     status = MPR_DIAG_FAILURE;
1399                     goto done;
1400           }
1401 
1402           /*
1403            * Process RELEASE reply.
1404            */
1405           reply = (MPI2_DIAG_RELEASE_REPLY *)cm->cm_reply;
1406           if (reply == NULL) {
1407                     mpr_printf(sc, "%s: reply is NULL, probably due to "
1408                         "reinitialization", __func__);
1409                     status = MPR_DIAG_FAILURE;
1410                     goto done;
1411           }
1412           if (((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
1413               MPI2_IOCSTATUS_SUCCESS) || pBuffer->owned_by_firmware) {
1414                     status = MPR_DIAG_FAILURE;
1415                     mpr_dprint(sc, MPR_FAULT, "%s: release of FW Diag Buffer "
1416                         "failed with IOCStatus = 0x%x and IOCLogInfo = 0x%x\n",
1417                         __func__, le16toh(reply->IOCStatus),
1418                         le32toh(reply->IOCLogInfo));
1419                     goto done;
1420           }
1421 
1422           /*
1423            * Release was successful.
1424            */
1425           *return_code = MPR_FW_DIAG_ERROR_SUCCESS;
1426           status = MPR_DIAG_SUCCESS;
1427 
1428           /*
1429            * If this was for an UNREGISTER diag type command, clear the unique ID.
1430            */
1431           if (diag_type == MPR_FW_DIAG_TYPE_UNREGISTER) {
1432                     pBuffer->unique_id = MPR_FW_DIAG_INVALID_UID;
1433           }
1434 
1435 done:
1436           if (cm != NULL)
1437                     mpr_free_command(sc, cm);
1438 
1439           return (status);
1440 }
1441 
1442 static int
mpr_diag_register(struct mpr_softc * sc,mpr_fw_diag_register_t * diag_register,uint32_t * return_code)1443 mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register,
1444     uint32_t *return_code)
1445 {
1446           mpr_fw_diagnostic_buffer_t    *pBuffer;
1447           struct mpr_busdma_context     *ctx;
1448           uint8_t                                 extended_type, buffer_type, i;
1449           uint32_t                      buffer_size;
1450           uint32_t                      unique_id;
1451           int                                     status;
1452           int                                     error;
1453 
1454           extended_type = diag_register->ExtendedType;
1455           buffer_type = diag_register->BufferType;
1456           buffer_size = diag_register->RequestedBufferSize;
1457           unique_id = diag_register->UniqueId;
1458           ctx = NULL;
1459           error = 0;
1460 
1461           /*
1462            * Check for valid buffer type
1463            */
1464           if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) {
1465                     *return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1466                     return (MPR_DIAG_FAILURE);
1467           }
1468 
1469           /*
1470            * Get the current buffer and look up the unique ID.  The unique ID
1471            * should not be found.  If it is, the ID is already in use.
1472            */
1473           i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1474           pBuffer = &sc->fw_diag_buffer_list[buffer_type];
1475           if (i != MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1476                     *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1477                     return (MPR_DIAG_FAILURE);
1478           }
1479 
1480           /*
1481            * The buffer's unique ID should not be registered yet, and the given
1482            * unique ID cannot be 0.
1483            */
1484           if ((pBuffer->unique_id != MPR_FW_DIAG_INVALID_UID) ||
1485               (unique_id == MPR_FW_DIAG_INVALID_UID)) {
1486                     *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1487                     return (MPR_DIAG_FAILURE);
1488           }
1489 
1490           /*
1491            * If this buffer is already posted as immediate, just change owner.
1492            */
1493           if (pBuffer->immediate && pBuffer->owned_by_firmware &&
1494               (pBuffer->unique_id == MPR_FW_DIAG_INVALID_UID)) {
1495                     pBuffer->immediate = FALSE;
1496                     pBuffer->unique_id = unique_id;
1497                     return (MPR_DIAG_SUCCESS);
1498           }
1499 
1500           /*
1501            * Post a new buffer after checking if it's enabled.  The DMA buffer
1502            * that is allocated will be contiguous (nsegments = 1).
1503            */
1504           if (!pBuffer->enabled) {
1505                     *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
1506                     return (MPR_DIAG_FAILURE);
1507           }
1508           if (bus_dma_tag_create( sc->mpr_parent_dmat,    /* parent */
1509                                         1, 0,                         /* algnmnt, boundary */
1510                                         BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
1511                                         BUS_SPACE_MAXADDR,  /* highaddr */
1512                                 buffer_size,                /* maxsize */
1513                                 1,                          /* nsegments */
1514                                 buffer_size,                /* maxsegsize */
1515                                 0,                          /* flags */
1516                                 &sc->fw_diag_dmat)) {
1517                     mpr_dprint(sc, MPR_ERROR,
1518                         "Cannot allocate FW diag buffer DMA tag\n");
1519                     *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
1520                     status = MPR_DIAG_FAILURE;
1521                     goto bailout;
1522           }
1523         if (bus_dmamem_alloc(sc->fw_diag_dmat, (void **)&sc->fw_diag_buffer,
1524               BUS_DMA_NOWAIT, &sc->fw_diag_map)) {
1525                     mpr_dprint(sc, MPR_ERROR,
1526                         "Cannot allocate FW diag buffer memory\n");
1527                     *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
1528                     status = MPR_DIAG_FAILURE;
1529                     goto bailout;
1530           }
1531           bzero(sc->fw_diag_buffer, buffer_size);
1532 
1533           ctx = kmalloc(sizeof(*ctx), M_MPR, M_WAITOK | M_ZERO);
1534           if (ctx == NULL) {
1535                     device_printf(sc->mpr_dev, "%s: context kmalloc failed\n",
1536                         __func__);
1537                     *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
1538                     status = MPR_DIAG_FAILURE;
1539                     goto bailout;
1540           }
1541           ctx->addr = &sc->fw_diag_busaddr;
1542           ctx->buffer_dmat = sc->fw_diag_dmat;
1543           ctx->buffer_dmamap = sc->fw_diag_map;
1544           ctx->softc = sc;
1545           error = bus_dmamap_load(sc->fw_diag_dmat, sc->fw_diag_map,
1546               sc->fw_diag_buffer, buffer_size, mpr_memaddr_wait_cb,
1547               ctx, 0);
1548           if (error == EINPROGRESS) {
1549 
1550                     /* XXX KDM */
1551                     device_printf(sc->mpr_dev, "%s: Deferred bus_dmamap_load\n",
1552                         __func__);
1553                     /*
1554                      * Wait for the load to complete.  If we're interrupted,
1555                      * bail out.
1556                      */
1557                     mpr_lock(sc);
1558                     if (ctx->completed == 0) {
1559                               error = lksleep(ctx, &sc->mpr_lock, PCATCH, "mprwait", 0);
1560                               if (error != 0) {
1561                                         /*
1562                                          * We got an error from msleep(9).  This is
1563                                          * most likely due to a signal.  Tell
1564                                          * mpr_memaddr_wait_cb() that we've abandoned
1565                                          * the context, so it needs to clean up when
1566                                          * it is called.
1567                                          */
1568                                         ctx->abandoned = 1;
1569 
1570                                         /* The callback will free this memory */
1571                                         ctx = NULL;
1572                                         mpr_unlock(sc);
1573 
1574                                         device_printf(sc->mpr_dev, "Cannot "
1575                                             "bus_dmamap_load FW diag buffer, error = "
1576                                             "%d returned from lksleep\n", error);
1577                                         *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
1578                                         status = MPR_DIAG_FAILURE;
1579                                         goto bailout;
1580                               }
1581                     }
1582                     mpr_unlock(sc);
1583           }
1584 
1585           if ((error != 0) || (ctx->error != 0)) {
1586                     device_printf(sc->mpr_dev, "Cannot bus_dmamap_load FW diag "
1587                         "buffer, %serror = %d\n", error ? "" : "callback ",
1588                         error ? error : ctx->error);
1589                     *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
1590                     status = MPR_DIAG_FAILURE;
1591                     goto bailout;
1592           }
1593 
1594           bus_dmamap_sync(sc->fw_diag_dmat, sc->fw_diag_map, BUS_DMASYNC_PREREAD);
1595 
1596           pBuffer->size = buffer_size;
1597 
1598           /*
1599            * Copy the given info to the diag buffer and post the buffer.
1600            */
1601           pBuffer->buffer_type = buffer_type;
1602           pBuffer->immediate = FALSE;
1603           if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) {
1604                     for (i = 0; i < (sizeof (pBuffer->product_specific) / 4);
1605                         i++) {
1606                               pBuffer->product_specific[i] =
1607                                   diag_register->ProductSpecific[i];
1608                     }
1609           }
1610           pBuffer->extended_type = extended_type;
1611           pBuffer->unique_id = unique_id;
1612           status = mpr_post_fw_diag_buffer(sc, pBuffer, return_code);
1613 
1614 bailout:
1615 
1616           /*
1617            * In case there was a failure, free the DMA buffer.
1618            */
1619           if (status == MPR_DIAG_FAILURE) {
1620                     if (sc->fw_diag_busaddr != 0) {
1621                               bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
1622                               sc->fw_diag_busaddr = 0;
1623                     }
1624                     if (sc->fw_diag_buffer != NULL) {
1625                               bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
1626                                   sc->fw_diag_map);
1627                               sc->fw_diag_buffer = NULL;
1628                     }
1629                     if (sc->fw_diag_dmat != NULL) {
1630                               bus_dma_tag_destroy(sc->fw_diag_dmat);
1631                               sc->fw_diag_dmat = NULL;
1632                     }
1633           }
1634 
1635           if (ctx != NULL)
1636                     kfree(ctx, M_MPR);
1637 
1638           return (status);
1639 }
1640 
1641 static int
mpr_diag_unregister(struct mpr_softc * sc,mpr_fw_diag_unregister_t * diag_unregister,uint32_t * return_code)1642 mpr_diag_unregister(struct mpr_softc *sc,
1643     mpr_fw_diag_unregister_t *diag_unregister, uint32_t *return_code)
1644 {
1645           mpr_fw_diagnostic_buffer_t    *pBuffer;
1646           uint8_t                                 i;
1647           uint32_t                      unique_id;
1648           int                                     status;
1649 
1650           unique_id = diag_unregister->UniqueId;
1651 
1652           /*
1653            * Get the current buffer and look up the unique ID.  The unique ID
1654            * should be there.
1655            */
1656           i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1657           if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1658                     *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1659                     return (MPR_DIAG_FAILURE);
1660           }
1661 
1662           pBuffer = &sc->fw_diag_buffer_list[i];
1663 
1664           /*
1665            * Try to release the buffer from FW before freeing it.  If release
1666            * fails, don't free the DMA buffer in case FW tries to access it
1667            * later.  If buffer is not owned by firmware, can't release it.
1668            */
1669           if (!pBuffer->owned_by_firmware) {
1670                     status = MPR_DIAG_SUCCESS;
1671           } else {
1672                     status = mpr_release_fw_diag_buffer(sc, pBuffer, return_code,
1673                         MPR_FW_DIAG_TYPE_UNREGISTER);
1674           }
1675 
1676           /*
1677            * At this point, return the current status no matter what happens with
1678            * the DMA buffer.
1679            */
1680           pBuffer->unique_id = MPR_FW_DIAG_INVALID_UID;
1681           if (status == MPR_DIAG_SUCCESS) {
1682                     if (sc->fw_diag_busaddr != 0) {
1683                               bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
1684                               sc->fw_diag_busaddr = 0;
1685                     }
1686                     if (sc->fw_diag_buffer != NULL) {
1687                               bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
1688                                   sc->fw_diag_map);
1689                               sc->fw_diag_buffer = NULL;
1690                     }
1691                     if (sc->fw_diag_dmat != NULL) {
1692                               bus_dma_tag_destroy(sc->fw_diag_dmat);
1693                               sc->fw_diag_dmat = NULL;
1694                     }
1695           }
1696 
1697           return (status);
1698 }
1699 
1700 static int
mpr_diag_query(struct mpr_softc * sc,mpr_fw_diag_query_t * diag_query,uint32_t * return_code)1701 mpr_diag_query(struct mpr_softc *sc, mpr_fw_diag_query_t *diag_query,
1702     uint32_t *return_code)
1703 {
1704           mpr_fw_diagnostic_buffer_t    *pBuffer;
1705           uint8_t                                 i;
1706           uint32_t                      unique_id;
1707 
1708           unique_id = diag_query->UniqueId;
1709 
1710           /*
1711            * If ID is valid, query on ID.
1712            * If ID is invalid, query on buffer type.
1713            */
1714           if (unique_id == MPR_FW_DIAG_INVALID_UID) {
1715                     i = diag_query->BufferType;
1716                     if (i >= MPI2_DIAG_BUF_TYPE_COUNT) {
1717                               *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1718                               return (MPR_DIAG_FAILURE);
1719                     }
1720           } else {
1721                     i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1722                     if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1723                               *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1724                               return (MPR_DIAG_FAILURE);
1725                     }
1726           }
1727 
1728           /*
1729            * Fill query structure with the diag buffer info.
1730            */
1731           pBuffer = &sc->fw_diag_buffer_list[i];
1732           diag_query->BufferType = pBuffer->buffer_type;
1733           diag_query->ExtendedType = pBuffer->extended_type;
1734           if (diag_query->BufferType == MPI2_DIAG_BUF_TYPE_TRACE) {
1735                     for (i = 0; i < (sizeof(diag_query->ProductSpecific) / 4);
1736                         i++) {
1737                               diag_query->ProductSpecific[i] =
1738                                   pBuffer->product_specific[i];
1739                     }
1740           }
1741           diag_query->TotalBufferSize = pBuffer->size;
1742           diag_query->DriverAddedBufferSize = 0;
1743           diag_query->UniqueId = pBuffer->unique_id;
1744           diag_query->ApplicationFlags = 0;
1745           diag_query->DiagnosticFlags = 0;
1746 
1747           /*
1748            * Set/Clear application flags
1749            */
1750           if (pBuffer->immediate) {
1751                     diag_query->ApplicationFlags &= ~MPR_FW_DIAG_FLAG_APP_OWNED;
1752           } else {
1753                     diag_query->ApplicationFlags |= MPR_FW_DIAG_FLAG_APP_OWNED;
1754           }
1755           if (pBuffer->valid_data || pBuffer->owned_by_firmware) {
1756                     diag_query->ApplicationFlags |= MPR_FW_DIAG_FLAG_BUFFER_VALID;
1757           } else {
1758                     diag_query->ApplicationFlags &= ~MPR_FW_DIAG_FLAG_BUFFER_VALID;
1759           }
1760           if (pBuffer->owned_by_firmware) {
1761                     diag_query->ApplicationFlags |=
1762                         MPR_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
1763           } else {
1764                     diag_query->ApplicationFlags &=
1765                         ~MPR_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
1766           }
1767 
1768           return (MPR_DIAG_SUCCESS);
1769 }
1770 
1771 static int
mpr_diag_read_buffer(struct mpr_softc * sc,mpr_diag_read_buffer_t * diag_read_buffer,uint8_t * ioctl_buf,uint32_t * return_code)1772 mpr_diag_read_buffer(struct mpr_softc *sc,
1773     mpr_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
1774     uint32_t *return_code)
1775 {
1776           mpr_fw_diagnostic_buffer_t    *pBuffer;
1777           uint8_t                                 i, *pData;
1778           uint32_t                      unique_id;
1779           int                                     status;
1780 
1781           unique_id = diag_read_buffer->UniqueId;
1782 
1783           /*
1784            * Get the current buffer and look up the unique ID.  The unique ID
1785            * should be there.
1786            */
1787           i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1788           if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1789                     *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1790                     return (MPR_DIAG_FAILURE);
1791           }
1792 
1793           pBuffer = &sc->fw_diag_buffer_list[i];
1794 
1795           /*
1796            * Make sure requested read is within limits
1797            */
1798           if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead >
1799               pBuffer->size) {
1800                     *return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1801                     return (MPR_DIAG_FAILURE);
1802           }
1803 
1804           /* Sync the DMA map before we copy to userland. */
1805           bus_dmamap_sync(sc->fw_diag_dmat, sc->fw_diag_map,
1806               BUS_DMASYNC_POSTREAD);
1807 
1808           /*
1809            * Copy the requested data from DMA to the diag_read_buffer.  The DMA
1810            * buffer that was allocated is one contiguous buffer.
1811            */
1812           pData = (uint8_t *)(sc->fw_diag_buffer +
1813               diag_read_buffer->StartingOffset);
1814           if (copyout(pData, ioctl_buf, diag_read_buffer->BytesToRead) != 0)
1815                     return (MPR_DIAG_FAILURE);
1816           diag_read_buffer->Status = 0;
1817 
1818           /*
1819            * Set or clear the Force Release flag.
1820            */
1821           if (pBuffer->force_release) {
1822                     diag_read_buffer->Flags |= MPR_FW_DIAG_FLAG_FORCE_RELEASE;
1823           } else {
1824                     diag_read_buffer->Flags &= ~MPR_FW_DIAG_FLAG_FORCE_RELEASE;
1825           }
1826 
1827           /*
1828            * If buffer is to be reregistered, make sure it's not already owned by
1829            * firmware first.
1830            */
1831           status = MPR_DIAG_SUCCESS;
1832           if (!pBuffer->owned_by_firmware) {
1833                     if (diag_read_buffer->Flags & MPR_FW_DIAG_FLAG_REREGISTER) {
1834                               status = mpr_post_fw_diag_buffer(sc, pBuffer,
1835                                   return_code);
1836                     }
1837           }
1838 
1839           return (status);
1840 }
1841 
1842 static int
mpr_diag_release(struct mpr_softc * sc,mpr_fw_diag_release_t * diag_release,uint32_t * return_code)1843 mpr_diag_release(struct mpr_softc *sc, mpr_fw_diag_release_t *diag_release,
1844     uint32_t *return_code)
1845 {
1846           mpr_fw_diagnostic_buffer_t    *pBuffer;
1847           uint8_t                                 i;
1848           uint32_t                      unique_id;
1849           int                                     status;
1850 
1851           unique_id = diag_release->UniqueId;
1852 
1853           /*
1854            * Get the current buffer and look up the unique ID.  The unique ID
1855            * should be there.
1856            */
1857           i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1858           if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1859                     *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1860                     return (MPR_DIAG_FAILURE);
1861           }
1862 
1863           pBuffer = &sc->fw_diag_buffer_list[i];
1864 
1865           /*
1866            * If buffer is not owned by firmware, it's already been released.
1867            */
1868           if (!pBuffer->owned_by_firmware) {
1869                     *return_code = MPR_FW_DIAG_ERROR_ALREADY_RELEASED;
1870                     return (MPR_DIAG_FAILURE);
1871           }
1872 
1873           /*
1874            * Release the buffer.
1875            */
1876           status = mpr_release_fw_diag_buffer(sc, pBuffer, return_code,
1877               MPR_FW_DIAG_TYPE_RELEASE);
1878           return (status);
1879 }
1880 
1881 static int
mpr_do_diag_action(struct mpr_softc * sc,uint32_t action,uint8_t * diag_action,uint32_t length,uint32_t * return_code)1882 mpr_do_diag_action(struct mpr_softc *sc, uint32_t action, uint8_t *diag_action,
1883     uint32_t length, uint32_t *return_code)
1884 {
1885           mpr_fw_diag_register_t                  diag_register;
1886           mpr_fw_diag_unregister_t      diag_unregister;
1887           mpr_fw_diag_query_t           diag_query;
1888           mpr_diag_read_buffer_t                  diag_read_buffer;
1889           mpr_fw_diag_release_t                   diag_release;
1890           int                                     status = MPR_DIAG_SUCCESS;
1891           uint32_t                      original_return_code;
1892 
1893           original_return_code = *return_code;
1894           *return_code = MPR_FW_DIAG_ERROR_SUCCESS;
1895 
1896           switch (action) {
1897                     case MPR_FW_DIAG_TYPE_REGISTER:
1898                               if (!length) {
1899                                         *return_code =
1900                                             MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1901                                         status = MPR_DIAG_FAILURE;
1902                                         break;
1903                               }
1904                               if (copyin(diag_action, &diag_register,
1905                                   sizeof(diag_register)) != 0)
1906                                         return (MPR_DIAG_FAILURE);
1907                               status = mpr_diag_register(sc, &diag_register,
1908                                   return_code);
1909                               break;
1910 
1911                     case MPR_FW_DIAG_TYPE_UNREGISTER:
1912                               if (length < sizeof(diag_unregister)) {
1913                                         *return_code =
1914                                             MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1915                                         status = MPR_DIAG_FAILURE;
1916                                         break;
1917                               }
1918                               if (copyin(diag_action, &diag_unregister,
1919                                   sizeof(diag_unregister)) != 0)
1920                                         return (MPR_DIAG_FAILURE);
1921                               status = mpr_diag_unregister(sc, &diag_unregister,
1922                                   return_code);
1923                               break;
1924 
1925                     case MPR_FW_DIAG_TYPE_QUERY:
1926                               if (length < sizeof (diag_query)) {
1927                                         *return_code =
1928                                             MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1929                                         status = MPR_DIAG_FAILURE;
1930                                         break;
1931                               }
1932                               if (copyin(diag_action, &diag_query, sizeof(diag_query))
1933                                   != 0)
1934                                         return (MPR_DIAG_FAILURE);
1935                               status = mpr_diag_query(sc, &diag_query, return_code);
1936                               if (status == MPR_DIAG_SUCCESS)
1937                                         if (copyout(&diag_query, diag_action,
1938                                             sizeof (diag_query)) != 0)
1939                                                   return (MPR_DIAG_FAILURE);
1940                               break;
1941 
1942                     case MPR_FW_DIAG_TYPE_READ_BUFFER:
1943                               if (copyin(diag_action, &diag_read_buffer,
1944                                   sizeof(diag_read_buffer)) != 0)
1945                                         return (MPR_DIAG_FAILURE);
1946                               if (length < diag_read_buffer.BytesToRead) {
1947                                         *return_code =
1948                                             MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1949                                         status = MPR_DIAG_FAILURE;
1950                                         break;
1951                               }
1952                               status = mpr_diag_read_buffer(sc, &diag_read_buffer,
1953                                   PTRIN(diag_read_buffer.PtrDataBuffer),
1954                                   return_code);
1955                               if (status == MPR_DIAG_SUCCESS) {
1956                                         if (copyout(&diag_read_buffer, diag_action,
1957                                             sizeof(diag_read_buffer) -
1958                                             sizeof(diag_read_buffer.PtrDataBuffer)) !=
1959                                             0)
1960                                                   return (MPR_DIAG_FAILURE);
1961                               }
1962                               break;
1963 
1964                     case MPR_FW_DIAG_TYPE_RELEASE:
1965                               if (length < sizeof(diag_release)) {
1966                                         *return_code =
1967                                             MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1968                                         status = MPR_DIAG_FAILURE;
1969                                         break;
1970                               }
1971                               if (copyin(diag_action, &diag_release,
1972                                   sizeof(diag_release)) != 0)
1973                                         return (MPR_DIAG_FAILURE);
1974                               status = mpr_diag_release(sc, &diag_release,
1975                                   return_code);
1976                               break;
1977 
1978                     default:
1979                               *return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1980                               status = MPR_DIAG_FAILURE;
1981                               break;
1982           }
1983 
1984           if ((status == MPR_DIAG_FAILURE) &&
1985               (original_return_code == MPR_FW_DIAG_NEW) &&
1986               (*return_code != MPR_FW_DIAG_ERROR_SUCCESS))
1987                     status = MPR_DIAG_SUCCESS;
1988 
1989           return (status);
1990 }
1991 
1992 static int
mpr_user_diag_action(struct mpr_softc * sc,mpr_diag_action_t * data)1993 mpr_user_diag_action(struct mpr_softc *sc, mpr_diag_action_t *data)
1994 {
1995           int                           status;
1996 
1997           /*
1998            * Only allow one diag action at one time.
1999            */
2000           if (sc->mpr_flags & MPR_FLAGS_BUSY) {
2001                     mpr_dprint(sc, MPR_USER, "%s: Only one FW diag command "
2002                         "allowed at a single time.", __func__);
2003                     return (EBUSY);
2004           }
2005           sc->mpr_flags |= MPR_FLAGS_BUSY;
2006 
2007           /*
2008            * Send diag action request
2009            */
2010           if (data->Action == MPR_FW_DIAG_TYPE_REGISTER ||
2011               data->Action == MPR_FW_DIAG_TYPE_UNREGISTER ||
2012               data->Action == MPR_FW_DIAG_TYPE_QUERY ||
2013               data->Action == MPR_FW_DIAG_TYPE_READ_BUFFER ||
2014               data->Action == MPR_FW_DIAG_TYPE_RELEASE) {
2015                     status = mpr_do_diag_action(sc, data->Action,
2016                         PTRIN(data->PtrDiagAction), data->Length,
2017                         &data->ReturnCode);
2018           } else
2019                     status = EINVAL;
2020 
2021           sc->mpr_flags &= ~MPR_FLAGS_BUSY;
2022           return (status);
2023 }
2024 
2025 /*
2026  * Copy the event recording mask and the event queue size out.  For
2027  * clarification, the event recording mask (events_to_record) is not the same
2028  * thing as the event mask (event_mask).  events_to_record has a bit set for
2029  * every event type that is to be recorded by the driver, and event_mask has a
2030  * bit cleared for every event that is allowed into the driver from the IOC.
2031  * They really have nothing to do with each other.
2032  */
2033 static void
mpr_user_event_query(struct mpr_softc * sc,mpr_event_query_t * data)2034 mpr_user_event_query(struct mpr_softc *sc, mpr_event_query_t *data)
2035 {
2036           uint8_t   i;
2037 
2038           mpr_lock(sc);
2039           data->Entries = MPR_EVENT_QUEUE_SIZE;
2040 
2041           for (i = 0; i < 4; i++) {
2042                     data->Types[i] = sc->events_to_record[i];
2043           }
2044           mpr_unlock(sc);
2045 }
2046 
2047 /*
2048  * Set the driver's event mask according to what's been given.  See
2049  * mpr_user_event_query for explanation of the event recording mask and the IOC
2050  * event mask.  It's the app's responsibility to enable event logging by setting
2051  * the bits in events_to_record.  Initially, no events will be logged.
2052  */
2053 static void
mpr_user_event_enable(struct mpr_softc * sc,mpr_event_enable_t * data)2054 mpr_user_event_enable(struct mpr_softc *sc, mpr_event_enable_t *data)
2055 {
2056           uint8_t   i;
2057 
2058           mpr_lock(sc);
2059           for (i = 0; i < 4; i++) {
2060                     sc->events_to_record[i] = data->Types[i];
2061           }
2062           mpr_unlock(sc);
2063 }
2064 
2065 /*
2066  * Copy out the events that have been recorded, up to the max events allowed.
2067  */
2068 static int
mpr_user_event_report(struct mpr_softc * sc,mpr_event_report_t * data)2069 mpr_user_event_report(struct mpr_softc *sc, mpr_event_report_t *data)
2070 {
2071           int                 status = 0;
2072           uint32_t  size;
2073 
2074           mpr_lock(sc);
2075           size = data->Size;
2076           if ((size >= sizeof(sc->recorded_events)) && (status == 0)) {
2077                     mpr_unlock(sc);
2078                     if (copyout((void *)sc->recorded_events,
2079                         PTRIN(data->PtrEvents), size) != 0)
2080                               status = EFAULT;
2081                     mpr_lock(sc);
2082           } else {
2083                     /*
2084                      * data->Size value is not large enough to copy event data.
2085                      */
2086                     status = EFAULT;
2087           }
2088 
2089           /*
2090            * Change size value to match the number of bytes that were copied.
2091            */
2092           if (status == 0)
2093                     data->Size = sizeof(sc->recorded_events);
2094           mpr_unlock(sc);
2095 
2096           return (status);
2097 }
2098 
2099 /*
2100  * Record events into the driver from the IOC if they are not masked.
2101  */
2102 void
mprsas_record_event(struct mpr_softc * sc,MPI2_EVENT_NOTIFICATION_REPLY * event_reply)2103 mprsas_record_event(struct mpr_softc *sc,
2104     MPI2_EVENT_NOTIFICATION_REPLY *event_reply)
2105 {
2106           uint32_t  event;
2107           int                 i, j;
2108           uint16_t  event_data_len;
2109           boolean_t sendAEN = FALSE;
2110 
2111           event = event_reply->Event;
2112 
2113           /*
2114            * Generate a system event to let anyone who cares know that a
2115            * LOG_ENTRY_ADDED event has occurred.  This is sent no matter what the
2116            * event mask is set to.
2117            */
2118           if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
2119                     sendAEN = TRUE;
2120           }
2121 
2122           /*
2123            * Record the event only if its corresponding bit is set in
2124            * events_to_record.  event_index is the index into recorded_events and
2125            * event_number is the overall number of an event being recorded since
2126            * start-of-day.  event_index will roll over; event_number will never
2127            * roll over.
2128            */
2129           i = (uint8_t)(event / 32);
2130           j = (uint8_t)(event % 32);
2131           if ((i < 4) && ((1 << j) & sc->events_to_record[i])) {
2132                     i = sc->event_index;
2133                     sc->recorded_events[i].Type = event;
2134                     sc->recorded_events[i].Number = ++sc->event_number;
2135                     bzero(sc->recorded_events[i].Data, MPR_MAX_EVENT_DATA_LENGTH *
2136                         4);
2137                     event_data_len = event_reply->EventDataLength;
2138 
2139                     if (event_data_len > 0) {
2140                               /*
2141                                * Limit data to size in m_event entry
2142                                */
2143                               if (event_data_len > MPR_MAX_EVENT_DATA_LENGTH) {
2144                                         event_data_len = MPR_MAX_EVENT_DATA_LENGTH;
2145                               }
2146                               for (j = 0; j < event_data_len; j++) {
2147                                         sc->recorded_events[i].Data[j] =
2148                                             event_reply->EventData[j];
2149                               }
2150 
2151                               /*
2152                                * check for index wrap-around
2153                                */
2154                               if (++i == MPR_EVENT_QUEUE_SIZE) {
2155                                         i = 0;
2156                               }
2157                               sc->event_index = (uint8_t)i;
2158 
2159                               /*
2160                                * Set flag to send the event.
2161                                */
2162                               sendAEN = TRUE;
2163                     }
2164           }
2165 
2166           /*
2167            * Generate a system event if flag is set to let anyone who cares know
2168            * that an event has occurred.
2169            */
2170           if (sendAEN) {
2171 //SLM-how to send a system event (see kqueue, kevent)
2172 //                  (void) ddi_log_sysevent(mpt->m_dip, DDI_VENDOR_LSI, "MPT_SAS",
2173 //                      "SAS", NULL, NULL, DDI_NOSLEEP);
2174           }
2175 }
2176 
2177 static int
mpr_user_reg_access(struct mpr_softc * sc,mpr_reg_access_t * data)2178 mpr_user_reg_access(struct mpr_softc *sc, mpr_reg_access_t *data)
2179 {
2180           int       status = 0;
2181 
2182           switch (data->Command) {
2183                     /*
2184                      * IO access is not supported.
2185                      */
2186                     case REG_IO_READ:
2187                     case REG_IO_WRITE:
2188                               mpr_dprint(sc, MPR_USER, "IO access is not supported. "
2189                                   "Use memory access.");
2190                               status = EINVAL;
2191                               break;
2192 
2193                     case REG_MEM_READ:
2194                               data->RegData = mpr_regread(sc, data->RegOffset);
2195                               break;
2196 
2197                     case REG_MEM_WRITE:
2198                               mpr_regwrite(sc, data->RegOffset, data->RegData);
2199                               break;
2200 
2201                     default:
2202                               status = EINVAL;
2203                               break;
2204           }
2205 
2206           return (status);
2207 }
2208 
2209 static int
mpr_user_btdh(struct mpr_softc * sc,mpr_btdh_mapping_t * data)2210 mpr_user_btdh(struct mpr_softc *sc, mpr_btdh_mapping_t *data)
2211 {
2212           uint8_t             bt2dh = FALSE;
2213           uint8_t             dh2bt = FALSE;
2214           uint16_t  dev_handle, bus, target;
2215 
2216           bus = data->Bus;
2217           target = data->TargetID;
2218           dev_handle = data->DevHandle;
2219 
2220           /*
2221            * When DevHandle is 0xFFFF and Bus/Target are not 0xFFFF, use Bus/
2222            * Target to get DevHandle.  When Bus/Target are 0xFFFF and DevHandle is
2223            * not 0xFFFF, use DevHandle to get Bus/Target.  Anything else is
2224            * invalid.
2225            */
2226           if ((bus == 0xFFFF) && (target == 0xFFFF) && (dev_handle != 0xFFFF))
2227                     dh2bt = TRUE;
2228           if ((dev_handle == 0xFFFF) && (bus != 0xFFFF) && (target != 0xFFFF))
2229                     bt2dh = TRUE;
2230           if (!dh2bt && !bt2dh)
2231                     return (EINVAL);
2232 
2233           /*
2234            * Only handle bus of 0.  Make sure target is within range.
2235            */
2236           if (bt2dh) {
2237                     if (bus != 0)
2238                               return (EINVAL);
2239 
2240                     if (target > sc->max_devices) {
2241                               mpr_dprint(sc, MPR_XINFO, "Target ID is out of range "
2242                                  "for Bus/Target to DevHandle mapping.");
2243                               return (EINVAL);
2244                     }
2245                     dev_handle = sc->mapping_table[target].dev_handle;
2246                     if (dev_handle)
2247                               data->DevHandle = dev_handle;
2248           } else {
2249                     bus = 0;
2250                     target = mpr_mapping_get_tid_from_handle(sc, dev_handle);
2251                     data->Bus = bus;
2252                     data->TargetID = target;
2253           }
2254 
2255           return (0);
2256 }
2257 
2258 static int
mpr_ioctl(struct cdev * dev,u_long cmd,void * arg,int flag)2259 mpr_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag)
2260 {
2261           struct mpr_softc *sc;
2262           struct mpr_cfg_page_req *page_req;
2263           struct mpr_ext_cfg_page_req *ext_page_req;
2264           void *mpr_page;
2265           int error, msleep_ret;
2266 
2267           mpr_page = NULL;
2268           sc = dev->si_drv1;
2269           page_req = (void *)arg;
2270           ext_page_req = (void *)arg;
2271 
2272           switch (cmd) {
2273           case MPRIO_READ_CFG_HEADER:
2274                     mpr_lock(sc);
2275                     error = mpr_user_read_cfg_header(sc, page_req);
2276                     mpr_unlock(sc);
2277                     break;
2278           case MPRIO_READ_CFG_PAGE:
2279                     mpr_page = kmalloc(page_req->len, M_MPRUSER, M_WAITOK | M_ZERO);
2280                     error = copyin(page_req->buf, mpr_page,
2281                         sizeof(MPI2_CONFIG_PAGE_HEADER));
2282                     if (error)
2283                               break;
2284                     mpr_lock(sc);
2285                     error = mpr_user_read_cfg_page(sc, page_req, mpr_page);
2286                     mpr_unlock(sc);
2287                     if (error)
2288                               break;
2289                     error = copyout(mpr_page, page_req->buf, page_req->len);
2290                     break;
2291           case MPRIO_READ_EXT_CFG_HEADER:
2292                     mpr_lock(sc);
2293                     error = mpr_user_read_extcfg_header(sc, ext_page_req);
2294                     mpr_unlock(sc);
2295                     break;
2296           case MPRIO_READ_EXT_CFG_PAGE:
2297                     mpr_page = kmalloc(ext_page_req->len, M_MPRUSER,
2298                         M_WAITOK | M_ZERO);
2299                     error = copyin(ext_page_req->buf, mpr_page,
2300                         sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
2301                     if (error)
2302                               break;
2303                     mpr_lock(sc);
2304                     error = mpr_user_read_extcfg_page(sc, ext_page_req, mpr_page);
2305                     mpr_unlock(sc);
2306                     if (error)
2307                               break;
2308                     error = copyout(mpr_page, ext_page_req->buf, ext_page_req->len);
2309                     break;
2310           case MPRIO_WRITE_CFG_PAGE:
2311                     mpr_page = kmalloc(page_req->len, M_MPRUSER, M_WAITOK|M_ZERO);
2312                     error = copyin(page_req->buf, mpr_page, page_req->len);
2313                     if (error)
2314                               break;
2315                     mpr_lock(sc);
2316                     error = mpr_user_write_cfg_page(sc, page_req, mpr_page);
2317                     mpr_unlock(sc);
2318                     break;
2319           case MPRIO_MPR_COMMAND:
2320                     error = mpr_user_command(sc, (struct mpr_usr_command *)arg);
2321                     break;
2322           case MPTIOCTL_PASS_THRU:
2323                     /*
2324                      * The user has requested to pass through a command to be
2325                      * executed by the MPT firmware.  Call our routine which does
2326                      * this.  Only allow one passthru IOCTL at one time.
2327                      */
2328                     error = mpr_user_pass_thru(sc, (mpr_pass_thru_t *)arg);
2329                     break;
2330           case MPTIOCTL_GET_ADAPTER_DATA:
2331                     /*
2332                      * The user has requested to read adapter data.  Call our
2333                      * routine which does this.
2334                      */
2335                     error = 0;
2336                     mpr_user_get_adapter_data(sc, (mpr_adapter_data_t *)arg);
2337                     break;
2338           case MPTIOCTL_GET_PCI_INFO:
2339                     /*
2340                      * The user has requested to read pci info.  Call
2341                      * our routine which does this.
2342                      */
2343                     mpr_lock(sc);
2344                     error = 0;
2345                     mpr_user_read_pci_info(sc, (mpr_pci_info_t *)arg);
2346                     mpr_unlock(sc);
2347                     break;
2348           case MPTIOCTL_RESET_ADAPTER:
2349                     mpr_lock(sc);
2350                     sc->port_enable_complete = 0;
2351                     uint32_t reinit_start = time_uptime;
2352                     error = mpr_reinit(sc);
2353                     /* Sleep for 300 second. */
2354                     msleep_ret = lksleep(&sc->port_enable_complete, &sc->mpr_lock,
2355                         0, "mpr_porten", 300 * hz);
2356                     mpr_unlock(sc);
2357                     if (msleep_ret)
2358                               kprintf("Port Enable did not complete after Diag "
2359                                   "Reset lksleep error %d.\n", msleep_ret);
2360                     else
2361                               mpr_dprint(sc, MPR_USER, "Hard Reset with Port Enable "
2362                                   "completed in %d seconds.\n",
2363                                   (uint32_t)(time_uptime - reinit_start));
2364                     break;
2365           case MPTIOCTL_DIAG_ACTION:
2366                     /*
2367                      * The user has done a diag buffer action.  Call our routine
2368                      * which does this.  Only allow one diag action at one time.
2369                      */
2370                     mpr_lock(sc);
2371                     error = mpr_user_diag_action(sc, (mpr_diag_action_t *)arg);
2372                     mpr_unlock(sc);
2373                     break;
2374           case MPTIOCTL_EVENT_QUERY:
2375                     /*
2376                      * The user has done an event query. Call our routine which does
2377                      * this.
2378                      */
2379                     error = 0;
2380                     mpr_user_event_query(sc, (mpr_event_query_t *)arg);
2381                     break;
2382           case MPTIOCTL_EVENT_ENABLE:
2383                     /*
2384                      * The user has done an event enable. Call our routine which
2385                      * does this.
2386                      */
2387                     error = 0;
2388                     mpr_user_event_enable(sc, (mpr_event_enable_t *)arg);
2389                     break;
2390           case MPTIOCTL_EVENT_REPORT:
2391                     /*
2392                      * The user has done an event report. Call our routine which
2393                      * does this.
2394                      */
2395                     error = mpr_user_event_report(sc, (mpr_event_report_t *)arg);
2396                     break;
2397           case MPTIOCTL_REG_ACCESS:
2398                     /*
2399                      * The user has requested register access.  Call our routine
2400                      * which does this.
2401                      */
2402                     mpr_lock(sc);
2403                     error = mpr_user_reg_access(sc, (mpr_reg_access_t *)arg);
2404                     mpr_unlock(sc);
2405                     break;
2406           case MPTIOCTL_BTDH_MAPPING:
2407                     /*
2408                      * The user has requested to translate a bus/target to a
2409                      * DevHandle or a DevHandle to a bus/target.  Call our routine
2410                      * which does this.
2411                      */
2412                     error = mpr_user_btdh(sc, (mpr_btdh_mapping_t *)arg);
2413                     break;
2414           default:
2415                     error = ENOIOCTL;
2416                     break;
2417           }
2418 
2419           if (mpr_page != NULL)
2420                     kfree(mpr_page, M_MPRUSER);
2421 
2422           return (error);
2423 }
2424 
2425 #ifdef COMPAT_FREEBSD32
2426 
2427 struct mpr_cfg_page_req32 {
2428           MPI2_CONFIG_PAGE_HEADER header;
2429           uint32_t page_address;
2430           uint32_t buf;
2431           int       len;
2432           uint16_t ioc_status;
2433 };
2434 
2435 struct mpr_ext_cfg_page_req32 {
2436           MPI2_CONFIG_EXTENDED_PAGE_HEADER header;
2437           uint32_t page_address;
2438           uint32_t buf;
2439           int       len;
2440           uint16_t ioc_status;
2441 };
2442 
2443 struct mpr_raid_action32 {
2444           uint8_t action;
2445           uint8_t volume_bus;
2446           uint8_t volume_id;
2447           uint8_t phys_disk_num;
2448           uint32_t action_data_word;
2449           uint32_t buf;
2450           int len;
2451           uint32_t volume_status;
2452           uint32_t action_data[4];
2453           uint16_t action_status;
2454           uint16_t ioc_status;
2455           uint8_t write;
2456 };
2457 
2458 struct mpr_usr_command32 {
2459           uint32_t req;
2460           uint32_t req_len;
2461           uint32_t rpl;
2462           uint32_t rpl_len;
2463           uint32_t buf;
2464           int len;
2465           uint32_t flags;
2466 };
2467 
2468 #define   MPRIO_READ_CFG_HEADER32       _IOWR('M', 200, struct mpr_cfg_page_req32)
2469 #define   MPRIO_READ_CFG_PAGE32         _IOWR('M', 201, struct mpr_cfg_page_req32)
2470 #define   MPRIO_READ_EXT_CFG_HEADER32 _IOWR('M', 202, struct mpr_ext_cfg_page_req32)
2471 #define   MPRIO_READ_EXT_CFG_PAGE32 _IOWR('M', 203, struct mpr_ext_cfg_page_req32)
2472 #define   MPRIO_WRITE_CFG_PAGE32        _IOWR('M', 204, struct mpr_cfg_page_req32)
2473 #define   MPRIO_RAID_ACTION32 _IOWR('M', 205, struct mpr_raid_action32)
2474 #define   MPRIO_MPR_COMMAND32 _IOWR('M', 210, struct mpr_usr_command32)
2475 
2476 static int
mpr_ioctl32(struct cdev * dev,u_long cmd32,void * _arg,int flag,struct thread * td)2477 mpr_ioctl32(struct cdev *dev, u_long cmd32, void *_arg, int flag,
2478     struct thread *td)
2479 {
2480           struct mpr_cfg_page_req32 *page32 = _arg;
2481           struct mpr_ext_cfg_page_req32 *ext32 = _arg;
2482           struct mpr_raid_action32 *raid32 = _arg;
2483           struct mpr_usr_command32 *user32 = _arg;
2484           union {
2485                     struct mpr_cfg_page_req page;
2486                     struct mpr_ext_cfg_page_req ext;
2487                     struct mpr_raid_action raid;
2488                     struct mpr_usr_command user;
2489           } arg;
2490           u_long cmd;
2491           int error;
2492 
2493           switch (cmd32) {
2494           case MPRIO_READ_CFG_HEADER32:
2495           case MPRIO_READ_CFG_PAGE32:
2496           case MPRIO_WRITE_CFG_PAGE32:
2497                     if (cmd32 == MPRIO_READ_CFG_HEADER32)
2498                               cmd = MPRIO_READ_CFG_HEADER;
2499                     else if (cmd32 == MPRIO_READ_CFG_PAGE32)
2500                               cmd = MPRIO_READ_CFG_PAGE;
2501                     else
2502                               cmd = MPRIO_WRITE_CFG_PAGE;
2503                     CP(*page32, arg.page, header);
2504                     CP(*page32, arg.page, page_address);
2505                     PTRIN_CP(*page32, arg.page, buf);
2506                     CP(*page32, arg.page, len);
2507                     CP(*page32, arg.page, ioc_status);
2508                     break;
2509 
2510           case MPRIO_READ_EXT_CFG_HEADER32:
2511           case MPRIO_READ_EXT_CFG_PAGE32:
2512                     if (cmd32 == MPRIO_READ_EXT_CFG_HEADER32)
2513                               cmd = MPRIO_READ_EXT_CFG_HEADER;
2514                     else
2515                               cmd = MPRIO_READ_EXT_CFG_PAGE;
2516                     CP(*ext32, arg.ext, header);
2517                     CP(*ext32, arg.ext, page_address);
2518                     PTRIN_CP(*ext32, arg.ext, buf);
2519                     CP(*ext32, arg.ext, len);
2520                     CP(*ext32, arg.ext, ioc_status);
2521                     break;
2522 
2523           case MPRIO_RAID_ACTION32:
2524                     cmd = MPRIO_RAID_ACTION;
2525                     CP(*raid32, arg.raid, action);
2526                     CP(*raid32, arg.raid, volume_bus);
2527                     CP(*raid32, arg.raid, volume_id);
2528                     CP(*raid32, arg.raid, phys_disk_num);
2529                     CP(*raid32, arg.raid, action_data_word);
2530                     PTRIN_CP(*raid32, arg.raid, buf);
2531                     CP(*raid32, arg.raid, len);
2532                     CP(*raid32, arg.raid, volume_status);
2533                     bcopy(raid32->action_data, arg.raid.action_data,
2534                         sizeof arg.raid.action_data);
2535                     CP(*raid32, arg.raid, ioc_status);
2536                     CP(*raid32, arg.raid, write);
2537                     break;
2538 
2539           case MPRIO_MPR_COMMAND32:
2540                     cmd = MPRIO_MPR_COMMAND;
2541                     PTRIN_CP(*user32, arg.user, req);
2542                     CP(*user32, arg.user, req_len);
2543                     PTRIN_CP(*user32, arg.user, rpl);
2544                     CP(*user32, arg.user, rpl_len);
2545                     PTRIN_CP(*user32, arg.user, buf);
2546                     CP(*user32, arg.user, len);
2547                     CP(*user32, arg.user, flags);
2548                     break;
2549           default:
2550                     return (ENOIOCTL);
2551           }
2552 
2553           error = mpr_ioctl(dev, cmd, &arg, flag, td);
2554           if (error == 0 && (cmd32 & IOC_OUT) != 0) {
2555                     switch (cmd32) {
2556                     case MPRIO_READ_CFG_HEADER32:
2557                     case MPRIO_READ_CFG_PAGE32:
2558                     case MPRIO_WRITE_CFG_PAGE32:
2559                               CP(arg.page, *page32, header);
2560                               CP(arg.page, *page32, page_address);
2561                               PTROUT_CP(arg.page, *page32, buf);
2562                               CP(arg.page, *page32, len);
2563                               CP(arg.page, *page32, ioc_status);
2564                               break;
2565 
2566                     case MPRIO_READ_EXT_CFG_HEADER32:
2567                     case MPRIO_READ_EXT_CFG_PAGE32:
2568                               CP(arg.ext, *ext32, header);
2569                               CP(arg.ext, *ext32, page_address);
2570                               PTROUT_CP(arg.ext, *ext32, buf);
2571                               CP(arg.ext, *ext32, len);
2572                               CP(arg.ext, *ext32, ioc_status);
2573                               break;
2574 
2575                     case MPRIO_RAID_ACTION32:
2576                               CP(arg.raid, *raid32, action);
2577                               CP(arg.raid, *raid32, volume_bus);
2578                               CP(arg.raid, *raid32, volume_id);
2579                               CP(arg.raid, *raid32, phys_disk_num);
2580                               CP(arg.raid, *raid32, action_data_word);
2581                               PTROUT_CP(arg.raid, *raid32, buf);
2582                               CP(arg.raid, *raid32, len);
2583                               CP(arg.raid, *raid32, volume_status);
2584                               bcopy(arg.raid.action_data, raid32->action_data,
2585                                   sizeof arg.raid.action_data);
2586                               CP(arg.raid, *raid32, ioc_status);
2587                               CP(arg.raid, *raid32, write);
2588                               break;
2589 
2590                     case MPRIO_MPR_COMMAND32:
2591                               PTROUT_CP(arg.user, *user32, req);
2592                               CP(arg.user, *user32, req_len);
2593                               PTROUT_CP(arg.user, *user32, rpl);
2594                               CP(arg.user, *user32, rpl_len);
2595                               PTROUT_CP(arg.user, *user32, buf);
2596                               CP(arg.user, *user32, len);
2597                               CP(arg.user, *user32, flags);
2598                               break;
2599                     }
2600           }
2601 
2602           return (error);
2603 }
2604 #endif /* COMPAT_FREEBSD32 */
2605 
2606 static int
mpr_ioctl_devsw(struct dev_ioctl_args * ap)2607 mpr_ioctl_devsw(struct dev_ioctl_args *ap)
2608 {
2609           cdev_t dev = ap->a_head.a_dev;
2610           u_long cmd = ap->a_cmd;
2611           int flag = ap->a_fflag;
2612           caddr_t arg = ap->a_data;
2613 
2614 #ifdef COMPAT_FREEBSD32
2615           if (SV_CURPROC_FLAG(SV_ILP32))
2616                     return (mpr_ioctl32(dev, com, arg, flag, td));
2617 #endif
2618           return (mpr_ioctl(dev, cmd, arg, flag));
2619 }
2620