2 * Copyright (c) 2014, LSI Corp.
5 * Support: freebsdraid@lsi.com
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of the <ORGANIZATION> nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 * The views and conclusions contained in the software and documentation
35 * are those of the authors and should not be interpreted as representing
36 * official policies,either expressed or implied, of the FreeBSD Project.
38 * Send feedback to: <megaraidfbsd@lsi.com>
39 * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
40 * ATTN: MegaRaid FreeBSD
42 * $FreeBSD: head/sys/dev/mrsas/mrsas_ioctl.c 265555 2014-05-07 16:16:49Z ambrisko $
45 #include <dev/raid/mrsas/mrsas.h>
46 #include <dev/raid/mrsas/mrsas_ioctl.h>
51 int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc);
52 int mrsas_passthru(struct mrsas_softc *sc, void *arg);
53 void mrsas_free_ioc_cmd(struct mrsas_softc *sc);
54 void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
55 void mrsas_dump_dcmd(struct mrsas_softc *sc, struct mrsas_dcmd_frame* dcmd);
56 void mrsas_dump_ioctl(struct mrsas_softc *sc, struct mrsas_iocpacket *user_ioc);
57 void * mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
58 static int mrsas_create_frame_pool(struct mrsas_softc *sc);
59 static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
60 int nsegs, int error);
62 extern struct mrsas_mfi_cmd* mrsas_get_mfi_cmd(struct mrsas_softc *sc);
63 extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd);
64 extern int mrsas_issue_blocked_cmd(struct mrsas_softc *sc,
65 struct mrsas_mfi_cmd *cmd);
69 * mrsas_dump_ioctl: Print debug output for DCMDs
70 * input: Adapter instance soft state
71 * DCMD frame structure
73 * This function is called from mrsas_passthru() to print out debug information
74 * in the handling and routing of DCMD commands.
76 void mrsas_dump_dcmd( struct mrsas_softc *sc, struct mrsas_dcmd_frame* dcmd )
80 device_printf(sc->mrsas_dev, "dcmd->cmd: 0x%02hhx\n", dcmd->cmd);
81 device_printf(sc->mrsas_dev, "dcmd->cmd_status: 0x%02hhx\n", dcmd->cmd_status);
82 device_printf(sc->mrsas_dev, "dcmd->sge_count: 0x%02hhx\n", dcmd->sge_count);
83 device_printf(sc->mrsas_dev, "dcmd->context: 0x%08x\n", dcmd->context);
84 device_printf(sc->mrsas_dev, "dcmd->flags: 0x%04hx\n", dcmd->flags);
85 device_printf(sc->mrsas_dev, "dcmd->timeout: 0x%04hx\n", dcmd->timeout);
86 device_printf(sc->mrsas_dev, "dcmd->data_xfer_len: 0x%08x\n", dcmd->data_xfer_len);
87 device_printf(sc->mrsas_dev, "dcmd->opcode: 0x%08x\n", dcmd->opcode);
88 device_printf(sc->mrsas_dev, "dcmd->mbox.w[0]: 0x%08x\n", dcmd->mbox.w[0]);
89 device_printf(sc->mrsas_dev, "dcmd->mbox.w[1]: 0x%08x\n", dcmd->mbox.w[1]);
90 device_printf(sc->mrsas_dev, "dcmd->mbox.w[2]: 0x%08x\n", dcmd->mbox.w[2]);
91 for (i=0; i< MIN(MAX_IOCTL_SGE, dcmd->sge_count); i++) {
92 device_printf(sc->mrsas_dev, "sgl[%02d]\n", i);
93 device_printf(sc->mrsas_dev, " sge32[%02d].phys_addr: 0x%08x\n",
94 i, dcmd->sgl.sge32[i].phys_addr);
95 device_printf(sc->mrsas_dev, " sge32[%02d].length: 0x%08x\n",
96 i, dcmd->sgl.sge32[i].length);
97 device_printf(sc->mrsas_dev, " sge64[%02d].phys_addr: 0x%08llx\n",
98 i, (unsigned long long) dcmd->sgl.sge64[i].phys_addr);
99 device_printf(sc->mrsas_dev, " sge64[%02d].length: 0x%08x\n",
100 i, dcmd->sgl.sge64[i].length);
105 * mrsas_dump_ioctl: Print debug output for ioctl
106 * input: Adapter instance soft state
107 * iocpacket structure
109 * This function is called from mrsas_passthru() to print out debug information
110 * in the handling and routing of ioctl commands.
112 void mrsas_dump_ioctl(struct mrsas_softc *sc, struct mrsas_iocpacket *user_ioc)
114 union mrsas_frame *in_cmd = (union mrsas_frame *) &(user_ioc->frame.raw);
115 struct mrsas_dcmd_frame* dcmd = (struct mrsas_dcmd_frame *) &(in_cmd->dcmd);
118 device_printf(sc->mrsas_dev,
119 "====== In %s() ======================================\n", __func__);
120 device_printf(sc->mrsas_dev, "host_no: 0x%04hx\n", user_ioc->host_no);
121 device_printf(sc->mrsas_dev, " __pad1: 0x%04hx\n", user_ioc->__pad1);
122 device_printf(sc->mrsas_dev, "sgl_off: 0x%08x\n", user_ioc->sgl_off);
123 device_printf(sc->mrsas_dev, "sge_count: 0x%08x\n", user_ioc->sge_count);
124 device_printf(sc->mrsas_dev, "sense_off: 0x%08x\n", user_ioc->sense_off);
125 device_printf(sc->mrsas_dev, "sense_len: 0x%08x\n", user_ioc->sense_len);
127 mrsas_dump_dcmd(sc, dcmd);
129 for (i=0; i< MIN(MAX_IOCTL_SGE, user_ioc->sge_count); i++) {
130 device_printf(sc->mrsas_dev, "sge[%02d]\n", i);
131 device_printf(sc->mrsas_dev,
132 " iov_base: %p\n", user_ioc->sgl[i].iov_base);
133 device_printf(sc->mrsas_dev, " iov_len: %p\n",
134 (void*)user_ioc->sgl[i].iov_len);
136 device_printf(sc->mrsas_dev,
137 "==================================================================\n");
141 * mrsas_passthru: Handle pass-through commands
142 * input: Adapter instance soft state
145 * This function is called from mrsas_ioctl() to handle pass-through and
146 * ioctl commands to Firmware.
148 int mrsas_passthru( struct mrsas_softc *sc, void *arg )
150 struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg;
151 union mrsas_frame *in_cmd = (union mrsas_frame *) &(user_ioc->frame.raw);
152 struct mrsas_mfi_cmd *cmd = NULL;
153 bus_dma_tag_t ioctl_data_tag[MAX_IOCTL_SGE];
154 bus_dmamap_t ioctl_data_dmamap[MAX_IOCTL_SGE];
155 void *ioctl_data_mem[MAX_IOCTL_SGE]; // ioctl data virtual addr
156 bus_addr_t ioctl_data_phys_addr[MAX_IOCTL_SGE]; // ioctl data phys addr
157 bus_dma_tag_t ioctl_sense_tag = 0;
158 bus_dmamap_t ioctl_sense_dmamap = 0;
159 void *ioctl_sense_mem = NULL;
160 bus_addr_t ioctl_sense_phys_addr = 0;
161 int i, adapter, ioctl_data_size, ioctl_sense_size, ret=0;
162 struct mrsas_sge32 *kern_sge32;
163 unsigned long *sense_ptr;
165 /* For debug - uncomment the following line for debug output */
166 //mrsas_dump_ioctl(sc, user_ioc);
169 * Check for NOP from MegaCli... MegaCli can issue a DCMD of 0. In this
170 * case do nothing and return 0 to it as status.
172 if (in_cmd->dcmd.opcode == 0) {
173 device_printf(sc->mrsas_dev, "In %s() Got a NOP\n", __func__);
174 user_ioc->frame.hdr.cmd_status = MFI_STAT_OK;
178 /* Validate host_no */
179 adapter = user_ioc->host_no;
180 if (adapter != device_get_unit(sc->mrsas_dev)) {
181 device_printf(sc->mrsas_dev, "In %s() IOCTL not for me!\n", __func__);
185 /* Validate SGL length */
186 if (user_ioc->sge_count > MAX_IOCTL_SGE) {
187 device_printf(sc->mrsas_dev, "In %s() SGL is too long (%d > 8).\n",
188 __func__, user_ioc->sge_count);
193 cmd = mrsas_get_mfi_cmd(sc);
195 device_printf(sc->mrsas_dev, "Failed to get a free cmd for IOCTL\n");
200 * User's IOCTL packet has 2 frames (maximum). Copy those two
201 * frames into our cmd's frames. cmd->frame's context will get
202 * overwritten when we copy from user's frames. So set that value
205 memcpy(cmd->frame, user_ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
206 cmd->frame->hdr.context = cmd->index;
207 cmd->frame->hdr.pad_0 = 0;
208 cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 |
212 * The management interface between applications and the fw uses
213 * MFI frames. E.g, RAID configuration changes, LD property changes
214 * etc are accomplishes through different kinds of MFI frames. The
215 * driver needs to care only about substituting user buffers with
216 * kernel buffers in SGLs. The location of SGL is embedded in the
217 * struct iocpacket itself.
219 kern_sge32 = (struct mrsas_sge32 *)
220 ((unsigned long)cmd->frame + user_ioc->sgl_off);
223 * For each user buffer, create a mirror buffer and copy in
225 for (i=0; i < user_ioc->sge_count; i++) {
226 if (!user_ioc->sgl[i].iov_len)
228 ioctl_data_size = user_ioc->sgl[i].iov_len;
229 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
230 1, 0, // algnmnt, boundary
231 BUS_SPACE_MAXADDR_32BIT,// lowaddr
232 BUS_SPACE_MAXADDR, // highaddr
233 ioctl_data_size, // maxsize
235 ioctl_data_size, // maxsegsize
236 BUS_DMA_ALLOCNOW, // flags
237 &ioctl_data_tag[i])) {
238 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n");
241 if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i],
242 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) {
243 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
246 if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i],
247 ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb,
248 &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) {
249 device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n");
253 /* Save the physical address and length */
254 kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i];
255 kern_sge32[i].length = user_ioc->sgl[i].iov_len;
257 /* Copy in data from user space */
258 ret = copyin(user_ioc->sgl[i].iov_base, ioctl_data_mem[i],
259 user_ioc->sgl[i].iov_len);
261 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n");
266 ioctl_sense_size = user_ioc->sense_len;
267 if (user_ioc->sense_len) {
268 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
269 1, 0, // algnmnt, boundary
270 BUS_SPACE_MAXADDR_32BIT,// lowaddr
271 BUS_SPACE_MAXADDR, // highaddr
272 ioctl_sense_size, // maxsize
274 ioctl_sense_size, // maxsegsize
275 BUS_DMA_ALLOCNOW, // flags
277 device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense tag\n");
280 if (bus_dmamem_alloc(ioctl_sense_tag, (void **)&ioctl_sense_mem,
281 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_sense_dmamap)) {
282 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
285 if (bus_dmamap_load(ioctl_sense_tag, ioctl_sense_dmamap,
286 ioctl_sense_mem, ioctl_sense_size, mrsas_alloc_cb,
287 &ioctl_sense_phys_addr, BUS_DMA_NOWAIT)) {
288 device_printf(sc->mrsas_dev, "Cannot load ioctl sense mem\n");
292 (unsigned long *)((unsigned long)cmd->frame + user_ioc->sense_off);
293 *sense_ptr = ioctl_sense_phys_addr;
297 * Set the sync_cmd flag so that the ISR knows not to complete this
298 * cmd to the SCSI mid-layer
301 mrsas_issue_blocked_cmd(sc, cmd);
305 * copy out the kernel buffers to user buffers
307 for (i = 0; i < user_ioc->sge_count; i++) {
308 ret = copyout(ioctl_data_mem[i], user_ioc->sgl[i].iov_base,
309 user_ioc->sgl[i].iov_len);
311 device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n");
319 if (user_ioc->sense_len) {
321 * sense_buff points to the location that has the user
322 * sense buffer address
324 sense_ptr = (unsigned long *) ((unsigned long)user_ioc->frame.raw +
325 user_ioc->sense_off);
326 ret = copyout(ioctl_sense_mem, (unsigned long*)*sense_ptr,
327 user_ioc->sense_len);
329 device_printf(sc->mrsas_dev, "IOCTL sense copyout failed!\n");
335 * Return command status to user space
337 memcpy(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status,
342 * Release sense buffer
344 if (ioctl_sense_phys_addr)
345 bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap);
347 bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap);
349 bus_dma_tag_destroy(ioctl_sense_tag);
352 * Release data buffers
354 for (i = 0; i < user_ioc->sge_count; i++) {
355 if (!user_ioc->sgl[i].iov_len)
357 if (ioctl_data_phys_addr[i])
358 bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]);
359 if (ioctl_data_mem[i] != NULL)
360 bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i],
361 ioctl_data_dmamap[i]);
362 if (ioctl_data_tag[i] != NULL)
363 bus_dma_tag_destroy(ioctl_data_tag[i]);
367 mrsas_release_mfi_cmd(cmd);
373 * mrsas_alloc_mfi_cmds: Allocates the command packets
374 * input: Adapter instance soft state
376 * Each IOCTL or passthru command that is issued to the FW are wrapped in a
377 * local data structure called mrsas_mfi_cmd. The frame embedded in this
378 * mrsas_mfi is issued to FW. The array is used only to look up the
379 * mrsas_mfi_cmd given the context. The free commands are maintained in a
382 int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc)
386 struct mrsas_mfi_cmd *cmd;
388 max_cmd = MRSAS_MAX_MFI_CMDS;
391 * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers. Allocate the
392 * dynamic array first and then allocate individual commands.
394 sc->mfi_cmd_list = kmalloc(sizeof(struct mrsas_mfi_cmd*)*max_cmd, M_MRSAS, M_NOWAIT);
395 if (!sc->mfi_cmd_list) {
396 device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n");
399 memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *)*max_cmd);
400 for (i = 0; i < max_cmd; i++) {
401 sc->mfi_cmd_list[i] = kmalloc(sizeof(struct mrsas_mfi_cmd),
403 if (!sc->mfi_cmd_list[i]) {
404 for (j = 0; j < i; j++)
405 kfree(sc->mfi_cmd_list[j],M_MRSAS);
406 kfree(sc->mfi_cmd_list, M_MRSAS);
407 sc->mfi_cmd_list = NULL;
412 for (i = 0; i < max_cmd; i++) {
413 cmd = sc->mfi_cmd_list[i];
414 memset(cmd, 0, sizeof(struct mrsas_mfi_cmd));
418 TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next);
421 /* create a frame pool and assign one frame to each command */
422 if (mrsas_create_frame_pool(sc)) {
423 device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n");
424 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { // Free the frames
425 cmd = sc->mfi_cmd_list[i];
426 mrsas_free_frame(sc, cmd);
428 if (sc->mficmd_frame_tag != NULL)
429 bus_dma_tag_destroy(sc->mficmd_frame_tag);
437 * mrsas_create_frame_pool - Creates DMA pool for cmd frames
438 * input: Adapter soft state
440 * Each command packet has an embedded DMA memory buffer that is used for
441 * filling MFI frame and the SG list that immediately follows the frame. This
442 * function creates those DMA memory buffers for each command packet by using
443 * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value
444 * of context and could cause FW crash.
446 static int mrsas_create_frame_pool(struct mrsas_softc *sc)
449 struct mrsas_mfi_cmd *cmd;
451 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
452 1, 0, // algnmnt, boundary
453 BUS_SPACE_MAXADDR_32BIT,// lowaddr
454 BUS_SPACE_MAXADDR, // highaddr
455 MRSAS_MFI_FRAME_SIZE, // maxsize
457 MRSAS_MFI_FRAME_SIZE, // maxsegsize
458 BUS_DMA_ALLOCNOW, // flags
459 &sc->mficmd_frame_tag)) {
460 device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n");
464 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
465 cmd = sc->mfi_cmd_list[i];
466 cmd->frame = mrsas_alloc_frame(sc, cmd);
467 if (cmd->frame == NULL) {
468 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
471 memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE);
472 cmd->frame->io.context = cmd->index;
473 cmd->frame->io.pad_0 = 0;
480 * mrsas_alloc_frame - Allocates MFI Frames
481 * input: Adapter soft state
483 * Create bus DMA memory tag and dmamap and load memory for MFI frames.
484 * Returns virtual memory pointer to allocated region.
486 void *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
488 u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE;
490 if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem,
491 BUS_DMA_NOWAIT, &cmd->frame_dmamap)) {
492 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
495 if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap,
496 cmd->frame_mem, frame_size, mrsas_alloc_cb,
497 &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) {
498 device_printf(sc->mrsas_dev, "Cannot load IO request memory\n");
502 return(cmd->frame_mem);
506 * mrsas_alloc_cb: Callback function of bus_dmamap_load()
507 * input: callback argument,
508 * machine dependent type that describes DMA segments,
509 * number of segments,
512 * This function is for the driver to receive mapping information resultant
513 * of the bus_dmamap_load(). The information is actually not being used,
514 * but the address is saved anyway.
516 static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
517 int nsegs, int error)
522 *addr = segs[0].ds_addr;
526 * mrsas_free_frames: Frees memory for MFI frames
527 * input: Adapter soft state
529 * Deallocates MFI frames memory. Called from mrsas_free_mem() during
530 * detach and error case during creation of frame pool.
532 void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
534 if (cmd->frame_phys_addr)
535 bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap);
536 if (cmd->frame_mem != NULL)
537 bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap);