144961713Sgirish /* 244961713Sgirish * CDDL HEADER START 344961713Sgirish * 444961713Sgirish * The contents of this file are subject to the terms of the 544961713Sgirish * Common Development and Distribution License (the "License"). 644961713Sgirish * You may not use this file except in compliance with the License. 744961713Sgirish * 844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 944961713Sgirish * or http://www.opensolaris.org/os/licensing. 1044961713Sgirish * See the License for the specific language governing permissions 1144961713Sgirish * and limitations under the License. 1244961713Sgirish * 1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each 1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the 1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 1844961713Sgirish * 1944961713Sgirish * CDDL HEADER END 2044961713Sgirish */ 2144961713Sgirish /* 22678453a8Sspeer * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2344961713Sgirish * Use is subject to license terms. 2444961713Sgirish */ 2544961713Sgirish 2644961713Sgirish #include <sys/nxge/nxge_impl.h> 2744961713Sgirish #include <sys/nxge/nxge_txdma.h> 28678453a8Sspeer #include <sys/nxge/nxge_hio.h> 29678453a8Sspeer #include <npi_tx_rd64.h> 30678453a8Sspeer #include <npi_tx_wr64.h> 3144961713Sgirish #include <sys/llc1.h> 3244961713Sgirish 3344961713Sgirish uint32_t nxge_reclaim_pending = TXDMA_RECLAIM_PENDING_DEFAULT; 3444961713Sgirish uint32_t nxge_tx_minfree = 32; 3544961713Sgirish uint32_t nxge_tx_intr_thres = 0; 3644961713Sgirish uint32_t nxge_tx_max_gathers = TX_MAX_GATHER_POINTERS; 3744961713Sgirish uint32_t nxge_tx_tiny_pack = 1; 3844961713Sgirish uint32_t nxge_tx_use_bcopy = 1; 3944961713Sgirish 4044961713Sgirish extern uint32_t nxge_tx_ring_size; 4144961713Sgirish extern uint32_t nxge_bcopy_thresh; 4244961713Sgirish extern uint32_t nxge_dvma_thresh; 4344961713Sgirish extern uint32_t nxge_dma_stream_thresh; 4444961713Sgirish extern dma_method_t nxge_force_dma; 45b4d05839Sml extern uint32_t nxge_cksum_offload; 4644961713Sgirish 4744961713Sgirish /* Device register access attributes for PIO. */ 4844961713Sgirish extern ddi_device_acc_attr_t nxge_dev_reg_acc_attr; 4944961713Sgirish /* Device descriptor access attributes for DMA. */ 5044961713Sgirish extern ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr; 5144961713Sgirish /* Device buffer access attributes for DMA. */ 5244961713Sgirish extern ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr; 5344961713Sgirish extern ddi_dma_attr_t nxge_desc_dma_attr; 5444961713Sgirish extern ddi_dma_attr_t nxge_tx_dma_attr; 5544961713Sgirish 561f8914d5Sml extern int nxge_serial_tx(mblk_t *mp, void *arg); 571f8914d5Sml 58*2d99c5d4SMichael Speer void nxge_txdma_freemsg_task(p_tx_ring_t tx_ring_p); 59*2d99c5d4SMichael Speer 60678453a8Sspeer static nxge_status_t nxge_map_txdma(p_nxge_t, int); 6144961713Sgirish 62678453a8Sspeer static nxge_status_t nxge_txdma_hw_start(p_nxge_t, int); 6344961713Sgirish 6444961713Sgirish static nxge_status_t nxge_map_txdma_channel(p_nxge_t, uint16_t, 6544961713Sgirish p_nxge_dma_common_t *, p_tx_ring_t *, 6644961713Sgirish uint32_t, p_nxge_dma_common_t *, 6744961713Sgirish p_tx_mbox_t *); 68678453a8Sspeer static void nxge_unmap_txdma_channel(p_nxge_t, uint16_t); 6944961713Sgirish 7044961713Sgirish static nxge_status_t nxge_map_txdma_channel_buf_ring(p_nxge_t, uint16_t, 7144961713Sgirish p_nxge_dma_common_t *, p_tx_ring_t *, uint32_t); 7244961713Sgirish static void nxge_unmap_txdma_channel_buf_ring(p_nxge_t, p_tx_ring_t); 7344961713Sgirish 7444961713Sgirish static void nxge_map_txdma_channel_cfg_ring(p_nxge_t, uint16_t, 7544961713Sgirish p_nxge_dma_common_t *, p_tx_ring_t, 7644961713Sgirish p_tx_mbox_t *); 7744961713Sgirish static void nxge_unmap_txdma_channel_cfg_ring(p_nxge_t, 7844961713Sgirish p_tx_ring_t, p_tx_mbox_t); 7944961713Sgirish 8044961713Sgirish static nxge_status_t nxge_txdma_start_channel(p_nxge_t, uint16_t, 8144961713Sgirish p_tx_ring_t, p_tx_mbox_t); 82678453a8Sspeer static nxge_status_t nxge_txdma_stop_channel(p_nxge_t, uint16_t); 8344961713Sgirish 8444961713Sgirish static p_tx_ring_t nxge_txdma_get_ring(p_nxge_t, uint16_t); 8544961713Sgirish static nxge_status_t nxge_tx_err_evnts(p_nxge_t, uint_t, 8644961713Sgirish p_nxge_ldv_t, tx_cs_t); 8744961713Sgirish static p_tx_mbox_t nxge_txdma_get_mbox(p_nxge_t, uint16_t); 8844961713Sgirish static nxge_status_t nxge_txdma_fatal_err_recover(p_nxge_t, 8944961713Sgirish uint16_t, p_tx_ring_t); 9044961713Sgirish 91678453a8Sspeer static void nxge_txdma_fixup_hung_channel(p_nxge_t nxgep, 92678453a8Sspeer p_tx_ring_t ring_p, uint16_t channel); 93678453a8Sspeer 9444961713Sgirish nxge_status_t 9544961713Sgirish nxge_init_txdma_channels(p_nxge_t nxgep) 9644961713Sgirish { 97678453a8Sspeer nxge_grp_set_t *set = &nxgep->tx_set; 98678453a8Sspeer int i, count; 99678453a8Sspeer 100678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_init_txdma_channels")); 101678453a8Sspeer 102678453a8Sspeer for (i = 0, count = 0; i < NXGE_LOGICAL_GROUP_MAX; i++) { 103678453a8Sspeer if ((1 << i) & set->lg.map) { 104678453a8Sspeer int tdc; 105678453a8Sspeer nxge_grp_t *group = set->group[i]; 106678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 107678453a8Sspeer if ((1 << tdc) & group->map) { 108678453a8Sspeer if ((nxge_grp_dc_add(nxgep, 1096920a987SMisaki Miyashita group, VP_BOUND_TX, tdc))) 110678453a8Sspeer return (NXGE_ERROR); 111678453a8Sspeer } 112678453a8Sspeer } 113678453a8Sspeer } 114678453a8Sspeer if (++count == set->lg.count) 115678453a8Sspeer break; 116678453a8Sspeer } 117678453a8Sspeer 118678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_init_txdma_channels")); 119678453a8Sspeer 120678453a8Sspeer return (NXGE_OK); 121678453a8Sspeer } 122678453a8Sspeer 123678453a8Sspeer nxge_status_t 124678453a8Sspeer nxge_init_txdma_channel( 125678453a8Sspeer p_nxge_t nxge, 126678453a8Sspeer int channel) 127678453a8Sspeer { 128678453a8Sspeer nxge_status_t status; 12944961713Sgirish 130678453a8Sspeer NXGE_DEBUG_MSG((nxge, MEM2_CTL, "==> nxge_init_txdma_channel")); 13144961713Sgirish 132678453a8Sspeer status = nxge_map_txdma(nxge, channel); 13344961713Sgirish if (status != NXGE_OK) { 134678453a8Sspeer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, 135678453a8Sspeer "<== nxge_init_txdma_channel: status 0x%x", status)); 136678453a8Sspeer (void) npi_txdma_dump_tdc_regs(nxge->npi_handle, channel); 13744961713Sgirish return (status); 13844961713Sgirish } 13944961713Sgirish 140678453a8Sspeer status = nxge_txdma_hw_start(nxge, channel); 14144961713Sgirish if (status != NXGE_OK) { 142678453a8Sspeer (void) nxge_unmap_txdma_channel(nxge, channel); 143678453a8Sspeer (void) npi_txdma_dump_tdc_regs(nxge->npi_handle, channel); 14444961713Sgirish return (status); 14544961713Sgirish } 14644961713Sgirish 147678453a8Sspeer if (!nxge->statsp->tdc_ksp[channel]) 148678453a8Sspeer nxge_setup_tdc_kstats(nxge, channel); 14944961713Sgirish 150678453a8Sspeer NXGE_DEBUG_MSG((nxge, MEM2_CTL, "<== nxge_init_txdma_channel")); 151678453a8Sspeer 152678453a8Sspeer return (status); 15344961713Sgirish } 15444961713Sgirish 15544961713Sgirish void 15644961713Sgirish nxge_uninit_txdma_channels(p_nxge_t nxgep) 15744961713Sgirish { 158678453a8Sspeer nxge_grp_set_t *set = &nxgep->tx_set; 159678453a8Sspeer int tdc; 160678453a8Sspeer 161678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "==> nxge_uninit_txdma_channels")); 162678453a8Sspeer 163678453a8Sspeer if (set->owned.map == 0) { 164678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, 165678453a8Sspeer "nxge_uninit_txdma_channels: no channels")); 166678453a8Sspeer return; 167678453a8Sspeer } 168678453a8Sspeer 169678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 170678453a8Sspeer if ((1 << tdc) & set->owned.map) { 171678453a8Sspeer nxge_grp_dc_remove(nxgep, VP_BOUND_TX, tdc); 172678453a8Sspeer } 173678453a8Sspeer } 174678453a8Sspeer 175678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM2_CTL, "<== nxge_uninit_txdma_channels")); 176678453a8Sspeer } 177678453a8Sspeer 178678453a8Sspeer void 179678453a8Sspeer nxge_uninit_txdma_channel(p_nxge_t nxgep, int channel) 180678453a8Sspeer { 181678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_uninit_txdma_channel")); 182678453a8Sspeer 183678453a8Sspeer if (nxgep->statsp->tdc_ksp[channel]) { 184678453a8Sspeer kstat_delete(nxgep->statsp->tdc_ksp[channel]); 185678453a8Sspeer nxgep->statsp->tdc_ksp[channel] = 0; 186678453a8Sspeer } 18744961713Sgirish 188678453a8Sspeer (void) nxge_txdma_stop_channel(nxgep, channel); 189678453a8Sspeer nxge_unmap_txdma_channel(nxgep, channel); 19044961713Sgirish 19144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 19252ccf843Smisaki "<== nxge_uninit_txdma_channel")); 19344961713Sgirish } 19444961713Sgirish 19544961713Sgirish void 19644961713Sgirish nxge_setup_dma_common(p_nxge_dma_common_t dest_p, p_nxge_dma_common_t src_p, 19744961713Sgirish uint32_t entries, uint32_t size) 19844961713Sgirish { 19944961713Sgirish size_t tsize; 20044961713Sgirish *dest_p = *src_p; 20144961713Sgirish tsize = size * entries; 20244961713Sgirish dest_p->alength = tsize; 20344961713Sgirish dest_p->nblocks = entries; 20444961713Sgirish dest_p->block_size = size; 20544961713Sgirish dest_p->offset += tsize; 20644961713Sgirish 20744961713Sgirish src_p->kaddrp = (caddr_t)dest_p->kaddrp + tsize; 20844961713Sgirish src_p->alength -= tsize; 20944961713Sgirish src_p->dma_cookie.dmac_laddress += tsize; 21044961713Sgirish src_p->dma_cookie.dmac_size -= tsize; 21144961713Sgirish } 21244961713Sgirish 213678453a8Sspeer /* 214678453a8Sspeer * nxge_reset_txdma_channel 215678453a8Sspeer * 216678453a8Sspeer * Reset a TDC. 217678453a8Sspeer * 218678453a8Sspeer * Arguments: 219678453a8Sspeer * nxgep 220678453a8Sspeer * channel The channel to reset. 221678453a8Sspeer * reg_data The current TX_CS. 222678453a8Sspeer * 223678453a8Sspeer * Notes: 224678453a8Sspeer * 225678453a8Sspeer * NPI/NXGE function calls: 226678453a8Sspeer * npi_txdma_channel_reset() 227678453a8Sspeer * npi_txdma_channel_control() 228678453a8Sspeer * 229678453a8Sspeer * Registers accessed: 230678453a8Sspeer * TX_CS DMC+0x40028 Transmit Control And Status 231678453a8Sspeer * TX_RING_KICK DMC+0x40018 Transmit Ring Kick 232678453a8Sspeer * 233678453a8Sspeer * Context: 234678453a8Sspeer * Any domain 235678453a8Sspeer */ 23644961713Sgirish nxge_status_t 23744961713Sgirish nxge_reset_txdma_channel(p_nxge_t nxgep, uint16_t channel, uint64_t reg_data) 23844961713Sgirish { 23944961713Sgirish npi_status_t rs = NPI_SUCCESS; 24044961713Sgirish nxge_status_t status = NXGE_OK; 24144961713Sgirish npi_handle_t handle; 24244961713Sgirish 24344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, " ==> nxge_reset_txdma_channel")); 24444961713Sgirish 24544961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 24644961713Sgirish if ((reg_data & TX_CS_RST_MASK) == TX_CS_RST_MASK) { 24744961713Sgirish rs = npi_txdma_channel_reset(handle, channel); 24844961713Sgirish } else { 24944961713Sgirish rs = npi_txdma_channel_control(handle, TXDMA_RESET, 25052ccf843Smisaki channel); 25144961713Sgirish } 25244961713Sgirish 25344961713Sgirish if (rs != NPI_SUCCESS) { 25444961713Sgirish status = NXGE_ERROR | rs; 25544961713Sgirish } 25644961713Sgirish 25744961713Sgirish /* 25844961713Sgirish * Reset the tail (kick) register to 0. 25944961713Sgirish * (Hardware will not reset it. Tx overflow fatal 26044961713Sgirish * error if tail is not set to 0 after reset! 26144961713Sgirish */ 26244961713Sgirish TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, 0); 26344961713Sgirish 26444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, " <== nxge_reset_txdma_channel")); 26544961713Sgirish return (status); 26644961713Sgirish } 26744961713Sgirish 268678453a8Sspeer /* 269678453a8Sspeer * nxge_init_txdma_channel_event_mask 270678453a8Sspeer * 271678453a8Sspeer * Enable interrupts for a set of events. 272678453a8Sspeer * 273678453a8Sspeer * Arguments: 274678453a8Sspeer * nxgep 275678453a8Sspeer * channel The channel to map. 276678453a8Sspeer * mask_p The events to enable. 277678453a8Sspeer * 278678453a8Sspeer * Notes: 279678453a8Sspeer * 280678453a8Sspeer * NPI/NXGE function calls: 281678453a8Sspeer * npi_txdma_event_mask() 282678453a8Sspeer * 283678453a8Sspeer * Registers accessed: 284678453a8Sspeer * TX_ENT_MSK DMC+0x40020 Transmit Event Mask 285678453a8Sspeer * 286678453a8Sspeer * Context: 287678453a8Sspeer * Any domain 288678453a8Sspeer */ 28944961713Sgirish nxge_status_t 29044961713Sgirish nxge_init_txdma_channel_event_mask(p_nxge_t nxgep, uint16_t channel, 29144961713Sgirish p_tx_dma_ent_msk_t mask_p) 29244961713Sgirish { 29344961713Sgirish npi_handle_t handle; 29444961713Sgirish npi_status_t rs = NPI_SUCCESS; 29544961713Sgirish nxge_status_t status = NXGE_OK; 29644961713Sgirish 29744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 29852ccf843Smisaki "<== nxge_init_txdma_channel_event_mask")); 29944961713Sgirish 30044961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 30144961713Sgirish rs = npi_txdma_event_mask(handle, OP_SET, channel, mask_p); 30244961713Sgirish if (rs != NPI_SUCCESS) { 30344961713Sgirish status = NXGE_ERROR | rs; 30444961713Sgirish } 30544961713Sgirish 30644961713Sgirish return (status); 30744961713Sgirish } 30844961713Sgirish 309678453a8Sspeer /* 310678453a8Sspeer * nxge_init_txdma_channel_cntl_stat 311678453a8Sspeer * 312678453a8Sspeer * Stop a TDC. If at first we don't succeed, inject an error. 313678453a8Sspeer * 314678453a8Sspeer * Arguments: 315678453a8Sspeer * nxgep 316678453a8Sspeer * channel The channel to stop. 317678453a8Sspeer * 318678453a8Sspeer * Notes: 319678453a8Sspeer * 320678453a8Sspeer * NPI/NXGE function calls: 321678453a8Sspeer * npi_txdma_control_status() 322678453a8Sspeer * 323678453a8Sspeer * Registers accessed: 324678453a8Sspeer * TX_CS DMC+0x40028 Transmit Control And Status 325678453a8Sspeer * 326678453a8Sspeer * Context: 327678453a8Sspeer * Any domain 328678453a8Sspeer */ 32944961713Sgirish nxge_status_t 33044961713Sgirish nxge_init_txdma_channel_cntl_stat(p_nxge_t nxgep, uint16_t channel, 33144961713Sgirish uint64_t reg_data) 33244961713Sgirish { 33344961713Sgirish npi_handle_t handle; 33444961713Sgirish npi_status_t rs = NPI_SUCCESS; 33544961713Sgirish nxge_status_t status = NXGE_OK; 33644961713Sgirish 33744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 33852ccf843Smisaki "<== nxge_init_txdma_channel_cntl_stat")); 33944961713Sgirish 34044961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 34144961713Sgirish rs = npi_txdma_control_status(handle, OP_SET, channel, 34252ccf843Smisaki (p_tx_cs_t)®_data); 34344961713Sgirish 34444961713Sgirish if (rs != NPI_SUCCESS) { 34544961713Sgirish status = NXGE_ERROR | rs; 34644961713Sgirish } 34744961713Sgirish 34844961713Sgirish return (status); 34944961713Sgirish } 35044961713Sgirish 351678453a8Sspeer /* 352678453a8Sspeer * nxge_enable_txdma_channel 353678453a8Sspeer * 354678453a8Sspeer * Enable a TDC. 355678453a8Sspeer * 356678453a8Sspeer * Arguments: 357678453a8Sspeer * nxgep 358678453a8Sspeer * channel The channel to enable. 359678453a8Sspeer * tx_desc_p channel's transmit descriptor ring. 360678453a8Sspeer * mbox_p channel's mailbox, 361678453a8Sspeer * 362678453a8Sspeer * Notes: 363678453a8Sspeer * 364678453a8Sspeer * NPI/NXGE function calls: 365678453a8Sspeer * npi_txdma_ring_config() 366678453a8Sspeer * npi_txdma_mbox_config() 367678453a8Sspeer * npi_txdma_channel_init_enable() 368678453a8Sspeer * 369678453a8Sspeer * Registers accessed: 370678453a8Sspeer * TX_RNG_CFIG DMC+0x40000 Transmit Ring Configuration 371678453a8Sspeer * TXDMA_MBH DMC+0x40030 TXDMA Mailbox High 372678453a8Sspeer * TXDMA_MBL DMC+0x40038 TXDMA Mailbox Low 373678453a8Sspeer * TX_CS DMC+0x40028 Transmit Control And Status 374678453a8Sspeer * 375678453a8Sspeer * Context: 376678453a8Sspeer * Any domain 377678453a8Sspeer */ 37844961713Sgirish nxge_status_t 37944961713Sgirish nxge_enable_txdma_channel(p_nxge_t nxgep, 38044961713Sgirish uint16_t channel, p_tx_ring_t tx_desc_p, p_tx_mbox_t mbox_p) 38144961713Sgirish { 38244961713Sgirish npi_handle_t handle; 38344961713Sgirish npi_status_t rs = NPI_SUCCESS; 38444961713Sgirish nxge_status_t status = NXGE_OK; 38544961713Sgirish 38644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_enable_txdma_channel")); 38744961713Sgirish 38844961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 38944961713Sgirish /* 39044961713Sgirish * Use configuration data composed at init time. 39144961713Sgirish * Write to hardware the transmit ring configurations. 39244961713Sgirish */ 39344961713Sgirish rs = npi_txdma_ring_config(handle, OP_SET, channel, 394678453a8Sspeer (uint64_t *)&(tx_desc_p->tx_ring_cfig.value)); 39544961713Sgirish 39644961713Sgirish if (rs != NPI_SUCCESS) { 39744961713Sgirish return (NXGE_ERROR | rs); 39844961713Sgirish } 39944961713Sgirish 400678453a8Sspeer if (isLDOMguest(nxgep)) { 401678453a8Sspeer /* Add interrupt handler for this channel. */ 402678453a8Sspeer if (nxge_hio_intr_add(nxgep, VP_BOUND_TX, channel) != NXGE_OK) 403678453a8Sspeer return (NXGE_ERROR); 404678453a8Sspeer } 405678453a8Sspeer 40644961713Sgirish /* Write to hardware the mailbox */ 40744961713Sgirish rs = npi_txdma_mbox_config(handle, OP_SET, channel, 40852ccf843Smisaki (uint64_t *)&mbox_p->tx_mbox.dma_cookie.dmac_laddress); 40944961713Sgirish 41044961713Sgirish if (rs != NPI_SUCCESS) { 41144961713Sgirish return (NXGE_ERROR | rs); 41244961713Sgirish } 41344961713Sgirish 41444961713Sgirish /* Start the DMA engine. */ 41544961713Sgirish rs = npi_txdma_channel_init_enable(handle, channel); 41644961713Sgirish 41744961713Sgirish if (rs != NPI_SUCCESS) { 41844961713Sgirish return (NXGE_ERROR | rs); 41944961713Sgirish } 42044961713Sgirish 42144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_enable_txdma_channel")); 42244961713Sgirish 42344961713Sgirish return (status); 42444961713Sgirish } 42544961713Sgirish 42644961713Sgirish void 42744961713Sgirish nxge_fill_tx_hdr(p_mblk_t mp, boolean_t fill_len, 42844961713Sgirish boolean_t l4_cksum, int pkt_len, uint8_t npads, 429b4d05839Sml p_tx_pkt_hdr_all_t pkthdrp, 430b4d05839Sml t_uscalar_t start_offset, 431b4d05839Sml t_uscalar_t stuff_offset) 43244961713Sgirish { 43344961713Sgirish p_tx_pkt_header_t hdrp; 43444961713Sgirish p_mblk_t nmp; 43544961713Sgirish uint64_t tmp; 43644961713Sgirish size_t mblk_len; 43744961713Sgirish size_t iph_len; 43844961713Sgirish size_t hdrs_size; 43944961713Sgirish uint8_t hdrs_buf[sizeof (struct ether_header) + 44052ccf843Smisaki 64 + sizeof (uint32_t)]; 441ae2d3f74Smisaki uint8_t *cursor; 44244961713Sgirish uint8_t *ip_buf; 44344961713Sgirish uint16_t eth_type; 44444961713Sgirish uint8_t ipproto; 44544961713Sgirish boolean_t is_vlan = B_FALSE; 44644961713Sgirish size_t eth_hdr_size; 44744961713Sgirish 44844961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: mp $%p", mp)); 44944961713Sgirish 45044961713Sgirish /* 45144961713Sgirish * Caller should zero out the headers first. 45244961713Sgirish */ 45344961713Sgirish hdrp = (p_tx_pkt_header_t)&pkthdrp->pkthdr; 45444961713Sgirish 45544961713Sgirish if (fill_len) { 45644961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 45752ccf843Smisaki "==> nxge_fill_tx_hdr: pkt_len %d " 45852ccf843Smisaki "npads %d", pkt_len, npads)); 45944961713Sgirish tmp = (uint64_t)pkt_len; 46044961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_TOT_XFER_LEN_SHIFT); 46144961713Sgirish goto fill_tx_header_done; 46244961713Sgirish } 46344961713Sgirish 464b4d05839Sml hdrp->value |= (((uint64_t)npads) << TX_PKT_HEADER_PAD_SHIFT); 46544961713Sgirish 46644961713Sgirish /* 46744961713Sgirish * mp is the original data packet (does not include the 46844961713Sgirish * Neptune transmit header). 46944961713Sgirish */ 47044961713Sgirish nmp = mp; 47144961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: " 47252ccf843Smisaki "mp $%p b_rptr $%p len %d", 47352ccf843Smisaki mp, nmp->b_rptr, MBLKL(nmp))); 474ae2d3f74Smisaki /* copy ether_header from mblk to hdrs_buf */ 475ae2d3f74Smisaki cursor = &hdrs_buf[0]; 476ae2d3f74Smisaki tmp = sizeof (struct ether_vlan_header); 477ae2d3f74Smisaki while ((nmp != NULL) && (tmp > 0)) { 478ae2d3f74Smisaki size_t buflen; 479ae2d3f74Smisaki mblk_len = MBLKL(nmp); 4807c29db66Smisaki buflen = min((size_t)tmp, mblk_len); 481ae2d3f74Smisaki bcopy(nmp->b_rptr, cursor, buflen); 482ae2d3f74Smisaki cursor += buflen; 483ae2d3f74Smisaki tmp -= buflen; 484ae2d3f74Smisaki nmp = nmp->b_cont; 485ae2d3f74Smisaki } 486ae2d3f74Smisaki 487ae2d3f74Smisaki nmp = mp; 488ae2d3f74Smisaki mblk_len = MBLKL(nmp); 48944961713Sgirish ip_buf = NULL; 49044961713Sgirish eth_type = ntohs(((p_ether_header_t)hdrs_buf)->ether_type); 49144961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> : nxge_fill_tx_hdr: (value 0x%llx) " 49252ccf843Smisaki "ether type 0x%x", eth_type, hdrp->value)); 49344961713Sgirish 49444961713Sgirish if (eth_type < ETHERMTU) { 49544961713Sgirish tmp = 1ull; 49644961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_LLC_SHIFT); 49744961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: LLC " 49852ccf843Smisaki "value 0x%llx", hdrp->value)); 49944961713Sgirish if (*(hdrs_buf + sizeof (struct ether_header)) 50052ccf843Smisaki == LLC_SNAP_SAP) { 50144961713Sgirish eth_type = ntohs(*((uint16_t *)(hdrs_buf + 50252ccf843Smisaki sizeof (struct ether_header) + 6))); 50344961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 50452ccf843Smisaki "==> nxge_tx_pkt_hdr_init: LLC ether type 0x%x", 50552ccf843Smisaki eth_type)); 50644961713Sgirish } else { 50744961713Sgirish goto fill_tx_header_done; 50844961713Sgirish } 50944961713Sgirish } else if (eth_type == VLAN_ETHERTYPE) { 51044961713Sgirish tmp = 1ull; 51144961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_VLAN__SHIFT); 51244961713Sgirish 51344961713Sgirish eth_type = ntohs(((struct ether_vlan_header *) 51452ccf843Smisaki hdrs_buf)->ether_type); 51544961713Sgirish is_vlan = B_TRUE; 51644961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: VLAN " 51752ccf843Smisaki "value 0x%llx", hdrp->value)); 51844961713Sgirish } 51944961713Sgirish 52044961713Sgirish if (!is_vlan) { 52144961713Sgirish eth_hdr_size = sizeof (struct ether_header); 52244961713Sgirish } else { 52344961713Sgirish eth_hdr_size = sizeof (struct ether_vlan_header); 52444961713Sgirish } 52544961713Sgirish 52644961713Sgirish switch (eth_type) { 52744961713Sgirish case ETHERTYPE_IP: 52844961713Sgirish if (mblk_len > eth_hdr_size + sizeof (uint8_t)) { 52944961713Sgirish ip_buf = nmp->b_rptr + eth_hdr_size; 53044961713Sgirish mblk_len -= eth_hdr_size; 53144961713Sgirish iph_len = ((*ip_buf) & 0x0f); 53244961713Sgirish if (mblk_len > (iph_len + sizeof (uint32_t))) { 53344961713Sgirish ip_buf = nmp->b_rptr; 53444961713Sgirish ip_buf += eth_hdr_size; 53544961713Sgirish } else { 53644961713Sgirish ip_buf = NULL; 53744961713Sgirish } 53844961713Sgirish 53944961713Sgirish } 54044961713Sgirish if (ip_buf == NULL) { 54144961713Sgirish hdrs_size = 0; 54244961713Sgirish ((p_ether_header_t)hdrs_buf)->ether_type = 0; 54344961713Sgirish while ((nmp) && (hdrs_size < 54452ccf843Smisaki sizeof (hdrs_buf))) { 54544961713Sgirish mblk_len = (size_t)nmp->b_wptr - 54652ccf843Smisaki (size_t)nmp->b_rptr; 54744961713Sgirish if (mblk_len >= 54852ccf843Smisaki (sizeof (hdrs_buf) - hdrs_size)) 54944961713Sgirish mblk_len = sizeof (hdrs_buf) - 55052ccf843Smisaki hdrs_size; 55144961713Sgirish bcopy(nmp->b_rptr, 55252ccf843Smisaki &hdrs_buf[hdrs_size], mblk_len); 55344961713Sgirish hdrs_size += mblk_len; 55444961713Sgirish nmp = nmp->b_cont; 55544961713Sgirish } 55644961713Sgirish ip_buf = hdrs_buf; 55744961713Sgirish ip_buf += eth_hdr_size; 55844961713Sgirish iph_len = ((*ip_buf) & 0x0f); 55944961713Sgirish } 56044961713Sgirish 56144961713Sgirish ipproto = ip_buf[9]; 56244961713Sgirish 56344961713Sgirish tmp = (uint64_t)iph_len; 56444961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_IHL_SHIFT); 56544961713Sgirish tmp = (uint64_t)(eth_hdr_size >> 1); 56644961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_L3START_SHIFT); 56744961713Sgirish 56844961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: IPv4 " 56952ccf843Smisaki " iph_len %d l3start %d eth_hdr_size %d proto 0x%x" 57052ccf843Smisaki "tmp 0x%x", 57152ccf843Smisaki iph_len, hdrp->bits.hdw.l3start, eth_hdr_size, 57252ccf843Smisaki ipproto, tmp)); 57344961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: IP " 57452ccf843Smisaki "value 0x%llx", hdrp->value)); 57544961713Sgirish 57644961713Sgirish break; 57744961713Sgirish 57844961713Sgirish case ETHERTYPE_IPV6: 57944961713Sgirish hdrs_size = 0; 58044961713Sgirish ((p_ether_header_t)hdrs_buf)->ether_type = 0; 58144961713Sgirish while ((nmp) && (hdrs_size < 58252ccf843Smisaki sizeof (hdrs_buf))) { 58344961713Sgirish mblk_len = (size_t)nmp->b_wptr - (size_t)nmp->b_rptr; 58444961713Sgirish if (mblk_len >= 58552ccf843Smisaki (sizeof (hdrs_buf) - hdrs_size)) 58644961713Sgirish mblk_len = sizeof (hdrs_buf) - 58752ccf843Smisaki hdrs_size; 58844961713Sgirish bcopy(nmp->b_rptr, 58952ccf843Smisaki &hdrs_buf[hdrs_size], mblk_len); 59044961713Sgirish hdrs_size += mblk_len; 59144961713Sgirish nmp = nmp->b_cont; 59244961713Sgirish } 59344961713Sgirish ip_buf = hdrs_buf; 59444961713Sgirish ip_buf += eth_hdr_size; 59544961713Sgirish 59644961713Sgirish tmp = 1ull; 59744961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_IP_VER_SHIFT); 59844961713Sgirish 59944961713Sgirish tmp = (eth_hdr_size >> 1); 60044961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_L3START_SHIFT); 60144961713Sgirish 60244961713Sgirish /* byte 6 is the next header protocol */ 60344961713Sgirish ipproto = ip_buf[6]; 60444961713Sgirish 60544961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: IPv6 " 60652ccf843Smisaki " iph_len %d l3start %d eth_hdr_size %d proto 0x%x", 60752ccf843Smisaki iph_len, hdrp->bits.hdw.l3start, eth_hdr_size, 60852ccf843Smisaki ipproto)); 60944961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: IPv6 " 61052ccf843Smisaki "value 0x%llx", hdrp->value)); 61144961713Sgirish 61244961713Sgirish break; 61344961713Sgirish 61444961713Sgirish default: 61544961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: non-IP")); 61644961713Sgirish goto fill_tx_header_done; 61744961713Sgirish } 61844961713Sgirish 61944961713Sgirish switch (ipproto) { 62044961713Sgirish case IPPROTO_TCP: 62144961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 622b4d05839Sml "==> nxge_fill_tx_hdr: TCP (cksum flag %d)", l4_cksum)); 62344961713Sgirish if (l4_cksum) { 624b4d05839Sml hdrp->value |= TX_CKSUM_EN_PKT_TYPE_TCP; 625b4d05839Sml hdrp->value |= 626b4d05839Sml (((uint64_t)(start_offset >> 1)) << 627b4d05839Sml TX_PKT_HEADER_L4START_SHIFT); 628b4d05839Sml hdrp->value |= 629b4d05839Sml (((uint64_t)(stuff_offset >> 1)) << 630b4d05839Sml TX_PKT_HEADER_L4STUFF_SHIFT); 631b4d05839Sml 63244961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 633b4d05839Sml "==> nxge_tx_pkt_hdr_init: TCP CKSUM " 634b4d05839Sml "value 0x%llx", hdrp->value)); 63544961713Sgirish } 63644961713Sgirish 63744961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: TCP " 638b4d05839Sml "value 0x%llx", hdrp->value)); 63944961713Sgirish break; 64044961713Sgirish 64144961713Sgirish case IPPROTO_UDP: 64244961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: UDP")); 64344961713Sgirish if (l4_cksum) { 644b4d05839Sml if (!nxge_cksum_offload) { 645b4d05839Sml uint16_t *up; 646b4d05839Sml uint16_t cksum; 647b4d05839Sml t_uscalar_t stuff_len; 648b4d05839Sml 649b4d05839Sml /* 650b4d05839Sml * The checksum field has the 651b4d05839Sml * partial checksum. 652b4d05839Sml * IP_CSUM() macro calls ip_cksum() which 653b4d05839Sml * can add in the partial checksum. 654b4d05839Sml */ 655b4d05839Sml cksum = IP_CSUM(mp, start_offset, 0); 656b4d05839Sml stuff_len = stuff_offset; 657b4d05839Sml nmp = mp; 658b4d05839Sml mblk_len = MBLKL(nmp); 659b4d05839Sml while ((nmp != NULL) && 660b4d05839Sml (mblk_len < stuff_len)) { 661b4d05839Sml stuff_len -= mblk_len; 662b4d05839Sml nmp = nmp->b_cont; 663b4d05839Sml } 664b4d05839Sml ASSERT(nmp); 665b4d05839Sml up = (uint16_t *)(nmp->b_rptr + stuff_len); 666b4d05839Sml 667b4d05839Sml *up = cksum; 668b4d05839Sml hdrp->value &= ~TX_CKSUM_EN_PKT_TYPE_UDP; 669b4d05839Sml NXGE_DEBUG_MSG((NULL, TX_CTL, 670b4d05839Sml "==> nxge_tx_pkt_hdr_init: UDP offset %d " 671b4d05839Sml "use sw cksum " 672b4d05839Sml "write to $%p cksum 0x%x content up 0x%x", 673b4d05839Sml stuff_len, 674b4d05839Sml up, 675b4d05839Sml cksum, 676b4d05839Sml *up)); 677b4d05839Sml } else { 678b4d05839Sml /* Hardware will compute the full checksum */ 679b4d05839Sml hdrp->value |= TX_CKSUM_EN_PKT_TYPE_UDP; 680b4d05839Sml hdrp->value |= 681b4d05839Sml (((uint64_t)(start_offset >> 1)) << 682b4d05839Sml TX_PKT_HEADER_L4START_SHIFT); 683b4d05839Sml hdrp->value |= 684b4d05839Sml (((uint64_t)(stuff_offset >> 1)) << 685b4d05839Sml TX_PKT_HEADER_L4STUFF_SHIFT); 686b4d05839Sml 687b4d05839Sml NXGE_DEBUG_MSG((NULL, TX_CTL, 688b4d05839Sml "==> nxge_tx_pkt_hdr_init: UDP offset %d " 689b4d05839Sml " use partial checksum " 690b4d05839Sml "cksum 0x%x ", 691b4d05839Sml "value 0x%llx", 692b4d05839Sml stuff_offset, 693b4d05839Sml IP_CSUM(mp, start_offset, 0), 694b4d05839Sml hdrp->value)); 695b4d05839Sml } 69644961713Sgirish } 697b4d05839Sml 69844961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 69952ccf843Smisaki "==> nxge_tx_pkt_hdr_init: UDP" 70052ccf843Smisaki "value 0x%llx", hdrp->value)); 70144961713Sgirish break; 70244961713Sgirish 70344961713Sgirish default: 70444961713Sgirish goto fill_tx_header_done; 70544961713Sgirish } 70644961713Sgirish 70744961713Sgirish fill_tx_header_done: 70844961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 70952ccf843Smisaki "==> nxge_fill_tx_hdr: pkt_len %d " 71052ccf843Smisaki "npads %d value 0x%llx", pkt_len, npads, hdrp->value)); 71144961713Sgirish 71244961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "<== nxge_fill_tx_hdr")); 71344961713Sgirish } 71444961713Sgirish 71544961713Sgirish /*ARGSUSED*/ 71644961713Sgirish p_mblk_t 71744961713Sgirish nxge_tx_pkt_header_reserve(p_mblk_t mp, uint8_t *npads) 71844961713Sgirish { 71944961713Sgirish p_mblk_t newmp = NULL; 72044961713Sgirish 72144961713Sgirish if ((newmp = allocb(TX_PKT_HEADER_SIZE, BPRI_MED)) == NULL) { 72244961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 72352ccf843Smisaki "<== nxge_tx_pkt_header_reserve: allocb failed")); 72444961713Sgirish return (NULL); 72544961713Sgirish } 72644961713Sgirish 72744961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 72852ccf843Smisaki "==> nxge_tx_pkt_header_reserve: get new mp")); 72944961713Sgirish DB_TYPE(newmp) = M_DATA; 73044961713Sgirish newmp->b_rptr = newmp->b_wptr = DB_LIM(newmp); 73144961713Sgirish linkb(newmp, mp); 73244961713Sgirish newmp->b_rptr -= TX_PKT_HEADER_SIZE; 73344961713Sgirish 73444961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==>nxge_tx_pkt_header_reserve: " 73552ccf843Smisaki "b_rptr $%p b_wptr $%p", 73652ccf843Smisaki newmp->b_rptr, newmp->b_wptr)); 73744961713Sgirish 73844961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 73952ccf843Smisaki "<== nxge_tx_pkt_header_reserve: use new mp")); 74044961713Sgirish 74144961713Sgirish return (newmp); 74244961713Sgirish } 74344961713Sgirish 74444961713Sgirish int 74544961713Sgirish nxge_tx_pkt_nmblocks(p_mblk_t mp, int *tot_xfer_len_p) 74644961713Sgirish { 74744961713Sgirish uint_t nmblks; 74844961713Sgirish ssize_t len; 74944961713Sgirish uint_t pkt_len; 75044961713Sgirish p_mblk_t nmp, bmp, tmp; 75144961713Sgirish uint8_t *b_wptr; 75244961713Sgirish 75344961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 75452ccf843Smisaki "==> nxge_tx_pkt_nmblocks: mp $%p rptr $%p wptr $%p " 75552ccf843Smisaki "len %d", mp, mp->b_rptr, mp->b_wptr, MBLKL(mp))); 75644961713Sgirish 75744961713Sgirish nmp = mp; 75844961713Sgirish bmp = mp; 75944961713Sgirish nmblks = 0; 76044961713Sgirish pkt_len = 0; 76144961713Sgirish *tot_xfer_len_p = 0; 76244961713Sgirish 76344961713Sgirish while (nmp) { 76444961713Sgirish len = MBLKL(nmp); 76544961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_nmblocks: " 76652ccf843Smisaki "len %d pkt_len %d nmblks %d tot_xfer_len %d", 76752ccf843Smisaki len, pkt_len, nmblks, 76852ccf843Smisaki *tot_xfer_len_p)); 76944961713Sgirish 77044961713Sgirish if (len <= 0) { 77144961713Sgirish bmp = nmp; 77244961713Sgirish nmp = nmp->b_cont; 77344961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 77452ccf843Smisaki "==> nxge_tx_pkt_nmblocks: " 77552ccf843Smisaki "len (0) pkt_len %d nmblks %d", 77652ccf843Smisaki pkt_len, nmblks)); 77744961713Sgirish continue; 77844961713Sgirish } 77944961713Sgirish 78044961713Sgirish *tot_xfer_len_p += len; 78144961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_nmblocks: " 78252ccf843Smisaki "len %d pkt_len %d nmblks %d tot_xfer_len %d", 78352ccf843Smisaki len, pkt_len, nmblks, 78452ccf843Smisaki *tot_xfer_len_p)); 78544961713Sgirish 78644961713Sgirish if (len < nxge_bcopy_thresh) { 78744961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 78852ccf843Smisaki "==> nxge_tx_pkt_nmblocks: " 78952ccf843Smisaki "len %d (< thresh) pkt_len %d nmblks %d", 79052ccf843Smisaki len, pkt_len, nmblks)); 79144961713Sgirish if (pkt_len == 0) 79244961713Sgirish nmblks++; 79344961713Sgirish pkt_len += len; 79444961713Sgirish if (pkt_len >= nxge_bcopy_thresh) { 79544961713Sgirish pkt_len = 0; 79644961713Sgirish len = 0; 79744961713Sgirish nmp = bmp; 79844961713Sgirish } 79944961713Sgirish } else { 80044961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 80152ccf843Smisaki "==> nxge_tx_pkt_nmblocks: " 80252ccf843Smisaki "len %d (> thresh) pkt_len %d nmblks %d", 80352ccf843Smisaki len, pkt_len, nmblks)); 80444961713Sgirish pkt_len = 0; 80544961713Sgirish nmblks++; 80644961713Sgirish /* 80744961713Sgirish * Hardware limits the transfer length to 4K. 80844961713Sgirish * If len is more than 4K, we need to break 80944961713Sgirish * it up to at most 2 more blocks. 81044961713Sgirish */ 81144961713Sgirish if (len > TX_MAX_TRANSFER_LENGTH) { 81244961713Sgirish uint32_t nsegs; 81344961713Sgirish 814678453a8Sspeer nsegs = 1; 81544961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 81652ccf843Smisaki "==> nxge_tx_pkt_nmblocks: " 81752ccf843Smisaki "len %d pkt_len %d nmblks %d nsegs %d", 81852ccf843Smisaki len, pkt_len, nmblks, nsegs)); 81944961713Sgirish if (len % (TX_MAX_TRANSFER_LENGTH * 2)) { 82044961713Sgirish ++nsegs; 82144961713Sgirish } 82244961713Sgirish do { 82344961713Sgirish b_wptr = nmp->b_rptr + 82452ccf843Smisaki TX_MAX_TRANSFER_LENGTH; 82544961713Sgirish nmp->b_wptr = b_wptr; 82644961713Sgirish if ((tmp = dupb(nmp)) == NULL) { 82744961713Sgirish return (0); 82844961713Sgirish } 82944961713Sgirish tmp->b_rptr = b_wptr; 83044961713Sgirish tmp->b_wptr = nmp->b_wptr; 83144961713Sgirish tmp->b_cont = nmp->b_cont; 83244961713Sgirish nmp->b_cont = tmp; 83344961713Sgirish nmblks++; 83444961713Sgirish if (--nsegs) { 83544961713Sgirish nmp = tmp; 83644961713Sgirish } 83744961713Sgirish } while (nsegs); 83844961713Sgirish nmp = tmp; 83944961713Sgirish } 84044961713Sgirish } 84144961713Sgirish 84244961713Sgirish /* 84344961713Sgirish * Hardware limits the transmit gather pointers to 15. 84444961713Sgirish */ 84544961713Sgirish if (nmp->b_cont && (nmblks + TX_GATHER_POINTERS_THRESHOLD) > 84652ccf843Smisaki TX_MAX_GATHER_POINTERS) { 84744961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 84852ccf843Smisaki "==> nxge_tx_pkt_nmblocks: pull msg - " 84952ccf843Smisaki "len %d pkt_len %d nmblks %d", 85052ccf843Smisaki len, pkt_len, nmblks)); 85144961713Sgirish /* Pull all message blocks from b_cont */ 85244961713Sgirish if ((tmp = msgpullup(nmp->b_cont, -1)) == NULL) { 85344961713Sgirish return (0); 85444961713Sgirish } 85544961713Sgirish freemsg(nmp->b_cont); 85644961713Sgirish nmp->b_cont = tmp; 85744961713Sgirish pkt_len = 0; 85844961713Sgirish } 85944961713Sgirish bmp = nmp; 86044961713Sgirish nmp = nmp->b_cont; 86144961713Sgirish } 86244961713Sgirish 86344961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 86452ccf843Smisaki "<== nxge_tx_pkt_nmblocks: rptr $%p wptr $%p " 86552ccf843Smisaki "nmblks %d len %d tot_xfer_len %d", 86652ccf843Smisaki mp->b_rptr, mp->b_wptr, nmblks, 86752ccf843Smisaki MBLKL(mp), *tot_xfer_len_p)); 86844961713Sgirish 86944961713Sgirish return (nmblks); 87044961713Sgirish } 87144961713Sgirish 872*2d99c5d4SMichael Speer static void 873*2d99c5d4SMichael Speer nxge_txdma_freemsg_list_add(p_tx_ring_t tx_ring_p, p_tx_msg_t msgp) 874*2d99c5d4SMichael Speer { 875*2d99c5d4SMichael Speer MUTEX_ENTER(&tx_ring_p->freelock); 876*2d99c5d4SMichael Speer if (tx_ring_p->tx_free_list_p != NULL) 877*2d99c5d4SMichael Speer msgp->nextp = tx_ring_p->tx_free_list_p; 878*2d99c5d4SMichael Speer tx_ring_p->tx_free_list_p = msgp; 879*2d99c5d4SMichael Speer MUTEX_EXIT(&tx_ring_p->freelock); 880*2d99c5d4SMichael Speer } 881*2d99c5d4SMichael Speer 882*2d99c5d4SMichael Speer /* 883*2d99c5d4SMichael Speer * void 884*2d99c5d4SMichael Speer * nxge_txdma_freemsg_task() -- walk the list of messages to be 885*2d99c5d4SMichael Speer * freed and free the messages. 886*2d99c5d4SMichael Speer */ 887*2d99c5d4SMichael Speer void 888*2d99c5d4SMichael Speer nxge_txdma_freemsg_task(p_tx_ring_t tx_ring_p) 889*2d99c5d4SMichael Speer { 890*2d99c5d4SMichael Speer p_tx_msg_t msgp, nextp; 891*2d99c5d4SMichael Speer 892*2d99c5d4SMichael Speer if (tx_ring_p->tx_free_list_p != NULL) { 893*2d99c5d4SMichael Speer MUTEX_ENTER(&tx_ring_p->freelock); 894*2d99c5d4SMichael Speer msgp = tx_ring_p->tx_free_list_p; 895*2d99c5d4SMichael Speer tx_ring_p->tx_free_list_p = (p_tx_msg_t)NULL; 896*2d99c5d4SMichael Speer MUTEX_EXIT(&tx_ring_p->freelock); 897*2d99c5d4SMichael Speer 898*2d99c5d4SMichael Speer while (msgp != NULL) { 899*2d99c5d4SMichael Speer nextp = msgp->nextp; 900*2d99c5d4SMichael Speer if (msgp->tx_message != NULL) { 901*2d99c5d4SMichael Speer freemsg(msgp->tx_message); 902*2d99c5d4SMichael Speer msgp->tx_message = NULL; 903*2d99c5d4SMichael Speer } 904*2d99c5d4SMichael Speer msgp->nextp = NULL; 905*2d99c5d4SMichael Speer msgp = nextp; 906*2d99c5d4SMichael Speer } 907*2d99c5d4SMichael Speer } 908*2d99c5d4SMichael Speer } 909*2d99c5d4SMichael Speer 91044961713Sgirish boolean_t 91144961713Sgirish nxge_txdma_reclaim(p_nxge_t nxgep, p_tx_ring_t tx_ring_p, int nmblks) 91244961713Sgirish { 91344961713Sgirish boolean_t status = B_TRUE; 91444961713Sgirish p_nxge_dma_common_t tx_desc_dma_p; 91544961713Sgirish nxge_dma_common_t desc_area; 91644961713Sgirish p_tx_desc_t tx_desc_ring_vp; 91744961713Sgirish p_tx_desc_t tx_desc_p; 91844961713Sgirish p_tx_desc_t tx_desc_pp; 91944961713Sgirish tx_desc_t r_tx_desc; 92044961713Sgirish p_tx_msg_t tx_msg_ring; 92144961713Sgirish p_tx_msg_t tx_msg_p; 92244961713Sgirish npi_handle_t handle; 92344961713Sgirish tx_ring_hdl_t tx_head; 92444961713Sgirish uint32_t pkt_len; 92544961713Sgirish uint_t tx_rd_index; 92644961713Sgirish uint16_t head_index, tail_index; 92744961713Sgirish uint8_t tdc; 92844961713Sgirish boolean_t head_wrap, tail_wrap; 929*2d99c5d4SMichael Speer p_nxge_tx_ring_stats_t tdc_stats; 93044961713Sgirish int rc; 93144961713Sgirish 93244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_reclaim")); 93344961713Sgirish 93444961713Sgirish status = ((tx_ring_p->descs_pending < nxge_reclaim_pending) && 93552ccf843Smisaki (nmblks != 0)); 93644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 93752ccf843Smisaki "==> nxge_txdma_reclaim: pending %d reclaim %d nmblks %d", 93852ccf843Smisaki tx_ring_p->descs_pending, nxge_reclaim_pending, 93952ccf843Smisaki nmblks)); 94044961713Sgirish if (!status) { 94144961713Sgirish tx_desc_dma_p = &tx_ring_p->tdc_desc; 94244961713Sgirish desc_area = tx_ring_p->tdc_desc; 94344961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 94444961713Sgirish tx_desc_ring_vp = tx_desc_dma_p->kaddrp; 94544961713Sgirish tx_desc_ring_vp = 94652ccf843Smisaki (p_tx_desc_t)DMA_COMMON_VPTR(desc_area); 94744961713Sgirish tx_rd_index = tx_ring_p->rd_index; 94844961713Sgirish tx_desc_p = &tx_desc_ring_vp[tx_rd_index]; 94944961713Sgirish tx_msg_ring = tx_ring_p->tx_msg_ring; 95044961713Sgirish tx_msg_p = &tx_msg_ring[tx_rd_index]; 95144961713Sgirish tdc = tx_ring_p->tdc; 95244961713Sgirish tdc_stats = tx_ring_p->tdc_stats; 95344961713Sgirish if (tx_ring_p->descs_pending > tdc_stats->tx_max_pend) { 95444961713Sgirish tdc_stats->tx_max_pend = tx_ring_p->descs_pending; 95544961713Sgirish } 95644961713Sgirish 95744961713Sgirish tail_index = tx_ring_p->wr_index; 95844961713Sgirish tail_wrap = tx_ring_p->wr_index_wrap; 95944961713Sgirish 96044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 96152ccf843Smisaki "==> nxge_txdma_reclaim: tdc %d tx_rd_index %d " 96252ccf843Smisaki "tail_index %d tail_wrap %d " 96352ccf843Smisaki "tx_desc_p $%p ($%p) ", 96452ccf843Smisaki tdc, tx_rd_index, tail_index, tail_wrap, 96552ccf843Smisaki tx_desc_p, (*(uint64_t *)tx_desc_p))); 96644961713Sgirish /* 96744961713Sgirish * Read the hardware maintained transmit head 96844961713Sgirish * and wrap around bit. 96944961713Sgirish */ 97044961713Sgirish TXDMA_REG_READ64(handle, TX_RING_HDL_REG, tdc, &tx_head.value); 97144961713Sgirish head_index = tx_head.bits.ldw.head; 97244961713Sgirish head_wrap = tx_head.bits.ldw.wrap; 97344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 97452ccf843Smisaki "==> nxge_txdma_reclaim: " 97552ccf843Smisaki "tx_rd_index %d tail %d tail_wrap %d " 97652ccf843Smisaki "head %d wrap %d", 97752ccf843Smisaki tx_rd_index, tail_index, tail_wrap, 97852ccf843Smisaki head_index, head_wrap)); 97944961713Sgirish 98044961713Sgirish if (head_index == tail_index) { 98144961713Sgirish if (TXDMA_RING_EMPTY(head_index, head_wrap, 98252ccf843Smisaki tail_index, tail_wrap) && 98352ccf843Smisaki (head_index == tx_rd_index)) { 98444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 98552ccf843Smisaki "==> nxge_txdma_reclaim: EMPTY")); 98644961713Sgirish return (B_TRUE); 98744961713Sgirish } 98844961713Sgirish 98944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 99052ccf843Smisaki "==> nxge_txdma_reclaim: Checking " 99152ccf843Smisaki "if ring full")); 99244961713Sgirish if (TXDMA_RING_FULL(head_index, head_wrap, tail_index, 99352ccf843Smisaki tail_wrap)) { 99444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 99552ccf843Smisaki "==> nxge_txdma_reclaim: full")); 99644961713Sgirish return (B_FALSE); 99744961713Sgirish } 99844961713Sgirish } 99944961713Sgirish 100044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 100152ccf843Smisaki "==> nxge_txdma_reclaim: tx_rd_index and head_index")); 100244961713Sgirish 100344961713Sgirish tx_desc_pp = &r_tx_desc; 100444961713Sgirish while ((tx_rd_index != head_index) && 100552ccf843Smisaki (tx_ring_p->descs_pending != 0)) { 100644961713Sgirish 100744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 100852ccf843Smisaki "==> nxge_txdma_reclaim: Checking if pending")); 100944961713Sgirish 101044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 101152ccf843Smisaki "==> nxge_txdma_reclaim: " 101252ccf843Smisaki "descs_pending %d ", 101352ccf843Smisaki tx_ring_p->descs_pending)); 101444961713Sgirish 101544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 101652ccf843Smisaki "==> nxge_txdma_reclaim: " 101752ccf843Smisaki "(tx_rd_index %d head_index %d " 101852ccf843Smisaki "(tx_desc_p $%p)", 101952ccf843Smisaki tx_rd_index, head_index, 102052ccf843Smisaki tx_desc_p)); 102144961713Sgirish 102244961713Sgirish tx_desc_pp->value = tx_desc_p->value; 102344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 102452ccf843Smisaki "==> nxge_txdma_reclaim: " 102552ccf843Smisaki "(tx_rd_index %d head_index %d " 102652ccf843Smisaki "tx_desc_p $%p (desc value 0x%llx) ", 102752ccf843Smisaki tx_rd_index, head_index, 102852ccf843Smisaki tx_desc_pp, (*(uint64_t *)tx_desc_pp))); 102944961713Sgirish 103044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 103152ccf843Smisaki "==> nxge_txdma_reclaim: dump desc:")); 103244961713Sgirish 103344961713Sgirish pkt_len = tx_desc_pp->bits.hdw.tr_len; 103444961713Sgirish tdc_stats->obytes += pkt_len; 103544961713Sgirish tdc_stats->opackets += tx_desc_pp->bits.hdw.sop; 103644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 103752ccf843Smisaki "==> nxge_txdma_reclaim: pkt_len %d " 103852ccf843Smisaki "tdc channel %d opackets %d", 103952ccf843Smisaki pkt_len, 104052ccf843Smisaki tdc, 104152ccf843Smisaki tdc_stats->opackets)); 104244961713Sgirish 104344961713Sgirish if (tx_msg_p->flags.dma_type == USE_DVMA) { 104444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 104552ccf843Smisaki "tx_desc_p = $%p " 104652ccf843Smisaki "tx_desc_pp = $%p " 104752ccf843Smisaki "index = %d", 104852ccf843Smisaki tx_desc_p, 104952ccf843Smisaki tx_desc_pp, 105052ccf843Smisaki tx_ring_p->rd_index)); 105144961713Sgirish (void) dvma_unload(tx_msg_p->dvma_handle, 105252ccf843Smisaki 0, -1); 105344961713Sgirish tx_msg_p->dvma_handle = NULL; 105444961713Sgirish if (tx_ring_p->dvma_wr_index == 105552ccf843Smisaki tx_ring_p->dvma_wrap_mask) { 105644961713Sgirish tx_ring_p->dvma_wr_index = 0; 105744961713Sgirish } else { 105844961713Sgirish tx_ring_p->dvma_wr_index++; 105944961713Sgirish } 106044961713Sgirish tx_ring_p->dvma_pending--; 106144961713Sgirish } else if (tx_msg_p->flags.dma_type == 106252ccf843Smisaki USE_DMA) { 106344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 106452ccf843Smisaki "==> nxge_txdma_reclaim: " 106552ccf843Smisaki "USE DMA")); 106644961713Sgirish if (rc = ddi_dma_unbind_handle 106752ccf843Smisaki (tx_msg_p->dma_handle)) { 106844961713Sgirish cmn_err(CE_WARN, "!nxge_reclaim: " 106952ccf843Smisaki "ddi_dma_unbind_handle " 107052ccf843Smisaki "failed. status %d", rc); 107144961713Sgirish } 107244961713Sgirish } 107344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 107452ccf843Smisaki "==> nxge_txdma_reclaim: count packets")); 1075*2d99c5d4SMichael Speer 107644961713Sgirish /* 107744961713Sgirish * count a chained packet only once. 107844961713Sgirish */ 107944961713Sgirish if (tx_msg_p->tx_message != NULL) { 1080*2d99c5d4SMichael Speer nxge_txdma_freemsg_list_add(tx_ring_p, 1081*2d99c5d4SMichael Speer tx_msg_p); 108244961713Sgirish } 108344961713Sgirish 108444961713Sgirish tx_msg_p->flags.dma_type = USE_NONE; 108544961713Sgirish tx_rd_index = tx_ring_p->rd_index; 108644961713Sgirish tx_rd_index = (tx_rd_index + 1) & 108752ccf843Smisaki tx_ring_p->tx_wrap_mask; 108844961713Sgirish tx_ring_p->rd_index = tx_rd_index; 108944961713Sgirish tx_ring_p->descs_pending--; 109044961713Sgirish tx_desc_p = &tx_desc_ring_vp[tx_rd_index]; 109144961713Sgirish tx_msg_p = &tx_msg_ring[tx_rd_index]; 109244961713Sgirish } 109344961713Sgirish 109444961713Sgirish status = (nmblks <= (tx_ring_p->tx_ring_size - 109552ccf843Smisaki tx_ring_p->descs_pending - 109652ccf843Smisaki TX_FULL_MARK)); 109744961713Sgirish if (status) { 109844961713Sgirish cas32((uint32_t *)&tx_ring_p->queueing, 1, 0); 109944961713Sgirish } 110044961713Sgirish } else { 110144961713Sgirish status = (nmblks <= 110252ccf843Smisaki (tx_ring_p->tx_ring_size - 110352ccf843Smisaki tx_ring_p->descs_pending - 110452ccf843Smisaki TX_FULL_MARK)); 110544961713Sgirish } 110644961713Sgirish 110744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 110852ccf843Smisaki "<== nxge_txdma_reclaim status = 0x%08x", status)); 110944961713Sgirish 111044961713Sgirish return (status); 111144961713Sgirish } 111244961713Sgirish 1113678453a8Sspeer /* 1114678453a8Sspeer * nxge_tx_intr 1115678453a8Sspeer * 1116678453a8Sspeer * Process a TDC interrupt 1117678453a8Sspeer * 1118678453a8Sspeer * Arguments: 1119678453a8Sspeer * arg1 A Logical Device state Vector (LSV) data structure. 1120678453a8Sspeer * arg2 nxge_t * 1121678453a8Sspeer * 1122678453a8Sspeer * Notes: 1123678453a8Sspeer * 1124678453a8Sspeer * NPI/NXGE function calls: 1125678453a8Sspeer * npi_txdma_control_status() 1126678453a8Sspeer * npi_intr_ldg_mgmt_set() 1127678453a8Sspeer * 1128678453a8Sspeer * nxge_tx_err_evnts() 1129678453a8Sspeer * nxge_txdma_reclaim() 1130678453a8Sspeer * 1131678453a8Sspeer * Registers accessed: 1132678453a8Sspeer * TX_CS DMC+0x40028 Transmit Control And Status 1133678453a8Sspeer * PIO_LDSV 1134678453a8Sspeer * 1135678453a8Sspeer * Context: 1136678453a8Sspeer * Any domain 1137678453a8Sspeer */ 113844961713Sgirish uint_t 113944961713Sgirish nxge_tx_intr(void *arg1, void *arg2) 114044961713Sgirish { 114144961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 114244961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 114344961713Sgirish p_nxge_ldg_t ldgp; 114444961713Sgirish uint8_t channel; 114544961713Sgirish uint32_t vindex; 114644961713Sgirish npi_handle_t handle; 114744961713Sgirish tx_cs_t cs; 114844961713Sgirish p_tx_ring_t *tx_rings; 114944961713Sgirish p_tx_ring_t tx_ring_p; 115044961713Sgirish npi_status_t rs = NPI_SUCCESS; 115144961713Sgirish uint_t serviced = DDI_INTR_UNCLAIMED; 115244961713Sgirish nxge_status_t status = NXGE_OK; 115344961713Sgirish 115444961713Sgirish if (ldvp == NULL) { 115544961713Sgirish NXGE_DEBUG_MSG((NULL, INT_CTL, 115652ccf843Smisaki "<== nxge_tx_intr: nxgep $%p ldvp $%p", 115752ccf843Smisaki nxgep, ldvp)); 115844961713Sgirish return (DDI_INTR_UNCLAIMED); 115944961713Sgirish } 116044961713Sgirish 116144961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 116244961713Sgirish nxgep = ldvp->nxgep; 116344961713Sgirish } 116444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 116552ccf843Smisaki "==> nxge_tx_intr: nxgep(arg2) $%p ldvp(arg1) $%p", 116652ccf843Smisaki nxgep, ldvp)); 116722c0d73aSspeer 116822c0d73aSspeer if ((!(nxgep->drv_state & STATE_HW_INITIALIZED)) || 116922c0d73aSspeer (nxgep->nxge_mac_state != NXGE_MAC_STARTED)) { 117022c0d73aSspeer NXGE_DEBUG_MSG((nxgep, INT_CTL, 117122c0d73aSspeer "<== nxge_tx_intr: interface not started or intialized")); 117222c0d73aSspeer return (DDI_INTR_CLAIMED); 117322c0d73aSspeer } 117422c0d73aSspeer 117544961713Sgirish /* 117644961713Sgirish * This interrupt handler is for a specific 117744961713Sgirish * transmit dma channel. 117844961713Sgirish */ 117944961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 118044961713Sgirish /* Get the control and status for this channel. */ 118144961713Sgirish channel = ldvp->channel; 118244961713Sgirish ldgp = ldvp->ldgp; 118344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 118452ccf843Smisaki "==> nxge_tx_intr: nxgep $%p ldvp (ldvp) $%p " 118552ccf843Smisaki "channel %d", 118652ccf843Smisaki nxgep, ldvp, channel)); 118744961713Sgirish 118844961713Sgirish rs = npi_txdma_control_status(handle, OP_GET, channel, &cs); 118944961713Sgirish vindex = ldvp->vdma_index; 119044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 119152ccf843Smisaki "==> nxge_tx_intr:channel %d ring index %d status 0x%08x", 119252ccf843Smisaki channel, vindex, rs)); 119344961713Sgirish if (!rs && cs.bits.ldw.mk) { 119444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 119552ccf843Smisaki "==> nxge_tx_intr:channel %d ring index %d " 119652ccf843Smisaki "status 0x%08x (mk bit set)", 119752ccf843Smisaki channel, vindex, rs)); 119844961713Sgirish tx_rings = nxgep->tx_rings->rings; 119944961713Sgirish tx_ring_p = tx_rings[vindex]; 120044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 120152ccf843Smisaki "==> nxge_tx_intr:channel %d ring index %d " 120252ccf843Smisaki "status 0x%08x (mk bit set, calling reclaim)", 120352ccf843Smisaki channel, vindex, rs)); 120444961713Sgirish 120544961713Sgirish MUTEX_ENTER(&tx_ring_p->lock); 120644961713Sgirish (void) nxge_txdma_reclaim(nxgep, tx_rings[vindex], 0); 120744961713Sgirish MUTEX_EXIT(&tx_ring_p->lock); 1208*2d99c5d4SMichael Speer 1209*2d99c5d4SMichael Speer nxge_txdma_freemsg_task(tx_ring_p); 1210*2d99c5d4SMichael Speer 121144961713Sgirish mac_tx_update(nxgep->mach); 121244961713Sgirish } 121344961713Sgirish 121444961713Sgirish /* 121544961713Sgirish * Process other transmit control and status. 121644961713Sgirish * Check the ldv state. 121744961713Sgirish */ 121844961713Sgirish status = nxge_tx_err_evnts(nxgep, ldvp->vdma_index, ldvp, cs); 121944961713Sgirish /* 122044961713Sgirish * Rearm this logical group if this is a single device 122144961713Sgirish * group. 122244961713Sgirish */ 122344961713Sgirish if (ldgp->nldvs == 1) { 122444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 122552ccf843Smisaki "==> nxge_tx_intr: rearm")); 122644961713Sgirish if (status == NXGE_OK) { 1227678453a8Sspeer if (isLDOMguest(nxgep)) { 1228678453a8Sspeer nxge_hio_ldgimgn(nxgep, ldgp); 1229678453a8Sspeer } else { 1230678453a8Sspeer (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 1231678453a8Sspeer B_TRUE, ldgp->ldg_timer); 1232678453a8Sspeer } 123344961713Sgirish } 123444961713Sgirish } 123544961713Sgirish 123644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_tx_intr")); 123744961713Sgirish serviced = DDI_INTR_CLAIMED; 123844961713Sgirish return (serviced); 123944961713Sgirish } 124044961713Sgirish 124144961713Sgirish void 1242678453a8Sspeer nxge_txdma_stop(p_nxge_t nxgep) /* Dead */ 124344961713Sgirish { 124444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop")); 124544961713Sgirish 124644961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 124744961713Sgirish 124844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop")); 124944961713Sgirish } 125044961713Sgirish 125144961713Sgirish void 1252678453a8Sspeer nxge_txdma_stop_start(p_nxge_t nxgep) /* Dead */ 125344961713Sgirish { 125444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop_start")); 125544961713Sgirish 125644961713Sgirish (void) nxge_txdma_stop(nxgep); 125744961713Sgirish 125844961713Sgirish (void) nxge_fixup_txdma_rings(nxgep); 125944961713Sgirish (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START); 126044961713Sgirish (void) nxge_tx_mac_enable(nxgep); 126144961713Sgirish (void) nxge_txdma_hw_kick(nxgep); 126244961713Sgirish 126344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop_start")); 126444961713Sgirish } 126544961713Sgirish 1266678453a8Sspeer npi_status_t 1267678453a8Sspeer nxge_txdma_channel_disable( 1268678453a8Sspeer nxge_t *nxge, 1269678453a8Sspeer int channel) 1270678453a8Sspeer { 1271678453a8Sspeer npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxge); 1272678453a8Sspeer npi_status_t rs; 1273678453a8Sspeer tdmc_intr_dbg_t intr_dbg; 1274678453a8Sspeer 1275678453a8Sspeer /* 1276678453a8Sspeer * Stop the dma channel and wait for the stop-done. 1277678453a8Sspeer * If the stop-done bit is not present, then force 1278678453a8Sspeer * an error so TXC will stop. 1279678453a8Sspeer * All channels bound to this port need to be stopped 1280678453a8Sspeer * and reset after injecting an interrupt error. 1281678453a8Sspeer */ 1282678453a8Sspeer rs = npi_txdma_channel_disable(handle, channel); 1283678453a8Sspeer NXGE_DEBUG_MSG((nxge, MEM3_CTL, 128452ccf843Smisaki "==> nxge_txdma_channel_disable(%d) " 128552ccf843Smisaki "rs 0x%x", channel, rs)); 1286678453a8Sspeer if (rs != NPI_SUCCESS) { 1287678453a8Sspeer /* Inject any error */ 1288678453a8Sspeer intr_dbg.value = 0; 1289678453a8Sspeer intr_dbg.bits.ldw.nack_pref = 1; 1290678453a8Sspeer NXGE_DEBUG_MSG((nxge, MEM3_CTL, 129152ccf843Smisaki "==> nxge_txdma_hw_mode: " 129252ccf843Smisaki "channel %d (stop failed 0x%x) " 129352ccf843Smisaki "(inject err)", rs, channel)); 1294678453a8Sspeer (void) npi_txdma_inj_int_error_set( 129552ccf843Smisaki handle, channel, &intr_dbg); 1296678453a8Sspeer rs = npi_txdma_channel_disable(handle, channel); 1297678453a8Sspeer NXGE_DEBUG_MSG((nxge, MEM3_CTL, 129852ccf843Smisaki "==> nxge_txdma_hw_mode: " 129952ccf843Smisaki "channel %d (stop again 0x%x) " 130052ccf843Smisaki "(after inject err)", 130152ccf843Smisaki rs, channel)); 1302678453a8Sspeer } 1303678453a8Sspeer 1304678453a8Sspeer return (rs); 1305678453a8Sspeer } 1306678453a8Sspeer 1307678453a8Sspeer /* 1308678453a8Sspeer * nxge_txdma_hw_mode 1309678453a8Sspeer * 1310678453a8Sspeer * Toggle all TDCs on (enable) or off (disable). 1311678453a8Sspeer * 1312678453a8Sspeer * Arguments: 1313678453a8Sspeer * nxgep 1314678453a8Sspeer * enable Enable or disable a TDC. 1315678453a8Sspeer * 1316678453a8Sspeer * Notes: 1317678453a8Sspeer * 1318678453a8Sspeer * NPI/NXGE function calls: 1319678453a8Sspeer * npi_txdma_channel_enable(TX_CS) 1320678453a8Sspeer * npi_txdma_channel_disable(TX_CS) 1321678453a8Sspeer * npi_txdma_inj_int_error_set(TDMC_INTR_DBG) 1322678453a8Sspeer * 1323678453a8Sspeer * Registers accessed: 1324678453a8Sspeer * TX_CS DMC+0x40028 Transmit Control And Status 1325678453a8Sspeer * TDMC_INTR_DBG DMC + 0x40060 Transmit DMA Interrupt Debug 1326678453a8Sspeer * 1327678453a8Sspeer * Context: 1328678453a8Sspeer * Any domain 1329678453a8Sspeer */ 133044961713Sgirish nxge_status_t 133144961713Sgirish nxge_txdma_hw_mode(p_nxge_t nxgep, boolean_t enable) 133244961713Sgirish { 1333678453a8Sspeer nxge_grp_set_t *set = &nxgep->tx_set; 1334678453a8Sspeer 1335678453a8Sspeer npi_handle_t handle; 1336678453a8Sspeer nxge_status_t status; 1337678453a8Sspeer npi_status_t rs; 1338678453a8Sspeer int tdc; 133944961713Sgirish 134044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 134152ccf843Smisaki "==> nxge_txdma_hw_mode: enable mode %d", enable)); 134244961713Sgirish 134344961713Sgirish if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 134444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 134552ccf843Smisaki "<== nxge_txdma_mode: not initialized")); 134644961713Sgirish return (NXGE_ERROR); 134744961713Sgirish } 134844961713Sgirish 1349678453a8Sspeer if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 135044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 1351678453a8Sspeer "<== nxge_txdma_hw_mode: NULL ring pointer(s)")); 135244961713Sgirish return (NXGE_ERROR); 135344961713Sgirish } 135444961713Sgirish 1355678453a8Sspeer /* Enable or disable all of the TDCs owned by us. */ 135644961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 1357678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 1358678453a8Sspeer if ((1 << tdc) & set->owned.map) { 1359678453a8Sspeer tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 1360678453a8Sspeer if (ring) { 1361678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 1362678453a8Sspeer "==> nxge_txdma_hw_mode: channel %d", tdc)); 1363678453a8Sspeer if (enable) { 1364678453a8Sspeer rs = npi_txdma_channel_enable 1365678453a8Sspeer (handle, tdc); 136644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 1367678453a8Sspeer "==> nxge_txdma_hw_mode: " 1368678453a8Sspeer "channel %d (enable) rs 0x%x", 1369678453a8Sspeer tdc, rs)); 1370678453a8Sspeer } else { 1371678453a8Sspeer rs = nxge_txdma_channel_disable 1372678453a8Sspeer (nxgep, tdc); 137344961713Sgirish } 137444961713Sgirish } 137544961713Sgirish } 137644961713Sgirish } 137744961713Sgirish 137844961713Sgirish status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs); 137944961713Sgirish 138044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 138152ccf843Smisaki "<== nxge_txdma_hw_mode: status 0x%x", status)); 138244961713Sgirish 138344961713Sgirish return (status); 138444961713Sgirish } 138544961713Sgirish 138644961713Sgirish void 138744961713Sgirish nxge_txdma_enable_channel(p_nxge_t nxgep, uint16_t channel) 138844961713Sgirish { 138944961713Sgirish npi_handle_t handle; 139044961713Sgirish 139144961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 139252ccf843Smisaki "==> nxge_txdma_enable_channel: channel %d", channel)); 139344961713Sgirish 139444961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 139544961713Sgirish /* enable the transmit dma channels */ 139644961713Sgirish (void) npi_txdma_channel_enable(handle, channel); 139744961713Sgirish 139844961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_txdma_enable_channel")); 139944961713Sgirish } 140044961713Sgirish 140144961713Sgirish void 140244961713Sgirish nxge_txdma_disable_channel(p_nxge_t nxgep, uint16_t channel) 140344961713Sgirish { 140444961713Sgirish npi_handle_t handle; 140544961713Sgirish 140644961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 140752ccf843Smisaki "==> nxge_txdma_disable_channel: channel %d", channel)); 140844961713Sgirish 140944961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 141044961713Sgirish /* stop the transmit dma channels */ 141144961713Sgirish (void) npi_txdma_channel_disable(handle, channel); 141244961713Sgirish 141344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_disable_channel")); 141444961713Sgirish } 141544961713Sgirish 1416678453a8Sspeer /* 1417678453a8Sspeer * nxge_txdma_stop_inj_err 1418678453a8Sspeer * 1419678453a8Sspeer * Stop a TDC. If at first we don't succeed, inject an error. 1420678453a8Sspeer * 1421678453a8Sspeer * Arguments: 1422678453a8Sspeer * nxgep 1423678453a8Sspeer * channel The channel to stop. 1424678453a8Sspeer * 1425678453a8Sspeer * Notes: 1426678453a8Sspeer * 1427678453a8Sspeer * NPI/NXGE function calls: 1428678453a8Sspeer * npi_txdma_channel_disable() 1429678453a8Sspeer * npi_txdma_inj_int_error_set() 1430678453a8Sspeer * #if defined(NXGE_DEBUG) 1431678453a8Sspeer * nxge_txdma_regs_dump_channels(nxgep); 1432678453a8Sspeer * #endif 1433678453a8Sspeer * 1434678453a8Sspeer * Registers accessed: 1435678453a8Sspeer * TX_CS DMC+0x40028 Transmit Control And Status 1436678453a8Sspeer * TDMC_INTR_DBG DMC + 0x40060 Transmit DMA Interrupt Debug 1437678453a8Sspeer * 1438678453a8Sspeer * Context: 1439678453a8Sspeer * Any domain 1440678453a8Sspeer */ 144144961713Sgirish int 144244961713Sgirish nxge_txdma_stop_inj_err(p_nxge_t nxgep, int channel) 144344961713Sgirish { 144444961713Sgirish npi_handle_t handle; 144544961713Sgirish tdmc_intr_dbg_t intr_dbg; 144644961713Sgirish int status; 144744961713Sgirish npi_status_t rs = NPI_SUCCESS; 144844961713Sgirish 144944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop_inj_err")); 145044961713Sgirish /* 145144961713Sgirish * Stop the dma channel waits for the stop done. 145244961713Sgirish * If the stop done bit is not set, then create 145344961713Sgirish * an error. 145444961713Sgirish */ 145544961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 145644961713Sgirish rs = npi_txdma_channel_disable(handle, channel); 145744961713Sgirish status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs); 145844961713Sgirish if (status == NXGE_OK) { 145944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 146052ccf843Smisaki "<== nxge_txdma_stop_inj_err (channel %d): " 146152ccf843Smisaki "stopped OK", channel)); 146244961713Sgirish return (status); 146344961713Sgirish } 146444961713Sgirish 146544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 146652ccf843Smisaki "==> nxge_txdma_stop_inj_err (channel %d): stop failed (0x%x) " 146752ccf843Smisaki "injecting error", channel, rs)); 146844961713Sgirish /* Inject any error */ 146944961713Sgirish intr_dbg.value = 0; 147044961713Sgirish intr_dbg.bits.ldw.nack_pref = 1; 147144961713Sgirish (void) npi_txdma_inj_int_error_set(handle, channel, &intr_dbg); 147244961713Sgirish 147344961713Sgirish /* Stop done bit will be set as a result of error injection */ 147444961713Sgirish rs = npi_txdma_channel_disable(handle, channel); 147544961713Sgirish status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs); 147644961713Sgirish if (!(rs & NPI_TXDMA_STOP_FAILED)) { 147744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 147852ccf843Smisaki "<== nxge_txdma_stop_inj_err (channel %d): " 147952ccf843Smisaki "stopped OK ", channel)); 148044961713Sgirish return (status); 148144961713Sgirish } 148244961713Sgirish 148344961713Sgirish #if defined(NXGE_DEBUG) 148444961713Sgirish nxge_txdma_regs_dump_channels(nxgep); 148544961713Sgirish #endif 148644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 148752ccf843Smisaki "==> nxge_txdma_stop_inj_err (channel): stop failed (0x%x) " 148852ccf843Smisaki " (injected error but still not stopped)", channel, rs)); 148944961713Sgirish 149044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop_inj_err")); 149144961713Sgirish return (status); 149244961713Sgirish } 149344961713Sgirish 149444961713Sgirish /*ARGSUSED*/ 149544961713Sgirish void 149644961713Sgirish nxge_fixup_txdma_rings(p_nxge_t nxgep) 149744961713Sgirish { 1498678453a8Sspeer nxge_grp_set_t *set = &nxgep->tx_set; 1499678453a8Sspeer int tdc; 150044961713Sgirish 150144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_fixup_txdma_rings")); 150244961713Sgirish 1503678453a8Sspeer if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 1504678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, 1505678453a8Sspeer "<== nxge_fixup_txdma_rings: NULL ring pointer(s)")); 150644961713Sgirish return; 150744961713Sgirish } 150844961713Sgirish 1509678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 1510678453a8Sspeer if ((1 << tdc) & set->owned.map) { 1511678453a8Sspeer tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 1512678453a8Sspeer if (ring) { 1513678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 1514678453a8Sspeer "==> nxge_fixup_txdma_rings: channel %d", 1515678453a8Sspeer tdc)); 1516678453a8Sspeer nxge_txdma_fixup_channel(nxgep, ring, tdc); 1517678453a8Sspeer } 1518678453a8Sspeer } 151944961713Sgirish } 152044961713Sgirish 152144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_fixup_txdma_rings")); 152244961713Sgirish } 152344961713Sgirish 152444961713Sgirish /*ARGSUSED*/ 152544961713Sgirish void 152644961713Sgirish nxge_txdma_fix_channel(p_nxge_t nxgep, uint16_t channel) 152744961713Sgirish { 152844961713Sgirish p_tx_ring_t ring_p; 152944961713Sgirish 153044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fix_channel")); 153144961713Sgirish ring_p = nxge_txdma_get_ring(nxgep, channel); 153244961713Sgirish if (ring_p == NULL) { 153344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_channel")); 153444961713Sgirish return; 153544961713Sgirish } 153644961713Sgirish 153744961713Sgirish if (ring_p->tdc != channel) { 153844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 153952ccf843Smisaki "<== nxge_txdma_fix_channel: channel not matched " 154052ccf843Smisaki "ring tdc %d passed channel", 154152ccf843Smisaki ring_p->tdc, channel)); 154244961713Sgirish return; 154344961713Sgirish } 154444961713Sgirish 154544961713Sgirish nxge_txdma_fixup_channel(nxgep, ring_p, channel); 154644961713Sgirish 154744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_channel")); 154844961713Sgirish } 154944961713Sgirish 155044961713Sgirish /*ARGSUSED*/ 155144961713Sgirish void 155244961713Sgirish nxge_txdma_fixup_channel(p_nxge_t nxgep, p_tx_ring_t ring_p, uint16_t channel) 155344961713Sgirish { 155444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fixup_channel")); 155544961713Sgirish 155644961713Sgirish if (ring_p == NULL) { 155744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 155852ccf843Smisaki "<== nxge_txdma_fixup_channel: NULL ring pointer")); 155944961713Sgirish return; 156044961713Sgirish } 156144961713Sgirish 156244961713Sgirish if (ring_p->tdc != channel) { 156344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 156452ccf843Smisaki "<== nxge_txdma_fixup_channel: channel not matched " 156552ccf843Smisaki "ring tdc %d passed channel", 156652ccf843Smisaki ring_p->tdc, channel)); 156744961713Sgirish return; 156844961713Sgirish } 156944961713Sgirish 157044961713Sgirish MUTEX_ENTER(&ring_p->lock); 157144961713Sgirish (void) nxge_txdma_reclaim(nxgep, ring_p, 0); 157244961713Sgirish ring_p->rd_index = 0; 157344961713Sgirish ring_p->wr_index = 0; 157444961713Sgirish ring_p->ring_head.value = 0; 157544961713Sgirish ring_p->ring_kick_tail.value = 0; 157644961713Sgirish ring_p->descs_pending = 0; 157744961713Sgirish MUTEX_EXIT(&ring_p->lock); 1578*2d99c5d4SMichael Speer nxge_txdma_freemsg_task(ring_p); 157944961713Sgirish 158044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fixup_channel")); 158144961713Sgirish } 158244961713Sgirish 158344961713Sgirish /*ARGSUSED*/ 158444961713Sgirish void 158544961713Sgirish nxge_txdma_hw_kick(p_nxge_t nxgep) 158644961713Sgirish { 1587678453a8Sspeer nxge_grp_set_t *set = &nxgep->tx_set; 1588678453a8Sspeer int tdc; 158944961713Sgirish 159044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hw_kick")); 159144961713Sgirish 1592678453a8Sspeer if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 159344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 1594678453a8Sspeer "<== nxge_txdma_hw_kick: NULL ring pointer(s)")); 159544961713Sgirish return; 159644961713Sgirish } 159744961713Sgirish 1598678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 1599678453a8Sspeer if ((1 << tdc) & set->owned.map) { 1600678453a8Sspeer tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 1601678453a8Sspeer if (ring) { 1602678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 1603678453a8Sspeer "==> nxge_txdma_hw_kick: channel %d", tdc)); 1604678453a8Sspeer nxge_txdma_hw_kick_channel(nxgep, ring, tdc); 1605678453a8Sspeer } 1606678453a8Sspeer } 160744961713Sgirish } 160844961713Sgirish 160944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hw_kick")); 161044961713Sgirish } 161144961713Sgirish 161244961713Sgirish /*ARGSUSED*/ 161344961713Sgirish void 161444961713Sgirish nxge_txdma_kick_channel(p_nxge_t nxgep, uint16_t channel) 161544961713Sgirish { 161644961713Sgirish p_tx_ring_t ring_p; 161744961713Sgirish 161844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_kick_channel")); 161944961713Sgirish 162044961713Sgirish ring_p = nxge_txdma_get_ring(nxgep, channel); 162144961713Sgirish if (ring_p == NULL) { 162244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 162352ccf843Smisaki " nxge_txdma_kick_channel")); 162444961713Sgirish return; 162544961713Sgirish } 162644961713Sgirish 162744961713Sgirish if (ring_p->tdc != channel) { 162844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 162952ccf843Smisaki "<== nxge_txdma_kick_channel: channel not matched " 163052ccf843Smisaki "ring tdc %d passed channel", 163152ccf843Smisaki ring_p->tdc, channel)); 163244961713Sgirish return; 163344961713Sgirish } 163444961713Sgirish 163544961713Sgirish nxge_txdma_hw_kick_channel(nxgep, ring_p, channel); 163644961713Sgirish 163744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_kick_channel")); 163844961713Sgirish } 1639a3c5bd6dSspeer 164044961713Sgirish /*ARGSUSED*/ 164144961713Sgirish void 164244961713Sgirish nxge_txdma_hw_kick_channel(p_nxge_t nxgep, p_tx_ring_t ring_p, uint16_t channel) 164344961713Sgirish { 164444961713Sgirish 164544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hw_kick_channel")); 164644961713Sgirish 164744961713Sgirish if (ring_p == NULL) { 164844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 164952ccf843Smisaki "<== nxge_txdma_hw_kick_channel: NULL ring pointer")); 165044961713Sgirish return; 165144961713Sgirish } 165244961713Sgirish 165344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hw_kick_channel")); 165444961713Sgirish } 165544961713Sgirish 1656678453a8Sspeer /* 1657678453a8Sspeer * nxge_check_tx_hang 1658678453a8Sspeer * 1659678453a8Sspeer * Check the state of all TDCs belonging to nxgep. 1660678453a8Sspeer * 1661678453a8Sspeer * Arguments: 1662678453a8Sspeer * nxgep 1663678453a8Sspeer * 1664678453a8Sspeer * Notes: 1665678453a8Sspeer * Called by nxge_hw.c:nxge_check_hw_state(). 1666678453a8Sspeer * 1667678453a8Sspeer * NPI/NXGE function calls: 1668678453a8Sspeer * 1669678453a8Sspeer * Registers accessed: 1670678453a8Sspeer * 1671678453a8Sspeer * Context: 1672678453a8Sspeer * Any domain 1673678453a8Sspeer */ 167444961713Sgirish /*ARGSUSED*/ 167544961713Sgirish void 167644961713Sgirish nxge_check_tx_hang(p_nxge_t nxgep) 167744961713Sgirish { 167844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_check_tx_hang")); 167944961713Sgirish 168022c0d73aSspeer if ((!(nxgep->drv_state & STATE_HW_INITIALIZED)) || 168122c0d73aSspeer (nxgep->nxge_mac_state != NXGE_MAC_STARTED)) { 168222c0d73aSspeer goto nxge_check_tx_hang_exit; 168322c0d73aSspeer } 168422c0d73aSspeer 168544961713Sgirish /* 168644961713Sgirish * Needs inputs from hardware for regs: 168744961713Sgirish * head index had not moved since last timeout. 168844961713Sgirish * packets not transmitted or stuffed registers. 168944961713Sgirish */ 169044961713Sgirish if (nxge_txdma_hung(nxgep)) { 169144961713Sgirish nxge_fixup_hung_txdma_rings(nxgep); 169244961713Sgirish } 169322c0d73aSspeer 169422c0d73aSspeer nxge_check_tx_hang_exit: 169544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_check_tx_hang")); 169644961713Sgirish } 169744961713Sgirish 1698678453a8Sspeer /* 1699678453a8Sspeer * nxge_txdma_hung 1700678453a8Sspeer * 1701678453a8Sspeer * Reset a TDC. 1702678453a8Sspeer * 1703678453a8Sspeer * Arguments: 1704678453a8Sspeer * nxgep 1705678453a8Sspeer * channel The channel to reset. 1706678453a8Sspeer * reg_data The current TX_CS. 1707678453a8Sspeer * 1708678453a8Sspeer * Notes: 1709678453a8Sspeer * Called by nxge_check_tx_hang() 1710678453a8Sspeer * 1711678453a8Sspeer * NPI/NXGE function calls: 1712678453a8Sspeer * nxge_txdma_channel_hung() 1713678453a8Sspeer * 1714678453a8Sspeer * Registers accessed: 1715678453a8Sspeer * 1716678453a8Sspeer * Context: 1717678453a8Sspeer * Any domain 1718678453a8Sspeer */ 171944961713Sgirish int 172044961713Sgirish nxge_txdma_hung(p_nxge_t nxgep) 172144961713Sgirish { 1722330cd344SMichael Speer nxge_grp_set_t *set = &nxgep->tx_set; 1723330cd344SMichael Speer int tdc; 1724330cd344SMichael Speer boolean_t shared; 172544961713Sgirish 172644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hung")); 172744961713Sgirish 1728678453a8Sspeer if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 172944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 1730678453a8Sspeer "<== nxge_txdma_hung: NULL ring pointer(s)")); 173144961713Sgirish return (B_FALSE); 173244961713Sgirish } 173344961713Sgirish 1734678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 1735330cd344SMichael Speer /* 1736330cd344SMichael Speer * Grab the shared state of the TDC. 1737330cd344SMichael Speer */ 1738330cd344SMichael Speer if (isLDOMservice(nxgep)) { 1739330cd344SMichael Speer nxge_hio_data_t *nhd = 1740330cd344SMichael Speer (nxge_hio_data_t *)nxgep->nxge_hw_p->hio; 1741330cd344SMichael Speer 1742330cd344SMichael Speer MUTEX_ENTER(&nhd->lock); 1743330cd344SMichael Speer shared = nxgep->tdc_is_shared[tdc]; 1744330cd344SMichael Speer MUTEX_EXIT(&nhd->lock); 1745330cd344SMichael Speer } else { 1746330cd344SMichael Speer shared = B_FALSE; 1747330cd344SMichael Speer } 1748330cd344SMichael Speer 1749330cd344SMichael Speer /* 1750330cd344SMichael Speer * Now, process continue to process. 1751330cd344SMichael Speer */ 1752330cd344SMichael Speer if (((1 << tdc) & set->owned.map) && !shared) { 1753678453a8Sspeer tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 1754678453a8Sspeer if (ring) { 1755678453a8Sspeer if (nxge_txdma_channel_hung(nxgep, ring, tdc)) { 1756678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, 1757678453a8Sspeer "==> nxge_txdma_hung: TDC %d hung", 1758678453a8Sspeer tdc)); 1759678453a8Sspeer return (B_TRUE); 1760678453a8Sspeer } 1761678453a8Sspeer } 176244961713Sgirish } 176344961713Sgirish } 176444961713Sgirish 176544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hung")); 176644961713Sgirish 176744961713Sgirish return (B_FALSE); 176844961713Sgirish } 176944961713Sgirish 1770678453a8Sspeer /* 1771678453a8Sspeer * nxge_txdma_channel_hung 1772678453a8Sspeer * 1773678453a8Sspeer * Reset a TDC. 1774678453a8Sspeer * 1775678453a8Sspeer * Arguments: 1776678453a8Sspeer * nxgep 1777678453a8Sspeer * ring <channel>'s ring. 1778678453a8Sspeer * channel The channel to reset. 1779678453a8Sspeer * 1780678453a8Sspeer * Notes: 1781678453a8Sspeer * Called by nxge_txdma.c:nxge_txdma_hung() 1782678453a8Sspeer * 1783678453a8Sspeer * NPI/NXGE function calls: 1784678453a8Sspeer * npi_txdma_ring_head_get() 1785678453a8Sspeer * 1786678453a8Sspeer * Registers accessed: 1787678453a8Sspeer * TX_RING_HDL DMC+0x40010 Transmit Ring Head Low 1788678453a8Sspeer * 1789678453a8Sspeer * Context: 1790678453a8Sspeer * Any domain 1791678453a8Sspeer */ 179244961713Sgirish int 179344961713Sgirish nxge_txdma_channel_hung(p_nxge_t nxgep, p_tx_ring_t tx_ring_p, uint16_t channel) 179444961713Sgirish { 179544961713Sgirish uint16_t head_index, tail_index; 179644961713Sgirish boolean_t head_wrap, tail_wrap; 179744961713Sgirish npi_handle_t handle; 179844961713Sgirish tx_ring_hdl_t tx_head; 179944961713Sgirish uint_t tx_rd_index; 180044961713Sgirish 180144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_channel_hung")); 180244961713Sgirish 180344961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 180444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 180552ccf843Smisaki "==> nxge_txdma_channel_hung: channel %d", channel)); 180644961713Sgirish MUTEX_ENTER(&tx_ring_p->lock); 180744961713Sgirish (void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0); 180844961713Sgirish 180944961713Sgirish tail_index = tx_ring_p->wr_index; 181044961713Sgirish tail_wrap = tx_ring_p->wr_index_wrap; 181144961713Sgirish tx_rd_index = tx_ring_p->rd_index; 181244961713Sgirish MUTEX_EXIT(&tx_ring_p->lock); 1813*2d99c5d4SMichael Speer nxge_txdma_freemsg_task(tx_ring_p); 181444961713Sgirish 181544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 181652ccf843Smisaki "==> nxge_txdma_channel_hung: tdc %d tx_rd_index %d " 181752ccf843Smisaki "tail_index %d tail_wrap %d ", 181852ccf843Smisaki channel, tx_rd_index, tail_index, tail_wrap)); 181944961713Sgirish /* 182044961713Sgirish * Read the hardware maintained transmit head 182144961713Sgirish * and wrap around bit. 182244961713Sgirish */ 182344961713Sgirish (void) npi_txdma_ring_head_get(handle, channel, &tx_head); 182444961713Sgirish head_index = tx_head.bits.ldw.head; 182544961713Sgirish head_wrap = tx_head.bits.ldw.wrap; 182644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 182752ccf843Smisaki "==> nxge_txdma_channel_hung: " 182852ccf843Smisaki "tx_rd_index %d tail %d tail_wrap %d " 182952ccf843Smisaki "head %d wrap %d", 183052ccf843Smisaki tx_rd_index, tail_index, tail_wrap, 183152ccf843Smisaki head_index, head_wrap)); 183244961713Sgirish 183344961713Sgirish if (TXDMA_RING_EMPTY(head_index, head_wrap, 183452ccf843Smisaki tail_index, tail_wrap) && 183552ccf843Smisaki (head_index == tx_rd_index)) { 183644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 183752ccf843Smisaki "==> nxge_txdma_channel_hung: EMPTY")); 183844961713Sgirish return (B_FALSE); 183944961713Sgirish } 184044961713Sgirish 184144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 184252ccf843Smisaki "==> nxge_txdma_channel_hung: Checking if ring full")); 184344961713Sgirish if (TXDMA_RING_FULL(head_index, head_wrap, tail_index, 184452ccf843Smisaki tail_wrap)) { 184544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 184652ccf843Smisaki "==> nxge_txdma_channel_hung: full")); 184744961713Sgirish return (B_TRUE); 184844961713Sgirish } 184944961713Sgirish 185044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_channel_hung")); 185144961713Sgirish 185244961713Sgirish return (B_FALSE); 185344961713Sgirish } 185444961713Sgirish 1855678453a8Sspeer /* 1856678453a8Sspeer * nxge_fixup_hung_txdma_rings 1857678453a8Sspeer * 1858678453a8Sspeer * Disable a TDC. 1859678453a8Sspeer * 1860678453a8Sspeer * Arguments: 1861678453a8Sspeer * nxgep 1862678453a8Sspeer * channel The channel to reset. 1863678453a8Sspeer * reg_data The current TX_CS. 1864678453a8Sspeer * 1865678453a8Sspeer * Notes: 1866678453a8Sspeer * Called by nxge_check_tx_hang() 1867678453a8Sspeer * 1868678453a8Sspeer * NPI/NXGE function calls: 1869678453a8Sspeer * npi_txdma_ring_head_get() 1870678453a8Sspeer * 1871678453a8Sspeer * Registers accessed: 1872678453a8Sspeer * TX_RING_HDL DMC+0x40010 Transmit Ring Head Low 1873678453a8Sspeer * 1874678453a8Sspeer * Context: 1875678453a8Sspeer * Any domain 1876678453a8Sspeer */ 187744961713Sgirish /*ARGSUSED*/ 187844961713Sgirish void 187944961713Sgirish nxge_fixup_hung_txdma_rings(p_nxge_t nxgep) 188044961713Sgirish { 1881678453a8Sspeer nxge_grp_set_t *set = &nxgep->tx_set; 1882678453a8Sspeer int tdc; 188344961713Sgirish 188444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_fixup_hung_txdma_rings")); 188544961713Sgirish 1886678453a8Sspeer if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 188744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 1888678453a8Sspeer "<== nxge_fixup_hung_txdma_rings: NULL ring pointer(s)")); 188944961713Sgirish return; 189044961713Sgirish } 189144961713Sgirish 1892678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 1893678453a8Sspeer if ((1 << tdc) & set->owned.map) { 1894678453a8Sspeer tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 1895678453a8Sspeer if (ring) { 1896678453a8Sspeer nxge_txdma_fixup_hung_channel(nxgep, ring, tdc); 1897678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, 1898678453a8Sspeer "==> nxge_fixup_hung_txdma_rings: TDC %d", 1899678453a8Sspeer tdc)); 1900678453a8Sspeer } 1901678453a8Sspeer } 190244961713Sgirish } 190344961713Sgirish 190444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_fixup_hung_txdma_rings")); 190544961713Sgirish } 190644961713Sgirish 1907678453a8Sspeer /* 1908678453a8Sspeer * nxge_txdma_fixup_hung_channel 1909678453a8Sspeer * 1910678453a8Sspeer * 'Fix' a hung TDC. 1911678453a8Sspeer * 1912678453a8Sspeer * Arguments: 1913678453a8Sspeer * nxgep 1914678453a8Sspeer * channel The channel to fix. 1915678453a8Sspeer * 1916678453a8Sspeer * Notes: 1917678453a8Sspeer * Called by nxge_fixup_hung_txdma_rings() 1918678453a8Sspeer * 1919678453a8Sspeer * 1. Reclaim the TDC. 1920678453a8Sspeer * 2. Disable the TDC. 1921678453a8Sspeer * 1922678453a8Sspeer * NPI/NXGE function calls: 1923678453a8Sspeer * nxge_txdma_reclaim() 1924678453a8Sspeer * npi_txdma_channel_disable(TX_CS) 1925678453a8Sspeer * npi_txdma_inj_int_error_set(TDMC_INTR_DBG) 1926678453a8Sspeer * 1927678453a8Sspeer * Registers accessed: 1928678453a8Sspeer * TX_CS DMC+0x40028 Transmit Control And Status 1929678453a8Sspeer * TDMC_INTR_DBG DMC + 0x40060 Transmit DMA Interrupt Debug 1930678453a8Sspeer * 1931678453a8Sspeer * Context: 1932678453a8Sspeer * Any domain 1933678453a8Sspeer */ 193444961713Sgirish /*ARGSUSED*/ 193544961713Sgirish void 193644961713Sgirish nxge_txdma_fix_hung_channel(p_nxge_t nxgep, uint16_t channel) 193744961713Sgirish { 193844961713Sgirish p_tx_ring_t ring_p; 193944961713Sgirish 194044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fix_hung_channel")); 194144961713Sgirish ring_p = nxge_txdma_get_ring(nxgep, channel); 194244961713Sgirish if (ring_p == NULL) { 194344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 194452ccf843Smisaki "<== nxge_txdma_fix_hung_channel")); 194544961713Sgirish return; 194644961713Sgirish } 194744961713Sgirish 194844961713Sgirish if (ring_p->tdc != channel) { 194944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 195052ccf843Smisaki "<== nxge_txdma_fix_hung_channel: channel not matched " 195152ccf843Smisaki "ring tdc %d passed channel", 195252ccf843Smisaki ring_p->tdc, channel)); 195344961713Sgirish return; 195444961713Sgirish } 195544961713Sgirish 195644961713Sgirish nxge_txdma_fixup_channel(nxgep, ring_p, channel); 195744961713Sgirish 195844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_hung_channel")); 195944961713Sgirish } 196044961713Sgirish 196144961713Sgirish /*ARGSUSED*/ 196244961713Sgirish void 196344961713Sgirish nxge_txdma_fixup_hung_channel(p_nxge_t nxgep, p_tx_ring_t ring_p, 196444961713Sgirish uint16_t channel) 196544961713Sgirish { 196644961713Sgirish npi_handle_t handle; 196744961713Sgirish tdmc_intr_dbg_t intr_dbg; 196844961713Sgirish int status = NXGE_OK; 196944961713Sgirish 197044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fixup_hung_channel")); 197144961713Sgirish 197244961713Sgirish if (ring_p == NULL) { 197344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 197452ccf843Smisaki "<== nxge_txdma_fixup_channel: NULL ring pointer")); 197544961713Sgirish return; 197644961713Sgirish } 197744961713Sgirish 197844961713Sgirish if (ring_p->tdc != channel) { 197944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 198052ccf843Smisaki "<== nxge_txdma_fixup_hung_channel: channel " 198152ccf843Smisaki "not matched " 198252ccf843Smisaki "ring tdc %d passed channel", 198352ccf843Smisaki ring_p->tdc, channel)); 198444961713Sgirish return; 198544961713Sgirish } 198644961713Sgirish 198744961713Sgirish /* Reclaim descriptors */ 198844961713Sgirish MUTEX_ENTER(&ring_p->lock); 198944961713Sgirish (void) nxge_txdma_reclaim(nxgep, ring_p, 0); 199044961713Sgirish MUTEX_EXIT(&ring_p->lock); 199144961713Sgirish 1992*2d99c5d4SMichael Speer nxge_txdma_freemsg_task(ring_p); 1993*2d99c5d4SMichael Speer 199444961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 199544961713Sgirish /* 199644961713Sgirish * Stop the dma channel waits for the stop done. 199744961713Sgirish * If the stop done bit is not set, then force 199844961713Sgirish * an error. 199944961713Sgirish */ 200044961713Sgirish status = npi_txdma_channel_disable(handle, channel); 200144961713Sgirish if (!(status & NPI_TXDMA_STOP_FAILED)) { 200244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 200352ccf843Smisaki "<== nxge_txdma_fixup_hung_channel: stopped OK " 200452ccf843Smisaki "ring tdc %d passed channel %d", 200552ccf843Smisaki ring_p->tdc, channel)); 200644961713Sgirish return; 200744961713Sgirish } 200844961713Sgirish 200944961713Sgirish /* Inject any error */ 201044961713Sgirish intr_dbg.value = 0; 201144961713Sgirish intr_dbg.bits.ldw.nack_pref = 1; 201244961713Sgirish (void) npi_txdma_inj_int_error_set(handle, channel, &intr_dbg); 201344961713Sgirish 201444961713Sgirish /* Stop done bit will be set as a result of error injection */ 201544961713Sgirish status = npi_txdma_channel_disable(handle, channel); 201644961713Sgirish if (!(status & NPI_TXDMA_STOP_FAILED)) { 201744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 201852ccf843Smisaki "<== nxge_txdma_fixup_hung_channel: stopped again" 201952ccf843Smisaki "ring tdc %d passed channel", 202052ccf843Smisaki ring_p->tdc, channel)); 202144961713Sgirish return; 202244961713Sgirish } 202344961713Sgirish 202444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 202552ccf843Smisaki "<== nxge_txdma_fixup_hung_channel: stop done still not set!! " 202652ccf843Smisaki "ring tdc %d passed channel", 202752ccf843Smisaki ring_p->tdc, channel)); 202844961713Sgirish 202944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fixup_hung_channel")); 203044961713Sgirish } 203144961713Sgirish 203244961713Sgirish /*ARGSUSED*/ 203344961713Sgirish void 203444961713Sgirish nxge_reclaim_rings(p_nxge_t nxgep) 203544961713Sgirish { 2036678453a8Sspeer nxge_grp_set_t *set = &nxgep->tx_set; 2037678453a8Sspeer int tdc; 203844961713Sgirish 2039678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_reclaim_rings")); 204044961713Sgirish 2041678453a8Sspeer if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 204244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 2043678453a8Sspeer "<== nxge_fixup_hung_txdma_rings: NULL ring pointer(s)")); 204444961713Sgirish return; 204544961713Sgirish } 204644961713Sgirish 2047678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 2048678453a8Sspeer if ((1 << tdc) & set->owned.map) { 2049678453a8Sspeer tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 2050678453a8Sspeer if (ring) { 2051678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, 2052678453a8Sspeer "==> nxge_reclaim_rings: TDC %d", tdc)); 2053678453a8Sspeer MUTEX_ENTER(&ring->lock); 2054678453a8Sspeer (void) nxge_txdma_reclaim(nxgep, ring, tdc); 2055678453a8Sspeer MUTEX_EXIT(&ring->lock); 2056*2d99c5d4SMichael Speer 2057*2d99c5d4SMichael Speer nxge_txdma_freemsg_task(ring); 2058678453a8Sspeer } 2059678453a8Sspeer } 206044961713Sgirish } 206144961713Sgirish 206244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_reclaim_rings")); 206344961713Sgirish } 206444961713Sgirish 206544961713Sgirish void 206644961713Sgirish nxge_txdma_regs_dump_channels(p_nxge_t nxgep) 206744961713Sgirish { 2068678453a8Sspeer nxge_grp_set_t *set = &nxgep->tx_set; 2069678453a8Sspeer npi_handle_t handle; 2070678453a8Sspeer int tdc; 207144961713Sgirish 2072678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_regs_dump_channels")); 207344961713Sgirish 207444961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 207544961713Sgirish 2076678453a8Sspeer if (!isLDOMguest(nxgep)) { 2077678453a8Sspeer (void) npi_txdma_dump_fzc_regs(handle); 207844961713Sgirish 2079678453a8Sspeer /* Dump TXC registers. */ 2080678453a8Sspeer (void) npi_txc_dump_fzc_regs(handle); 2081678453a8Sspeer (void) npi_txc_dump_port_fzc_regs(handle, nxgep->function_num); 208244961713Sgirish } 208344961713Sgirish 2084678453a8Sspeer if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 208544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 2086678453a8Sspeer "<== nxge_fixup_hung_txdma_rings: NULL ring pointer(s)")); 208744961713Sgirish return; 208844961713Sgirish } 208944961713Sgirish 2090678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 2091678453a8Sspeer if ((1 << tdc) & set->owned.map) { 2092678453a8Sspeer tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 2093678453a8Sspeer if (ring) { 2094678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, 2095678453a8Sspeer "==> nxge_txdma_regs_dump_channels: " 2096678453a8Sspeer "TDC %d", tdc)); 2097678453a8Sspeer (void) npi_txdma_dump_tdc_regs(handle, tdc); 2098678453a8Sspeer 2099678453a8Sspeer /* Dump TXC registers, if able to. */ 2100678453a8Sspeer if (!isLDOMguest(nxgep)) { 2101678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, 2102678453a8Sspeer "==> nxge_txdma_regs_dump_channels:" 2103678453a8Sspeer " FZC TDC %d", tdc)); 2104678453a8Sspeer (void) npi_txc_dump_tdc_fzc_regs 2105678453a8Sspeer (handle, tdc); 2106678453a8Sspeer } 2107678453a8Sspeer nxge_txdma_regs_dump(nxgep, tdc); 2108678453a8Sspeer } 2109678453a8Sspeer } 211044961713Sgirish } 211144961713Sgirish 211244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_regs_dump")); 211344961713Sgirish } 211444961713Sgirish 211544961713Sgirish void 211644961713Sgirish nxge_txdma_regs_dump(p_nxge_t nxgep, int channel) 211744961713Sgirish { 211844961713Sgirish npi_handle_t handle; 211944961713Sgirish tx_ring_hdl_t hdl; 212044961713Sgirish tx_ring_kick_t kick; 212144961713Sgirish tx_cs_t cs; 212244961713Sgirish txc_control_t control; 212344961713Sgirish uint32_t bitmap = 0; 212444961713Sgirish uint32_t burst = 0; 212544961713Sgirish uint32_t bytes = 0; 212644961713Sgirish dma_log_page_t cfg; 212744961713Sgirish 212844961713Sgirish printf("\n\tfunc # %d tdc %d ", 212952ccf843Smisaki nxgep->function_num, channel); 213044961713Sgirish cfg.page_num = 0; 213144961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 213244961713Sgirish (void) npi_txdma_log_page_get(handle, channel, &cfg); 213344961713Sgirish printf("\n\tlog page func %d valid page 0 %d", 213452ccf843Smisaki cfg.func_num, cfg.valid); 213544961713Sgirish cfg.page_num = 1; 213644961713Sgirish (void) npi_txdma_log_page_get(handle, channel, &cfg); 213744961713Sgirish printf("\n\tlog page func %d valid page 1 %d", 213852ccf843Smisaki cfg.func_num, cfg.valid); 213944961713Sgirish 214044961713Sgirish (void) npi_txdma_ring_head_get(handle, channel, &hdl); 214144961713Sgirish (void) npi_txdma_desc_kick_reg_get(handle, channel, &kick); 214244961713Sgirish printf("\n\thead value is 0x%0llx", 214352ccf843Smisaki (long long)hdl.value); 214444961713Sgirish printf("\n\thead index %d", hdl.bits.ldw.head); 214544961713Sgirish printf("\n\tkick value is 0x%0llx", 214652ccf843Smisaki (long long)kick.value); 214744961713Sgirish printf("\n\ttail index %d\n", kick.bits.ldw.tail); 214844961713Sgirish 214944961713Sgirish (void) npi_txdma_control_status(handle, OP_GET, channel, &cs); 215044961713Sgirish printf("\n\tControl statue is 0x%0llx", (long long)cs.value); 215144961713Sgirish printf("\n\tControl status RST state %d", cs.bits.ldw.rst); 215244961713Sgirish 215344961713Sgirish (void) npi_txc_control(handle, OP_GET, &control); 215444961713Sgirish (void) npi_txc_port_dma_list_get(handle, nxgep->function_num, &bitmap); 215544961713Sgirish (void) npi_txc_dma_max_burst(handle, OP_GET, channel, &burst); 215644961713Sgirish (void) npi_txc_dma_bytes_transmitted(handle, channel, &bytes); 215744961713Sgirish 215844961713Sgirish printf("\n\tTXC port control 0x%0llx", 215952ccf843Smisaki (long long)control.value); 216044961713Sgirish printf("\n\tTXC port bitmap 0x%x", bitmap); 216144961713Sgirish printf("\n\tTXC max burst %d", burst); 216244961713Sgirish printf("\n\tTXC bytes xmt %d\n", bytes); 216344961713Sgirish 216444961713Sgirish { 216544961713Sgirish ipp_status_t status; 216644961713Sgirish 216744961713Sgirish (void) npi_ipp_get_status(handle, nxgep->function_num, &status); 2168adfcba55Sjoycey #if defined(__i386) 2169adfcba55Sjoycey printf("\n\tIPP status 0x%llux\n", (uint64_t)status.value); 2170adfcba55Sjoycey #else 217144961713Sgirish printf("\n\tIPP status 0x%lux\n", (uint64_t)status.value); 2172adfcba55Sjoycey #endif 217344961713Sgirish } 217444961713Sgirish } 217544961713Sgirish 217644961713Sgirish /* 2177678453a8Sspeer * nxge_tdc_hvio_setup 2178678453a8Sspeer * 2179678453a8Sspeer * I'm not exactly sure what this code does. 2180678453a8Sspeer * 2181678453a8Sspeer * Arguments: 2182678453a8Sspeer * nxgep 2183678453a8Sspeer * channel The channel to map. 2184678453a8Sspeer * 2185678453a8Sspeer * Notes: 2186678453a8Sspeer * 2187678453a8Sspeer * NPI/NXGE function calls: 2188678453a8Sspeer * na 2189678453a8Sspeer * 2190678453a8Sspeer * Context: 2191678453a8Sspeer * Service domain? 219244961713Sgirish */ 2193678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 2194678453a8Sspeer static void 2195678453a8Sspeer nxge_tdc_hvio_setup( 2196678453a8Sspeer nxge_t *nxgep, int channel) 219744961713Sgirish { 2198678453a8Sspeer nxge_dma_common_t *data; 2199678453a8Sspeer nxge_dma_common_t *control; 2200678453a8Sspeer tx_ring_t *ring; 2201678453a8Sspeer 2202678453a8Sspeer ring = nxgep->tx_rings->rings[channel]; 2203678453a8Sspeer data = nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2204678453a8Sspeer 2205678453a8Sspeer ring->hv_set = B_FALSE; 2206678453a8Sspeer 2207678453a8Sspeer ring->hv_tx_buf_base_ioaddr_pp = 2208678453a8Sspeer (uint64_t)data->orig_ioaddr_pp; 2209678453a8Sspeer ring->hv_tx_buf_ioaddr_size = 2210678453a8Sspeer (uint64_t)data->orig_alength; 2211678453a8Sspeer 2212678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma_channel: " 221352ccf843Smisaki "hv data buf base io $%p size 0x%llx (%d) buf base io $%p " 221452ccf843Smisaki "orig vatopa base io $%p orig_len 0x%llx (%d)", 221552ccf843Smisaki ring->hv_tx_buf_base_ioaddr_pp, 221652ccf843Smisaki ring->hv_tx_buf_ioaddr_size, ring->hv_tx_buf_ioaddr_size, 221752ccf843Smisaki data->ioaddr_pp, data->orig_vatopa, 221852ccf843Smisaki data->orig_alength, data->orig_alength)); 2219678453a8Sspeer 2220678453a8Sspeer control = nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2221678453a8Sspeer 2222678453a8Sspeer ring->hv_tx_cntl_base_ioaddr_pp = 2223678453a8Sspeer (uint64_t)control->orig_ioaddr_pp; 2224678453a8Sspeer ring->hv_tx_cntl_ioaddr_size = 2225678453a8Sspeer (uint64_t)control->orig_alength; 2226678453a8Sspeer 2227678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma_channel: " 222852ccf843Smisaki "hv cntl base io $%p orig ioaddr_pp ($%p) " 222952ccf843Smisaki "orig vatopa ($%p) size 0x%llx (%d 0x%x)", 223052ccf843Smisaki ring->hv_tx_cntl_base_ioaddr_pp, 223152ccf843Smisaki control->orig_ioaddr_pp, control->orig_vatopa, 223252ccf843Smisaki ring->hv_tx_cntl_ioaddr_size, 223352ccf843Smisaki control->orig_alength, control->orig_alength)); 2234678453a8Sspeer } 223544961713Sgirish #endif 223644961713Sgirish 2237678453a8Sspeer static nxge_status_t 2238678453a8Sspeer nxge_map_txdma(p_nxge_t nxgep, int channel) 2239678453a8Sspeer { 2240678453a8Sspeer nxge_dma_common_t **pData; 2241678453a8Sspeer nxge_dma_common_t **pControl; 2242678453a8Sspeer tx_ring_t **pRing, *ring; 2243678453a8Sspeer tx_mbox_t **mailbox; 2244678453a8Sspeer uint32_t num_chunks; 2245678453a8Sspeer 2246678453a8Sspeer nxge_status_t status = NXGE_OK; 224744961713Sgirish 2248678453a8Sspeer NXGE_ERROR_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma")); 224944961713Sgirish 2250678453a8Sspeer if (!nxgep->tx_cntl_pool_p->buf_allocated) { 2251678453a8Sspeer if (nxge_alloc_tx_mem_pool(nxgep) != NXGE_OK) { 2252678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2253678453a8Sspeer "<== nxge_map_txdma: buf not allocated")); 2254678453a8Sspeer return (NXGE_ERROR); 2255678453a8Sspeer } 225644961713Sgirish } 225744961713Sgirish 2258678453a8Sspeer if (nxge_alloc_txb(nxgep, channel) != NXGE_OK) 225944961713Sgirish return (NXGE_ERROR); 226044961713Sgirish 2261678453a8Sspeer num_chunks = nxgep->tx_buf_pool_p->num_chunks[channel]; 2262678453a8Sspeer pData = &nxgep->tx_buf_pool_p->dma_buf_pool_p[channel]; 2263678453a8Sspeer pControl = &nxgep->tx_cntl_pool_p->dma_buf_pool_p[channel]; 2264678453a8Sspeer pRing = &nxgep->tx_rings->rings[channel]; 2265678453a8Sspeer mailbox = &nxgep->tx_mbox_areas_p->txmbox_areas_p[channel]; 226644961713Sgirish 2267678453a8Sspeer NXGE_ERROR_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma: " 226852ccf843Smisaki "tx_rings $%p tx_desc_rings $%p", 226952ccf843Smisaki nxgep->tx_rings, nxgep->tx_rings->rings)); 227044961713Sgirish 227144961713Sgirish /* 2272678453a8Sspeer * Map descriptors from the buffer pools for <channel>. 227344961713Sgirish */ 227444961713Sgirish 2275678453a8Sspeer /* 2276678453a8Sspeer * Set up and prepare buffer blocks, descriptors 2277678453a8Sspeer * and mailbox. 2278678453a8Sspeer */ 2279678453a8Sspeer status = nxge_map_txdma_channel(nxgep, channel, 2280678453a8Sspeer pData, pRing, num_chunks, pControl, mailbox); 2281678453a8Sspeer if (status != NXGE_OK) { 2282678453a8Sspeer NXGE_ERROR_MSG((nxgep, MEM3_CTL, 228352ccf843Smisaki "==> nxge_map_txdma(%d): nxge_map_txdma_channel() " 228452ccf843Smisaki "returned 0x%x", 228552ccf843Smisaki nxgep, channel, status)); 2286678453a8Sspeer return (status); 228744961713Sgirish } 228844961713Sgirish 2289678453a8Sspeer ring = *pRing; 229044961713Sgirish 2291678453a8Sspeer ring->index = (uint16_t)channel; 2292678453a8Sspeer ring->tdc_stats = &nxgep->statsp->tdc_stats[channel]; 229344961713Sgirish 2294678453a8Sspeer #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 2295678453a8Sspeer if (isLDOMguest(nxgep)) { 2296678453a8Sspeer (void) nxge_tdc_lp_conf(nxgep, channel); 2297678453a8Sspeer } else { 2298678453a8Sspeer nxge_tdc_hvio_setup(nxgep, channel); 229944961713Sgirish } 2300678453a8Sspeer #endif 230144961713Sgirish 2302678453a8Sspeer NXGE_ERROR_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma: " 2303678453a8Sspeer "(status 0x%x channel %d)", status, channel)); 230444961713Sgirish 2305678453a8Sspeer return (status); 230644961713Sgirish } 230744961713Sgirish 230844961713Sgirish static nxge_status_t 230944961713Sgirish nxge_map_txdma_channel(p_nxge_t nxgep, uint16_t channel, 231044961713Sgirish p_nxge_dma_common_t *dma_buf_p, 231144961713Sgirish p_tx_ring_t *tx_desc_p, 231244961713Sgirish uint32_t num_chunks, 231344961713Sgirish p_nxge_dma_common_t *dma_cntl_p, 231444961713Sgirish p_tx_mbox_t *tx_mbox_p) 231544961713Sgirish { 231644961713Sgirish int status = NXGE_OK; 231744961713Sgirish 231844961713Sgirish /* 231944961713Sgirish * Set up and prepare buffer blocks, descriptors 232044961713Sgirish * and mailbox. 232144961713Sgirish */ 2322678453a8Sspeer NXGE_ERROR_MSG((nxgep, MEM3_CTL, 232352ccf843Smisaki "==> nxge_map_txdma_channel (channel %d)", channel)); 232444961713Sgirish /* 232544961713Sgirish * Transmit buffer blocks 232644961713Sgirish */ 232744961713Sgirish status = nxge_map_txdma_channel_buf_ring(nxgep, channel, 232852ccf843Smisaki dma_buf_p, tx_desc_p, num_chunks); 232944961713Sgirish if (status != NXGE_OK) { 233044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 233152ccf843Smisaki "==> nxge_map_txdma_channel (channel %d): " 233252ccf843Smisaki "map buffer failed 0x%x", channel, status)); 233344961713Sgirish goto nxge_map_txdma_channel_exit; 233444961713Sgirish } 233544961713Sgirish 233644961713Sgirish /* 233744961713Sgirish * Transmit block ring, and mailbox. 233844961713Sgirish */ 233944961713Sgirish nxge_map_txdma_channel_cfg_ring(nxgep, channel, dma_cntl_p, *tx_desc_p, 234052ccf843Smisaki tx_mbox_p); 234144961713Sgirish 234244961713Sgirish goto nxge_map_txdma_channel_exit; 234344961713Sgirish 234444961713Sgirish nxge_map_txdma_channel_fail1: 2345678453a8Sspeer NXGE_ERROR_MSG((nxgep, MEM3_CTL, 234652ccf843Smisaki "==> nxge_map_txdma_channel: unmap buf" 234752ccf843Smisaki "(status 0x%x channel %d)", 234852ccf843Smisaki status, channel)); 234944961713Sgirish nxge_unmap_txdma_channel_buf_ring(nxgep, *tx_desc_p); 235044961713Sgirish 235144961713Sgirish nxge_map_txdma_channel_exit: 2352678453a8Sspeer NXGE_ERROR_MSG((nxgep, MEM3_CTL, 235352ccf843Smisaki "<== nxge_map_txdma_channel: " 235452ccf843Smisaki "(status 0x%x channel %d)", 235552ccf843Smisaki status, channel)); 235644961713Sgirish 235744961713Sgirish return (status); 235844961713Sgirish } 235944961713Sgirish 236044961713Sgirish /*ARGSUSED*/ 236144961713Sgirish static void 2362678453a8Sspeer nxge_unmap_txdma_channel(p_nxge_t nxgep, uint16_t channel) 236344961713Sgirish { 2364678453a8Sspeer tx_ring_t *ring; 2365678453a8Sspeer tx_mbox_t *mailbox; 2366678453a8Sspeer 236744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 236852ccf843Smisaki "==> nxge_unmap_txdma_channel (channel %d)", channel)); 236944961713Sgirish /* 237044961713Sgirish * unmap tx block ring, and mailbox. 237144961713Sgirish */ 2372678453a8Sspeer ring = nxgep->tx_rings->rings[channel]; 2373678453a8Sspeer mailbox = nxgep->tx_mbox_areas_p->txmbox_areas_p[channel]; 2374678453a8Sspeer 2375678453a8Sspeer (void) nxge_unmap_txdma_channel_cfg_ring(nxgep, ring, mailbox); 237644961713Sgirish 237744961713Sgirish /* unmap buffer blocks */ 2378678453a8Sspeer (void) nxge_unmap_txdma_channel_buf_ring(nxgep, ring); 2379678453a8Sspeer 2380678453a8Sspeer nxge_free_txb(nxgep, channel); 238144961713Sgirish 238244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_unmap_txdma_channel")); 238344961713Sgirish } 238444961713Sgirish 2385678453a8Sspeer /* 2386678453a8Sspeer * nxge_map_txdma_channel_cfg_ring 2387678453a8Sspeer * 2388678453a8Sspeer * Map a TDC into our kernel space. 2389678453a8Sspeer * This function allocates all of the per-channel data structures. 2390678453a8Sspeer * 2391678453a8Sspeer * Arguments: 2392678453a8Sspeer * nxgep 2393678453a8Sspeer * dma_channel The channel to map. 2394678453a8Sspeer * dma_cntl_p 2395678453a8Sspeer * tx_ring_p dma_channel's transmit ring 2396678453a8Sspeer * tx_mbox_p dma_channel's mailbox 2397678453a8Sspeer * 2398678453a8Sspeer * Notes: 2399678453a8Sspeer * 2400678453a8Sspeer * NPI/NXGE function calls: 2401678453a8Sspeer * nxge_setup_dma_common() 2402678453a8Sspeer * 2403678453a8Sspeer * Registers accessed: 2404678453a8Sspeer * none. 2405678453a8Sspeer * 2406678453a8Sspeer * Context: 2407678453a8Sspeer * Any domain 2408678453a8Sspeer */ 240944961713Sgirish /*ARGSUSED*/ 241044961713Sgirish static void 241144961713Sgirish nxge_map_txdma_channel_cfg_ring(p_nxge_t nxgep, uint16_t dma_channel, 241244961713Sgirish p_nxge_dma_common_t *dma_cntl_p, 241344961713Sgirish p_tx_ring_t tx_ring_p, 241444961713Sgirish p_tx_mbox_t *tx_mbox_p) 241544961713Sgirish { 241644961713Sgirish p_tx_mbox_t mboxp; 241744961713Sgirish p_nxge_dma_common_t cntl_dmap; 241844961713Sgirish p_nxge_dma_common_t dmap; 241944961713Sgirish p_tx_rng_cfig_t tx_ring_cfig_p; 242044961713Sgirish p_tx_ring_kick_t tx_ring_kick_p; 242144961713Sgirish p_tx_cs_t tx_cs_p; 242244961713Sgirish p_tx_dma_ent_msk_t tx_evmask_p; 242344961713Sgirish p_txdma_mbh_t mboxh_p; 242444961713Sgirish p_txdma_mbl_t mboxl_p; 242544961713Sgirish uint64_t tx_desc_len; 242644961713Sgirish 242744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 242852ccf843Smisaki "==> nxge_map_txdma_channel_cfg_ring")); 242944961713Sgirish 243044961713Sgirish cntl_dmap = *dma_cntl_p; 243144961713Sgirish 243244961713Sgirish dmap = (p_nxge_dma_common_t)&tx_ring_p->tdc_desc; 243344961713Sgirish nxge_setup_dma_common(dmap, cntl_dmap, tx_ring_p->tx_ring_size, 243452ccf843Smisaki sizeof (tx_desc_t)); 243544961713Sgirish /* 243644961713Sgirish * Zero out transmit ring descriptors. 243744961713Sgirish */ 243844961713Sgirish bzero((caddr_t)dmap->kaddrp, dmap->alength); 243944961713Sgirish tx_ring_cfig_p = &(tx_ring_p->tx_ring_cfig); 244044961713Sgirish tx_ring_kick_p = &(tx_ring_p->tx_ring_kick); 244144961713Sgirish tx_cs_p = &(tx_ring_p->tx_cs); 244244961713Sgirish tx_evmask_p = &(tx_ring_p->tx_evmask); 244344961713Sgirish tx_ring_cfig_p->value = 0; 244444961713Sgirish tx_ring_kick_p->value = 0; 244544961713Sgirish tx_cs_p->value = 0; 244644961713Sgirish tx_evmask_p->value = 0; 244744961713Sgirish 244844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 244952ccf843Smisaki "==> nxge_map_txdma_channel_cfg_ring: channel %d des $%p", 245052ccf843Smisaki dma_channel, 245152ccf843Smisaki dmap->dma_cookie.dmac_laddress)); 245244961713Sgirish 245344961713Sgirish tx_ring_cfig_p->value = 0; 245444961713Sgirish tx_desc_len = (uint64_t)(tx_ring_p->tx_ring_size >> 3); 245544961713Sgirish tx_ring_cfig_p->value = 245652ccf843Smisaki (dmap->dma_cookie.dmac_laddress & TX_RNG_CFIG_ADDR_MASK) | 245752ccf843Smisaki (tx_desc_len << TX_RNG_CFIG_LEN_SHIFT); 245844961713Sgirish 245944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 246052ccf843Smisaki "==> nxge_map_txdma_channel_cfg_ring: channel %d cfg 0x%llx", 246152ccf843Smisaki dma_channel, 246252ccf843Smisaki tx_ring_cfig_p->value)); 246344961713Sgirish 246444961713Sgirish tx_cs_p->bits.ldw.rst = 1; 246544961713Sgirish 246644961713Sgirish /* Map in mailbox */ 246744961713Sgirish mboxp = (p_tx_mbox_t) 246852ccf843Smisaki KMEM_ZALLOC(sizeof (tx_mbox_t), KM_SLEEP); 246944961713Sgirish dmap = (p_nxge_dma_common_t)&mboxp->tx_mbox; 247044961713Sgirish nxge_setup_dma_common(dmap, cntl_dmap, 1, sizeof (txdma_mailbox_t)); 247144961713Sgirish mboxh_p = (p_txdma_mbh_t)&tx_ring_p->tx_mbox_mbh; 247244961713Sgirish mboxl_p = (p_txdma_mbl_t)&tx_ring_p->tx_mbox_mbl; 247344961713Sgirish mboxh_p->value = mboxl_p->value = 0; 247444961713Sgirish 247544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 247652ccf843Smisaki "==> nxge_map_txdma_channel_cfg_ring: mbox 0x%lx", 247752ccf843Smisaki dmap->dma_cookie.dmac_laddress)); 247844961713Sgirish 247944961713Sgirish mboxh_p->bits.ldw.mbaddr = ((dmap->dma_cookie.dmac_laddress >> 248052ccf843Smisaki TXDMA_MBH_ADDR_SHIFT) & TXDMA_MBH_MASK); 248144961713Sgirish 248244961713Sgirish mboxl_p->bits.ldw.mbaddr = ((dmap->dma_cookie.dmac_laddress & 248352ccf843Smisaki TXDMA_MBL_MASK) >> TXDMA_MBL_SHIFT); 248444961713Sgirish 248544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 248652ccf843Smisaki "==> nxge_map_txdma_channel_cfg_ring: mbox 0x%lx", 248752ccf843Smisaki dmap->dma_cookie.dmac_laddress)); 248844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 248952ccf843Smisaki "==> nxge_map_txdma_channel_cfg_ring: hmbox $%p " 249052ccf843Smisaki "mbox $%p", 249152ccf843Smisaki mboxh_p->bits.ldw.mbaddr, mboxl_p->bits.ldw.mbaddr)); 249244961713Sgirish tx_ring_p->page_valid.value = 0; 249344961713Sgirish tx_ring_p->page_mask_1.value = tx_ring_p->page_mask_2.value = 0; 249444961713Sgirish tx_ring_p->page_value_1.value = tx_ring_p->page_value_2.value = 0; 249544961713Sgirish tx_ring_p->page_reloc_1.value = tx_ring_p->page_reloc_2.value = 0; 249644961713Sgirish tx_ring_p->page_hdl.value = 0; 249744961713Sgirish 249844961713Sgirish tx_ring_p->page_valid.bits.ldw.page0 = 1; 249944961713Sgirish tx_ring_p->page_valid.bits.ldw.page1 = 1; 250044961713Sgirish 250144961713Sgirish tx_ring_p->max_burst.value = 0; 250244961713Sgirish tx_ring_p->max_burst.bits.ldw.dma_max_burst = TXC_DMA_MAX_BURST_DEFAULT; 250344961713Sgirish 250444961713Sgirish *tx_mbox_p = mboxp; 250544961713Sgirish 250644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 250752ccf843Smisaki "<== nxge_map_txdma_channel_cfg_ring")); 250844961713Sgirish } 250944961713Sgirish 251044961713Sgirish /*ARGSUSED*/ 251144961713Sgirish static void 251244961713Sgirish nxge_unmap_txdma_channel_cfg_ring(p_nxge_t nxgep, 251344961713Sgirish p_tx_ring_t tx_ring_p, p_tx_mbox_t tx_mbox_p) 251444961713Sgirish { 251544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 251652ccf843Smisaki "==> nxge_unmap_txdma_channel_cfg_ring: channel %d", 251752ccf843Smisaki tx_ring_p->tdc)); 251844961713Sgirish 251944961713Sgirish KMEM_FREE(tx_mbox_p, sizeof (tx_mbox_t)); 252044961713Sgirish 252144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 252252ccf843Smisaki "<== nxge_unmap_txdma_channel_cfg_ring")); 252344961713Sgirish } 252444961713Sgirish 2525678453a8Sspeer /* 2526678453a8Sspeer * nxge_map_txdma_channel_buf_ring 2527678453a8Sspeer * 2528678453a8Sspeer * 2529678453a8Sspeer * Arguments: 2530678453a8Sspeer * nxgep 2531678453a8Sspeer * channel The channel to map. 2532678453a8Sspeer * dma_buf_p 2533678453a8Sspeer * tx_desc_p channel's descriptor ring 2534678453a8Sspeer * num_chunks 2535678453a8Sspeer * 2536678453a8Sspeer * Notes: 2537678453a8Sspeer * 2538678453a8Sspeer * NPI/NXGE function calls: 2539678453a8Sspeer * nxge_setup_dma_common() 2540678453a8Sspeer * 2541678453a8Sspeer * Registers accessed: 2542678453a8Sspeer * none. 2543678453a8Sspeer * 2544678453a8Sspeer * Context: 2545678453a8Sspeer * Any domain 2546678453a8Sspeer */ 254744961713Sgirish static nxge_status_t 254844961713Sgirish nxge_map_txdma_channel_buf_ring(p_nxge_t nxgep, uint16_t channel, 254944961713Sgirish p_nxge_dma_common_t *dma_buf_p, 255044961713Sgirish p_tx_ring_t *tx_desc_p, uint32_t num_chunks) 255144961713Sgirish { 255244961713Sgirish p_nxge_dma_common_t dma_bufp, tmp_bufp; 255344961713Sgirish p_nxge_dma_common_t dmap; 255444961713Sgirish nxge_os_dma_handle_t tx_buf_dma_handle; 255544961713Sgirish p_tx_ring_t tx_ring_p; 255644961713Sgirish p_tx_msg_t tx_msg_ring; 255744961713Sgirish nxge_status_t status = NXGE_OK; 255844961713Sgirish int ddi_status = DDI_SUCCESS; 255944961713Sgirish int i, j, index; 256044961713Sgirish uint32_t size, bsize; 256144961713Sgirish uint32_t nblocks, nmsgs; 256244961713Sgirish 256344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 256452ccf843Smisaki "==> nxge_map_txdma_channel_buf_ring")); 256544961713Sgirish 256644961713Sgirish dma_bufp = tmp_bufp = *dma_buf_p; 256744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 256844961713Sgirish " nxge_map_txdma_channel_buf_ring: channel %d to map %d " 256944961713Sgirish "chunks bufp $%p", 257052ccf843Smisaki channel, num_chunks, dma_bufp)); 257144961713Sgirish 257244961713Sgirish nmsgs = 0; 257344961713Sgirish for (i = 0; i < num_chunks; i++, tmp_bufp++) { 257444961713Sgirish nmsgs += tmp_bufp->nblocks; 257544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 257652ccf843Smisaki "==> nxge_map_txdma_channel_buf_ring: channel %d " 257752ccf843Smisaki "bufp $%p nblocks %d nmsgs %d", 257852ccf843Smisaki channel, tmp_bufp, tmp_bufp->nblocks, nmsgs)); 257944961713Sgirish } 258044961713Sgirish if (!nmsgs) { 258144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 258252ccf843Smisaki "<== nxge_map_txdma_channel_buf_ring: channel %d " 258352ccf843Smisaki "no msg blocks", 258452ccf843Smisaki channel)); 258544961713Sgirish status = NXGE_ERROR; 258644961713Sgirish goto nxge_map_txdma_channel_buf_ring_exit; 258744961713Sgirish } 258844961713Sgirish 258944961713Sgirish tx_ring_p = (p_tx_ring_t) 259052ccf843Smisaki KMEM_ZALLOC(sizeof (tx_ring_t), KM_SLEEP); 259144961713Sgirish MUTEX_INIT(&tx_ring_p->lock, NULL, MUTEX_DRIVER, 259252ccf843Smisaki (void *)nxgep->interrupt_cookie); 2593*2d99c5d4SMichael Speer MUTEX_INIT(&tx_ring_p->freelock, NULL, MUTEX_DRIVER, 2594*2d99c5d4SMichael Speer (void *)nxgep->interrupt_cookie); 25951f8914d5Sml 259622c0d73aSspeer (void) atomic_swap_32(&tx_ring_p->tx_ring_offline, NXGE_TX_RING_ONLINE); 25976895688eSspeer tx_ring_p->tx_ring_busy = B_FALSE; 25981f8914d5Sml tx_ring_p->nxgep = nxgep; 25991f8914d5Sml tx_ring_p->serial = nxge_serialize_create(nmsgs, 260052ccf843Smisaki nxge_serial_tx, tx_ring_p); 260144961713Sgirish /* 260244961713Sgirish * Allocate transmit message rings and handles for packets 260344961713Sgirish * not to be copied to premapped buffers. 260444961713Sgirish */ 260544961713Sgirish size = nmsgs * sizeof (tx_msg_t); 260644961713Sgirish tx_msg_ring = KMEM_ZALLOC(size, KM_SLEEP); 260744961713Sgirish for (i = 0; i < nmsgs; i++) { 260844961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr, 260952ccf843Smisaki DDI_DMA_DONTWAIT, 0, 261052ccf843Smisaki &tx_msg_ring[i].dma_handle); 261144961713Sgirish if (ddi_status != DDI_SUCCESS) { 261244961713Sgirish status |= NXGE_DDI_FAILED; 261344961713Sgirish break; 261444961713Sgirish } 261544961713Sgirish } 261644961713Sgirish if (i < nmsgs) { 261756d930aeSspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 261856d930aeSspeer "Allocate handles failed.")); 261944961713Sgirish goto nxge_map_txdma_channel_buf_ring_fail1; 262044961713Sgirish } 262144961713Sgirish 262244961713Sgirish tx_ring_p->tdc = channel; 262344961713Sgirish tx_ring_p->tx_msg_ring = tx_msg_ring; 262444961713Sgirish tx_ring_p->tx_ring_size = nmsgs; 262544961713Sgirish tx_ring_p->num_chunks = num_chunks; 262644961713Sgirish if (!nxge_tx_intr_thres) { 262744961713Sgirish nxge_tx_intr_thres = tx_ring_p->tx_ring_size/4; 262844961713Sgirish } 262944961713Sgirish tx_ring_p->tx_wrap_mask = tx_ring_p->tx_ring_size - 1; 263044961713Sgirish tx_ring_p->rd_index = 0; 263144961713Sgirish tx_ring_p->wr_index = 0; 263244961713Sgirish tx_ring_p->ring_head.value = 0; 263344961713Sgirish tx_ring_p->ring_kick_tail.value = 0; 263444961713Sgirish tx_ring_p->descs_pending = 0; 263544961713Sgirish 263644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 263752ccf843Smisaki "==> nxge_map_txdma_channel_buf_ring: channel %d " 263852ccf843Smisaki "actual tx desc max %d nmsgs %d " 263952ccf843Smisaki "(config nxge_tx_ring_size %d)", 264052ccf843Smisaki channel, tx_ring_p->tx_ring_size, nmsgs, 264152ccf843Smisaki nxge_tx_ring_size)); 264244961713Sgirish 264344961713Sgirish /* 264444961713Sgirish * Map in buffers from the buffer pool. 264544961713Sgirish */ 264644961713Sgirish index = 0; 264744961713Sgirish bsize = dma_bufp->block_size; 264844961713Sgirish 264944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma_channel_buf_ring: " 265052ccf843Smisaki "dma_bufp $%p tx_rng_p $%p " 265152ccf843Smisaki "tx_msg_rng_p $%p bsize %d", 265252ccf843Smisaki dma_bufp, tx_ring_p, tx_msg_ring, bsize)); 265344961713Sgirish 265444961713Sgirish tx_buf_dma_handle = dma_bufp->dma_handle; 265544961713Sgirish for (i = 0; i < num_chunks; i++, dma_bufp++) { 265644961713Sgirish bsize = dma_bufp->block_size; 265744961713Sgirish nblocks = dma_bufp->nblocks; 265844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 265952ccf843Smisaki "==> nxge_map_txdma_channel_buf_ring: dma chunk %d " 266052ccf843Smisaki "size %d dma_bufp $%p", 266152ccf843Smisaki i, sizeof (nxge_dma_common_t), dma_bufp)); 266244961713Sgirish 266344961713Sgirish for (j = 0; j < nblocks; j++) { 266444961713Sgirish tx_msg_ring[index].buf_dma_handle = tx_buf_dma_handle; 2665*2d99c5d4SMichael Speer tx_msg_ring[index].nextp = NULL; 266644961713Sgirish dmap = &tx_msg_ring[index++].buf_dma; 266744961713Sgirish #ifdef TX_MEM_DEBUG 266844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 266952ccf843Smisaki "==> nxge_map_txdma_channel_buf_ring: j %d" 267052ccf843Smisaki "dmap $%p", i, dmap)); 267144961713Sgirish #endif 267244961713Sgirish nxge_setup_dma_common(dmap, dma_bufp, 1, 267352ccf843Smisaki bsize); 267444961713Sgirish } 267544961713Sgirish } 267644961713Sgirish 267744961713Sgirish if (i < num_chunks) { 267856d930aeSspeer status = NXGE_ERROR; 267944961713Sgirish goto nxge_map_txdma_channel_buf_ring_fail1; 268044961713Sgirish } 268144961713Sgirish 268244961713Sgirish *tx_desc_p = tx_ring_p; 268344961713Sgirish 268444961713Sgirish goto nxge_map_txdma_channel_buf_ring_exit; 268544961713Sgirish 268644961713Sgirish nxge_map_txdma_channel_buf_ring_fail1: 26871f8914d5Sml if (tx_ring_p->serial) { 26881f8914d5Sml nxge_serialize_destroy(tx_ring_p->serial); 26891f8914d5Sml tx_ring_p->serial = NULL; 26901f8914d5Sml } 26911f8914d5Sml 269244961713Sgirish index--; 269344961713Sgirish for (; index >= 0; index--) { 269456d930aeSspeer if (tx_msg_ring[index].dma_handle != NULL) { 269556d930aeSspeer ddi_dma_free_handle(&tx_msg_ring[index].dma_handle); 269644961713Sgirish } 269744961713Sgirish } 2698*2d99c5d4SMichael Speer 2699*2d99c5d4SMichael Speer MUTEX_DESTROY(&tx_ring_p->freelock); 270044961713Sgirish MUTEX_DESTROY(&tx_ring_p->lock); 270156d930aeSspeer KMEM_FREE(tx_msg_ring, size); 270244961713Sgirish KMEM_FREE(tx_ring_p, sizeof (tx_ring_t)); 270344961713Sgirish 270456d930aeSspeer status = NXGE_ERROR; 270556d930aeSspeer 270644961713Sgirish nxge_map_txdma_channel_buf_ring_exit: 270744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 270852ccf843Smisaki "<== nxge_map_txdma_channel_buf_ring status 0x%x", status)); 270944961713Sgirish 271044961713Sgirish return (status); 271144961713Sgirish } 271244961713Sgirish 271344961713Sgirish /*ARGSUSED*/ 271444961713Sgirish static void 271544961713Sgirish nxge_unmap_txdma_channel_buf_ring(p_nxge_t nxgep, p_tx_ring_t tx_ring_p) 271644961713Sgirish { 271744961713Sgirish p_tx_msg_t tx_msg_ring; 271844961713Sgirish p_tx_msg_t tx_msg_p; 271944961713Sgirish int i; 272044961713Sgirish 272144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 272252ccf843Smisaki "==> nxge_unmap_txdma_channel_buf_ring")); 272344961713Sgirish if (tx_ring_p == NULL) { 272444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 272552ccf843Smisaki "<== nxge_unmap_txdma_channel_buf_ring: NULL ringp")); 272644961713Sgirish return; 272744961713Sgirish } 272844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 272952ccf843Smisaki "==> nxge_unmap_txdma_channel_buf_ring: channel %d", 273052ccf843Smisaki tx_ring_p->tdc)); 273144961713Sgirish 273244961713Sgirish tx_msg_ring = tx_ring_p->tx_msg_ring; 2733678453a8Sspeer 2734678453a8Sspeer /* 2735678453a8Sspeer * Since the serialization thread, timer thread and 2736678453a8Sspeer * interrupt thread can all call the transmit reclaim, 2737678453a8Sspeer * the unmapping function needs to acquire the lock 2738678453a8Sspeer * to free those buffers which were transmitted 2739678453a8Sspeer * by the hardware already. 2740678453a8Sspeer */ 2741678453a8Sspeer MUTEX_ENTER(&tx_ring_p->lock); 2742678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, 2743678453a8Sspeer "==> nxge_unmap_txdma_channel_buf_ring (reclaim): " 2744678453a8Sspeer "channel %d", 2745678453a8Sspeer tx_ring_p->tdc)); 2746678453a8Sspeer (void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0); 2747678453a8Sspeer 274844961713Sgirish for (i = 0; i < tx_ring_p->tx_ring_size; i++) { 274944961713Sgirish tx_msg_p = &tx_msg_ring[i]; 275044961713Sgirish if (tx_msg_p->tx_message != NULL) { 275144961713Sgirish freemsg(tx_msg_p->tx_message); 275244961713Sgirish tx_msg_p->tx_message = NULL; 275344961713Sgirish } 275444961713Sgirish } 275544961713Sgirish 275644961713Sgirish for (i = 0; i < tx_ring_p->tx_ring_size; i++) { 275744961713Sgirish if (tx_msg_ring[i].dma_handle != NULL) { 275844961713Sgirish ddi_dma_free_handle(&tx_msg_ring[i].dma_handle); 275944961713Sgirish } 2760678453a8Sspeer tx_msg_ring[i].dma_handle = NULL; 276144961713Sgirish } 276244961713Sgirish 2763678453a8Sspeer MUTEX_EXIT(&tx_ring_p->lock); 2764678453a8Sspeer 27651f8914d5Sml if (tx_ring_p->serial) { 27661f8914d5Sml nxge_serialize_destroy(tx_ring_p->serial); 27671f8914d5Sml tx_ring_p->serial = NULL; 27681f8914d5Sml } 27691f8914d5Sml 2770*2d99c5d4SMichael Speer MUTEX_DESTROY(&tx_ring_p->freelock); 277144961713Sgirish MUTEX_DESTROY(&tx_ring_p->lock); 277244961713Sgirish KMEM_FREE(tx_msg_ring, sizeof (tx_msg_t) * tx_ring_p->tx_ring_size); 277344961713Sgirish KMEM_FREE(tx_ring_p, sizeof (tx_ring_t)); 277444961713Sgirish 277544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 277652ccf843Smisaki "<== nxge_unmap_txdma_channel_buf_ring")); 277744961713Sgirish } 277844961713Sgirish 277944961713Sgirish static nxge_status_t 2780678453a8Sspeer nxge_txdma_hw_start(p_nxge_t nxgep, int channel) 278144961713Sgirish { 278244961713Sgirish p_tx_rings_t tx_rings; 278344961713Sgirish p_tx_ring_t *tx_desc_rings; 278444961713Sgirish p_tx_mbox_areas_t tx_mbox_areas_p; 278544961713Sgirish p_tx_mbox_t *tx_mbox_p; 278644961713Sgirish nxge_status_t status = NXGE_OK; 278744961713Sgirish 278844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start")); 278944961713Sgirish 279044961713Sgirish tx_rings = nxgep->tx_rings; 279144961713Sgirish if (tx_rings == NULL) { 279244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 279352ccf843Smisaki "<== nxge_txdma_hw_start: NULL ring pointer")); 279444961713Sgirish return (NXGE_ERROR); 279544961713Sgirish } 279644961713Sgirish tx_desc_rings = tx_rings->rings; 279744961713Sgirish if (tx_desc_rings == NULL) { 279844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 279952ccf843Smisaki "<== nxge_txdma_hw_start: NULL ring pointers")); 280044961713Sgirish return (NXGE_ERROR); 280144961713Sgirish } 280244961713Sgirish 2803678453a8Sspeer NXGE_ERROR_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: " 2804678453a8Sspeer "tx_rings $%p tx_desc_rings $%p", tx_rings, tx_desc_rings)); 280544961713Sgirish 280644961713Sgirish tx_mbox_areas_p = nxgep->tx_mbox_areas_p; 280744961713Sgirish tx_mbox_p = tx_mbox_areas_p->txmbox_areas_p; 280844961713Sgirish 2809678453a8Sspeer status = nxge_txdma_start_channel(nxgep, channel, 2810678453a8Sspeer (p_tx_ring_t)tx_desc_rings[channel], 2811678453a8Sspeer (p_tx_mbox_t)tx_mbox_p[channel]); 2812678453a8Sspeer if (status != NXGE_OK) { 2813678453a8Sspeer goto nxge_txdma_hw_start_fail1; 281444961713Sgirish } 281544961713Sgirish 281644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: " 281752ccf843Smisaki "tx_rings $%p rings $%p", 281852ccf843Smisaki nxgep->tx_rings, nxgep->tx_rings->rings)); 281944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: " 282052ccf843Smisaki "tx_rings $%p tx_desc_rings $%p", 282152ccf843Smisaki nxgep->tx_rings, tx_desc_rings)); 282244961713Sgirish 282344961713Sgirish goto nxge_txdma_hw_start_exit; 282444961713Sgirish 282544961713Sgirish nxge_txdma_hw_start_fail1: 282644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 282752ccf843Smisaki "==> nxge_txdma_hw_start: disable " 282852ccf843Smisaki "(status 0x%x channel %d)", status, channel)); 282944961713Sgirish 283044961713Sgirish nxge_txdma_hw_start_exit: 283144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 283252ccf843Smisaki "==> nxge_txdma_hw_start: (status 0x%x)", status)); 283344961713Sgirish 283444961713Sgirish return (status); 283544961713Sgirish } 283644961713Sgirish 2837678453a8Sspeer /* 2838678453a8Sspeer * nxge_txdma_start_channel 2839678453a8Sspeer * 2840678453a8Sspeer * Start a TDC. 2841678453a8Sspeer * 2842678453a8Sspeer * Arguments: 2843678453a8Sspeer * nxgep 2844678453a8Sspeer * channel The channel to start. 2845678453a8Sspeer * tx_ring_p channel's transmit descriptor ring. 2846678453a8Sspeer * tx_mbox_p channel' smailbox. 2847678453a8Sspeer * 2848678453a8Sspeer * Notes: 2849678453a8Sspeer * 2850678453a8Sspeer * NPI/NXGE function calls: 2851678453a8Sspeer * nxge_reset_txdma_channel() 2852678453a8Sspeer * nxge_init_txdma_channel_event_mask() 2853678453a8Sspeer * nxge_enable_txdma_channel() 2854678453a8Sspeer * 2855678453a8Sspeer * Registers accessed: 2856678453a8Sspeer * none directly (see functions above). 2857678453a8Sspeer * 2858678453a8Sspeer * Context: 2859678453a8Sspeer * Any domain 2860678453a8Sspeer */ 286144961713Sgirish static nxge_status_t 286244961713Sgirish nxge_txdma_start_channel(p_nxge_t nxgep, uint16_t channel, 286344961713Sgirish p_tx_ring_t tx_ring_p, p_tx_mbox_t tx_mbox_p) 286444961713Sgirish 286544961713Sgirish { 286644961713Sgirish nxge_status_t status = NXGE_OK; 286744961713Sgirish 286844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 286944961713Sgirish "==> nxge_txdma_start_channel (channel %d)", channel)); 287044961713Sgirish /* 287144961713Sgirish * TXDMA/TXC must be in stopped state. 287244961713Sgirish */ 287344961713Sgirish (void) nxge_txdma_stop_inj_err(nxgep, channel); 287444961713Sgirish 287544961713Sgirish /* 287644961713Sgirish * Reset TXDMA channel 287744961713Sgirish */ 287844961713Sgirish tx_ring_p->tx_cs.value = 0; 287944961713Sgirish tx_ring_p->tx_cs.bits.ldw.rst = 1; 288044961713Sgirish status = nxge_reset_txdma_channel(nxgep, channel, 288144961713Sgirish tx_ring_p->tx_cs.value); 288244961713Sgirish if (status != NXGE_OK) { 288344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 288444961713Sgirish "==> nxge_txdma_start_channel (channel %d)" 288544961713Sgirish " reset channel failed 0x%x", channel, status)); 288644961713Sgirish goto nxge_txdma_start_channel_exit; 288744961713Sgirish } 288844961713Sgirish 288944961713Sgirish /* 289044961713Sgirish * Initialize the TXDMA channel specific FZC control 289144961713Sgirish * configurations. These FZC registers are pertaining 289244961713Sgirish * to each TX channel (i.e. logical pages). 289344961713Sgirish */ 2894678453a8Sspeer if (!isLDOMguest(nxgep)) { 2895678453a8Sspeer status = nxge_init_fzc_txdma_channel(nxgep, channel, 2896678453a8Sspeer tx_ring_p, tx_mbox_p); 2897678453a8Sspeer if (status != NXGE_OK) { 2898678453a8Sspeer goto nxge_txdma_start_channel_exit; 2899678453a8Sspeer } 290044961713Sgirish } 290144961713Sgirish 290244961713Sgirish /* 290344961713Sgirish * Initialize the event masks. 290444961713Sgirish */ 290544961713Sgirish tx_ring_p->tx_evmask.value = 0; 290644961713Sgirish status = nxge_init_txdma_channel_event_mask(nxgep, 2907678453a8Sspeer channel, &tx_ring_p->tx_evmask); 290844961713Sgirish if (status != NXGE_OK) { 290944961713Sgirish goto nxge_txdma_start_channel_exit; 291044961713Sgirish } 291144961713Sgirish 291244961713Sgirish /* 291344961713Sgirish * Load TXDMA descriptors, buffers, mailbox, 291444961713Sgirish * initialise the DMA channels and 291544961713Sgirish * enable each DMA channel. 291644961713Sgirish */ 291744961713Sgirish status = nxge_enable_txdma_channel(nxgep, channel, 291844961713Sgirish tx_ring_p, tx_mbox_p); 291944961713Sgirish if (status != NXGE_OK) { 292044961713Sgirish goto nxge_txdma_start_channel_exit; 292144961713Sgirish } 292244961713Sgirish 292344961713Sgirish nxge_txdma_start_channel_exit: 292444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_txdma_start_channel")); 292544961713Sgirish 292644961713Sgirish return (status); 292744961713Sgirish } 292844961713Sgirish 2929678453a8Sspeer /* 2930678453a8Sspeer * nxge_txdma_stop_channel 2931678453a8Sspeer * 2932678453a8Sspeer * Stop a TDC. 2933678453a8Sspeer * 2934678453a8Sspeer * Arguments: 2935678453a8Sspeer * nxgep 2936678453a8Sspeer * channel The channel to stop. 2937678453a8Sspeer * tx_ring_p channel's transmit descriptor ring. 2938678453a8Sspeer * tx_mbox_p channel' smailbox. 2939678453a8Sspeer * 2940678453a8Sspeer * Notes: 2941678453a8Sspeer * 2942678453a8Sspeer * NPI/NXGE function calls: 2943678453a8Sspeer * nxge_txdma_stop_inj_err() 2944678453a8Sspeer * nxge_reset_txdma_channel() 2945678453a8Sspeer * nxge_init_txdma_channel_event_mask() 2946678453a8Sspeer * nxge_init_txdma_channel_cntl_stat() 2947678453a8Sspeer * nxge_disable_txdma_channel() 2948678453a8Sspeer * 2949678453a8Sspeer * Registers accessed: 2950678453a8Sspeer * none directly (see functions above). 2951678453a8Sspeer * 2952678453a8Sspeer * Context: 2953678453a8Sspeer * Any domain 2954678453a8Sspeer */ 295544961713Sgirish /*ARGSUSED*/ 295644961713Sgirish static nxge_status_t 2957678453a8Sspeer nxge_txdma_stop_channel(p_nxge_t nxgep, uint16_t channel) 295844961713Sgirish { 2959678453a8Sspeer p_tx_ring_t tx_ring_p; 2960678453a8Sspeer int status = NXGE_OK; 296144961713Sgirish 296244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 296352ccf843Smisaki "==> nxge_txdma_stop_channel: channel %d", channel)); 296444961713Sgirish 296544961713Sgirish /* 296644961713Sgirish * Stop (disable) TXDMA and TXC (if stop bit is set 296744961713Sgirish * and STOP_N_GO bit not set, the TXDMA reset state will 296844961713Sgirish * not be set if reset TXDMA. 296944961713Sgirish */ 297044961713Sgirish (void) nxge_txdma_stop_inj_err(nxgep, channel); 297144961713Sgirish 2972678453a8Sspeer tx_ring_p = nxgep->tx_rings->rings[channel]; 2973678453a8Sspeer 297444961713Sgirish /* 297544961713Sgirish * Reset TXDMA channel 297644961713Sgirish */ 297744961713Sgirish tx_ring_p->tx_cs.value = 0; 297844961713Sgirish tx_ring_p->tx_cs.bits.ldw.rst = 1; 297944961713Sgirish status = nxge_reset_txdma_channel(nxgep, channel, 298052ccf843Smisaki tx_ring_p->tx_cs.value); 298144961713Sgirish if (status != NXGE_OK) { 298244961713Sgirish goto nxge_txdma_stop_channel_exit; 298344961713Sgirish } 298444961713Sgirish 298544961713Sgirish #ifdef HARDWARE_REQUIRED 298644961713Sgirish /* Set up the interrupt event masks. */ 298744961713Sgirish tx_ring_p->tx_evmask.value = 0; 298844961713Sgirish status = nxge_init_txdma_channel_event_mask(nxgep, 298952ccf843Smisaki channel, &tx_ring_p->tx_evmask); 299044961713Sgirish if (status != NXGE_OK) { 299144961713Sgirish goto nxge_txdma_stop_channel_exit; 299244961713Sgirish } 299344961713Sgirish 299444961713Sgirish /* Initialize the DMA control and status register */ 299544961713Sgirish tx_ring_p->tx_cs.value = TX_ENT_MSK_MK_ALL; 299644961713Sgirish status = nxge_init_txdma_channel_cntl_stat(nxgep, channel, 299752ccf843Smisaki tx_ring_p->tx_cs.value); 299844961713Sgirish if (status != NXGE_OK) { 299944961713Sgirish goto nxge_txdma_stop_channel_exit; 300044961713Sgirish } 300144961713Sgirish 3002678453a8Sspeer tx_mbox_p = nxgep->tx_mbox_areas_p->txmbox_areas_p[channel]; 3003678453a8Sspeer 300444961713Sgirish /* Disable channel */ 300544961713Sgirish status = nxge_disable_txdma_channel(nxgep, channel, 3006678453a8Sspeer tx_ring_p, tx_mbox_p); 300744961713Sgirish if (status != NXGE_OK) { 300844961713Sgirish goto nxge_txdma_start_channel_exit; 300944961713Sgirish } 301044961713Sgirish 301144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 301252ccf843Smisaki "==> nxge_txdma_stop_channel: event done")); 301344961713Sgirish 301444961713Sgirish #endif 301544961713Sgirish 301644961713Sgirish nxge_txdma_stop_channel_exit: 301744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_txdma_stop_channel")); 301844961713Sgirish return (status); 301944961713Sgirish } 302044961713Sgirish 3021678453a8Sspeer /* 3022678453a8Sspeer * nxge_txdma_get_ring 3023678453a8Sspeer * 3024678453a8Sspeer * Get the ring for a TDC. 3025678453a8Sspeer * 3026678453a8Sspeer * Arguments: 3027678453a8Sspeer * nxgep 3028678453a8Sspeer * channel 3029678453a8Sspeer * 3030678453a8Sspeer * Notes: 3031678453a8Sspeer * 3032678453a8Sspeer * NPI/NXGE function calls: 3033678453a8Sspeer * 3034678453a8Sspeer * Registers accessed: 3035678453a8Sspeer * 3036678453a8Sspeer * Context: 3037678453a8Sspeer * Any domain 3038678453a8Sspeer */ 303944961713Sgirish static p_tx_ring_t 304044961713Sgirish nxge_txdma_get_ring(p_nxge_t nxgep, uint16_t channel) 304144961713Sgirish { 3042678453a8Sspeer nxge_grp_set_t *set = &nxgep->tx_set; 3043678453a8Sspeer int tdc; 304444961713Sgirish 304544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_get_ring")); 304644961713Sgirish 3047678453a8Sspeer if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 304844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 3049678453a8Sspeer "<== nxge_txdma_get_ring: NULL ring pointer(s)")); 3050678453a8Sspeer goto return_null; 3051678453a8Sspeer } 3052678453a8Sspeer 3053678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3054678453a8Sspeer if ((1 << tdc) & set->owned.map) { 3055678453a8Sspeer tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 3056678453a8Sspeer if (ring) { 3057678453a8Sspeer if (channel == ring->tdc) { 3058678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, 3059678453a8Sspeer "<== nxge_txdma_get_ring: " 3060678453a8Sspeer "tdc %d ring $%p", tdc, ring)); 3061678453a8Sspeer return (ring); 3062678453a8Sspeer } 3063678453a8Sspeer } 306444961713Sgirish } 306544961713Sgirish } 306644961713Sgirish 3067678453a8Sspeer return_null: 3068678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_get_ring: " 306952ccf843Smisaki "ring not found")); 3070678453a8Sspeer 307144961713Sgirish return (NULL); 307244961713Sgirish } 307344961713Sgirish 3074678453a8Sspeer /* 3075678453a8Sspeer * nxge_txdma_get_mbox 3076678453a8Sspeer * 3077678453a8Sspeer * Get the mailbox for a TDC. 3078678453a8Sspeer * 3079678453a8Sspeer * Arguments: 3080678453a8Sspeer * nxgep 3081678453a8Sspeer * channel 3082678453a8Sspeer * 3083678453a8Sspeer * Notes: 3084678453a8Sspeer * 3085678453a8Sspeer * NPI/NXGE function calls: 3086678453a8Sspeer * 3087678453a8Sspeer * Registers accessed: 3088678453a8Sspeer * 3089678453a8Sspeer * Context: 3090678453a8Sspeer * Any domain 3091678453a8Sspeer */ 309244961713Sgirish static p_tx_mbox_t 309344961713Sgirish nxge_txdma_get_mbox(p_nxge_t nxgep, uint16_t channel) 309444961713Sgirish { 3095678453a8Sspeer nxge_grp_set_t *set = &nxgep->tx_set; 3096678453a8Sspeer int tdc; 309744961713Sgirish 309844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_get_mbox")); 309944961713Sgirish 3100678453a8Sspeer if (nxgep->tx_mbox_areas_p == 0 || 3101678453a8Sspeer nxgep->tx_mbox_areas_p->txmbox_areas_p == 0) { 3102678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, 3103678453a8Sspeer "<== nxge_txdma_get_mbox: NULL mailbox pointer(s)")); 3104678453a8Sspeer goto return_null; 310544961713Sgirish } 310644961713Sgirish 3107678453a8Sspeer if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 3108678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, 3109678453a8Sspeer "<== nxge_txdma_get_mbox: NULL ring pointer(s)")); 3110678453a8Sspeer goto return_null; 3111678453a8Sspeer } 3112678453a8Sspeer 3113678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3114678453a8Sspeer if ((1 << tdc) & set->owned.map) { 3115678453a8Sspeer tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 3116678453a8Sspeer if (ring) { 3117678453a8Sspeer if (channel == ring->tdc) { 3118678453a8Sspeer tx_mbox_t *mailbox = nxgep-> 3119678453a8Sspeer tx_mbox_areas_p-> 3120678453a8Sspeer txmbox_areas_p[tdc]; 3121678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, 3122678453a8Sspeer "<== nxge_txdma_get_mbox: tdc %d " 3123678453a8Sspeer "ring $%p", tdc, mailbox)); 3124678453a8Sspeer return (mailbox); 3125678453a8Sspeer } 3126678453a8Sspeer } 312744961713Sgirish } 312844961713Sgirish } 312944961713Sgirish 3130678453a8Sspeer return_null: 3131678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_get_mbox: " 313252ccf843Smisaki "mailbox not found")); 3133678453a8Sspeer 313444961713Sgirish return (NULL); 313544961713Sgirish } 313644961713Sgirish 3137678453a8Sspeer /* 3138678453a8Sspeer * nxge_tx_err_evnts 3139678453a8Sspeer * 3140678453a8Sspeer * Recover a TDC. 3141678453a8Sspeer * 3142678453a8Sspeer * Arguments: 3143678453a8Sspeer * nxgep 3144678453a8Sspeer * index The index to the TDC ring. 3145678453a8Sspeer * ldvp Used to get the channel number ONLY. 3146678453a8Sspeer * cs A copy of the bits from TX_CS. 3147678453a8Sspeer * 3148678453a8Sspeer * Notes: 3149678453a8Sspeer * Calling tree: 3150678453a8Sspeer * nxge_tx_intr() 3151678453a8Sspeer * 3152678453a8Sspeer * NPI/NXGE function calls: 3153678453a8Sspeer * npi_txdma_ring_error_get() 3154678453a8Sspeer * npi_txdma_inj_par_error_get() 3155678453a8Sspeer * nxge_txdma_fatal_err_recover() 3156678453a8Sspeer * 3157678453a8Sspeer * Registers accessed: 3158678453a8Sspeer * TX_RNG_ERR_LOGH DMC+0x40048 Transmit Ring Error Log High 3159678453a8Sspeer * TX_RNG_ERR_LOGL DMC+0x40050 Transmit Ring Error Log Low 3160678453a8Sspeer * TDMC_INJ_PAR_ERR (FZC_DMC + 0x45040) TDMC Inject Parity Error 3161678453a8Sspeer * 3162678453a8Sspeer * Context: 3163678453a8Sspeer * Any domain XXX Remove code which accesses TDMC_INJ_PAR_ERR. 3164678453a8Sspeer */ 316544961713Sgirish /*ARGSUSED*/ 316644961713Sgirish static nxge_status_t 316744961713Sgirish nxge_tx_err_evnts(p_nxge_t nxgep, uint_t index, p_nxge_ldv_t ldvp, tx_cs_t cs) 316844961713Sgirish { 316944961713Sgirish npi_handle_t handle; 317044961713Sgirish npi_status_t rs; 317144961713Sgirish uint8_t channel; 317244961713Sgirish p_tx_ring_t *tx_rings; 317344961713Sgirish p_tx_ring_t tx_ring_p; 317444961713Sgirish p_nxge_tx_ring_stats_t tdc_stats; 317544961713Sgirish boolean_t txchan_fatal = B_FALSE; 317644961713Sgirish nxge_status_t status = NXGE_OK; 317744961713Sgirish tdmc_inj_par_err_t par_err; 317844961713Sgirish uint32_t value; 317944961713Sgirish 3180678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX2_CTL, "==> nxge_tx_err_evnts")); 318144961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 318244961713Sgirish channel = ldvp->channel; 318344961713Sgirish 318444961713Sgirish tx_rings = nxgep->tx_rings->rings; 318544961713Sgirish tx_ring_p = tx_rings[index]; 318644961713Sgirish tdc_stats = tx_ring_p->tdc_stats; 318744961713Sgirish if ((cs.bits.ldw.pkt_size_err) || (cs.bits.ldw.pref_buf_par_err) || 318852ccf843Smisaki (cs.bits.ldw.nack_pref) || (cs.bits.ldw.nack_pkt_rd) || 318952ccf843Smisaki (cs.bits.ldw.conf_part_err) || (cs.bits.ldw.pkt_prt_err)) { 319044961713Sgirish if ((rs = npi_txdma_ring_error_get(handle, channel, 319152ccf843Smisaki &tdc_stats->errlog)) != NPI_SUCCESS) 319244961713Sgirish return (NXGE_ERROR | rs); 319344961713Sgirish } 319444961713Sgirish 319544961713Sgirish if (cs.bits.ldw.mbox_err) { 319644961713Sgirish tdc_stats->mbox_err++; 319744961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 319852ccf843Smisaki NXGE_FM_EREPORT_TDMC_MBOX_ERR); 319944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 320052ccf843Smisaki "==> nxge_tx_err_evnts(channel %d): " 320152ccf843Smisaki "fatal error: mailbox", channel)); 320244961713Sgirish txchan_fatal = B_TRUE; 320344961713Sgirish } 320444961713Sgirish if (cs.bits.ldw.pkt_size_err) { 320544961713Sgirish tdc_stats->pkt_size_err++; 320644961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 320752ccf843Smisaki NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR); 320844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 320952ccf843Smisaki "==> nxge_tx_err_evnts(channel %d): " 321052ccf843Smisaki "fatal error: pkt_size_err", channel)); 321144961713Sgirish txchan_fatal = B_TRUE; 321244961713Sgirish } 321344961713Sgirish if (cs.bits.ldw.tx_ring_oflow) { 321444961713Sgirish tdc_stats->tx_ring_oflow++; 321544961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 321652ccf843Smisaki NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW); 321744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 321852ccf843Smisaki "==> nxge_tx_err_evnts(channel %d): " 321952ccf843Smisaki "fatal error: tx_ring_oflow", channel)); 322044961713Sgirish txchan_fatal = B_TRUE; 322144961713Sgirish } 322244961713Sgirish if (cs.bits.ldw.pref_buf_par_err) { 322344961713Sgirish tdc_stats->pre_buf_par_err++; 322444961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 322552ccf843Smisaki NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR); 322644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 322752ccf843Smisaki "==> nxge_tx_err_evnts(channel %d): " 322852ccf843Smisaki "fatal error: pre_buf_par_err", channel)); 322944961713Sgirish /* Clear error injection source for parity error */ 323044961713Sgirish (void) npi_txdma_inj_par_error_get(handle, &value); 323144961713Sgirish par_err.value = value; 323244961713Sgirish par_err.bits.ldw.inject_parity_error &= ~(1 << channel); 323344961713Sgirish (void) npi_txdma_inj_par_error_set(handle, par_err.value); 323444961713Sgirish txchan_fatal = B_TRUE; 323544961713Sgirish } 323644961713Sgirish if (cs.bits.ldw.nack_pref) { 323744961713Sgirish tdc_stats->nack_pref++; 323844961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 323952ccf843Smisaki NXGE_FM_EREPORT_TDMC_NACK_PREF); 324044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 324152ccf843Smisaki "==> nxge_tx_err_evnts(channel %d): " 324252ccf843Smisaki "fatal error: nack_pref", channel)); 324344961713Sgirish txchan_fatal = B_TRUE; 324444961713Sgirish } 324544961713Sgirish if (cs.bits.ldw.nack_pkt_rd) { 324644961713Sgirish tdc_stats->nack_pkt_rd++; 324744961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 324852ccf843Smisaki NXGE_FM_EREPORT_TDMC_NACK_PKT_RD); 324944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 325052ccf843Smisaki "==> nxge_tx_err_evnts(channel %d): " 325152ccf843Smisaki "fatal error: nack_pkt_rd", channel)); 325244961713Sgirish txchan_fatal = B_TRUE; 325344961713Sgirish } 325444961713Sgirish if (cs.bits.ldw.conf_part_err) { 325544961713Sgirish tdc_stats->conf_part_err++; 325644961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 325752ccf843Smisaki NXGE_FM_EREPORT_TDMC_CONF_PART_ERR); 325844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 325952ccf843Smisaki "==> nxge_tx_err_evnts(channel %d): " 326052ccf843Smisaki "fatal error: config_partition_err", channel)); 326144961713Sgirish txchan_fatal = B_TRUE; 326244961713Sgirish } 326344961713Sgirish if (cs.bits.ldw.pkt_prt_err) { 326444961713Sgirish tdc_stats->pkt_part_err++; 326544961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 326652ccf843Smisaki NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR); 326744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 326852ccf843Smisaki "==> nxge_tx_err_evnts(channel %d): " 326952ccf843Smisaki "fatal error: pkt_prt_err", channel)); 327044961713Sgirish txchan_fatal = B_TRUE; 327144961713Sgirish } 327244961713Sgirish 327344961713Sgirish /* Clear error injection source in case this is an injected error */ 327444961713Sgirish TXDMA_REG_WRITE64(nxgep->npi_handle, TDMC_INTR_DBG_REG, channel, 0); 327544961713Sgirish 327644961713Sgirish if (txchan_fatal) { 327744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 327852ccf843Smisaki " nxge_tx_err_evnts: " 327952ccf843Smisaki " fatal error on channel %d cs 0x%llx\n", 328052ccf843Smisaki channel, cs.value)); 328144961713Sgirish status = nxge_txdma_fatal_err_recover(nxgep, channel, 328252ccf843Smisaki tx_ring_p); 328344961713Sgirish if (status == NXGE_OK) { 328444961713Sgirish FM_SERVICE_RESTORED(nxgep); 328544961713Sgirish } 328644961713Sgirish } 328744961713Sgirish 3288678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX2_CTL, "<== nxge_tx_err_evnts")); 328944961713Sgirish 329044961713Sgirish return (status); 329144961713Sgirish } 329244961713Sgirish 329344961713Sgirish static nxge_status_t 3294678453a8Sspeer nxge_txdma_fatal_err_recover( 3295678453a8Sspeer p_nxge_t nxgep, 3296678453a8Sspeer uint16_t channel, 3297678453a8Sspeer p_tx_ring_t tx_ring_p) 329844961713Sgirish { 329944961713Sgirish npi_handle_t handle; 330044961713Sgirish npi_status_t rs = NPI_SUCCESS; 330144961713Sgirish p_tx_mbox_t tx_mbox_p; 330244961713Sgirish nxge_status_t status = NXGE_OK; 330344961713Sgirish 330444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fatal_err_recover")); 330544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 330652ccf843Smisaki "Recovering from TxDMAChannel#%d error...", channel)); 330744961713Sgirish 330844961713Sgirish /* 330944961713Sgirish * Stop the dma channel waits for the stop done. 331044961713Sgirish * If the stop done bit is not set, then create 331144961713Sgirish * an error. 331244961713Sgirish */ 331344961713Sgirish 331444961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 331544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel stop...")); 331644961713Sgirish MUTEX_ENTER(&tx_ring_p->lock); 331744961713Sgirish rs = npi_txdma_channel_control(handle, TXDMA_STOP, channel); 331844961713Sgirish if (rs != NPI_SUCCESS) { 331944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 332052ccf843Smisaki "==> nxge_txdma_fatal_err_recover (channel %d): " 332152ccf843Smisaki "stop failed ", channel)); 332244961713Sgirish goto fail; 332344961713Sgirish } 332444961713Sgirish 332544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel reclaim...")); 332644961713Sgirish (void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0); 332744961713Sgirish 332844961713Sgirish /* 332944961713Sgirish * Reset TXDMA channel 333044961713Sgirish */ 333144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel reset...")); 333244961713Sgirish if ((rs = npi_txdma_channel_control(handle, TXDMA_RESET, channel)) != 333352ccf843Smisaki NPI_SUCCESS) { 333444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 333552ccf843Smisaki "==> nxge_txdma_fatal_err_recover (channel %d)" 333652ccf843Smisaki " reset channel failed 0x%x", channel, rs)); 333744961713Sgirish goto fail; 333844961713Sgirish } 333944961713Sgirish 334044961713Sgirish /* 334144961713Sgirish * Reset the tail (kick) register to 0. 334244961713Sgirish * (Hardware will not reset it. Tx overflow fatal 334344961713Sgirish * error if tail is not set to 0 after reset! 334444961713Sgirish */ 334544961713Sgirish TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, 0); 334644961713Sgirish 334744961713Sgirish /* Restart TXDMA channel */ 334844961713Sgirish 3349678453a8Sspeer if (!isLDOMguest(nxgep)) { 3350678453a8Sspeer tx_mbox_p = nxge_txdma_get_mbox(nxgep, channel); 335144961713Sgirish 3352678453a8Sspeer // XXX This is a problem in HIO! 3353678453a8Sspeer /* 3354678453a8Sspeer * Initialize the TXDMA channel specific FZC control 3355678453a8Sspeer * configurations. These FZC registers are pertaining 3356678453a8Sspeer * to each TX channel (i.e. logical pages). 3357678453a8Sspeer */ 3358678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel restart...")); 3359678453a8Sspeer status = nxge_init_fzc_txdma_channel(nxgep, channel, 3360678453a8Sspeer tx_ring_p, tx_mbox_p); 3361678453a8Sspeer if (status != NXGE_OK) 3362678453a8Sspeer goto fail; 3363678453a8Sspeer } 336444961713Sgirish 336544961713Sgirish /* 336644961713Sgirish * Initialize the event masks. 336744961713Sgirish */ 336844961713Sgirish tx_ring_p->tx_evmask.value = 0; 336944961713Sgirish status = nxge_init_txdma_channel_event_mask(nxgep, channel, 337052ccf843Smisaki &tx_ring_p->tx_evmask); 337144961713Sgirish if (status != NXGE_OK) 337244961713Sgirish goto fail; 337344961713Sgirish 337444961713Sgirish tx_ring_p->wr_index_wrap = B_FALSE; 337544961713Sgirish tx_ring_p->wr_index = 0; 337644961713Sgirish tx_ring_p->rd_index = 0; 337744961713Sgirish 337844961713Sgirish /* 337944961713Sgirish * Load TXDMA descriptors, buffers, mailbox, 338044961713Sgirish * initialise the DMA channels and 338144961713Sgirish * enable each DMA channel. 338244961713Sgirish */ 338344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel enable...")); 338444961713Sgirish status = nxge_enable_txdma_channel(nxgep, channel, 338552ccf843Smisaki tx_ring_p, tx_mbox_p); 338644961713Sgirish MUTEX_EXIT(&tx_ring_p->lock); 338744961713Sgirish if (status != NXGE_OK) 338844961713Sgirish goto fail; 338944961713Sgirish 3390*2d99c5d4SMichael Speer nxge_txdma_freemsg_task(tx_ring_p); 3391*2d99c5d4SMichael Speer 339244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 339352ccf843Smisaki "Recovery Successful, TxDMAChannel#%d Restored", 339452ccf843Smisaki channel)); 339544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fatal_err_recover")); 339644961713Sgirish 339744961713Sgirish return (NXGE_OK); 339844961713Sgirish 339944961713Sgirish fail: 340044961713Sgirish MUTEX_EXIT(&tx_ring_p->lock); 3401*2d99c5d4SMichael Speer 3402*2d99c5d4SMichael Speer nxge_txdma_freemsg_task(tx_ring_p); 3403*2d99c5d4SMichael Speer 340444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 340552ccf843Smisaki "nxge_txdma_fatal_err_recover (channel %d): " 340652ccf843Smisaki "failed to recover this txdma channel", channel)); 340744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed")); 340844961713Sgirish 340944961713Sgirish return (status); 341044961713Sgirish } 341144961713Sgirish 3412678453a8Sspeer /* 3413678453a8Sspeer * nxge_tx_port_fatal_err_recover 3414678453a8Sspeer * 3415678453a8Sspeer * Attempt to recover from a fatal port error. 3416678453a8Sspeer * 3417678453a8Sspeer * Arguments: 3418678453a8Sspeer * nxgep 3419678453a8Sspeer * 3420678453a8Sspeer * Notes: 3421678453a8Sspeer * How would a guest do this? 3422678453a8Sspeer * 3423678453a8Sspeer * NPI/NXGE function calls: 3424678453a8Sspeer * 3425678453a8Sspeer * Registers accessed: 3426678453a8Sspeer * 3427678453a8Sspeer * Context: 3428678453a8Sspeer * Service domain 3429678453a8Sspeer */ 343044961713Sgirish nxge_status_t 343144961713Sgirish nxge_tx_port_fatal_err_recover(p_nxge_t nxgep) 343244961713Sgirish { 3433678453a8Sspeer nxge_grp_set_t *set = &nxgep->tx_set; 3434678453a8Sspeer nxge_channel_t tdc; 3435678453a8Sspeer 3436678453a8Sspeer tx_ring_t *ring; 3437678453a8Sspeer tx_mbox_t *mailbox; 3438678453a8Sspeer 343944961713Sgirish npi_handle_t handle; 3440678453a8Sspeer nxge_status_t status; 3441678453a8Sspeer npi_status_t rs; 344244961713Sgirish 344344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_tx_port_fatal_err_recover")); 344444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3445678453a8Sspeer "Recovering from TxPort error...")); 344644961713Sgirish 3447678453a8Sspeer if (isLDOMguest(nxgep)) { 3448678453a8Sspeer return (NXGE_OK); 344944961713Sgirish } 345044961713Sgirish 3451678453a8Sspeer if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 3452678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, 3453678453a8Sspeer "<== nxge_tx_port_fatal_err_recover: not initialized")); 3454678453a8Sspeer return (NXGE_ERROR); 345544961713Sgirish } 345644961713Sgirish 3457678453a8Sspeer if (nxgep->tx_rings == 0 || nxgep->tx_rings->rings == 0) { 3458678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, 3459678453a8Sspeer "<== nxge_tx_port_fatal_err_recover: " 3460678453a8Sspeer "NULL ring pointer(s)")); 3461678453a8Sspeer return (NXGE_ERROR); 3462678453a8Sspeer } 346344961713Sgirish 3464678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3465678453a8Sspeer if ((1 << tdc) & set->owned.map) { 3466678453a8Sspeer tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 3467678453a8Sspeer if (ring) 3468678453a8Sspeer MUTEX_ENTER(&ring->lock); 346944961713Sgirish } 347044961713Sgirish } 347144961713Sgirish 3472678453a8Sspeer handle = NXGE_DEV_NPI_HANDLE(nxgep); 3473678453a8Sspeer 347444961713Sgirish /* 3475678453a8Sspeer * Stop all the TDCs owned by us. 3476678453a8Sspeer * (The shared TDCs will have been stopped by their owners.) 347744961713Sgirish */ 3478678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3479678453a8Sspeer if ((1 << tdc) & set->owned.map) { 3480678453a8Sspeer ring = nxgep->tx_rings->rings[tdc]; 3481678453a8Sspeer if (ring) { 3482678453a8Sspeer rs = npi_txdma_channel_control 3483678453a8Sspeer (handle, TXDMA_STOP, tdc); 3484678453a8Sspeer if (rs != NPI_SUCCESS) { 3485678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3486678453a8Sspeer "nxge_tx_port_fatal_err_recover " 3487678453a8Sspeer "(channel %d): stop failed ", tdc)); 3488678453a8Sspeer goto fail; 3489678453a8Sspeer } 3490678453a8Sspeer } 349144961713Sgirish } 3492678453a8Sspeer } 349344961713Sgirish 3494678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, "Reclaiming all TDCs...")); 349544961713Sgirish 3496678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3497678453a8Sspeer if ((1 << tdc) & set->owned.map) { 3498678453a8Sspeer tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 3499*2d99c5d4SMichael Speer if (ring) { 3500*2d99c5d4SMichael Speer MUTEX_ENTER(&ring->lock); 3501678453a8Sspeer (void) nxge_txdma_reclaim(nxgep, ring, 0); 3502*2d99c5d4SMichael Speer MUTEX_EXIT(&ring->lock); 3503*2d99c5d4SMichael Speer 3504*2d99c5d4SMichael Speer nxge_txdma_freemsg_task(ring); 3505*2d99c5d4SMichael Speer } 3506678453a8Sspeer } 350744961713Sgirish } 350844961713Sgirish 350944961713Sgirish /* 3510678453a8Sspeer * Reset all the TDCs. 351144961713Sgirish */ 3512678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, "Resetting all TDCs...")); 3513678453a8Sspeer 3514678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3515678453a8Sspeer if ((1 << tdc) & set->owned.map) { 3516678453a8Sspeer tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 3517678453a8Sspeer if (ring) { 3518678453a8Sspeer if ((rs = npi_txdma_channel_control 351952ccf843Smisaki (handle, TXDMA_RESET, tdc)) 3520678453a8Sspeer != NPI_SUCCESS) { 3521678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3522678453a8Sspeer "nxge_tx_port_fatal_err_recover " 3523678453a8Sspeer "(channel %d) reset channel " 3524678453a8Sspeer "failed 0x%x", tdc, rs)); 3525678453a8Sspeer goto fail; 3526678453a8Sspeer } 3527678453a8Sspeer } 3528678453a8Sspeer /* 3529678453a8Sspeer * Reset the tail (kick) register to 0. 3530678453a8Sspeer * (Hardware will not reset it. Tx overflow fatal 3531678453a8Sspeer * error if tail is not set to 0 after reset! 3532678453a8Sspeer */ 3533678453a8Sspeer TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, tdc, 0); 353444961713Sgirish } 3535678453a8Sspeer } 353644961713Sgirish 3537678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, "Restarting all TDCs...")); 3538678453a8Sspeer 3539678453a8Sspeer /* Restart all the TDCs */ 3540678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3541678453a8Sspeer if ((1 << tdc) & set->owned.map) { 3542678453a8Sspeer ring = nxgep->tx_rings->rings[tdc]; 3543678453a8Sspeer if (ring) { 3544678453a8Sspeer mailbox = nxge_txdma_get_mbox(nxgep, tdc); 3545678453a8Sspeer status = nxge_init_fzc_txdma_channel(nxgep, tdc, 3546678453a8Sspeer ring, mailbox); 3547678453a8Sspeer ring->tx_evmask.value = 0; 3548678453a8Sspeer /* 3549678453a8Sspeer * Initialize the event masks. 3550678453a8Sspeer */ 3551678453a8Sspeer status = nxge_init_txdma_channel_event_mask 3552678453a8Sspeer (nxgep, tdc, &ring->tx_evmask); 3553678453a8Sspeer 3554678453a8Sspeer ring->wr_index_wrap = B_FALSE; 3555678453a8Sspeer ring->wr_index = 0; 3556678453a8Sspeer ring->rd_index = 0; 3557678453a8Sspeer 3558678453a8Sspeer if (status != NXGE_OK) 3559678453a8Sspeer goto fail; 3560678453a8Sspeer if (status != NXGE_OK) 3561678453a8Sspeer goto fail; 3562678453a8Sspeer } 3563678453a8Sspeer } 356444961713Sgirish } 356544961713Sgirish 3566678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, "Re-enabling all TDCs...")); 356744961713Sgirish 3568678453a8Sspeer /* Re-enable all the TDCs */ 3569678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3570678453a8Sspeer if ((1 << tdc) & set->owned.map) { 3571678453a8Sspeer ring = nxgep->tx_rings->rings[tdc]; 3572678453a8Sspeer if (ring) { 3573678453a8Sspeer mailbox = nxge_txdma_get_mbox(nxgep, tdc); 3574678453a8Sspeer status = nxge_enable_txdma_channel(nxgep, tdc, 3575678453a8Sspeer ring, mailbox); 3576678453a8Sspeer if (status != NXGE_OK) 3577678453a8Sspeer goto fail; 3578678453a8Sspeer } 357944961713Sgirish } 358044961713Sgirish } 358144961713Sgirish 3582678453a8Sspeer /* 3583678453a8Sspeer * Unlock all the TDCs. 3584678453a8Sspeer */ 3585678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3586678453a8Sspeer if ((1 << tdc) & set->owned.map) { 3587678453a8Sspeer tx_ring_t *ring = nxgep->tx_rings->rings[tdc]; 3588678453a8Sspeer if (ring) 3589678453a8Sspeer MUTEX_EXIT(&ring->lock); 359044961713Sgirish } 359144961713Sgirish } 359244961713Sgirish 3593678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Tx port recovery succeeded")); 359444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_tx_port_fatal_err_recover")); 359544961713Sgirish 359644961713Sgirish return (NXGE_OK); 359744961713Sgirish 359844961713Sgirish fail: 3599678453a8Sspeer for (tdc = 0; tdc < NXGE_MAX_TDCS; tdc++) { 3600678453a8Sspeer if ((1 << tdc) & set->owned.map) { 3601678453a8Sspeer ring = nxgep->tx_rings->rings[tdc]; 3602678453a8Sspeer if (ring) 3603678453a8Sspeer MUTEX_EXIT(&ring->lock); 360444961713Sgirish } 360544961713Sgirish } 360644961713Sgirish 3607678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Tx port recovery failed")); 3608678453a8Sspeer NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_tx_port_fatal_err_recover")); 360944961713Sgirish 361044961713Sgirish return (status); 361144961713Sgirish } 361244961713Sgirish 3613678453a8Sspeer /* 3614678453a8Sspeer * nxge_txdma_inject_err 3615678453a8Sspeer * 3616678453a8Sspeer * Inject an error into a TDC. 3617678453a8Sspeer * 3618678453a8Sspeer * Arguments: 3619678453a8Sspeer * nxgep 3620678453a8Sspeer * err_id The error to inject. 3621678453a8Sspeer * chan The channel to inject into. 3622678453a8Sspeer * 3623678453a8Sspeer * Notes: 3624678453a8Sspeer * This is called from nxge_main.c:nxge_err_inject() 3625678453a8Sspeer * Has this ioctl ever been used? 3626678453a8Sspeer * 3627678453a8Sspeer * NPI/NXGE function calls: 3628678453a8Sspeer * npi_txdma_inj_par_error_get() 3629678453a8Sspeer * npi_txdma_inj_par_error_set() 3630678453a8Sspeer * 3631678453a8Sspeer * Registers accessed: 3632678453a8Sspeer * TDMC_INJ_PAR_ERR (FZC_DMC + 0x45040) TDMC Inject Parity Error 3633678453a8Sspeer * TDMC_INTR_DBG DMC + 0x40060 Transmit DMA Interrupt Debug 3634678453a8Sspeer * TDMC_INTR_DBG DMC + 0x40060 Transmit DMA Interrupt Debug 3635678453a8Sspeer * 3636678453a8Sspeer * Context: 3637678453a8Sspeer * Service domain 3638678453a8Sspeer */ 363944961713Sgirish void 364044961713Sgirish nxge_txdma_inject_err(p_nxge_t nxgep, uint32_t err_id, uint8_t chan) 364144961713Sgirish { 364244961713Sgirish tdmc_intr_dbg_t tdi; 364344961713Sgirish tdmc_inj_par_err_t par_err; 364444961713Sgirish uint32_t value; 364544961713Sgirish npi_handle_t handle; 364644961713Sgirish 364744961713Sgirish switch (err_id) { 364844961713Sgirish 364944961713Sgirish case NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR: 365044961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 365144961713Sgirish /* Clear error injection source for parity error */ 365244961713Sgirish (void) npi_txdma_inj_par_error_get(handle, &value); 365344961713Sgirish par_err.value = value; 365444961713Sgirish par_err.bits.ldw.inject_parity_error &= ~(1 << chan); 365544961713Sgirish (void) npi_txdma_inj_par_error_set(handle, par_err.value); 365644961713Sgirish 365744961713Sgirish par_err.bits.ldw.inject_parity_error = (1 << chan); 365844961713Sgirish (void) npi_txdma_inj_par_error_get(handle, &value); 365944961713Sgirish par_err.value = value; 366044961713Sgirish par_err.bits.ldw.inject_parity_error |= (1 << chan); 366144961713Sgirish cmn_err(CE_NOTE, "!Write 0x%llx to TDMC_INJ_PAR_ERR_REG\n", 366252ccf843Smisaki (unsigned long long)par_err.value); 366344961713Sgirish (void) npi_txdma_inj_par_error_set(handle, par_err.value); 366444961713Sgirish break; 366544961713Sgirish 366644961713Sgirish case NXGE_FM_EREPORT_TDMC_MBOX_ERR: 366744961713Sgirish case NXGE_FM_EREPORT_TDMC_NACK_PREF: 366844961713Sgirish case NXGE_FM_EREPORT_TDMC_NACK_PKT_RD: 366944961713Sgirish case NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR: 367044961713Sgirish case NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW: 367144961713Sgirish case NXGE_FM_EREPORT_TDMC_CONF_PART_ERR: 367244961713Sgirish case NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR: 367344961713Sgirish TXDMA_REG_READ64(nxgep->npi_handle, TDMC_INTR_DBG_REG, 367452ccf843Smisaki chan, &tdi.value); 367544961713Sgirish if (err_id == NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR) 367644961713Sgirish tdi.bits.ldw.pref_buf_par_err = 1; 367744961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_MBOX_ERR) 367844961713Sgirish tdi.bits.ldw.mbox_err = 1; 367944961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_NACK_PREF) 368044961713Sgirish tdi.bits.ldw.nack_pref = 1; 368144961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_NACK_PKT_RD) 368244961713Sgirish tdi.bits.ldw.nack_pkt_rd = 1; 368344961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR) 368444961713Sgirish tdi.bits.ldw.pkt_size_err = 1; 368544961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW) 368644961713Sgirish tdi.bits.ldw.tx_ring_oflow = 1; 368744961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_CONF_PART_ERR) 368844961713Sgirish tdi.bits.ldw.conf_part_err = 1; 368944961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR) 369044961713Sgirish tdi.bits.ldw.pkt_part_err = 1; 3691adfcba55Sjoycey #if defined(__i386) 3692adfcba55Sjoycey cmn_err(CE_NOTE, "!Write 0x%llx to TDMC_INTR_DBG_REG\n", 369352ccf843Smisaki tdi.value); 3694adfcba55Sjoycey #else 369544961713Sgirish cmn_err(CE_NOTE, "!Write 0x%lx to TDMC_INTR_DBG_REG\n", 369652ccf843Smisaki tdi.value); 3697adfcba55Sjoycey #endif 369844961713Sgirish TXDMA_REG_WRITE64(nxgep->npi_handle, TDMC_INTR_DBG_REG, 369952ccf843Smisaki chan, tdi.value); 370044961713Sgirish 370144961713Sgirish break; 370244961713Sgirish } 370344961713Sgirish } 3704