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