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