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 466 /* Copy in data from user space */ 467 ret = copyin(ioc->buf, ioctl_temp_data_mem, ioc->buf_size); 468 if (ret) { 469 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n"); 470 goto out; 471 } 472 473 /* 474 * Allocate a temporary struct to hold parameters for the 475 * callback 476 */ 477 passcmd = malloc(sizeof(struct mrsas_passthru_cmd), M_MRSAS, 478 M_WAITOK); 479 passcmd->complete = 0; 480 passcmd->sc = sc; 481 passcmd->cmd = cmd; 482 passcmd->kern_sge = kern_sge; 483 484 /* 485 * Create a dma tag for passthru buffers 486 */ 487 if (bus_dma_tag_create(sc->mrsas_parent_tag, /* parent */ 488 1, 0, /* algnmnt, boundary */ 489 BUS_SPACE_MAXADDR, /* lowaddr */ 490 BUS_SPACE_MAXADDR, /* highaddr */ 491 NULL, NULL, /* filter, filterarg */ 492 ioctl_data_size, /* maxsize */ 493 MAX_IOCTL_SGE, /* msegments */ 494 ioctl_data_size, /* maxsegsize */ 495 BUS_DMA_ALLOCNOW, /* flags */ 496 busdma_lock_mutex, /* lockfunc */ 497 &sc->ioctl_lock, /* lockarg */ 498 &ioctl_data_tag)) { 499 device_printf(sc->mrsas_dev, 500 "Cannot allocate ioctl data tag %d\n", 501 ioc->buf_size); 502 ret = ENOMEM; 503 goto out; 504 } 505 506 /* Create memmap */ 507 if (bus_dmamap_create(ioctl_data_tag, 0, &ioctl_data_dmamap)) { 508 device_printf(sc->mrsas_dev, "Cannot create ioctl " 509 "passthru dmamap\n"); 510 ret = ENOMEM; 511 goto out; 512 } 513 514 passcmd->ioctl_data_tag = ioctl_data_tag; 515 passcmd->ioctl_data_dmamap = ioctl_data_dmamap; 516 517 /* Map data buffer into bus space */ 518 if (bus_dmamap_load(ioctl_data_tag, ioctl_data_dmamap, 519 ioctl_temp_data_mem, ioc->buf_size, mrsas_passthru_load_cb, 520 passcmd, BUS_DMA_NOWAIT)) { 521 device_printf(sc->mrsas_dev, "Cannot load ioctl " 522 "passthru data mem%s %d\n", curproc->p_comm, ioctl_data_size); 523 ret = ENOMEM; 524 goto out; 525 } 526 527 while (passcmd->complete == 0) { 528 pause("mrsas_passthru", hz); 529 } 530 531 cmd->frame->dcmd.sge_count = passcmd->sge_count; 532 } 533 534 /* 535 * Set the sync_cmd flag so that the ISR knows not to complete this 536 * cmd to the SCSI mid-layer 537 */ 538 cmd->sync_cmd = 1; 539 mrsas_issue_blocked_cmd(sc, cmd); 540 cmd->sync_cmd = 0; 541 542 if (ioctl_data_size != 0) { 543 bus_dmamap_sync(ioctl_data_tag, ioctl_data_dmamap, 544 BUS_DMASYNC_POSTREAD); 545 /* 546 * copy out the kernel buffers to user buffers 547 */ 548 ret = copyout(ioctl_temp_data_mem, ioc->buf, ioc->buf_size); 549 if (ret) { 550 device_printf(sc->mrsas_dev, 551 "IOCTL copyout failed!\n"); 552 goto out; 553 } 554 } 555 556 /* 557 * Return command status to user space 558 */ 559 memcpy(&ioc->ioc_frame.cmd_status, &cmd->frame->hdr.cmd_status, 560 sizeof(u_int8_t)); 561 562 out: 563 /* 564 * Release temporary passthrough ioctl 565 */ 566 if (ioctl_temp_data_mem) 567 free(ioctl_temp_data_mem, M_MRSAS); 568 if (passcmd) 569 free(passcmd, M_MRSAS); 570 571 /* 572 * Release data buffers 573 */ 574 if (ioctl_data_phys_addr) { 575 bus_dmamap_unload(ioctl_data_tag, ioctl_data_dmamap); 576 bus_dmamap_destroy(ioctl_data_tag, ioctl_data_dmamap); 577 } 578 if (ioctl_data_tag != NULL) 579 bus_dma_tag_destroy(ioctl_data_tag); 580 /* Free command */ 581 mrsas_release_mfi_cmd(cmd); 582 583 return(ret); 584 } 585 586 587 /* 588 * mrsas_alloc_mfi_cmds: Allocates the command packets 589 * input: Adapter instance soft state 590 * 591 * Each IOCTL or passthru command that is issued to the FW are wrapped in a 592 * local data structure called mrsas_mfi_cmd. The frame embedded in this 593 * mrsas_mfi is issued to FW. The array is used only to look up the 594 * mrsas_mfi_cmd given the context. The free commands are maintained in a 595 * linked list. 596 */ 597 int 598 mrsas_alloc_mfi_cmds(struct mrsas_softc *sc) 599 { 600 int i, j; 601 u_int32_t max_cmd; 602 struct mrsas_mfi_cmd *cmd; 603 604 max_cmd = MRSAS_MAX_MFI_CMDS; 605 606 /* 607 * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers. 608 * Allocate the dynamic array first and then allocate individual 609 * commands. 610 */ 611 sc->mfi_cmd_list = malloc(sizeof(struct mrsas_mfi_cmd *) * max_cmd, M_MRSAS, M_NOWAIT); 612 if (!sc->mfi_cmd_list) { 613 device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n"); 614 return (ENOMEM); 615 } 616 memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *) * max_cmd); 617 for (i = 0; i < max_cmd; i++) { 618 sc->mfi_cmd_list[i] = malloc(sizeof(struct mrsas_mfi_cmd), 619 M_MRSAS, M_NOWAIT); 620 if (!sc->mfi_cmd_list[i]) { 621 for (j = 0; j < i; j++) 622 free(sc->mfi_cmd_list[j], M_MRSAS); 623 free(sc->mfi_cmd_list, M_MRSAS); 624 sc->mfi_cmd_list = NULL; 625 return (ENOMEM); 626 } 627 } 628 629 for (i = 0; i < max_cmd; i++) { 630 cmd = sc->mfi_cmd_list[i]; 631 memset(cmd, 0, sizeof(struct mrsas_mfi_cmd)); 632 cmd->index = i; 633 cmd->ccb_ptr = NULL; 634 cmd->sc = sc; 635 TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next); 636 } 637 638 /* create a frame pool and assign one frame to each command */ 639 if (mrsas_create_frame_pool(sc)) { 640 device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n"); 641 /* Free the frames */ 642 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { 643 cmd = sc->mfi_cmd_list[i]; 644 mrsas_free_frame(sc, cmd); 645 } 646 if (sc->mficmd_frame_tag != NULL) 647 bus_dma_tag_destroy(sc->mficmd_frame_tag); 648 return (ENOMEM); 649 } 650 return (0); 651 } 652 653 /* 654 * mrsas_create_frame_pool: Creates DMA pool for cmd frames 655 * input: Adapter soft state 656 * 657 * Each command packet has an embedded DMA memory buffer that is used for 658 * filling MFI frame and the SG list that immediately follows the frame. This 659 * function creates those DMA memory buffers for each command packet by using 660 * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value 661 * of context and could cause FW crash. 662 */ 663 static int 664 mrsas_create_frame_pool(struct mrsas_softc *sc) 665 { 666 int i; 667 struct mrsas_mfi_cmd *cmd; 668 669 if (bus_dma_tag_create(sc->mrsas_parent_tag, 670 1, 0, 671 BUS_SPACE_MAXADDR_32BIT, 672 BUS_SPACE_MAXADDR, 673 NULL, NULL, 674 MRSAS_MFI_FRAME_SIZE, 675 1, 676 MRSAS_MFI_FRAME_SIZE, 677 BUS_DMA_ALLOCNOW, 678 NULL, NULL, 679 &sc->mficmd_frame_tag)) { 680 device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n"); 681 return (ENOMEM); 682 } 683 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { 684 cmd = sc->mfi_cmd_list[i]; 685 cmd->frame = mrsas_alloc_frame(sc, cmd); 686 if (cmd->frame == NULL) { 687 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n"); 688 return (ENOMEM); 689 } 690 /* 691 * For MFI controllers. 692 * max_num_sge = 60 693 * max_sge_sz = 16 byte (sizeof megasas_sge_skinny) 694 * Totl 960 byte (15 MFI frame of 64 byte) 695 * 696 * Fusion adapter require only 3 extra frame. 697 * max_num_sge = 16 (defined as MAX_IOCTL_SGE) 698 * max_sge_sz = 12 byte (sizeof megasas_sge64) 699 * Total 192 byte (3 MFI frame of 64 byte) 700 */ 701 memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE); 702 cmd->frame->io.context = cmd->index; 703 cmd->frame->io.pad_0 = 0; 704 } 705 706 return (0); 707 } 708 709 /* 710 * mrsas_alloc_frame: Allocates MFI Frames 711 * input: Adapter soft state 712 * 713 * Create bus DMA memory tag and dmamap and load memory for MFI frames. Returns 714 * virtual memory pointer to allocated region. 715 */ 716 void * 717 mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 718 { 719 u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE; 720 721 if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem, 722 BUS_DMA_NOWAIT, &cmd->frame_dmamap)) { 723 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n"); 724 return (NULL); 725 } 726 if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap, 727 cmd->frame_mem, frame_size, mrsas_alloc_cb, 728 &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) { 729 device_printf(sc->mrsas_dev, "Cannot load IO request memory\n"); 730 return (NULL); 731 } 732 return (cmd->frame_mem); 733 } 734 735 /* 736 * mrsas_alloc_cb: Callback function of bus_dmamap_load() 737 * input: callback argument, 738 * machine dependent type that describes DMA segments, 739 * number of segments, 740 * error code. 741 * 742 * This function is for the driver to receive mapping information resultant of 743 * the bus_dmamap_load(). The information is actually not being used, but the 744 * address is saved anyway. 745 */ 746 static void 747 mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs, 748 int nsegs, int error) 749 { 750 bus_addr_t *addr; 751 752 addr = arg; 753 *addr = segs[0].ds_addr; 754 } 755 756 /* 757 * mrsas_free_frames: Frees memory for MFI frames 758 * input: Adapter soft state 759 * 760 * Deallocates MFI frames memory. Called from mrsas_free_mem() during detach 761 * and error case during creation of frame pool. 762 */ 763 void 764 mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 765 { 766 if (cmd->frame_phys_addr) 767 bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap); 768 if (cmd->frame_mem != NULL) 769 bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap); 770 } 771