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
45struct 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 */
60int	mrsas_alloc_mfi_cmds(struct mrsas_softc *sc);
61int	mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd);
62void	mrsas_free_ioc_cmd(struct mrsas_softc *sc);
63void	mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
64void   *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
65static int mrsas_create_frame_pool(struct mrsas_softc *sc);
66static void
67mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
68    int nsegs, int error);
69
70extern struct mrsas_mfi_cmd *mrsas_get_mfi_cmd(struct mrsas_softc *sc);
71extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd);
72extern int
73mrsas_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 */
85static void
86mrsas_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 */
131int
132mrsas_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
367out:
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 */
413int
414mrsas_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
575out:
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 */
610int
611mrsas_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 */
676static int
677mrsas_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 */
729void   *
730mrsas_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 */
759static void
760mrsas_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 */
776void
777mrsas_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