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 <sys/nxge/nxge_impl.h> 29 #include <sys/nxge/nxge_txdma.h> 30 #include <sys/nxge/nxge_hio.h> 31 #include <npi_tx_rd64.h> 32 #include <npi_tx_wr64.h> 33 #include <sys/llc1.h> 34 35 uint32_t nxge_reclaim_pending = TXDMA_RECLAIM_PENDING_DEFAULT; 36 uint32_t nxge_tx_minfree = 32; 37 uint32_t nxge_tx_intr_thres = 0; 38 uint32_t nxge_tx_max_gathers = TX_MAX_GATHER_POINTERS; 39 uint32_t nxge_tx_tiny_pack = 1; 40 uint32_t nxge_tx_use_bcopy = 1; 41 42 extern uint32_t nxge_tx_ring_size; 43 extern uint32_t nxge_bcopy_thresh; 44 extern uint32_t nxge_dvma_thresh; 45 extern uint32_t nxge_dma_stream_thresh; 46 extern dma_method_t nxge_force_dma; 47 extern uint32_t nxge_cksum_offload; 48 49 /* Device register access attributes for PIO. */ 50 extern ddi_device_acc_attr_t nxge_dev_reg_acc_attr; 51 /* Device descriptor access attributes for DMA. */ 52 extern ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr; 53 /* Device buffer access attributes for DMA. */ 54 extern ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr; 55 extern ddi_dma_attr_t nxge_desc_dma_attr; 56 extern ddi_dma_attr_t nxge_tx_dma_attr; 57 58 extern int nxge_serial_tx(mblk_t *mp, void *arg); 59 60 static nxge_status_t nxge_map_txdma(p_nxge_t, int); 61 62 static nxge_status_t nxge_txdma_hw_start(p_nxge_t, int); 63 64 static nxge_status_t nxge_map_txdma_channel(p_nxge_t, uint16_t, 65 p_nxge_dma_common_t *, p_tx_ring_t *, 66 uint32_t, p_nxge_dma_common_t *, 67 p_tx_mbox_t *); 68 static void nxge_unmap_txdma_channel(p_nxge_t, uint16_t); 69 70 static nxge_status_t nxge_map_txdma_channel_buf_ring(p_nxge_t, uint16_t, 71 p_nxge_dma_common_t *, p_tx_ring_t *, uint32_t); 72 static void nxge_unmap_txdma_channel_buf_ring(p_nxge_t, p_tx_ring_t); 73 74 static void nxge_map_txdma_channel_cfg_ring(p_nxge_t, uint16_t, 75 p_nxge_dma_common_t *, p_tx_ring_t, 76 p_tx_mbox_t *); 77 static void nxge_unmap_txdma_channel_cfg_ring(p_nxge_t, 78 p_tx_ring_t, p_tx_mbox_t); 79 80 static nxge_status_t nxge_txdma_start_channel(p_nxge_t, uint16_t, 81 p_tx_ring_t, p_tx_mbox_t); 82 static nxge_status_t nxge_txdma_stop_channel(p_nxge_t, uint16_t); 83 84 static p_tx_ring_t nxge_txdma_get_ring(p_nxge_t, uint16_t); 85 static nxge_status_t nxge_tx_err_evnts(p_nxge_t, uint_t, 86 p_nxge_ldv_t, tx_cs_t); 87 static p_tx_mbox_t nxge_txdma_get_mbox(p_nxge_t, uint16_t); 88 static nxge_status_t nxge_txdma_fatal_err_recover(p_nxge_t, 89 uint16_t, p_tx_ring_t); 90 91 static void nxge_txdma_fixup_hung_channel(p_nxge_t nxgep, 92 p_tx_ring_t ring_p, uint16_t channel); 93 94 nxge_status_t 95 nxge_init_txdma_channels(p_nxge_t nxgep) 96 { 97 nxge_grp_set_t *set = &nxgep->tx_set; 98 int i, count; 99 100 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_init_txdma_channels")); 101 102 for (i = 0, count = 0; i < NXGE_LOGICAL_GROUP_MAX; i++) { 103 if ((1 << i) & set->lg.map) { 104 int tdc; 105 nxge_grp_t *group = set->group[i]; 106 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 107 if ((1 << tdc) & group->map) { 108 if ((nxge_grp_dc_add(nxgep, 109 (vr_handle_t)group, 110 VP_BOUND_TX, tdc))) 111 return (NXGE_ERROR); 112 } 113 } 114 } 115 if (++count == set->lg.count) 116 break; 117 } 118 119 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_init_txdma_channels")); 120 121 return (NXGE_OK); 122 } 123 124 nxge_status_t 125 nxge_init_txdma_channel( 126 p_nxge_t nxge, 127 int channel) 128 { 129 nxge_status_t status; 130 131 NXGE_DEBUG_MSG((nxge, MEM2_CTL, "==> nxge_init_txdma_channel")); 132 133 status = nxge_map_txdma(nxge, channel); 134 if (status != NXGE_OK) { 135 NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 136 "<== nxge_init_txdma_channel: status 0x%x", status)); 137 (void) npi_txdma_dump_tdc_regs(nxge->npi_handle, channel); 138 return (status); 139 } 140 141 status = nxge_txdma_hw_start(nxge, channel); 142 if (status != NXGE_OK) { 143 (void) nxge_unmap_txdma_channel(nxge, channel); 144 (void) npi_txdma_dump_tdc_regs(nxge->npi_handle, channel); 145 return (status); 146 } 147 148 if (!nxge->statsp->tdc_ksp[channel]) 149 nxge_setup_tdc_kstats(nxge, channel); 150 151 NXGE_DEBUG_MSG((nxge, MEM2_CTL, "<== nxge_init_txdma_channel")); 152 153 return (status); 154 } 155 156 void 157 nxge_uninit_txdma_channels(p_nxge_t nxgep) 158 { 159 nxge_grp_set_t *set = &nxgep->tx_set; 160 int tdc; 161 162 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_uninit_txdma_channels")); 163 164 if (set->owned.map == 0) { 165 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 166 "nxge_uninit_txdma_channels: no channels")); 167 return; 168 } 169 170 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 171 if ((1 << tdc) & set->owned.map) { 172 nxge_grp_dc_remove(nxgep, VP_BOUND_TX, tdc); 173 } 174 } 175 176 NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_uninit_txdma_channels")); 177 } 178 179 void 180 nxge_uninit_txdma_channel(p_nxge_t nxgep, int channel) 181 { 182 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_uninit_txdma_channel")); 183 184 if (nxgep->statsp->tdc_ksp[channel]) { 185 kstat_delete(nxgep->statsp->tdc_ksp[channel]); 186 nxgep->statsp->tdc_ksp[channel] = 0; 187 } 188 189 (void) nxge_txdma_stop_channel(nxgep, channel); 190 nxge_unmap_txdma_channel(nxgep, channel); 191 192 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 193 "<== nxge_uninit_txdma_channel")); 194 } 195 196 void 197 nxge_setup_dma_common(p_nxge_dma_common_t dest_p, p_nxge_dma_common_t src_p, 198 uint32_t entries, uint32_t size) 199 { 200 size_t tsize; 201 *dest_p = *src_p; 202 tsize = size * entries; 203 dest_p->alength = tsize; 204 dest_p->nblocks = entries; 205 dest_p->block_size = size; 206 dest_p->offset += tsize; 207 208 src_p->kaddrp = (caddr_t)dest_p->kaddrp + tsize; 209 src_p->alength -= tsize; 210 src_p->dma_cookie.dmac_laddress += tsize; 211 src_p->dma_cookie.dmac_size -= tsize; 212 } 213 214 /* 215 * nxge_reset_txdma_channel 216 * 217 * Reset a TDC. 218 * 219 * Arguments: 220 * nxgep 221 * channel The channel to reset. 222 * reg_data The current TX_CS. 223 * 224 * Notes: 225 * 226 * NPI/NXGE function calls: 227 * npi_txdma_channel_reset() 228 * npi_txdma_channel_control() 229 * 230 * Registers accessed: 231 * TX_CS DMC+0x40028 Transmit Control And Status 232 * TX_RING_KICK DMC+0x40018 Transmit Ring Kick 233 * 234 * Context: 235 * Any domain 236 */ 237 nxge_status_t 238 nxge_reset_txdma_channel(p_nxge_t nxgep, uint16_t channel, uint64_t reg_data) 239 { 240 npi_status_t rs = NPI_SUCCESS; 241 nxge_status_t status = NXGE_OK; 242 npi_handle_t handle; 243 244 NXGE_DEBUG_MSG((nxgep, TX_CTL, " ==> nxge_reset_txdma_channel")); 245 246 handle = NXGE_DEV_NPI_HANDLE(nxgep); 247 if ((reg_data & TX_CS_RST_MASK) == TX_CS_RST_MASK) { 248 rs = npi_txdma_channel_reset(handle, channel); 249 } else { 250 rs = npi_txdma_channel_control(handle, TXDMA_RESET, 251 channel); 252 } 253 254 if (rs != NPI_SUCCESS) { 255 status = NXGE_ERROR | rs; 256 } 257 258 /* 259 * Reset the tail (kick) register to 0. 260 * (Hardware will not reset it. Tx overflow fatal 261 * error if tail is not set to 0 after reset! 262 */ 263 TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, 0); 264 265 NXGE_DEBUG_MSG((nxgep, TX_CTL, " <== nxge_reset_txdma_channel")); 266 return (status); 267 } 268 269 /* 270 * nxge_init_txdma_channel_event_mask 271 * 272 * Enable interrupts for a set of events. 273 * 274 * Arguments: 275 * nxgep 276 * channel The channel to map. 277 * mask_p The events to enable. 278 * 279 * Notes: 280 * 281 * NPI/NXGE function calls: 282 * npi_txdma_event_mask() 283 * 284 * Registers accessed: 285 * TX_ENT_MSK DMC+0x40020 Transmit Event Mask 286 * 287 * Context: 288 * Any domain 289 */ 290 nxge_status_t 291 nxge_init_txdma_channel_event_mask(p_nxge_t nxgep, uint16_t channel, 292 p_tx_dma_ent_msk_t mask_p) 293 { 294 npi_handle_t handle; 295 npi_status_t rs = NPI_SUCCESS; 296 nxge_status_t status = NXGE_OK; 297 298 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 299 "<== nxge_init_txdma_channel_event_mask")); 300 301 handle = NXGE_DEV_NPI_HANDLE(nxgep); 302 rs = npi_txdma_event_mask(handle, OP_SET, channel, mask_p); 303 if (rs != NPI_SUCCESS) { 304 status = NXGE_ERROR | rs; 305 } 306 307 return (status); 308 } 309 310 /* 311 * nxge_init_txdma_channel_cntl_stat 312 * 313 * Stop a TDC. If at first we don't succeed, inject an error. 314 * 315 * Arguments: 316 * nxgep 317 * channel The channel to stop. 318 * 319 * Notes: 320 * 321 * NPI/NXGE function calls: 322 * npi_txdma_control_status() 323 * 324 * Registers accessed: 325 * TX_CS DMC+0x40028 Transmit Control And Status 326 * 327 * Context: 328 * Any domain 329 */ 330 nxge_status_t 331 nxge_init_txdma_channel_cntl_stat(p_nxge_t nxgep, uint16_t channel, 332 uint64_t reg_data) 333 { 334 npi_handle_t handle; 335 npi_status_t rs = NPI_SUCCESS; 336 nxge_status_t status = NXGE_OK; 337 338 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 339 "<== nxge_init_txdma_channel_cntl_stat")); 340 341 handle = NXGE_DEV_NPI_HANDLE(nxgep); 342 rs = npi_txdma_control_status(handle, OP_SET, channel, 343 (p_tx_cs_t)®_data); 344 345 if (rs != NPI_SUCCESS) { 346 status = NXGE_ERROR | rs; 347 } 348 349 return (status); 350 } 351 352 /* 353 * nxge_enable_txdma_channel 354 * 355 * Enable a TDC. 356 * 357 * Arguments: 358 * nxgep 359 * channel The channel to enable. 360 * tx_desc_p channel's transmit descriptor ring. 361 * mbox_p channel's mailbox, 362 * 363 * Notes: 364 * 365 * NPI/NXGE function calls: 366 * npi_txdma_ring_config() 367 * npi_txdma_mbox_config() 368 * npi_txdma_channel_init_enable() 369 * 370 * Registers accessed: 371 * TX_RNG_CFIG DMC+0x40000 Transmit Ring Configuration 372 * TXDMA_MBH DMC+0x40030 TXDMA Mailbox High 373 * TXDMA_MBL DMC+0x40038 TXDMA Mailbox Low 374 * TX_CS DMC+0x40028 Transmit Control And Status 375 * 376 * Context: 377 * Any domain 378 */ 379 nxge_status_t 380 nxge_enable_txdma_channel(p_nxge_t nxgep, 381 uint16_t channel, p_tx_ring_t tx_desc_p, p_tx_mbox_t mbox_p) 382 { 383 npi_handle_t handle; 384 npi_status_t rs = NPI_SUCCESS; 385 nxge_status_t status = NXGE_OK; 386 387 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_enable_txdma_channel")); 388 389 handle = NXGE_DEV_NPI_HANDLE(nxgep); 390 /* 391 * Use configuration data composed at init time. 392 * Write to hardware the transmit ring configurations. 393 */ 394 rs = npi_txdma_ring_config(handle, OP_SET, channel, 395 (uint64_t *)&(tx_desc_p->tx_ring_cfig.value)); 396 397 if (rs != NPI_SUCCESS) { 398 return (NXGE_ERROR | rs); 399 } 400 401 if (isLDOMguest(nxgep)) { 402 /* Add interrupt handler for this channel. */ 403 if (nxge_hio_intr_add(nxgep, VP_BOUND_TX, channel) != NXGE_OK) 404 return (NXGE_ERROR); 405 } 406 407 /* Write to hardware the mailbox */ 408 rs = npi_txdma_mbox_config(handle, OP_SET, channel, 409 (uint64_t *)&mbox_p->tx_mbox.dma_cookie.dmac_laddress); 410 411 if (rs != NPI_SUCCESS) { 412 return (NXGE_ERROR | rs); 413 } 414 415 /* Start the DMA engine. */ 416 rs = npi_txdma_channel_init_enable(handle, channel); 417 418 if (rs != NPI_SUCCESS) { 419 return (NXGE_ERROR | rs); 420 } 421 422 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_enable_txdma_channel")); 423 424 return (status); 425 } 426 427 void 428 nxge_fill_tx_hdr(p_mblk_t mp, boolean_t fill_len, 429 boolean_t l4_cksum, int pkt_len, uint8_t npads, 430 p_tx_pkt_hdr_all_t pkthdrp, 431 t_uscalar_t start_offset, 432 t_uscalar_t stuff_offset) 433 { 434 p_tx_pkt_header_t hdrp; 435 p_mblk_t nmp; 436 uint64_t tmp; 437 size_t mblk_len; 438 size_t iph_len; 439 size_t hdrs_size; 440 uint8_t hdrs_buf[sizeof (struct ether_header) + 441 64 + sizeof (uint32_t)]; 442 uint8_t *cursor; 443 uint8_t *ip_buf; 444 uint16_t eth_type; 445 uint8_t ipproto; 446 boolean_t is_vlan = B_FALSE; 447 size_t eth_hdr_size; 448 449 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: mp $%p", mp)); 450 451 /* 452 * Caller should zero out the headers first. 453 */ 454 hdrp = (p_tx_pkt_header_t)&pkthdrp->pkthdr; 455 456 if (fill_len) { 457 NXGE_DEBUG_MSG((NULL, TX_CTL, 458 "==> nxge_fill_tx_hdr: pkt_len %d " 459 "npads %d", pkt_len, npads)); 460 tmp = (uint64_t)pkt_len; 461 hdrp->value |= (tmp << TX_PKT_HEADER_TOT_XFER_LEN_SHIFT); 462 goto fill_tx_header_done; 463 } 464 465 hdrp->value |= (((uint64_t)npads) << TX_PKT_HEADER_PAD_SHIFT); 466 467 /* 468 * mp is the original data packet (does not include the 469 * Neptune transmit header). 470 */ 471 nmp = mp; 472 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: " 473 "mp $%p b_rptr $%p len %d", 474 mp, nmp->b_rptr, MBLKL(nmp))); 475 /* copy ether_header from mblk to hdrs_buf */ 476 cursor = &hdrs_buf[0]; 477 tmp = sizeof (struct ether_vlan_header); 478 while ((nmp != NULL) && (tmp > 0)) { 479 size_t buflen; 480 mblk_len = MBLKL(nmp); 481 buflen = min((size_t)tmp, mblk_len); 482 bcopy(nmp->b_rptr, cursor, buflen); 483 cursor += buflen; 484 tmp -= buflen; 485 nmp = nmp->b_cont; 486 } 487 488 nmp = mp; 489 mblk_len = MBLKL(nmp); 490 ip_buf = NULL; 491 eth_type = ntohs(((p_ether_header_t)hdrs_buf)->ether_type); 492 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> : nxge_fill_tx_hdr: (value 0x%llx) " 493 "ether type 0x%x", eth_type, hdrp->value)); 494 495 if (eth_type < ETHERMTU) { 496 tmp = 1ull; 497 hdrp->value |= (tmp << TX_PKT_HEADER_LLC_SHIFT); 498 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: LLC " 499 "value 0x%llx", hdrp->value)); 500 if (*(hdrs_buf + sizeof (struct ether_header)) 501 == LLC_SNAP_SAP) { 502 eth_type = ntohs(*((uint16_t *)(hdrs_buf + 503 sizeof (struct ether_header) + 6))); 504 NXGE_DEBUG_MSG((NULL, TX_CTL, 505 "==> nxge_tx_pkt_hdr_init: LLC ether type 0x%x", 506 eth_type)); 507 } else { 508 goto fill_tx_header_done; 509 } 510 } else if (eth_type == VLAN_ETHERTYPE) { 511 tmp = 1ull; 512 hdrp->value |= (tmp << TX_PKT_HEADER_VLAN__SHIFT); 513 514 eth_type = ntohs(((struct ether_vlan_header *) 515 hdrs_buf)->ether_type); 516 is_vlan = B_TRUE; 517 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: VLAN " 518 "value 0x%llx", hdrp->value)); 519 } 520 521 if (!is_vlan) { 522 eth_hdr_size = sizeof (struct ether_header); 523 } else { 524 eth_hdr_size = sizeof (struct ether_vlan_header); 525 } 526 527 switch (eth_type) { 528 case ETHERTYPE_IP: 529 if (mblk_len > eth_hdr_size + sizeof (uint8_t)) { 530 ip_buf = nmp->b_rptr + eth_hdr_size; 531 mblk_len -= eth_hdr_size; 532 iph_len = ((*ip_buf) & 0x0f); 533 if (mblk_len > (iph_len + sizeof (uint32_t))) { 534 ip_buf = nmp->b_rptr; 535 ip_buf += eth_hdr_size; 536 } else { 537 ip_buf = NULL; 538 } 539 540 } 541 if (ip_buf == NULL) { 542 hdrs_size = 0; 543 ((p_ether_header_t)hdrs_buf)->ether_type = 0; 544 while ((nmp) && (hdrs_size < 545 sizeof (hdrs_buf))) { 546 mblk_len = (size_t)nmp->b_wptr - 547 (size_t)nmp->b_rptr; 548 if (mblk_len >= 549 (sizeof (hdrs_buf) - hdrs_size)) 550 mblk_len = sizeof (hdrs_buf) - 551 hdrs_size; 552 bcopy(nmp->b_rptr, 553 &hdrs_buf[hdrs_size], mblk_len); 554 hdrs_size += mblk_len; 555 nmp = nmp->b_cont; 556 } 557 ip_buf = hdrs_buf; 558 ip_buf += eth_hdr_size; 559 iph_len = ((*ip_buf) & 0x0f); 560 } 561 562 ipproto = ip_buf[9]; 563 564 tmp = (uint64_t)iph_len; 565 hdrp->value |= (tmp << TX_PKT_HEADER_IHL_SHIFT); 566 tmp = (uint64_t)(eth_hdr_size >> 1); 567 hdrp->value |= (tmp << TX_PKT_HEADER_L3START_SHIFT); 568 569 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: IPv4 " 570 " iph_len %d l3start %d eth_hdr_size %d proto 0x%x" 571 "tmp 0x%x", 572 iph_len, hdrp->bits.hdw.l3start, eth_hdr_size, 573 ipproto, tmp)); 574 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: IP " 575 "value 0x%llx", hdrp->value)); 576 577 break; 578 579 case ETHERTYPE_IPV6: 580 hdrs_size = 0; 581 ((p_ether_header_t)hdrs_buf)->ether_type = 0; 582 while ((nmp) && (hdrs_size < 583 sizeof (hdrs_buf))) { 584 mblk_len = (size_t)nmp->b_wptr - (size_t)nmp->b_rptr; 585 if (mblk_len >= 586 (sizeof (hdrs_buf) - hdrs_size)) 587 mblk_len = sizeof (hdrs_buf) - 588 hdrs_size; 589 bcopy(nmp->b_rptr, 590 &hdrs_buf[hdrs_size], mblk_len); 591 hdrs_size += mblk_len; 592 nmp = nmp->b_cont; 593 } 594 ip_buf = hdrs_buf; 595 ip_buf += eth_hdr_size; 596 597 tmp = 1ull; 598 hdrp->value |= (tmp << TX_PKT_HEADER_IP_VER_SHIFT); 599 600 tmp = (eth_hdr_size >> 1); 601 hdrp->value |= (tmp << TX_PKT_HEADER_L3START_SHIFT); 602 603 /* byte 6 is the next header protocol */ 604 ipproto = ip_buf[6]; 605 606 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: IPv6 " 607 " iph_len %d l3start %d eth_hdr_size %d proto 0x%x", 608 iph_len, hdrp->bits.hdw.l3start, eth_hdr_size, 609 ipproto)); 610 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: IPv6 " 611 "value 0x%llx", hdrp->value)); 612 613 break; 614 615 default: 616 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: non-IP")); 617 goto fill_tx_header_done; 618 } 619 620 switch (ipproto) { 621 case IPPROTO_TCP: 622 NXGE_DEBUG_MSG((NULL, TX_CTL, 623 "==> nxge_fill_tx_hdr: TCP (cksum flag %d)", l4_cksum)); 624 if (l4_cksum) { 625 hdrp->value |= TX_CKSUM_EN_PKT_TYPE_TCP; 626 hdrp->value |= 627 (((uint64_t)(start_offset >> 1)) << 628 TX_PKT_HEADER_L4START_SHIFT); 629 hdrp->value |= 630 (((uint64_t)(stuff_offset >> 1)) << 631 TX_PKT_HEADER_L4STUFF_SHIFT); 632 633 NXGE_DEBUG_MSG((NULL, TX_CTL, 634 "==> nxge_tx_pkt_hdr_init: TCP CKSUM " 635 "value 0x%llx", hdrp->value)); 636 } 637 638 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: TCP " 639 "value 0x%llx", hdrp->value)); 640 break; 641 642 case IPPROTO_UDP: 643 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: UDP")); 644 if (l4_cksum) { 645 if (!nxge_cksum_offload) { 646 uint16_t *up; 647 uint16_t cksum; 648 t_uscalar_t stuff_len; 649 650 /* 651 * The checksum field has the 652 * partial checksum. 653 * IP_CSUM() macro calls ip_cksum() which 654 * can add in the partial checksum. 655 */ 656 cksum = IP_CSUM(mp, start_offset, 0); 657 stuff_len = stuff_offset; 658 nmp = mp; 659 mblk_len = MBLKL(nmp); 660 while ((nmp != NULL) && 661 (mblk_len < stuff_len)) { 662 stuff_len -= mblk_len; 663 nmp = nmp->b_cont; 664 } 665 ASSERT(nmp); 666 up = (uint16_t *)(nmp->b_rptr + stuff_len); 667 668 *up = cksum; 669 hdrp->value &= ~TX_CKSUM_EN_PKT_TYPE_UDP; 670 NXGE_DEBUG_MSG((NULL, TX_CTL, 671 "==> nxge_tx_pkt_hdr_init: UDP offset %d " 672 "use sw cksum " 673 "write to $%p cksum 0x%x content up 0x%x", 674 stuff_len, 675 up, 676 cksum, 677 *up)); 678 } else { 679 /* Hardware will compute the full checksum */ 680 hdrp->value |= TX_CKSUM_EN_PKT_TYPE_UDP; 681 hdrp->value |= 682 (((uint64_t)(start_offset >> 1)) << 683 TX_PKT_HEADER_L4START_SHIFT); 684 hdrp->value |= 685 (((uint64_t)(stuff_offset >> 1)) << 686 TX_PKT_HEADER_L4STUFF_SHIFT); 687 688 NXGE_DEBUG_MSG((NULL, TX_CTL, 689 "==> nxge_tx_pkt_hdr_init: UDP offset %d " 690 " use partial checksum " 691 "cksum 0x%x ", 692 "value 0x%llx", 693 stuff_offset, 694 IP_CSUM(mp, start_offset, 0), 695 hdrp->value)); 696 } 697 } 698 699 NXGE_DEBUG_MSG((NULL, TX_CTL, 700 "==> nxge_tx_pkt_hdr_init: UDP" 701 "value 0x%llx", hdrp->value)); 702 break; 703 704 default: 705 goto fill_tx_header_done; 706 } 707 708 fill_tx_header_done: 709 NXGE_DEBUG_MSG((NULL, TX_CTL, 710 "==> nxge_fill_tx_hdr: pkt_len %d " 711 "npads %d value 0x%llx", pkt_len, npads, hdrp->value)); 712 713 NXGE_DEBUG_MSG((NULL, TX_CTL, "<== nxge_fill_tx_hdr")); 714 } 715 716 /*ARGSUSED*/ 717 p_mblk_t 718 nxge_tx_pkt_header_reserve(p_mblk_t mp, uint8_t *npads) 719 { 720 p_mblk_t newmp = NULL; 721 722 if ((newmp = allocb(TX_PKT_HEADER_SIZE, BPRI_MED)) == NULL) { 723 NXGE_DEBUG_MSG((NULL, TX_CTL, 724 "<== nxge_tx_pkt_header_reserve: allocb failed")); 725 return (NULL); 726 } 727 728 NXGE_DEBUG_MSG((NULL, TX_CTL, 729 "==> nxge_tx_pkt_header_reserve: get new mp")); 730 DB_TYPE(newmp) = M_DATA; 731 newmp->b_rptr = newmp->b_wptr = DB_LIM(newmp); 732 linkb(newmp, mp); 733 newmp->b_rptr -= TX_PKT_HEADER_SIZE; 734 735 NXGE_DEBUG_MSG((NULL, TX_CTL, "==>nxge_tx_pkt_header_reserve: " 736 "b_rptr $%p b_wptr $%p", 737 newmp->b_rptr, newmp->b_wptr)); 738 739 NXGE_DEBUG_MSG((NULL, TX_CTL, 740 "<== nxge_tx_pkt_header_reserve: use new mp")); 741 742 return (newmp); 743 } 744 745 int 746 nxge_tx_pkt_nmblocks(p_mblk_t mp, int *tot_xfer_len_p) 747 { 748 uint_t nmblks; 749 ssize_t len; 750 uint_t pkt_len; 751 p_mblk_t nmp, bmp, tmp; 752 uint8_t *b_wptr; 753 754 NXGE_DEBUG_MSG((NULL, TX_CTL, 755 "==> nxge_tx_pkt_nmblocks: mp $%p rptr $%p wptr $%p " 756 "len %d", mp, mp->b_rptr, mp->b_wptr, MBLKL(mp))); 757 758 nmp = mp; 759 bmp = mp; 760 nmblks = 0; 761 pkt_len = 0; 762 *tot_xfer_len_p = 0; 763 764 while (nmp) { 765 len = MBLKL(nmp); 766 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_nmblocks: " 767 "len %d pkt_len %d nmblks %d tot_xfer_len %d", 768 len, pkt_len, nmblks, 769 *tot_xfer_len_p)); 770 771 if (len <= 0) { 772 bmp = nmp; 773 nmp = nmp->b_cont; 774 NXGE_DEBUG_MSG((NULL, TX_CTL, 775 "==> nxge_tx_pkt_nmblocks: " 776 "len (0) pkt_len %d nmblks %d", 777 pkt_len, nmblks)); 778 continue; 779 } 780 781 *tot_xfer_len_p += len; 782 NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_nmblocks: " 783 "len %d pkt_len %d nmblks %d tot_xfer_len %d", 784 len, pkt_len, nmblks, 785 *tot_xfer_len_p)); 786 787 if (len < nxge_bcopy_thresh) { 788 NXGE_DEBUG_MSG((NULL, TX_CTL, 789 "==> nxge_tx_pkt_nmblocks: " 790 "len %d (< thresh) pkt_len %d nmblks %d", 791 len, pkt_len, nmblks)); 792 if (pkt_len == 0) 793 nmblks++; 794 pkt_len += len; 795 if (pkt_len >= nxge_bcopy_thresh) { 796 pkt_len = 0; 797 len = 0; 798 nmp = bmp; 799 } 800 } else { 801 NXGE_DEBUG_MSG((NULL, TX_CTL, 802 "==> nxge_tx_pkt_nmblocks: " 803 "len %d (> thresh) pkt_len %d nmblks %d", 804 len, pkt_len, nmblks)); 805 pkt_len = 0; 806 nmblks++; 807 /* 808 * Hardware limits the transfer length to 4K. 809 * If len is more than 4K, we need to break 810 * it up to at most 2 more blocks. 811 */ 812 if (len > TX_MAX_TRANSFER_LENGTH) { 813 uint32_t nsegs; 814 815 nsegs = 1; 816 NXGE_DEBUG_MSG((NULL, TX_CTL, 817 "==> nxge_tx_pkt_nmblocks: " 818 "len %d pkt_len %d nmblks %d nsegs %d", 819 len, pkt_len, nmblks, nsegs)); 820 if (len % (TX_MAX_TRANSFER_LENGTH * 2)) { 821 ++nsegs; 822 } 823 do { 824 b_wptr = nmp->b_rptr + 825 TX_MAX_TRANSFER_LENGTH; 826 nmp->b_wptr = b_wptr; 827 if ((tmp = dupb(nmp)) == NULL) { 828 return (0); 829 } 830 tmp->b_rptr = b_wptr; 831 tmp->b_wptr = nmp->b_wptr; 832 tmp->b_cont = nmp->b_cont; 833 nmp->b_cont = tmp; 834 nmblks++; 835 if (--nsegs) { 836 nmp = tmp; 837 } 838 } while (nsegs); 839 nmp = tmp; 840 } 841 } 842 843 /* 844 * Hardware limits the transmit gather pointers to 15. 845 */ 846 if (nmp->b_cont && (nmblks + TX_GATHER_POINTERS_THRESHOLD) > 847 TX_MAX_GATHER_POINTERS) { 848 NXGE_DEBUG_MSG((NULL, TX_CTL, 849 "==> nxge_tx_pkt_nmblocks: pull msg - " 850 "len %d pkt_len %d nmblks %d", 851 len, pkt_len, nmblks)); 852 /* Pull all message blocks from b_cont */ 853 if ((tmp = msgpullup(nmp->b_cont, -1)) == NULL) { 854 return (0); 855 } 856 freemsg(nmp->b_cont); 857 nmp->b_cont = tmp; 858 pkt_len = 0; 859 } 860 bmp = nmp; 861 nmp = nmp->b_cont; 862 } 863 864 NXGE_DEBUG_MSG((NULL, TX_CTL, 865 "<== nxge_tx_pkt_nmblocks: rptr $%p wptr $%p " 866 "nmblks %d len %d tot_xfer_len %d", 867 mp->b_rptr, mp->b_wptr, nmblks, 868 MBLKL(mp), *tot_xfer_len_p)); 869 870 return (nmblks); 871 } 872 873 boolean_t 874 nxge_txdma_reclaim(p_nxge_t nxgep, p_tx_ring_t tx_ring_p, int nmblks) 875 { 876 boolean_t status = B_TRUE; 877 p_nxge_dma_common_t tx_desc_dma_p; 878 nxge_dma_common_t desc_area; 879 p_tx_desc_t tx_desc_ring_vp; 880 p_tx_desc_t tx_desc_p; 881 p_tx_desc_t tx_desc_pp; 882 tx_desc_t r_tx_desc; 883 p_tx_msg_t tx_msg_ring; 884 p_tx_msg_t tx_msg_p; 885 npi_handle_t handle; 886 tx_ring_hdl_t tx_head; 887 uint32_t pkt_len; 888 uint_t tx_rd_index; 889 uint16_t head_index, tail_index; 890 uint8_t tdc; 891 boolean_t head_wrap, tail_wrap; 892 p_nxge_tx_ring_stats_t tdc_stats; 893 int rc; 894 895 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_reclaim")); 896 897 status = ((tx_ring_p->descs_pending < nxge_reclaim_pending) && 898 (nmblks != 0)); 899 NXGE_DEBUG_MSG((nxgep, TX_CTL, 900 "==> nxge_txdma_reclaim: pending %d reclaim %d nmblks %d", 901 tx_ring_p->descs_pending, nxge_reclaim_pending, 902 nmblks)); 903 if (!status) { 904 tx_desc_dma_p = &tx_ring_p->tdc_desc; 905 desc_area = tx_ring_p->tdc_desc; 906 handle = NXGE_DEV_NPI_HANDLE(nxgep); 907 tx_desc_ring_vp = tx_desc_dma_p->kaddrp; 908 tx_desc_ring_vp = 909 (p_tx_desc_t)DMA_COMMON_VPTR(desc_area); 910 tx_rd_index = tx_ring_p->rd_index; 911 tx_desc_p = &tx_desc_ring_vp[tx_rd_index]; 912 tx_msg_ring = tx_ring_p->tx_msg_ring; 913 tx_msg_p = &tx_msg_ring[tx_rd_index]; 914 tdc = tx_ring_p->tdc; 915 tdc_stats = tx_ring_p->tdc_stats; 916 if (tx_ring_p->descs_pending > tdc_stats->tx_max_pend) { 917 tdc_stats->tx_max_pend = tx_ring_p->descs_pending; 918 } 919 920 tail_index = tx_ring_p->wr_index; 921 tail_wrap = tx_ring_p->wr_index_wrap; 922 923 NXGE_DEBUG_MSG((nxgep, TX_CTL, 924 "==> nxge_txdma_reclaim: tdc %d tx_rd_index %d " 925 "tail_index %d tail_wrap %d " 926 "tx_desc_p $%p ($%p) ", 927 tdc, tx_rd_index, tail_index, tail_wrap, 928 tx_desc_p, (*(uint64_t *)tx_desc_p))); 929 /* 930 * Read the hardware maintained transmit head 931 * and wrap around bit. 932 */ 933 TXDMA_REG_READ64(handle, TX_RING_HDL_REG, tdc, &tx_head.value); 934 head_index = tx_head.bits.ldw.head; 935 head_wrap = tx_head.bits.ldw.wrap; 936 NXGE_DEBUG_MSG((nxgep, TX_CTL, 937 "==> nxge_txdma_reclaim: " 938 "tx_rd_index %d tail %d tail_wrap %d " 939 "head %d wrap %d", 940 tx_rd_index, tail_index, tail_wrap, 941 head_index, head_wrap)); 942 943 if (head_index == tail_index) { 944 if (TXDMA_RING_EMPTY(head_index, head_wrap, 945 tail_index, tail_wrap) && 946 (head_index == tx_rd_index)) { 947 NXGE_DEBUG_MSG((nxgep, TX_CTL, 948 "==> nxge_txdma_reclaim: EMPTY")); 949 return (B_TRUE); 950 } 951 952 NXGE_DEBUG_MSG((nxgep, TX_CTL, 953 "==> nxge_txdma_reclaim: Checking " 954 "if ring full")); 955 if (TXDMA_RING_FULL(head_index, head_wrap, tail_index, 956 tail_wrap)) { 957 NXGE_DEBUG_MSG((nxgep, TX_CTL, 958 "==> nxge_txdma_reclaim: full")); 959 return (B_FALSE); 960 } 961 } 962 963 NXGE_DEBUG_MSG((nxgep, TX_CTL, 964 "==> nxge_txdma_reclaim: tx_rd_index and head_index")); 965 966 tx_desc_pp = &r_tx_desc; 967 while ((tx_rd_index != head_index) && 968 (tx_ring_p->descs_pending != 0)) { 969 970 NXGE_DEBUG_MSG((nxgep, TX_CTL, 971 "==> nxge_txdma_reclaim: Checking if pending")); 972 973 NXGE_DEBUG_MSG((nxgep, TX_CTL, 974 "==> nxge_txdma_reclaim: " 975 "descs_pending %d ", 976 tx_ring_p->descs_pending)); 977 978 NXGE_DEBUG_MSG((nxgep, TX_CTL, 979 "==> nxge_txdma_reclaim: " 980 "(tx_rd_index %d head_index %d " 981 "(tx_desc_p $%p)", 982 tx_rd_index, head_index, 983 tx_desc_p)); 984 985 tx_desc_pp->value = tx_desc_p->value; 986 NXGE_DEBUG_MSG((nxgep, TX_CTL, 987 "==> nxge_txdma_reclaim: " 988 "(tx_rd_index %d head_index %d " 989 "tx_desc_p $%p (desc value 0x%llx) ", 990 tx_rd_index, head_index, 991 tx_desc_pp, (*(uint64_t *)tx_desc_pp))); 992 993 NXGE_DEBUG_MSG((nxgep, TX_CTL, 994 "==> nxge_txdma_reclaim: dump desc:")); 995 996 pkt_len = tx_desc_pp->bits.hdw.tr_len; 997 tdc_stats->obytes += pkt_len; 998 tdc_stats->opackets += tx_desc_pp->bits.hdw.sop; 999 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1000 "==> nxge_txdma_reclaim: pkt_len %d " 1001 "tdc channel %d opackets %d", 1002 pkt_len, 1003 tdc, 1004 tdc_stats->opackets)); 1005 1006 if (tx_msg_p->flags.dma_type == USE_DVMA) { 1007 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1008 "tx_desc_p = $%p " 1009 "tx_desc_pp = $%p " 1010 "index = %d", 1011 tx_desc_p, 1012 tx_desc_pp, 1013 tx_ring_p->rd_index)); 1014 (void) dvma_unload(tx_msg_p->dvma_handle, 1015 0, -1); 1016 tx_msg_p->dvma_handle = NULL; 1017 if (tx_ring_p->dvma_wr_index == 1018 tx_ring_p->dvma_wrap_mask) { 1019 tx_ring_p->dvma_wr_index = 0; 1020 } else { 1021 tx_ring_p->dvma_wr_index++; 1022 } 1023 tx_ring_p->dvma_pending--; 1024 } else if (tx_msg_p->flags.dma_type == 1025 USE_DMA) { 1026 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1027 "==> nxge_txdma_reclaim: " 1028 "USE DMA")); 1029 if (rc = ddi_dma_unbind_handle 1030 (tx_msg_p->dma_handle)) { 1031 cmn_err(CE_WARN, "!nxge_reclaim: " 1032 "ddi_dma_unbind_handle " 1033 "failed. status %d", rc); 1034 } 1035 } 1036 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1037 "==> nxge_txdma_reclaim: count packets")); 1038 /* 1039 * count a chained packet only once. 1040 */ 1041 if (tx_msg_p->tx_message != NULL) { 1042 freemsg(tx_msg_p->tx_message); 1043 tx_msg_p->tx_message = NULL; 1044 } 1045 1046 tx_msg_p->flags.dma_type = USE_NONE; 1047 tx_rd_index = tx_ring_p->rd_index; 1048 tx_rd_index = (tx_rd_index + 1) & 1049 tx_ring_p->tx_wrap_mask; 1050 tx_ring_p->rd_index = tx_rd_index; 1051 tx_ring_p->descs_pending--; 1052 tx_desc_p = &tx_desc_ring_vp[tx_rd_index]; 1053 tx_msg_p = &tx_msg_ring[tx_rd_index]; 1054 } 1055 1056 status = (nmblks <= (tx_ring_p->tx_ring_size - 1057 tx_ring_p->descs_pending - 1058 TX_FULL_MARK)); 1059 if (status) { 1060 cas32((uint32_t *)&tx_ring_p->queueing, 1, 0); 1061 } 1062 } else { 1063 status = (nmblks <= 1064 (tx_ring_p->tx_ring_size - 1065 tx_ring_p->descs_pending - 1066 TX_FULL_MARK)); 1067 } 1068 1069 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1070 "<== nxge_txdma_reclaim status = 0x%08x", status)); 1071 1072 return (status); 1073 } 1074 1075 /* 1076 * nxge_tx_intr 1077 * 1078 * Process a TDC interrupt 1079 * 1080 * Arguments: 1081 * arg1 A Logical Device state Vector (LSV) data structure. 1082 * arg2 nxge_t * 1083 * 1084 * Notes: 1085 * 1086 * NPI/NXGE function calls: 1087 * npi_txdma_control_status() 1088 * npi_intr_ldg_mgmt_set() 1089 * 1090 * nxge_tx_err_evnts() 1091 * nxge_txdma_reclaim() 1092 * 1093 * Registers accessed: 1094 * TX_CS DMC+0x40028 Transmit Control And Status 1095 * PIO_LDSV 1096 * 1097 * Context: 1098 * Any domain 1099 */ 1100 uint_t 1101 nxge_tx_intr(void *arg1, void *arg2) 1102 { 1103 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 1104 p_nxge_t nxgep = (p_nxge_t)arg2; 1105 p_nxge_ldg_t ldgp; 1106 uint8_t channel; 1107 uint32_t vindex; 1108 npi_handle_t handle; 1109 tx_cs_t cs; 1110 p_tx_ring_t *tx_rings; 1111 p_tx_ring_t tx_ring_p; 1112 npi_status_t rs = NPI_SUCCESS; 1113 uint_t serviced = DDI_INTR_UNCLAIMED; 1114 nxge_status_t status = NXGE_OK; 1115 1116 if (ldvp == NULL) { 1117 NXGE_DEBUG_MSG((NULL, INT_CTL, 1118 "<== nxge_tx_intr: nxgep $%p ldvp $%p", 1119 nxgep, ldvp)); 1120 return (DDI_INTR_UNCLAIMED); 1121 } 1122 1123 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 1124 nxgep = ldvp->nxgep; 1125 } 1126 NXGE_DEBUG_MSG((nxgep, INT_CTL, 1127 "==> nxge_tx_intr: nxgep(arg2) $%p ldvp(arg1) $%p", 1128 nxgep, ldvp)); 1129 1130 if ((!(nxgep->drv_state & STATE_HW_INITIALIZED)) || 1131 (nxgep->nxge_mac_state != NXGE_MAC_STARTED)) { 1132 NXGE_DEBUG_MSG((nxgep, INT_CTL, 1133 "<== nxge_tx_intr: interface not started or intialized")); 1134 return (DDI_INTR_CLAIMED); 1135 } 1136 1137 /* 1138 * This interrupt handler is for a specific 1139 * transmit dma channel. 1140 */ 1141 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1142 /* Get the control and status for this channel. */ 1143 channel = ldvp->channel; 1144 ldgp = ldvp->ldgp; 1145 NXGE_DEBUG_MSG((nxgep, INT_CTL, 1146 "==> nxge_tx_intr: nxgep $%p ldvp (ldvp) $%p " 1147 "channel %d", 1148 nxgep, ldvp, channel)); 1149 1150 rs = npi_txdma_control_status(handle, OP_GET, channel, &cs); 1151 vindex = ldvp->vdma_index; 1152 NXGE_DEBUG_MSG((nxgep, INT_CTL, 1153 "==> nxge_tx_intr:channel %d ring index %d status 0x%08x", 1154 channel, vindex, rs)); 1155 if (!rs && cs.bits.ldw.mk) { 1156 NXGE_DEBUG_MSG((nxgep, INT_CTL, 1157 "==> nxge_tx_intr:channel %d ring index %d " 1158 "status 0x%08x (mk bit set)", 1159 channel, vindex, rs)); 1160 tx_rings = nxgep->tx_rings->rings; 1161 tx_ring_p = tx_rings[vindex]; 1162 NXGE_DEBUG_MSG((nxgep, INT_CTL, 1163 "==> nxge_tx_intr:channel %d ring index %d " 1164 "status 0x%08x (mk bit set, calling reclaim)", 1165 channel, vindex, rs)); 1166 1167 MUTEX_ENTER(&tx_ring_p->lock); 1168 (void) nxge_txdma_reclaim(nxgep, tx_rings[vindex], 0); 1169 MUTEX_EXIT(&tx_ring_p->lock); 1170 mac_tx_update(nxgep->mach); 1171 } 1172 1173 /* 1174 * Process other transmit control and status. 1175 * Check the ldv state. 1176 */ 1177 status = nxge_tx_err_evnts(nxgep, ldvp->vdma_index, ldvp, cs); 1178 /* 1179 * Rearm this logical group if this is a single device 1180 * group. 1181 */ 1182 if (ldgp->nldvs == 1) { 1183 NXGE_DEBUG_MSG((nxgep, INT_CTL, 1184 "==> nxge_tx_intr: rearm")); 1185 if (status == NXGE_OK) { 1186 if (isLDOMguest(nxgep)) { 1187 nxge_hio_ldgimgn(nxgep, ldgp); 1188 } else { 1189 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 1190 B_TRUE, ldgp->ldg_timer); 1191 } 1192 } 1193 } 1194 1195 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_tx_intr")); 1196 serviced = DDI_INTR_CLAIMED; 1197 return (serviced); 1198 } 1199 1200 void 1201 nxge_txdma_stop(p_nxge_t nxgep) /* Dead */ 1202 { 1203 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop")); 1204 1205 (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 1206 1207 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop")); 1208 } 1209 1210 void 1211 nxge_txdma_stop_start(p_nxge_t nxgep) /* Dead */ 1212 { 1213 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop_start")); 1214 1215 (void) nxge_txdma_stop(nxgep); 1216 1217 (void) nxge_fixup_txdma_rings(nxgep); 1218 (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START); 1219 (void) nxge_tx_mac_enable(nxgep); 1220 (void) nxge_txdma_hw_kick(nxgep); 1221 1222 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop_start")); 1223 } 1224 1225 npi_status_t 1226 nxge_txdma_channel_disable( 1227 nxge_t *nxge, 1228 int channel) 1229 { 1230 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxge); 1231 npi_status_t rs; 1232 tdmc_intr_dbg_t intr_dbg; 1233 1234 /* 1235 * Stop the dma channel and wait for the stop-done. 1236 * If the stop-done bit is not present, then force 1237 * an error so TXC will stop. 1238 * All channels bound to this port need to be stopped 1239 * and reset after injecting an interrupt error. 1240 */ 1241 rs = npi_txdma_channel_disable(handle, channel); 1242 NXGE_DEBUG_MSG((nxge, MEM3_CTL, 1243 "==> nxge_txdma_channel_disable(%d) " 1244 "rs 0x%x", channel, rs)); 1245 if (rs != NPI_SUCCESS) { 1246 /* Inject any error */ 1247 intr_dbg.value = 0; 1248 intr_dbg.bits.ldw.nack_pref = 1; 1249 NXGE_DEBUG_MSG((nxge, MEM3_CTL, 1250 "==> nxge_txdma_hw_mode: " 1251 "channel %d (stop failed 0x%x) " 1252 "(inject err)", rs, channel)); 1253 (void) npi_txdma_inj_int_error_set( 1254 handle, channel, &intr_dbg); 1255 rs = npi_txdma_channel_disable(handle, channel); 1256 NXGE_DEBUG_MSG((nxge, MEM3_CTL, 1257 "==> nxge_txdma_hw_mode: " 1258 "channel %d (stop again 0x%x) " 1259 "(after inject err)", 1260 rs, channel)); 1261 } 1262 1263 return (rs); 1264 } 1265 1266 /* 1267 * nxge_txdma_hw_mode 1268 * 1269 * Toggle all TDCs on (enable) or off (disable). 1270 * 1271 * Arguments: 1272 * nxgep 1273 * enable Enable or disable a TDC. 1274 * 1275 * Notes: 1276 * 1277 * NPI/NXGE function calls: 1278 * npi_txdma_channel_enable(TX_CS) 1279 * npi_txdma_channel_disable(TX_CS) 1280 * npi_txdma_inj_int_error_set(TDMC_INTR_DBG) 1281 * 1282 * Registers accessed: 1283 * TX_CS DMC+0x40028 Transmit Control And Status 1284 * TDMC_INTR_DBG DMC + 0x40060 Transmit DMA Interrupt Debug 1285 * 1286 * Context: 1287 * Any domain 1288 */ 1289 nxge_status_t 1290 nxge_txdma_hw_mode(p_nxge_t nxgep, boolean_t enable) 1291 { 1292 nxge_grp_set_t *set = &nxgep->tx_set; 1293 1294 npi_handle_t handle; 1295 nxge_status_t status; 1296 npi_status_t rs; 1297 int tdc; 1298 1299 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 1300 "==> nxge_txdma_hw_mode: enable mode %d", enable)); 1301 1302 if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 1303 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1304 "<== nxge_txdma_mode: not initialized")); 1305 return (NXGE_ERROR); 1306 } 1307 1308 if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 1309 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1310 "<== nxge_txdma_hw_mode: NULL ring pointer(s)")); 1311 return (NXGE_ERROR); 1312 } 1313 1314 /* Enable or disable all of the TDCs owned by us. */ 1315 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1316 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 1317 if ((1 << tdc) & set->owned.map) { 1318 tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 1319 if (ring) { 1320 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 1321 "==> nxge_txdma_hw_mode: channel %d", tdc)); 1322 if (enable) { 1323 rs = npi_txdma_channel_enable 1324 (handle, tdc); 1325 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 1326 "==> nxge_txdma_hw_mode: " 1327 "channel %d (enable) rs 0x%x", 1328 tdc, rs)); 1329 } else { 1330 rs = nxge_txdma_channel_disable 1331 (nxgep, tdc); 1332 } 1333 } 1334 } 1335 } 1336 1337 status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs); 1338 1339 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 1340 "<== nxge_txdma_hw_mode: status 0x%x", status)); 1341 1342 return (status); 1343 } 1344 1345 void 1346 nxge_txdma_enable_channel(p_nxge_t nxgep, uint16_t channel) 1347 { 1348 npi_handle_t handle; 1349 1350 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1351 "==> nxge_txdma_enable_channel: channel %d", channel)); 1352 1353 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1354 /* enable the transmit dma channels */ 1355 (void) npi_txdma_channel_enable(handle, channel); 1356 1357 NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_txdma_enable_channel")); 1358 } 1359 1360 void 1361 nxge_txdma_disable_channel(p_nxge_t nxgep, uint16_t channel) 1362 { 1363 npi_handle_t handle; 1364 1365 NXGE_DEBUG_MSG((nxgep, DMA_CTL, 1366 "==> nxge_txdma_disable_channel: channel %d", channel)); 1367 1368 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1369 /* stop the transmit dma channels */ 1370 (void) npi_txdma_channel_disable(handle, channel); 1371 1372 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_disable_channel")); 1373 } 1374 1375 /* 1376 * nxge_txdma_stop_inj_err 1377 * 1378 * Stop a TDC. If at first we don't succeed, inject an error. 1379 * 1380 * Arguments: 1381 * nxgep 1382 * channel The channel to stop. 1383 * 1384 * Notes: 1385 * 1386 * NPI/NXGE function calls: 1387 * npi_txdma_channel_disable() 1388 * npi_txdma_inj_int_error_set() 1389 * #if defined(NXGE_DEBUG) 1390 * nxge_txdma_regs_dump_channels(nxgep); 1391 * #endif 1392 * 1393 * Registers accessed: 1394 * TX_CS DMC+0x40028 Transmit Control And Status 1395 * TDMC_INTR_DBG DMC + 0x40060 Transmit DMA Interrupt Debug 1396 * 1397 * Context: 1398 * Any domain 1399 */ 1400 int 1401 nxge_txdma_stop_inj_err(p_nxge_t nxgep, int channel) 1402 { 1403 npi_handle_t handle; 1404 tdmc_intr_dbg_t intr_dbg; 1405 int status; 1406 npi_status_t rs = NPI_SUCCESS; 1407 1408 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop_inj_err")); 1409 /* 1410 * Stop the dma channel waits for the stop done. 1411 * If the stop done bit is not set, then create 1412 * an error. 1413 */ 1414 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1415 rs = npi_txdma_channel_disable(handle, channel); 1416 status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs); 1417 if (status == NXGE_OK) { 1418 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1419 "<== nxge_txdma_stop_inj_err (channel %d): " 1420 "stopped OK", channel)); 1421 return (status); 1422 } 1423 1424 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1425 "==> nxge_txdma_stop_inj_err (channel %d): stop failed (0x%x) " 1426 "injecting error", channel, rs)); 1427 /* Inject any error */ 1428 intr_dbg.value = 0; 1429 intr_dbg.bits.ldw.nack_pref = 1; 1430 (void) npi_txdma_inj_int_error_set(handle, channel, &intr_dbg); 1431 1432 /* Stop done bit will be set as a result of error injection */ 1433 rs = npi_txdma_channel_disable(handle, channel); 1434 status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs); 1435 if (!(rs & NPI_TXDMA_STOP_FAILED)) { 1436 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1437 "<== nxge_txdma_stop_inj_err (channel %d): " 1438 "stopped OK ", channel)); 1439 return (status); 1440 } 1441 1442 #if defined(NXGE_DEBUG) 1443 nxge_txdma_regs_dump_channels(nxgep); 1444 #endif 1445 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1446 "==> nxge_txdma_stop_inj_err (channel): stop failed (0x%x) " 1447 " (injected error but still not stopped)", channel, rs)); 1448 1449 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop_inj_err")); 1450 return (status); 1451 } 1452 1453 /*ARGSUSED*/ 1454 void 1455 nxge_fixup_txdma_rings(p_nxge_t nxgep) 1456 { 1457 nxge_grp_set_t *set = &nxgep->tx_set; 1458 int tdc; 1459 1460 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_fixup_txdma_rings")); 1461 1462 if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 1463 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1464 "<== nxge_fixup_txdma_rings: NULL ring pointer(s)")); 1465 return; 1466 } 1467 1468 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 1469 if ((1 << tdc) & set->owned.map) { 1470 tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 1471 if (ring) { 1472 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 1473 "==> nxge_fixup_txdma_rings: channel %d", 1474 tdc)); 1475 nxge_txdma_fixup_channel(nxgep, ring, tdc); 1476 } 1477 } 1478 } 1479 1480 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_fixup_txdma_rings")); 1481 } 1482 1483 /*ARGSUSED*/ 1484 void 1485 nxge_txdma_fix_channel(p_nxge_t nxgep, uint16_t channel) 1486 { 1487 p_tx_ring_t ring_p; 1488 1489 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fix_channel")); 1490 ring_p = nxge_txdma_get_ring(nxgep, channel); 1491 if (ring_p == NULL) { 1492 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_channel")); 1493 return; 1494 } 1495 1496 if (ring_p->tdc != channel) { 1497 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1498 "<== nxge_txdma_fix_channel: channel not matched " 1499 "ring tdc %d passed channel", 1500 ring_p->tdc, channel)); 1501 return; 1502 } 1503 1504 nxge_txdma_fixup_channel(nxgep, ring_p, channel); 1505 1506 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_channel")); 1507 } 1508 1509 /*ARGSUSED*/ 1510 void 1511 nxge_txdma_fixup_channel(p_nxge_t nxgep, p_tx_ring_t ring_p, uint16_t channel) 1512 { 1513 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fixup_channel")); 1514 1515 if (ring_p == NULL) { 1516 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1517 "<== nxge_txdma_fixup_channel: NULL ring pointer")); 1518 return; 1519 } 1520 1521 if (ring_p->tdc != channel) { 1522 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1523 "<== nxge_txdma_fixup_channel: channel not matched " 1524 "ring tdc %d passed channel", 1525 ring_p->tdc, channel)); 1526 return; 1527 } 1528 1529 MUTEX_ENTER(&ring_p->lock); 1530 (void) nxge_txdma_reclaim(nxgep, ring_p, 0); 1531 ring_p->rd_index = 0; 1532 ring_p->wr_index = 0; 1533 ring_p->ring_head.value = 0; 1534 ring_p->ring_kick_tail.value = 0; 1535 ring_p->descs_pending = 0; 1536 MUTEX_EXIT(&ring_p->lock); 1537 1538 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fixup_channel")); 1539 } 1540 1541 /*ARGSUSED*/ 1542 void 1543 nxge_txdma_hw_kick(p_nxge_t nxgep) 1544 { 1545 nxge_grp_set_t *set = &nxgep->tx_set; 1546 int tdc; 1547 1548 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hw_kick")); 1549 1550 if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 1551 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1552 "<== nxge_txdma_hw_kick: NULL ring pointer(s)")); 1553 return; 1554 } 1555 1556 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 1557 if ((1 << tdc) & set->owned.map) { 1558 tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 1559 if (ring) { 1560 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 1561 "==> nxge_txdma_hw_kick: channel %d", tdc)); 1562 nxge_txdma_hw_kick_channel(nxgep, ring, tdc); 1563 } 1564 } 1565 } 1566 1567 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hw_kick")); 1568 } 1569 1570 /*ARGSUSED*/ 1571 void 1572 nxge_txdma_kick_channel(p_nxge_t nxgep, uint16_t channel) 1573 { 1574 p_tx_ring_t ring_p; 1575 1576 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_kick_channel")); 1577 1578 ring_p = nxge_txdma_get_ring(nxgep, channel); 1579 if (ring_p == NULL) { 1580 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1581 " nxge_txdma_kick_channel")); 1582 return; 1583 } 1584 1585 if (ring_p->tdc != channel) { 1586 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1587 "<== nxge_txdma_kick_channel: channel not matched " 1588 "ring tdc %d passed channel", 1589 ring_p->tdc, channel)); 1590 return; 1591 } 1592 1593 nxge_txdma_hw_kick_channel(nxgep, ring_p, channel); 1594 1595 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_kick_channel")); 1596 } 1597 1598 /*ARGSUSED*/ 1599 void 1600 nxge_txdma_hw_kick_channel(p_nxge_t nxgep, p_tx_ring_t ring_p, uint16_t channel) 1601 { 1602 1603 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hw_kick_channel")); 1604 1605 if (ring_p == NULL) { 1606 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1607 "<== nxge_txdma_hw_kick_channel: NULL ring pointer")); 1608 return; 1609 } 1610 1611 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hw_kick_channel")); 1612 } 1613 1614 /* 1615 * nxge_check_tx_hang 1616 * 1617 * Check the state of all TDCs belonging to nxgep. 1618 * 1619 * Arguments: 1620 * nxgep 1621 * 1622 * Notes: 1623 * Called by nxge_hw.c:nxge_check_hw_state(). 1624 * 1625 * NPI/NXGE function calls: 1626 * 1627 * Registers accessed: 1628 * 1629 * Context: 1630 * Any domain 1631 */ 1632 /*ARGSUSED*/ 1633 void 1634 nxge_check_tx_hang(p_nxge_t nxgep) 1635 { 1636 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_check_tx_hang")); 1637 1638 if ((!(nxgep->drv_state & STATE_HW_INITIALIZED)) || 1639 (nxgep->nxge_mac_state != NXGE_MAC_STARTED)) { 1640 goto nxge_check_tx_hang_exit; 1641 } 1642 1643 /* 1644 * Needs inputs from hardware for regs: 1645 * head index had not moved since last timeout. 1646 * packets not transmitted or stuffed registers. 1647 */ 1648 if (nxge_txdma_hung(nxgep)) { 1649 nxge_fixup_hung_txdma_rings(nxgep); 1650 } 1651 1652 nxge_check_tx_hang_exit: 1653 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_check_tx_hang")); 1654 } 1655 1656 /* 1657 * nxge_txdma_hung 1658 * 1659 * Reset a TDC. 1660 * 1661 * Arguments: 1662 * nxgep 1663 * channel The channel to reset. 1664 * reg_data The current TX_CS. 1665 * 1666 * Notes: 1667 * Called by nxge_check_tx_hang() 1668 * 1669 * NPI/NXGE function calls: 1670 * nxge_txdma_channel_hung() 1671 * 1672 * Registers accessed: 1673 * 1674 * Context: 1675 * Any domain 1676 */ 1677 int 1678 nxge_txdma_hung(p_nxge_t nxgep) 1679 { 1680 nxge_grp_set_t *set = &nxgep->tx_set; 1681 int tdc; 1682 1683 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hung")); 1684 1685 if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 1686 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1687 "<== nxge_txdma_hung: NULL ring pointer(s)")); 1688 return (B_FALSE); 1689 } 1690 1691 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 1692 if ((1 << tdc) & set->owned.map) { 1693 tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 1694 if (ring) { 1695 if (nxge_txdma_channel_hung(nxgep, ring, tdc)) { 1696 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1697 "==> nxge_txdma_hung: TDC %d hung", 1698 tdc)); 1699 return (B_TRUE); 1700 } 1701 } 1702 } 1703 } 1704 1705 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hung")); 1706 1707 return (B_FALSE); 1708 } 1709 1710 /* 1711 * nxge_txdma_channel_hung 1712 * 1713 * Reset a TDC. 1714 * 1715 * Arguments: 1716 * nxgep 1717 * ring <channel>'s ring. 1718 * channel The channel to reset. 1719 * 1720 * Notes: 1721 * Called by nxge_txdma.c:nxge_txdma_hung() 1722 * 1723 * NPI/NXGE function calls: 1724 * npi_txdma_ring_head_get() 1725 * 1726 * Registers accessed: 1727 * TX_RING_HDL DMC+0x40010 Transmit Ring Head Low 1728 * 1729 * Context: 1730 * Any domain 1731 */ 1732 int 1733 nxge_txdma_channel_hung(p_nxge_t nxgep, p_tx_ring_t tx_ring_p, uint16_t channel) 1734 { 1735 uint16_t head_index, tail_index; 1736 boolean_t head_wrap, tail_wrap; 1737 npi_handle_t handle; 1738 tx_ring_hdl_t tx_head; 1739 uint_t tx_rd_index; 1740 1741 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_channel_hung")); 1742 1743 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1744 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1745 "==> nxge_txdma_channel_hung: channel %d", channel)); 1746 MUTEX_ENTER(&tx_ring_p->lock); 1747 (void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0); 1748 1749 tail_index = tx_ring_p->wr_index; 1750 tail_wrap = tx_ring_p->wr_index_wrap; 1751 tx_rd_index = tx_ring_p->rd_index; 1752 MUTEX_EXIT(&tx_ring_p->lock); 1753 1754 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1755 "==> nxge_txdma_channel_hung: tdc %d tx_rd_index %d " 1756 "tail_index %d tail_wrap %d ", 1757 channel, tx_rd_index, tail_index, tail_wrap)); 1758 /* 1759 * Read the hardware maintained transmit head 1760 * and wrap around bit. 1761 */ 1762 (void) npi_txdma_ring_head_get(handle, channel, &tx_head); 1763 head_index = tx_head.bits.ldw.head; 1764 head_wrap = tx_head.bits.ldw.wrap; 1765 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1766 "==> nxge_txdma_channel_hung: " 1767 "tx_rd_index %d tail %d tail_wrap %d " 1768 "head %d wrap %d", 1769 tx_rd_index, tail_index, tail_wrap, 1770 head_index, head_wrap)); 1771 1772 if (TXDMA_RING_EMPTY(head_index, head_wrap, 1773 tail_index, tail_wrap) && 1774 (head_index == tx_rd_index)) { 1775 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1776 "==> nxge_txdma_channel_hung: EMPTY")); 1777 return (B_FALSE); 1778 } 1779 1780 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1781 "==> nxge_txdma_channel_hung: Checking if ring full")); 1782 if (TXDMA_RING_FULL(head_index, head_wrap, tail_index, 1783 tail_wrap)) { 1784 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1785 "==> nxge_txdma_channel_hung: full")); 1786 return (B_TRUE); 1787 } 1788 1789 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_channel_hung")); 1790 1791 return (B_FALSE); 1792 } 1793 1794 /* 1795 * nxge_fixup_hung_txdma_rings 1796 * 1797 * Disable a TDC. 1798 * 1799 * Arguments: 1800 * nxgep 1801 * channel The channel to reset. 1802 * reg_data The current TX_CS. 1803 * 1804 * Notes: 1805 * Called by nxge_check_tx_hang() 1806 * 1807 * NPI/NXGE function calls: 1808 * npi_txdma_ring_head_get() 1809 * 1810 * Registers accessed: 1811 * TX_RING_HDL DMC+0x40010 Transmit Ring Head Low 1812 * 1813 * Context: 1814 * Any domain 1815 */ 1816 /*ARGSUSED*/ 1817 void 1818 nxge_fixup_hung_txdma_rings(p_nxge_t nxgep) 1819 { 1820 nxge_grp_set_t *set = &nxgep->tx_set; 1821 int tdc; 1822 1823 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_fixup_hung_txdma_rings")); 1824 1825 if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 1826 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1827 "<== nxge_fixup_hung_txdma_rings: NULL ring pointer(s)")); 1828 return; 1829 } 1830 1831 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 1832 if ((1 << tdc) & set->owned.map) { 1833 tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 1834 if (ring) { 1835 nxge_txdma_fixup_hung_channel(nxgep, ring, tdc); 1836 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1837 "==> nxge_fixup_hung_txdma_rings: TDC %d", 1838 tdc)); 1839 } 1840 } 1841 } 1842 1843 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_fixup_hung_txdma_rings")); 1844 } 1845 1846 /* 1847 * nxge_txdma_fixup_hung_channel 1848 * 1849 * 'Fix' a hung TDC. 1850 * 1851 * Arguments: 1852 * nxgep 1853 * channel The channel to fix. 1854 * 1855 * Notes: 1856 * Called by nxge_fixup_hung_txdma_rings() 1857 * 1858 * 1. Reclaim the TDC. 1859 * 2. Disable the TDC. 1860 * 1861 * NPI/NXGE function calls: 1862 * nxge_txdma_reclaim() 1863 * npi_txdma_channel_disable(TX_CS) 1864 * npi_txdma_inj_int_error_set(TDMC_INTR_DBG) 1865 * 1866 * Registers accessed: 1867 * TX_CS DMC+0x40028 Transmit Control And Status 1868 * TDMC_INTR_DBG DMC + 0x40060 Transmit DMA Interrupt Debug 1869 * 1870 * Context: 1871 * Any domain 1872 */ 1873 /*ARGSUSED*/ 1874 void 1875 nxge_txdma_fix_hung_channel(p_nxge_t nxgep, uint16_t channel) 1876 { 1877 p_tx_ring_t ring_p; 1878 1879 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fix_hung_channel")); 1880 ring_p = nxge_txdma_get_ring(nxgep, channel); 1881 if (ring_p == NULL) { 1882 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1883 "<== nxge_txdma_fix_hung_channel")); 1884 return; 1885 } 1886 1887 if (ring_p->tdc != channel) { 1888 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1889 "<== nxge_txdma_fix_hung_channel: channel not matched " 1890 "ring tdc %d passed channel", 1891 ring_p->tdc, channel)); 1892 return; 1893 } 1894 1895 nxge_txdma_fixup_channel(nxgep, ring_p, channel); 1896 1897 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_hung_channel")); 1898 } 1899 1900 /*ARGSUSED*/ 1901 void 1902 nxge_txdma_fixup_hung_channel(p_nxge_t nxgep, p_tx_ring_t ring_p, 1903 uint16_t channel) 1904 { 1905 npi_handle_t handle; 1906 tdmc_intr_dbg_t intr_dbg; 1907 int status = NXGE_OK; 1908 1909 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fixup_hung_channel")); 1910 1911 if (ring_p == NULL) { 1912 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1913 "<== nxge_txdma_fixup_channel: NULL ring pointer")); 1914 return; 1915 } 1916 1917 if (ring_p->tdc != channel) { 1918 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1919 "<== nxge_txdma_fixup_hung_channel: channel " 1920 "not matched " 1921 "ring tdc %d passed channel", 1922 ring_p->tdc, channel)); 1923 return; 1924 } 1925 1926 /* Reclaim descriptors */ 1927 MUTEX_ENTER(&ring_p->lock); 1928 (void) nxge_txdma_reclaim(nxgep, ring_p, 0); 1929 MUTEX_EXIT(&ring_p->lock); 1930 1931 handle = NXGE_DEV_NPI_HANDLE(nxgep); 1932 /* 1933 * Stop the dma channel waits for the stop done. 1934 * If the stop done bit is not set, then force 1935 * an error. 1936 */ 1937 status = npi_txdma_channel_disable(handle, channel); 1938 if (!(status & NPI_TXDMA_STOP_FAILED)) { 1939 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1940 "<== nxge_txdma_fixup_hung_channel: stopped OK " 1941 "ring tdc %d passed channel %d", 1942 ring_p->tdc, channel)); 1943 return; 1944 } 1945 1946 /* Inject any error */ 1947 intr_dbg.value = 0; 1948 intr_dbg.bits.ldw.nack_pref = 1; 1949 (void) npi_txdma_inj_int_error_set(handle, channel, &intr_dbg); 1950 1951 /* Stop done bit will be set as a result of error injection */ 1952 status = npi_txdma_channel_disable(handle, channel); 1953 if (!(status & NPI_TXDMA_STOP_FAILED)) { 1954 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1955 "<== nxge_txdma_fixup_hung_channel: stopped again" 1956 "ring tdc %d passed channel", 1957 ring_p->tdc, channel)); 1958 return; 1959 } 1960 1961 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1962 "<== nxge_txdma_fixup_hung_channel: stop done still not set!! " 1963 "ring tdc %d passed channel", 1964 ring_p->tdc, channel)); 1965 1966 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fixup_hung_channel")); 1967 } 1968 1969 /*ARGSUSED*/ 1970 void 1971 nxge_reclaim_rings(p_nxge_t nxgep) 1972 { 1973 nxge_grp_set_t *set = &nxgep->tx_set; 1974 int tdc; 1975 1976 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_reclaim_rings")); 1977 1978 if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 1979 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1980 "<== nxge_fixup_hung_txdma_rings: NULL ring pointer(s)")); 1981 return; 1982 } 1983 1984 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 1985 if ((1 << tdc) & set->owned.map) { 1986 tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 1987 if (ring) { 1988 NXGE_DEBUG_MSG((nxgep, TX_CTL, 1989 "==> nxge_reclaim_rings: TDC %d", tdc)); 1990 MUTEX_ENTER(&ring->lock); 1991 (void) nxge_txdma_reclaim(nxgep, ring, tdc); 1992 MUTEX_EXIT(&ring->lock); 1993 } 1994 } 1995 } 1996 1997 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_reclaim_rings")); 1998 } 1999 2000 void 2001 nxge_txdma_regs_dump_channels(p_nxge_t nxgep) 2002 { 2003 nxge_grp_set_t *set = &nxgep->tx_set; 2004 npi_handle_t handle; 2005 int tdc; 2006 2007 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_regs_dump_channels")); 2008 2009 handle = NXGE_DEV_NPI_HANDLE(nxgep); 2010 2011 if (!isLDOMguest(nxgep)) { 2012 (void) npi_txdma_dump_fzc_regs(handle); 2013 2014 /* Dump TXC registers. */ 2015 (void) npi_txc_dump_fzc_regs(handle); 2016 (void) npi_txc_dump_port_fzc_regs(handle, nxgep->function_num); 2017 } 2018 2019 if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 2020 NXGE_DEBUG_MSG((nxgep, TX_CTL, 2021 "<== nxge_fixup_hung_txdma_rings: NULL ring pointer(s)")); 2022 return; 2023 } 2024 2025 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 2026 if ((1 << tdc) & set->owned.map) { 2027 tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 2028 if (ring) { 2029 NXGE_DEBUG_MSG((nxgep, TX_CTL, 2030 "==> nxge_txdma_regs_dump_channels: " 2031 "TDC %d", tdc)); 2032 (void) npi_txdma_dump_tdc_regs(handle, tdc); 2033 2034 /* Dump TXC registers, if able to. */ 2035 if (!isLDOMguest(nxgep)) { 2036 NXGE_DEBUG_MSG((nxgep, TX_CTL, 2037 "==> nxge_txdma_regs_dump_channels:" 2038 " FZC TDC %d", tdc)); 2039 (void) npi_txc_dump_tdc_fzc_regs 2040 (handle, tdc); 2041 } 2042 nxge_txdma_regs_dump(nxgep, tdc); 2043 } 2044 } 2045 } 2046 2047 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_regs_dump")); 2048 } 2049 2050 void 2051 nxge_txdma_regs_dump(p_nxge_t nxgep, int channel) 2052 { 2053 npi_handle_t handle; 2054 tx_ring_hdl_t hdl; 2055 tx_ring_kick_t kick; 2056 tx_cs_t cs; 2057 txc_control_t control; 2058 uint32_t bitmap = 0; 2059 uint32_t burst = 0; 2060 uint32_t bytes = 0; 2061 dma_log_page_t cfg; 2062 2063 printf("\n\tfunc # %d tdc %d ", 2064 nxgep->function_num, channel); 2065 cfg.page_num = 0; 2066 handle = NXGE_DEV_NPI_HANDLE(nxgep); 2067 (void) npi_txdma_log_page_get(handle, channel, &cfg); 2068 printf("\n\tlog page func %d valid page 0 %d", 2069 cfg.func_num, cfg.valid); 2070 cfg.page_num = 1; 2071 (void) npi_txdma_log_page_get(handle, channel, &cfg); 2072 printf("\n\tlog page func %d valid page 1 %d", 2073 cfg.func_num, cfg.valid); 2074 2075 (void) npi_txdma_ring_head_get(handle, channel, &hdl); 2076 (void) npi_txdma_desc_kick_reg_get(handle, channel, &kick); 2077 printf("\n\thead value is 0x%0llx", 2078 (long long)hdl.value); 2079 printf("\n\thead index %d", hdl.bits.ldw.head); 2080 printf("\n\tkick value is 0x%0llx", 2081 (long long)kick.value); 2082 printf("\n\ttail index %d\n", kick.bits.ldw.tail); 2083 2084 (void) npi_txdma_control_status(handle, OP_GET, channel, &cs); 2085 printf("\n\tControl statue is 0x%0llx", (long long)cs.value); 2086 printf("\n\tControl status RST state %d", cs.bits.ldw.rst); 2087 2088 (void) npi_txc_control(handle, OP_GET, &control); 2089 (void) npi_txc_port_dma_list_get(handle, nxgep->function_num, &bitmap); 2090 (void) npi_txc_dma_max_burst(handle, OP_GET, channel, &burst); 2091 (void) npi_txc_dma_bytes_transmitted(handle, channel, &bytes); 2092 2093 printf("\n\tTXC port control 0x%0llx", 2094 (long long)control.value); 2095 printf("\n\tTXC port bitmap 0x%x", bitmap); 2096 printf("\n\tTXC max burst %d", burst); 2097 printf("\n\tTXC bytes xmt %d\n", bytes); 2098 2099 { 2100 ipp_status_t status; 2101 2102 (void) npi_ipp_get_status(handle, nxgep->function_num, &status); 2103 #if defined(__i386) 2104 printf("\n\tIPP status 0x%llux\n", (uint64_t)status.value); 2105 #else 2106 printf("\n\tIPP status 0x%lux\n", (uint64_t)status.value); 2107 #endif 2108 } 2109 } 2110 2111 /* 2112 * nxge_tdc_hvio_setup 2113 * 2114 * I'm not exactly sure what this code does. 2115 * 2116 * Arguments: 2117 * nxgep 2118 * channel The channel to map. 2119 * 2120 * Notes: 2121 * 2122 * NPI/NXGE function calls: 2123 * na 2124 * 2125 * Context: 2126 * Service domain? 2127 */ 2128 #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 2129 static void 2130 nxge_tdc_hvio_setup( 2131 nxge_t *nxgep, int channel) 2132 { 2133 nxge_dma_common_t *data; 2134 nxge_dma_common_t *control; 2135 tx_ring_t *ring; 2136 2137 ring = nxgep->tx_rings->rings[channel]; 2138 data = nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2139 2140 ring->hv_set = B_FALSE; 2141 2142 ring->hv_tx_buf_base_ioaddr_pp = 2143 (uint64_t)data->orig_ioaddr_pp; 2144 ring->hv_tx_buf_ioaddr_size = 2145 (uint64_t)data->orig_alength; 2146 2147 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma_channel: " 2148 "hv data buf base io $%p size 0x%llx (%d) buf base io $%p " 2149 "orig vatopa base io $%p orig_len 0x%llx (%d)", 2150 ring->hv_tx_buf_base_ioaddr_pp, 2151 ring->hv_tx_buf_ioaddr_size, ring->hv_tx_buf_ioaddr_size, 2152 data->ioaddr_pp, data->orig_vatopa, 2153 data->orig_alength, data->orig_alength)); 2154 2155 control = nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2156 2157 ring->hv_tx_cntl_base_ioaddr_pp = 2158 (uint64_t)control->orig_ioaddr_pp; 2159 ring->hv_tx_cntl_ioaddr_size = 2160 (uint64_t)control->orig_alength; 2161 2162 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma_channel: " 2163 "hv cntl base io $%p orig ioaddr_pp ($%p) " 2164 "orig vatopa ($%p) size 0x%llx (%d 0x%x)", 2165 ring->hv_tx_cntl_base_ioaddr_pp, 2166 control->orig_ioaddr_pp, control->orig_vatopa, 2167 ring->hv_tx_cntl_ioaddr_size, 2168 control->orig_alength, control->orig_alength)); 2169 } 2170 #endif 2171 2172 static nxge_status_t 2173 nxge_map_txdma(p_nxge_t nxgep, int channel) 2174 { 2175 nxge_dma_common_t **pData; 2176 nxge_dma_common_t **pControl; 2177 tx_ring_t **pRing, *ring; 2178 tx_mbox_t **mailbox; 2179 uint32_t num_chunks; 2180 2181 nxge_status_t status = NXGE_OK; 2182 2183 NXGE_ERROR_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma")); 2184 2185 if (!nxgep->tx_cntl_pool_p->buf_allocated) { 2186 if (nxge_alloc_tx_mem_pool(nxgep) != NXGE_OK) { 2187 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2188 "<== nxge_map_txdma: buf not allocated")); 2189 return (NXGE_ERROR); 2190 } 2191 } 2192 2193 if (nxge_alloc_txb(nxgep, channel) != NXGE_OK) 2194 return (NXGE_ERROR); 2195 2196 num_chunks = nxgep->tx_buf_pool_p->num_chunks[channel]; 2197 pData = &nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2198 pControl = &nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2199 pRing = &nxgep->tx_rings->rings[channel]; 2200 mailbox = &nxgep->tx_mbox_areas_p->txmbox_areas_p[channel]; 2201 2202 NXGE_ERROR_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma: " 2203 "tx_rings $%p tx_desc_rings $%p", 2204 nxgep->tx_rings, nxgep->tx_rings->rings)); 2205 2206 /* 2207 * Map descriptors from the buffer pools for <channel>. 2208 */ 2209 2210 /* 2211 * Set up and prepare buffer blocks, descriptors 2212 * and mailbox. 2213 */ 2214 status = nxge_map_txdma_channel(nxgep, channel, 2215 pData, pRing, num_chunks, pControl, mailbox); 2216 if (status != NXGE_OK) { 2217 NXGE_ERROR_MSG((nxgep, MEM3_CTL, 2218 "==> nxge_map_txdma(%d): nxge_map_txdma_channel() " 2219 "returned 0x%x", 2220 nxgep, channel, status)); 2221 return (status); 2222 } 2223 2224 ring = *pRing; 2225 2226 ring->index = (uint16_t)channel; 2227 ring->tdc_stats = &nxgep->statsp->tdc_stats[channel]; 2228 2229 #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 2230 if (isLDOMguest(nxgep)) { 2231 (void) nxge_tdc_lp_conf(nxgep, channel); 2232 } else { 2233 nxge_tdc_hvio_setup(nxgep, channel); 2234 } 2235 #endif 2236 2237 NXGE_ERROR_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma: " 2238 "(status 0x%x channel %d)", status, channel)); 2239 2240 return (status); 2241 } 2242 2243 static nxge_status_t 2244 nxge_map_txdma_channel(p_nxge_t nxgep, uint16_t channel, 2245 p_nxge_dma_common_t *dma_buf_p, 2246 p_tx_ring_t *tx_desc_p, 2247 uint32_t num_chunks, 2248 p_nxge_dma_common_t *dma_cntl_p, 2249 p_tx_mbox_t *tx_mbox_p) 2250 { 2251 int status = NXGE_OK; 2252 2253 /* 2254 * Set up and prepare buffer blocks, descriptors 2255 * and mailbox. 2256 */ 2257 NXGE_ERROR_MSG((nxgep, MEM3_CTL, 2258 "==> nxge_map_txdma_channel (channel %d)", channel)); 2259 /* 2260 * Transmit buffer blocks 2261 */ 2262 status = nxge_map_txdma_channel_buf_ring(nxgep, channel, 2263 dma_buf_p, tx_desc_p, num_chunks); 2264 if (status != NXGE_OK) { 2265 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2266 "==> nxge_map_txdma_channel (channel %d): " 2267 "map buffer failed 0x%x", channel, status)); 2268 goto nxge_map_txdma_channel_exit; 2269 } 2270 2271 /* 2272 * Transmit block ring, and mailbox. 2273 */ 2274 nxge_map_txdma_channel_cfg_ring(nxgep, channel, dma_cntl_p, *tx_desc_p, 2275 tx_mbox_p); 2276 2277 goto nxge_map_txdma_channel_exit; 2278 2279 nxge_map_txdma_channel_fail1: 2280 NXGE_ERROR_MSG((nxgep, MEM3_CTL, 2281 "==> nxge_map_txdma_channel: unmap buf" 2282 "(status 0x%x channel %d)", 2283 status, channel)); 2284 nxge_unmap_txdma_channel_buf_ring(nxgep, *tx_desc_p); 2285 2286 nxge_map_txdma_channel_exit: 2287 NXGE_ERROR_MSG((nxgep, MEM3_CTL, 2288 "<== nxge_map_txdma_channel: " 2289 "(status 0x%x channel %d)", 2290 status, channel)); 2291 2292 return (status); 2293 } 2294 2295 /*ARGSUSED*/ 2296 static void 2297 nxge_unmap_txdma_channel(p_nxge_t nxgep, uint16_t channel) 2298 { 2299 tx_ring_t *ring; 2300 tx_mbox_t *mailbox; 2301 2302 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2303 "==> nxge_unmap_txdma_channel (channel %d)", channel)); 2304 /* 2305 * unmap tx block ring, and mailbox. 2306 */ 2307 ring = nxgep->tx_rings->rings[channel]; 2308 mailbox = nxgep->tx_mbox_areas_p->txmbox_areas_p[channel]; 2309 2310 (void) nxge_unmap_txdma_channel_cfg_ring(nxgep, ring, mailbox); 2311 2312 /* unmap buffer blocks */ 2313 (void) nxge_unmap_txdma_channel_buf_ring(nxgep, ring); 2314 2315 nxge_free_txb(nxgep, channel); 2316 2317 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_unmap_txdma_channel")); 2318 } 2319 2320 /* 2321 * nxge_map_txdma_channel_cfg_ring 2322 * 2323 * Map a TDC into our kernel space. 2324 * This function allocates all of the per-channel data structures. 2325 * 2326 * Arguments: 2327 * nxgep 2328 * dma_channel The channel to map. 2329 * dma_cntl_p 2330 * tx_ring_p dma_channel's transmit ring 2331 * tx_mbox_p dma_channel's mailbox 2332 * 2333 * Notes: 2334 * 2335 * NPI/NXGE function calls: 2336 * nxge_setup_dma_common() 2337 * 2338 * Registers accessed: 2339 * none. 2340 * 2341 * Context: 2342 * Any domain 2343 */ 2344 /*ARGSUSED*/ 2345 static void 2346 nxge_map_txdma_channel_cfg_ring(p_nxge_t nxgep, uint16_t dma_channel, 2347 p_nxge_dma_common_t *dma_cntl_p, 2348 p_tx_ring_t tx_ring_p, 2349 p_tx_mbox_t *tx_mbox_p) 2350 { 2351 p_tx_mbox_t mboxp; 2352 p_nxge_dma_common_t cntl_dmap; 2353 p_nxge_dma_common_t dmap; 2354 p_tx_rng_cfig_t tx_ring_cfig_p; 2355 p_tx_ring_kick_t tx_ring_kick_p; 2356 p_tx_cs_t tx_cs_p; 2357 p_tx_dma_ent_msk_t tx_evmask_p; 2358 p_txdma_mbh_t mboxh_p; 2359 p_txdma_mbl_t mboxl_p; 2360 uint64_t tx_desc_len; 2361 2362 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2363 "==> nxge_map_txdma_channel_cfg_ring")); 2364 2365 cntl_dmap = *dma_cntl_p; 2366 2367 dmap = (p_nxge_dma_common_t)&tx_ring_p->tdc_desc; 2368 nxge_setup_dma_common(dmap, cntl_dmap, tx_ring_p->tx_ring_size, 2369 sizeof (tx_desc_t)); 2370 /* 2371 * Zero out transmit ring descriptors. 2372 */ 2373 bzero((caddr_t)dmap->kaddrp, dmap->alength); 2374 tx_ring_cfig_p = &(tx_ring_p->tx_ring_cfig); 2375 tx_ring_kick_p = &(tx_ring_p->tx_ring_kick); 2376 tx_cs_p = &(tx_ring_p->tx_cs); 2377 tx_evmask_p = &(tx_ring_p->tx_evmask); 2378 tx_ring_cfig_p->value = 0; 2379 tx_ring_kick_p->value = 0; 2380 tx_cs_p->value = 0; 2381 tx_evmask_p->value = 0; 2382 2383 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2384 "==> nxge_map_txdma_channel_cfg_ring: channel %d des $%p", 2385 dma_channel, 2386 dmap->dma_cookie.dmac_laddress)); 2387 2388 tx_ring_cfig_p->value = 0; 2389 tx_desc_len = (uint64_t)(tx_ring_p->tx_ring_size >> 3); 2390 tx_ring_cfig_p->value = 2391 (dmap->dma_cookie.dmac_laddress & TX_RNG_CFIG_ADDR_MASK) | 2392 (tx_desc_len << TX_RNG_CFIG_LEN_SHIFT); 2393 2394 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2395 "==> nxge_map_txdma_channel_cfg_ring: channel %d cfg 0x%llx", 2396 dma_channel, 2397 tx_ring_cfig_p->value)); 2398 2399 tx_cs_p->bits.ldw.rst = 1; 2400 2401 /* Map in mailbox */ 2402 mboxp = (p_tx_mbox_t) 2403 KMEM_ZALLOC(sizeof (tx_mbox_t), KM_SLEEP); 2404 dmap = (p_nxge_dma_common_t)&mboxp->tx_mbox; 2405 nxge_setup_dma_common(dmap, cntl_dmap, 1, sizeof (txdma_mailbox_t)); 2406 mboxh_p = (p_txdma_mbh_t)&tx_ring_p->tx_mbox_mbh; 2407 mboxl_p = (p_txdma_mbl_t)&tx_ring_p->tx_mbox_mbl; 2408 mboxh_p->value = mboxl_p->value = 0; 2409 2410 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2411 "==> nxge_map_txdma_channel_cfg_ring: mbox 0x%lx", 2412 dmap->dma_cookie.dmac_laddress)); 2413 2414 mboxh_p->bits.ldw.mbaddr = ((dmap->dma_cookie.dmac_laddress >> 2415 TXDMA_MBH_ADDR_SHIFT) & TXDMA_MBH_MASK); 2416 2417 mboxl_p->bits.ldw.mbaddr = ((dmap->dma_cookie.dmac_laddress & 2418 TXDMA_MBL_MASK) >> TXDMA_MBL_SHIFT); 2419 2420 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2421 "==> nxge_map_txdma_channel_cfg_ring: mbox 0x%lx", 2422 dmap->dma_cookie.dmac_laddress)); 2423 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2424 "==> nxge_map_txdma_channel_cfg_ring: hmbox $%p " 2425 "mbox $%p", 2426 mboxh_p->bits.ldw.mbaddr, mboxl_p->bits.ldw.mbaddr)); 2427 tx_ring_p->page_valid.value = 0; 2428 tx_ring_p->page_mask_1.value = tx_ring_p->page_mask_2.value = 0; 2429 tx_ring_p->page_value_1.value = tx_ring_p->page_value_2.value = 0; 2430 tx_ring_p->page_reloc_1.value = tx_ring_p->page_reloc_2.value = 0; 2431 tx_ring_p->page_hdl.value = 0; 2432 2433 tx_ring_p->page_valid.bits.ldw.page0 = 1; 2434 tx_ring_p->page_valid.bits.ldw.page1 = 1; 2435 2436 tx_ring_p->max_burst.value = 0; 2437 tx_ring_p->max_burst.bits.ldw.dma_max_burst = TXC_DMA_MAX_BURST_DEFAULT; 2438 2439 *tx_mbox_p = mboxp; 2440 2441 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2442 "<== nxge_map_txdma_channel_cfg_ring")); 2443 } 2444 2445 /*ARGSUSED*/ 2446 static void 2447 nxge_unmap_txdma_channel_cfg_ring(p_nxge_t nxgep, 2448 p_tx_ring_t tx_ring_p, p_tx_mbox_t tx_mbox_p) 2449 { 2450 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2451 "==> nxge_unmap_txdma_channel_cfg_ring: channel %d", 2452 tx_ring_p->tdc)); 2453 2454 KMEM_FREE(tx_mbox_p, sizeof (tx_mbox_t)); 2455 2456 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2457 "<== nxge_unmap_txdma_channel_cfg_ring")); 2458 } 2459 2460 /* 2461 * nxge_map_txdma_channel_buf_ring 2462 * 2463 * 2464 * Arguments: 2465 * nxgep 2466 * channel The channel to map. 2467 * dma_buf_p 2468 * tx_desc_p channel's descriptor ring 2469 * num_chunks 2470 * 2471 * Notes: 2472 * 2473 * NPI/NXGE function calls: 2474 * nxge_setup_dma_common() 2475 * 2476 * Registers accessed: 2477 * none. 2478 * 2479 * Context: 2480 * Any domain 2481 */ 2482 static nxge_status_t 2483 nxge_map_txdma_channel_buf_ring(p_nxge_t nxgep, uint16_t channel, 2484 p_nxge_dma_common_t *dma_buf_p, 2485 p_tx_ring_t *tx_desc_p, uint32_t num_chunks) 2486 { 2487 p_nxge_dma_common_t dma_bufp, tmp_bufp; 2488 p_nxge_dma_common_t dmap; 2489 nxge_os_dma_handle_t tx_buf_dma_handle; 2490 p_tx_ring_t tx_ring_p; 2491 p_tx_msg_t tx_msg_ring; 2492 nxge_status_t status = NXGE_OK; 2493 int ddi_status = DDI_SUCCESS; 2494 int i, j, index; 2495 uint32_t size, bsize; 2496 uint32_t nblocks, nmsgs; 2497 2498 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2499 "==> nxge_map_txdma_channel_buf_ring")); 2500 2501 dma_bufp = tmp_bufp = *dma_buf_p; 2502 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2503 " nxge_map_txdma_channel_buf_ring: channel %d to map %d " 2504 "chunks bufp $%p", 2505 channel, num_chunks, dma_bufp)); 2506 2507 nmsgs = 0; 2508 for (i = 0; i < num_chunks; i++, tmp_bufp++) { 2509 nmsgs += tmp_bufp->nblocks; 2510 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2511 "==> nxge_map_txdma_channel_buf_ring: channel %d " 2512 "bufp $%p nblocks %d nmsgs %d", 2513 channel, tmp_bufp, tmp_bufp->nblocks, nmsgs)); 2514 } 2515 if (!nmsgs) { 2516 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2517 "<== nxge_map_txdma_channel_buf_ring: channel %d " 2518 "no msg blocks", 2519 channel)); 2520 status = NXGE_ERROR; 2521 goto nxge_map_txdma_channel_buf_ring_exit; 2522 } 2523 2524 tx_ring_p = (p_tx_ring_t) 2525 KMEM_ZALLOC(sizeof (tx_ring_t), KM_SLEEP); 2526 MUTEX_INIT(&tx_ring_p->lock, NULL, MUTEX_DRIVER, 2527 (void *)nxgep->interrupt_cookie); 2528 2529 (void) atomic_swap_32(&tx_ring_p->tx_ring_offline, NXGE_TX_RING_ONLINE); 2530 tx_ring_p->nxgep = nxgep; 2531 tx_ring_p->serial = nxge_serialize_create(nmsgs, 2532 nxge_serial_tx, tx_ring_p); 2533 /* 2534 * Allocate transmit message rings and handles for packets 2535 * not to be copied to premapped buffers. 2536 */ 2537 size = nmsgs * sizeof (tx_msg_t); 2538 tx_msg_ring = KMEM_ZALLOC(size, KM_SLEEP); 2539 for (i = 0; i < nmsgs; i++) { 2540 ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr, 2541 DDI_DMA_DONTWAIT, 0, 2542 &tx_msg_ring[i].dma_handle); 2543 if (ddi_status != DDI_SUCCESS) { 2544 status |= NXGE_DDI_FAILED; 2545 break; 2546 } 2547 } 2548 if (i < nmsgs) { 2549 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2550 "Allocate handles failed.")); 2551 goto nxge_map_txdma_channel_buf_ring_fail1; 2552 } 2553 2554 tx_ring_p->tdc = channel; 2555 tx_ring_p->tx_msg_ring = tx_msg_ring; 2556 tx_ring_p->tx_ring_size = nmsgs; 2557 tx_ring_p->num_chunks = num_chunks; 2558 if (!nxge_tx_intr_thres) { 2559 nxge_tx_intr_thres = tx_ring_p->tx_ring_size/4; 2560 } 2561 tx_ring_p->tx_wrap_mask = tx_ring_p->tx_ring_size - 1; 2562 tx_ring_p->rd_index = 0; 2563 tx_ring_p->wr_index = 0; 2564 tx_ring_p->ring_head.value = 0; 2565 tx_ring_p->ring_kick_tail.value = 0; 2566 tx_ring_p->descs_pending = 0; 2567 2568 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2569 "==> nxge_map_txdma_channel_buf_ring: channel %d " 2570 "actual tx desc max %d nmsgs %d " 2571 "(config nxge_tx_ring_size %d)", 2572 channel, tx_ring_p->tx_ring_size, nmsgs, 2573 nxge_tx_ring_size)); 2574 2575 /* 2576 * Map in buffers from the buffer pool. 2577 */ 2578 index = 0; 2579 bsize = dma_bufp->block_size; 2580 2581 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma_channel_buf_ring: " 2582 "dma_bufp $%p tx_rng_p $%p " 2583 "tx_msg_rng_p $%p bsize %d", 2584 dma_bufp, tx_ring_p, tx_msg_ring, bsize)); 2585 2586 tx_buf_dma_handle = dma_bufp->dma_handle; 2587 for (i = 0; i < num_chunks; i++, dma_bufp++) { 2588 bsize = dma_bufp->block_size; 2589 nblocks = dma_bufp->nblocks; 2590 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2591 "==> nxge_map_txdma_channel_buf_ring: dma chunk %d " 2592 "size %d dma_bufp $%p", 2593 i, sizeof (nxge_dma_common_t), dma_bufp)); 2594 2595 for (j = 0; j < nblocks; j++) { 2596 tx_msg_ring[index].buf_dma_handle = tx_buf_dma_handle; 2597 dmap = &tx_msg_ring[index++].buf_dma; 2598 #ifdef TX_MEM_DEBUG 2599 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2600 "==> nxge_map_txdma_channel_buf_ring: j %d" 2601 "dmap $%p", i, dmap)); 2602 #endif 2603 nxge_setup_dma_common(dmap, dma_bufp, 1, 2604 bsize); 2605 } 2606 } 2607 2608 if (i < num_chunks) { 2609 status = NXGE_ERROR; 2610 goto nxge_map_txdma_channel_buf_ring_fail1; 2611 } 2612 2613 *tx_desc_p = tx_ring_p; 2614 2615 goto nxge_map_txdma_channel_buf_ring_exit; 2616 2617 nxge_map_txdma_channel_buf_ring_fail1: 2618 if (tx_ring_p->serial) { 2619 nxge_serialize_destroy(tx_ring_p->serial); 2620 tx_ring_p->serial = NULL; 2621 } 2622 2623 index--; 2624 for (; index >= 0; index--) { 2625 if (tx_msg_ring[index].dma_handle != NULL) { 2626 ddi_dma_free_handle(&tx_msg_ring[index].dma_handle); 2627 } 2628 } 2629 MUTEX_DESTROY(&tx_ring_p->lock); 2630 KMEM_FREE(tx_msg_ring, size); 2631 KMEM_FREE(tx_ring_p, sizeof (tx_ring_t)); 2632 2633 status = NXGE_ERROR; 2634 2635 nxge_map_txdma_channel_buf_ring_exit: 2636 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2637 "<== nxge_map_txdma_channel_buf_ring status 0x%x", status)); 2638 2639 return (status); 2640 } 2641 2642 /*ARGSUSED*/ 2643 static void 2644 nxge_unmap_txdma_channel_buf_ring(p_nxge_t nxgep, p_tx_ring_t tx_ring_p) 2645 { 2646 p_tx_msg_t tx_msg_ring; 2647 p_tx_msg_t tx_msg_p; 2648 int i; 2649 2650 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2651 "==> nxge_unmap_txdma_channel_buf_ring")); 2652 if (tx_ring_p == NULL) { 2653 NXGE_DEBUG_MSG((nxgep, TX_CTL, 2654 "<== nxge_unmap_txdma_channel_buf_ring: NULL ringp")); 2655 return; 2656 } 2657 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2658 "==> nxge_unmap_txdma_channel_buf_ring: channel %d", 2659 tx_ring_p->tdc)); 2660 2661 tx_msg_ring = tx_ring_p->tx_msg_ring; 2662 2663 /* 2664 * Since the serialization thread, timer thread and 2665 * interrupt thread can all call the transmit reclaim, 2666 * the unmapping function needs to acquire the lock 2667 * to free those buffers which were transmitted 2668 * by the hardware already. 2669 */ 2670 MUTEX_ENTER(&tx_ring_p->lock); 2671 NXGE_DEBUG_MSG((nxgep, TX_CTL, 2672 "==> nxge_unmap_txdma_channel_buf_ring (reclaim): " 2673 "channel %d", 2674 tx_ring_p->tdc)); 2675 (void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0); 2676 2677 for (i = 0; i < tx_ring_p->tx_ring_size; i++) { 2678 tx_msg_p = &tx_msg_ring[i]; 2679 if (tx_msg_p->tx_message != NULL) { 2680 freemsg(tx_msg_p->tx_message); 2681 tx_msg_p->tx_message = NULL; 2682 } 2683 } 2684 2685 for (i = 0; i < tx_ring_p->tx_ring_size; i++) { 2686 if (tx_msg_ring[i].dma_handle != NULL) { 2687 ddi_dma_free_handle(&tx_msg_ring[i].dma_handle); 2688 } 2689 tx_msg_ring[i].dma_handle = NULL; 2690 } 2691 2692 MUTEX_EXIT(&tx_ring_p->lock); 2693 2694 if (tx_ring_p->serial) { 2695 nxge_serialize_destroy(tx_ring_p->serial); 2696 tx_ring_p->serial = NULL; 2697 } 2698 2699 MUTEX_DESTROY(&tx_ring_p->lock); 2700 KMEM_FREE(tx_msg_ring, sizeof (tx_msg_t) * tx_ring_p->tx_ring_size); 2701 KMEM_FREE(tx_ring_p, sizeof (tx_ring_t)); 2702 2703 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2704 "<== nxge_unmap_txdma_channel_buf_ring")); 2705 } 2706 2707 static nxge_status_t 2708 nxge_txdma_hw_start(p_nxge_t nxgep, int channel) 2709 { 2710 p_tx_rings_t tx_rings; 2711 p_tx_ring_t *tx_desc_rings; 2712 p_tx_mbox_areas_t tx_mbox_areas_p; 2713 p_tx_mbox_t *tx_mbox_p; 2714 nxge_status_t status = NXGE_OK; 2715 2716 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start")); 2717 2718 tx_rings = nxgep->tx_rings; 2719 if (tx_rings == NULL) { 2720 NXGE_DEBUG_MSG((nxgep, TX_CTL, 2721 "<== nxge_txdma_hw_start: NULL ring pointer")); 2722 return (NXGE_ERROR); 2723 } 2724 tx_desc_rings = tx_rings->rings; 2725 if (tx_desc_rings == NULL) { 2726 NXGE_DEBUG_MSG((nxgep, TX_CTL, 2727 "<== nxge_txdma_hw_start: NULL ring pointers")); 2728 return (NXGE_ERROR); 2729 } 2730 2731 NXGE_ERROR_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: " 2732 "tx_rings $%p tx_desc_rings $%p", tx_rings, tx_desc_rings)); 2733 2734 tx_mbox_areas_p = nxgep->tx_mbox_areas_p; 2735 tx_mbox_p = tx_mbox_areas_p->txmbox_areas_p; 2736 2737 status = nxge_txdma_start_channel(nxgep, channel, 2738 (p_tx_ring_t)tx_desc_rings[channel], 2739 (p_tx_mbox_t)tx_mbox_p[channel]); 2740 if (status != NXGE_OK) { 2741 goto nxge_txdma_hw_start_fail1; 2742 } 2743 2744 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: " 2745 "tx_rings $%p rings $%p", 2746 nxgep->tx_rings, nxgep->tx_rings->rings)); 2747 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: " 2748 "tx_rings $%p tx_desc_rings $%p", 2749 nxgep->tx_rings, tx_desc_rings)); 2750 2751 goto nxge_txdma_hw_start_exit; 2752 2753 nxge_txdma_hw_start_fail1: 2754 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2755 "==> nxge_txdma_hw_start: disable " 2756 "(status 0x%x channel %d)", status, channel)); 2757 2758 nxge_txdma_hw_start_exit: 2759 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2760 "==> nxge_txdma_hw_start: (status 0x%x)", status)); 2761 2762 return (status); 2763 } 2764 2765 /* 2766 * nxge_txdma_start_channel 2767 * 2768 * Start a TDC. 2769 * 2770 * Arguments: 2771 * nxgep 2772 * channel The channel to start. 2773 * tx_ring_p channel's transmit descriptor ring. 2774 * tx_mbox_p channel' smailbox. 2775 * 2776 * Notes: 2777 * 2778 * NPI/NXGE function calls: 2779 * nxge_reset_txdma_channel() 2780 * nxge_init_txdma_channel_event_mask() 2781 * nxge_enable_txdma_channel() 2782 * 2783 * Registers accessed: 2784 * none directly (see functions above). 2785 * 2786 * Context: 2787 * Any domain 2788 */ 2789 static nxge_status_t 2790 nxge_txdma_start_channel(p_nxge_t nxgep, uint16_t channel, 2791 p_tx_ring_t tx_ring_p, p_tx_mbox_t tx_mbox_p) 2792 2793 { 2794 nxge_status_t status = NXGE_OK; 2795 2796 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2797 "==> nxge_txdma_start_channel (channel %d)", channel)); 2798 /* 2799 * TXDMA/TXC must be in stopped state. 2800 */ 2801 (void) nxge_txdma_stop_inj_err(nxgep, channel); 2802 2803 /* 2804 * Reset TXDMA channel 2805 */ 2806 tx_ring_p->tx_cs.value = 0; 2807 tx_ring_p->tx_cs.bits.ldw.rst = 1; 2808 status = nxge_reset_txdma_channel(nxgep, channel, 2809 tx_ring_p->tx_cs.value); 2810 if (status != NXGE_OK) { 2811 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2812 "==> nxge_txdma_start_channel (channel %d)" 2813 " reset channel failed 0x%x", channel, status)); 2814 goto nxge_txdma_start_channel_exit; 2815 } 2816 2817 /* 2818 * Initialize the TXDMA channel specific FZC control 2819 * configurations. These FZC registers are pertaining 2820 * to each TX channel (i.e. logical pages). 2821 */ 2822 if (!isLDOMguest(nxgep)) { 2823 status = nxge_init_fzc_txdma_channel(nxgep, channel, 2824 tx_ring_p, tx_mbox_p); 2825 if (status != NXGE_OK) { 2826 goto nxge_txdma_start_channel_exit; 2827 } 2828 } 2829 2830 /* 2831 * Initialize the event masks. 2832 */ 2833 tx_ring_p->tx_evmask.value = 0; 2834 status = nxge_init_txdma_channel_event_mask(nxgep, 2835 channel, &tx_ring_p->tx_evmask); 2836 if (status != NXGE_OK) { 2837 goto nxge_txdma_start_channel_exit; 2838 } 2839 2840 /* 2841 * Load TXDMA descriptors, buffers, mailbox, 2842 * initialise the DMA channels and 2843 * enable each DMA channel. 2844 */ 2845 status = nxge_enable_txdma_channel(nxgep, channel, 2846 tx_ring_p, tx_mbox_p); 2847 if (status != NXGE_OK) { 2848 goto nxge_txdma_start_channel_exit; 2849 } 2850 2851 nxge_txdma_start_channel_exit: 2852 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_txdma_start_channel")); 2853 2854 return (status); 2855 } 2856 2857 /* 2858 * nxge_txdma_stop_channel 2859 * 2860 * Stop a TDC. 2861 * 2862 * Arguments: 2863 * nxgep 2864 * channel The channel to stop. 2865 * tx_ring_p channel's transmit descriptor ring. 2866 * tx_mbox_p channel' smailbox. 2867 * 2868 * Notes: 2869 * 2870 * NPI/NXGE function calls: 2871 * nxge_txdma_stop_inj_err() 2872 * nxge_reset_txdma_channel() 2873 * nxge_init_txdma_channel_event_mask() 2874 * nxge_init_txdma_channel_cntl_stat() 2875 * nxge_disable_txdma_channel() 2876 * 2877 * Registers accessed: 2878 * none directly (see functions above). 2879 * 2880 * Context: 2881 * Any domain 2882 */ 2883 /*ARGSUSED*/ 2884 static nxge_status_t 2885 nxge_txdma_stop_channel(p_nxge_t nxgep, uint16_t channel) 2886 { 2887 p_tx_ring_t tx_ring_p; 2888 int status = NXGE_OK; 2889 2890 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2891 "==> nxge_txdma_stop_channel: channel %d", channel)); 2892 2893 /* 2894 * Stop (disable) TXDMA and TXC (if stop bit is set 2895 * and STOP_N_GO bit not set, the TXDMA reset state will 2896 * not be set if reset TXDMA. 2897 */ 2898 (void) nxge_txdma_stop_inj_err(nxgep, channel); 2899 2900 tx_ring_p = nxgep->tx_rings->rings[channel]; 2901 2902 /* 2903 * Reset TXDMA channel 2904 */ 2905 tx_ring_p->tx_cs.value = 0; 2906 tx_ring_p->tx_cs.bits.ldw.rst = 1; 2907 status = nxge_reset_txdma_channel(nxgep, channel, 2908 tx_ring_p->tx_cs.value); 2909 if (status != NXGE_OK) { 2910 goto nxge_txdma_stop_channel_exit; 2911 } 2912 2913 #ifdef HARDWARE_REQUIRED 2914 /* Set up the interrupt event masks. */ 2915 tx_ring_p->tx_evmask.value = 0; 2916 status = nxge_init_txdma_channel_event_mask(nxgep, 2917 channel, &tx_ring_p->tx_evmask); 2918 if (status != NXGE_OK) { 2919 goto nxge_txdma_stop_channel_exit; 2920 } 2921 2922 /* Initialize the DMA control and status register */ 2923 tx_ring_p->tx_cs.value = TX_ENT_MSK_MK_ALL; 2924 status = nxge_init_txdma_channel_cntl_stat(nxgep, channel, 2925 tx_ring_p->tx_cs.value); 2926 if (status != NXGE_OK) { 2927 goto nxge_txdma_stop_channel_exit; 2928 } 2929 2930 tx_mbox_p = nxgep->tx_mbox_areas_p->txmbox_areas_p[channel]; 2931 2932 /* Disable channel */ 2933 status = nxge_disable_txdma_channel(nxgep, channel, 2934 tx_ring_p, tx_mbox_p); 2935 if (status != NXGE_OK) { 2936 goto nxge_txdma_start_channel_exit; 2937 } 2938 2939 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 2940 "==> nxge_txdma_stop_channel: event done")); 2941 2942 #endif 2943 2944 nxge_txdma_stop_channel_exit: 2945 NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_txdma_stop_channel")); 2946 return (status); 2947 } 2948 2949 /* 2950 * nxge_txdma_get_ring 2951 * 2952 * Get the ring for a TDC. 2953 * 2954 * Arguments: 2955 * nxgep 2956 * channel 2957 * 2958 * Notes: 2959 * 2960 * NPI/NXGE function calls: 2961 * 2962 * Registers accessed: 2963 * 2964 * Context: 2965 * Any domain 2966 */ 2967 static p_tx_ring_t 2968 nxge_txdma_get_ring(p_nxge_t nxgep, uint16_t channel) 2969 { 2970 nxge_grp_set_t *set = &nxgep->tx_set; 2971 int tdc; 2972 2973 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_get_ring")); 2974 2975 if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 2976 NXGE_DEBUG_MSG((nxgep, TX_CTL, 2977 "<== nxge_txdma_get_ring: NULL ring pointer(s)")); 2978 goto return_null; 2979 } 2980 2981 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 2982 if ((1 << tdc) & set->owned.map) { 2983 tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 2984 if (ring) { 2985 if (channel == ring->tdc) { 2986 NXGE_DEBUG_MSG((nxgep, TX_CTL, 2987 "<== nxge_txdma_get_ring: " 2988 "tdc %d ring $%p", tdc, ring)); 2989 return (ring); 2990 } 2991 } 2992 } 2993 } 2994 2995 return_null: 2996 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_get_ring: " 2997 "ring not found")); 2998 2999 return (NULL); 3000 } 3001 3002 /* 3003 * nxge_txdma_get_mbox 3004 * 3005 * Get the mailbox for a TDC. 3006 * 3007 * Arguments: 3008 * nxgep 3009 * channel 3010 * 3011 * Notes: 3012 * 3013 * NPI/NXGE function calls: 3014 * 3015 * Registers accessed: 3016 * 3017 * Context: 3018 * Any domain 3019 */ 3020 static p_tx_mbox_t 3021 nxge_txdma_get_mbox(p_nxge_t nxgep, uint16_t channel) 3022 { 3023 nxge_grp_set_t *set = &nxgep->tx_set; 3024 int tdc; 3025 3026 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_get_mbox")); 3027 3028 if (nxgep->tx_mbox_areas_p == 0 || 3029 nxgep->tx_mbox_areas_p->txmbox_areas_p == 0) { 3030 NXGE_DEBUG_MSG((nxgep, TX_CTL, 3031 "<== nxge_txdma_get_mbox: NULL mailbox pointer(s)")); 3032 goto return_null; 3033 } 3034 3035 if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 3036 NXGE_DEBUG_MSG((nxgep, TX_CTL, 3037 "<== nxge_txdma_get_mbox: NULL ring pointer(s)")); 3038 goto return_null; 3039 } 3040 3041 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3042 if ((1 << tdc) & set->owned.map) { 3043 tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 3044 if (ring) { 3045 if (channel == ring->tdc) { 3046 tx_mbox_t *mailbox = nxgep-> 3047 tx_mbox_areas_p-> 3048 txmbox_areas_p[tdc]; 3049 NXGE_DEBUG_MSG((nxgep, TX_CTL, 3050 "<== nxge_txdma_get_mbox: tdc %d " 3051 "ring $%p", tdc, mailbox)); 3052 return (mailbox); 3053 } 3054 } 3055 } 3056 } 3057 3058 return_null: 3059 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_get_mbox: " 3060 "mailbox not found")); 3061 3062 return (NULL); 3063 } 3064 3065 /* 3066 * nxge_tx_err_evnts 3067 * 3068 * Recover a TDC. 3069 * 3070 * Arguments: 3071 * nxgep 3072 * index The index to the TDC ring. 3073 * ldvp Used to get the channel number ONLY. 3074 * cs A copy of the bits from TX_CS. 3075 * 3076 * Notes: 3077 * Calling tree: 3078 * nxge_tx_intr() 3079 * 3080 * NPI/NXGE function calls: 3081 * npi_txdma_ring_error_get() 3082 * npi_txdma_inj_par_error_get() 3083 * nxge_txdma_fatal_err_recover() 3084 * 3085 * Registers accessed: 3086 * TX_RNG_ERR_LOGH DMC+0x40048 Transmit Ring Error Log High 3087 * TX_RNG_ERR_LOGL DMC+0x40050 Transmit Ring Error Log Low 3088 * TDMC_INJ_PAR_ERR (FZC_DMC + 0x45040) TDMC Inject Parity Error 3089 * 3090 * Context: 3091 * Any domain XXX Remove code which accesses TDMC_INJ_PAR_ERR. 3092 */ 3093 /*ARGSUSED*/ 3094 static nxge_status_t 3095 nxge_tx_err_evnts(p_nxge_t nxgep, uint_t index, p_nxge_ldv_t ldvp, tx_cs_t cs) 3096 { 3097 npi_handle_t handle; 3098 npi_status_t rs; 3099 uint8_t channel; 3100 p_tx_ring_t *tx_rings; 3101 p_tx_ring_t tx_ring_p; 3102 p_nxge_tx_ring_stats_t tdc_stats; 3103 boolean_t txchan_fatal = B_FALSE; 3104 nxge_status_t status = NXGE_OK; 3105 tdmc_inj_par_err_t par_err; 3106 uint32_t value; 3107 3108 NXGE_DEBUG_MSG((nxgep, TX2_CTL, "==> nxge_tx_err_evnts")); 3109 handle = NXGE_DEV_NPI_HANDLE(nxgep); 3110 channel = ldvp->channel; 3111 3112 tx_rings = nxgep->tx_rings->rings; 3113 tx_ring_p = tx_rings[index]; 3114 tdc_stats = tx_ring_p->tdc_stats; 3115 if ((cs.bits.ldw.pkt_size_err) || (cs.bits.ldw.pref_buf_par_err) || 3116 (cs.bits.ldw.nack_pref) || (cs.bits.ldw.nack_pkt_rd) || 3117 (cs.bits.ldw.conf_part_err) || (cs.bits.ldw.pkt_prt_err)) { 3118 if ((rs = npi_txdma_ring_error_get(handle, channel, 3119 &tdc_stats->errlog)) != NPI_SUCCESS) 3120 return (NXGE_ERROR | rs); 3121 } 3122 3123 if (cs.bits.ldw.mbox_err) { 3124 tdc_stats->mbox_err++; 3125 NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 3126 NXGE_FM_EREPORT_TDMC_MBOX_ERR); 3127 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3128 "==> nxge_tx_err_evnts(channel %d): " 3129 "fatal error: mailbox", channel)); 3130 txchan_fatal = B_TRUE; 3131 } 3132 if (cs.bits.ldw.pkt_size_err) { 3133 tdc_stats->pkt_size_err++; 3134 NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 3135 NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR); 3136 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3137 "==> nxge_tx_err_evnts(channel %d): " 3138 "fatal error: pkt_size_err", channel)); 3139 txchan_fatal = B_TRUE; 3140 } 3141 if (cs.bits.ldw.tx_ring_oflow) { 3142 tdc_stats->tx_ring_oflow++; 3143 NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 3144 NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW); 3145 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3146 "==> nxge_tx_err_evnts(channel %d): " 3147 "fatal error: tx_ring_oflow", channel)); 3148 txchan_fatal = B_TRUE; 3149 } 3150 if (cs.bits.ldw.pref_buf_par_err) { 3151 tdc_stats->pre_buf_par_err++; 3152 NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 3153 NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR); 3154 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3155 "==> nxge_tx_err_evnts(channel %d): " 3156 "fatal error: pre_buf_par_err", channel)); 3157 /* Clear error injection source for parity error */ 3158 (void) npi_txdma_inj_par_error_get(handle, &value); 3159 par_err.value = value; 3160 par_err.bits.ldw.inject_parity_error &= ~(1 << channel); 3161 (void) npi_txdma_inj_par_error_set(handle, par_err.value); 3162 txchan_fatal = B_TRUE; 3163 } 3164 if (cs.bits.ldw.nack_pref) { 3165 tdc_stats->nack_pref++; 3166 NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 3167 NXGE_FM_EREPORT_TDMC_NACK_PREF); 3168 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3169 "==> nxge_tx_err_evnts(channel %d): " 3170 "fatal error: nack_pref", channel)); 3171 txchan_fatal = B_TRUE; 3172 } 3173 if (cs.bits.ldw.nack_pkt_rd) { 3174 tdc_stats->nack_pkt_rd++; 3175 NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 3176 NXGE_FM_EREPORT_TDMC_NACK_PKT_RD); 3177 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3178 "==> nxge_tx_err_evnts(channel %d): " 3179 "fatal error: nack_pkt_rd", channel)); 3180 txchan_fatal = B_TRUE; 3181 } 3182 if (cs.bits.ldw.conf_part_err) { 3183 tdc_stats->conf_part_err++; 3184 NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 3185 NXGE_FM_EREPORT_TDMC_CONF_PART_ERR); 3186 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3187 "==> nxge_tx_err_evnts(channel %d): " 3188 "fatal error: config_partition_err", channel)); 3189 txchan_fatal = B_TRUE; 3190 } 3191 if (cs.bits.ldw.pkt_prt_err) { 3192 tdc_stats->pkt_part_err++; 3193 NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 3194 NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR); 3195 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3196 "==> nxge_tx_err_evnts(channel %d): " 3197 "fatal error: pkt_prt_err", channel)); 3198 txchan_fatal = B_TRUE; 3199 } 3200 3201 /* Clear error injection source in case this is an injected error */ 3202 TXDMA_REG_WRITE64(nxgep->npi_handle, TDMC_INTR_DBG_REG, channel, 0); 3203 3204 if (txchan_fatal) { 3205 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3206 " nxge_tx_err_evnts: " 3207 " fatal error on channel %d cs 0x%llx\n", 3208 channel, cs.value)); 3209 status = nxge_txdma_fatal_err_recover(nxgep, channel, 3210 tx_ring_p); 3211 if (status == NXGE_OK) { 3212 FM_SERVICE_RESTORED(nxgep); 3213 } 3214 } 3215 3216 NXGE_DEBUG_MSG((nxgep, TX2_CTL, "<== nxge_tx_err_evnts")); 3217 3218 return (status); 3219 } 3220 3221 static nxge_status_t 3222 nxge_txdma_fatal_err_recover( 3223 p_nxge_t nxgep, 3224 uint16_t channel, 3225 p_tx_ring_t tx_ring_p) 3226 { 3227 npi_handle_t handle; 3228 npi_status_t rs = NPI_SUCCESS; 3229 p_tx_mbox_t tx_mbox_p; 3230 nxge_status_t status = NXGE_OK; 3231 3232 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fatal_err_recover")); 3233 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3234 "Recovering from TxDMAChannel#%d error...", channel)); 3235 3236 /* 3237 * Stop the dma channel waits for the stop done. 3238 * If the stop done bit is not set, then create 3239 * an error. 3240 */ 3241 3242 handle = NXGE_DEV_NPI_HANDLE(nxgep); 3243 NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel stop...")); 3244 MUTEX_ENTER(&tx_ring_p->lock); 3245 rs = npi_txdma_channel_control(handle, TXDMA_STOP, channel); 3246 if (rs != NPI_SUCCESS) { 3247 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3248 "==> nxge_txdma_fatal_err_recover (channel %d): " 3249 "stop failed ", channel)); 3250 goto fail; 3251 } 3252 3253 NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel reclaim...")); 3254 (void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0); 3255 3256 /* 3257 * Reset TXDMA channel 3258 */ 3259 NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel reset...")); 3260 if ((rs = npi_txdma_channel_control(handle, TXDMA_RESET, channel)) != 3261 NPI_SUCCESS) { 3262 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3263 "==> nxge_txdma_fatal_err_recover (channel %d)" 3264 " reset channel failed 0x%x", channel, rs)); 3265 goto fail; 3266 } 3267 3268 /* 3269 * Reset the tail (kick) register to 0. 3270 * (Hardware will not reset it. Tx overflow fatal 3271 * error if tail is not set to 0 after reset! 3272 */ 3273 TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, 0); 3274 3275 /* Restart TXDMA channel */ 3276 3277 if (!isLDOMguest(nxgep)) { 3278 tx_mbox_p = nxge_txdma_get_mbox(nxgep, channel); 3279 3280 // XXX This is a problem in HIO! 3281 /* 3282 * Initialize the TXDMA channel specific FZC control 3283 * configurations. These FZC registers are pertaining 3284 * to each TX channel (i.e. logical pages). 3285 */ 3286 NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel restart...")); 3287 status = nxge_init_fzc_txdma_channel(nxgep, channel, 3288 tx_ring_p, tx_mbox_p); 3289 if (status != NXGE_OK) 3290 goto fail; 3291 } 3292 3293 /* 3294 * Initialize the event masks. 3295 */ 3296 tx_ring_p->tx_evmask.value = 0; 3297 status = nxge_init_txdma_channel_event_mask(nxgep, channel, 3298 &tx_ring_p->tx_evmask); 3299 if (status != NXGE_OK) 3300 goto fail; 3301 3302 tx_ring_p->wr_index_wrap = B_FALSE; 3303 tx_ring_p->wr_index = 0; 3304 tx_ring_p->rd_index = 0; 3305 3306 /* 3307 * Load TXDMA descriptors, buffers, mailbox, 3308 * initialise the DMA channels and 3309 * enable each DMA channel. 3310 */ 3311 NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel enable...")); 3312 status = nxge_enable_txdma_channel(nxgep, channel, 3313 tx_ring_p, tx_mbox_p); 3314 MUTEX_EXIT(&tx_ring_p->lock); 3315 if (status != NXGE_OK) 3316 goto fail; 3317 3318 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3319 "Recovery Successful, TxDMAChannel#%d Restored", 3320 channel)); 3321 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fatal_err_recover")); 3322 3323 return (NXGE_OK); 3324 3325 fail: 3326 MUTEX_EXIT(&tx_ring_p->lock); 3327 NXGE_DEBUG_MSG((nxgep, TX_CTL, 3328 "nxge_txdma_fatal_err_recover (channel %d): " 3329 "failed to recover this txdma channel", channel)); 3330 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed")); 3331 3332 return (status); 3333 } 3334 3335 /* 3336 * nxge_tx_port_fatal_err_recover 3337 * 3338 * Attempt to recover from a fatal port error. 3339 * 3340 * Arguments: 3341 * nxgep 3342 * 3343 * Notes: 3344 * How would a guest do this? 3345 * 3346 * NPI/NXGE function calls: 3347 * 3348 * Registers accessed: 3349 * 3350 * Context: 3351 * Service domain 3352 */ 3353 nxge_status_t 3354 nxge_tx_port_fatal_err_recover(p_nxge_t nxgep) 3355 { 3356 nxge_grp_set_t *set = &nxgep->tx_set; 3357 nxge_channel_t tdc; 3358 3359 tx_ring_t *ring; 3360 tx_mbox_t *mailbox; 3361 3362 npi_handle_t handle; 3363 nxge_status_t status; 3364 npi_status_t rs; 3365 3366 NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_tx_port_fatal_err_recover")); 3367 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3368 "Recovering from TxPort error...")); 3369 3370 if (isLDOMguest(nxgep)) { 3371 return (NXGE_OK); 3372 } 3373 3374 if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 3375 NXGE_DEBUG_MSG((nxgep, TX_CTL, 3376 "<== nxge_tx_port_fatal_err_recover: not initialized")); 3377 return (NXGE_ERROR); 3378 } 3379 3380 if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 3381 NXGE_DEBUG_MSG((nxgep, TX_CTL, 3382 "<== nxge_tx_port_fatal_err_recover: " 3383 "NULL ring pointer(s)")); 3384 return (NXGE_ERROR); 3385 } 3386 3387 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3388 if ((1 << tdc) & set->owned.map) { 3389 tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 3390 if (ring) 3391 MUTEX_ENTER(&ring->lock); 3392 } 3393 } 3394 3395 handle = NXGE_DEV_NPI_HANDLE(nxgep); 3396 3397 /* 3398 * Stop all the TDCs owned by us. 3399 * (The shared TDCs will have been stopped by their owners.) 3400 */ 3401 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3402 if ((1 << tdc) & set->owned.map) { 3403 ring = nxgep->tx_rings->rings[tdc]; 3404 if (ring) { 3405 rs = npi_txdma_channel_control 3406 (handle, TXDMA_STOP, tdc); 3407 if (rs != NPI_SUCCESS) { 3408 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3409 "nxge_tx_port_fatal_err_recover " 3410 "(channel %d): stop failed ", tdc)); 3411 goto fail; 3412 } 3413 } 3414 } 3415 } 3416 3417 NXGE_DEBUG_MSG((nxgep, TX_CTL, "Reclaiming all TDCs...")); 3418 3419 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3420 if ((1 << tdc) & set->owned.map) { 3421 tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 3422 if (ring) 3423 (void) nxge_txdma_reclaim(nxgep, ring, 0); 3424 } 3425 } 3426 3427 /* 3428 * Reset all the TDCs. 3429 */ 3430 NXGE_DEBUG_MSG((nxgep, TX_CTL, "Resetting all TDCs...")); 3431 3432 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3433 if ((1 << tdc) & set->owned.map) { 3434 tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 3435 if (ring) { 3436 if ((rs = npi_txdma_channel_control 3437 (handle, TXDMA_RESET, tdc)) 3438 != NPI_SUCCESS) { 3439 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3440 "nxge_tx_port_fatal_err_recover " 3441 "(channel %d) reset channel " 3442 "failed 0x%x", tdc, rs)); 3443 goto fail; 3444 } 3445 } 3446 /* 3447 * Reset the tail (kick) register to 0. 3448 * (Hardware will not reset it. Tx overflow fatal 3449 * error if tail is not set to 0 after reset! 3450 */ 3451 TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, tdc, 0); 3452 } 3453 } 3454 3455 NXGE_DEBUG_MSG((nxgep, TX_CTL, "Restarting all TDCs...")); 3456 3457 /* Restart all the TDCs */ 3458 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3459 if ((1 << tdc) & set->owned.map) { 3460 ring = nxgep->tx_rings->rings[tdc]; 3461 if (ring) { 3462 mailbox = nxge_txdma_get_mbox(nxgep, tdc); 3463 status = nxge_init_fzc_txdma_channel(nxgep, tdc, 3464 ring, mailbox); 3465 ring->tx_evmask.value = 0; 3466 /* 3467 * Initialize the event masks. 3468 */ 3469 status = nxge_init_txdma_channel_event_mask 3470 (nxgep, tdc, &ring->tx_evmask); 3471 3472 ring->wr_index_wrap = B_FALSE; 3473 ring->wr_index = 0; 3474 ring->rd_index = 0; 3475 3476 if (status != NXGE_OK) 3477 goto fail; 3478 if (status != NXGE_OK) 3479 goto fail; 3480 } 3481 } 3482 } 3483 3484 NXGE_DEBUG_MSG((nxgep, TX_CTL, "Re-enabling all TDCs...")); 3485 3486 /* Re-enable all the TDCs */ 3487 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3488 if ((1 << tdc) & set->owned.map) { 3489 ring = nxgep->tx_rings->rings[tdc]; 3490 if (ring) { 3491 mailbox = nxge_txdma_get_mbox(nxgep, tdc); 3492 status = nxge_enable_txdma_channel(nxgep, tdc, 3493 ring, mailbox); 3494 if (status != NXGE_OK) 3495 goto fail; 3496 } 3497 } 3498 } 3499 3500 /* 3501 * Unlock all the TDCs. 3502 */ 3503 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3504 if ((1 << tdc) & set->owned.map) { 3505 tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 3506 if (ring) 3507 MUTEX_EXIT(&ring->lock); 3508 } 3509 } 3510 3511 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Tx port recovery succeeded")); 3512 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_tx_port_fatal_err_recover")); 3513 3514 return (NXGE_OK); 3515 3516 fail: 3517 for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3518 if ((1 << tdc) & set->owned.map) { 3519 ring = nxgep->tx_rings->rings[tdc]; 3520 if (ring) 3521 MUTEX_EXIT(&ring->lock); 3522 } 3523 } 3524 3525 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Tx port recovery failed")); 3526 NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_tx_port_fatal_err_recover")); 3527 3528 return (status); 3529 } 3530 3531 /* 3532 * nxge_txdma_inject_err 3533 * 3534 * Inject an error into a TDC. 3535 * 3536 * Arguments: 3537 * nxgep 3538 * err_id The error to inject. 3539 * chan The channel to inject into. 3540 * 3541 * Notes: 3542 * This is called from nxge_main.c:nxge_err_inject() 3543 * Has this ioctl ever been used? 3544 * 3545 * NPI/NXGE function calls: 3546 * npi_txdma_inj_par_error_get() 3547 * npi_txdma_inj_par_error_set() 3548 * 3549 * Registers accessed: 3550 * TDMC_INJ_PAR_ERR (FZC_DMC + 0x45040) TDMC Inject Parity Error 3551 * TDMC_INTR_DBG DMC + 0x40060 Transmit DMA Interrupt Debug 3552 * TDMC_INTR_DBG DMC + 0x40060 Transmit DMA Interrupt Debug 3553 * 3554 * Context: 3555 * Service domain 3556 */ 3557 void 3558 nxge_txdma_inject_err(p_nxge_t nxgep, uint32_t err_id, uint8_t chan) 3559 { 3560 tdmc_intr_dbg_t tdi; 3561 tdmc_inj_par_err_t par_err; 3562 uint32_t value; 3563 npi_handle_t handle; 3564 3565 switch (err_id) { 3566 3567 case NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR: 3568 handle = NXGE_DEV_NPI_HANDLE(nxgep); 3569 /* Clear error injection source for parity error */ 3570 (void) npi_txdma_inj_par_error_get(handle, &value); 3571 par_err.value = value; 3572 par_err.bits.ldw.inject_parity_error &= ~(1 << chan); 3573 (void) npi_txdma_inj_par_error_set(handle, par_err.value); 3574 3575 par_err.bits.ldw.inject_parity_error = (1 << chan); 3576 (void) npi_txdma_inj_par_error_get(handle, &value); 3577 par_err.value = value; 3578 par_err.bits.ldw.inject_parity_error |= (1 << chan); 3579 cmn_err(CE_NOTE, "!Write 0x%llx to TDMC_INJ_PAR_ERR_REG\n", 3580 (unsigned long long)par_err.value); 3581 (void) npi_txdma_inj_par_error_set(handle, par_err.value); 3582 break; 3583 3584 case NXGE_FM_EREPORT_TDMC_MBOX_ERR: 3585 case NXGE_FM_EREPORT_TDMC_NACK_PREF: 3586 case NXGE_FM_EREPORT_TDMC_NACK_PKT_RD: 3587 case NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR: 3588 case NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW: 3589 case NXGE_FM_EREPORT_TDMC_CONF_PART_ERR: 3590 case NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR: 3591 TXDMA_REG_READ64(nxgep->npi_handle, TDMC_INTR_DBG_REG, 3592 chan, &tdi.value); 3593 if (err_id == NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR) 3594 tdi.bits.ldw.pref_buf_par_err = 1; 3595 else if (err_id == NXGE_FM_EREPORT_TDMC_MBOX_ERR) 3596 tdi.bits.ldw.mbox_err = 1; 3597 else if (err_id == NXGE_FM_EREPORT_TDMC_NACK_PREF) 3598 tdi.bits.ldw.nack_pref = 1; 3599 else if (err_id == NXGE_FM_EREPORT_TDMC_NACK_PKT_RD) 3600 tdi.bits.ldw.nack_pkt_rd = 1; 3601 else if (err_id == NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR) 3602 tdi.bits.ldw.pkt_size_err = 1; 3603 else if (err_id == NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW) 3604 tdi.bits.ldw.tx_ring_oflow = 1; 3605 else if (err_id == NXGE_FM_EREPORT_TDMC_CONF_PART_ERR) 3606 tdi.bits.ldw.conf_part_err = 1; 3607 else if (err_id == NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR) 3608 tdi.bits.ldw.pkt_part_err = 1; 3609 #if defined(__i386) 3610 cmn_err(CE_NOTE, "!Write 0x%llx to TDMC_INTR_DBG_REG\n", 3611 tdi.value); 3612 #else 3613 cmn_err(CE_NOTE, "!Write 0x%lx to TDMC_INTR_DBG_REG\n", 3614 tdi.value); 3615 #endif 3616 TXDMA_REG_WRITE64(nxgep->npi_handle, TDMC_INTR_DBG_REG, 3617 chan, tdi.value); 3618 3619 break; 3620 } 3621 } 3622