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 NULL, NULL, // filter, filterarg
234 ioctl_data_size, // maxsize
236 ioctl_data_size, // maxsegsize
237 BUS_DMA_ALLOCNOW, // flags
238 &ioctl_data_tag[i])) {
239 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n");
242 if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i],
243 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) {
244 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
247 if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i],
248 ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb,
249 &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) {
250 device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n");
254 /* Save the physical address and length */
255 kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i];
256 kern_sge32[i].length = user_ioc->sgl[i].iov_len;
258 /* Copy in data from user space */
259 ret = copyin(user_ioc->sgl[i].iov_base, ioctl_data_mem[i],
260 user_ioc->sgl[i].iov_len);
262 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n");
267 ioctl_sense_size = user_ioc->sense_len;
268 if (user_ioc->sense_len) {
269 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
270 1, 0, // algnmnt, boundary
271 BUS_SPACE_MAXADDR_32BIT,// lowaddr
272 BUS_SPACE_MAXADDR, // highaddr
273 NULL, NULL, // filter, filterarg
274 ioctl_sense_size, // maxsize
276 ioctl_sense_size, // maxsegsize
277 BUS_DMA_ALLOCNOW, // flags
279 device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense tag\n");
282 if (bus_dmamem_alloc(ioctl_sense_tag, (void **)&ioctl_sense_mem,
283 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_sense_dmamap)) {
284 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
287 if (bus_dmamap_load(ioctl_sense_tag, ioctl_sense_dmamap,
288 ioctl_sense_mem, ioctl_sense_size, mrsas_alloc_cb,
289 &ioctl_sense_phys_addr, BUS_DMA_NOWAIT)) {
290 device_printf(sc->mrsas_dev, "Cannot load ioctl sense mem\n");
294 (unsigned long *)((unsigned long)cmd->frame + user_ioc->sense_off);
295 *sense_ptr = ioctl_sense_phys_addr;
299 * Set the sync_cmd flag so that the ISR knows not to complete this
300 * cmd to the SCSI mid-layer
303 mrsas_issue_blocked_cmd(sc, cmd);
307 * copy out the kernel buffers to user buffers
309 for (i = 0; i < user_ioc->sge_count; i++) {
310 ret = copyout(ioctl_data_mem[i], user_ioc->sgl[i].iov_base,
311 user_ioc->sgl[i].iov_len);
313 device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n");
321 if (user_ioc->sense_len) {
323 * sense_buff points to the location that has the user
324 * sense buffer address
326 sense_ptr = (unsigned long *) ((unsigned long)user_ioc->frame.raw +
327 user_ioc->sense_off);
328 ret = copyout(ioctl_sense_mem, (unsigned long*)*sense_ptr,
329 user_ioc->sense_len);
331 device_printf(sc->mrsas_dev, "IOCTL sense copyout failed!\n");
337 * Return command status to user space
339 memcpy(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status,
344 * Release sense buffer
346 if (ioctl_sense_phys_addr)
347 bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap);
349 bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap);
351 bus_dma_tag_destroy(ioctl_sense_tag);
354 * Release data buffers
356 for (i = 0; i < user_ioc->sge_count; i++) {
357 if (!user_ioc->sgl[i].iov_len)
359 if (ioctl_data_phys_addr[i])
360 bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]);
361 if (ioctl_data_mem[i] != NULL)
362 bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i],
363 ioctl_data_dmamap[i]);
364 if (ioctl_data_tag[i] != NULL)
365 bus_dma_tag_destroy(ioctl_data_tag[i]);
369 mrsas_release_mfi_cmd(cmd);
375 * mrsas_alloc_mfi_cmds: Allocates the command packets
376 * input: Adapter instance soft state
378 * Each IOCTL or passthru command that is issued to the FW are wrapped in a
379 * local data structure called mrsas_mfi_cmd. The frame embedded in this
380 * mrsas_mfi is issued to FW. The array is used only to look up the
381 * mrsas_mfi_cmd given the context. The free commands are maintained in a
384 int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc)
388 struct mrsas_mfi_cmd *cmd;
390 max_cmd = MRSAS_MAX_MFI_CMDS;
393 * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers. Allocate the
394 * dynamic array first and then allocate individual commands.
396 sc->mfi_cmd_list = kmalloc(sizeof(struct mrsas_mfi_cmd*)*max_cmd, M_MRSAS, M_NOWAIT);
397 if (!sc->mfi_cmd_list) {
398 device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n");
401 memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *)*max_cmd);
402 for (i = 0; i < max_cmd; i++) {
403 sc->mfi_cmd_list[i] = kmalloc(sizeof(struct mrsas_mfi_cmd),
405 if (!sc->mfi_cmd_list[i]) {
406 for (j = 0; j < i; j++)
407 kfree(sc->mfi_cmd_list[j],M_MRSAS);
408 kfree(sc->mfi_cmd_list, M_MRSAS);
409 sc->mfi_cmd_list = NULL;
414 for (i = 0; i < max_cmd; i++) {
415 cmd = sc->mfi_cmd_list[i];
416 memset(cmd, 0, sizeof(struct mrsas_mfi_cmd));
420 TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next);
423 /* create a frame pool and assign one frame to each command */
424 if (mrsas_create_frame_pool(sc)) {
425 device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n");
426 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { // Free the frames
427 cmd = sc->mfi_cmd_list[i];
428 mrsas_free_frame(sc, cmd);
430 if (sc->mficmd_frame_tag != NULL)
431 bus_dma_tag_destroy(sc->mficmd_frame_tag);
439 * mrsas_create_frame_pool - Creates DMA pool for cmd frames
440 * input: Adapter soft state
442 * Each command packet has an embedded DMA memory buffer that is used for
443 * filling MFI frame and the SG list that immediately follows the frame. This
444 * function creates those DMA memory buffers for each command packet by using
445 * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value
446 * of context and could cause FW crash.
448 static int mrsas_create_frame_pool(struct mrsas_softc *sc)
451 struct mrsas_mfi_cmd *cmd;
453 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
454 1, 0, // algnmnt, boundary
455 BUS_SPACE_MAXADDR_32BIT,// lowaddr
456 BUS_SPACE_MAXADDR, // highaddr
457 NULL, NULL, // filter, filterarg
458 MRSAS_MFI_FRAME_SIZE, // maxsize
460 MRSAS_MFI_FRAME_SIZE, // maxsegsize
461 BUS_DMA_ALLOCNOW, // flags
462 &sc->mficmd_frame_tag)) {
463 device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n");
467 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
468 cmd = sc->mfi_cmd_list[i];
469 cmd->frame = mrsas_alloc_frame(sc, cmd);
470 if (cmd->frame == NULL) {
471 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
474 memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE);
475 cmd->frame->io.context = cmd->index;
476 cmd->frame->io.pad_0 = 0;
483 * mrsas_alloc_frame - Allocates MFI Frames
484 * input: Adapter soft state
486 * Create bus DMA memory tag and dmamap and load memory for MFI frames.
487 * Returns virtual memory pointer to allocated region.
489 void *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
491 u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE;
493 if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem,
494 BUS_DMA_NOWAIT, &cmd->frame_dmamap)) {
495 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
498 if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap,
499 cmd->frame_mem, frame_size, mrsas_alloc_cb,
500 &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) {
501 device_printf(sc->mrsas_dev, "Cannot load IO request memory\n");
505 return(cmd->frame_mem);
509 * mrsas_alloc_cb: Callback function of bus_dmamap_load()
510 * input: callback argument,
511 * machine dependent type that describes DMA segments,
512 * number of segments,
515 * This function is for the driver to receive mapping information resultant
516 * of the bus_dmamap_load(). The information is actually not being used,
517 * but the address is saved anyway.
519 static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
520 int nsegs, int error)
525 *addr = segs[0].ds_addr;
529 * mrsas_free_frames: Frees memory for MFI frames
530 * input: Adapter soft state
532 * Deallocates MFI frames memory. Called from mrsas_free_mem() during
533 * detach and error case during creation of frame pool.
535 void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
537 if (cmd->frame_phys_addr)
538 bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap);
539 if (cmd->frame_mem != NULL)
540 bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap);