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