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 <dev/mrsas/mrsas.h> 44 #include <dev/mrsas/mrsas_ioctl.h> 45 46 /* 47 * Function prototypes 48 */ 49 int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc); 50 int mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd); 51 void mrsas_free_ioc_cmd(struct mrsas_softc *sc); 52 void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 53 void *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 54 static int mrsas_create_frame_pool(struct mrsas_softc *sc); 55 static void 56 mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs, 57 int nsegs, int error); 58 59 extern struct mrsas_mfi_cmd *mrsas_get_mfi_cmd(struct mrsas_softc *sc); 60 extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd); 61 extern int 62 mrsas_issue_blocked_cmd(struct mrsas_softc *sc, 63 struct mrsas_mfi_cmd *cmd); 64 65 /* 66 * mrsas_passthru: Handle pass-through commands 67 * input: Adapter instance soft state argument pointer 68 * 69 * This function is called from mrsas_ioctl() to handle pass-through and ioctl 70 * commands to Firmware. 71 */ 72 int 73 mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd) 74 { 75 struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg; 76 77 #ifdef COMPAT_FREEBSD32 78 struct mrsas_iocpacket32 *user_ioc32 = (struct mrsas_iocpacket32 *)arg; 79 80 #endif 81 union mrsas_frame *in_cmd = (union mrsas_frame *)&(user_ioc->frame.raw); 82 struct mrsas_mfi_cmd *cmd = NULL; 83 bus_dma_tag_t ioctl_data_tag[MAX_IOCTL_SGE]; 84 bus_dmamap_t ioctl_data_dmamap[MAX_IOCTL_SGE]; 85 void *ioctl_data_mem[MAX_IOCTL_SGE]; 86 bus_addr_t ioctl_data_phys_addr[MAX_IOCTL_SGE]; 87 bus_dma_tag_t ioctl_sense_tag = 0; 88 bus_dmamap_t ioctl_sense_dmamap = 0; 89 void *ioctl_sense_mem = NULL; 90 bus_addr_t ioctl_sense_phys_addr = 0; 91 int i, ioctl_data_size = 0, ioctl_sense_size, ret = 0; 92 struct mrsas_sge32 *kern_sge32; 93 unsigned long *sense_ptr; 94 uint8_t *iov_base_ptrin = NULL; 95 size_t iov_len = 0; 96 97 /* 98 * Check for NOP from MegaCli... MegaCli can issue a DCMD of 0. In 99 * this case do nothing and return 0 to it as status. 100 */ 101 if (in_cmd->dcmd.opcode == 0) { 102 device_printf(sc->mrsas_dev, "In %s() Got a NOP\n", __func__); 103 user_ioc->frame.hdr.cmd_status = MFI_STAT_OK; 104 return (0); 105 } 106 /* Validate SGL length */ 107 if (user_ioc->sge_count > MAX_IOCTL_SGE) { 108 device_printf(sc->mrsas_dev, "In %s() SGL is too long (%d > 8).\n", 109 __func__, user_ioc->sge_count); 110 return (ENOENT); 111 } 112 /* Get a command */ 113 cmd = mrsas_get_mfi_cmd(sc); 114 if (!cmd) { 115 device_printf(sc->mrsas_dev, "Failed to get a free cmd for IOCTL\n"); 116 return (ENOMEM); 117 } 118 /* 119 * User's IOCTL packet has 2 frames (maximum). Copy those two frames 120 * into our cmd's frames. cmd->frame's context will get overwritten 121 * when we copy from user's frames. So set that value alone 122 * separately 123 */ 124 memcpy(cmd->frame, user_ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); 125 cmd->frame->hdr.context = cmd->index; 126 cmd->frame->hdr.pad_0 = 0; 127 cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 | 128 MFI_FRAME_SENSE64); 129 130 /* 131 * The management interface between applications and the fw uses MFI 132 * frames. E.g, RAID configuration changes, LD property changes etc 133 * are accomplishes through different kinds of MFI frames. The driver 134 * needs to care only about substituting user buffers with kernel 135 * buffers in SGLs. The location of SGL is embedded in the struct 136 * iocpacket itself. 137 */ 138 kern_sge32 = (struct mrsas_sge32 *) 139 ((unsigned long)cmd->frame + user_ioc->sgl_off); 140 141 memset(ioctl_data_tag, 0, (sizeof(bus_dma_tag_t) * MAX_IOCTL_SGE)); 142 memset(ioctl_data_dmamap, 0, (sizeof(bus_dmamap_t) * MAX_IOCTL_SGE)); 143 memset(ioctl_data_mem, 0, (sizeof(void *) * MAX_IOCTL_SGE)); 144 memset(ioctl_data_phys_addr, 0, (sizeof(bus_addr_t) * MAX_IOCTL_SGE)); 145 146 /* 147 * For each user buffer, create a mirror buffer and copy in 148 */ 149 for (i = 0; i < user_ioc->sge_count; i++) { 150 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) { 151 if (!user_ioc->sgl[i].iov_len) 152 continue; 153 ioctl_data_size = user_ioc->sgl[i].iov_len; 154 #ifdef COMPAT_FREEBSD32 155 } else { 156 if (!user_ioc32->sgl[i].iov_len) 157 continue; 158 ioctl_data_size = user_ioc32->sgl[i].iov_len; 159 #endif 160 } 161 if (bus_dma_tag_create(sc->mrsas_parent_tag, 162 1, 0, 163 BUS_SPACE_MAXADDR_32BIT, 164 BUS_SPACE_MAXADDR, 165 NULL, NULL, 166 ioctl_data_size, 167 1, 168 ioctl_data_size, 169 BUS_DMA_ALLOCNOW, 170 NULL, NULL, 171 &ioctl_data_tag[i])) { 172 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n"); 173 ret = ENOMEM; 174 goto out; 175 } 176 if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i], 177 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) { 178 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n"); 179 ret = ENOMEM; 180 goto out; 181 } 182 if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i], 183 ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb, 184 &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) { 185 device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n"); 186 ret = ENOMEM; 187 goto out; 188 } 189 /* Save the physical address and length */ 190 kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i]; 191 192 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) { 193 kern_sge32[i].length = user_ioc->sgl[i].iov_len; 194 195 iov_base_ptrin = user_ioc->sgl[i].iov_base; 196 iov_len = user_ioc->sgl[i].iov_len; 197 #ifdef COMPAT_FREEBSD32 198 } else { 199 kern_sge32[i].length = user_ioc32->sgl[i].iov_len; 200 201 iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base); 202 iov_len = user_ioc32->sgl[i].iov_len; 203 #endif 204 } 205 206 /* Copy in data from user space */ 207 ret = copyin(iov_base_ptrin, ioctl_data_mem[i], iov_len); 208 if (ret) { 209 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n"); 210 goto out; 211 } 212 } 213 214 ioctl_sense_size = user_ioc->sense_len; 215 216 if (user_ioc->sense_len) { 217 if (bus_dma_tag_create(sc->mrsas_parent_tag, 218 1, 0, 219 BUS_SPACE_MAXADDR_32BIT, 220 BUS_SPACE_MAXADDR, 221 NULL, NULL, 222 ioctl_sense_size, 223 1, 224 ioctl_sense_size, 225 BUS_DMA_ALLOCNOW, 226 NULL, NULL, 227 &ioctl_sense_tag)) { 228 device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense tag\n"); 229 ret = ENOMEM; 230 goto out; 231 } 232 if (bus_dmamem_alloc(ioctl_sense_tag, (void **)&ioctl_sense_mem, 233 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_sense_dmamap)) { 234 device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense mem\n"); 235 ret = ENOMEM; 236 goto out; 237 } 238 if (bus_dmamap_load(ioctl_sense_tag, ioctl_sense_dmamap, 239 ioctl_sense_mem, ioctl_sense_size, mrsas_alloc_cb, 240 &ioctl_sense_phys_addr, BUS_DMA_NOWAIT)) { 241 device_printf(sc->mrsas_dev, "Cannot load ioctl sense mem\n"); 242 ret = ENOMEM; 243 goto out; 244 } 245 sense_ptr = 246 (unsigned long *)((unsigned long)cmd->frame + user_ioc->sense_off); 247 *sense_ptr = ioctl_sense_phys_addr; 248 } 249 /* 250 * Set the sync_cmd flag so that the ISR knows not to complete this 251 * cmd to the SCSI mid-layer 252 */ 253 cmd->sync_cmd = 1; 254 ret = mrsas_issue_blocked_cmd(sc, cmd); 255 if (ret == ETIMEDOUT) { 256 mrsas_dprint(sc, MRSAS_OCR, 257 "IOCTL command is timed out, initiating OCR\n"); 258 sc->do_timedout_reset = MFI_DCMD_TIMEOUT_OCR; 259 ret = EAGAIN; 260 goto out; 261 } 262 cmd->sync_cmd = 0; 263 264 /* 265 * copy out the kernel buffers to user buffers 266 */ 267 for (i = 0; i < user_ioc->sge_count; i++) { 268 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) { 269 iov_base_ptrin = user_ioc->sgl[i].iov_base; 270 iov_len = user_ioc->sgl[i].iov_len; 271 #ifdef COMPAT_FREEBSD32 272 } else { 273 iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base); 274 iov_len = user_ioc32->sgl[i].iov_len; 275 #endif 276 } 277 278 ret = copyout(ioctl_data_mem[i], iov_base_ptrin, iov_len); 279 if (ret) { 280 device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n"); 281 goto out; 282 } 283 } 284 285 /* 286 * copy out the sense 287 */ 288 if (user_ioc->sense_len) { 289 /* 290 * sense_buff points to the location that has the user sense 291 * buffer address 292 */ 293 sense_ptr = (unsigned long *)((unsigned long)user_ioc->frame.raw + 294 user_ioc->sense_off); 295 ret = copyout(ioctl_sense_mem, (unsigned long *)*sense_ptr, 296 user_ioc->sense_len); 297 if (ret) { 298 device_printf(sc->mrsas_dev, "IOCTL sense copyout failed!\n"); 299 goto out; 300 } 301 } 302 /* 303 * Return command status to user space 304 */ 305 memcpy(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status, 306 sizeof(u_int8_t)); 307 308 out: 309 /* 310 * Release sense buffer 311 */ 312 if (user_ioc->sense_len) { 313 if (ioctl_sense_phys_addr) 314 bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap); 315 if (ioctl_sense_mem != NULL) 316 bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap); 317 if (ioctl_sense_tag != NULL) 318 bus_dma_tag_destroy(ioctl_sense_tag); 319 } 320 /* 321 * Release data buffers 322 */ 323 for (i = 0; i < user_ioc->sge_count; i++) { 324 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) { 325 if (!user_ioc->sgl[i].iov_len) 326 continue; 327 #ifdef COMPAT_FREEBSD32 328 } else { 329 if (!user_ioc32->sgl[i].iov_len) 330 continue; 331 #endif 332 } 333 if (ioctl_data_phys_addr[i]) 334 bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]); 335 if (ioctl_data_mem[i] != NULL) 336 bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i], 337 ioctl_data_dmamap[i]); 338 if (ioctl_data_tag[i] != NULL) 339 bus_dma_tag_destroy(ioctl_data_tag[i]); 340 } 341 /* Free command */ 342 mrsas_release_mfi_cmd(cmd); 343 344 return (ret); 345 } 346 347 /* 348 * mrsas_alloc_mfi_cmds: Allocates the command packets 349 * input: Adapter instance soft state 350 * 351 * Each IOCTL or passthru command that is issued to the FW are wrapped in a 352 * local data structure called mrsas_mfi_cmd. The frame embedded in this 353 * mrsas_mfi is issued to FW. The array is used only to look up the 354 * mrsas_mfi_cmd given the context. The free commands are maintained in a 355 * linked list. 356 */ 357 int 358 mrsas_alloc_mfi_cmds(struct mrsas_softc *sc) 359 { 360 int i, j; 361 u_int32_t max_cmd; 362 struct mrsas_mfi_cmd *cmd; 363 364 max_cmd = MRSAS_MAX_MFI_CMDS; 365 366 /* 367 * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers. 368 * Allocate the dynamic array first and then allocate individual 369 * commands. 370 */ 371 sc->mfi_cmd_list = malloc(sizeof(struct mrsas_mfi_cmd *) * max_cmd, M_MRSAS, M_NOWAIT); 372 if (!sc->mfi_cmd_list) { 373 device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n"); 374 return (ENOMEM); 375 } 376 memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *) * max_cmd); 377 for (i = 0; i < max_cmd; i++) { 378 sc->mfi_cmd_list[i] = malloc(sizeof(struct mrsas_mfi_cmd), 379 M_MRSAS, M_NOWAIT); 380 if (!sc->mfi_cmd_list[i]) { 381 for (j = 0; j < i; j++) 382 free(sc->mfi_cmd_list[j], M_MRSAS); 383 free(sc->mfi_cmd_list, M_MRSAS); 384 sc->mfi_cmd_list = NULL; 385 return (ENOMEM); 386 } 387 } 388 389 for (i = 0; i < max_cmd; i++) { 390 cmd = sc->mfi_cmd_list[i]; 391 memset(cmd, 0, sizeof(struct mrsas_mfi_cmd)); 392 cmd->index = i; 393 cmd->ccb_ptr = NULL; 394 cmd->sc = sc; 395 TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next); 396 } 397 398 /* create a frame pool and assign one frame to each command */ 399 if (mrsas_create_frame_pool(sc)) { 400 device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n"); 401 /* Free the frames */ 402 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { 403 cmd = sc->mfi_cmd_list[i]; 404 mrsas_free_frame(sc, cmd); 405 } 406 if (sc->mficmd_frame_tag != NULL) 407 bus_dma_tag_destroy(sc->mficmd_frame_tag); 408 return (ENOMEM); 409 } 410 return (0); 411 } 412 413 /* 414 * mrsas_create_frame_pool: Creates DMA pool for cmd frames 415 * input: Adapter soft state 416 * 417 * Each command packet has an embedded DMA memory buffer that is used for 418 * filling MFI frame and the SG list that immediately follows the frame. This 419 * function creates those DMA memory buffers for each command packet by using 420 * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value 421 * of context and could cause FW crash. 422 */ 423 static int 424 mrsas_create_frame_pool(struct mrsas_softc *sc) 425 { 426 int i; 427 struct mrsas_mfi_cmd *cmd; 428 429 if (bus_dma_tag_create(sc->mrsas_parent_tag, 430 1, 0, 431 BUS_SPACE_MAXADDR_32BIT, 432 BUS_SPACE_MAXADDR, 433 NULL, NULL, 434 MRSAS_MFI_FRAME_SIZE, 435 1, 436 MRSAS_MFI_FRAME_SIZE, 437 BUS_DMA_ALLOCNOW, 438 NULL, NULL, 439 &sc->mficmd_frame_tag)) { 440 device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n"); 441 return (ENOMEM); 442 } 443 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { 444 cmd = sc->mfi_cmd_list[i]; 445 cmd->frame = mrsas_alloc_frame(sc, cmd); 446 if (cmd->frame == NULL) { 447 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n"); 448 return (ENOMEM); 449 } 450 /* 451 * For MFI controllers. 452 * max_num_sge = 60 453 * max_sge_sz = 16 byte (sizeof megasas_sge_skinny) 454 * Totl 960 byte (15 MFI frame of 64 byte) 455 * 456 * Fusion adapter require only 3 extra frame. 457 * max_num_sge = 16 (defined as MAX_IOCTL_SGE) 458 * max_sge_sz = 12 byte (sizeof megasas_sge64) 459 * Total 192 byte (3 MFI frame of 64 byte) 460 */ 461 memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE); 462 cmd->frame->io.context = cmd->index; 463 cmd->frame->io.pad_0 = 0; 464 } 465 466 return (0); 467 } 468 469 /* 470 * mrsas_alloc_frame: Allocates MFI Frames 471 * input: Adapter soft state 472 * 473 * Create bus DMA memory tag and dmamap and load memory for MFI frames. Returns 474 * virtual memory pointer to allocated region. 475 */ 476 void * 477 mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 478 { 479 u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE; 480 481 if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem, 482 BUS_DMA_NOWAIT, &cmd->frame_dmamap)) { 483 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n"); 484 return (NULL); 485 } 486 if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap, 487 cmd->frame_mem, frame_size, mrsas_alloc_cb, 488 &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) { 489 device_printf(sc->mrsas_dev, "Cannot load IO request memory\n"); 490 return (NULL); 491 } 492 return (cmd->frame_mem); 493 } 494 495 /* 496 * mrsas_alloc_cb: Callback function of bus_dmamap_load() 497 * input: callback argument, 498 * machine dependent type that describes DMA segments, 499 * number of segments, 500 * error code. 501 * 502 * This function is for the driver to receive mapping information resultant of 503 * the bus_dmamap_load(). The information is actually not being used, but the 504 * address is saved anyway. 505 */ 506 static void 507 mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs, 508 int nsegs, int error) 509 { 510 bus_addr_t *addr; 511 512 addr = arg; 513 *addr = segs[0].ds_addr; 514 } 515 516 /* 517 * mrsas_free_frames: Frees memory for MFI frames 518 * input: Adapter soft state 519 * 520 * Deallocates MFI frames memory. Called from mrsas_free_mem() during detach 521 * and error case during creation of frame pool. 522 */ 523 void 524 mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) 525 { 526 if (cmd->frame_phys_addr) 527 bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap); 528 if (cmd->frame_mem != NULL) 529 bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap); 530 } 531