xref: /freebsd/sys/dev/mrsas/mrsas_ioctl.c (revision f126890a)
1 /*
2  * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy
3  * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy
4  * Support: freebsdraid@avagotech.com
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer. 2. Redistributions
12  * in binary form must reproduce the above copyright notice, this list of
13  * conditions and the following disclaimer in the documentation and/or other
14  * materials provided with the distribution. 3. Neither the name of the
15  * <ORGANIZATION> nor the names of its contributors may be used to endorse or
16  * promote products derived from this software without specific prior written
17  * permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  * The views and conclusions contained in the software and documentation are
32  * those of the authors and should not be interpreted as representing
33  * official policies,either expressed or implied, of the FreeBSD Project.
34  *
35  * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621
36  * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD
37  *
38  */
39 
40 #include <sys/cdefs.h>
41 #include <sys/abi_compat.h>
42 #include <dev/mrsas/mrsas.h>
43 #include <dev/mrsas/mrsas_ioctl.h>
44 
45 struct mrsas_passthru_cmd {
46 	struct mrsas_sge64 *kern_sge;
47 	struct mrsas_softc *sc;
48 	struct mrsas_mfi_cmd *cmd;
49 	bus_dma_tag_t ioctl_data_tag;
50 	bus_dmamap_t ioctl_data_dmamap;
51 
52 	u_int32_t error_code;
53 	u_int32_t sge_count;
54 	int complete;
55 };
56 
57 /*
58  * Function prototypes
59  */
60 int	mrsas_alloc_mfi_cmds(struct mrsas_softc *sc);
61 int	mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd);
62 void	mrsas_free_ioc_cmd(struct mrsas_softc *sc);
63 void	mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
64 void   *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
65 static int mrsas_create_frame_pool(struct mrsas_softc *sc);
66 static void
67 mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
68     int nsegs, int error);
69 
70 extern struct mrsas_mfi_cmd *mrsas_get_mfi_cmd(struct mrsas_softc *sc);
71 extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd);
72 extern int
73 mrsas_issue_blocked_cmd(struct mrsas_softc *sc,
74     struct mrsas_mfi_cmd *cmd);
75 
76 /*
77  * mrsas_data_load_cb:  Callback entry point
78  * input:                               Pointer to command packet as argument
79  *                                              Pointer to segment
80  *                                              Number of segments Error
81  *
82  * This is the callback function of the bus dma map load.  It builds the SG
83  * list.
84  */
85 static void
86 mrsas_passthru_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
87 {
88         struct mrsas_passthru_cmd *cb = (struct mrsas_passthru_cmd *)arg;
89         struct mrsas_softc *sc = cb->sc;
90 	int i = 0;
91 
92 	if (error) {
93 		cb->error_code = error;
94 		if (error == EFBIG) {
95 			device_printf(sc->mrsas_dev, "mrsas_passthru_load_cb: "
96 			    "error=%d EFBIG\n", error);
97 			cb->complete = 1;
98 			return;
99 		} else {
100 			device_printf(sc->mrsas_dev, "mrsas_passthru_load_cb: "
101 			    "error=%d UNKNOWN\n", error);
102 		}
103 	}
104 	if (nseg > MAX_IOCTL_SGE) {
105 		cb->error_code = EFBIG;
106 		device_printf(sc->mrsas_dev, "mrsas_passthru_load_cb: "
107 		    "too many segments: %d\n", nseg);
108 		cb->complete = 1;
109 		return;
110 	}
111 
112 	for (i = 0; i < nseg; i++) {
113 		cb->kern_sge[i].phys_addr = htole64(segs[i].ds_addr);
114 		cb->kern_sge[i].length = htole32(segs[i].ds_len);
115 	}
116 	cb->sge_count = nseg;
117 
118 	bus_dmamap_sync(cb->ioctl_data_tag, cb->ioctl_data_dmamap,
119             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
120 
121 	cb->complete = 1;
122 }
123 
124 /*
125  * mrsas_passthru:	Handle pass-through commands
126  * input:			Adapter instance soft state argument pointer
127  *
128  * This function is called from mrsas_ioctl() to handle pass-through and ioctl
129  * commands to Firmware.
130  */
131 int
132 mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd)
133 {
134 	struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg;
135 
136 #ifdef COMPAT_FREEBSD32
137 	struct mrsas_iocpacket32 *user_ioc32 = (struct mrsas_iocpacket32 *)arg;
138 
139 #endif
140 	union mrsas_frame *in_cmd = (union mrsas_frame *)&(user_ioc->frame.raw);
141 	struct mrsas_mfi_cmd *cmd = NULL;
142 	bus_dma_tag_t ioctl_data_tag[MAX_IOCTL_SGE];
143 	bus_dmamap_t ioctl_data_dmamap[MAX_IOCTL_SGE];
144 	void *ioctl_data_mem[MAX_IOCTL_SGE];
145 	bus_addr_t ioctl_data_phys_addr[MAX_IOCTL_SGE];
146 	bus_dma_tag_t ioctl_sense_tag = 0;
147 	bus_dmamap_t ioctl_sense_dmamap = 0;
148 	void *ioctl_sense_mem = NULL;
149 	bus_addr_t ioctl_sense_phys_addr = 0;
150 	int i, ioctl_data_size = 0, ioctl_sense_size, ret = 0;
151 	struct mrsas_sge32 *kern_sge32;
152 	unsigned long *sense_ptr;
153 	uint8_t *iov_base_ptrin = NULL;
154 	size_t iov_len = 0;
155 
156 	/*
157 	 * Check for NOP from MegaCli... MegaCli can issue a DCMD of 0.  In
158 	 * this case do nothing and return 0 to it as status.
159 	 */
160 	if (in_cmd->dcmd.opcode == 0) {
161 		device_printf(sc->mrsas_dev, "In %s() Got a NOP\n", __func__);
162 		user_ioc->frame.hdr.cmd_status = MFI_STAT_OK;
163 		return (0);
164 	}
165 	/* Validate SGL length */
166 	if (user_ioc->sge_count > MAX_IOCTL_SGE) {
167 		device_printf(sc->mrsas_dev, "In %s() SGL is too long (%d > 8).\n",
168 		    __func__, user_ioc->sge_count);
169 		return (ENOENT);
170 	}
171 	/* Get a command */
172 	cmd = mrsas_get_mfi_cmd(sc);
173 	if (!cmd) {
174 		device_printf(sc->mrsas_dev, "Failed to get a free cmd for IOCTL\n");
175 		return (ENOMEM);
176 	}
177 	/*
178 	 * User's IOCTL packet has 2 frames (maximum). Copy those two frames
179 	 * into our cmd's frames. cmd->frame's context will get overwritten
180 	 * when we copy from user's frames. So set that value alone
181 	 * separately
182 	 */
183 	memcpy(cmd->frame, user_ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
184 	cmd->frame->hdr.context = cmd->index;
185 	cmd->frame->hdr.pad_0 = 0;
186 	cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 |
187 	    MFI_FRAME_SENSE64);
188 
189 	/*
190 	 * The management interface between applications and the fw uses MFI
191 	 * frames. E.g, RAID configuration changes, LD property changes etc
192 	 * are accomplishes through different kinds of MFI frames. The driver
193 	 * needs to care only about substituting user buffers with kernel
194 	 * buffers in SGLs. The location of SGL is embedded in the struct
195 	 * iocpacket itself.
196 	 */
197 	kern_sge32 = (struct mrsas_sge32 *)
198 	    ((uintptr_t)cmd->frame + user_ioc->sgl_off);
199 
200 	memset(ioctl_data_tag, 0, (sizeof(bus_dma_tag_t) * MAX_IOCTL_SGE));
201 	memset(ioctl_data_dmamap, 0, (sizeof(bus_dmamap_t) * MAX_IOCTL_SGE));
202 	memset(ioctl_data_mem, 0, (sizeof(void *) * MAX_IOCTL_SGE));
203 	memset(ioctl_data_phys_addr, 0, (sizeof(bus_addr_t) * MAX_IOCTL_SGE));
204 
205 	/*
206 	 * For each user buffer, create a mirror buffer and copy in
207 	 */
208 	for (i = 0; i < user_ioc->sge_count; i++) {
209 		if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
210 			if (!user_ioc->sgl[i].iov_len)
211 				continue;
212 			ioctl_data_size = user_ioc->sgl[i].iov_len;
213 #ifdef COMPAT_FREEBSD32
214 		} else {
215 			if (!user_ioc32->sgl[i].iov_len)
216 				continue;
217 			ioctl_data_size = user_ioc32->sgl[i].iov_len;
218 #endif
219 		}
220 		if (bus_dma_tag_create(sc->mrsas_parent_tag,
221 		    1, 0,
222 		    BUS_SPACE_MAXADDR_32BIT,
223 		    BUS_SPACE_MAXADDR,
224 		    NULL, NULL,
225 		    ioctl_data_size,
226 		    1,
227 		    ioctl_data_size,
228 		    BUS_DMA_ALLOCNOW,
229 		    NULL, NULL,
230 		    &ioctl_data_tag[i])) {
231 			device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n");
232 			ret = ENOMEM;
233 			goto out;
234 		}
235 		if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i],
236 		    (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) {
237 			device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
238 			ret = ENOMEM;
239 			goto out;
240 		}
241 		if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i],
242 		    ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb,
243 		    &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) {
244 			device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n");
245 			ret = ENOMEM;
246 			goto out;
247 		}
248 		/* Save the physical address and length */
249 		kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i];
250 
251 		if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
252 			kern_sge32[i].length = user_ioc->sgl[i].iov_len;
253 
254 			iov_base_ptrin = user_ioc->sgl[i].iov_base;
255 			iov_len = user_ioc->sgl[i].iov_len;
256 #ifdef COMPAT_FREEBSD32
257 		} else {
258 			kern_sge32[i].length = user_ioc32->sgl[i].iov_len;
259 
260 			iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base);
261 			iov_len = user_ioc32->sgl[i].iov_len;
262 #endif
263 		}
264 
265 		/* Copy in data from user space */
266 		ret = copyin(iov_base_ptrin, ioctl_data_mem[i], iov_len);
267 		if (ret) {
268 			device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n");
269 			goto out;
270 		}
271 	}
272 
273 	ioctl_sense_size = user_ioc->sense_len;
274 
275 	if (user_ioc->sense_len) {
276 		if (bus_dma_tag_create(sc->mrsas_parent_tag,
277 		    1, 0,
278 		    BUS_SPACE_MAXADDR_32BIT,
279 		    BUS_SPACE_MAXADDR,
280 		    NULL, NULL,
281 		    ioctl_sense_size,
282 		    1,
283 		    ioctl_sense_size,
284 		    BUS_DMA_ALLOCNOW,
285 		    NULL, NULL,
286 		    &ioctl_sense_tag)) {
287 			device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense tag\n");
288 			ret = ENOMEM;
289 			goto out;
290 		}
291 		if (bus_dmamem_alloc(ioctl_sense_tag, (void **)&ioctl_sense_mem,
292 		    (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_sense_dmamap)) {
293 			device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense mem\n");
294 			ret = ENOMEM;
295 			goto out;
296 		}
297 		if (bus_dmamap_load(ioctl_sense_tag, ioctl_sense_dmamap,
298 		    ioctl_sense_mem, ioctl_sense_size, mrsas_alloc_cb,
299 		    &ioctl_sense_phys_addr, BUS_DMA_NOWAIT)) {
300 			device_printf(sc->mrsas_dev, "Cannot load ioctl sense mem\n");
301 			ret = ENOMEM;
302 			goto out;
303 		}
304 		sense_ptr =
305 		    (unsigned long *)((uintptr_t)cmd->frame + user_ioc->sense_off);
306 		*sense_ptr = ioctl_sense_phys_addr;
307 	}
308 	/*
309 	 * Set the sync_cmd flag so that the ISR knows not to complete this
310 	 * cmd to the SCSI mid-layer
311 	 */
312 	cmd->sync_cmd = 1;
313 	ret = mrsas_issue_blocked_cmd(sc, cmd);
314 	if (ret == ETIMEDOUT) {
315 		mrsas_dprint(sc, MRSAS_OCR,
316 		    "IOCTL command is timed out, initiating OCR\n");
317 		sc->do_timedout_reset = MFI_DCMD_TIMEOUT_OCR;
318 		ret = EAGAIN;
319 		goto out;
320 	}
321 	cmd->sync_cmd = 0;
322 
323 	/*
324 	 * copy out the kernel buffers to user buffers
325 	 */
326 	for (i = 0; i < user_ioc->sge_count; i++) {
327 		if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
328 			iov_base_ptrin = user_ioc->sgl[i].iov_base;
329 			iov_len = user_ioc->sgl[i].iov_len;
330 #ifdef COMPAT_FREEBSD32
331 		} else {
332 			iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base);
333 			iov_len = user_ioc32->sgl[i].iov_len;
334 #endif
335 		}
336 
337 		ret = copyout(ioctl_data_mem[i], iov_base_ptrin, iov_len);
338 		if (ret) {
339 			device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n");
340 			goto out;
341 		}
342 	}
343 
344 	/*
345 	 * copy out the sense
346 	 */
347 	if (user_ioc->sense_len) {
348 		/*
349 		 * sense_buff points to the location that has the user sense
350 		 * buffer address
351 		 */
352 		sense_ptr = (unsigned long *)((uintptr_t)user_ioc->frame.raw +
353 		    user_ioc->sense_off);
354 		ret = copyout(ioctl_sense_mem, (unsigned long *)(uintptr_t)*sense_ptr,
355 		    user_ioc->sense_len);
356 		if (ret) {
357 			device_printf(sc->mrsas_dev, "IOCTL sense copyout failed!\n");
358 			goto out;
359 		}
360 	}
361 	/*
362 	 * Return command status to user space
363 	 */
364 	memcpy(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status,
365 	    sizeof(u_int8_t));
366 
367 out:
368 	/*
369 	 * Release sense buffer
370 	 */
371 	if (user_ioc->sense_len) {
372 		if (ioctl_sense_phys_addr)
373 			bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap);
374 		if (ioctl_sense_mem != NULL)
375 			bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap);
376 		if (ioctl_sense_tag != NULL)
377 			bus_dma_tag_destroy(ioctl_sense_tag);
378 	}
379 	/*
380 	 * Release data buffers
381 	 */
382 	for (i = 0; i < user_ioc->sge_count; i++) {
383 		if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
384 			if (!user_ioc->sgl[i].iov_len)
385 				continue;
386 #ifdef COMPAT_FREEBSD32
387 		} else {
388 			if (!user_ioc32->sgl[i].iov_len)
389 				continue;
390 #endif
391 		}
392 		if (ioctl_data_phys_addr[i])
393 			bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]);
394 		if (ioctl_data_mem[i] != NULL)
395 			bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i],
396 			    ioctl_data_dmamap[i]);
397 		if (ioctl_data_tag[i] != NULL)
398 			bus_dma_tag_destroy(ioctl_data_tag[i]);
399 	}
400 	/* Free command */
401 	mrsas_release_mfi_cmd(cmd);
402 
403 	return (ret);
404 }
405 
406 /**
407  * mrsas_user_command:    Handle user mode DCMD and buffer
408  * input:                 Adapter instance soft state
409  *                        argument pointer
410  *
411  * This function is called from mrsas_ioctl() DCMDs to firmware for mfiutil
412  */
413 int
414 mrsas_user_command(struct mrsas_softc *sc, struct mfi_ioc_passthru *ioc)
415 {
416 	struct mrsas_mfi_cmd *cmd;
417 	struct mrsas_dcmd_frame *dcmd;
418 	struct mrsas_passthru_cmd *passcmd;
419 	bus_dma_tag_t ioctl_data_tag;
420 	bus_dmamap_t ioctl_data_dmamap;
421 	bus_addr_t ioctl_data_phys_addr;
422 	struct mrsas_sge64 *kern_sge;
423 	int ret, ioctl_data_size;
424 	char *ioctl_temp_data_mem;
425 
426 	ret = 0;
427 	ioctl_temp_data_mem = NULL;
428 	passcmd = NULL;
429 	ioctl_data_phys_addr = 0;
430 	dcmd = NULL;
431 	cmd = NULL;
432 	ioctl_data_tag = NULL;
433 	ioctl_data_dmamap = NULL;
434 	ioctl_data_dmamap = NULL;
435 
436 	/* Get a command */
437 	cmd = mrsas_get_mfi_cmd(sc);
438 	if (!cmd) {
439 		device_printf(sc->mrsas_dev,
440 		    "Failed to get a free cmd for IOCTL\n");
441 		return(ENOMEM);
442 	}
443 
444 	/*
445 	 * Frame is DCMD
446 	 */
447 	dcmd = (struct mrsas_dcmd_frame *)cmd->frame;
448 	memcpy(dcmd, &ioc->ioc_frame, sizeof(struct mrsas_dcmd_frame));
449 
450 	ioctl_data_size = ioc->buf_size;
451 
452 	cmd->frame->hdr.context = cmd->index;
453 	cmd->frame->hdr.pad_0 = 0;
454 	cmd->frame->hdr.flags = MFI_FRAME_DIR_BOTH;
455 	if (sizeof(bus_addr_t) == 8)
456 		cmd->frame->hdr.flags |= MFI_FRAME_SGL64 | MFI_FRAME_SENSE64;
457 
458 	kern_sge = (struct mrsas_sge64 *)(&dcmd->sgl);
459 
460 	if (ioctl_data_size == 0) {
461 		kern_sge[0].phys_addr = 0;
462 		kern_sge[0].length = 0;
463 	} else {
464 		ioctl_temp_data_mem = malloc(ioc->buf_size, M_MRSAS, M_WAITOK);
465 		if (ioctl_temp_data_mem == NULL) {
466 			device_printf(sc->mrsas_dev, "Could not allocate "
467 			    "%d memory for temporary passthrough ioctl\n",
468 			    ioc->buf_size);
469 		ret = ENOMEM;
470 		goto out;
471 		}
472 
473 		/* Copy in data from user space */
474 		ret = copyin(ioc->buf, ioctl_temp_data_mem, ioc->buf_size);
475 		if (ret) {
476 			device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n");
477 			goto out;
478 		}
479 
480 		/*
481 		 * Allocate a temporary struct to hold parameters for the
482 		 * callback
483 		 */
484 		passcmd = malloc(sizeof(struct mrsas_passthru_cmd), M_MRSAS,
485 		    M_WAITOK);
486 		if (passcmd == NULL) {
487 			device_printf(sc->mrsas_dev, "Could not allocate "
488 			    "memory for temporary passthrough cb struct\n");
489 			ret = ENOMEM;
490 			goto out;
491 		}
492 		passcmd->complete = 0;
493 		passcmd->sc = sc;
494 		passcmd->cmd = cmd;
495 		passcmd->kern_sge = kern_sge;
496 
497 		/*
498 		 * Create a dma tag for passthru buffers
499 		 */
500 		if (bus_dma_tag_create(sc->mrsas_parent_tag,   /* parent */
501 		    1, 0,                   /* algnmnt, boundary */
502 		    BUS_SPACE_MAXADDR,      /* lowaddr */
503 		    BUS_SPACE_MAXADDR,      /* highaddr */
504 		    NULL, NULL,             /* filter, filterarg */
505 		    ioctl_data_size,        /* maxsize */
506 		    MAX_IOCTL_SGE,          /* msegments */
507 		    ioctl_data_size,        /* maxsegsize */
508 		    BUS_DMA_ALLOCNOW,       /* flags */
509 		    busdma_lock_mutex,      /* lockfunc */
510 		    &sc->ioctl_lock,        /* lockarg */
511 		    &ioctl_data_tag)) {
512 			device_printf(sc->mrsas_dev,
513 			   "Cannot allocate ioctl data tag %d\n",
514 			    ioc->buf_size);
515 			ret = ENOMEM;
516 			goto out;
517 		}
518 
519 		/* Create memmap */
520 		if (bus_dmamap_create(ioctl_data_tag, 0, &ioctl_data_dmamap)) {
521 			device_printf(sc->mrsas_dev, "Cannot create ioctl "
522 			    "passthru dmamap\n");
523 			ret = ENOMEM;
524 			goto out;
525 		}
526 
527 		passcmd->ioctl_data_tag = ioctl_data_tag;
528 		passcmd->ioctl_data_dmamap = ioctl_data_dmamap;
529 
530 		/* Map data buffer into bus space */
531 		if (bus_dmamap_load(ioctl_data_tag, ioctl_data_dmamap,
532 		    ioctl_temp_data_mem, ioc->buf_size, mrsas_passthru_load_cb,
533 		    passcmd, BUS_DMA_NOWAIT)) {
534 			device_printf(sc->mrsas_dev, "Cannot load ioctl "
535 			    "passthru data mem%s %d\n", curproc->p_comm, ioctl_data_size);
536 			ret = ENOMEM;
537 			goto out;
538 		}
539 
540 		while (passcmd->complete == 0) {
541 			pause("mrsas_passthru", hz);
542 		}
543 
544 		cmd->frame->dcmd.sge_count = passcmd->sge_count;
545 	}
546 
547 	/*
548 	 * Set the sync_cmd flag so that the ISR knows not to complete this
549 	 * cmd to the SCSI mid-layer
550 	 */
551 	cmd->sync_cmd = 1;
552 	mrsas_issue_blocked_cmd(sc, cmd);
553 	cmd->sync_cmd = 0;
554 
555 	if (ioctl_data_size != 0) {
556 		bus_dmamap_sync(ioctl_data_tag, ioctl_data_dmamap,
557 		    BUS_DMASYNC_POSTREAD);
558 		/*
559 		 * copy out the kernel buffers to user buffers
560 		 */
561 		ret = copyout(ioctl_temp_data_mem, ioc->buf, ioc->buf_size);
562 		if (ret) {
563 			device_printf(sc->mrsas_dev,
564 			    "IOCTL copyout failed!\n");
565 			goto out;
566 		}
567 	}
568 
569 	/*
570 	 * Return command status to user space
571 	 */
572 	memcpy(&ioc->ioc_frame.cmd_status, &cmd->frame->hdr.cmd_status,
573 	    sizeof(u_int8_t));
574 
575 out:
576 	/*
577 	 * Release temporary passthrough ioctl
578 	 */
579 	if (ioctl_temp_data_mem)
580 		free(ioctl_temp_data_mem, M_MRSAS);
581 	if (passcmd)
582 		free(passcmd, M_MRSAS);
583 
584 	/*
585 	 * Release data buffers
586 	 */
587 	if (ioctl_data_phys_addr) {
588 		bus_dmamap_unload(ioctl_data_tag, ioctl_data_dmamap);
589 		bus_dmamap_destroy(ioctl_data_tag, ioctl_data_dmamap);
590 	}
591 	if (ioctl_data_tag != NULL)
592 		bus_dma_tag_destroy(ioctl_data_tag);
593 	/* Free command */
594 	mrsas_release_mfi_cmd(cmd);
595 
596 	return(ret);
597 }
598 
599 
600 /*
601  * mrsas_alloc_mfi_cmds:	Allocates the command packets
602  * input:					Adapter instance soft state
603  *
604  * Each IOCTL or passthru command that is issued to the FW are wrapped in a
605  * local data structure called mrsas_mfi_cmd.  The frame embedded in this
606  * mrsas_mfi is issued to FW. The array is used only to look up the
607  * mrsas_mfi_cmd given the context. The free commands are maintained in a
608  * linked list.
609  */
610 int
611 mrsas_alloc_mfi_cmds(struct mrsas_softc *sc)
612 {
613 	int i, j;
614 	u_int32_t max_cmd;
615 	struct mrsas_mfi_cmd *cmd;
616 
617 	max_cmd = MRSAS_MAX_MFI_CMDS;
618 
619 	/*
620 	 * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers.
621 	 * Allocate the dynamic array first and then allocate individual
622 	 * commands.
623 	 */
624 	sc->mfi_cmd_list = malloc(sizeof(struct mrsas_mfi_cmd *) * max_cmd, M_MRSAS, M_NOWAIT);
625 	if (!sc->mfi_cmd_list) {
626 		device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n");
627 		return (ENOMEM);
628 	}
629 	memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *) * max_cmd);
630 	for (i = 0; i < max_cmd; i++) {
631 		sc->mfi_cmd_list[i] = malloc(sizeof(struct mrsas_mfi_cmd),
632 		    M_MRSAS, M_NOWAIT);
633 		if (!sc->mfi_cmd_list[i]) {
634 			for (j = 0; j < i; j++)
635 				free(sc->mfi_cmd_list[j], M_MRSAS);
636 			free(sc->mfi_cmd_list, M_MRSAS);
637 			sc->mfi_cmd_list = NULL;
638 			return (ENOMEM);
639 		}
640 	}
641 
642 	for (i = 0; i < max_cmd; i++) {
643 		cmd = sc->mfi_cmd_list[i];
644 		memset(cmd, 0, sizeof(struct mrsas_mfi_cmd));
645 		cmd->index = i;
646 		cmd->ccb_ptr = NULL;
647 		cmd->sc = sc;
648 		TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next);
649 	}
650 
651 	/* create a frame pool and assign one frame to each command */
652 	if (mrsas_create_frame_pool(sc)) {
653 		device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n");
654 		/* Free the frames */
655 		for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
656 			cmd = sc->mfi_cmd_list[i];
657 			mrsas_free_frame(sc, cmd);
658 		}
659 		if (sc->mficmd_frame_tag != NULL)
660 			bus_dma_tag_destroy(sc->mficmd_frame_tag);
661 		return (ENOMEM);
662 	}
663 	return (0);
664 }
665 
666 /*
667  * mrsas_create_frame_pool:	Creates DMA pool for cmd frames
668  * input:					Adapter soft state
669  *
670  * Each command packet has an embedded DMA memory buffer that is used for
671  * filling MFI frame and the SG list that immediately follows the frame. This
672  * function creates those DMA memory buffers for each command packet by using
673  * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value
674  * of context and could cause FW crash.
675  */
676 static int
677 mrsas_create_frame_pool(struct mrsas_softc *sc)
678 {
679 	int i;
680 	struct mrsas_mfi_cmd *cmd;
681 
682 	if (bus_dma_tag_create(sc->mrsas_parent_tag,
683 	    1, 0,
684 	    BUS_SPACE_MAXADDR_32BIT,
685 	    BUS_SPACE_MAXADDR,
686 	    NULL, NULL,
687 	    MRSAS_MFI_FRAME_SIZE,
688 	    1,
689 	    MRSAS_MFI_FRAME_SIZE,
690 	    BUS_DMA_ALLOCNOW,
691 	    NULL, NULL,
692 	    &sc->mficmd_frame_tag)) {
693 		device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n");
694 		return (ENOMEM);
695 	}
696 	for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
697 		cmd = sc->mfi_cmd_list[i];
698 		cmd->frame = mrsas_alloc_frame(sc, cmd);
699 		if (cmd->frame == NULL) {
700 			device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
701 			return (ENOMEM);
702 		}
703 		/*
704 		 * For MFI controllers.
705 		 * max_num_sge = 60
706 		 * max_sge_sz  = 16 byte (sizeof megasas_sge_skinny)
707 		 * Totl 960 byte (15 MFI frame of 64 byte)
708 		 *
709 		 * Fusion adapter require only 3 extra frame.
710 		 * max_num_sge = 16 (defined as MAX_IOCTL_SGE)
711 		 * max_sge_sz  = 12 byte (sizeof  megasas_sge64)
712 		 * Total 192 byte (3 MFI frame of 64 byte)
713 		 */
714 		memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE);
715 		cmd->frame->io.context = cmd->index;
716 		cmd->frame->io.pad_0 = 0;
717 	}
718 
719 	return (0);
720 }
721 
722 /*
723  * mrsas_alloc_frame:	Allocates MFI Frames
724  * input:				Adapter soft state
725  *
726  * Create bus DMA memory tag and dmamap and load memory for MFI frames. Returns
727  * virtual memory pointer to allocated region.
728  */
729 void   *
730 mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
731 {
732 	u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE;
733 
734 	if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem,
735 	    BUS_DMA_NOWAIT, &cmd->frame_dmamap)) {
736 		device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
737 		return (NULL);
738 	}
739 	if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap,
740 	    cmd->frame_mem, frame_size, mrsas_alloc_cb,
741 	    &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) {
742 		device_printf(sc->mrsas_dev, "Cannot load IO request memory\n");
743 		return (NULL);
744 	}
745 	return (cmd->frame_mem);
746 }
747 
748 /*
749  * mrsas_alloc_cb:	Callback function of bus_dmamap_load()
750  * input:			callback argument,
751  * 					machine dependent type that describes DMA segments,
752  * 					number of segments,
753  * 					error code.
754  *
755  * This function is for the driver to receive mapping information resultant of
756  * the bus_dmamap_load(). The information is actually not being used, but the
757  * address is saved anyway.
758  */
759 static void
760 mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
761     int nsegs, int error)
762 {
763 	bus_addr_t *addr;
764 
765 	addr = arg;
766 	*addr = segs[0].ds_addr;
767 }
768 
769 /*
770  * mrsas_free_frames:	Frees memory for  MFI frames
771  * input:				Adapter soft state
772  *
773  * Deallocates MFI frames memory.  Called from mrsas_free_mem() during detach
774  * and error case during creation of frame pool.
775  */
776 void
777 mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
778 {
779 	if (cmd->frame_phys_addr)
780 		bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap);
781 	if (cmd->frame_mem != NULL)
782 		bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap);
783 }
784