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 ioctl_data_size, // maxsize 234 1, // msegments 235 ioctl_data_size, // maxsegsize 236 BUS_DMA_ALLOCNOW, // flags 237 &ioctl_data_tag[i])) { 238 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n"); 239 return (ENOMEM); 240 } 241 if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i], 242 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) { 243 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n"); 244 return (ENOMEM); 245 } 246 if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i], 247 ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb, 248 &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) { 249 device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n"); 250 return (ENOMEM); 251 } 252 253 /* Save the physical address and length */ 254 kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i]; 255 kern_sge32[i].length = user_ioc->sgl[i].iov_len; 256 257 /* Copy in data from user space */ 258 ret = copyin(user_ioc->sgl[i].iov_base, ioctl_data_mem[i], 259 user_ioc->sgl[i].iov_len); 260 if (ret) { 261 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n"); 262 goto out; 263 } 264 } 265 266 ioctl_sense_size = user_ioc->sense_len; 267 if (user_ioc->sense_len) { 268 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent 269 1, 0, // algnmnt, boundary 270 BUS_SPACE_MAXADDR_32BIT,// lowaddr 271 BUS_SPACE_MAXADDR, // highaddr 272 ioctl_sense_size, // maxsize 273 1, // msegments 274 ioctl_sense_size, // maxsegsize 275 BUS_DMA_ALLOCNOW, // flags 276 &ioctl_sense_tag)) { 277 device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense tag\n"); 278 return (ENOMEM); 279 } 280 if (bus_dmamem_alloc(ioctl_sense_tag, (void **)&ioctl_sense_mem, 281 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_sense_dmamap)) { 282 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n"); 283 return (ENOMEM); 284 } 285 if (bus_dmamap_load(ioctl_sense_tag, ioctl_sense_dmamap, 286 ioctl_sense_mem, ioctl_sense_size, mrsas_alloc_cb, 287 &ioctl_sense_phys_addr, BUS_DMA_NOWAIT)) { 288 device_printf(sc->mrsas_dev, "Cannot load ioctl sense mem\n"); 289 return (ENOMEM); 290 } 291 sense_ptr = 292 (unsigned long *)((unsigned long)cmd->frame + user_ioc->sense_off); 293 *sense_ptr = ioctl_sense_phys_addr; 294 } 295 296 /* 297 * Set the sync_cmd flag so that the ISR knows not to complete this 298 * cmd to the SCSI mid-layer 299 */ 300 cmd->sync_cmd = 1; 301 mrsas_issue_blocked_cmd(sc, cmd); 302 cmd->sync_cmd = 0; 303 304 /* 305 * copy out the kernel buffers to user buffers 306 */ 307 for (i = 0; i < user_ioc->sge_count; i++) { 308 ret = copyout(ioctl_data_mem[i], user_ioc->sgl[i].iov_base, 309 user_ioc->sgl[i].iov_len); 310 if (ret) { 311 device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n"); 312 goto out; 313 } 314 } 315 316 /* 317 * copy out the sense 318 */ 319 if (user_ioc->sense_len) { 320 /* 321 * sense_buff points to the location that has the user 322 * sense buffer address 323 */ 324 sense_ptr = (unsigned long *) ((unsigned long)user_ioc->frame.raw + 325 user_ioc->sense_off); 326 ret = copyout(ioctl_sense_mem, (unsigned long*)*sense_ptr, 327 user_ioc->sense_len); 328 if (ret) { 329 device_printf(sc->mrsas_dev, "IOCTL sense copyout failed!\n"); 330 goto out; 331 } 332 } 333 334 /* 335 * Return command status to user space 336 */ 337 memcpy(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status, 338 sizeof(u_int8_t)); 339 340 out: 341 /* 342 * Release sense buffer 343 */ 344 if (ioctl_sense_phys_addr) 345 bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap); 346 if (ioctl_sense_mem) 347 bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap); 348 if (ioctl_sense_tag) 349 bus_dma_tag_destroy(ioctl_sense_tag); 350 351 /* 352 * Release data buffers 353 */ 354 for (i = 0; i < user_ioc->sge_count; i++) { 355 if (!user_ioc->sgl[i].iov_len) 356 continue; 357 if (ioctl_data_phys_addr[i]) 358 bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]); 359 if (ioctl_data_mem[i] != NULL) 360 bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i], 361 ioctl_data_dmamap[i]); 362 if (ioctl_data_tag[i] != NULL) 363 bus_dma_tag_destroy(ioctl_data_tag[i]); 364 } 365 366 /* Free command */ 367 mrsas_release_mfi_cmd(cmd); 368 369 return(ret); 370 } 371 372 /** 373 * mrsas_alloc_mfi_cmds: Allocates the command packets 374 * input: Adapter instance soft state 375 * 376 * Each IOCTL or passthru command that is issued to the FW are wrapped in a 377 * local data structure called mrsas_mfi_cmd. The frame embedded in this 378 * mrsas_mfi is issued to FW. The array is used only to look up the 379 * mrsas_mfi_cmd given the context. The free commands are maintained in a 380 * linked list. 381 */ 382 int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc) 383 { 384 int i, j; 385 u_int32_t max_cmd; 386 struct mrsas_mfi_cmd *cmd; 387 388 max_cmd = MRSAS_MAX_MFI_CMDS; 389 390 /* 391 * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers. Allocate the 392 * dynamic array first and then allocate individual commands. 393 */ 394 sc->mfi_cmd_list = kmalloc(sizeof(struct mrsas_mfi_cmd*)*max_cmd, M_MRSAS, M_NOWAIT); 395 if (!sc->mfi_cmd_list) { 396 device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n"); 397 return(ENOMEM); 398 } 399 memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *)*max_cmd); 400 for (i = 0; i < max_cmd; i++) { 401 sc->mfi_cmd_list[i] = kmalloc(sizeof(struct mrsas_mfi_cmd), 402 M_MRSAS, M_NOWAIT); 403 if (!sc->mfi_cmd_list[i]) { 404 for (j = 0; j < i; j++) 405 kfree(sc->mfi_cmd_list[j],M_MRSAS); 406 kfree(sc->mfi_cmd_list, M_MRSAS); 407 sc->mfi_cmd_list = NULL; 408 return(ENOMEM); 409 } 410 } 411 412 for (i = 0; i < max_cmd; i++) { 413 cmd = sc->mfi_cmd_list[i]; 414 memset(cmd, 0, sizeof(struct mrsas_mfi_cmd)); 415 cmd->index = i; 416 cmd->ccb_ptr = NULL; 417 cmd->sc = sc; 418 TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next); 419 } 420 421 /* create a frame pool and assign one frame to each command */ 422 if (mrsas_create_frame_pool(sc)) { 423 device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n"); 424 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { // Free the frames 425 cmd = sc->mfi_cmd_list[i]; 426 mrsas_free_frame(sc, cmd); 427 } 428 if (sc->mficmd_frame_tag != NULL) 429 bus_dma_tag_destroy(sc->mficmd_frame_tag); 430 return(ENOMEM); 431 } 432 433 return(0); 434 } 435 436 /** 437 * mrsas_create_frame_pool - Creates DMA pool for cmd frames 438 * input: Adapter soft state 439 * 440 * Each command packet has an embedded DMA memory buffer that is used for 441 * filling MFI frame and the SG list that immediately follows the frame. This 442 * function creates those DMA memory buffers for each command packet by using 443 * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value 444 * of context and could cause FW crash. 445 */ 446 static int mrsas_create_frame_pool(struct mrsas_softc *sc) 447 { 448 int i; 449 struct mrsas_mfi_cmd *cmd; 450 451 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent 452 1, 0, // algnmnt, boundary 453 BUS_SPACE_MAXADDR_32BIT,// lowaddr 454 BUS_SPACE_MAXADDR, // highaddr 455 MRSAS_MFI_FRAME_SIZE, // maxsize 456 1, // msegments 457 MRSAS_MFI_FRAME_SIZE, // maxsegsize 458 BUS_DMA_ALLOCNOW, // flags 459 &sc->mficmd_frame_tag)) { 460 device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n"); 461 return (ENOMEM); 462 } 463 464 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { 465 cmd = sc->mfi_cmd_list[i]; 466 cmd->frame = mrsas_alloc_frame(sc, cmd); 467 if (cmd->frame == NULL) { 468 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n"); 469 return (ENOMEM); 470 } 471 memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE); 472 cmd->frame->io.context = cmd->index; 473 cmd->frame->io.pad_0 = 0; 474 } 475 476 return(0); 477 } 478 479 /** 480 * mrsas_alloc_frame - Allocates MFI Frames 481 * input: Adapter soft state 482 * 483 * Create bus DMA memory tag and dmamap and load memory for MFI frames. 484 * Returns virtual memory pointer to allocated region. 485 */ 486 void *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 487 { 488 u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE; 489 490 if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem, 491 BUS_DMA_NOWAIT, &cmd->frame_dmamap)) { 492 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n"); 493 return (NULL); 494 } 495 if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap, 496 cmd->frame_mem, frame_size, mrsas_alloc_cb, 497 &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) { 498 device_printf(sc->mrsas_dev, "Cannot load IO request memory\n"); 499 return (NULL); 500 } 501 502 return(cmd->frame_mem); 503 } 504 505 /* 506 * mrsas_alloc_cb: Callback function of bus_dmamap_load() 507 * input: callback argument, 508 * machine dependent type that describes DMA segments, 509 * number of segments, 510 * error code. 511 * 512 * This function is for the driver to receive mapping information resultant 513 * of the bus_dmamap_load(). The information is actually not being used, 514 * but the address is saved anyway. 515 */ 516 static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs, 517 int nsegs, int error) 518 { 519 bus_addr_t *addr; 520 521 addr = arg; 522 *addr = segs[0].ds_addr; 523 } 524 525 /** 526 * mrsas_free_frames: Frees memory for MFI frames 527 * input: Adapter soft state 528 * 529 * Deallocates MFI frames memory. Called from mrsas_free_mem() during 530 * detach and error case during creation of frame pool. 531 */ 532 void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 533 { 534 if (cmd->frame_phys_addr) 535 bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap); 536 if (cmd->frame_mem != NULL) 537 bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap); 538 } 539