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}
|