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_SERDES)) { 992 rs = npi_rxdma_cfg_port_ddr_weight(handle, 993 nxgep->function_num, NXGE_RX_DRR_WT_1G); 994 if (rs != NPI_SUCCESS) { 995 return (NXGE_ERROR | rs); 996 } 997 } 998 999 /* Program the default RDC of a port */ 1000 rs = npi_rxdma_cfg_default_port_rdc(handle, nxgep->function_num, 1001 p_cfgp->def_rdc); 1002 if (rs != NPI_SUCCESS) { 1003 return (NXGE_ERROR | rs); 1004 } 1005 1006 /* 1007 * Configure the MAC host info table with RDC tables 1008 */ 1009 hostinfo.value = 0; 1010 p_class_cfgp = (p_nxge_class_pt_cfg_t)&nxgep->class_config; 1011 for (i = 0; i < p_cfgp->max_macs; i++) { 1012 hostinfo.bits.w0.rdc_tbl_num = p_cfgp->def_mac_rxdma_grpid; 1013 hostinfo.bits.w0.mac_pref = p_cfgp->mac_pref; 1014 if (p_class_cfgp->mac_host_info[i].flag) { 1015 hostinfo.bits.w0.rdc_tbl_num = 1016 p_class_cfgp->mac_host_info[i].rdctbl; 1017 hostinfo.bits.w0.mac_pref = 1018 p_class_cfgp->mac_host_info[i].mpr_npr; 1019 } 1020 1021 rs = npi_mac_hostinfo_entry(handle, OP_SET, 1022 nxgep->function_num, i, &hostinfo); 1023 if (rs != NPI_SUCCESS) 1024 return (NXGE_ERROR | rs); 1025 } 1026 1027 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1028 "<== nxge_init_fzc_rxdma_port rs 0x%08x", rs)); 1029 1030 return (NXGE_OK); 1031 1032 } 1033 1034 nxge_status_t 1035 nxge_fzc_dmc_def_port_rdc(p_nxge_t nxgep, uint8_t port, uint16_t rdc) 1036 { 1037 npi_status_t rs = NPI_SUCCESS; 1038 rs = npi_rxdma_cfg_default_port_rdc(nxgep->npi_reg_handle, 1039 port, rdc); 1040 if (rs & NPI_FAILURE) 1041 return (NXGE_ERROR | rs); 1042 return (NXGE_OK); 1043 } 1044 1045 /* 1046 * nxge_init_fzc_tdc_pages 1047 * 1048 * Configure a TDC's logical pages. 1049 * 1050 * This function is executed by the service domain, on behalf of 1051 * a guest domain, to whom this TDC has been loaned. 1052 * 1053 * Arguments: 1054 * nxgep 1055 * channel The channel to initialize. 1056 * page0 Logical page 0 definition. 1057 * page1 Logical page 1 definition. 1058 * 1059 * Notes: 1060 * I think that this function can be called from any 1061 * domain, but I need to check. 1062 * 1063 * NPI/NXGE function calls: 1064 * hv_niu_tx_logical_page_conf() 1065 * hv_niu_tx_logical_page_info() 1066 * 1067 * Context: 1068 * Any domain 1069 */ 1070 nxge_status_t 1071 nxge_init_fzc_tdc_pages( 1072 p_nxge_t nxgep, 1073 uint16_t channel, 1074 dma_log_page_t *page0, 1075 dma_log_page_t *page1) 1076 { 1077 npi_handle_t handle; 1078 npi_status_t rs; 1079 1080 log_page_hdl_t page_handle; 1081 1082 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1083 "==> nxge_init_fzc_txdma_channel_pages")); 1084 1085 #ifndef NIU_HV_WORKAROUND 1086 if (nxgep->niu_type == N2_NIU) { 1087 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1088 "<== nxge_init_fzc_tdc_pages: " 1089 "N2_NIU: no need to set txdma logical pages")); 1090 return (NXGE_OK); 1091 } 1092 #else 1093 if (nxgep->niu_type == N2_NIU) { 1094 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1095 "<== nxge_init_fzc_tdc_pages: " 1096 "N2_NIU: NEED to set txdma logical pages")); 1097 } 1098 #endif 1099 1100 /* 1101 * Initialize logical page 1. 1102 */ 1103 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1104 if ((rs = npi_txdma_log_page_set(handle, channel, page0)) 1105 != NPI_SUCCESS) 1106 return (NXGE_ERROR | rs); 1107 1108 /* 1109 * Initialize logical page 2. 1110 */ 1111 if ((rs = npi_txdma_log_page_set(handle, channel, page1)) 1112 != NPI_SUCCESS) 1113 return (NXGE_ERROR | rs); 1114 1115 /* 1116 * Initialize the page handle. 1117 * (In the current driver, this is always set to 0.) 1118 */ 1119 page_handle.value = 0; 1120 rs = npi_txdma_log_page_handle_set(handle, channel, &page_handle); 1121 if (rs == NPI_SUCCESS) { 1122 return (NXGE_OK); 1123 } else { 1124 return (NXGE_ERROR | rs); 1125 } 1126 } 1127 1128 nxge_status_t 1129 nxge_init_fzc_txdma_channel_pages(p_nxge_t nxgep, uint16_t channel, 1130 p_tx_ring_t tx_ring_p) 1131 { 1132 npi_handle_t handle; 1133 dma_log_page_t cfg; 1134 npi_status_t rs = NPI_SUCCESS; 1135 1136 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1137 "==> nxge_init_fzc_txdma_channel_pages")); 1138 1139 #ifndef NIU_HV_WORKAROUND 1140 if (nxgep->niu_type == N2_NIU) { 1141 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1142 "<== nxge_init_fzc_txdma_channel_pages: " 1143 "N2_NIU: no need to set txdma logical pages")); 1144 return (NXGE_OK); 1145 } 1146 #else 1147 if (nxgep->niu_type == N2_NIU) { 1148 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1149 "<== nxge_init_fzc_txdma_channel_pages: " 1150 "N2_NIU: NEED to set txdma logical pages")); 1151 } 1152 #endif 1153 1154 /* 1155 * Initialize logical page 1. 1156 */ 1157 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1158 cfg.func_num = nxgep->function_num; 1159 cfg.page_num = 0; 1160 cfg.valid = tx_ring_p->page_valid.bits.ldw.page0; 1161 cfg.value = tx_ring_p->page_value_1.value; 1162 cfg.mask = tx_ring_p->page_mask_1.value; 1163 cfg.reloc = tx_ring_p->page_reloc_1.value; 1164 1165 rs = npi_txdma_log_page_set(handle, channel, 1166 (p_dma_log_page_t)&cfg); 1167 if (rs != NPI_SUCCESS) { 1168 return (NXGE_ERROR | rs); 1169 } 1170 1171 /* 1172 * Initialize logical page 2. 1173 */ 1174 cfg.page_num = 1; 1175 cfg.valid = tx_ring_p->page_valid.bits.ldw.page1; 1176 cfg.value = tx_ring_p->page_value_2.value; 1177 cfg.mask = tx_ring_p->page_mask_2.value; 1178 cfg.reloc = tx_ring_p->page_reloc_2.value; 1179 1180 rs = npi_txdma_log_page_set(handle, channel, &cfg); 1181 if (rs != NPI_SUCCESS) { 1182 return (NXGE_ERROR | rs); 1183 } 1184 1185 /* Initialize the page handle */ 1186 rs = npi_txdma_log_page_handle_set(handle, channel, 1187 &tx_ring_p->page_hdl); 1188 1189 if (rs == NPI_SUCCESS) { 1190 return (NXGE_OK); 1191 } else { 1192 return (NXGE_ERROR | rs); 1193 } 1194 } 1195 1196 1197 nxge_status_t 1198 nxge_init_fzc_txdma_channel_drr(p_nxge_t nxgep, uint16_t channel, 1199 p_tx_ring_t tx_ring_p) 1200 { 1201 npi_status_t rs = NPI_SUCCESS; 1202 npi_handle_t handle; 1203 1204 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1205 rs = npi_txc_dma_max_burst_set(handle, channel, 1206 tx_ring_p->max_burst.value); 1207 if (rs == NPI_SUCCESS) { 1208 return (NXGE_OK); 1209 } else { 1210 return (NXGE_ERROR | rs); 1211 } 1212 } 1213 1214 nxge_status_t 1215 nxge_fzc_sys_err_mask_set(p_nxge_t nxgep, uint64_t mask) 1216 { 1217 npi_status_t rs = NPI_SUCCESS; 1218 npi_handle_t handle; 1219 1220 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1221 rs = npi_fzc_sys_err_mask_set(handle, mask); 1222 if (rs == NPI_SUCCESS) { 1223 return (NXGE_OK); 1224 } else { 1225 return (NXGE_ERROR | rs); 1226 } 1227 } 1228 1229 /* 1230 * nxge_init_hv_fzc_txdma_channel_pages 1231 * 1232 * Configure a TDC's logical pages. 1233 * 1234 * Arguments: 1235 * nxgep 1236 * channel The channel to initialize. 1237 * tx_ring_p The transmit ring. 1238 * 1239 * Notes: 1240 * I think that this function can be called from any 1241 * domain, but I need to check. 1242 * 1243 * NPI/NXGE function calls: 1244 * hv_niu_tx_logical_page_conf() 1245 * hv_niu_tx_logical_page_info() 1246 * 1247 * Context: 1248 * Any domain 1249 */ 1250 #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 1251 nxge_status_t 1252 nxge_init_hv_fzc_txdma_channel_pages(p_nxge_t nxgep, uint16_t channel, 1253 p_tx_ring_t tx_ring_p) 1254 { 1255 int err; 1256 uint64_t hverr; 1257 #ifdef DEBUG 1258 uint64_t ra, size; 1259 #endif 1260 1261 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1262 "==> nxge_init_hv_fzc_txdma_channel_pages")); 1263 1264 if (tx_ring_p->hv_set) { 1265 return (NXGE_OK); 1266 } 1267 1268 /* 1269 * Initialize logical page 1 for data buffers. 1270 */ 1271 hverr = hv_niu_tx_logical_page_conf((uint64_t)channel, 1272 (uint64_t)0, 1273 tx_ring_p->hv_tx_buf_base_ioaddr_pp, 1274 tx_ring_p->hv_tx_buf_ioaddr_size); 1275 1276 err = (nxge_status_t)nxge_herr2kerr(hverr); 1277 if (err != 0) { 1278 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1279 "<== nxge_init_hv_fzc_txdma_channel_pages: channel %d " 1280 "error status 0x%x " 1281 "(page 0 data buf) hverr 0x%llx " 1282 "ioaddr_pp $%p " 1283 "size 0x%llx ", 1284 channel, 1285 err, 1286 hverr, 1287 tx_ring_p->hv_tx_buf_base_ioaddr_pp, 1288 tx_ring_p->hv_tx_buf_ioaddr_size)); 1289 return (NXGE_ERROR | err); 1290 } 1291 1292 #ifdef DEBUG 1293 ra = size = 0; 1294 hverr = hv_niu_tx_logical_page_info((uint64_t)channel, 1295 (uint64_t)0, 1296 &ra, 1297 &size); 1298 1299 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1300 "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d " 1301 "ok status 0x%x " 1302 "(page 0 data buf) hverr 0x%llx " 1303 "set ioaddr_pp $%p " 1304 "set size 0x%llx " 1305 "get ra ioaddr_pp $%p " 1306 "get size 0x%llx ", 1307 channel, 1308 err, 1309 hverr, 1310 tx_ring_p->hv_tx_buf_base_ioaddr_pp, 1311 tx_ring_p->hv_tx_buf_ioaddr_size, 1312 ra, 1313 size)); 1314 #endif 1315 1316 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1317 "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d " 1318 "(page 0 data buf) hverr 0x%llx " 1319 "ioaddr_pp $%p " 1320 "size 0x%llx ", 1321 channel, 1322 hverr, 1323 tx_ring_p->hv_tx_buf_base_ioaddr_pp, 1324 tx_ring_p->hv_tx_buf_ioaddr_size)); 1325 1326 /* 1327 * Initialize logical page 2 for control buffers. 1328 */ 1329 hverr = hv_niu_tx_logical_page_conf((uint64_t)channel, 1330 (uint64_t)1, 1331 tx_ring_p->hv_tx_cntl_base_ioaddr_pp, 1332 tx_ring_p->hv_tx_cntl_ioaddr_size); 1333 1334 err = (nxge_status_t)nxge_herr2kerr(hverr); 1335 1336 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1337 "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d" 1338 "ok status 0x%x " 1339 "(page 1 cntl buf) hverr 0x%llx " 1340 "ioaddr_pp $%p " 1341 "size 0x%llx ", 1342 channel, 1343 err, 1344 hverr, 1345 tx_ring_p->hv_tx_cntl_base_ioaddr_pp, 1346 tx_ring_p->hv_tx_cntl_ioaddr_size)); 1347 1348 if (err != 0) { 1349 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1350 "<== nxge_init_hv_fzc_txdma_channel_pages: channel %d" 1351 "error status 0x%x " 1352 "(page 1 cntl buf) hverr 0x%llx " 1353 "ioaddr_pp $%p " 1354 "size 0x%llx ", 1355 channel, 1356 err, 1357 hverr, 1358 tx_ring_p->hv_tx_cntl_base_ioaddr_pp, 1359 tx_ring_p->hv_tx_cntl_ioaddr_size)); 1360 return (NXGE_ERROR | err); 1361 } 1362 1363 #ifdef DEBUG 1364 ra = size = 0; 1365 hverr = hv_niu_tx_logical_page_info((uint64_t)channel, 1366 (uint64_t)1, 1367 &ra, 1368 &size); 1369 1370 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1371 "==> nxge_init_hv_fzc_txdma_channel_pages: channel %d " 1372 "(page 1 cntl buf) hverr 0x%llx " 1373 "set ioaddr_pp $%p " 1374 "set size 0x%llx " 1375 "get ra ioaddr_pp $%p " 1376 "get size 0x%llx ", 1377 channel, 1378 hverr, 1379 tx_ring_p->hv_tx_cntl_base_ioaddr_pp, 1380 tx_ring_p->hv_tx_cntl_ioaddr_size, 1381 ra, 1382 size)); 1383 #endif 1384 1385 tx_ring_p->hv_set = B_TRUE; 1386 1387 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1388 "<== nxge_init_hv_fzc_txdma_channel_pages")); 1389 1390 return (NXGE_OK); 1391 } 1392 1393 /*ARGSUSED*/ 1394 nxge_status_t 1395 nxge_init_hv_fzc_rxdma_channel_pages(p_nxge_t nxgep, 1396 uint16_t channel, p_rx_rbr_ring_t rbrp) 1397 { 1398 int err; 1399 uint64_t hverr; 1400 #ifdef DEBUG 1401 uint64_t ra, size; 1402 #endif 1403 1404 NXGE_DEBUG_MSG((nxgep, RX_CTL, 1405 "==> nxge_init_hv_fzc_rxdma_channel_pages")); 1406 1407 if (rbrp->hv_set) { 1408 return (NXGE_OK); 1409 } 1410 1411 /* Initialize data buffers for page 0 */ 1412 hverr = hv_niu_rx_logical_page_conf((uint64_t)channel, 1413 (uint64_t)0, 1414 rbrp->hv_rx_buf_base_ioaddr_pp, 1415 rbrp->hv_rx_buf_ioaddr_size); 1416 err = (nxge_status_t)nxge_herr2kerr(hverr); 1417 if (err != 0) { 1418 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1419 "<== nxge_init_hv_fzc_rxdma_channel_pages: channel %d" 1420 "error status 0x%x " 1421 "(page 0 data buf) hverr 0x%llx " 1422 "ioaddr_pp $%p " 1423 "size 0x%llx ", 1424 channel, 1425 err, 1426 hverr, 1427 rbrp->hv_rx_buf_base_ioaddr_pp, 1428 rbrp->hv_rx_buf_ioaddr_size)); 1429 1430 return (NXGE_ERROR | err); 1431 } 1432 1433 #ifdef DEBUG 1434 ra = size = 0; 1435 (void) hv_niu_rx_logical_page_info((uint64_t)channel, 1436 (uint64_t)0, 1437 &ra, 1438 &size); 1439 1440 NXGE_DEBUG_MSG((nxgep, RX_CTL, 1441 "==> nxge_init_hv_fzc_rxdma_channel_pages: channel %d " 1442 "ok status 0x%x " 1443 "(page 0 data buf) hverr 0x%llx " 1444 "set databuf ioaddr_pp $%p " 1445 "set databuf size 0x%llx " 1446 "get databuf ra ioaddr_pp %p " 1447 "get databuf size 0x%llx", 1448 channel, 1449 err, 1450 hverr, 1451 rbrp->hv_rx_buf_base_ioaddr_pp, 1452 rbrp->hv_rx_buf_ioaddr_size, 1453 ra, 1454 size)); 1455 #endif 1456 1457 /* Initialize control buffers for logical page 1. */ 1458 hverr = hv_niu_rx_logical_page_conf((uint64_t)channel, 1459 (uint64_t)1, 1460 rbrp->hv_rx_cntl_base_ioaddr_pp, 1461 rbrp->hv_rx_cntl_ioaddr_size); 1462 1463 err = (nxge_status_t)nxge_herr2kerr(hverr); 1464 if (err != 0) { 1465 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1466 "<== nxge_init_hv_fzc_rxdma_channel_pages: channel %d" 1467 "error status 0x%x " 1468 "(page 1 cntl buf) hverr 0x%llx " 1469 "ioaddr_pp $%p " 1470 "size 0x%llx ", 1471 channel, 1472 err, 1473 hverr, 1474 rbrp->hv_rx_buf_base_ioaddr_pp, 1475 rbrp->hv_rx_buf_ioaddr_size)); 1476 1477 return (NXGE_ERROR | err); 1478 } 1479 1480 #ifdef DEBUG 1481 ra = size = 0; 1482 (void) hv_niu_rx_logical_page_info((uint64_t)channel, 1483 (uint64_t)1, 1484 &ra, 1485 &size); 1486 1487 1488 NXGE_DEBUG_MSG((nxgep, RX_CTL, 1489 "==> nxge_init_hv_fzc_rxdma_channel_pages: channel %d " 1490 "error status 0x%x " 1491 "(page 1 cntl buf) hverr 0x%llx " 1492 "set cntl ioaddr_pp $%p " 1493 "set cntl size 0x%llx " 1494 "get cntl ioaddr_pp $%p " 1495 "get cntl size 0x%llx ", 1496 channel, 1497 err, 1498 hverr, 1499 rbrp->hv_rx_cntl_base_ioaddr_pp, 1500 rbrp->hv_rx_cntl_ioaddr_size, 1501 ra, 1502 size)); 1503 #endif 1504 1505 rbrp->hv_set = B_FALSE; 1506 1507 NXGE_DEBUG_MSG((nxgep, RX_CTL, 1508 "<== nxge_init_hv_fzc_rxdma_channel_pages")); 1509 1510 return (NXGE_OK); 1511 } 1512 1513 /* 1514 * Map hypervisor error code to errno. Only 1515 * H_ENORADDR, H_EBADALIGN and H_EINVAL are meaningful 1516 * for niu driver. Any other error codes are mapped to EINVAL. 1517 */ 1518 static int 1519 nxge_herr2kerr(uint64_t hv_errcode) 1520 { 1521 int s_errcode; 1522 1523 switch (hv_errcode) { 1524 case H_ENORADDR: 1525 case H_EBADALIGN: 1526 s_errcode = EFAULT; 1527 break; 1528 case H_EOK: 1529 s_errcode = 0; 1530 break; 1531 default: 1532 s_errcode = EINVAL; 1533 break; 1534 } 1535 return (s_errcode); 1536 } 1537 1538 #endif /* sun4v and NIU_LP_WORKAROUND */ 1539