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