1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * tavor_ioctl.c 29 * Tavor IOCTL Routines 30 * 31 * Implements all ioctl access into the driver. This includes all routines 32 * necessary for updating firmware, accessing the tavor flash device, and 33 * providing interfaces for VTS. 34 */ 35 36 #include <sys/types.h> 37 #include <sys/conf.h> 38 #include <sys/ddi.h> 39 #include <sys/sunddi.h> 40 #include <sys/modctl.h> 41 #include <sys/file.h> 42 43 #include <sys/ib/adapters/tavor/tavor.h> 44 45 /* Tavor HCA state pointer (extern) */ 46 extern void *tavor_statep; 47 48 /* 49 * The ioctl declarations (for firmware flash burning, register read/write 50 * (DEBUG-only), and VTS interfaces) 51 */ 52 static int tavor_ioctl_flash_read(tavor_state_t *state, dev_t dev, 53 intptr_t arg, int mode); 54 static int tavor_ioctl_flash_write(tavor_state_t *state, dev_t dev, 55 intptr_t arg, int mode); 56 static int tavor_ioctl_flash_erase(tavor_state_t *state, dev_t dev, 57 intptr_t arg, int mode); 58 static int tavor_ioctl_flash_init(tavor_state_t *state, dev_t dev, 59 intptr_t arg, int mode); 60 static int tavor_ioctl_flash_fini(tavor_state_t *state, dev_t dev); 61 static void tavor_ioctl_flash_cleanup(tavor_state_t *state); 62 static void tavor_ioctl_flash_cleanup_nolock(tavor_state_t *state); 63 #ifdef DEBUG 64 static int tavor_ioctl_reg_write(tavor_state_t *state, intptr_t arg, 65 int mode); 66 static int tavor_ioctl_reg_read(tavor_state_t *state, intptr_t arg, 67 int mode); 68 #endif /* DEBUG */ 69 static int tavor_ioctl_info(tavor_state_t *state, dev_t dev, 70 intptr_t arg, int mode); 71 static int tavor_ioctl_ports(tavor_state_t *state, intptr_t arg, 72 int mode); 73 static int tavor_ioctl_loopback(tavor_state_t *state, intptr_t arg, 74 int mode); 75 static int tavor_ioctl_ddr_read(tavor_state_t *state, intptr_t arg, 76 int mode); 77 78 /* Tavor Flash Functions */ 79 static void tavor_flash_read_sector(tavor_state_t *state, uint32_t sector_num); 80 static void tavor_flash_read_quadlet(tavor_state_t *state, uint32_t *data, 81 uint32_t addr); 82 static int tavor_flash_write_sector(tavor_state_t *state, uint32_t sector_num); 83 static int tavor_flash_write_byte(tavor_state_t *state, uint32_t addr, 84 uchar_t data); 85 static int tavor_flash_erase_sector(tavor_state_t *state, uint32_t sector_num); 86 static int tavor_flash_erase_chip(tavor_state_t *state); 87 static void tavor_flash_bank(tavor_state_t *state, uint32_t addr); 88 static uint32_t tavor_flash_read(tavor_state_t *state, uint32_t addr); 89 static void tavor_flash_write(tavor_state_t *state, uint32_t addr, 90 uchar_t data); 91 static void tavor_flash_init(tavor_state_t *state); 92 static void tavor_flash_cfi_init(tavor_state_t *state, uint32_t *cfi_info, 93 int *intel_xcmd); 94 static void tavor_flash_fini(tavor_state_t *state); 95 static void tavor_flash_reset(tavor_state_t *state); 96 static uint32_t tavor_flash_read_cfg(ddi_acc_handle_t pci_config_hdl, 97 uint32_t addr); 98 static void tavor_flash_write_cfg(ddi_acc_handle_t pci_config_hdl, 99 uint32_t addr, uint32_t data); 100 static void tavor_flash_cfi_byte(uint8_t *ch, uint32_t dword, int i); 101 static void tavor_flash_cfi_dword(uint32_t *dword, uint8_t *ch, int i); 102 103 /* Tavor loopback test functions */ 104 static void tavor_loopback_free_qps(tavor_loopback_state_t *lstate); 105 static void tavor_loopback_free_state(tavor_loopback_state_t *lstate); 106 static int tavor_loopback_init(tavor_state_t *state, 107 tavor_loopback_state_t *lstate); 108 static void tavor_loopback_init_qp_info(tavor_loopback_state_t *lstate, 109 tavor_loopback_comm_t *comm); 110 static int tavor_loopback_alloc_mem(tavor_loopback_state_t *lstate, 111 tavor_loopback_comm_t *comm, int sz); 112 static int tavor_loopback_alloc_qps(tavor_loopback_state_t *lstate, 113 tavor_loopback_comm_t *comm); 114 static int tavor_loopback_modify_qp(tavor_loopback_state_t *lstate, 115 tavor_loopback_comm_t *comm, uint_t qp_num); 116 static int tavor_loopback_copyout(tavor_loopback_ioctl_t *lb, 117 intptr_t arg, int mode); 118 static int tavor_loopback_post_send(tavor_loopback_state_t *lstate, 119 tavor_loopback_comm_t *tx, tavor_loopback_comm_t *rx); 120 static int tavor_loopback_poll_cq(tavor_loopback_state_t *lstate, 121 tavor_loopback_comm_t *comm); 122 123 /* Patchable timeout values for flash operations */ 124 int tavor_hw_flash_timeout_gpio_sema = TAVOR_HW_FLASH_TIMEOUT_GPIO_SEMA; 125 int tavor_hw_flash_timeout_config = TAVOR_HW_FLASH_TIMEOUT_CONFIG; 126 int tavor_hw_flash_timeout_write = TAVOR_HW_FLASH_TIMEOUT_WRITE; 127 int tavor_hw_flash_timeout_erase = TAVOR_HW_FLASH_TIMEOUT_ERASE; 128 129 /* 130 * tavor_ioctl() 131 */ 132 /* ARGSUSED */ 133 int 134 tavor_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 135 int *rvalp) 136 { 137 tavor_state_t *state; 138 minor_t instance; 139 int status; 140 141 if (drv_priv(credp) != 0) { 142 return (EPERM); 143 } 144 145 instance = TAVOR_DEV_INSTANCE(dev); 146 if (instance == -1) { 147 return (EBADF); 148 } 149 150 state = ddi_get_soft_state(tavor_statep, instance); 151 if (state == NULL) { 152 return (EBADF); 153 } 154 155 status = 0; 156 157 switch (cmd) { 158 case TAVOR_IOCTL_FLASH_READ: 159 status = tavor_ioctl_flash_read(state, dev, arg, mode); 160 break; 161 162 case TAVOR_IOCTL_FLASH_WRITE: 163 status = tavor_ioctl_flash_write(state, dev, arg, mode); 164 break; 165 166 case TAVOR_IOCTL_FLASH_ERASE: 167 status = tavor_ioctl_flash_erase(state, dev, arg, mode); 168 break; 169 170 case TAVOR_IOCTL_FLASH_INIT: 171 status = tavor_ioctl_flash_init(state, dev, arg, mode); 172 break; 173 174 case TAVOR_IOCTL_FLASH_FINI: 175 status = tavor_ioctl_flash_fini(state, dev); 176 break; 177 178 case TAVOR_IOCTL_INFO: 179 status = tavor_ioctl_info(state, dev, arg, mode); 180 break; 181 182 case TAVOR_IOCTL_PORTS: 183 status = tavor_ioctl_ports(state, arg, mode); 184 break; 185 186 case TAVOR_IOCTL_DDR_READ: 187 status = tavor_ioctl_ddr_read(state, arg, mode); 188 break; 189 190 case TAVOR_IOCTL_LOOPBACK: 191 status = tavor_ioctl_loopback(state, arg, mode); 192 break; 193 194 #ifdef DEBUG 195 case TAVOR_IOCTL_REG_WRITE: 196 status = tavor_ioctl_reg_write(state, arg, mode); 197 break; 198 199 case TAVOR_IOCTL_REG_READ: 200 status = tavor_ioctl_reg_read(state, arg, mode); 201 break; 202 #endif /* DEBUG */ 203 204 default: 205 status = ENOTTY; 206 break; 207 } 208 *rvalp = status; 209 210 return (status); 211 } 212 213 /* 214 * tavor_ioctl_flash_read() 215 */ 216 static int 217 tavor_ioctl_flash_read(tavor_state_t *state, dev_t dev, intptr_t arg, int mode) 218 { 219 tavor_flash_ioctl_t ioctl_info; 220 int status = 0; 221 222 /* 223 * Check that flash init ioctl has been called first. And check 224 * that the same dev_t that called init is the one calling read now. 225 */ 226 mutex_enter(&state->ts_fw_flashlock); 227 if ((state->ts_fw_flashdev != dev) || 228 (state->ts_fw_flashstarted == 0)) { 229 mutex_exit(&state->ts_fw_flashlock); 230 return (EIO); 231 } 232 233 /* copy user struct to kernel */ 234 #ifdef _MULTI_DATAMODEL 235 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 236 tavor_flash_ioctl32_t info32; 237 238 if (ddi_copyin((void *)arg, &info32, 239 sizeof (tavor_flash_ioctl32_t), mode) != 0) { 240 mutex_exit(&state->ts_fw_flashlock); 241 return (EFAULT); 242 } 243 ioctl_info.tf_type = info32.tf_type; 244 ioctl_info.tf_sector = (caddr_t)(uintptr_t)info32.tf_sector; 245 ioctl_info.tf_sector_num = info32.tf_sector_num; 246 ioctl_info.tf_addr = info32.tf_addr; 247 } else 248 #endif /* _MULTI_DATAMODEL */ 249 if (ddi_copyin((void *)arg, &ioctl_info, sizeof (tavor_flash_ioctl_t), 250 mode) != 0) { 251 mutex_exit(&state->ts_fw_flashlock); 252 return (EFAULT); 253 } 254 255 /* 256 * Determine type of READ ioctl 257 */ 258 switch (ioctl_info.tf_type) { 259 case TAVOR_FLASH_READ_SECTOR: 260 /* Check if sector num is too large for flash device */ 261 if (ioctl_info.tf_sector_num >= 262 (state->ts_fw_device_sz >> state->ts_fw_log_sector_sz)) { 263 mutex_exit(&state->ts_fw_flashlock); 264 return (EFAULT); 265 } 266 267 /* Perform the Sector Read */ 268 tavor_flash_reset(state); 269 tavor_flash_read_sector(state, ioctl_info.tf_sector_num); 270 271 /* copyout the firmware sector image data */ 272 if (ddi_copyout(&state->ts_fw_sector[0], 273 &ioctl_info.tf_sector[0], 1 << state->ts_fw_log_sector_sz, 274 mode) != 0) { 275 mutex_exit(&state->ts_fw_flashlock); 276 return (EFAULT); 277 } 278 break; 279 280 case TAVOR_FLASH_READ_QUADLET: 281 /* Check if addr is too large for flash device */ 282 if (ioctl_info.tf_addr >= state->ts_fw_device_sz) { 283 mutex_exit(&state->ts_fw_flashlock); 284 return (EFAULT); 285 } 286 287 /* Perform the Quadlet Read */ 288 tavor_flash_reset(state); 289 tavor_flash_read_quadlet(state, &ioctl_info.tf_quadlet, 290 ioctl_info.tf_addr); 291 break; 292 293 default: 294 status = EIO; 295 break; 296 } 297 298 /* copy results back to userland */ 299 #ifdef _MULTI_DATAMODEL 300 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 301 tavor_flash_ioctl32_t info32; 302 303 info32.tf_quadlet = ioctl_info.tf_quadlet; 304 info32.tf_type = ioctl_info.tf_type; 305 info32.tf_sector_num = ioctl_info.tf_sector_num; 306 info32.tf_sector = (caddr32_t)(uintptr_t)ioctl_info.tf_sector; 307 info32.tf_addr = ioctl_info.tf_addr; 308 309 if (ddi_copyout(&info32, (void *)arg, 310 sizeof (tavor_flash_ioctl32_t), mode) != 0) { 311 mutex_exit(&state->ts_fw_flashlock); 312 return (EFAULT); 313 } 314 } else 315 #endif /* _MULTI_DATAMODEL */ 316 if (ddi_copyout(&ioctl_info, (void *)arg, 317 sizeof (tavor_flash_ioctl_t), mode) != 0) { 318 mutex_exit(&state->ts_fw_flashlock); 319 return (EFAULT); 320 } 321 322 mutex_exit(&state->ts_fw_flashlock); 323 return (status); 324 } 325 326 /* 327 * tavor_ioctl_flash_write() 328 */ 329 static int 330 tavor_ioctl_flash_write(tavor_state_t *state, dev_t dev, intptr_t arg, int mode) 331 { 332 tavor_flash_ioctl_t ioctl_info; 333 int status = 0; 334 335 /* 336 * Check that flash init ioctl has been called first. And check 337 * that the same dev_t that called init is the one calling write now. 338 */ 339 mutex_enter(&state->ts_fw_flashlock); 340 if ((state->ts_fw_flashdev != dev) || 341 (state->ts_fw_flashstarted == 0)) { 342 mutex_exit(&state->ts_fw_flashlock); 343 return (EIO); 344 } 345 346 /* copy user struct to kernel */ 347 #ifdef _MULTI_DATAMODEL 348 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 349 tavor_flash_ioctl32_t info32; 350 351 if (ddi_copyin((void *)arg, &info32, 352 sizeof (tavor_flash_ioctl32_t), mode) != 0) { 353 mutex_exit(&state->ts_fw_flashlock); 354 return (EFAULT); 355 } 356 ioctl_info.tf_type = info32.tf_type; 357 ioctl_info.tf_sector = (caddr_t)(uintptr_t)info32.tf_sector; 358 ioctl_info.tf_sector_num = info32.tf_sector_num; 359 ioctl_info.tf_addr = info32.tf_addr; 360 ioctl_info.tf_byte = info32.tf_byte; 361 } else 362 #endif /* _MULTI_DATAMODEL */ 363 if (ddi_copyin((void *)arg, &ioctl_info, 364 sizeof (tavor_flash_ioctl_t), mode) != 0) { 365 mutex_exit(&state->ts_fw_flashlock); 366 return (EFAULT); 367 } 368 369 /* 370 * Determine type of WRITE ioctl 371 */ 372 switch (ioctl_info.tf_type) { 373 case TAVOR_FLASH_WRITE_SECTOR: 374 /* Check if sector num is too large for flash device */ 375 if (ioctl_info.tf_sector_num >= 376 (state->ts_fw_device_sz >> state->ts_fw_log_sector_sz)) { 377 mutex_exit(&state->ts_fw_flashlock); 378 return (EFAULT); 379 } 380 381 /* copy in fw sector image data */ 382 if (ddi_copyin(&ioctl_info.tf_sector[0], 383 &state->ts_fw_sector[0], 1 << state->ts_fw_log_sector_sz, 384 mode) != 0) { 385 mutex_exit(&state->ts_fw_flashlock); 386 return (EFAULT); 387 } 388 389 /* Perform Write Sector */ 390 status = tavor_flash_write_sector(state, 391 ioctl_info.tf_sector_num); 392 break; 393 394 case TAVOR_FLASH_WRITE_BYTE: 395 /* Check if addr is too large for flash device */ 396 if (ioctl_info.tf_addr >= state->ts_fw_device_sz) { 397 mutex_exit(&state->ts_fw_flashlock); 398 return (EFAULT); 399 } 400 401 /* Perform Write Byte */ 402 tavor_flash_bank(state, ioctl_info.tf_addr); 403 tavor_flash_reset(state); 404 status = tavor_flash_write_byte(state, ioctl_info.tf_addr, 405 ioctl_info.tf_byte); 406 tavor_flash_reset(state); 407 break; 408 409 default: 410 status = EIO; 411 break; 412 } 413 414 mutex_exit(&state->ts_fw_flashlock); 415 return (status); 416 } 417 418 /* 419 * tavor_ioctl_flash_erase() 420 */ 421 static int 422 tavor_ioctl_flash_erase(tavor_state_t *state, dev_t dev, intptr_t arg, int mode) 423 { 424 tavor_flash_ioctl_t ioctl_info; 425 int status = 0; 426 427 /* 428 * Check that flash init ioctl has been called first. And check 429 * that the same dev_t that called init is the one calling erase now. 430 */ 431 mutex_enter(&state->ts_fw_flashlock); 432 if ((state->ts_fw_flashdev != dev) || 433 (state->ts_fw_flashstarted == 0)) { 434 mutex_exit(&state->ts_fw_flashlock); 435 return (EIO); 436 } 437 438 /* copy user struct to kernel */ 439 #ifdef _MULTI_DATAMODEL 440 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 441 tavor_flash_ioctl32_t info32; 442 443 if (ddi_copyin((void *)arg, &info32, 444 sizeof (tavor_flash_ioctl32_t), mode) != 0) { 445 mutex_exit(&state->ts_fw_flashlock); 446 return (EFAULT); 447 } 448 ioctl_info.tf_type = info32.tf_type; 449 ioctl_info.tf_sector_num = info32.tf_sector_num; 450 } else 451 #endif /* _MULTI_DATAMODEL */ 452 if (ddi_copyin((void *)arg, &ioctl_info, sizeof (tavor_flash_ioctl_t), 453 mode) != 0) { 454 mutex_exit(&state->ts_fw_flashlock); 455 return (EFAULT); 456 } 457 458 /* 459 * Determine type of ERASE ioctl 460 */ 461 switch (ioctl_info.tf_type) { 462 case TAVOR_FLASH_ERASE_SECTOR: 463 /* Check if sector num is too large for flash device */ 464 if (ioctl_info.tf_sector_num >= 465 (state->ts_fw_device_sz >> state->ts_fw_log_sector_sz)) { 466 mutex_exit(&state->ts_fw_flashlock); 467 return (EFAULT); 468 } 469 470 /* Perform Sector Erase */ 471 status = tavor_flash_erase_sector(state, 472 ioctl_info.tf_sector_num); 473 break; 474 475 case TAVOR_FLASH_ERASE_CHIP: 476 /* Perform Chip Erase */ 477 status = tavor_flash_erase_chip(state); 478 break; 479 480 default: 481 status = EIO; 482 break; 483 } 484 485 mutex_exit(&state->ts_fw_flashlock); 486 return (status); 487 } 488 489 /* 490 * tavor_ioctl_flash_init() 491 */ 492 static int 493 tavor_ioctl_flash_init(tavor_state_t *state, dev_t dev, intptr_t arg, int mode) 494 { 495 tavor_flash_init_ioctl_t init_info; 496 int ret; 497 int intel_xcmd = 0; 498 499 /* 500 * init cannot be called more than once. If we have already init'd the 501 * flash, return directly. 502 */ 503 mutex_enter(&state->ts_fw_flashlock); 504 if (state->ts_fw_flashstarted == 1) { 505 mutex_exit(&state->ts_fw_flashlock); 506 return (EIO); 507 } 508 509 /* copyin the user struct to kernel */ 510 if (ddi_copyin((void *)arg, &init_info, 511 sizeof (tavor_flash_init_ioctl_t), mode) != 0) { 512 mutex_exit(&state->ts_fw_flashlock); 513 return (EFAULT); 514 } 515 516 /* Init Flash */ 517 tavor_flash_init(state); 518 519 /* Read CFI info */ 520 tavor_flash_cfi_init(state, &init_info.tf_cfi_info[0], &intel_xcmd); 521 522 /* 523 * Return error if the command set is unknown. 524 */ 525 if (state->ts_fw_cmdset == TAVOR_FLASH_UNKNOWN_CMDSET) { 526 mutex_exit(&state->ts_fw_flashlock); 527 return (EFAULT); 528 } 529 530 /* Read HWREV - least significant 8 bits is revision ID */ 531 init_info.tf_hwrev = pci_config_get32(state->ts_pci_cfghdl, 532 TAVOR_HW_FLASH_CFG_HWREV) & 0xFF; 533 534 /* Fill in the firmwate revision numbers */ 535 init_info.tf_fwrev.tfi_maj = state->ts_fw.fw_rev_major; 536 init_info.tf_fwrev.tfi_min = state->ts_fw.fw_rev_minor; 537 init_info.tf_fwrev.tfi_sub = state->ts_fw.fw_rev_subminor; 538 539 /* Alloc flash mem for one sector size */ 540 state->ts_fw_sector = (uint32_t *)kmem_zalloc(1 << 541 state->ts_fw_log_sector_sz, KM_SLEEP); 542 543 /* Set HW part number and length */ 544 init_info.tf_pn_len = state->ts_hca_pn_len; 545 if (state->ts_hca_pn_len != 0) { 546 (void) memcpy(init_info.tf_hwpn, state->ts_hca_pn, 547 state->ts_hca_pn_len); 548 } 549 550 /* Copy ioctl results back to userland */ 551 if (ddi_copyout(&init_info, (void *)arg, 552 sizeof (tavor_flash_init_ioctl_t), mode) != 0) { 553 554 tavor_ioctl_flash_cleanup_nolock(state); 555 556 mutex_exit(&state->ts_fw_flashlock); 557 return (EFAULT); 558 } 559 560 /* Set flash state to started */ 561 state->ts_fw_flashstarted = 1; 562 state->ts_fw_flashdev = dev; 563 564 mutex_exit(&state->ts_fw_flashlock); 565 566 /* 567 * If "flash init" is successful, add an "on close" callback to the 568 * current dev node to ensure that "flash fini" gets called later 569 * even if the userland process prematurely exits. 570 */ 571 ret = tavor_umap_db_set_onclose_cb(dev, 572 TAVOR_ONCLOSE_FLASH_INPROGRESS, 573 (void (*)(void *))tavor_ioctl_flash_cleanup, state); 574 if (ret != DDI_SUCCESS) { 575 (void) tavor_ioctl_flash_fini(state, dev); 576 577 return (EFAULT); 578 } 579 580 return (0); 581 } 582 583 /* 584 * tavor_ioctl_flash_fini() 585 */ 586 static int 587 tavor_ioctl_flash_fini(tavor_state_t *state, dev_t dev) 588 { 589 int ret; 590 591 /* 592 * Check that flash init ioctl has been called first. And check 593 * that the same dev_t that called init is the one calling fini now. 594 */ 595 mutex_enter(&state->ts_fw_flashlock); 596 if ((state->ts_fw_flashdev != dev) || 597 (state->ts_fw_flashstarted == 0)) { 598 mutex_exit(&state->ts_fw_flashlock); 599 return (EIO); 600 } 601 602 tavor_ioctl_flash_cleanup_nolock(state); 603 604 mutex_exit(&state->ts_fw_flashlock); 605 606 /* 607 * If "flash fini" is successful, remove the "on close" callback 608 * that was setup during "flash init". 609 */ 610 ret = tavor_umap_db_clear_onclose_cb(dev, 611 TAVOR_ONCLOSE_FLASH_INPROGRESS); 612 if (ret != DDI_SUCCESS) { 613 return (EFAULT); 614 } 615 616 return (0); 617 } 618 619 620 /* 621 * tavor_ioctl_flash_cleanup() 622 */ 623 static void 624 tavor_ioctl_flash_cleanup(tavor_state_t *state) 625 { 626 mutex_enter(&state->ts_fw_flashlock); 627 tavor_ioctl_flash_cleanup_nolock(state); 628 mutex_exit(&state->ts_fw_flashlock); 629 } 630 631 632 /* 633 * tavor_ioctl_flash_cleanup_nolock() 634 */ 635 static void 636 tavor_ioctl_flash_cleanup_nolock(tavor_state_t *state) 637 { 638 ASSERT(MUTEX_HELD(&state->ts_fw_flashlock)); 639 640 /* free flash mem */ 641 kmem_free(state->ts_fw_sector, 1 << state->ts_fw_log_sector_sz); 642 643 /* Fini the Flash */ 644 tavor_flash_fini(state); 645 646 /* Set flash state to fini */ 647 state->ts_fw_flashstarted = 0; 648 state->ts_fw_flashdev = 0; 649 } 650 651 652 /* 653 * tavor_ioctl_info() 654 */ 655 static int 656 tavor_ioctl_info(tavor_state_t *state, dev_t dev, intptr_t arg, int mode) 657 { 658 tavor_info_ioctl_t info; 659 tavor_flash_init_ioctl_t init_info; 660 661 /* 662 * Access to Tavor VTS ioctls is not allowed in "maintenance mode". 663 */ 664 if (state->ts_operational_mode == TAVOR_MAINTENANCE_MODE) { 665 return (EFAULT); 666 } 667 668 /* copyin the user struct to kernel */ 669 if (ddi_copyin((void *)arg, &info, sizeof (tavor_info_ioctl_t), 670 mode) != 0) { 671 return (EFAULT); 672 } 673 674 /* 675 * Check ioctl revision 676 */ 677 if (info.ti_revision != TAVOR_VTS_IOCTL_REVISION) { 678 return (EINVAL); 679 } 680 681 /* 682 * If the 'fw_device_sz' has not been initialized yet, we initialize it 683 * here. This is done by leveraging the 684 * tavor_ioctl_flash_init()/fini() calls. We also hold our own mutex 685 * around this operation in case we have multiple VTS threads in 686 * process at the same time. 687 */ 688 mutex_enter(&state->ts_info_lock); 689 if (state->ts_fw_device_sz == 0) { 690 if (tavor_ioctl_flash_init(state, dev, (intptr_t)&init_info, 691 (FKIOCTL | mode)) != 0) { 692 mutex_exit(&state->ts_info_lock); 693 return (EFAULT); 694 } 695 (void) tavor_ioctl_flash_fini(state, dev); 696 } 697 mutex_exit(&state->ts_info_lock); 698 699 info.ti_hw_rev = state->ts_adapter.rev_id; 700 info.ti_flash_sz = state->ts_fw_device_sz; 701 info.ti_fw_rev.tfi_maj = state->ts_fw.fw_rev_major; 702 info.ti_fw_rev.tfi_min = state->ts_fw.fw_rev_minor; 703 info.ti_fw_rev.tfi_sub = state->ts_fw.fw_rev_subminor; 704 info.ti_mem_start_offset = 0; 705 info.ti_mem_end_offset = state->ts_ddr.ddr_endaddr - 706 state->ts_ddr.ddr_baseaddr; 707 708 /* Copy ioctl results back to user struct */ 709 if (ddi_copyout(&info, (void *)arg, sizeof (tavor_info_ioctl_t), 710 mode) != 0) { 711 return (EFAULT); 712 } 713 714 return (0); 715 } 716 717 /* 718 * tavor_ioctl_ports() 719 */ 720 static int 721 tavor_ioctl_ports(tavor_state_t *state, intptr_t arg, int mode) 722 { 723 tavor_ports_ioctl_t info; 724 tavor_stat_port_ioctl_t portstat; 725 ibt_hca_portinfo_t pi; 726 uint_t tbl_size; 727 ib_gid_t *sgid_tbl; 728 ib_pkey_t *pkey_tbl; 729 int i; 730 731 /* 732 * Access to Tavor VTS ioctls is not allowed in "maintenance mode". 733 */ 734 if (state->ts_operational_mode == TAVOR_MAINTENANCE_MODE) { 735 return (EFAULT); 736 } 737 738 /* copyin the user struct to kernel */ 739 #ifdef _MULTI_DATAMODEL 740 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 741 tavor_ports_ioctl32_t info32; 742 743 if (ddi_copyin((void *)arg, &info32, 744 sizeof (tavor_ports_ioctl32_t), mode) != 0) { 745 return (EFAULT); 746 } 747 info.tp_revision = info32.tp_revision; 748 info.tp_ports = 749 (tavor_stat_port_ioctl_t *)(uintptr_t)info32.tp_ports; 750 info.tp_num_ports = info32.tp_num_ports; 751 752 } else 753 #endif /* _MULTI_DATAMODEL */ 754 if (ddi_copyin((void *)arg, &info, sizeof (tavor_ports_ioctl_t), 755 mode) != 0) { 756 return (EFAULT); 757 } 758 759 /* 760 * Check ioctl revision 761 */ 762 if (info.tp_revision != TAVOR_VTS_IOCTL_REVISION) { 763 return (EINVAL); 764 } 765 766 /* Allocate space for temporary GID table/PKey table */ 767 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_gidtbl); 768 sgid_tbl = (ib_gid_t *)kmem_zalloc(tbl_size * sizeof (ib_gid_t), 769 KM_SLEEP); 770 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_pkeytbl); 771 pkey_tbl = (ib_pkey_t *)kmem_zalloc(tbl_size * sizeof (ib_pkey_t), 772 KM_SLEEP); 773 774 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sgid_tbl, *pkey_tbl)) 775 776 /* 777 * Setup the number of ports, then loop through all ports and 778 * query properties of each. 779 */ 780 info.tp_num_ports = (uint8_t)state->ts_cfg_profile->cp_num_ports; 781 for (i = 0; i < info.tp_num_ports; i++) { 782 /* 783 * Get portstate information from the device. If 784 * tavor_port_query() fails, leave zeroes in user 785 * struct port entry and continue. 786 */ 787 bzero(&pi, sizeof (ibt_hca_portinfo_t)); 788 pi.p_sgid_tbl = sgid_tbl; 789 pi.p_pkey_tbl = pkey_tbl; 790 (void) tavor_port_query(state, i + 1, &pi); 791 792 portstat.tsp_port_num = pi.p_port_num; 793 portstat.tsp_state = pi.p_linkstate; 794 portstat.tsp_guid = pi.p_sgid_tbl[0].gid_guid; 795 796 /* 797 * Copy queried port results back to user struct. If 798 * this fails, then break out of loop, attempt to copy 799 * out remaining info to user struct, and return (without 800 * error). 801 */ 802 if (ddi_copyout(&portstat, 803 &(((tavor_stat_port_ioctl_t *)info.tp_ports)[i]), 804 sizeof (tavor_stat_port_ioctl_t), mode) != 0) { 805 break; 806 } 807 } 808 809 /* Free the temporary space used for GID table/PKey table */ 810 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_gidtbl); 811 kmem_free(sgid_tbl, tbl_size * sizeof (ib_gid_t)); 812 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_pkeytbl); 813 kmem_free(pkey_tbl, tbl_size * sizeof (ib_pkey_t)); 814 815 /* Copy ioctl results back to user struct */ 816 #ifdef _MULTI_DATAMODEL 817 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 818 tavor_ports_ioctl32_t info32; 819 820 info32.tp_revision = info.tp_revision; 821 info32.tp_ports = (caddr32_t)(uintptr_t)info.tp_ports; 822 info32.tp_num_ports = info.tp_num_ports; 823 824 if (ddi_copyout(&info32, (void *)arg, 825 sizeof (tavor_ports_ioctl32_t), mode) != 0) { 826 return (EFAULT); 827 } 828 } else 829 #endif /* _MULTI_DATAMODEL */ 830 if (ddi_copyout(&info, (void *)arg, sizeof (tavor_ports_ioctl_t), 831 mode) != 0) { 832 return (EFAULT); 833 } 834 835 return (0); 836 } 837 838 /* 839 * tavor_ioctl_loopback() 840 */ 841 static int 842 tavor_ioctl_loopback(tavor_state_t *state, intptr_t arg, int mode) 843 { 844 tavor_loopback_ioctl_t lb; 845 tavor_loopback_state_t lstate; 846 ibt_hca_portinfo_t pi; 847 uint_t tbl_size, loopmax, max_usec; 848 ib_gid_t *sgid_tbl; 849 ib_pkey_t *pkey_tbl; 850 int j, iter, ret; 851 852 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(lstate)) 853 854 /* 855 * Access to Tavor VTS ioctls is not allowed in "maintenance mode". 856 */ 857 if (state->ts_operational_mode == TAVOR_MAINTENANCE_MODE) { 858 return (EFAULT); 859 } 860 861 /* copyin the user struct to kernel */ 862 #ifdef _MULTI_DATAMODEL 863 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 864 tavor_loopback_ioctl32_t lb32; 865 866 if (ddi_copyin((void *)arg, &lb32, 867 sizeof (tavor_loopback_ioctl32_t), mode) != 0) { 868 return (EFAULT); 869 } 870 lb.tlb_revision = lb32.tlb_revision; 871 lb.tlb_send_buf = (caddr_t)(uintptr_t)lb32.tlb_send_buf; 872 lb.tlb_fail_buf = (caddr_t)(uintptr_t)lb32.tlb_fail_buf; 873 lb.tlb_buf_sz = lb32.tlb_buf_sz; 874 lb.tlb_num_iter = lb32.tlb_num_iter; 875 lb.tlb_pass_done = lb32.tlb_pass_done; 876 lb.tlb_timeout = lb32.tlb_timeout; 877 lb.tlb_error_type = lb32.tlb_error_type; 878 lb.tlb_port_num = lb32.tlb_port_num; 879 lb.tlb_num_retry = lb32.tlb_num_retry; 880 } else 881 #endif /* _MULTI_DATAMODEL */ 882 if (ddi_copyin((void *)arg, &lb, sizeof (tavor_loopback_ioctl_t), 883 mode) != 0) { 884 return (EFAULT); 885 } 886 887 /* Initialize the internal loopback test state structure */ 888 bzero(&lstate, sizeof (tavor_loopback_state_t)); 889 890 /* 891 * Check ioctl revision 892 */ 893 if (lb.tlb_revision != TAVOR_VTS_IOCTL_REVISION) { 894 lb.tlb_error_type = TAVOR_LOOPBACK_INVALID_REVISION; 895 (void) tavor_loopback_copyout(&lb, arg, mode); 896 return (EINVAL); 897 } 898 899 /* Validate that specified port number is legal */ 900 if (!tavor_portnum_is_valid(state, lb.tlb_port_num)) { 901 lb.tlb_error_type = TAVOR_LOOPBACK_INVALID_PORT; 902 (void) tavor_loopback_copyout(&lb, arg, mode); 903 return (EINVAL); 904 } 905 906 /* Allocate space for temporary GID table/PKey table */ 907 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_gidtbl); 908 sgid_tbl = (ib_gid_t *)kmem_zalloc(tbl_size * sizeof (ib_gid_t), 909 KM_SLEEP); 910 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_pkeytbl); 911 pkey_tbl = (ib_pkey_t *)kmem_zalloc(tbl_size * sizeof (ib_pkey_t), 912 KM_SLEEP); 913 914 /* 915 * Get portstate information from specific port on device 916 */ 917 bzero(&pi, sizeof (ibt_hca_portinfo_t)); 918 pi.p_sgid_tbl = sgid_tbl; 919 pi.p_pkey_tbl = pkey_tbl; 920 if (tavor_port_query(state, lb.tlb_port_num, &pi) != 0) { 921 /* Free the temporary space used for GID table/PKey table */ 922 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_gidtbl); 923 kmem_free(sgid_tbl, tbl_size * sizeof (ib_gid_t)); 924 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_pkeytbl); 925 kmem_free(pkey_tbl, tbl_size * sizeof (ib_pkey_t)); 926 927 lb.tlb_error_type = TAVOR_LOOPBACK_INVALID_PORT; 928 (void) tavor_loopback_copyout(&lb, arg, mode); 929 tavor_loopback_free_state(&lstate); 930 return (EINVAL); 931 } 932 933 lstate.tls_port = pi.p_port_num; 934 lstate.tls_lid = pi.p_base_lid; 935 lstate.tls_pkey_ix = (pi.p_linkstate == TAVOR_PORT_LINK_ACTIVE) ? 1 : 0; 936 lstate.tls_state = state; 937 lstate.tls_retry = lb.tlb_num_retry; 938 939 /* Free the temporary space used for GID table/PKey table */ 940 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_gidtbl); 941 kmem_free(sgid_tbl, tbl_size * sizeof (ib_gid_t)); 942 tbl_size = (1 << state->ts_cfg_profile->cp_log_max_pkeytbl); 943 kmem_free(pkey_tbl, tbl_size * sizeof (ib_pkey_t)); 944 945 /* 946 * Compute the timeout duration in usec per the formula: 947 * to_usec_per_retry = 4.096us * (2 ^ supplied_timeout) 948 * (plus we add a little fudge-factor here too) 949 */ 950 lstate.tls_timeout = lb.tlb_timeout; 951 max_usec = (4096 * (1 << lstate.tls_timeout)) / 1000; 952 max_usec = max_usec * (lstate.tls_retry + 1); 953 max_usec = max_usec + 10000; 954 955 /* 956 * Determine how many times we should loop before declaring a 957 * timeout failure. 958 */ 959 loopmax = max_usec/TAVOR_VTS_LOOPBACK_MIN_WAIT_DUR; 960 if ((max_usec % TAVOR_VTS_LOOPBACK_MIN_WAIT_DUR) != 0) { 961 loopmax++; 962 } 963 964 if (lb.tlb_send_buf == NULL || lb.tlb_buf_sz == 0) { 965 lb.tlb_error_type = TAVOR_LOOPBACK_SEND_BUF_INVALID; 966 (void) tavor_loopback_copyout(&lb, arg, mode); 967 tavor_loopback_free_state(&lstate); 968 return (EINVAL); 969 } 970 971 /* Allocate protection domain (PD) */ 972 if (tavor_loopback_init(state, &lstate) != 0) { 973 lb.tlb_error_type = lstate.tls_err; 974 (void) tavor_loopback_copyout(&lb, arg, mode); 975 tavor_loopback_free_state(&lstate); 976 return (EFAULT); 977 } 978 979 /* Allocate and register a TX buffer */ 980 if (tavor_loopback_alloc_mem(&lstate, &lstate.tls_tx, 981 lb.tlb_buf_sz) != 0) { 982 lb.tlb_error_type = 983 TAVOR_LOOPBACK_SEND_BUF_MEM_REGION_ALLOC_FAIL; 984 (void) tavor_loopback_copyout(&lb, arg, mode); 985 tavor_loopback_free_state(&lstate); 986 return (EFAULT); 987 } 988 989 /* Allocate and register an RX buffer */ 990 if (tavor_loopback_alloc_mem(&lstate, &lstate.tls_rx, 991 lb.tlb_buf_sz) != 0) { 992 lb.tlb_error_type = 993 TAVOR_LOOPBACK_RECV_BUF_MEM_REGION_ALLOC_FAIL; 994 (void) tavor_loopback_copyout(&lb, arg, mode); 995 tavor_loopback_free_state(&lstate); 996 return (EFAULT); 997 } 998 999 /* Copy in the transmit buffer data */ 1000 if (ddi_copyin((void *)lb.tlb_send_buf, lstate.tls_tx.tlc_buf, 1001 lb.tlb_buf_sz, mode) != 0) { 1002 lb.tlb_error_type = TAVOR_LOOPBACK_SEND_BUF_COPY_FAIL; 1003 (void) tavor_loopback_copyout(&lb, arg, mode); 1004 tavor_loopback_free_state(&lstate); 1005 return (EFAULT); 1006 } 1007 1008 /* Allocate the transmit QP and CQs */ 1009 lstate.tls_err = TAVOR_LOOPBACK_XMIT_SEND_CQ_ALLOC_FAIL; 1010 if (tavor_loopback_alloc_qps(&lstate, &lstate.tls_tx) != 0) { 1011 lb.tlb_error_type = lstate.tls_err; 1012 (void) tavor_loopback_copyout(&lb, arg, mode); 1013 tavor_loopback_free_state(&lstate); 1014 return (EFAULT); 1015 } 1016 1017 /* Allocate the receive QP and CQs */ 1018 lstate.tls_err = TAVOR_LOOPBACK_RECV_SEND_CQ_ALLOC_FAIL; 1019 if (tavor_loopback_alloc_qps(&lstate, &lstate.tls_rx) != 0) { 1020 lb.tlb_error_type = lstate.tls_err; 1021 (void) tavor_loopback_copyout(&lb, arg, mode); 1022 tavor_loopback_free_state(&lstate); 1023 return (EFAULT); 1024 } 1025 1026 /* Activate the TX QP (connect to RX QP) */ 1027 lstate.tls_err = TAVOR_LOOPBACK_XMIT_QP_INIT_FAIL; 1028 if (tavor_loopback_modify_qp(&lstate, &lstate.tls_tx, 1029 lstate.tls_rx.tlc_qp_num) != 0) { 1030 lb.tlb_error_type = lstate.tls_err; 1031 (void) tavor_loopback_copyout(&lb, arg, mode); 1032 tavor_loopback_free_state(&lstate); 1033 return (EFAULT); 1034 } 1035 1036 /* Activate the RX QP (connect to TX QP) */ 1037 lstate.tls_err = TAVOR_LOOPBACK_RECV_QP_INIT_FAIL; 1038 if (tavor_loopback_modify_qp(&lstate, &lstate.tls_rx, 1039 lstate.tls_tx.tlc_qp_num) != 0) { 1040 lb.tlb_error_type = lstate.tls_err; 1041 (void) tavor_loopback_copyout(&lb, arg, mode); 1042 tavor_loopback_free_state(&lstate); 1043 return (EFAULT); 1044 } 1045 1046 /* Run the loopback test (for specified number of iterations) */ 1047 lb.tlb_pass_done = 0; 1048 for (iter = 0; iter < lb.tlb_num_iter; iter++) { 1049 lstate.tls_err = 0; 1050 bzero(lstate.tls_rx.tlc_buf, lb.tlb_buf_sz); 1051 1052 /* Post RDMA Write work request */ 1053 if (tavor_loopback_post_send(&lstate, &lstate.tls_tx, 1054 &lstate.tls_rx) != IBT_SUCCESS) { 1055 lb.tlb_error_type = TAVOR_LOOPBACK_WQE_POST_FAIL; 1056 (void) tavor_loopback_copyout(&lb, arg, mode); 1057 tavor_loopback_free_state(&lstate); 1058 return (EFAULT); 1059 } 1060 1061 /* Poll the TX CQ for a completion every few ticks */ 1062 for (j = 0; j < loopmax; j++) { 1063 delay(drv_usectohz(TAVOR_VTS_LOOPBACK_MIN_WAIT_DUR)); 1064 1065 ret = tavor_loopback_poll_cq(&lstate, &lstate.tls_tx); 1066 if (((ret != IBT_SUCCESS) && (ret != IBT_CQ_EMPTY)) || 1067 ((ret == IBT_CQ_EMPTY) && (j == loopmax - 1))) { 1068 lb.tlb_error_type = TAVOR_LOOPBACK_CQ_POLL_FAIL; 1069 if (ddi_copyout(lstate.tls_rx.tlc_buf, 1070 lb.tlb_fail_buf, lstate.tls_tx.tlc_buf_sz, 1071 mode) != 0) { 1072 return (EFAULT); 1073 } 1074 (void) tavor_loopback_copyout(&lb, arg, mode); 1075 tavor_loopback_free_state(&lstate); 1076 return (EFAULT); 1077 } else if (ret == IBT_CQ_EMPTY) { 1078 continue; 1079 } 1080 1081 /* Compare the data buffers */ 1082 if (bcmp(lstate.tls_tx.tlc_buf, lstate.tls_rx.tlc_buf, 1083 lb.tlb_buf_sz) == 0) { 1084 break; 1085 } else { 1086 lb.tlb_error_type = 1087 TAVOR_LOOPBACK_SEND_RECV_COMPARE_FAIL; 1088 if (ddi_copyout(lstate.tls_rx.tlc_buf, 1089 lb.tlb_fail_buf, lstate.tls_tx.tlc_buf_sz, 1090 mode) != 0) { 1091 return (EFAULT); 1092 } 1093 (void) tavor_loopback_copyout(&lb, arg, mode); 1094 tavor_loopback_free_state(&lstate); 1095 return (EFAULT); 1096 } 1097 } 1098 1099 lstate.tls_err = TAVOR_LOOPBACK_SUCCESS; 1100 lb.tlb_pass_done = iter + 1; 1101 } 1102 1103 lb.tlb_error_type = TAVOR_LOOPBACK_SUCCESS; 1104 1105 /* Copy ioctl results back to user struct */ 1106 ret = tavor_loopback_copyout(&lb, arg, mode); 1107 1108 /* Free up everything and release all consumed resources */ 1109 tavor_loopback_free_state(&lstate); 1110 1111 return (ret); 1112 } 1113 1114 /* 1115 * tavor_ioctl_ddr_read() 1116 */ 1117 static int 1118 tavor_ioctl_ddr_read(tavor_state_t *state, intptr_t arg, int mode) 1119 { 1120 tavor_ddr_read_ioctl_t rdreg; 1121 uint32_t *addr; 1122 uintptr_t baseaddr; 1123 uint64_t ddr_size; 1124 1125 /* 1126 * Access to Tavor VTS ioctls is not allowed in "maintenance mode". 1127 */ 1128 if (state->ts_operational_mode == TAVOR_MAINTENANCE_MODE) { 1129 return (EFAULT); 1130 } 1131 1132 /* copyin the user struct to kernel */ 1133 if (ddi_copyin((void *)arg, &rdreg, sizeof (tavor_ddr_read_ioctl_t), 1134 mode) != 0) { 1135 return (EFAULT); 1136 } 1137 1138 /* 1139 * Check ioctl revision 1140 */ 1141 if (rdreg.tdr_revision != TAVOR_VTS_IOCTL_REVISION) { 1142 return (EINVAL); 1143 } 1144 1145 /* 1146 * Check for valid offset 1147 */ 1148 ddr_size = (state->ts_ddr.ddr_endaddr - state->ts_ddr.ddr_baseaddr + 1); 1149 if ((uint64_t)rdreg.tdr_offset >= ddr_size) { 1150 return (EINVAL); 1151 } 1152 1153 /* Determine base address for requested register read */ 1154 baseaddr = (uintptr_t)state->ts_reg_ddr_baseaddr; 1155 1156 /* Ensure that address is properly-aligned */ 1157 addr = (uint32_t *)((baseaddr + rdreg.tdr_offset) & ~0x3); 1158 1159 /* Read the register pointed to by addr */ 1160 rdreg.tdr_data = ddi_get32(state->ts_reg_cmdhdl, addr); 1161 1162 /* Copy ioctl results back to user struct */ 1163 if (ddi_copyout(&rdreg, (void *)arg, sizeof (tavor_ddr_read_ioctl_t), 1164 mode) != 0) { 1165 return (EFAULT); 1166 } 1167 1168 return (0); 1169 } 1170 1171 1172 #ifdef DEBUG 1173 /* 1174 * tavor_ioctl_reg_read() 1175 */ 1176 static int 1177 tavor_ioctl_reg_read(tavor_state_t *state, intptr_t arg, int mode) 1178 { 1179 tavor_reg_ioctl_t rdreg; 1180 uint32_t *addr; 1181 uintptr_t baseaddr; 1182 int status; 1183 1184 /* 1185 * Access to Tavor registers is not allowed in "maintenance mode". 1186 * This is primarily because the device may not have BARs to access 1187 */ 1188 if (state->ts_operational_mode == TAVOR_MAINTENANCE_MODE) { 1189 return (EFAULT); 1190 } 1191 1192 /* Copy in the tavor_reg_ioctl_t structure */ 1193 status = ddi_copyin((void *)arg, &rdreg, sizeof (tavor_reg_ioctl_t), 1194 mode); 1195 if (status != 0) { 1196 return (EFAULT); 1197 } 1198 1199 /* Determine base address for requested register set */ 1200 switch (rdreg.trg_reg_set) { 1201 case TAVOR_CMD_BAR: 1202 baseaddr = (uintptr_t)state->ts_reg_cmd_baseaddr; 1203 break; 1204 1205 case TAVOR_UAR_BAR: 1206 baseaddr = (uintptr_t)state->ts_reg_uar_baseaddr; 1207 break; 1208 1209 case TAVOR_DDR_BAR: 1210 baseaddr = (uintptr_t)state->ts_reg_ddr_baseaddr; 1211 break; 1212 1213 default: 1214 return (EFAULT); 1215 } 1216 1217 /* Ensure that address is properly-aligned */ 1218 addr = (uint32_t *)((baseaddr + rdreg.trg_offset) & ~0x3); 1219 1220 /* Read the register pointed to by addr */ 1221 rdreg.trg_data = ddi_get32(state->ts_reg_cmdhdl, addr); 1222 1223 /* Copy in the result into the tavor_reg_ioctl_t structure */ 1224 status = ddi_copyout(&rdreg, (void *)arg, sizeof (tavor_reg_ioctl_t), 1225 mode); 1226 if (status != 0) { 1227 return (EFAULT); 1228 } 1229 1230 return (0); 1231 } 1232 1233 1234 /* 1235 * tavor_ioctl_reg_write() 1236 */ 1237 static int 1238 tavor_ioctl_reg_write(tavor_state_t *state, intptr_t arg, int mode) 1239 { 1240 tavor_reg_ioctl_t wrreg; 1241 uint32_t *addr; 1242 uintptr_t baseaddr; 1243 int status; 1244 1245 /* 1246 * Access to Tavor registers is not allowed in "maintenance mode". 1247 * This is primarily because the device may not have BARs to access 1248 */ 1249 if (state->ts_operational_mode == TAVOR_MAINTENANCE_MODE) { 1250 return (EFAULT); 1251 } 1252 1253 /* Copy in the tavor_reg_ioctl_t structure */ 1254 status = ddi_copyin((void *)arg, &wrreg, sizeof (tavor_reg_ioctl_t), 1255 mode); 1256 if (status != 0) { 1257 return (EFAULT); 1258 } 1259 1260 /* Determine base address for requested register set */ 1261 switch (wrreg.trg_reg_set) { 1262 case TAVOR_CMD_BAR: 1263 baseaddr = (uintptr_t)state->ts_reg_cmd_baseaddr; 1264 break; 1265 1266 case TAVOR_UAR_BAR: 1267 baseaddr = (uintptr_t)state->ts_reg_uar_baseaddr; 1268 break; 1269 1270 case TAVOR_DDR_BAR: 1271 baseaddr = (uintptr_t)state->ts_reg_ddr_baseaddr; 1272 break; 1273 1274 default: 1275 return (EFAULT); 1276 } 1277 1278 /* Ensure that address is properly-aligned */ 1279 addr = (uint32_t *)((baseaddr + wrreg.trg_offset) & ~0x3); 1280 1281 /* Write the data to the register pointed to by addr */ 1282 ddi_put32(state->ts_reg_cmdhdl, addr, wrreg.trg_data); 1283 1284 return (0); 1285 } 1286 #endif /* DEBUG */ 1287 1288 /* 1289 * tavor_flash_reset() 1290 */ 1291 static void 1292 tavor_flash_reset(tavor_state_t *state) 1293 { 1294 /* 1295 * Performs a reset to the flash device. After a reset the flash will 1296 * be operating in normal mode (capable of read/write, etc.). 1297 */ 1298 switch (state->ts_fw_cmdset) { 1299 case TAVOR_FLASH_AMD_CMDSET: 1300 tavor_flash_write(state, 0x555, TAVOR_HW_FLASH_RESET_AMD); 1301 break; 1302 1303 case TAVOR_FLASH_INTEL_CMDSET: 1304 tavor_flash_write(state, 0x555, TAVOR_HW_FLASH_RESET_INTEL); 1305 break; 1306 1307 default: 1308 break; 1309 } 1310 } 1311 1312 /* 1313 * tavor_flash_read_sector() 1314 */ 1315 static void 1316 tavor_flash_read_sector(tavor_state_t *state, uint32_t sector_num) 1317 { 1318 uint32_t addr; 1319 uint32_t end_addr; 1320 uint32_t *image; 1321 int i; 1322 1323 image = (uint32_t *)&state->ts_fw_sector[0]; 1324 1325 /* 1326 * Calculate the start and end address of the sector, based on the 1327 * sector number passed in. 1328 */ 1329 addr = sector_num << state->ts_fw_log_sector_sz; 1330 end_addr = addr + (1 << state->ts_fw_log_sector_sz); 1331 1332 /* Set the flash bank correctly for the given address */ 1333 tavor_flash_bank(state, addr); 1334 1335 /* Read the entire sector, one quadlet at a time */ 1336 for (i = 0; addr < end_addr; i++, addr += 4) { 1337 image[i] = tavor_flash_read(state, addr); 1338 } 1339 } 1340 1341 /* 1342 * tavor_flash_read_quadlet() 1343 */ 1344 static void 1345 tavor_flash_read_quadlet(tavor_state_t *state, uint32_t *data, 1346 uint32_t addr) 1347 { 1348 /* Set the flash bank correctly for the given address */ 1349 tavor_flash_bank(state, addr); 1350 1351 /* Read one quadlet of data */ 1352 *data = tavor_flash_read(state, addr); 1353 } 1354 1355 /* 1356 * tavor_flash_write_sector() 1357 */ 1358 static int 1359 tavor_flash_write_sector(tavor_state_t *state, uint32_t sector_num) 1360 { 1361 uint32_t addr; 1362 uint32_t end_addr; 1363 uchar_t *sector; 1364 int status = 0; 1365 int i; 1366 1367 sector = (uchar_t *)&state->ts_fw_sector[0]; 1368 1369 /* 1370 * Calculate the start and end address of the sector, based on the 1371 * sector number passed in. 1372 */ 1373 addr = sector_num << state->ts_fw_log_sector_sz; 1374 end_addr = addr + (1 << state->ts_fw_log_sector_sz); 1375 1376 /* Set the flash bank correctly for the given address */ 1377 tavor_flash_bank(state, addr); 1378 1379 /* Erase the sector before writing */ 1380 tavor_flash_reset(state); 1381 status = tavor_flash_erase_sector(state, sector_num); 1382 if (status != 0) { 1383 return (status); 1384 } 1385 1386 /* Write the entire sector, one byte at a time */ 1387 for (i = 0; addr < end_addr; i++, addr++) { 1388 status = tavor_flash_write_byte(state, addr, sector[i]); 1389 if (status != 0) { 1390 break; 1391 } 1392 } 1393 1394 tavor_flash_reset(state); 1395 return (status); 1396 } 1397 1398 /* 1399 * tavor_flash_write_byte() 1400 */ 1401 static int 1402 tavor_flash_write_byte(tavor_state_t *state, uint32_t addr, uchar_t data) 1403 { 1404 uint32_t stat; 1405 int status = 0; 1406 int i; 1407 1408 switch (state->ts_fw_cmdset) { 1409 case TAVOR_FLASH_AMD_CMDSET: 1410 /* Issue Flash Byte program command */ 1411 tavor_flash_write(state, addr, 0xAA); 1412 tavor_flash_write(state, addr, 0x55); 1413 tavor_flash_write(state, addr, 0xA0); 1414 tavor_flash_write(state, addr, data); 1415 1416 /* 1417 * Wait for Write Byte to Complete: 1418 * 1) Wait 1usec 1419 * 2) Read status of the write operation 1420 * 3) Determine if we have timed out the write operation 1421 * 4) Compare correct data value to the status value that 1422 * was read from the same address. 1423 */ 1424 i = 0; 1425 do { 1426 drv_usecwait(1); 1427 stat = tavor_flash_read(state, addr & ~3); 1428 1429 if (i == tavor_hw_flash_timeout_write) { 1430 cmn_err(CE_WARN, 1431 "tavor_flash_write_byte: ACS write " 1432 "timeout: addr: 0x%x, data: 0x%x\n", 1433 addr, data); 1434 status = EIO; 1435 break; 1436 } 1437 1438 i++; 1439 } while (data != ((stat >> ((3 - (addr & 3)) << 3)) & 0xFF)); 1440 break; 1441 1442 case TAVOR_FLASH_INTEL_CMDSET: 1443 /* Issue Flash Byte program command */ 1444 tavor_flash_write(state, addr, TAVOR_HW_FLASH_ICS_WRITE); 1445 tavor_flash_write(state, addr, data); 1446 1447 /* wait for completion */ 1448 i = 0; 1449 do { 1450 drv_usecwait(1); 1451 stat = tavor_flash_read(state, addr & ~3); 1452 1453 if (i == tavor_hw_flash_timeout_write) { 1454 cmn_err(CE_WARN, 1455 "tavor_flash_write_byte: ICS write " 1456 "timeout: addr: %x, data: %x\n", 1457 addr, data); 1458 status = EIO; 1459 break; 1460 } 1461 1462 i++; 1463 } while ((stat & TAVOR_HW_FLASH_ICS_READY) == 0); 1464 1465 if (stat & TAVOR_HW_FLASH_ICS_ERROR) { 1466 cmn_err(CE_WARN, 1467 "tavor_flash_write_byte: ICS write cmd error: " 1468 "addr: %x, data: %x\n", 1469 addr, data); 1470 status = EIO; 1471 } 1472 break; 1473 1474 default: 1475 cmn_err(CE_WARN, 1476 "tavor_flash_write_byte: unknown cmd set: 0x%x\n", 1477 state->ts_fw_cmdset); 1478 status = EIO; 1479 break; 1480 } 1481 1482 return (status); 1483 } 1484 1485 /* 1486 * tavor_flash_erase_sector() 1487 */ 1488 static int 1489 tavor_flash_erase_sector(tavor_state_t *state, uint32_t sector_num) 1490 { 1491 uint32_t addr; 1492 uint32_t stat; 1493 int status = 0; 1494 int i; 1495 1496 /* Get address from sector num */ 1497 addr = sector_num << state->ts_fw_log_sector_sz; 1498 1499 switch (state->ts_fw_cmdset) { 1500 case TAVOR_FLASH_AMD_CMDSET: 1501 /* Issue Flash Sector Erase Command */ 1502 tavor_flash_write(state, addr, 0xAA); 1503 tavor_flash_write(state, addr, 0x55); 1504 tavor_flash_write(state, addr, 0x80); 1505 tavor_flash_write(state, addr, 0xAA); 1506 tavor_flash_write(state, addr, 0x55); 1507 tavor_flash_write(state, addr, 0x30); 1508 1509 /* 1510 * Wait for Sector Erase to Complete 1511 * 1) Wait 1usec 1512 * 2) read the status at the base addr of the sector 1513 * 3) Determine if we have timed out 1514 * 4) Compare status of address with the value of a fully 1515 * erased quadlet. If these are equal, the sector 1516 * has been erased. 1517 */ 1518 i = 0; 1519 do { 1520 /* wait 1usec */ 1521 drv_usecwait(1); 1522 stat = tavor_flash_read(state, addr); 1523 1524 if (i == tavor_hw_flash_timeout_erase) { 1525 cmn_err(CE_WARN, 1526 "tavor_flash_erase_sector: " 1527 "ACS erase timeout\n"); 1528 status = EIO; 1529 break; 1530 } 1531 1532 i++; 1533 } while (stat != 0xFFFFFFFF); 1534 break; 1535 1536 case TAVOR_FLASH_INTEL_CMDSET: 1537 /* Issue Erase Command */ 1538 tavor_flash_write(state, addr, TAVOR_HW_FLASH_ICS_ERASE); 1539 tavor_flash_write(state, addr, TAVOR_HW_FLASH_ICS_CONFIRM); 1540 1541 /* wait for completion */ 1542 i = 0; 1543 do { 1544 drv_usecwait(1); 1545 stat = tavor_flash_read(state, addr & ~3); 1546 1547 if (i == tavor_hw_flash_timeout_erase) { 1548 cmn_err(CE_WARN, 1549 "tavor_flash_erase_sector: " 1550 "ICS erase timeout\n"); 1551 status = EIO; 1552 break; 1553 } 1554 1555 i++; 1556 } while ((stat & TAVOR_HW_FLASH_ICS_READY) == 0); 1557 1558 if (stat & TAVOR_HW_FLASH_ICS_ERROR) { 1559 cmn_err(CE_WARN, 1560 "tavor_flash_erase_sector: " 1561 "ICS erase cmd error\n"); 1562 status = EIO; 1563 } 1564 break; 1565 1566 default: 1567 cmn_err(CE_WARN, 1568 "tavor_flash_erase_sector: unknown cmd set: 0x%x\n", 1569 state->ts_fw_cmdset); 1570 status = EIO; 1571 break; 1572 } 1573 1574 tavor_flash_reset(state); 1575 1576 return (status); 1577 } 1578 1579 /* 1580 * tavor_flash_erase_chip() 1581 */ 1582 static int 1583 tavor_flash_erase_chip(tavor_state_t *state) 1584 { 1585 uint_t size; 1586 uint32_t stat; 1587 int status = 0; 1588 int num_sect; 1589 int i; 1590 1591 switch (state->ts_fw_cmdset) { 1592 case TAVOR_FLASH_AMD_CMDSET: 1593 /* Issue Flash Chip Erase Command */ 1594 tavor_flash_write(state, 0, 0xAA); 1595 tavor_flash_write(state, 0, 0x55); 1596 tavor_flash_write(state, 0, 0x80); 1597 tavor_flash_write(state, 0, 0xAA); 1598 tavor_flash_write(state, 0, 0x55); 1599 tavor_flash_write(state, 0, 0x10); 1600 1601 /* 1602 * Wait for Chip Erase to Complete 1603 * 1) Wait 1usec 1604 * 2) read the status at the base addr of the sector 1605 * 3) Determine if we have timed out 1606 * 4) Compare status of address with the value of a 1607 * fully erased quadlet. If these are equal, the 1608 * chip has been erased. 1609 */ 1610 i = 0; 1611 do { 1612 /* wait 1usec */ 1613 drv_usecwait(1); 1614 stat = tavor_flash_read(state, 0); 1615 1616 if (i == tavor_hw_flash_timeout_erase) { 1617 cmn_err(CE_WARN, 1618 "tavor_flash_erase_chip: erase timeout\n"); 1619 status = EIO; 1620 break; 1621 } 1622 1623 i++; 1624 } while (stat != 0xFFFFFFFF); 1625 break; 1626 1627 case TAVOR_FLASH_INTEL_CMDSET: 1628 /* 1629 * The Intel chip doesn't have a chip erase command, so erase 1630 * all blocks one at a time. 1631 */ 1632 size = (0x1 << state->ts_fw_log_sector_sz); 1633 num_sect = state->ts_fw_device_sz / size; 1634 1635 for (i = 0; i < num_sect; i++) { 1636 status = tavor_flash_erase_sector(state, i); 1637 if (status != 0) { 1638 cmn_err(CE_WARN, 1639 "tavor_flash_erase_chip: " 1640 "ICS sector %d erase error\n", i); 1641 status = EIO; 1642 break; 1643 } 1644 } 1645 break; 1646 1647 default: 1648 cmn_err(CE_WARN, "tavor_flash_erase_chip: " 1649 "unknown cmd set: 0x%x\n", state->ts_fw_cmdset); 1650 status = EIO; 1651 break; 1652 } 1653 1654 return (status); 1655 } 1656 1657 /* 1658 * tavor_flash_bank() 1659 */ 1660 static void 1661 tavor_flash_bank(tavor_state_t *state, uint32_t addr) 1662 { 1663 ddi_acc_handle_t hdl; 1664 uint32_t bank; 1665 1666 /* Set handle */ 1667 hdl = state->ts_pci_cfghdl; 1668 1669 /* Determine the bank setting from the address */ 1670 bank = addr & TAVOR_HW_FLASH_BANK_MASK; 1671 1672 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(state->ts_fw_flashbank)) 1673 1674 /* 1675 * If the bank is different from the currently set bank, we need to 1676 * change it. Also, if an 'addr' of 0 is given, this allows the 1677 * capability to force the flash bank to 0. This is useful at init 1678 * time to initially set the bank value 1679 */ 1680 if (state->ts_fw_flashbank != bank || addr == 0) { 1681 /* Set bank using the GPIO settings */ 1682 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_DATACLEAR, 0x70); 1683 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_DATASET, 1684 (bank >> 15) & 0x70); 1685 1686 /* Save the bank state */ 1687 state->ts_fw_flashbank = bank; 1688 } 1689 } 1690 1691 /* 1692 * tavor_flash_read() 1693 */ 1694 static uint32_t 1695 tavor_flash_read(tavor_state_t *state, uint32_t addr) 1696 { 1697 ddi_acc_handle_t hdl; 1698 uint32_t data; 1699 int timeout; 1700 1701 /* Set handle */ 1702 hdl = state->ts_pci_cfghdl; 1703 1704 /* 1705 * The Read operation does the following: 1706 * 1) Write the masked address to the TAVOR_FLASH_ADDR register. 1707 * Only the least significant 19 bits are valid. 1708 * 2) Read back the register until the command has completed. 1709 * 3) Read the data retrieved from the address at the TAVOR_FLASH_DATA 1710 * register. 1711 */ 1712 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_ADDR, 1713 (addr & TAVOR_HW_FLASH_ADDR_MASK) | (1 << 29)); 1714 1715 timeout = 0; 1716 do { 1717 data = tavor_flash_read_cfg(hdl, TAVOR_HW_FLASH_ADDR); 1718 timeout++; 1719 } while ((data & TAVOR_HW_FLASH_CMD_MASK) && 1720 (timeout < tavor_hw_flash_timeout_config)); 1721 1722 if (timeout == tavor_hw_flash_timeout_config) { 1723 cmn_err(CE_WARN, "tavor_flash_read: config command timeout.\n"); 1724 } 1725 1726 data = tavor_flash_read_cfg(hdl, TAVOR_HW_FLASH_DATA); 1727 1728 return (data); 1729 } 1730 1731 /* 1732 * tavor_flash_write() 1733 */ 1734 static void 1735 tavor_flash_write(tavor_state_t *state, uint32_t addr, uchar_t data) 1736 { 1737 ddi_acc_handle_t hdl; 1738 int cmd; 1739 int timeout; 1740 1741 /* Set handle */ 1742 hdl = state->ts_pci_cfghdl; 1743 1744 /* 1745 * The Write operation does the following: 1746 * 1) Write the data to be written to the TAVOR_FLASH_DATA offset. 1747 * 2) Write the address to write the data to to the TAVOR_FLASH_ADDR 1748 * offset. 1749 * 3) Wait until the write completes. 1750 */ 1751 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_DATA, data << 24); 1752 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_ADDR, 1753 (addr & 0x7FFFF) | (2 << 29)); 1754 1755 timeout = 0; 1756 do { 1757 cmd = tavor_flash_read_cfg(hdl, TAVOR_HW_FLASH_ADDR); 1758 timeout++; 1759 } while ((cmd & TAVOR_HW_FLASH_CMD_MASK) && 1760 (timeout < tavor_hw_flash_timeout_config)); 1761 1762 if (timeout == tavor_hw_flash_timeout_config) { 1763 cmn_err(CE_WARN, "tavor_flash_write: config cmd timeout.\n"); 1764 } 1765 } 1766 1767 /* 1768 * tavor_flash_init() 1769 */ 1770 static void 1771 tavor_flash_init(tavor_state_t *state) 1772 { 1773 uint32_t word; 1774 ddi_acc_handle_t hdl; 1775 int sema_cnt; 1776 int gpio; 1777 1778 /* Set handle */ 1779 hdl = state->ts_pci_cfghdl; 1780 1781 /* Init the flash */ 1782 1783 /* 1784 * Grab the GPIO semaphore. This allows us exclusive access to the 1785 * GPIO settings on the Tavor for the duration of the flash burning 1786 * procedure. 1787 */ 1788 sema_cnt = 0; 1789 do { 1790 word = tavor_flash_read_cfg(hdl, TAVOR_HW_FLASH_GPIO_SEMA); 1791 if (word == 0) { 1792 break; 1793 } 1794 1795 sema_cnt++; 1796 drv_usecwait(1); 1797 } while (sema_cnt < tavor_hw_flash_timeout_gpio_sema); 1798 1799 /* 1800 * Determine if we timed out trying to grab the GPIO semaphore 1801 */ 1802 if (sema_cnt == tavor_hw_flash_timeout_gpio_sema) { 1803 cmn_err(CE_WARN, "tavor_flash_init: GPIO SEMA timeout\n"); 1804 } 1805 1806 /* Save away original GPIO Values */ 1807 state->ts_fw_gpio[0] = tavor_flash_read_cfg(hdl, 1808 TAVOR_HW_FLASH_GPIO_DIR); 1809 state->ts_fw_gpio[1] = tavor_flash_read_cfg(hdl, 1810 TAVOR_HW_FLASH_GPIO_POL); 1811 state->ts_fw_gpio[2] = tavor_flash_read_cfg(hdl, 1812 TAVOR_HW_FLASH_GPIO_MOD); 1813 state->ts_fw_gpio[3] = tavor_flash_read_cfg(hdl, 1814 TAVOR_HW_FLASH_GPIO_DAT); 1815 1816 /* Set New GPIO Values */ 1817 gpio = state->ts_fw_gpio[0] | 0x70; 1818 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_DIR, gpio); 1819 1820 gpio = state->ts_fw_gpio[1] & ~0x70; 1821 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_POL, gpio); 1822 1823 gpio = state->ts_fw_gpio[2] & ~0x70; 1824 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_MOD, gpio); 1825 1826 /* Set CPUMODE to enable tavor to access the flash device */ 1827 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_CPUMODE, 1828 1 << TAVOR_HW_FLASH_CPU_SHIFT); 1829 1830 /* Initialize to bank 0 */ 1831 tavor_flash_bank(state, 0); 1832 } 1833 1834 /* 1835 * tavor_flash_cfi_init 1836 * Implements access to the CFI (Common Flash Interface) data 1837 */ 1838 static void 1839 tavor_flash_cfi_init(tavor_state_t *state, uint32_t *cfi_info, int *intel_xcmd) 1840 { 1841 uint32_t data; 1842 uint32_t sector_sz_bytes; 1843 uint32_t bit_count; 1844 uint8_t cfi_ch_info[TAVOR_CFI_INFO_SIZE]; 1845 int i; 1846 1847 /* 1848 * Determine if the user command supports the Intel Extended 1849 * Command Set. The query string is contained in the fourth 1850 * quad word. 1851 */ 1852 tavor_flash_cfi_byte(cfi_ch_info, cfi_info[0x04], 0x10); 1853 if (cfi_ch_info[0x10] == 'M' && 1854 cfi_ch_info[0x11] == 'X' && 1855 cfi_ch_info[0x12] == '2') { 1856 *intel_xcmd = 1; /* support is there */ 1857 } 1858 1859 /* CFI QUERY */ 1860 tavor_flash_write(state, 0x55, TAVOR_FLASH_CFI_INIT); 1861 1862 /* Read in CFI data */ 1863 for (i = 0; i < TAVOR_CFI_INFO_SIZE; i += 4) { 1864 data = tavor_flash_read(state, i); 1865 tavor_flash_cfi_byte(cfi_ch_info, data, i); 1866 } 1867 1868 /* Determine chip set */ 1869 state->ts_fw_cmdset = TAVOR_FLASH_UNKNOWN_CMDSET; 1870 if (cfi_ch_info[0x20] == 'Q' && 1871 cfi_ch_info[0x22] == 'R' && 1872 cfi_ch_info[0x24] == 'Y') { 1873 /* 1874 * Mode: x16 working in x8 mode (Intel). 1875 * Pack data - skip spacing bytes. 1876 */ 1877 for (i = 0; i < TAVOR_CFI_INFO_SIZE; i += 2) { 1878 cfi_ch_info[i/2] = cfi_ch_info[i]; 1879 } 1880 } 1881 state->ts_fw_cmdset = cfi_ch_info[0x13]; 1882 if (state->ts_fw_cmdset != TAVOR_FLASH_INTEL_CMDSET && 1883 state->ts_fw_cmdset != TAVOR_FLASH_AMD_CMDSET) { 1884 cmn_err(CE_WARN, 1885 "tavor_flash_cfi_init: UNKNOWN chip cmd set\n"); 1886 state->ts_fw_cmdset = TAVOR_FLASH_UNKNOWN_CMDSET; 1887 return; 1888 } 1889 1890 /* Determine total bytes in one sector size */ 1891 sector_sz_bytes = ((cfi_ch_info[0x30] << 8) | cfi_ch_info[0x2F]) << 8; 1892 1893 /* Calculate equivalent of log2 (n) */ 1894 for (bit_count = 0; sector_sz_bytes > 1; bit_count++) { 1895 sector_sz_bytes >>= 1; 1896 } 1897 1898 /* Set sector size */ 1899 state->ts_fw_log_sector_sz = bit_count; 1900 1901 /* Set flash size */ 1902 state->ts_fw_device_sz = 0x1 << cfi_ch_info[0x27]; 1903 1904 /* Reset to turn off CFI mode */ 1905 tavor_flash_reset(state); 1906 1907 /* 1908 * Pass CFI data back to user command. 1909 */ 1910 for (i = 0; i < TAVOR_FLASH_CFI_SIZE_QUADLET; i++) { 1911 tavor_flash_cfi_dword(&cfi_info[i], cfi_ch_info, i << 2); 1912 } 1913 1914 if (*intel_xcmd == 1) { 1915 /* 1916 * Inform the user cmd that this driver does support the 1917 * Intel Extended Command Set. 1918 */ 1919 cfi_ch_info[0x10] = 'M'; 1920 cfi_ch_info[0x11] = 'X'; 1921 cfi_ch_info[0x12] = '2'; 1922 } else { 1923 cfi_ch_info[0x10] = 'Q'; 1924 cfi_ch_info[0x11] = 'R'; 1925 cfi_ch_info[0x12] = 'Y'; 1926 } 1927 cfi_ch_info[0x13] = state->ts_fw_cmdset; 1928 tavor_flash_cfi_dword(&cfi_info[0x4], cfi_ch_info, 0x10); 1929 } 1930 1931 /* 1932 * tavor_flash_fini() 1933 */ 1934 static void 1935 tavor_flash_fini(tavor_state_t *state) 1936 { 1937 ddi_acc_handle_t hdl; 1938 1939 /* Set handle */ 1940 hdl = state->ts_pci_cfghdl; 1941 1942 /* Restore original GPIO Values */ 1943 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_DIR, 1944 state->ts_fw_gpio[0]); 1945 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_POL, 1946 state->ts_fw_gpio[1]); 1947 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_MOD, 1948 state->ts_fw_gpio[2]); 1949 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_DAT, 1950 state->ts_fw_gpio[3]); 1951 1952 /* Give up semaphore */ 1953 tavor_flash_write_cfg(hdl, TAVOR_HW_FLASH_GPIO_SEMA, 0); 1954 } 1955 1956 /* 1957 * tavor_flash_read_cfg 1958 */ 1959 static uint32_t 1960 tavor_flash_read_cfg(ddi_acc_handle_t pci_config_hdl, uint32_t addr) 1961 { 1962 uint32_t read; 1963 1964 /* 1965 * Perform flash read operation: 1966 * 1) Place addr to read from on the TAVOR_HW_FLASH_CFG_ADDR register 1967 * 2) Read data at that addr from the TAVOR_HW_FLASH_CFG_DATA register 1968 */ 1969 pci_config_put32(pci_config_hdl, TAVOR_HW_FLASH_CFG_ADDR, addr); 1970 read = pci_config_get32(pci_config_hdl, TAVOR_HW_FLASH_CFG_DATA); 1971 1972 return (read); 1973 } 1974 1975 /* 1976 * tavor_flash_write_cfg 1977 */ 1978 static void 1979 tavor_flash_write_cfg(ddi_acc_handle_t pci_config_hdl, uint32_t addr, 1980 uint32_t data) 1981 { 1982 /* 1983 * Perform flash write operation: 1984 * 1) Place addr to write to on the TAVOR_HW_FLASH_CFG_ADDR register 1985 * 2) Place data to write on to the TAVOR_HW_FLASH_CFG_DATA register 1986 */ 1987 pci_config_put32(pci_config_hdl, TAVOR_HW_FLASH_CFG_ADDR, addr); 1988 pci_config_put32(pci_config_hdl, TAVOR_HW_FLASH_CFG_DATA, data); 1989 } 1990 1991 /* 1992 * Support routines to convert Common Flash Interface (CFI) data 1993 * from a 32 bit word to a char array, and from a char array to 1994 * a 32 bit word. 1995 */ 1996 static void 1997 tavor_flash_cfi_byte(uint8_t *ch, uint32_t dword, int i) 1998 { 1999 ch[i] = (uint8_t)((dword & 0xFF000000) >> 24); 2000 ch[i+1] = (uint8_t)((dword & 0x00FF0000) >> 16); 2001 ch[i+2] = (uint8_t)((dword & 0x0000FF00) >> 8); 2002 ch[i+3] = (uint8_t)((dword & 0x000000FF)); 2003 } 2004 2005 static void 2006 tavor_flash_cfi_dword(uint32_t *dword, uint8_t *ch, int i) 2007 { 2008 *dword = (uint32_t) 2009 ((uint32_t)ch[i] << 24 | 2010 (uint32_t)ch[i+1] << 16 | 2011 (uint32_t)ch[i+2] << 8 | 2012 (uint32_t)ch[i+3]); 2013 } 2014 2015 /* 2016 * tavor_loopback_free_qps 2017 */ 2018 static void 2019 tavor_loopback_free_qps(tavor_loopback_state_t *lstate) 2020 { 2021 int i; 2022 2023 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate)) 2024 2025 if (lstate->tls_tx.tlc_qp_hdl != NULL) { 2026 (void) tavor_qp_free(lstate->tls_state, 2027 &lstate->tls_tx.tlc_qp_hdl, IBC_FREE_QP_AND_QPN, NULL, 2028 TAVOR_NOSLEEP); 2029 } 2030 if (lstate->tls_rx.tlc_qp_hdl != NULL) { 2031 (void) tavor_qp_free(lstate->tls_state, 2032 &lstate->tls_rx.tlc_qp_hdl, IBC_FREE_QP_AND_QPN, NULL, 2033 TAVOR_NOSLEEP); 2034 } 2035 lstate->tls_tx.tlc_qp_hdl = NULL; 2036 lstate->tls_rx.tlc_qp_hdl = NULL; 2037 for (i = 0; i < 2; i++) { 2038 if (lstate->tls_tx.tlc_cqhdl[i] != NULL) { 2039 (void) tavor_cq_free(lstate->tls_state, 2040 &lstate->tls_tx.tlc_cqhdl[i], TAVOR_NOSLEEP); 2041 } 2042 if (lstate->tls_rx.tlc_cqhdl[i] != NULL) { 2043 (void) tavor_cq_free(lstate->tls_state, 2044 &lstate->tls_rx.tlc_cqhdl[i], TAVOR_NOSLEEP); 2045 } 2046 lstate->tls_tx.tlc_cqhdl[i] = NULL; 2047 lstate->tls_rx.tlc_cqhdl[i] = NULL; 2048 } 2049 } 2050 2051 /* 2052 * tavor_loopback_free_state 2053 */ 2054 static void 2055 tavor_loopback_free_state(tavor_loopback_state_t *lstate) 2056 { 2057 tavor_loopback_free_qps(lstate); 2058 if (lstate->tls_tx.tlc_mrhdl != NULL) { 2059 (void) tavor_mr_deregister(lstate->tls_state, 2060 &lstate->tls_tx.tlc_mrhdl, TAVOR_MR_DEREG_ALL, 2061 TAVOR_NOSLEEP); 2062 } 2063 if (lstate->tls_rx.tlc_mrhdl != NULL) { 2064 (void) tavor_mr_deregister(lstate->tls_state, 2065 &lstate->tls_rx.tlc_mrhdl, TAVOR_MR_DEREG_ALL, 2066 TAVOR_NOSLEEP); 2067 } 2068 if (lstate->tls_pd_hdl != NULL) { 2069 (void) tavor_pd_free(lstate->tls_state, &lstate->tls_pd_hdl); 2070 } 2071 if (lstate->tls_tx.tlc_buf != NULL) { 2072 kmem_free(lstate->tls_tx.tlc_buf, lstate->tls_tx.tlc_buf_sz); 2073 } 2074 if (lstate->tls_rx.tlc_buf != NULL) { 2075 kmem_free(lstate->tls_rx.tlc_buf, lstate->tls_rx.tlc_buf_sz); 2076 } 2077 bzero(lstate, sizeof (tavor_loopback_state_t)); 2078 } 2079 2080 /* 2081 * tavor_loopback_init 2082 */ 2083 static int 2084 tavor_loopback_init(tavor_state_t *state, tavor_loopback_state_t *lstate) 2085 { 2086 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate)) 2087 2088 lstate->tls_hca_hdl = (ibc_hca_hdl_t)state; 2089 lstate->tls_status = tavor_pd_alloc(lstate->tls_state, 2090 &lstate->tls_pd_hdl, TAVOR_NOSLEEP); 2091 if (lstate->tls_status != IBT_SUCCESS) { 2092 lstate->tls_err = TAVOR_LOOPBACK_PROT_DOMAIN_ALLOC_FAIL; 2093 return (EFAULT); 2094 } 2095 2096 return (0); 2097 } 2098 2099 /* 2100 * tavor_loopback_init_qp_info 2101 */ 2102 static void 2103 tavor_loopback_init_qp_info(tavor_loopback_state_t *lstate, 2104 tavor_loopback_comm_t *comm) 2105 { 2106 bzero(&comm->tlc_cq_attr, sizeof (ibt_cq_attr_t)); 2107 bzero(&comm->tlc_qp_attr, sizeof (ibt_qp_alloc_attr_t)); 2108 bzero(&comm->tlc_qp_info, sizeof (ibt_qp_info_t)); 2109 2110 comm->tlc_wrid = 1; 2111 comm->tlc_cq_attr.cq_size = 128; 2112 comm->tlc_qp_attr.qp_sizes.cs_sq_sgl = 3; 2113 comm->tlc_qp_attr.qp_sizes.cs_rq_sgl = 3; 2114 comm->tlc_qp_attr.qp_sizes.cs_sq = 16; 2115 comm->tlc_qp_attr.qp_sizes.cs_rq = 16; 2116 comm->tlc_qp_attr.qp_flags = IBT_WR_SIGNALED; 2117 2118 comm->tlc_qp_info.qp_state = IBT_STATE_RESET; 2119 comm->tlc_qp_info.qp_trans = IBT_RC_SRV; 2120 comm->tlc_qp_info.qp_flags = IBT_CEP_RDMA_RD | IBT_CEP_RDMA_WR; 2121 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_hca_port_num = 2122 lstate->tls_port; 2123 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_pkey_ix = 2124 lstate->tls_pkey_ix; 2125 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_timeout = 2126 lstate->tls_timeout; 2127 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_srvl = 0; 2128 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_srate = 2129 IBT_SRATE_4X; 2130 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_send_grh = 0; 2131 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dlid = 2132 lstate->tls_lid; 2133 comm->tlc_qp_info.qp_transport.rc.rc_retry_cnt = lstate->tls_retry; 2134 comm->tlc_qp_info.qp_transport.rc.rc_sq_psn = 0; 2135 comm->tlc_qp_info.qp_transport.rc.rc_rq_psn = 0; 2136 comm->tlc_qp_info.qp_transport.rc.rc_rdma_ra_in = 4; 2137 comm->tlc_qp_info.qp_transport.rc.rc_rdma_ra_out = 4; 2138 comm->tlc_qp_info.qp_transport.rc.rc_dst_qpn = 0; 2139 comm->tlc_qp_info.qp_transport.rc.rc_min_rnr_nak = IBT_RNR_NAK_655ms; 2140 comm->tlc_qp_info.qp_transport.rc.rc_path_mtu = IB_MTU_1K; 2141 } 2142 2143 /* 2144 * tavor_loopback_alloc_mem 2145 */ 2146 static int 2147 tavor_loopback_alloc_mem(tavor_loopback_state_t *lstate, 2148 tavor_loopback_comm_t *comm, int sz) 2149 { 2150 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm)) 2151 2152 /* Allocate buffer of specified size */ 2153 comm->tlc_buf_sz = sz; 2154 comm->tlc_buf = kmem_zalloc(sz, KM_NOSLEEP); 2155 if (comm->tlc_buf == NULL) { 2156 return (EFAULT); 2157 } 2158 2159 /* Register the buffer as a memory region */ 2160 comm->tlc_memattr.mr_vaddr = (uint64_t)(uintptr_t)comm->tlc_buf; 2161 comm->tlc_memattr.mr_len = (ib_msglen_t)sz; 2162 comm->tlc_memattr.mr_as = NULL; 2163 comm->tlc_memattr.mr_flags = IBT_MR_NOSLEEP | 2164 IBT_MR_ENABLE_REMOTE_WRITE | IBT_MR_ENABLE_LOCAL_WRITE; 2165 2166 comm->tlc_status = tavor_mr_register(lstate->tls_state, 2167 lstate->tls_pd_hdl, &comm->tlc_memattr, &comm->tlc_mrhdl, NULL); 2168 2169 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm->tlc_mrhdl)) 2170 2171 comm->tlc_mrdesc.md_vaddr = comm->tlc_mrhdl->mr_bindinfo.bi_addr; 2172 comm->tlc_mrdesc.md_lkey = comm->tlc_mrhdl->mr_lkey; 2173 comm->tlc_mrdesc.md_rkey = comm->tlc_mrhdl->mr_rkey; 2174 if (comm->tlc_status != IBT_SUCCESS) { 2175 return (EFAULT); 2176 } 2177 return (0); 2178 } 2179 2180 /* 2181 * tavor_loopback_alloc_qps 2182 */ 2183 static int 2184 tavor_loopback_alloc_qps(tavor_loopback_state_t *lstate, 2185 tavor_loopback_comm_t *comm) 2186 { 2187 uint32_t i, real_size; 2188 tavor_qp_info_t qpinfo; 2189 2190 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm)) 2191 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate)) 2192 2193 /* Allocate send and recv CQs */ 2194 for (i = 0; i < 2; i++) { 2195 bzero(&comm->tlc_cq_attr, sizeof (ibt_cq_attr_t)); 2196 comm->tlc_cq_attr.cq_size = 128; 2197 comm->tlc_status = tavor_cq_alloc(lstate->tls_state, 2198 (ibt_cq_hdl_t)NULL, &comm->tlc_cq_attr, &real_size, 2199 &comm->tlc_cqhdl[i], TAVOR_NOSLEEP); 2200 if (comm->tlc_status != IBT_SUCCESS) { 2201 lstate->tls_err += i; 2202 return (EFAULT); 2203 } 2204 } 2205 2206 /* Allocate the QP */ 2207 tavor_loopback_init_qp_info(lstate, comm); 2208 comm->tlc_qp_attr.qp_pd_hdl = (ibt_pd_hdl_t)lstate->tls_pd_hdl; 2209 comm->tlc_qp_attr.qp_scq_hdl = (ibt_cq_hdl_t)comm->tlc_cqhdl[0]; 2210 comm->tlc_qp_attr.qp_rcq_hdl = (ibt_cq_hdl_t)comm->tlc_cqhdl[1]; 2211 comm->tlc_qp_attr.qp_ibc_scq_hdl = (ibt_opaque1_t)comm->tlc_cqhdl[0]; 2212 comm->tlc_qp_attr.qp_ibc_rcq_hdl = (ibt_opaque1_t)comm->tlc_cqhdl[1]; 2213 qpinfo.qpi_attrp = &comm->tlc_qp_attr; 2214 qpinfo.qpi_type = IBT_RC_RQP; 2215 qpinfo.qpi_ibt_qphdl = NULL; 2216 qpinfo.qpi_queueszp = &comm->tlc_chan_sizes; 2217 qpinfo.qpi_qpn = &comm->tlc_qp_num; 2218 comm->tlc_status = tavor_qp_alloc(lstate->tls_state, &qpinfo, 2219 TAVOR_NOSLEEP, NULL); 2220 if (comm->tlc_status == DDI_SUCCESS) { 2221 comm->tlc_qp_hdl = qpinfo.qpi_qphdl; 2222 } 2223 2224 if (comm->tlc_status != IBT_SUCCESS) { 2225 lstate->tls_err += 2; 2226 return (EFAULT); 2227 } 2228 return (0); 2229 } 2230 2231 /* 2232 * tavor_loopback_modify_qp 2233 */ 2234 static int 2235 tavor_loopback_modify_qp(tavor_loopback_state_t *lstate, 2236 tavor_loopback_comm_t *comm, uint_t qp_num) 2237 { 2238 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm)) 2239 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate)) 2240 2241 /* Modify QP to INIT */ 2242 tavor_loopback_init_qp_info(lstate, comm); 2243 comm->tlc_qp_info.qp_state = IBT_STATE_INIT; 2244 comm->tlc_status = tavor_qp_modify(lstate->tls_state, comm->tlc_qp_hdl, 2245 IBT_CEP_SET_STATE, &comm->tlc_qp_info, &comm->tlc_queue_sizes); 2246 if (comm->tlc_status != IBT_SUCCESS) { 2247 return (EFAULT); 2248 } 2249 2250 /* 2251 * Modify QP to RTR (set destination LID and QP number to local 2252 * LID and QP number) 2253 */ 2254 comm->tlc_qp_info.qp_state = IBT_STATE_RTR; 2255 comm->tlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dlid 2256 = lstate->tls_lid; 2257 comm->tlc_qp_info.qp_transport.rc.rc_dst_qpn = qp_num; 2258 comm->tlc_status = tavor_qp_modify(lstate->tls_state, comm->tlc_qp_hdl, 2259 IBT_CEP_SET_STATE, &comm->tlc_qp_info, &comm->tlc_queue_sizes); 2260 if (comm->tlc_status != IBT_SUCCESS) { 2261 lstate->tls_err += 1; 2262 return (EFAULT); 2263 } 2264 2265 /* Modify QP to RTS */ 2266 comm->tlc_qp_info.qp_current_state = IBT_STATE_RTR; 2267 comm->tlc_qp_info.qp_state = IBT_STATE_RTS; 2268 comm->tlc_status = tavor_qp_modify(lstate->tls_state, comm->tlc_qp_hdl, 2269 IBT_CEP_SET_STATE, &comm->tlc_qp_info, &comm->tlc_queue_sizes); 2270 if (comm->tlc_status != IBT_SUCCESS) { 2271 lstate->tls_err += 2; 2272 return (EFAULT); 2273 } 2274 return (0); 2275 } 2276 2277 /* 2278 * tavor_loopback_copyout 2279 */ 2280 static int 2281 tavor_loopback_copyout(tavor_loopback_ioctl_t *lb, intptr_t arg, int mode) 2282 { 2283 #ifdef _MULTI_DATAMODEL 2284 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { 2285 tavor_loopback_ioctl32_t lb32; 2286 2287 lb32.tlb_revision = lb->tlb_revision; 2288 lb32.tlb_send_buf = 2289 (caddr32_t)(uintptr_t)lb->tlb_send_buf; 2290 lb32.tlb_fail_buf = 2291 (caddr32_t)(uintptr_t)lb->tlb_fail_buf; 2292 lb32.tlb_buf_sz = lb->tlb_buf_sz; 2293 lb32.tlb_num_iter = lb->tlb_num_iter; 2294 lb32.tlb_pass_done = lb->tlb_pass_done; 2295 lb32.tlb_timeout = lb->tlb_timeout; 2296 lb32.tlb_error_type = lb->tlb_error_type; 2297 lb32.tlb_port_num = lb->tlb_port_num; 2298 lb32.tlb_num_retry = lb->tlb_num_retry; 2299 2300 if (ddi_copyout(&lb32, (void *)arg, 2301 sizeof (tavor_loopback_ioctl32_t), mode) != 0) { 2302 return (EFAULT); 2303 } 2304 } else 2305 #endif /* _MULTI_DATAMODEL */ 2306 if (ddi_copyout(lb, (void *)arg, sizeof (tavor_loopback_ioctl_t), 2307 mode) != 0) { 2308 return (EFAULT); 2309 } 2310 return (0); 2311 } 2312 2313 /* 2314 * tavor_loopback_post_send 2315 */ 2316 static int 2317 tavor_loopback_post_send(tavor_loopback_state_t *lstate, 2318 tavor_loopback_comm_t *tx, tavor_loopback_comm_t *rx) 2319 { 2320 int ret; 2321 2322 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tx)) 2323 2324 bzero(&tx->tlc_sgl, sizeof (ibt_wr_ds_t)); 2325 bzero(&tx->tlc_wr, sizeof (ibt_send_wr_t)); 2326 2327 /* Initialize local address for TX buffer */ 2328 tx->tlc_sgl.ds_va = tx->tlc_mrdesc.md_vaddr; 2329 tx->tlc_sgl.ds_key = tx->tlc_mrdesc.md_lkey; 2330 tx->tlc_sgl.ds_len = tx->tlc_buf_sz; 2331 2332 /* Initialize the remaining details of the work request */ 2333 tx->tlc_wr.wr_id = tx->tlc_wrid++; 2334 tx->tlc_wr.wr_flags = IBT_WR_SEND_SIGNAL; 2335 tx->tlc_wr.wr_nds = 1; 2336 tx->tlc_wr.wr_sgl = &tx->tlc_sgl; 2337 tx->tlc_wr.wr_opcode = IBT_WRC_RDMAW; 2338 tx->tlc_wr.wr_trans = IBT_RC_SRV; 2339 2340 /* Initialize the remote address for RX buffer */ 2341 tx->tlc_wr.wr.rc.rcwr.rdma.rdma_raddr = rx->tlc_mrdesc.md_vaddr; 2342 tx->tlc_wr.wr.rc.rcwr.rdma.rdma_rkey = rx->tlc_mrdesc.md_rkey; 2343 tx->tlc_complete = 0; 2344 ret = tavor_post_send(lstate->tls_state, tx->tlc_qp_hdl, &tx->tlc_wr, 2345 1, NULL); 2346 if (ret != IBT_SUCCESS) { 2347 return (EFAULT); 2348 } 2349 return (0); 2350 } 2351 2352 /* 2353 * tavor_loopback_poll_cq 2354 */ 2355 static int 2356 tavor_loopback_poll_cq(tavor_loopback_state_t *lstate, 2357 tavor_loopback_comm_t *comm) 2358 { 2359 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm)) 2360 2361 comm->tlc_wc.wc_status = 0; 2362 comm->tlc_num_polled = 0; 2363 comm->tlc_status = tavor_cq_poll(lstate->tls_state, 2364 comm->tlc_cqhdl[0], &comm->tlc_wc, 1, &comm->tlc_num_polled); 2365 if ((comm->tlc_status == IBT_SUCCESS) && 2366 (comm->tlc_wc.wc_status != IBT_WC_SUCCESS)) { 2367 comm->tlc_status = ibc_get_ci_failure(0); 2368 } 2369 return (comm->tlc_status); 2370 } 2371