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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <nxge_impl.h> 29 #include <npi_mac.h> 30 #include <npi_rxdma.h> 31 #include <nxge_hio.h> 32 33 #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 34 static int nxge_herr2kerr(uint64_t); 35 #endif 36 37 static nxge_status_t nxge_init_fzc_rdc_pages(p_nxge_t, 38 uint16_t, dma_log_page_t *, dma_log_page_t *); 39 40 static nxge_status_t nxge_init_fzc_tdc_pages(p_nxge_t, 41 uint16_t, dma_log_page_t *, dma_log_page_t *); 42 43 /* 44 * The following interfaces are controlled by the 45 * function control registers. Some global registers 46 * are to be initialized by only byt one of the 2/4 functions. 47 * Use the test and set register. 48 */ 49 /*ARGSUSED*/ 50 nxge_status_t 51 nxge_test_and_set(p_nxge_t nxgep, uint8_t tas) 52 { 53 npi_handle_t handle; 54 npi_status_t rs = NPI_SUCCESS; 55 56 handle = NXGE_DEV_NPI_HANDLE(nxgep); 57 if ((rs = npi_dev_func_sr_sr_get_set_clear(handle, tas)) 58 != NPI_SUCCESS) { 59 return (NXGE_ERROR | rs); 60 } 61 62 return (NXGE_OK); 63 } 64 65 nxge_status_t 66 nxge_set_fzc_multi_part_ctl(p_nxge_t nxgep, boolean_t mpc) 67 { 68 npi_handle_t handle; 69 npi_status_t rs = NPI_SUCCESS; 70 71 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_set_fzc_multi_part_ctl")); 72 73 /* 74 * In multi-partitioning, the partition manager 75 * who owns function zero should set this multi-partition 76 * control bit. 77 */ 78 if (nxgep->use_partition && nxgep->function_num) { 79 return (NXGE_ERROR); 80 } 81 82 handle = NXGE_DEV_NPI_HANDLE(nxgep); 83 if ((rs = npi_fzc_mpc_set(handle, mpc)) != NPI_SUCCESS) { 84 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 85 "<== nxge_set_fzc_multi_part_ctl")); 86 return (NXGE_ERROR | rs); 87 } 88 89 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_set_fzc_multi_part_ctl")); 90 91 return (NXGE_OK); 92 } 93 94 nxge_status_t 95 nxge_get_fzc_multi_part_ctl(p_nxge_t nxgep, boolean_t *mpc_p) 96 { 97 npi_handle_t handle; 98 npi_status_t rs = NPI_SUCCESS; 99 100 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_get_fzc_multi_part_ctl")); 101 102 handle = NXGE_DEV_NPI_HANDLE(nxgep); 103 if ((rs = npi_fzc_mpc_get(handle, mpc_p)) != NPI_SUCCESS) { 104 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 105 "<== nxge_set_fzc_multi_part_ctl")); 106 return (NXGE_ERROR | rs); 107 } 108 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_get_fzc_multi_part_ctl")); 109 110 return (NXGE_OK); 111 } 112 113 /* 114 * System interrupt registers that are under function zero 115 * management. 116 */ 117 nxge_status_t 118 nxge_fzc_intr_init(p_nxge_t nxgep) 119 { 120 nxge_status_t status = NXGE_OK; 121 122 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_init")); 123 124 /* Configure the initial timer resolution */ 125 if ((status = nxge_fzc_intr_tmres_set(nxgep)) != NXGE_OK) { 126 return (status); 127 } 128 129 if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 130 /* 131 * Set up the logical device group's logical devices that 132 * the group owns. 133 */ 134 if ((status = nxge_fzc_intr_ldg_num_set(nxgep)) != NXGE_OK) 135 goto fzc_intr_init_exit; 136 137 /* Configure the system interrupt data */ 138 if ((status = nxge_fzc_intr_sid_set(nxgep)) != NXGE_OK) 139 goto fzc_intr_init_exit; 140 } 141 142 fzc_intr_init_exit: 143 144 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_init")); 145 146 return (status); 147 } 148 149 nxge_status_t 150 nxge_fzc_intr_ldg_num_set(p_nxge_t nxgep) 151 { 152 p_nxge_ldg_t ldgp; 153 p_nxge_ldv_t ldvp; 154 npi_handle_t handle; 155 int i, j; 156 npi_status_t rs = NPI_SUCCESS; 157 158 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_ldg_num_set")); 159 160 if (nxgep->ldgvp == NULL) { 161 return (NXGE_ERROR); 162 } 163 164 ldgp = nxgep->ldgvp->ldgp; 165 ldvp = nxgep->ldgvp->ldvp; 166 if (ldgp == NULL || ldvp == NULL) { 167 return (NXGE_ERROR); 168 } 169 170 handle = NXGE_DEV_NPI_HANDLE(nxgep); 171 172 for (i = 0; i < nxgep->ldgvp->ldg_intrs; i++, ldgp++) { 173 NXGE_DEBUG_MSG((nxgep, INT_CTL, 174 "==> nxge_fzc_intr_ldg_num_set " 175 "<== nxge_f(Neptune): # ldv %d " 176 "in group %d", ldgp->nldvs, ldgp->ldg)); 177 178 for (j = 0; j < ldgp->nldvs; j++, ldvp++) { 179 rs = npi_fzc_ldg_num_set(handle, ldvp->ldv, 180 ldvp->ldg_assigned); 181 if (rs != NPI_SUCCESS) { 182 NXGE_DEBUG_MSG((nxgep, INT_CTL, 183 "<== nxge_fzc_intr_ldg_num_set failed " 184 " rs 0x%x ldv %d ldg %d", 185 rs, ldvp->ldv, ldvp->ldg_assigned)); 186 return (NXGE_ERROR | rs); 187 } 188 NXGE_DEBUG_MSG((nxgep, INT_CTL, 189 "<== nxge_fzc_intr_ldg_num_set OK " 190 " ldv %d ldg %d", 191 ldvp->ldv, ldvp->ldg_assigned)); 192 } 193 } 194 195 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_ldg_num_set")); 196 197 return (NXGE_OK); 198 } 199 200 nxge_status_t 201 nxge_fzc_intr_tmres_set(p_nxge_t nxgep) 202 { 203 npi_handle_t handle; 204 npi_status_t rs = NPI_SUCCESS; 205 206 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_tmrese_set")); 207 if (nxgep->ldgvp == NULL) { 208 return (NXGE_ERROR); 209 } 210 handle = NXGE_DEV_NPI_HANDLE(nxgep); 211 if ((rs = npi_fzc_ldg_timer_res_set(handle, nxgep->ldgvp->tmres))) { 212 return (NXGE_ERROR | rs); 213 } 214 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_tmrese_set")); 215 216 return (NXGE_OK); 217 } 218 219 nxge_status_t 220 nxge_fzc_intr_sid_set(p_nxge_t nxgep) 221 { 222 npi_handle_t handle; 223 p_nxge_ldg_t ldgp; 224 fzc_sid_t sid; 225 int i; 226 npi_status_t rs = NPI_SUCCESS; 227 228 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_fzc_intr_sid_set")); 229 if (nxgep->ldgvp == NULL) { 230 NXGE_DEBUG_MSG((nxgep, INT_CTL, 231 "<== nxge_fzc_intr_sid_set: no ldg")); 232 return (NXGE_ERROR); 233 } 234 handle = NXGE_DEV_NPI_HANDLE(nxgep); 235 ldgp = nxgep->ldgvp->ldgp; 236 NXGE_DEBUG_MSG((nxgep, INT_CTL, 237 "==> nxge_fzc_intr_sid_set: #int %d", nxgep->ldgvp->ldg_intrs)); 238 for (i = 0; i < nxgep->ldgvp->ldg_intrs; i++, ldgp++) { 239 sid.ldg = ldgp->ldg; 240 sid.niu = B_FALSE; 241 sid.func = ldgp->func; 242 sid.vector = ldgp->vector; 243 NXGE_DEBUG_MSG((nxgep, INT_CTL, 244 "==> nxge_fzc_intr_sid_set(%d): func %d group %d " 245 "vector %d", 246 i, sid.func, sid.ldg, sid.vector)); 247 rs = npi_fzc_sid_set(handle, sid); 248 if (rs != NPI_SUCCESS) { 249 NXGE_DEBUG_MSG((nxgep, INT_CTL, 250 "<== nxge_fzc_intr_sid_set:failed 0x%x", 251 rs)); 252 return (NXGE_ERROR | rs); 253 } 254 } 255 256 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_fzc_intr_sid_set")); 257 258 return (NXGE_OK); 259 260 } 261 262 /* 263 * nxge_init_fzc_rdc 264 * 265 * Initialize all of a RDC's FZC_DMC registers. 266 * This is executed by the service domain, on behalf of a 267 * guest domain, who cannot access these registers. 268 * 269 * Arguments: 270 * nxgep 271 * channel The channel to initialize. 272 * 273 * NPI_NXGE function calls: 274 * nxge_init_fzc_rdc_pages() 275 * 276 * Context: 277 * Service Domain 278 */ 279 /*ARGSUSED*/ 280 nxge_status_t 281 nxge_init_fzc_rdc(p_nxge_t nxgep, uint16_t channel) 282 { 283 nxge_status_t status = NXGE_OK; 284 285 dma_log_page_t page1, page2; 286 npi_handle_t handle; 287 rdc_red_para_t red; 288 289 /* 290 * Initialize the RxDMA channel-specific FZC control 291 * registers. 292 */ 293 294 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_tdc")); 295 296 handle = NXGE_DEV_NPI_HANDLE(nxgep); 297 298 /* Reset RXDMA channel */ 299 status = npi_rxdma_cfg_rdc_reset(handle, channel); 300 if (status != NPI_SUCCESS) { 301 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 302 "==> nxge_init_fzc_rdc: npi_rxdma_cfg_rdc_reset(%d) " 303 "returned 0x%08x", channel, status)); 304 return (NXGE_ERROR | status); 305 } 306 307 /* 308 * These values have been copied from 309 * nxge_txdma.c:nxge_map_txdma_channel_cfg_ring(). 310 */ 311 page1.page_num = 0; 312 page1.valid = 1; 313 page1.func_num = nxgep->function_num; 314 page1.mask = 0; 315 page1.value = 0; 316 page1.reloc = 0; 317 318 page2.page_num = 1; 319 page2.valid = 1; 320 page2.func_num = nxgep->function_num; 321 page2.mask = 0; 322 page2.value = 0; 323 page2.reloc = 0; 324 325 if (nxgep->niu_type == N2_NIU) { 326 #if !defined(NIU_HV_WORKAROUND) 327 status = NXGE_OK; 328 #else 329 NXGE_DEBUG_MSG((nxgep, RX_CTL, 330 "==> nxge_init_fzc_rxdma_channel: N2_NIU - NEED to " 331 "set up logical pages")); 332 /* Initialize the RXDMA logical pages */ 333 status = nxge_init_fzc_rdc_pages(nxgep, channel, 334 &page1, &page2); 335 if (status != NXGE_OK) { 336 return (status); 337 } 338 #endif 339 } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 340 /* Initialize the RXDMA logical pages */ 341 status = nxge_init_fzc_rdc_pages(nxgep, channel, 342 &page1, &page2); 343 if (status != NXGE_OK) { 344 return (status); 345 } 346 } else { 347 return (NXGE_ERROR); 348 } 349 350 /* 351 * Configure RED parameters 352 */ 353 red.value = 0; 354 red.bits.ldw.win = RXDMA_RED_WINDOW_DEFAULT; 355 red.bits.ldw.thre = 356 (nxgep->nxge_port_rcr_size - RXDMA_RED_LESS_ENTRIES); 357 red.bits.ldw.win_syn = RXDMA_RED_WINDOW_DEFAULT; 358 red.bits.ldw.thre_sync = 359 (nxgep->nxge_port_rcr_size - RXDMA_RED_LESS_ENTRIES); 360 361 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 362 "==> nxge_init_fzc_rxdma_channel_red(thre_sync %d(%x))", 363 red.bits.ldw.thre_sync, 364 red.bits.ldw.thre_sync)); 365 366 status |= npi_rxdma_cfg_wred_param(handle, channel, &red); 367 368 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_init_fzc_rdc")); 369 370 return (status); 371 } 372 373 /* 374 * nxge_init_fzc_rxdma_channel 375 * 376 * Initialize all per-channel FZC_DMC registers. 377 * 378 * Arguments: 379 * nxgep 380 * channel The channel to start 381 * 382 * NPI_NXGE function calls: 383 * nxge_init_hv_fzc_rxdma_channel_pages() 384 * nxge_init_fzc_rxdma_channel_pages() 385 * nxge_init_fzc_rxdma_channel_red() 386 * 387 * Context: 388 * Service Domain 389 */ 390 /*ARGSUSED*/ 391 nxge_status_t 392 nxge_init_fzc_rxdma_channel(p_nxge_t nxgep, uint16_t channel) 393 { 394 rx_rbr_ring_t *rbr_ring; 395 rx_rcr_ring_t *rcr_ring; 396 397 nxge_status_t status = NXGE_OK; 398 399 NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_init_fzc_rxdma_channel")); 400 401 rbr_ring = nxgep->rx_rbr_rings->rbr_rings[channel]; 402 rcr_ring = nxgep->rx_rcr_rings->rcr_rings[channel]; 403 404 if (nxgep->niu_type == N2_NIU) { 405 #ifndef NIU_HV_WORKAROUND 406 #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 407 NXGE_DEBUG_MSG((nxgep, RX_CTL, 408 "==> nxge_init_fzc_rxdma_channel: N2_NIU - call HV " 409 "set up logical pages")); 410 /* Initialize the RXDMA logical pages */ 411 status = nxge_init_hv_fzc_rxdma_channel_pages(nxgep, channel, 412 rbr_ring); 413 if (status != NXGE_OK) { 414 return (status); 415 } 416 #endif 417 status = NXGE_OK; 418 #else 419 NXGE_DEBUG_MSG((nxgep, RX_CTL, 420 "==> nxge_init_fzc_rxdma_channel: N2_NIU - NEED to " 421 "set up logical pages")); 422 /* Initialize the RXDMA logical pages */ 423 status = nxge_init_fzc_rxdma_channel_pages(nxgep, channel, 424 rbr_ring); 425 if (status != NXGE_OK) { 426 return (status); 427 } 428 #endif 429 } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 430 /* Initialize the RXDMA logical pages */ 431 status = nxge_init_fzc_rxdma_channel_pages(nxgep, 432 channel, rbr_ring); 433 if (status != NXGE_OK) { 434 return (status); 435 } 436 } else { 437 return (NXGE_ERROR); 438 } 439 440 /* Configure RED parameters */ 441 status = nxge_init_fzc_rxdma_channel_red(nxgep, channel, rcr_ring); 442 443 NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_init_fzc_rxdma_channel")); 444 return (status); 445 } 446 447 /* 448 * nxge_init_fzc_rdc_pages 449 * 450 * Configure a TDC's logical pages. 451 * 452 * This function is executed by the service domain, on behalf of 453 * a guest domain, to whom this RDC has been loaned. 454 * 455 * Arguments: 456 * nxgep 457 * channel The channel to initialize. 458 * page0 Logical page 0 definition. 459 * page1 Logical page 1 definition. 460 * 461 * Notes: 462 * I think that this function can be called from any 463 * domain, but I need to check. 464 * 465 * NPI/NXGE function calls: 466 * hv_niu_tx_logical_page_conf() 467 * hv_niu_tx_logical_page_info() 468 * 469 * Context: 470 * Any domain 471 */ 472 nxge_status_t 473 nxge_init_fzc_rdc_pages( 474 p_nxge_t nxgep, 475 uint16_t channel, 476 dma_log_page_t *page0, 477 dma_log_page_t *page1) 478 { 479 npi_handle_t handle; 480 npi_status_t rs; 481 482 uint64_t page_handle; 483 484 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 485 "==> nxge_init_fzc_txdma_channel_pages")); 486 487 #ifndef NIU_HV_WORKAROUND 488 if (nxgep->niu_type == N2_NIU) { 489 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 490 "<== nxge_init_fzc_rdc_pages: " 491 "N2_NIU: no need to set rxdma logical pages")); 492 return (NXGE_OK); 493 } 494 #else 495 if (nxgep->niu_type == N2_NIU) { 496 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 497 "<== nxge_init_fzc_rdc_pages: " 498 "N2_NIU: NEED to set rxdma logical pages")); 499 } 500 #endif 501 502 /* 503 * Initialize logical page 1. 504 */ 505 handle = NXGE_DEV_NPI_HANDLE(nxgep); 506 if ((rs = npi_rxdma_cfg_logical_page(handle, channel, page0)) 507 != NPI_SUCCESS) 508 return (NXGE_ERROR | rs); 509 510 /* 511 * Initialize logical page 2. 512 */ 513 if ((rs = npi_rxdma_cfg_logical_page(handle, channel, page1)) 514 != NPI_SUCCESS) 515 return (NXGE_ERROR | rs); 516 517 /* 518 * Initialize the page handle. 519 * (In the current driver, this is always set to 0.) 520 */ 521 page_handle = 0; 522 rs = npi_rxdma_cfg_logical_page_handle(handle, channel, page_handle); 523 if (rs == NPI_SUCCESS) { 524 return (NXGE_OK); 525 } else { 526 return (NXGE_ERROR | rs); 527 } 528 } 529 530 /*ARGSUSED*/ 531 nxge_status_t 532 nxge_init_fzc_rxdma_channel_pages(p_nxge_t nxgep, 533 uint16_t channel, p_rx_rbr_ring_t rbrp) 534 { 535 npi_handle_t handle; 536 dma_log_page_t cfg; 537 npi_status_t rs = NPI_SUCCESS; 538 539 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 540 "==> nxge_init_fzc_rxdma_channel_pages")); 541 542 handle = NXGE_DEV_NPI_HANDLE(nxgep); 543 /* 544 * Initialize logical page 1. 545 */ 546 cfg.func_num = nxgep->function_num; 547 cfg.page_num = 0; 548 cfg.valid = rbrp->page_valid.bits.ldw.page0; 549 cfg.value = rbrp->page_value_1.value; 550 cfg.mask = rbrp->page_mask_1.value; 551 cfg.reloc = rbrp->page_reloc_1.value; 552 rs = npi_rxdma_cfg_logical_page(handle, channel, 553 (p_dma_log_page_t)&cfg); 554 if (rs != NPI_SUCCESS) { 555 return (NXGE_ERROR | rs); 556 } 557 558 /* 559 * Initialize logical page 2. 560 */ 561 cfg.page_num = 1; 562 cfg.valid = rbrp->page_valid.bits.ldw.page1; 563 cfg.value = rbrp->page_value_2.value; 564 cfg.mask = rbrp->page_mask_2.value; 565 cfg.reloc = rbrp->page_reloc_2.value; 566 567 rs = npi_rxdma_cfg_logical_page(handle, channel, &cfg); 568 if (rs != NPI_SUCCESS) { 569 return (NXGE_ERROR | rs); 570 } 571 572 /* Initialize the page handle */ 573 rs = npi_rxdma_cfg_logical_page_handle(handle, channel, 574 rbrp->page_hdl.bits.ldw.handle); 575 576 if (rs != NPI_SUCCESS) { 577 return (NXGE_ERROR | rs); 578 } 579 580 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 581 "<== nxge_init_fzc_rxdma_channel_pages")); 582 583 return (NXGE_OK); 584 } 585 586 /*ARGSUSED*/ 587 nxge_status_t 588 nxge_init_fzc_rxdma_channel_red(p_nxge_t nxgep, 589 uint16_t channel, p_rx_rcr_ring_t rcr_p) 590 { 591 npi_handle_t handle; 592 rdc_red_para_t red; 593 npi_status_t rs = NPI_SUCCESS; 594 595 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_rxdma_channel_red")); 596 597 handle = NXGE_DEV_NPI_HANDLE(nxgep); 598 red.value = 0; 599 red.bits.ldw.win = RXDMA_RED_WINDOW_DEFAULT; 600 red.bits.ldw.thre = (rcr_p->comp_size - RXDMA_RED_LESS_ENTRIES); 601 red.bits.ldw.win_syn = RXDMA_RED_WINDOW_DEFAULT; 602 red.bits.ldw.thre_sync = (rcr_p->comp_size - RXDMA_RED_LESS_ENTRIES); 603 604 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 605 "==> nxge_init_fzc_rxdma_channel_red(thre_sync %d(%x))", 606 red.bits.ldw.thre_sync, 607 red.bits.ldw.thre_sync)); 608 609 rs = npi_rxdma_cfg_wred_param(handle, channel, &red); 610 if (rs != NPI_SUCCESS) { 611 return (NXGE_ERROR | rs); 612 } 613 614 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 615 "<== nxge_init_fzc_rxdma_channel_red")); 616 617 return (NXGE_OK); 618 } 619 620 /* 621 * nxge_init_fzc_tdc 622 * 623 * Initialize all of a TDC's FZC_DMC registers. 624 * This is executed by the service domain, on behalf of a 625 * guest domain, who cannot access these registers. 626 * 627 * Arguments: 628 * nxgep 629 * channel The channel to initialize. 630 * 631 * NPI_NXGE function calls: 632 * nxge_init_fzc_tdc_pages() 633 * npi_txc_dma_max_burst_set() 634 * 635 * Registers accessed: 636 * TXC_DMA_MAX_BURST 637 * 638 * Context: 639 * Service Domain 640 */ 641 /*ARGSUSED*/ 642 nxge_status_t 643 nxge_init_fzc_tdc(p_nxge_t nxgep, uint16_t channel) 644 { 645 nxge_status_t status = NXGE_OK; 646 647 dma_log_page_t page1, page2; 648 npi_handle_t handle; 649 650 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_tdc")); 651 652 /* 653 * These values have been copied from 654 * nxge_txdma.c:nxge_map_txdma_channel_cfg_ring(). 655 */ 656 page1.page_num = 0; 657 page1.valid = 1; 658 page1.func_num = nxgep->function_num; 659 page1.mask = 0; 660 page1.value = 0; 661 page1.reloc = 0; 662 663 page1.page_num = 1; 664 page1.valid = 1; 665 page1.func_num = nxgep->function_num; 666 page1.mask = 0; 667 page1.value = 0; 668 page1.reloc = 0; 669 670 #ifdef NIU_HV_WORKAROUND 671 if (nxgep->niu_type == N2_NIU) { 672 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 673 "==> nxge_init_fzc_txdma_channel " 674 "N2_NIU: NEED to set up txdma logical pages")); 675 /* Initialize the TXDMA logical pages */ 676 (void) nxge_init_fzc_tdc_pages(nxgep, channel, 677 &page1, &page2); 678 } 679 #endif 680 if (nxgep->niu_type != N2_NIU) { 681 if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 682 /* Initialize the TXDMA logical pages */ 683 (void) nxge_init_fzc_tdc_pages(nxgep, channel, 684 &page1, &page2); 685 } else 686 return (NXGE_ERROR); 687 } 688 689 /* 690 * Configure the TXC DMA Max Burst value. 691 * 692 * PRM.13.5 693 * 694 * TXC DMA Max Burst. TXC_DMA_MAX (FZC_TXC + 0000016) 695 * 19:0 dma_max_burst RW 696 * Max burst value associated with DMA. Used by DRR engine 697 * for computing when DMA has gone into deficit. 698 */ 699 handle = NXGE_DEV_NPI_HANDLE(nxgep); 700 (void) npi_txc_dma_max_burst_set( 701 handle, channel, TXC_DMA_MAX_BURST_DEFAULT); 702 703 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_init_fzc_tdc")); 704 705 return (status); 706 } 707 708 /*ARGSUSED*/ 709 nxge_status_t 710 nxge_init_fzc_txdma_channel(p_nxge_t nxgep, uint16_t channel, 711 p_tx_ring_t tx_ring_p, p_tx_mbox_t mbox_p) 712 { 713 nxge_status_t status = NXGE_OK; 714 715 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 716 "==> nxge_init_fzc_txdma_channel")); 717 718 if (nxgep->niu_type == N2_NIU) { 719 #ifndef NIU_HV_WORKAROUND 720 #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 721 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 722 "==> nxge_init_fzc_txdma_channel " 723 "N2_NIU: call HV to set up txdma logical pages")); 724 status = nxge_init_hv_fzc_txdma_channel_pages(nxgep, channel, 725 tx_ring_p); 726 if (status != NXGE_OK) { 727 return (status); 728 } 729 #endif 730 status = NXGE_OK; 731 #else 732 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 733 "==> nxge_init_fzc_txdma_channel " 734 "N2_NIU: NEED to set up txdma logical pages")); 735 /* Initialize the TXDMA logical pages */ 736 (void) nxge_init_fzc_txdma_channel_pages(nxgep, channel, 737 tx_ring_p); 738 #endif 739 } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 740 /* Initialize the TXDMA logical pages */ 741 (void) nxge_init_fzc_txdma_channel_pages(nxgep, 742 channel, tx_ring_p); 743 } else { 744 return (NXGE_ERROR); 745 } 746 747 /* 748 * Configure Transmit DRR Weight parameters 749 * (It actually programs the TXC max burst register). 750 */ 751 (void) nxge_init_fzc_txdma_channel_drr(nxgep, channel, tx_ring_p); 752 753 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 754 "<== nxge_init_fzc_txdma_channel")); 755 return (status); 756 } 757 758 nxge_status_t 759 nxge_init_fzc_common(p_nxge_t nxgep) 760 { 761 nxge_status_t status = NXGE_OK; 762 763 (void) nxge_init_fzc_rx_common(nxgep); 764 765 return (status); 766 } 767 768 nxge_status_t 769 nxge_init_fzc_rx_common(p_nxge_t nxgep) 770 { 771 npi_handle_t handle; 772 npi_status_t rs = NPI_SUCCESS; 773 nxge_status_t status = NXGE_OK; 774 clock_t lbolt; 775 int table; 776 777 nxge_hw_pt_cfg_t *hardware; 778 779 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_rx_common")); 780 handle = NXGE_DEV_NPI_HANDLE(nxgep); 781 if (!handle.regp) { 782 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 783 "==> nxge_init_fzc_rx_common null ptr")); 784 return (NXGE_ERROR); 785 } 786 787 /* 788 * Configure the rxdma clock divider 789 * This is the granularity counter based on 790 * the hardware system clock (i.e. 300 Mhz) and 791 * it is running around 3 nanoseconds. 792 * So, set the clock divider counter to 1000 to get 793 * microsecond granularity. 794 * For example, for a 3 microsecond timeout, the timeout 795 * will be set to 1. 796 */ 797 rs = npi_rxdma_cfg_clock_div_set(handle, RXDMA_CK_DIV_DEFAULT); 798 if (rs != NPI_SUCCESS) 799 return (NXGE_ERROR | rs); 800 801 #if defined(__i386) 802 rs = npi_rxdma_cfg_32bitmode_enable(handle); 803 if (rs != NPI_SUCCESS) 804 return (NXGE_ERROR | rs); 805 rs = npi_txdma_mode32_set(handle, B_TRUE); 806 if (rs != NPI_SUCCESS) 807 return (NXGE_ERROR | rs); 808 #endif 809 810 /* 811 * Enable WRED and program an initial value. 812 * Use time to set the initial random number. 813 */ 814 (void) drv_getparm(LBOLT, &lbolt); 815 rs = npi_rxdma_cfg_red_rand_init(handle, (uint16_t)lbolt); 816 if (rs != NPI_SUCCESS) 817 return (NXGE_ERROR | rs); 818 819 hardware = &nxgep->pt_config.hw_config; 820 for (table = 0; table < NXGE_MAX_RDC_GRPS; table++) { 821 /* Does this table belong to <nxgep>? */ 822 if (hardware->grpids[table] == (nxgep->function_num + 256)) 823 status = nxge_init_fzc_rdc_tbl(nxgep, table); 824 } 825 826 /* Ethernet Timeout Counter (?) */ 827 828 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 829 "<== nxge_init_fzc_rx_common:status 0x%08x", status)); 830 831 return (status); 832 } 833 834 nxge_status_t 835 nxge_init_fzc_rdc_tbl(p_nxge_t nxge, int rdc_tbl) 836 { 837 nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio; 838 nx_rdc_tbl_t *table; 839 nxge_rdc_grp_t *group; 840 npi_handle_t handle; 841 842 npi_status_t rs = NPI_SUCCESS; 843 nxge_status_t status = NXGE_OK; 844 845 NXGE_DEBUG_MSG((nxge, DMA_CTL, "==> nxge_init_fzc_rdc_tbl(%d)", table)); 846 847 group = &nxge->pt_config.rdc_grps[rdc_tbl]; 848 849 /* This RDC table must have been previously bound to <nxge>. */ 850 MUTEX_ENTER(&nhd->lock); 851 table = &nhd->rdc_tbl[rdc_tbl]; 852 if (table->nxge != (uintptr_t)nxge) { 853 MUTEX_EXIT(&nhd->lock); 854 NXGE_ERROR_MSG((nxge, DMA_CTL, 855 "nxge_init_fzc_rdc_tbl(%d): not owner", table)); 856 return (NXGE_ERROR); 857 } else { 858 table->map = group->map; 859 } 860 MUTEX_EXIT(&nhd->lock); 861 862 handle = NXGE_DEV_NPI_HANDLE(nxge); 863 864 rs = npi_rxdma_rdc_table_config(handle, rdc_tbl, 865 group->map, group->max_rdcs); 866 867 if (rs != NPI_SUCCESS) { 868 status = NXGE_ERROR | rs; 869 } 870 871 NXGE_DEBUG_MSG((nxge, DMA_CTL, "<== nxge_init_fzc_rdc_tbl(%d)", table)); 872 return (status); 873 } 874 875 static 876 int 877 rdc_tbl_bind(p_nxge_t nxge, int rdc_tbl) 878 { 879 nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio; 880 nx_rdc_tbl_t *table; 881 int i; 882 883 NXGE_DEBUG_MSG((nxge, DMA_CTL, "==> nxge_fzc_rdc_tbl_bind")); 884 885 MUTEX_ENTER(&nhd->lock); 886 /* is the caller asking for a particular table? */ 887 if (rdc_tbl >= 0 && rdc_tbl < NXGE_MAX_RDC_GROUPS) { 888 table = &nhd->rdc_tbl[rdc_tbl]; 889 if (table->nxge == 0) { 890 table->nxge = (uintptr_t)nxge; /* It is now bound. */ 891 NXGE_DEBUG_MSG((nxge, DMA_CTL, 892 "<== nxge_fzc_rdc_tbl_bind(%d)", rdc_tbl)); 893 MUTEX_EXIT(&nhd->lock); 894 return (rdc_tbl); 895 } 896 } else { /* The caller will take any old RDC table. */ 897 for (i = 0; i < NXGE_MAX_RDC_GROUPS; i++) { 898 nx_rdc_tbl_t *table = &nhd->rdc_tbl[i]; 899 if (table->nxge == 0) { 900 table->nxge = (uintptr_t)nxge; 901 /* It is now bound. */ 902 MUTEX_EXIT(&nhd->lock); 903 NXGE_DEBUG_MSG((nxge, DMA_CTL, 904 "<== nxge_fzc_rdc_tbl_bind: %d", i)); 905 return (i); 906 } 907 } 908 } 909 MUTEX_EXIT(&nhd->lock); 910 911 NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_fzc_rdc_tbl_bind")); 912 913 return (-EBUSY); /* RDC tables are bound. */ 914 } 915 916 int 917 nxge_fzc_rdc_tbl_bind( 918 nxge_t *nxge, 919 int grp_index, 920 int acceptNoSubstitutes) 921 { 922 nxge_hw_pt_cfg_t *hardware; 923 int index; 924 925 hardware = &nxge->pt_config.hw_config; 926 927 if ((index = rdc_tbl_bind(nxge, grp_index)) < 0) { 928 if (acceptNoSubstitutes) 929 return (index); 930 index = rdc_tbl_bind(nxge, grp_index); 931 if (index < 0) { 932 NXGE_ERROR_MSG((nxge, OBP_CTL, 933 "nxge_fzc_rdc_tbl_init: " 934 "there are no free RDC tables!")); 935 return (index); 936 } 937 } 938 939 hardware->grpids[index] = nxge->function_num + 256; 940 941 return (index); 942 } 943 944 int 945 nxge_fzc_rdc_tbl_unbind(p_nxge_t nxge, int rdc_tbl) 946 { 947 nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio; 948 nx_rdc_tbl_t *table; 949 950 NXGE_DEBUG_MSG((nxge, DMA_CTL, "==> nxge_fzc_rdc_tbl_unbind(%d)", 951 rdc_tbl)); 952 953 table = &nhd->rdc_tbl[rdc_tbl]; 954 if (table->nxge != (uintptr_t)nxge) { 955 NXGE_ERROR_MSG((nxge, DMA_CTL, 956 "nxge_fzc_rdc_tbl_unbind(%d): func%d not owner", 957 nxge->function_num, rdc_tbl)); 958 return (EINVAL); 959 } else { 960 bzero(table, sizeof (*table)); 961 } 962 963 NXGE_DEBUG_MSG((nxge, DMA_CTL, "<== nxge_fzc_rdc_tbl_unbind(%d)", 964 rdc_tbl)); 965 966 return (0); 967 } 968 969 nxge_status_t 970 nxge_init_fzc_rxdma_port(p_nxge_t nxgep) 971 { 972 npi_handle_t handle; 973 p_nxge_dma_pt_cfg_t p_all_cfgp; 974 p_nxge_hw_pt_cfg_t p_cfgp; 975 hostinfo_t hostinfo; 976 int i; 977 npi_status_t rs = NPI_SUCCESS; 978 p_nxge_class_pt_cfg_t p_class_cfgp; 979 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "==> nxge_init_fzc_rxdma_port")); 980 981 p_all_cfgp = (p_nxge_dma_pt_cfg_t)&nxgep->pt_config; 982 p_cfgp = (p_nxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 983 handle = NXGE_DEV_NPI_HANDLE(nxgep); 984 /* 985 * Initialize the port scheduler DRR weight. 986 * npi_rxdma_cfg_port_ddr_weight(); 987 */ 988 989 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 990 (nxgep->mac.portmode == PORT_1G_FIBER) || 991 (nxgep->mac.portmode == PORT_1G_TN1010) || 992 (nxgep->mac.portmode == PORT_1G_SERDES)) { 993 rs = npi_rxdma_cfg_port_ddr_weight(handle, 994 nxgep->function_num, NXGE_RX_DRR_WT_1G); 995 if (rs != NPI_SUCCESS) { 996 return (NXGE_ERROR | rs); 997 } 998 } 999 1000 /* Program the default RDC of a port */ 1001 rs = npi_rxdma_cfg_default_port_rdc(handle, nxgep->function_num, 1002 p_cfgp->def_rdc); 1003 if (rs != NPI_SUCCESS) { 1004 return (NXGE_ERROR | rs); 1005 } 1006 1007 /* 1008 * Configure the MAC host info table with RDC tables 1009 */ 1010 hostinfo.value = 0; 1011 p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config; 1012 for (i = 0; i < p_cfgp->max_macs; i++) { 1013 hostinfo.bits.w0.rdc_tbl_num = p_cfgp->def_mac_rxdma_grpid; 1014 hostinfo.bits.w0.mac_pref = p_cfgp->mac_pref; 1015 if (p_class_cfgp->mac_host_info[i].flag) { 1016 hostinfo.bits.w0.rdc_tbl_num = 1017 p_class_cfgp->mac_host_info[i].rdctbl; 1018 hostinfo.bits.w0.mac_pref = 1019 p_class_cfgp->mac_host_info[i].mpr_npr; 1020 } 1021 1022 rs = npi_mac_hostinfo_entry(handle, OP_SET, 1023 nxgep->function_num, i, &hostinfo); 1024 if (rs != NPI_SUCCESS) 1025 return (NXGE_ERROR | rs); 1026 } 1027 1028 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1029 "<== nxge_init_fzc_rxdma_port rs 0x%08x", rs)); 1030 1031 return (NXGE_OK); 1032 1033 } 1034 1035 nxge_status_t 1036 nxge_fzc_dmc_def_port_rdc(p_nxge_t nxgep, uint8_t port, uint16_t rdc) 1037 { 1038 npi_status_t rs = NPI_SUCCESS; 1039 rs = npi_rxdma_cfg_default_port_rdc(nxgep->npi_reg_handle, 1040 port, rdc); 1041 if (rs & NPI_FAILURE) 1042 return (NXGE_ERROR | rs); 1043 return (NXGE_OK); 1044 } 1045 1046 /* 1047 * nxge_init_fzc_tdc_pages 1048 * 1049 * Configure a TDC's logical pages. 1050 * 1051 * This function is executed by the service domain, on behalf of 1052 * a guest domain, to whom this TDC has been loaned. 1053 * 1054 * Arguments: 1055 * nxgep 1056 * channel The channel to initialize. 1057 * page0 Logical page 0 definition. 1058 * page1 Logical page 1 definition. 1059 * 1060 * Notes: 1061 * I think that this function can be called from any 1062 * domain, but I need to check. 1063 * 1064 * NPI/NXGE function calls: 1065 * hv_niu_tx_logical_page_conf() 1066 * hv_niu_tx_logical_page_info() 1067 * 1068 * Context: 1069 * Any domain 1070 */ 1071 nxge_status_t 1072 nxge_init_fzc_tdc_pages( 1073 p_nxge_t nxgep, 1074 uint16_t channel, 1075 dma_log_page_t *page0, 1076 dma_log_page_t *page1) 1077 { 1078 npi_handle_t handle; 1079 npi_status_t rs; 1080 1081 log_page_hdl_t page_handle; 1082 1083 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1084 "==> nxge_init_fzc_txdma_channel_pages")); 1085 1086 #ifndef NIU_HV_WORKAROUND 1087 if (nxgep->niu_type == N2_NIU) { 1088 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1089 "<== nxge_init_fzc_tdc_pages: " 1090 "N2_NIU: no need to set txdma logical pages")); 1091 return (NXGE_OK); 1092 } 1093 #else 1094 if (nxgep->niu_type == N2_NIU) { 1095 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1096 "<== nxge_init_fzc_tdc_pages: " 1097 "N2_NIU: NEED to set txdma logical pages")); 1098 } 1099 #endif 1100 1101 /* 1102 * Initialize logical page 1. 1103 */ 1104 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1105 if ((rs = npi_txdma_log_page_set(handle, channel, page0)) 1106 != NPI_SUCCESS) 1107 return (NXGE_ERROR | rs); 1108 1109 /* 1110 * Initialize logical page 2. 1111 */ 1112 if ((rs = npi_txdma_log_page_set(handle, channel, page1)) 1113 != NPI_SUCCESS) 1114 return (NXGE_ERROR | rs); 1115 1116 /* 1117 * Initialize the page handle. 1118 * (In the current driver, this is always set to 0.) 1119 */ 1120 page_handle.value = 0; 1121 rs = npi_txdma_log_page_handle_set(handle, channel, &page_handle); 1122 if (rs == NPI_SUCCESS) { 1123 return (NXGE_OK); 1124 } else { 1125 return (NXGE_ERROR | rs); 1126 } 1127 } 1128 1129 nxge_status_t 1130 nxge_init_fzc_txdma_channel_pages(p_nxge_t nxgep, uint16_t channel, 1131 p_tx_ring_t tx_ring_p) 1132 { 1133 npi_handle_t handle; 1134 dma_log_page_t cfg; 1135 npi_status_t rs = NPI_SUCCESS; 1136 1137 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1138 "==> nxge_init_fzc_txdma_channel_pages")); 1139 1140 #ifndef NIU_HV_WORKAROUND 1141 if (nxgep->niu_type == N2_NIU) { 1142 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1143 "<== nxge_init_fzc_txdma_channel_pages: " 1144 "N2_NIU: no need to set txdma logical pages")); 1145 return (NXGE_OK); 1146 } 1147 #else 1148 if (nxgep->niu_type == N2_NIU) { 1149 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1150 "<== nxge_init_fzc_txdma_channel_pages: " 1151 "N2_NIU: NEED to set txdma logical pages")); 1152 } 1153 #endif 1154 1155 /* 1156 * Initialize logical page 1. 1157 */ 1158 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1159 cfg.func_num = nxgep->function_num; 1160 cfg.page_num = 0; 1161 cfg.valid = tx_ring_p->page_valid.bits.ldw.page0; 1162 cfg.value = tx_ring_p->page_value_1.value; 1163 cfg.mask = tx_ring_p->page_mask_1.value; 1164 cfg.reloc = tx_ring_p->page_reloc_1.value; 1165 1166 rs = npi_txdma_log_page_set(handle, channel, 1167 (p_dma_log_page_t)&cfg); 1168 if (rs != NPI_SUCCESS) { 1169 return (NXGE_ERROR | rs); 1170 } 1171 1172 /* 1173 * Initialize logical page 2. 1174 */ 1175 cfg.page_num = 1; 1176 cfg.valid = tx_ring_p->page_valid.bits.ldw.page1; 1177 cfg.value = tx_ring_p->page_value_2.value; 1178 cfg.mask = tx_ring_p->page_mask_2.value; 1179 cfg.reloc = tx_ring_p->page_reloc_2.value; 1180 1181 rs = npi_txdma_log_page_set(handle, channel, &cfg); 1182 if (rs != NPI_SUCCESS) { 1183 return (NXGE_ERROR | rs); 1184 } 1185 1186 /* Initialize the page handle */ 1187 rs = npi_txdma_log_page_handle_set(handle, channel, 1188 &tx_ring_p->page_hdl); 1189 1190 if (rs == NPI_SUCCESS) { 1191 return (NXGE_OK); 1192 } else { 1193 return (NXGE_ERROR | rs); 1194 } 1195 } 1196 1197 1198 nxge_status_t 1199 nxge_init_fzc_txdma_channel_drr(p_nxge_t nxgep, uint16_t channel, 1200 p_tx_ring_t tx_ring_p) 1201 { 1202 npi_status_t rs = NPI_SUCCESS; 1203 npi_handle_t handle; 1204 1205 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1206 rs = npi_txc_dma_max_burst_set(handle, channel, 1207 tx_ring_p->max_burst.value); 1208 if (rs == NPI_SUCCESS) { 1209 return (NXGE_OK); 1210 } else { 1211 return (NXGE_ERROR | rs); 1212 } 1213 } 1214 1215 nxge_status_t 1216 nxge_fzc_sys_err_mask_set(p_nxge_t nxgep, uint64_t mask) 1217 { 1218 npi_status_t rs = NPI_SUCCESS; 1219 npi_handle_t handle; 1220 1221 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1222 rs = npi_fzc_sys_err_mask_set(handle, mask); 1223 if (rs == NPI_SUCCESS) { 1224 return (NXGE_OK); 1225 } else { 1226 return (NXGE_ERROR | rs); 1227 } 1228 } 1229 1230 /* 1231 * nxge_init_hv_fzc_txdma_channel_pages 1232 * 1233 * Configure a TDC's logical pages. 1234 * 1235 * Arguments: 1236 * nxgep 1237 * channel The channel to initialize. 1238 * tx_ring_p The transmit ring. 1239 * 1240 * Notes: 1241 * I think that this function can be called from any 1242 * domain, but I need to check. 1243 * 1244 * NPI/NXGE function calls: 1245 * hv_niu_tx_logical_page_conf() 1246 * hv_niu_tx_logical_page_info() 1247 * 1248 * Context: 1249 * Any domain 1250 */ 1251 #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 1252 nxge_status_t 1253 nxge_init_hv_fzc_txdma_channel_pages(p_nxge_t nxgep, uint16_t channel, 1254 p_tx_ring_t tx_ring_p) 1255 { 1256 int err; 1257 uint64_t hverr; 1258 #ifdef DEBUG 1259 uint64_t ra, size; 1260 #endif 1261 1262 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1263 "==> nxge_init_hv_fzc_txdma_channel_pages")); 1264 1265 if (tx_ring_p->hv_set) { 1266 return (NXGE_OK); 1267 } 1268 1269 /* 1270 * Initialize logical page 1 for data buffers. 1271 */ 1272 hverr = hv_niu_tx_logical_page_conf((uint64_t)channel, 1273 (uint64_t)0, 1274 tx_ring_p->hv_tx_buf_base_ioaddr_pp, 1275 tx_ring_p->hv_tx_buf_ioaddr_size); 1276 1277 err = (nxge_status_t)nxge_herr2kerr(hverr); 1278 if (err != 0) { 1279 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1280 "<== nxge_init_hv_fzc_txdma_channel_pages: channel %d " 1281 "error status 0x%x " 1282 "(page 0 data buf) hverr 0x%llx " 1283 "ioaddr_pp $%p " 1284 "size 0x%llx ", 1285 channel, 1286 err, 1287 hverr, 1288 tx_ring_p->hv_tx_buf_base_ioaddr_pp, 1289 tx_ring_p->hv_tx_buf_ioaddr_size)); 1290 return (NXGE_ERROR | err); 1291 } 1292 1293 #ifdef DEBUG 1294 ra = size = 0; 1295 hverr = hv_niu_tx_logical_page_info((uint64_t)channel, 1296 (uint64_t)0, 1297 &ra, 1298 &size); 1299 1300 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1301 "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d " 1302 "ok status 0x%x " 1303 "(page 0 data buf) hverr 0x%llx " 1304 "set ioaddr_pp $%p " 1305 "set size 0x%llx " 1306 "get ra ioaddr_pp $%p " 1307 "get size 0x%llx ", 1308 channel, 1309 err, 1310 hverr, 1311 tx_ring_p->hv_tx_buf_base_ioaddr_pp, 1312 tx_ring_p->hv_tx_buf_ioaddr_size, 1313 ra, 1314 size)); 1315 #endif 1316 1317 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1318 "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d " 1319 "(page 0 data buf) hverr 0x%llx " 1320 "ioaddr_pp $%p " 1321 "size 0x%llx ", 1322 channel, 1323 hverr, 1324 tx_ring_p->hv_tx_buf_base_ioaddr_pp, 1325 tx_ring_p->hv_tx_buf_ioaddr_size)); 1326 1327 /* 1328 * Initialize logical page 2 for control buffers. 1329 */ 1330 hverr = hv_niu_tx_logical_page_conf((uint64_t)channel, 1331 (uint64_t)1, 1332 tx_ring_p->hv_tx_cntl_base_ioaddr_pp, 1333 tx_ring_p->hv_tx_cntl_ioaddr_size); 1334 1335 err = (nxge_status_t)nxge_herr2kerr(hverr); 1336 1337 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1338 "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d" 1339 "ok status 0x%x " 1340 "(page 1 cntl buf) hverr 0x%llx " 1341 "ioaddr_pp $%p " 1342 "size 0x%llx ", 1343 channel, 1344 err, 1345 hverr, 1346 tx_ring_p->hv_tx_cntl_base_ioaddr_pp, 1347 tx_ring_p->hv_tx_cntl_ioaddr_size)); 1348 1349 if (err != 0) { 1350 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1351 "<== nxge_init_hv_fzc_txdma_channel_pages: channel %d" 1352 "error status 0x%x " 1353 "(page 1 cntl buf) hverr 0x%llx " 1354 "ioaddr_pp $%p " 1355 "size 0x%llx ", 1356 channel, 1357 err, 1358 hverr, 1359 tx_ring_p->hv_tx_cntl_base_ioaddr_pp, 1360 tx_ring_p->hv_tx_cntl_ioaddr_size)); 1361 return (NXGE_ERROR | err); 1362 } 1363 1364 #ifdef DEBUG 1365 ra = size = 0; 1366 hverr = hv_niu_tx_logical_page_info((uint64_t)channel, 1367 (uint64_t)1, 1368 &ra, 1369 &size); 1370 1371 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1372 "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d " 1373 "(page 1 cntl buf) hverr 0x%llx " 1374 "set ioaddr_pp $%p " 1375 "set size 0x%llx " 1376 "get ra ioaddr_pp $%p " 1377 "get size 0x%llx ", 1378 channel, 1379 hverr, 1380 tx_ring_p->hv_tx_cntl_base_ioaddr_pp, 1381 tx_ring_p->hv_tx_cntl_ioaddr_size, 1382 ra, 1383 size)); 1384 #endif 1385 1386 tx_ring_p->hv_set = B_TRUE; 1387 1388 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1389 "<== nxge_init_hv_fzc_txdma_channel_pages")); 1390 1391 return (NXGE_OK); 1392 } 1393 1394 /*ARGSUSED*/ 1395 nxge_status_t 1396 nxge_init_hv_fzc_rxdma_channel_pages(p_nxge_t nxgep, 1397 uint16_t channel, p_rx_rbr_ring_t rbrp) 1398 { 1399 int err; 1400 uint64_t hverr; 1401 #ifdef DEBUG 1402 uint64_t ra, size; 1403 #endif 1404 1405 NXGE_DEBUG_MSG((nxgep, RX_CTL, 1406 "==> nxge_init_hv_fzc_rxdma_channel_pages")); 1407 1408 if (rbrp->hv_set) { 1409 return (NXGE_OK); 1410 } 1411 1412 /* Initialize data buffers for page 0 */ 1413 hverr = hv_niu_rx_logical_page_conf((uint64_t)channel, 1414 (uint64_t)0, 1415 rbrp->hv_rx_buf_base_ioaddr_pp, 1416 rbrp->hv_rx_buf_ioaddr_size); 1417 err = (nxge_status_t)nxge_herr2kerr(hverr); 1418 if (err != 0) { 1419 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1420 "<== nxge_init_hv_fzc_rxdma_channel_pages: channel %d" 1421 "error status 0x%x " 1422 "(page 0 data buf) hverr 0x%llx " 1423 "ioaddr_pp $%p " 1424 "size 0x%llx ", 1425 channel, 1426 err, 1427 hverr, 1428 rbrp->hv_rx_buf_base_ioaddr_pp, 1429 rbrp->hv_rx_buf_ioaddr_size)); 1430 1431 return (NXGE_ERROR | err); 1432 } 1433 1434 #ifdef DEBUG 1435 ra = size = 0; 1436 (void) hv_niu_rx_logical_page_info((uint64_t)channel, 1437 (uint64_t)0, 1438 &ra, 1439 &size); 1440 1441 NXGE_DEBUG_MSG((nxgep, RX_CTL, 1442 "==> nxge_init_hv_fzc_rxdma_channel_pages: channel %d " 1443 "ok status 0x%x " 1444 "(page 0 data buf) hverr 0x%llx " 1445 "set databuf ioaddr_pp $%p " 1446 "set databuf size 0x%llx " 1447 "get databuf ra ioaddr_pp %p " 1448 "get databuf size 0x%llx", 1449 channel, 1450 err, 1451 hverr, 1452 rbrp->hv_rx_buf_base_ioaddr_pp, 1453 rbrp->hv_rx_buf_ioaddr_size, 1454 ra, 1455 size)); 1456 #endif 1457 1458 /* Initialize control buffers for logical page 1. */ 1459 hverr = hv_niu_rx_logical_page_conf((uint64_t)channel, 1460 (uint64_t)1, 1461 rbrp->hv_rx_cntl_base_ioaddr_pp, 1462 rbrp->hv_rx_cntl_ioaddr_size); 1463 1464 err = (nxge_status_t)nxge_herr2kerr(hverr); 1465 if (err != 0) { 1466 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1467 "<== nxge_init_hv_fzc_rxdma_channel_pages: channel %d" 1468 "error status 0x%x " 1469 "(page 1 cntl buf) hverr 0x%llx " 1470 "ioaddr_pp $%p " 1471 "size 0x%llx ", 1472 channel, 1473 err, 1474 hverr, 1475 rbrp->hv_rx_buf_base_ioaddr_pp, 1476 rbrp->hv_rx_buf_ioaddr_size)); 1477 1478 return (NXGE_ERROR | err); 1479 } 1480 1481 #ifdef DEBUG 1482 ra = size = 0; 1483 (void) hv_niu_rx_logical_page_info((uint64_t)channel, 1484 (uint64_t)1, 1485 &ra, 1486 &size); 1487 1488 1489 NXGE_DEBUG_MSG((nxgep, RX_CTL, 1490 "==> nxge_init_hv_fzc_rxdma_channel_pages: channel %d " 1491 "error status 0x%x " 1492 "(page 1 cntl buf) hverr 0x%llx " 1493 "set cntl ioaddr_pp $%p " 1494 "set cntl size 0x%llx " 1495 "get cntl ioaddr_pp $%p " 1496 "get cntl size 0x%llx ", 1497 channel, 1498 err, 1499 hverr, 1500 rbrp->hv_rx_cntl_base_ioaddr_pp, 1501 rbrp->hv_rx_cntl_ioaddr_size, 1502 ra, 1503 size)); 1504 #endif 1505 1506 rbrp->hv_set = B_FALSE; 1507 1508 NXGE_DEBUG_MSG((nxgep, RX_CTL, 1509 "<== nxge_init_hv_fzc_rxdma_channel_pages")); 1510 1511 return (NXGE_OK); 1512 } 1513 1514 /* 1515 * Map hypervisor error code to errno. Only 1516 * H_ENORADDR, H_EBADALIGN and H_EINVAL are meaningful 1517 * for niu driver. Any other error codes are mapped to EINVAL. 1518 */ 1519 static int 1520 nxge_herr2kerr(uint64_t hv_errcode) 1521 { 1522 int s_errcode; 1523 1524 switch (hv_errcode) { 1525 case H_ENORADDR: 1526 case H_EBADALIGN: 1527 s_errcode = EFAULT; 1528 break; 1529 case H_EOK: 1530 s_errcode = 0; 1531 break; 1532 default: 1533 s_errcode = EINVAL; 1534 break; 1535 } 1536 return (s_errcode); 1537 } 1538 1539 #endif /* sun4v and NIU_LP_WORKAROUND */ 1540