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$"); 46 47 #include <dev/mrsas/mrsas.h> 48 #include <dev/mrsas/mrsas_ioctl.h> 49 50 /* 51 * Function prototypes 52 */ 53 int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc); 54 int mrsas_passthru(struct mrsas_softc *sc, void *arg); 55 void mrsas_free_ioc_cmd(struct mrsas_softc *sc); 56 void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 57 void mrsas_dump_dcmd(struct mrsas_softc *sc, struct mrsas_dcmd_frame* dcmd); 58 void mrsas_dump_ioctl(struct mrsas_softc *sc, struct mrsas_iocpacket *user_ioc); 59 void * mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 60 static int mrsas_create_frame_pool(struct mrsas_softc *sc); 61 static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs, 62 int nsegs, int error); 63 64 extern struct mrsas_mfi_cmd* mrsas_get_mfi_cmd(struct mrsas_softc *sc); 65 extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd); 66 extern int mrsas_issue_blocked_cmd(struct mrsas_softc *sc, 67 struct mrsas_mfi_cmd *cmd); 68 69 70 /** 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 */ 78 void 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 */ 114 void 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 */ 150 int mrsas_passthru( struct mrsas_softc *sc, void *arg ) 151 { 152 struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg; 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; 163 int i, adapter, ioctl_data_size, ioctl_sense_size, ret=0; 164 struct mrsas_sge32 *kern_sge32; 165 unsigned long *sense_ptr; 166 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 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++) { 228 if (!user_ioc->sgl[i].iov_len) 229 continue; 230 ioctl_data_size = user_ioc->sgl[i].iov_len; 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])) { 242 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n"); 243 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]; 259 kern_sge32[i].length = user_ioc->sgl[i].iov_len; 260 261 /* 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); 264 if (ret) { 265 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n"); 266 goto out; 267 } 268 } 269 270 ioctl_sense_size = user_ioc->sense_len; 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++) { 314 ret = copyout(ioctl_data_mem[i], user_ioc->sgl[i].iov_base, 315 user_ioc->sgl[i].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 346 out: 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 } 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 */ 388 int 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 */ 452 static 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 */ 494 void *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 */ 524 static 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 */ 540 void 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 } 547