1 /* 2 * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy 3 * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy 4 * Support: freebsdraid@avagotech.com 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * 1. Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 2. Redistributions 12 * in binary form must reproduce the above copyright notice, this list of 13 * conditions and the following disclaimer in the documentation and/or other 14 * materials provided with the distribution. 3. Neither the name of the 15 * <ORGANIZATION> nor the names of its contributors may be used to endorse or 16 * promote products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 * 31 * The views and conclusions contained in the software and documentation are 32 * those of the authors and should not be interpreted as representing 33 * official policies,either expressed or implied, of the FreeBSD Project. 34 * 35 * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 36 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD 37 * 38 */ 39 40 #include <sys/cdefs.h> 41 #include <sys/abi_compat.h> 42 #include <dev/mrsas/mrsas.h> 43 #include <dev/mrsas/mrsas_ioctl.h> 44 45 struct mrsas_passthru_cmd { 46 struct mrsas_sge64 *kern_sge; 47 struct mrsas_softc *sc; 48 struct mrsas_mfi_cmd *cmd; 49 bus_dma_tag_t ioctl_data_tag; 50 bus_dmamap_t ioctl_data_dmamap; 51 52 u_int32_t error_code; 53 u_int32_t sge_count; 54 int complete; 55 }; 56 57 /* 58 * Function prototypes 59 */ 60 int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc); 61 int mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd); 62 void mrsas_free_ioc_cmd(struct mrsas_softc *sc); 63 void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 64 void *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 65 static int mrsas_create_frame_pool(struct mrsas_softc *sc); 66 static void 67 mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs, 68 int nsegs, int error); 69 70 extern struct mrsas_mfi_cmd *mrsas_get_mfi_cmd(struct mrsas_softc *sc); 71 extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd); 72 extern int 73 mrsas_issue_blocked_cmd(struct mrsas_softc *sc, 74 struct mrsas_mfi_cmd *cmd); 75 76 /* 77 * mrsas_data_load_cb: Callback entry point 78 * input: Pointer to command packet as argument 79 * Pointer to segment 80 * Number of segments Error 81 * 82 * This is the callback function of the bus dma map load. It builds the SG 83 * list. 84 */ 85 static void 86 mrsas_passthru_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 87 { 88 struct mrsas_passthru_cmd *cb = (struct mrsas_passthru_cmd *)arg; 89 struct mrsas_softc *sc = cb->sc; 90 int i = 0; 91 92 if (error) { 93 cb->error_code = error; 94 if (error == EFBIG) { 95 device_printf(sc->mrsas_dev, "mrsas_passthru_load_cb: " 96 "error=%d EFBIG\n", error); 97 cb->complete = 1; 98 return; 99 } else { 100 device_printf(sc->mrsas_dev, "mrsas_passthru_load_cb: " 101 "error=%d UNKNOWN\n", error); 102 } 103 } 104 if (nseg > MAX_IOCTL_SGE) { 105 cb->error_code = EFBIG; 106 device_printf(sc->mrsas_dev, "mrsas_passthru_load_cb: " 107 "too many segments: %d\n", nseg); 108 cb->complete = 1; 109 return; 110 } 111 112 for (i = 0; i < nseg; i++) { 113 cb->kern_sge[i].phys_addr = htole64(segs[i].ds_addr); 114 cb->kern_sge[i].length = htole32(segs[i].ds_len); 115 } 116 cb->sge_count = nseg; 117 118 bus_dmamap_sync(cb->ioctl_data_tag, cb->ioctl_data_dmamap, 119 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 120 121 cb->complete = 1; 122 } 123 124 /* 125 * mrsas_passthru: Handle pass-through commands 126 * input: Adapter instance soft state argument pointer 127 * 128 * This function is called from mrsas_ioctl() to handle pass-through and ioctl 129 * commands to Firmware. 130 */ 131 int 132 mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd) 133 { 134 struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg; 135 136 #ifdef COMPAT_FREEBSD32 137 struct mrsas_iocpacket32 *user_ioc32 = (struct mrsas_iocpacket32 *)arg; 138 139 #endif 140 union mrsas_frame *in_cmd = (union mrsas_frame *)&(user_ioc->frame.raw); 141 struct mrsas_mfi_cmd *cmd = NULL; 142 bus_dma_tag_t ioctl_data_tag[MAX_IOCTL_SGE]; 143 bus_dmamap_t ioctl_data_dmamap[MAX_IOCTL_SGE]; 144 void *ioctl_data_mem[MAX_IOCTL_SGE]; 145 bus_addr_t ioctl_data_phys_addr[MAX_IOCTL_SGE]; 146 bus_dma_tag_t ioctl_sense_tag = 0; 147 bus_dmamap_t ioctl_sense_dmamap = 0; 148 void *ioctl_sense_mem = NULL; 149 bus_addr_t ioctl_sense_phys_addr = 0; 150 int i, ioctl_data_size = 0, ioctl_sense_size, ret = 0; 151 struct mrsas_sge32 *kern_sge32; 152 unsigned long *sense_ptr; 153 uint8_t *iov_base_ptrin = NULL; 154 size_t iov_len = 0; 155 156 /* 157 * Check for NOP from MegaCli... MegaCli can issue a DCMD of 0. In 158 * this case do nothing and return 0 to it as status. 159 */ 160 if (in_cmd->dcmd.opcode == 0) { 161 device_printf(sc->mrsas_dev, "In %s() Got a NOP\n", __func__); 162 user_ioc->frame.hdr.cmd_status = MFI_STAT_OK; 163 return (0); 164 } 165 /* Validate SGL length */ 166 if (user_ioc->sge_count > MAX_IOCTL_SGE) { 167 device_printf(sc->mrsas_dev, "In %s() SGL is too long (%d > 8).\n", 168 __func__, user_ioc->sge_count); 169 return (ENOENT); 170 } 171 /* Get a command */ 172 cmd = mrsas_get_mfi_cmd(sc); 173 if (!cmd) { 174 device_printf(sc->mrsas_dev, "Failed to get a free cmd for IOCTL\n"); 175 return (ENOMEM); 176 } 177 /* 178 * User's IOCTL packet has 2 frames (maximum). Copy those two frames 179 * into our cmd's frames. cmd->frame's context will get overwritten 180 * when we copy from user's frames. So set that value alone 181 * separately 182 */ 183 memcpy(cmd->frame, user_ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); 184 cmd->frame->hdr.context = cmd->index; 185 cmd->frame->hdr.pad_0 = 0; 186 cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 | 187 MFI_FRAME_SENSE64); 188 189 /* 190 * The management interface between applications and the fw uses MFI 191 * frames. E.g, RAID configuration changes, LD property changes etc 192 * are accomplishes through different kinds of MFI frames. The driver 193 * needs to care only about substituting user buffers with kernel 194 * buffers in SGLs. The location of SGL is embedded in the struct 195 * iocpacket itself. 196 */ 197 kern_sge32 = (struct mrsas_sge32 *) 198 ((uintptr_t)cmd->frame + user_ioc->sgl_off); 199 200 memset(ioctl_data_tag, 0, (sizeof(bus_dma_tag_t) * MAX_IOCTL_SGE)); 201 memset(ioctl_data_dmamap, 0, (sizeof(bus_dmamap_t) * MAX_IOCTL_SGE)); 202 memset(ioctl_data_mem, 0, (sizeof(void *) * MAX_IOCTL_SGE)); 203 memset(ioctl_data_phys_addr, 0, (sizeof(bus_addr_t) * MAX_IOCTL_SGE)); 204 205 /* 206 * For each user buffer, create a mirror buffer and copy in 207 */ 208 for (i = 0; i < user_ioc->sge_count; i++) { 209 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) { 210 if (!user_ioc->sgl[i].iov_len) 211 continue; 212 ioctl_data_size = user_ioc->sgl[i].iov_len; 213 #ifdef COMPAT_FREEBSD32 214 } else { 215 if (!user_ioc32->sgl[i].iov_len) 216 continue; 217 ioctl_data_size = user_ioc32->sgl[i].iov_len; 218 #endif 219 } 220 if (bus_dma_tag_create(sc->mrsas_parent_tag, 221 1, 0, 222 BUS_SPACE_MAXADDR_32BIT, 223 BUS_SPACE_MAXADDR, 224 NULL, NULL, 225 ioctl_data_size, 226 1, 227 ioctl_data_size, 228 BUS_DMA_ALLOCNOW, 229 NULL, NULL, 230 &ioctl_data_tag[i])) { 231 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n"); 232 ret = ENOMEM; 233 goto out; 234 } 235 if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i], 236 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) { 237 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n"); 238 ret = ENOMEM; 239 goto out; 240 } 241 if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i], 242 ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb, 243 &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) { 244 device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n"); 245 ret = ENOMEM; 246 goto out; 247 } 248 /* Save the physical address and length */ 249 kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i]; 250 251 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) { 252 kern_sge32[i].length = user_ioc->sgl[i].iov_len; 253 254 iov_base_ptrin = user_ioc->sgl[i].iov_base; 255 iov_len = user_ioc->sgl[i].iov_len; 256 #ifdef COMPAT_FREEBSD32 257 } else { 258 kern_sge32[i].length = user_ioc32->sgl[i].iov_len; 259 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 /* Copy in data from user space */ 266 ret = copyin(iov_base_ptrin, ioctl_data_mem[i], iov_len); 267 if (ret) { 268 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n"); 269 goto out; 270 } 271 } 272 273 ioctl_sense_size = user_ioc->sense_len; 274 275 if (user_ioc->sense_len) { 276 if (bus_dma_tag_create(sc->mrsas_parent_tag, 277 1, 0, 278 BUS_SPACE_MAXADDR_32BIT, 279 BUS_SPACE_MAXADDR, 280 NULL, NULL, 281 ioctl_sense_size, 282 1, 283 ioctl_sense_size, 284 BUS_DMA_ALLOCNOW, 285 NULL, NULL, 286 &ioctl_sense_tag)) { 287 device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense tag\n"); 288 ret = ENOMEM; 289 goto out; 290 } 291 if (bus_dmamem_alloc(ioctl_sense_tag, (void **)&ioctl_sense_mem, 292 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_sense_dmamap)) { 293 device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense mem\n"); 294 ret = ENOMEM; 295 goto out; 296 } 297 if (bus_dmamap_load(ioctl_sense_tag, ioctl_sense_dmamap, 298 ioctl_sense_mem, ioctl_sense_size, mrsas_alloc_cb, 299 &ioctl_sense_phys_addr, BUS_DMA_NOWAIT)) { 300 device_printf(sc->mrsas_dev, "Cannot load ioctl sense mem\n"); 301 ret = ENOMEM; 302 goto out; 303 } 304 sense_ptr = 305 (unsigned long *)((uintptr_t)cmd->frame + user_ioc->sense_off); 306 *sense_ptr = ioctl_sense_phys_addr; 307 } 308 /* 309 * Set the sync_cmd flag so that the ISR knows not to complete this 310 * cmd to the SCSI mid-layer 311 */ 312 cmd->sync_cmd = 1; 313 ret = mrsas_issue_blocked_cmd(sc, cmd); 314 if (ret == ETIMEDOUT) { 315 mrsas_dprint(sc, MRSAS_OCR, 316 "IOCTL command is timed out, initiating OCR\n"); 317 sc->do_timedout_reset = MFI_DCMD_TIMEOUT_OCR; 318 ret = EAGAIN; 319 goto out; 320 } 321 cmd->sync_cmd = 0; 322 323 /* 324 * copy out the kernel buffers to user buffers 325 */ 326 for (i = 0; i < user_ioc->sge_count; i++) { 327 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) { 328 iov_base_ptrin = user_ioc->sgl[i].iov_base; 329 iov_len = user_ioc->sgl[i].iov_len; 330 #ifdef COMPAT_FREEBSD32 331 } else { 332 iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base); 333 iov_len = user_ioc32->sgl[i].iov_len; 334 #endif 335 } 336 337 ret = copyout(ioctl_data_mem[i], iov_base_ptrin, iov_len); 338 if (ret) { 339 device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n"); 340 goto out; 341 } 342 } 343 344 /* 345 * copy out the sense 346 */ 347 if (user_ioc->sense_len) { 348 /* 349 * sense_buff points to the location that has the user sense 350 * buffer address 351 */ 352 sense_ptr = (unsigned long *)((uintptr_t)user_ioc->frame.raw + 353 user_ioc->sense_off); 354 ret = copyout(ioctl_sense_mem, (unsigned long *)(uintptr_t)*sense_ptr, 355 user_ioc->sense_len); 356 if (ret) { 357 device_printf(sc->mrsas_dev, "IOCTL sense copyout failed!\n"); 358 goto out; 359 } 360 } 361 /* 362 * Return command status to user space 363 */ 364 memcpy(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status, 365 sizeof(u_int8_t)); 366 367 out: 368 /* 369 * Release sense buffer 370 */ 371 if (user_ioc->sense_len) { 372 if (ioctl_sense_phys_addr) 373 bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap); 374 if (ioctl_sense_mem != NULL) 375 bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap); 376 if (ioctl_sense_tag != NULL) 377 bus_dma_tag_destroy(ioctl_sense_tag); 378 } 379 /* 380 * Release data buffers 381 */ 382 for (i = 0; i < user_ioc->sge_count; i++) { 383 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) { 384 if (!user_ioc->sgl[i].iov_len) 385 continue; 386 #ifdef COMPAT_FREEBSD32 387 } else { 388 if (!user_ioc32->sgl[i].iov_len) 389 continue; 390 #endif 391 } 392 if (ioctl_data_phys_addr[i]) 393 bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]); 394 if (ioctl_data_mem[i] != NULL) 395 bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i], 396 ioctl_data_dmamap[i]); 397 if (ioctl_data_tag[i] != NULL) 398 bus_dma_tag_destroy(ioctl_data_tag[i]); 399 } 400 /* Free command */ 401 mrsas_release_mfi_cmd(cmd); 402 403 return (ret); 404 } 405 406 /** 407 * mrsas_user_command: Handle user mode DCMD and buffer 408 * input: Adapter instance soft state 409 * argument pointer 410 * 411 * This function is called from mrsas_ioctl() DCMDs to firmware for mfiutil 412 */ 413 int 414 mrsas_user_command(struct mrsas_softc *sc, struct mfi_ioc_passthru *ioc) 415 { 416 struct mrsas_mfi_cmd *cmd; 417 struct mrsas_dcmd_frame *dcmd; 418 struct mrsas_passthru_cmd *passcmd; 419 bus_dma_tag_t ioctl_data_tag; 420 bus_dmamap_t ioctl_data_dmamap; 421 bus_addr_t ioctl_data_phys_addr; 422 struct mrsas_sge64 *kern_sge; 423 int ret, ioctl_data_size; 424 char *ioctl_temp_data_mem; 425 426 ret = 0; 427 ioctl_temp_data_mem = NULL; 428 passcmd = NULL; 429 ioctl_data_phys_addr = 0; 430 dcmd = NULL; 431 cmd = NULL; 432 ioctl_data_tag = NULL; 433 ioctl_data_dmamap = NULL; 434 ioctl_data_dmamap = NULL; 435 436 /* Get a command */ 437 cmd = mrsas_get_mfi_cmd(sc); 438 if (!cmd) { 439 device_printf(sc->mrsas_dev, 440 "Failed to get a free cmd for IOCTL\n"); 441 return(ENOMEM); 442 } 443 444 /* 445 * Frame is DCMD 446 */ 447 dcmd = (struct mrsas_dcmd_frame *)cmd->frame; 448 memcpy(dcmd, &ioc->ioc_frame, sizeof(struct mrsas_dcmd_frame)); 449 450 ioctl_data_size = ioc->buf_size; 451 452 cmd->frame->hdr.context = cmd->index; 453 cmd->frame->hdr.pad_0 = 0; 454 cmd->frame->hdr.flags = MFI_FRAME_DIR_BOTH; 455 if (sizeof(bus_addr_t) == 8) 456 cmd->frame->hdr.flags |= MFI_FRAME_SGL64 | MFI_FRAME_SENSE64; 457 458 kern_sge = (struct mrsas_sge64 *)(&dcmd->sgl); 459 460 if (ioctl_data_size == 0) { 461 kern_sge[0].phys_addr = 0; 462 kern_sge[0].length = 0; 463 } else { 464 ioctl_temp_data_mem = malloc(ioc->buf_size, M_MRSAS, M_WAITOK); 465 if (ioctl_temp_data_mem == NULL) { 466 device_printf(sc->mrsas_dev, "Could not allocate " 467 "%d memory for temporary passthrough ioctl\n", 468 ioc->buf_size); 469 ret = ENOMEM; 470 goto out; 471 } 472 473 /* Copy in data from user space */ 474 ret = copyin(ioc->buf, ioctl_temp_data_mem, ioc->buf_size); 475 if (ret) { 476 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n"); 477 goto out; 478 } 479 480 /* 481 * Allocate a temporary struct to hold parameters for the 482 * callback 483 */ 484 passcmd = malloc(sizeof(struct mrsas_passthru_cmd), M_MRSAS, 485 M_WAITOK); 486 if (passcmd == NULL) { 487 device_printf(sc->mrsas_dev, "Could not allocate " 488 "memory for temporary passthrough cb struct\n"); 489 ret = ENOMEM; 490 goto out; 491 } 492 passcmd->complete = 0; 493 passcmd->sc = sc; 494 passcmd->cmd = cmd; 495 passcmd->kern_sge = kern_sge; 496 497 /* 498 * Create a dma tag for passthru buffers 499 */ 500 if (bus_dma_tag_create(sc->mrsas_parent_tag, /* parent */ 501 1, 0, /* algnmnt, boundary */ 502 BUS_SPACE_MAXADDR, /* lowaddr */ 503 BUS_SPACE_MAXADDR, /* highaddr */ 504 NULL, NULL, /* filter, filterarg */ 505 ioctl_data_size, /* maxsize */ 506 MAX_IOCTL_SGE, /* msegments */ 507 ioctl_data_size, /* maxsegsize */ 508 BUS_DMA_ALLOCNOW, /* flags */ 509 busdma_lock_mutex, /* lockfunc */ 510 &sc->ioctl_lock, /* lockarg */ 511 &ioctl_data_tag)) { 512 device_printf(sc->mrsas_dev, 513 "Cannot allocate ioctl data tag %d\n", 514 ioc->buf_size); 515 ret = ENOMEM; 516 goto out; 517 } 518 519 /* Create memmap */ 520 if (bus_dmamap_create(ioctl_data_tag, 0, &ioctl_data_dmamap)) { 521 device_printf(sc->mrsas_dev, "Cannot create ioctl " 522 "passthru dmamap\n"); 523 ret = ENOMEM; 524 goto out; 525 } 526 527 passcmd->ioctl_data_tag = ioctl_data_tag; 528 passcmd->ioctl_data_dmamap = ioctl_data_dmamap; 529 530 /* Map data buffer into bus space */ 531 if (bus_dmamap_load(ioctl_data_tag, ioctl_data_dmamap, 532 ioctl_temp_data_mem, ioc->buf_size, mrsas_passthru_load_cb, 533 passcmd, BUS_DMA_NOWAIT)) { 534 device_printf(sc->mrsas_dev, "Cannot load ioctl " 535 "passthru data mem%s %d\n", curproc->p_comm, ioctl_data_size); 536 ret = ENOMEM; 537 goto out; 538 } 539 540 while (passcmd->complete == 0) { 541 pause("mrsas_passthru", hz); 542 } 543 544 cmd->frame->dcmd.sge_count = passcmd->sge_count; 545 } 546 547 /* 548 * Set the sync_cmd flag so that the ISR knows not to complete this 549 * cmd to the SCSI mid-layer 550 */ 551 cmd->sync_cmd = 1; 552 mrsas_issue_blocked_cmd(sc, cmd); 553 cmd->sync_cmd = 0; 554 555 if (ioctl_data_size != 0) { 556 bus_dmamap_sync(ioctl_data_tag, ioctl_data_dmamap, 557 BUS_DMASYNC_POSTREAD); 558 /* 559 * copy out the kernel buffers to user buffers 560 */ 561 ret = copyout(ioctl_temp_data_mem, ioc->buf, ioc->buf_size); 562 if (ret) { 563 device_printf(sc->mrsas_dev, 564 "IOCTL copyout failed!\n"); 565 goto out; 566 } 567 } 568 569 /* 570 * Return command status to user space 571 */ 572 memcpy(&ioc->ioc_frame.cmd_status, &cmd->frame->hdr.cmd_status, 573 sizeof(u_int8_t)); 574 575 out: 576 /* 577 * Release temporary passthrough ioctl 578 */ 579 if (ioctl_temp_data_mem) 580 free(ioctl_temp_data_mem, M_MRSAS); 581 if (passcmd) 582 free(passcmd, M_MRSAS); 583 584 /* 585 * Release data buffers 586 */ 587 if (ioctl_data_phys_addr) { 588 bus_dmamap_unload(ioctl_data_tag, ioctl_data_dmamap); 589 bus_dmamap_destroy(ioctl_data_tag, ioctl_data_dmamap); 590 } 591 if (ioctl_data_tag != NULL) 592 bus_dma_tag_destroy(ioctl_data_tag); 593 /* Free command */ 594 mrsas_release_mfi_cmd(cmd); 595 596 return(ret); 597 } 598 599 600 /* 601 * mrsas_alloc_mfi_cmds: Allocates the command packets 602 * input: Adapter instance soft state 603 * 604 * Each IOCTL or passthru command that is issued to the FW are wrapped in a 605 * local data structure called mrsas_mfi_cmd. The frame embedded in this 606 * mrsas_mfi is issued to FW. The array is used only to look up the 607 * mrsas_mfi_cmd given the context. The free commands are maintained in a 608 * linked list. 609 */ 610 int 611 mrsas_alloc_mfi_cmds(struct mrsas_softc *sc) 612 { 613 int i, j; 614 u_int32_t max_cmd; 615 struct mrsas_mfi_cmd *cmd; 616 617 max_cmd = MRSAS_MAX_MFI_CMDS; 618 619 /* 620 * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers. 621 * Allocate the dynamic array first and then allocate individual 622 * commands. 623 */ 624 sc->mfi_cmd_list = malloc(sizeof(struct mrsas_mfi_cmd *) * max_cmd, M_MRSAS, M_NOWAIT); 625 if (!sc->mfi_cmd_list) { 626 device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n"); 627 return (ENOMEM); 628 } 629 memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *) * max_cmd); 630 for (i = 0; i < max_cmd; i++) { 631 sc->mfi_cmd_list[i] = malloc(sizeof(struct mrsas_mfi_cmd), 632 M_MRSAS, M_NOWAIT); 633 if (!sc->mfi_cmd_list[i]) { 634 for (j = 0; j < i; j++) 635 free(sc->mfi_cmd_list[j], M_MRSAS); 636 free(sc->mfi_cmd_list, M_MRSAS); 637 sc->mfi_cmd_list = NULL; 638 return (ENOMEM); 639 } 640 } 641 642 for (i = 0; i < max_cmd; i++) { 643 cmd = sc->mfi_cmd_list[i]; 644 memset(cmd, 0, sizeof(struct mrsas_mfi_cmd)); 645 cmd->index = i; 646 cmd->ccb_ptr = NULL; 647 cmd->sc = sc; 648 TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next); 649 } 650 651 /* create a frame pool and assign one frame to each command */ 652 if (mrsas_create_frame_pool(sc)) { 653 device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n"); 654 /* Free the frames */ 655 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { 656 cmd = sc->mfi_cmd_list[i]; 657 mrsas_free_frame(sc, cmd); 658 } 659 if (sc->mficmd_frame_tag != NULL) 660 bus_dma_tag_destroy(sc->mficmd_frame_tag); 661 return (ENOMEM); 662 } 663 return (0); 664 } 665 666 /* 667 * mrsas_create_frame_pool: Creates DMA pool for cmd frames 668 * input: Adapter soft state 669 * 670 * Each command packet has an embedded DMA memory buffer that is used for 671 * filling MFI frame and the SG list that immediately follows the frame. This 672 * function creates those DMA memory buffers for each command packet by using 673 * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value 674 * of context and could cause FW crash. 675 */ 676 static int 677 mrsas_create_frame_pool(struct mrsas_softc *sc) 678 { 679 int i; 680 struct mrsas_mfi_cmd *cmd; 681 682 if (bus_dma_tag_create(sc->mrsas_parent_tag, 683 1, 0, 684 BUS_SPACE_MAXADDR_32BIT, 685 BUS_SPACE_MAXADDR, 686 NULL, NULL, 687 MRSAS_MFI_FRAME_SIZE, 688 1, 689 MRSAS_MFI_FRAME_SIZE, 690 BUS_DMA_ALLOCNOW, 691 NULL, NULL, 692 &sc->mficmd_frame_tag)) { 693 device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n"); 694 return (ENOMEM); 695 } 696 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { 697 cmd = sc->mfi_cmd_list[i]; 698 cmd->frame = mrsas_alloc_frame(sc, cmd); 699 if (cmd->frame == NULL) { 700 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n"); 701 return (ENOMEM); 702 } 703 /* 704 * For MFI controllers. 705 * max_num_sge = 60 706 * max_sge_sz = 16 byte (sizeof megasas_sge_skinny) 707 * Totl 960 byte (15 MFI frame of 64 byte) 708 * 709 * Fusion adapter require only 3 extra frame. 710 * max_num_sge = 16 (defined as MAX_IOCTL_SGE) 711 * max_sge_sz = 12 byte (sizeof megasas_sge64) 712 * Total 192 byte (3 MFI frame of 64 byte) 713 */ 714 memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE); 715 cmd->frame->io.context = cmd->index; 716 cmd->frame->io.pad_0 = 0; 717 } 718 719 return (0); 720 } 721 722 /* 723 * mrsas_alloc_frame: Allocates MFI Frames 724 * input: Adapter soft state 725 * 726 * Create bus DMA memory tag and dmamap and load memory for MFI frames. Returns 727 * virtual memory pointer to allocated region. 728 */ 729 void * 730 mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 731 { 732 u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE; 733 734 if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem, 735 BUS_DMA_NOWAIT, &cmd->frame_dmamap)) { 736 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n"); 737 return (NULL); 738 } 739 if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap, 740 cmd->frame_mem, frame_size, mrsas_alloc_cb, 741 &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) { 742 device_printf(sc->mrsas_dev, "Cannot load IO request memory\n"); 743 return (NULL); 744 } 745 return (cmd->frame_mem); 746 } 747 748 /* 749 * mrsas_alloc_cb: Callback function of bus_dmamap_load() 750 * input: callback argument, 751 * machine dependent type that describes DMA segments, 752 * number of segments, 753 * error code. 754 * 755 * This function is for the driver to receive mapping information resultant of 756 * the bus_dmamap_load(). The information is actually not being used, but the 757 * address is saved anyway. 758 */ 759 static void 760 mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs, 761 int nsegs, int error) 762 { 763 bus_addr_t *addr; 764 765 addr = arg; 766 *addr = segs[0].ds_addr; 767 } 768 769 /* 770 * mrsas_free_frames: Frees memory for MFI frames 771 * input: Adapter soft state 772 * 773 * Deallocates MFI frames memory. Called from mrsas_free_mem() during detach 774 * and error case during creation of frame pool. 775 */ 776 void 777 mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 778 { 779 if (cmd->frame_phys_addr) 780 bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap); 781 if (cmd->frame_mem != NULL) 782 bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap); 783 } 784