Deleted Added
full compact
mrsas_ioctl.c (265555) mrsas_ioctl.c (272737)
1/*
2 * Copyright (c) 2014, LSI Corp.
3 * All rights reserved.
4 * Author: Marian Choy
5 * Support: freebsdraid@lsi.com
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
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
16 * distribution.
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.
20 *
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.
33 *
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.
37 *
38 * Send feedback to: <megaraidfbsd@lsi.com>
39 * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
40 * ATTN: MegaRaid FreeBSD
41 *
42 */
43
44#include <sys/cdefs.h>
1/*
2 * Copyright (c) 2014, LSI Corp.
3 * All rights reserved.
4 * Author: Marian Choy
5 * Support: freebsdraid@lsi.com
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
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
16 * distribution.
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.
20 *
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.
33 *
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.
37 *
38 * Send feedback to: <megaraidfbsd@lsi.com>
39 * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
40 * ATTN: MegaRaid FreeBSD
41 *
42 */
43
44#include <sys/cdefs.h>
45__FBSDID("$FreeBSD: head/sys/dev/mrsas/mrsas_ioctl.c 265555 2014-05-07 16:16:49Z ambrisko $");
45__FBSDID("$FreeBSD: head/sys/dev/mrsas/mrsas_ioctl.c 272737 2014-10-08 09:19:35Z kadesai $");
46
47#include <dev/mrsas/mrsas.h>
48#include <dev/mrsas/mrsas_ioctl.h>
49
50/*
51 * Function prototypes
52 */
53int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc);
46
47#include <dev/mrsas/mrsas.h>
48#include <dev/mrsas/mrsas_ioctl.h>
49
50/*
51 * Function prototypes
52 */
53int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc);
54int mrsas_passthru(struct mrsas_softc *sc, void *arg);
54int mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd);
55void mrsas_free_ioc_cmd(struct mrsas_softc *sc);
56void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
55void mrsas_free_ioc_cmd(struct mrsas_softc *sc);
56void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
57void mrsas_dump_dcmd(struct mrsas_softc *sc, struct mrsas_dcmd_frame* dcmd);
58void mrsas_dump_ioctl(struct mrsas_softc *sc, struct mrsas_iocpacket *user_ioc);
59void * mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
60static int mrsas_create_frame_pool(struct mrsas_softc *sc);
61static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
62 int nsegs, int error);
63
64extern struct mrsas_mfi_cmd* mrsas_get_mfi_cmd(struct mrsas_softc *sc);
65extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd);
66extern int mrsas_issue_blocked_cmd(struct mrsas_softc *sc,
67 struct mrsas_mfi_cmd *cmd);
68
57void * mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
58static int mrsas_create_frame_pool(struct mrsas_softc *sc);
59static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
60 int nsegs, int error);
61
62extern struct mrsas_mfi_cmd* mrsas_get_mfi_cmd(struct mrsas_softc *sc);
63extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd);
64extern int mrsas_issue_blocked_cmd(struct mrsas_softc *sc,
65 struct mrsas_mfi_cmd *cmd);
66
69
70/**
67/**
71 * mrsas_dump_ioctl: Print debug output for DCMDs
72 * input: Adapter instance soft state
73 * DCMD frame structure
74 *
75 * This function is called from mrsas_passthru() to print out debug information
76 * in the handling and routing of DCMD commands.
77 */
78void mrsas_dump_dcmd( struct mrsas_softc *sc, struct mrsas_dcmd_frame* dcmd )
79{
80 int i;
81
82 device_printf(sc->mrsas_dev, "dcmd->cmd: 0x%02hhx\n", dcmd->cmd);
83 device_printf(sc->mrsas_dev, "dcmd->cmd_status: 0x%02hhx\n", dcmd->cmd_status);
84 device_printf(sc->mrsas_dev, "dcmd->sge_count: 0x%02hhx\n", dcmd->sge_count);
85 device_printf(sc->mrsas_dev, "dcmd->context: 0x%08x\n", dcmd->context);
86 device_printf(sc->mrsas_dev, "dcmd->flags: 0x%04hx\n", dcmd->flags);
87 device_printf(sc->mrsas_dev, "dcmd->timeout: 0x%04hx\n", dcmd->timeout);
88 device_printf(sc->mrsas_dev, "dcmd->data_xfer_len: 0x%08x\n", dcmd->data_xfer_len);
89 device_printf(sc->mrsas_dev, "dcmd->opcode: 0x%08x\n", dcmd->opcode);
90 device_printf(sc->mrsas_dev, "dcmd->mbox.w[0]: 0x%08x\n", dcmd->mbox.w[0]);
91 device_printf(sc->mrsas_dev, "dcmd->mbox.w[1]: 0x%08x\n", dcmd->mbox.w[1]);
92 device_printf(sc->mrsas_dev, "dcmd->mbox.w[2]: 0x%08x\n", dcmd->mbox.w[2]);
93 for (i=0; i< MIN(MAX_IOCTL_SGE, dcmd->sge_count); i++) {
94 device_printf(sc->mrsas_dev, "sgl[%02d]\n", i);
95 device_printf(sc->mrsas_dev, " sge32[%02d].phys_addr: 0x%08x\n",
96 i, dcmd->sgl.sge32[i].phys_addr);
97 device_printf(sc->mrsas_dev, " sge32[%02d].length: 0x%08x\n",
98 i, dcmd->sgl.sge32[i].length);
99 device_printf(sc->mrsas_dev, " sge64[%02d].phys_addr: 0x%08llx\n",
100 i, (long long unsigned int) dcmd->sgl.sge64[i].phys_addr);
101 device_printf(sc->mrsas_dev, " sge64[%02d].length: 0x%08x\n",
102 i, dcmd->sgl.sge64[i].length);
103 }
104}
105
106/**
107 * mrsas_dump_ioctl: Print debug output for ioctl
108 * input: Adapter instance soft state
109 * iocpacket structure
110 *
111 * This function is called from mrsas_passthru() to print out debug information
112 * in the handling and routing of ioctl commands.
113 */
114void mrsas_dump_ioctl(struct mrsas_softc *sc, struct mrsas_iocpacket *user_ioc)
115{
116 union mrsas_frame *in_cmd = (union mrsas_frame *) &(user_ioc->frame.raw);
117 struct mrsas_dcmd_frame* dcmd = (struct mrsas_dcmd_frame *) &(in_cmd->dcmd);
118 int i;
119
120 device_printf(sc->mrsas_dev,
121 "====== In %s() ======================================\n", __func__);
122 device_printf(sc->mrsas_dev, "host_no: 0x%04hx\n", user_ioc->host_no);
123 device_printf(sc->mrsas_dev, " __pad1: 0x%04hx\n", user_ioc->__pad1);
124 device_printf(sc->mrsas_dev, "sgl_off: 0x%08x\n", user_ioc->sgl_off);
125 device_printf(sc->mrsas_dev, "sge_count: 0x%08x\n", user_ioc->sge_count);
126 device_printf(sc->mrsas_dev, "sense_off: 0x%08x\n", user_ioc->sense_off);
127 device_printf(sc->mrsas_dev, "sense_len: 0x%08x\n", user_ioc->sense_len);
128
129 mrsas_dump_dcmd(sc, dcmd);
130
131 for (i=0; i< MIN(MAX_IOCTL_SGE, user_ioc->sge_count); i++) {
132 device_printf(sc->mrsas_dev, "sge[%02d]\n", i);
133 device_printf(sc->mrsas_dev,
134 " iov_base: %p\n", user_ioc->sgl[i].iov_base);
135 device_printf(sc->mrsas_dev, " iov_len: %p\n",
136 (void*)user_ioc->sgl[i].iov_len);
137 }
138 device_printf(sc->mrsas_dev,
139 "==================================================================\n");
140}
141
142/**
143 * mrsas_passthru: Handle pass-through commands
144 * input: Adapter instance soft state
145 * argument pointer
146 *
147 * This function is called from mrsas_ioctl() to handle pass-through and
148 * ioctl commands to Firmware.
149 */
68 * mrsas_passthru: Handle pass-through commands
69 * input: Adapter instance soft state
70 * argument pointer
71 *
72 * This function is called from mrsas_ioctl() to handle pass-through and
73 * ioctl commands to Firmware.
74 */
150int mrsas_passthru( struct mrsas_softc *sc, void *arg )
75int mrsas_passthru( struct mrsas_softc *sc, void *arg, u_long ioctlCmd )
151{
152 struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg;
76{
77 struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg;
78#ifdef COMPAT_FREEBSD32
79 struct mrsas_iocpacket32 *user_ioc32 = (struct mrsas_iocpacket32 *)arg;
80#endif
153 union mrsas_frame *in_cmd = (union mrsas_frame *) &(user_ioc->frame.raw);
154 struct mrsas_mfi_cmd *cmd = NULL;
155 bus_dma_tag_t ioctl_data_tag[MAX_IOCTL_SGE];
156 bus_dmamap_t ioctl_data_dmamap[MAX_IOCTL_SGE];
157 void *ioctl_data_mem[MAX_IOCTL_SGE]; // ioctl data virtual addr
158 bus_addr_t ioctl_data_phys_addr[MAX_IOCTL_SGE]; // ioctl data phys addr
159 bus_dma_tag_t ioctl_sense_tag = 0;
160 bus_dmamap_t ioctl_sense_dmamap = 0;
161 void *ioctl_sense_mem = 0;
162 bus_addr_t ioctl_sense_phys_addr = 0;
81 union mrsas_frame *in_cmd = (union mrsas_frame *) &(user_ioc->frame.raw);
82 struct mrsas_mfi_cmd *cmd = NULL;
83 bus_dma_tag_t ioctl_data_tag[MAX_IOCTL_SGE];
84 bus_dmamap_t ioctl_data_dmamap[MAX_IOCTL_SGE];
85 void *ioctl_data_mem[MAX_IOCTL_SGE]; // ioctl data virtual addr
86 bus_addr_t ioctl_data_phys_addr[MAX_IOCTL_SGE]; // ioctl data phys addr
87 bus_dma_tag_t ioctl_sense_tag = 0;
88 bus_dmamap_t ioctl_sense_dmamap = 0;
89 void *ioctl_sense_mem = 0;
90 bus_addr_t ioctl_sense_phys_addr = 0;
163 int i, adapter, ioctl_data_size, ioctl_sense_size, ret=0;
91 int i, ioctl_data_size=0, ioctl_sense_size, ret=0;
164 struct mrsas_sge32 *kern_sge32;
165 unsigned long *sense_ptr;
92 struct mrsas_sge32 *kern_sge32;
93 unsigned long *sense_ptr;
94 uint8_t *iov_base_ptrin=NULL;
95 size_t iov_len=0;
166
96
167 /* For debug - uncomment the following line for debug output */
168 //mrsas_dump_ioctl(sc, user_ioc);
169
170 /*
171 * Check for NOP from MegaCli... MegaCli can issue a DCMD of 0. In this
172 * case do nothing and return 0 to it as status.
173 */
174 if (in_cmd->dcmd.opcode == 0) {
175 device_printf(sc->mrsas_dev, "In %s() Got a NOP\n", __func__);
176 user_ioc->frame.hdr.cmd_status = MFI_STAT_OK;
177 return (0);
178 }
179
97 /*
98 * Check for NOP from MegaCli... MegaCli can issue a DCMD of 0. In this
99 * case do nothing and return 0 to it as status.
100 */
101 if (in_cmd->dcmd.opcode == 0) {
102 device_printf(sc->mrsas_dev, "In %s() Got a NOP\n", __func__);
103 user_ioc->frame.hdr.cmd_status = MFI_STAT_OK;
104 return (0);
105 }
106
180 /* Validate host_no */
181 adapter = user_ioc->host_no;
182 if (adapter != device_get_unit(sc->mrsas_dev)) {
183 device_printf(sc->mrsas_dev, "In %s() IOCTL not for me!\n", __func__);
184 return(ENOENT);
185 }
186
187 /* Validate SGL length */
188 if (user_ioc->sge_count > MAX_IOCTL_SGE) {
189 device_printf(sc->mrsas_dev, "In %s() SGL is too long (%d > 8).\n",
190 __func__, user_ioc->sge_count);
191 return(ENOENT);
192 }
193
194 /* Get a command */
195 cmd = mrsas_get_mfi_cmd(sc);
196 if (!cmd) {
197 device_printf(sc->mrsas_dev, "Failed to get a free cmd for IOCTL\n");
198 return(ENOMEM);
199 }
200
201 /*
202 * User's IOCTL packet has 2 frames (maximum). Copy those two
203 * frames into our cmd's frames. cmd->frame's context will get
204 * overwritten when we copy from user's frames. So set that value
205 * alone separately
206 */
207 memcpy(cmd->frame, user_ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
208 cmd->frame->hdr.context = cmd->index;
209 cmd->frame->hdr.pad_0 = 0;
210 cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 |
211 MFI_FRAME_SENSE64);
212
213 /*
214 * The management interface between applications and the fw uses
215 * MFI frames. E.g, RAID configuration changes, LD property changes
216 * etc are accomplishes through different kinds of MFI frames. The
217 * driver needs to care only about substituting user buffers with
218 * kernel buffers in SGLs. The location of SGL is embedded in the
219 * struct iocpacket itself.
220 */
221 kern_sge32 = (struct mrsas_sge32 *)
222 ((unsigned long)cmd->frame + user_ioc->sgl_off);
223
224 /*
225 * For each user buffer, create a mirror buffer and copy in
226 */
227 for (i=0; i < user_ioc->sge_count; i++) {
107 /* Validate SGL length */
108 if (user_ioc->sge_count > MAX_IOCTL_SGE) {
109 device_printf(sc->mrsas_dev, "In %s() SGL is too long (%d > 8).\n",
110 __func__, user_ioc->sge_count);
111 return(ENOENT);
112 }
113
114 /* Get a command */
115 cmd = mrsas_get_mfi_cmd(sc);
116 if (!cmd) {
117 device_printf(sc->mrsas_dev, "Failed to get a free cmd for IOCTL\n");
118 return(ENOMEM);
119 }
120
121 /*
122 * User's IOCTL packet has 2 frames (maximum). Copy those two
123 * frames into our cmd's frames. cmd->frame's context will get
124 * overwritten when we copy from user's frames. So set that value
125 * alone separately
126 */
127 memcpy(cmd->frame, user_ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
128 cmd->frame->hdr.context = cmd->index;
129 cmd->frame->hdr.pad_0 = 0;
130 cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 |
131 MFI_FRAME_SENSE64);
132
133 /*
134 * The management interface between applications and the fw uses
135 * MFI frames. E.g, RAID configuration changes, LD property changes
136 * etc are accomplishes through different kinds of MFI frames. The
137 * driver needs to care only about substituting user buffers with
138 * kernel buffers in SGLs. The location of SGL is embedded in the
139 * struct iocpacket itself.
140 */
141 kern_sge32 = (struct mrsas_sge32 *)
142 ((unsigned long)cmd->frame + user_ioc->sgl_off);
143
144 /*
145 * For each user buffer, create a mirror buffer and copy in
146 */
147 for (i=0; i < user_ioc->sge_count; i++) {
228 if (!user_ioc->sgl[i].iov_len)
229 continue;
230 ioctl_data_size = user_ioc->sgl[i].iov_len;
148 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
149 if (!user_ioc->sgl[i].iov_len)
150 continue;
151 ioctl_data_size = user_ioc->sgl[i].iov_len;
152#ifdef COMPAT_FREEBSD32
153 } else {
154 if (!user_ioc32->sgl[i].iov_len)
155 continue;
156 ioctl_data_size = user_ioc32->sgl[i].iov_len;
157#endif
158 }
231 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
232 1, 0, // algnmnt, boundary
233 BUS_SPACE_MAXADDR_32BIT,// lowaddr
234 BUS_SPACE_MAXADDR, // highaddr
235 NULL, NULL, // filter, filterarg
236 ioctl_data_size, // maxsize
237 1, // msegments
238 ioctl_data_size, // maxsegsize
239 BUS_DMA_ALLOCNOW, // flags
240 NULL, NULL, // lockfunc, lockarg
241 &ioctl_data_tag[i])) {
159 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
160 1, 0, // algnmnt, boundary
161 BUS_SPACE_MAXADDR_32BIT,// lowaddr
162 BUS_SPACE_MAXADDR, // highaddr
163 NULL, NULL, // filter, filterarg
164 ioctl_data_size, // maxsize
165 1, // msegments
166 ioctl_data_size, // maxsegsize
167 BUS_DMA_ALLOCNOW, // flags
168 NULL, NULL, // lockfunc, lockarg
169 &ioctl_data_tag[i])) {
242 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n");
243 return (ENOMEM);
170 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n");
171 return (ENOMEM);
244 }
245 if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i],
246 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) {
247 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
248 return (ENOMEM);
249 }
250 if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i],
251 ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb,
252 &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) {
253 device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n");
254 return (ENOMEM);
255 }
256
257 /* Save the physical address and length */
258 kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i];
172 }
173 if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i],
174 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) {
175 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
176 return (ENOMEM);
177 }
178 if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i],
179 ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb,
180 &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) {
181 device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n");
182 return (ENOMEM);
183 }
184
185 /* Save the physical address and length */
186 kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i];
259 kern_sge32[i].length = user_ioc->sgl[i].iov_len;
260
187
188 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
189 kern_sge32[i].length = user_ioc->sgl[i].iov_len;
190
191 iov_base_ptrin = user_ioc->sgl[i].iov_base;
192 iov_len = user_ioc->sgl[i].iov_len;
193#ifdef COMPAT_FREEBSD32
194 } else {
195 kern_sge32[i].length = user_ioc32->sgl[i].iov_len;
196
197 iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base);
198 iov_len = user_ioc32->sgl[i].iov_len;
199#endif
200 }
201
261 /* Copy in data from user space */
202 /* Copy in data from user space */
262 ret = copyin(user_ioc->sgl[i].iov_base, ioctl_data_mem[i],
263 user_ioc->sgl[i].iov_len);
203 ret = copyin(iov_base_ptrin, ioctl_data_mem[i], iov_len);
264 if (ret) {
204 if (ret) {
265 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n");
266 goto out;
205 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n");
206 goto out;
267 }
268 }
269
270 ioctl_sense_size = user_ioc->sense_len;
207 }
208 }
209
210 ioctl_sense_size = user_ioc->sense_len;
211
271 if (user_ioc->sense_len) {
272 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
273 1, 0, // algnmnt, boundary
274 BUS_SPACE_MAXADDR_32BIT,// lowaddr
275 BUS_SPACE_MAXADDR, // highaddr
276 NULL, NULL, // filter, filterarg
277 ioctl_sense_size, // maxsize
278 1, // msegments
279 ioctl_sense_size, // maxsegsize
280 BUS_DMA_ALLOCNOW, // flags
281 NULL, NULL, // lockfunc, lockarg
282 &ioctl_sense_tag)) {
283 device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense tag\n");
284 return (ENOMEM);
285 }
286 if (bus_dmamem_alloc(ioctl_sense_tag, (void **)&ioctl_sense_mem,
287 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_sense_dmamap)) {
288 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
289 return (ENOMEM);
290 }
291 if (bus_dmamap_load(ioctl_sense_tag, ioctl_sense_dmamap,
292 ioctl_sense_mem, ioctl_sense_size, mrsas_alloc_cb,
293 &ioctl_sense_phys_addr, BUS_DMA_NOWAIT)) {
294 device_printf(sc->mrsas_dev, "Cannot load ioctl sense mem\n");
295 return (ENOMEM);
296 }
297 sense_ptr =
298 (unsigned long *)((unsigned long)cmd->frame + user_ioc->sense_off);
299 sense_ptr = ioctl_sense_mem;
300 }
301
302 /*
303 * Set the sync_cmd flag so that the ISR knows not to complete this
304 * cmd to the SCSI mid-layer
305 */
306 cmd->sync_cmd = 1;
307 mrsas_issue_blocked_cmd(sc, cmd);
308 cmd->sync_cmd = 0;
309
310 /*
311 * copy out the kernel buffers to user buffers
312 */
313 for (i = 0; i < user_ioc->sge_count; i++) {
212 if (user_ioc->sense_len) {
213 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
214 1, 0, // algnmnt, boundary
215 BUS_SPACE_MAXADDR_32BIT,// lowaddr
216 BUS_SPACE_MAXADDR, // highaddr
217 NULL, NULL, // filter, filterarg
218 ioctl_sense_size, // maxsize
219 1, // msegments
220 ioctl_sense_size, // maxsegsize
221 BUS_DMA_ALLOCNOW, // flags
222 NULL, NULL, // lockfunc, lockarg
223 &ioctl_sense_tag)) {
224 device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense tag\n");
225 return (ENOMEM);
226 }
227 if (bus_dmamem_alloc(ioctl_sense_tag, (void **)&ioctl_sense_mem,
228 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_sense_dmamap)) {
229 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
230 return (ENOMEM);
231 }
232 if (bus_dmamap_load(ioctl_sense_tag, ioctl_sense_dmamap,
233 ioctl_sense_mem, ioctl_sense_size, mrsas_alloc_cb,
234 &ioctl_sense_phys_addr, BUS_DMA_NOWAIT)) {
235 device_printf(sc->mrsas_dev, "Cannot load ioctl sense mem\n");
236 return (ENOMEM);
237 }
238 sense_ptr =
239 (unsigned long *)((unsigned long)cmd->frame + user_ioc->sense_off);
240 sense_ptr = ioctl_sense_mem;
241 }
242
243 /*
244 * Set the sync_cmd flag so that the ISR knows not to complete this
245 * cmd to the SCSI mid-layer
246 */
247 cmd->sync_cmd = 1;
248 mrsas_issue_blocked_cmd(sc, cmd);
249 cmd->sync_cmd = 0;
250
251 /*
252 * copy out the kernel buffers to user buffers
253 */
254 for (i = 0; i < user_ioc->sge_count; i++) {
314 ret = copyout(ioctl_data_mem[i], user_ioc->sgl[i].iov_base,
315 user_ioc->sgl[i].iov_len);
255 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
256 iov_base_ptrin = user_ioc->sgl[i].iov_base;
257 iov_len = user_ioc->sgl[i].iov_len;
258#ifdef COMPAT_FREEBSD32
259 } else {
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 ret = copyout(ioctl_data_mem[i], iov_base_ptrin, iov_len);
316 if (ret) {
317 device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n");
318 goto out;
319 }
320 }
321
322 /*
323 * copy out the sense
324 */
325 if (user_ioc->sense_len) {
326 /*
327 * sense_buff points to the location that has the user
328 * sense buffer address
329 */
330 sense_ptr = (unsigned long *) ((unsigned long)user_ioc->frame.raw +
331 user_ioc->sense_off);
332 ret = copyout(ioctl_sense_mem, (unsigned long*)*sense_ptr,
333 user_ioc->sense_len);
334 if (ret) {
335 device_printf(sc->mrsas_dev, "IOCTL sense copyout failed!\n");
336 goto out;
337 }
338 }
339
340 /*
341 * Return command status to user space
342 */
343 memcpy(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status,
344 sizeof(u_int8_t));
345
346out:
347 /*
348 * Release sense buffer
349 */
350 if (ioctl_sense_phys_addr)
351 bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap);
352 if (ioctl_sense_mem)
353 bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap);
354 if (ioctl_sense_tag)
355 bus_dma_tag_destroy(ioctl_sense_tag);
356
357 /*
358 * Release data buffers
359 */
360 for (i = 0; i < user_ioc->sge_count; i++) {
361 if (!user_ioc->sgl[i].iov_len)
362 continue;
363 if (ioctl_data_phys_addr[i])
364 bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]);
365 if (ioctl_data_mem[i] != NULL)
366 bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i],
367 ioctl_data_dmamap[i]);
368 if (ioctl_data_tag[i] != NULL)
369 bus_dma_tag_destroy(ioctl_data_tag[i]);
370 }
266 if (ret) {
267 device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n");
268 goto out;
269 }
270 }
271
272 /*
273 * copy out the sense
274 */
275 if (user_ioc->sense_len) {
276 /*
277 * sense_buff points to the location that has the user
278 * sense buffer address
279 */
280 sense_ptr = (unsigned long *) ((unsigned long)user_ioc->frame.raw +
281 user_ioc->sense_off);
282 ret = copyout(ioctl_sense_mem, (unsigned long*)*sense_ptr,
283 user_ioc->sense_len);
284 if (ret) {
285 device_printf(sc->mrsas_dev, "IOCTL sense copyout failed!\n");
286 goto out;
287 }
288 }
289
290 /*
291 * Return command status to user space
292 */
293 memcpy(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status,
294 sizeof(u_int8_t));
295
296out:
297 /*
298 * Release sense buffer
299 */
300 if (ioctl_sense_phys_addr)
301 bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap);
302 if (ioctl_sense_mem)
303 bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap);
304 if (ioctl_sense_tag)
305 bus_dma_tag_destroy(ioctl_sense_tag);
306
307 /*
308 * Release data buffers
309 */
310 for (i = 0; i < user_ioc->sge_count; i++) {
311 if (!user_ioc->sgl[i].iov_len)
312 continue;
313 if (ioctl_data_phys_addr[i])
314 bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]);
315 if (ioctl_data_mem[i] != NULL)
316 bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i],
317 ioctl_data_dmamap[i]);
318 if (ioctl_data_tag[i] != NULL)
319 bus_dma_tag_destroy(ioctl_data_tag[i]);
320 }
371
372 /* Free command */
373 mrsas_release_mfi_cmd(cmd);
374
375 return(ret);
376}
377
378/**
379 * mrsas_alloc_mfi_cmds: Allocates the command packets
380 * input: Adapter instance soft state
381 *
382 * Each IOCTL or passthru command that is issued to the FW are wrapped in a
383 * local data structure called mrsas_mfi_cmd. The frame embedded in this
384 * mrsas_mfi is issued to FW. The array is used only to look up the
385 * mrsas_mfi_cmd given the context. The free commands are maintained in a
386 * linked list.
387 */
388int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc)
389{
390 int i, j;
391 u_int32_t max_cmd;
392 struct mrsas_mfi_cmd *cmd;
393
394 max_cmd = MRSAS_MAX_MFI_CMDS;
395
396 /*
397 * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers. Allocate the
398 * dynamic array first and then allocate individual commands.
399 */
400 sc->mfi_cmd_list = malloc(sizeof(struct mrsas_mfi_cmd*)*max_cmd, M_MRSAS, M_NOWAIT);
401 if (!sc->mfi_cmd_list) {
402 device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n");
403 return(ENOMEM);
404 }
405 memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *)*max_cmd);
406 for (i = 0; i < max_cmd; i++) {
407 sc->mfi_cmd_list[i] = malloc(sizeof(struct mrsas_mfi_cmd),
408 M_MRSAS, M_NOWAIT);
409 if (!sc->mfi_cmd_list[i]) {
410 for (j = 0; j < i; j++)
411 free(sc->mfi_cmd_list[j],M_MRSAS);
412 free(sc->mfi_cmd_list, M_MRSAS);
413 sc->mfi_cmd_list = NULL;
414 return(ENOMEM);
415 }
416 }
417
418 for (i = 0; i < max_cmd; i++) {
419 cmd = sc->mfi_cmd_list[i];
420 memset(cmd, 0, sizeof(struct mrsas_mfi_cmd));
421 cmd->index = i;
422 cmd->ccb_ptr = NULL;
423 cmd->sc = sc;
424 TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next);
425 }
426
427 /* create a frame pool and assign one frame to each command */
428 if (mrsas_create_frame_pool(sc)) {
429 device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n");
430 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { // Free the frames
431 cmd = sc->mfi_cmd_list[i];
432 mrsas_free_frame(sc, cmd);
433 }
434 if (sc->mficmd_frame_tag != NULL)
435 bus_dma_tag_destroy(sc->mficmd_frame_tag);
436 return(ENOMEM);
437 }
438
439 return(0);
440}
441
442/**
443 * mrsas_create_frame_pool - Creates DMA pool for cmd frames
444 * input: Adapter soft state
445 *
446 * Each command packet has an embedded DMA memory buffer that is used for
447 * filling MFI frame and the SG list that immediately follows the frame. This
448 * function creates those DMA memory buffers for each command packet by using
449 * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value
450 * of context and could cause FW crash.
451 */
452static int mrsas_create_frame_pool(struct mrsas_softc *sc)
453{
454 int i;
455 struct mrsas_mfi_cmd *cmd;
456
457 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
458 1, 0, // algnmnt, boundary
459 BUS_SPACE_MAXADDR_32BIT,// lowaddr
460 BUS_SPACE_MAXADDR, // highaddr
461 NULL, NULL, // filter, filterarg
462 MRSAS_MFI_FRAME_SIZE, // maxsize
463 1, // msegments
464 MRSAS_MFI_FRAME_SIZE, // maxsegsize
465 BUS_DMA_ALLOCNOW, // flags
466 NULL, NULL, // lockfunc, lockarg
467 &sc->mficmd_frame_tag)) {
468 device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n");
469 return (ENOMEM);
470 }
471
472 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
473 cmd = sc->mfi_cmd_list[i];
474 cmd->frame = mrsas_alloc_frame(sc, cmd);
475 if (cmd->frame == NULL) {
476 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
477 return (ENOMEM);
478 }
479 memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE);
480 cmd->frame->io.context = cmd->index;
481 cmd->frame->io.pad_0 = 0;
482 }
483
484 return(0);
485}
486
487/**
488 * mrsas_alloc_frame - Allocates MFI Frames
489 * input: Adapter soft state
490 *
491 * Create bus DMA memory tag and dmamap and load memory for MFI frames.
492 * Returns virtual memory pointer to allocated region.
493 */
494void *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
495{
496 u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE;
497
498 if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem,
499 BUS_DMA_NOWAIT, &cmd->frame_dmamap)) {
500 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
501 return (NULL);
502 }
503 if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap,
504 cmd->frame_mem, frame_size, mrsas_alloc_cb,
505 &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) {
506 device_printf(sc->mrsas_dev, "Cannot load IO request memory\n");
507 return (NULL);
508 }
509
510 return(cmd->frame_mem);
511}
512
513/*
514 * mrsas_alloc_cb: Callback function of bus_dmamap_load()
515 * input: callback argument,
516 * machine dependent type that describes DMA segments,
517 * number of segments,
518 * error code.
519 *
520 * This function is for the driver to receive mapping information resultant
521 * of the bus_dmamap_load(). The information is actually not being used,
522 * but the address is saved anyway.
523 */
524static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
525 int nsegs, int error)
526{
527 bus_addr_t *addr;
528
529 addr = arg;
530 *addr = segs[0].ds_addr;
531}
532
533/**
534 * mrsas_free_frames: Frees memory for MFI frames
535 * input: Adapter soft state
536 *
537 * Deallocates MFI frames memory. Called from mrsas_free_mem() during
538 * detach and error case during creation of frame pool.
539 */
540void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
541{
542 if (cmd->frame_phys_addr)
543 bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap);
544 if (cmd->frame_mem != NULL)
545 bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap);
546}
321 /* Free command */
322 mrsas_release_mfi_cmd(cmd);
323
324 return(ret);
325}
326
327/**
328 * mrsas_alloc_mfi_cmds: Allocates the command packets
329 * input: Adapter instance soft state
330 *
331 * Each IOCTL or passthru command that is issued to the FW are wrapped in a
332 * local data structure called mrsas_mfi_cmd. The frame embedded in this
333 * mrsas_mfi is issued to FW. The array is used only to look up the
334 * mrsas_mfi_cmd given the context. The free commands are maintained in a
335 * linked list.
336 */
337int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc)
338{
339 int i, j;
340 u_int32_t max_cmd;
341 struct mrsas_mfi_cmd *cmd;
342
343 max_cmd = MRSAS_MAX_MFI_CMDS;
344
345 /*
346 * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers. Allocate the
347 * dynamic array first and then allocate individual commands.
348 */
349 sc->mfi_cmd_list = malloc(sizeof(struct mrsas_mfi_cmd*)*max_cmd, M_MRSAS, M_NOWAIT);
350 if (!sc->mfi_cmd_list) {
351 device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n");
352 return(ENOMEM);
353 }
354 memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *)*max_cmd);
355 for (i = 0; i < max_cmd; i++) {
356 sc->mfi_cmd_list[i] = malloc(sizeof(struct mrsas_mfi_cmd),
357 M_MRSAS, M_NOWAIT);
358 if (!sc->mfi_cmd_list[i]) {
359 for (j = 0; j < i; j++)
360 free(sc->mfi_cmd_list[j],M_MRSAS);
361 free(sc->mfi_cmd_list, M_MRSAS);
362 sc->mfi_cmd_list = NULL;
363 return(ENOMEM);
364 }
365 }
366
367 for (i = 0; i < max_cmd; i++) {
368 cmd = sc->mfi_cmd_list[i];
369 memset(cmd, 0, sizeof(struct mrsas_mfi_cmd));
370 cmd->index = i;
371 cmd->ccb_ptr = NULL;
372 cmd->sc = sc;
373 TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next);
374 }
375
376 /* create a frame pool and assign one frame to each command */
377 if (mrsas_create_frame_pool(sc)) {
378 device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n");
379 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { // Free the frames
380 cmd = sc->mfi_cmd_list[i];
381 mrsas_free_frame(sc, cmd);
382 }
383 if (sc->mficmd_frame_tag != NULL)
384 bus_dma_tag_destroy(sc->mficmd_frame_tag);
385 return(ENOMEM);
386 }
387
388 return(0);
389}
390
391/**
392 * mrsas_create_frame_pool - Creates DMA pool for cmd frames
393 * input: Adapter soft state
394 *
395 * Each command packet has an embedded DMA memory buffer that is used for
396 * filling MFI frame and the SG list that immediately follows the frame. This
397 * function creates those DMA memory buffers for each command packet by using
398 * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value
399 * of context and could cause FW crash.
400 */
401static int mrsas_create_frame_pool(struct mrsas_softc *sc)
402{
403 int i;
404 struct mrsas_mfi_cmd *cmd;
405
406 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
407 1, 0, // algnmnt, boundary
408 BUS_SPACE_MAXADDR_32BIT,// lowaddr
409 BUS_SPACE_MAXADDR, // highaddr
410 NULL, NULL, // filter, filterarg
411 MRSAS_MFI_FRAME_SIZE, // maxsize
412 1, // msegments
413 MRSAS_MFI_FRAME_SIZE, // maxsegsize
414 BUS_DMA_ALLOCNOW, // flags
415 NULL, NULL, // lockfunc, lockarg
416 &sc->mficmd_frame_tag)) {
417 device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n");
418 return (ENOMEM);
419 }
420
421 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
422 cmd = sc->mfi_cmd_list[i];
423 cmd->frame = mrsas_alloc_frame(sc, cmd);
424 if (cmd->frame == NULL) {
425 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
426 return (ENOMEM);
427 }
428 memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE);
429 cmd->frame->io.context = cmd->index;
430 cmd->frame->io.pad_0 = 0;
431 }
432
433 return(0);
434}
435
436/**
437 * mrsas_alloc_frame - Allocates MFI Frames
438 * input: Adapter soft state
439 *
440 * Create bus DMA memory tag and dmamap and load memory for MFI frames.
441 * Returns virtual memory pointer to allocated region.
442 */
443void *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
444{
445 u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE;
446
447 if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem,
448 BUS_DMA_NOWAIT, &cmd->frame_dmamap)) {
449 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
450 return (NULL);
451 }
452 if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap,
453 cmd->frame_mem, frame_size, mrsas_alloc_cb,
454 &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) {
455 device_printf(sc->mrsas_dev, "Cannot load IO request memory\n");
456 return (NULL);
457 }
458
459 return(cmd->frame_mem);
460}
461
462/*
463 * mrsas_alloc_cb: Callback function of bus_dmamap_load()
464 * input: callback argument,
465 * machine dependent type that describes DMA segments,
466 * number of segments,
467 * error code.
468 *
469 * This function is for the driver to receive mapping information resultant
470 * of the bus_dmamap_load(). The information is actually not being used,
471 * but the address is saved anyway.
472 */
473static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
474 int nsegs, int error)
475{
476 bus_addr_t *addr;
477
478 addr = arg;
479 *addr = segs[0].ds_addr;
480}
481
482/**
483 * mrsas_free_frames: Frees memory for MFI frames
484 * input: Adapter soft state
485 *
486 * Deallocates MFI frames memory. Called from mrsas_free_mem() during
487 * detach and error case during creation of frame pool.
488 */
489void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
490{
491 if (cmd->frame_phys_addr)
492 bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap);
493 if (cmd->frame_mem != NULL)
494 bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap);
495}