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 /* 22a3c5bd6dSspeer * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 2344961713Sgirish * Use is subject to license terms. 2444961713Sgirish */ 2544961713Sgirish 2644961713Sgirish #pragma ident "%Z%%M% %I% %E% SMI" 2744961713Sgirish 2844961713Sgirish #include <sys/nxge/nxge_impl.h> 2944961713Sgirish #include <sys/nxge/nxge_txdma.h> 3044961713Sgirish #include <sys/llc1.h> 3144961713Sgirish 3244961713Sgirish uint32_t nxge_reclaim_pending = TXDMA_RECLAIM_PENDING_DEFAULT; 3344961713Sgirish uint32_t nxge_tx_minfree = 32; 3444961713Sgirish uint32_t nxge_tx_intr_thres = 0; 3544961713Sgirish uint32_t nxge_tx_max_gathers = TX_MAX_GATHER_POINTERS; 3644961713Sgirish uint32_t nxge_tx_tiny_pack = 1; 3744961713Sgirish uint32_t nxge_tx_use_bcopy = 1; 3844961713Sgirish 3944961713Sgirish extern uint32_t nxge_tx_ring_size; 4044961713Sgirish extern uint32_t nxge_bcopy_thresh; 4144961713Sgirish extern uint32_t nxge_dvma_thresh; 4244961713Sgirish extern uint32_t nxge_dma_stream_thresh; 4344961713Sgirish extern dma_method_t nxge_force_dma; 4444961713Sgirish 4544961713Sgirish /* Device register access attributes for PIO. */ 4644961713Sgirish extern ddi_device_acc_attr_t nxge_dev_reg_acc_attr; 4744961713Sgirish /* Device descriptor access attributes for DMA. */ 4844961713Sgirish extern ddi_device_acc_attr_t nxge_dev_desc_dma_acc_attr; 4944961713Sgirish /* Device buffer access attributes for DMA. */ 5044961713Sgirish extern ddi_device_acc_attr_t nxge_dev_buf_dma_acc_attr; 5144961713Sgirish extern ddi_dma_attr_t nxge_desc_dma_attr; 5244961713Sgirish extern ddi_dma_attr_t nxge_tx_dma_attr; 5344961713Sgirish 541f8914d5Sml extern int nxge_serial_tx(mblk_t *mp, void *arg); 551f8914d5Sml 5644961713Sgirish static nxge_status_t nxge_map_txdma(p_nxge_t); 5744961713Sgirish static void nxge_unmap_txdma(p_nxge_t); 5844961713Sgirish 5944961713Sgirish static nxge_status_t nxge_txdma_hw_start(p_nxge_t); 6044961713Sgirish static void nxge_txdma_hw_stop(p_nxge_t); 6144961713Sgirish 6244961713Sgirish static nxge_status_t nxge_map_txdma_channel(p_nxge_t, uint16_t, 6344961713Sgirish p_nxge_dma_common_t *, p_tx_ring_t *, 6444961713Sgirish uint32_t, p_nxge_dma_common_t *, 6544961713Sgirish p_tx_mbox_t *); 6644961713Sgirish static void nxge_unmap_txdma_channel(p_nxge_t, uint16_t, 6744961713Sgirish p_tx_ring_t, p_tx_mbox_t); 6844961713Sgirish 6944961713Sgirish static nxge_status_t nxge_map_txdma_channel_buf_ring(p_nxge_t, uint16_t, 7044961713Sgirish p_nxge_dma_common_t *, p_tx_ring_t *, uint32_t); 7144961713Sgirish static void nxge_unmap_txdma_channel_buf_ring(p_nxge_t, p_tx_ring_t); 7244961713Sgirish 7344961713Sgirish static void nxge_map_txdma_channel_cfg_ring(p_nxge_t, uint16_t, 7444961713Sgirish p_nxge_dma_common_t *, p_tx_ring_t, 7544961713Sgirish p_tx_mbox_t *); 7644961713Sgirish static void nxge_unmap_txdma_channel_cfg_ring(p_nxge_t, 7744961713Sgirish p_tx_ring_t, p_tx_mbox_t); 7844961713Sgirish 7944961713Sgirish static nxge_status_t nxge_txdma_start_channel(p_nxge_t, uint16_t, 8044961713Sgirish p_tx_ring_t, p_tx_mbox_t); 8144961713Sgirish static nxge_status_t nxge_txdma_stop_channel(p_nxge_t, uint16_t, 8244961713Sgirish p_tx_ring_t, p_tx_mbox_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 9144961713Sgirish nxge_status_t 9244961713Sgirish nxge_init_txdma_channels(p_nxge_t nxgep) 9344961713Sgirish { 9444961713Sgirish nxge_status_t status = NXGE_OK; 9544961713Sgirish 9644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_init_txdma_channels")); 9744961713Sgirish 9844961713Sgirish status = nxge_map_txdma(nxgep); 9944961713Sgirish if (status != NXGE_OK) { 10044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 10144961713Sgirish "<== nxge_init_txdma_channels: status 0x%x", status)); 10244961713Sgirish return (status); 10344961713Sgirish } 10444961713Sgirish 10544961713Sgirish status = nxge_txdma_hw_start(nxgep); 10644961713Sgirish if (status != NXGE_OK) { 10744961713Sgirish nxge_unmap_txdma(nxgep); 10844961713Sgirish return (status); 10944961713Sgirish } 11044961713Sgirish 11144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 11244961713Sgirish "<== nxge_init_txdma_channels: status 0x%x", status)); 11344961713Sgirish 11444961713Sgirish return (NXGE_OK); 11544961713Sgirish } 11644961713Sgirish 11744961713Sgirish void 11844961713Sgirish nxge_uninit_txdma_channels(p_nxge_t nxgep) 11944961713Sgirish { 12044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_uninit_txdma_channels")); 12144961713Sgirish 12244961713Sgirish nxge_txdma_hw_stop(nxgep); 12344961713Sgirish nxge_unmap_txdma(nxgep); 12444961713Sgirish 12544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 12644961713Sgirish "<== nxge_uinit_txdma_channels")); 12744961713Sgirish } 12844961713Sgirish 12944961713Sgirish void 13044961713Sgirish nxge_setup_dma_common(p_nxge_dma_common_t dest_p, p_nxge_dma_common_t src_p, 13144961713Sgirish uint32_t entries, uint32_t size) 13244961713Sgirish { 13344961713Sgirish size_t tsize; 13444961713Sgirish *dest_p = *src_p; 13544961713Sgirish tsize = size * entries; 13644961713Sgirish dest_p->alength = tsize; 13744961713Sgirish dest_p->nblocks = entries; 13844961713Sgirish dest_p->block_size = size; 13944961713Sgirish dest_p->offset += tsize; 14044961713Sgirish 14144961713Sgirish src_p->kaddrp = (caddr_t)dest_p->kaddrp + tsize; 14244961713Sgirish src_p->alength -= tsize; 14344961713Sgirish src_p->dma_cookie.dmac_laddress += tsize; 14444961713Sgirish src_p->dma_cookie.dmac_size -= tsize; 14544961713Sgirish } 14644961713Sgirish 14744961713Sgirish nxge_status_t 14844961713Sgirish nxge_reset_txdma_channel(p_nxge_t nxgep, uint16_t channel, uint64_t reg_data) 14944961713Sgirish { 15044961713Sgirish npi_status_t rs = NPI_SUCCESS; 15144961713Sgirish nxge_status_t status = NXGE_OK; 15244961713Sgirish npi_handle_t handle; 15344961713Sgirish 15444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, " ==> nxge_reset_txdma_channel")); 15544961713Sgirish 15644961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 15744961713Sgirish if ((reg_data & TX_CS_RST_MASK) == TX_CS_RST_MASK) { 15844961713Sgirish rs = npi_txdma_channel_reset(handle, channel); 15944961713Sgirish } else { 16044961713Sgirish rs = npi_txdma_channel_control(handle, TXDMA_RESET, 16144961713Sgirish channel); 16244961713Sgirish } 16344961713Sgirish 16444961713Sgirish if (rs != NPI_SUCCESS) { 16544961713Sgirish status = NXGE_ERROR | rs; 16644961713Sgirish } 16744961713Sgirish 16844961713Sgirish /* 16944961713Sgirish * Reset the tail (kick) register to 0. 17044961713Sgirish * (Hardware will not reset it. Tx overflow fatal 17144961713Sgirish * error if tail is not set to 0 after reset! 17244961713Sgirish */ 17344961713Sgirish TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, 0); 17444961713Sgirish 17544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, " <== nxge_reset_txdma_channel")); 17644961713Sgirish return (status); 17744961713Sgirish } 17844961713Sgirish 17944961713Sgirish nxge_status_t 18044961713Sgirish nxge_init_txdma_channel_event_mask(p_nxge_t nxgep, uint16_t channel, 18144961713Sgirish p_tx_dma_ent_msk_t mask_p) 18244961713Sgirish { 18344961713Sgirish npi_handle_t handle; 18444961713Sgirish npi_status_t rs = NPI_SUCCESS; 18544961713Sgirish nxge_status_t status = NXGE_OK; 18644961713Sgirish 18744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 18844961713Sgirish "<== nxge_init_txdma_channel_event_mask")); 18944961713Sgirish 19044961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 19144961713Sgirish rs = npi_txdma_event_mask(handle, OP_SET, channel, mask_p); 19244961713Sgirish if (rs != NPI_SUCCESS) { 19344961713Sgirish status = NXGE_ERROR | rs; 19444961713Sgirish } 19544961713Sgirish 19644961713Sgirish return (status); 19744961713Sgirish } 19844961713Sgirish 19944961713Sgirish nxge_status_t 20044961713Sgirish nxge_init_txdma_channel_cntl_stat(p_nxge_t nxgep, uint16_t channel, 20144961713Sgirish uint64_t reg_data) 20244961713Sgirish { 20344961713Sgirish npi_handle_t handle; 20444961713Sgirish npi_status_t rs = NPI_SUCCESS; 20544961713Sgirish nxge_status_t status = NXGE_OK; 20644961713Sgirish 20744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 20844961713Sgirish "<== nxge_init_txdma_channel_cntl_stat")); 20944961713Sgirish 21044961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 21144961713Sgirish rs = npi_txdma_control_status(handle, OP_SET, channel, 21244961713Sgirish (p_tx_cs_t)®_data); 21344961713Sgirish 21444961713Sgirish if (rs != NPI_SUCCESS) { 21544961713Sgirish status = NXGE_ERROR | rs; 21644961713Sgirish } 21744961713Sgirish 21844961713Sgirish return (status); 21944961713Sgirish } 22044961713Sgirish 22144961713Sgirish nxge_status_t 22244961713Sgirish nxge_enable_txdma_channel(p_nxge_t nxgep, 22344961713Sgirish uint16_t channel, p_tx_ring_t tx_desc_p, p_tx_mbox_t mbox_p) 22444961713Sgirish { 22544961713Sgirish npi_handle_t handle; 22644961713Sgirish npi_status_t rs = NPI_SUCCESS; 22744961713Sgirish nxge_status_t status = NXGE_OK; 22844961713Sgirish 22944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_enable_txdma_channel")); 23044961713Sgirish 23144961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 23244961713Sgirish /* 23344961713Sgirish * Use configuration data composed at init time. 23444961713Sgirish * Write to hardware the transmit ring configurations. 23544961713Sgirish */ 23644961713Sgirish rs = npi_txdma_ring_config(handle, OP_SET, channel, 23744961713Sgirish (uint64_t *)&(tx_desc_p->tx_ring_cfig.value)); 23844961713Sgirish 23944961713Sgirish if (rs != NPI_SUCCESS) { 24044961713Sgirish return (NXGE_ERROR | rs); 24144961713Sgirish } 24244961713Sgirish 24344961713Sgirish /* Write to hardware the mailbox */ 24444961713Sgirish rs = npi_txdma_mbox_config(handle, OP_SET, channel, 24544961713Sgirish (uint64_t *)&mbox_p->tx_mbox.dma_cookie.dmac_laddress); 24644961713Sgirish 24744961713Sgirish if (rs != NPI_SUCCESS) { 24844961713Sgirish return (NXGE_ERROR | rs); 24944961713Sgirish } 25044961713Sgirish 25144961713Sgirish /* Start the DMA engine. */ 25244961713Sgirish rs = npi_txdma_channel_init_enable(handle, channel); 25344961713Sgirish 25444961713Sgirish if (rs != NPI_SUCCESS) { 25544961713Sgirish return (NXGE_ERROR | rs); 25644961713Sgirish } 25744961713Sgirish 25844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_enable_txdma_channel")); 25944961713Sgirish 26044961713Sgirish return (status); 26144961713Sgirish } 26244961713Sgirish 26344961713Sgirish void 26444961713Sgirish nxge_fill_tx_hdr(p_mblk_t mp, boolean_t fill_len, 26544961713Sgirish boolean_t l4_cksum, int pkt_len, uint8_t npads, 26644961713Sgirish p_tx_pkt_hdr_all_t pkthdrp) 26744961713Sgirish { 26844961713Sgirish p_tx_pkt_header_t hdrp; 26944961713Sgirish p_mblk_t nmp; 27044961713Sgirish uint64_t tmp; 27144961713Sgirish size_t mblk_len; 27244961713Sgirish size_t iph_len; 27344961713Sgirish size_t hdrs_size; 27444961713Sgirish uint8_t hdrs_buf[sizeof (struct ether_header) + 27544961713Sgirish 64 + sizeof (uint32_t)]; 27644961713Sgirish uint8_t *ip_buf; 27744961713Sgirish uint16_t eth_type; 27844961713Sgirish uint8_t ipproto; 27944961713Sgirish boolean_t is_vlan = B_FALSE; 28044961713Sgirish size_t eth_hdr_size; 28144961713Sgirish 28244961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: mp $%p", mp)); 28344961713Sgirish 28444961713Sgirish /* 28544961713Sgirish * Caller should zero out the headers first. 28644961713Sgirish */ 28744961713Sgirish hdrp = (p_tx_pkt_header_t)&pkthdrp->pkthdr; 28844961713Sgirish 28944961713Sgirish if (fill_len) { 29044961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 29144961713Sgirish "==> nxge_fill_tx_hdr: pkt_len %d " 29244961713Sgirish "npads %d", pkt_len, npads)); 29344961713Sgirish tmp = (uint64_t)pkt_len; 29444961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_TOT_XFER_LEN_SHIFT); 29544961713Sgirish goto fill_tx_header_done; 29644961713Sgirish } 29744961713Sgirish 29844961713Sgirish tmp = (uint64_t)npads; 29944961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_PAD_SHIFT); 30044961713Sgirish 30144961713Sgirish /* 30244961713Sgirish * mp is the original data packet (does not include the 30344961713Sgirish * Neptune transmit header). 30444961713Sgirish */ 30544961713Sgirish nmp = mp; 30644961713Sgirish mblk_len = (size_t)nmp->b_wptr - (size_t)nmp->b_rptr; 30744961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: " 30844961713Sgirish "mp $%p b_rptr $%p len %d", 30944961713Sgirish mp, nmp->b_rptr, mblk_len)); 31044961713Sgirish ip_buf = NULL; 31144961713Sgirish bcopy(nmp->b_rptr, &hdrs_buf[0], sizeof (struct ether_vlan_header)); 31244961713Sgirish eth_type = ntohs(((p_ether_header_t)hdrs_buf)->ether_type); 31344961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> : nxge_fill_tx_hdr: (value 0x%llx) " 31444961713Sgirish "ether type 0x%x", eth_type, hdrp->value)); 31544961713Sgirish 31644961713Sgirish if (eth_type < ETHERMTU) { 31744961713Sgirish tmp = 1ull; 31844961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_LLC_SHIFT); 31944961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: LLC " 32044961713Sgirish "value 0x%llx", hdrp->value)); 32144961713Sgirish if (*(hdrs_buf + sizeof (struct ether_header)) 32244961713Sgirish == LLC_SNAP_SAP) { 32344961713Sgirish eth_type = ntohs(*((uint16_t *)(hdrs_buf + 32444961713Sgirish sizeof (struct ether_header) + 6))); 32544961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 32644961713Sgirish "==> nxge_tx_pkt_hdr_init: LLC ether type 0x%x", 32744961713Sgirish eth_type)); 32844961713Sgirish } else { 32944961713Sgirish goto fill_tx_header_done; 33044961713Sgirish } 33144961713Sgirish } else if (eth_type == VLAN_ETHERTYPE) { 33244961713Sgirish tmp = 1ull; 33344961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_VLAN__SHIFT); 33444961713Sgirish 33544961713Sgirish eth_type = ntohs(((struct ether_vlan_header *) 33644961713Sgirish hdrs_buf)->ether_type); 33744961713Sgirish is_vlan = B_TRUE; 33844961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: VLAN " 33944961713Sgirish "value 0x%llx", hdrp->value)); 34044961713Sgirish } 34144961713Sgirish 34244961713Sgirish if (!is_vlan) { 34344961713Sgirish eth_hdr_size = sizeof (struct ether_header); 34444961713Sgirish } else { 34544961713Sgirish eth_hdr_size = sizeof (struct ether_vlan_header); 34644961713Sgirish } 34744961713Sgirish 34844961713Sgirish switch (eth_type) { 34944961713Sgirish case ETHERTYPE_IP: 35044961713Sgirish if (mblk_len > eth_hdr_size + sizeof (uint8_t)) { 35144961713Sgirish ip_buf = nmp->b_rptr + eth_hdr_size; 35244961713Sgirish mblk_len -= eth_hdr_size; 35344961713Sgirish iph_len = ((*ip_buf) & 0x0f); 35444961713Sgirish if (mblk_len > (iph_len + sizeof (uint32_t))) { 35544961713Sgirish ip_buf = nmp->b_rptr; 35644961713Sgirish ip_buf += eth_hdr_size; 35744961713Sgirish } else { 35844961713Sgirish ip_buf = NULL; 35944961713Sgirish } 36044961713Sgirish 36144961713Sgirish } 36244961713Sgirish if (ip_buf == NULL) { 36344961713Sgirish hdrs_size = 0; 36444961713Sgirish ((p_ether_header_t)hdrs_buf)->ether_type = 0; 36544961713Sgirish while ((nmp) && (hdrs_size < 36644961713Sgirish sizeof (hdrs_buf))) { 36744961713Sgirish mblk_len = (size_t)nmp->b_wptr - 36844961713Sgirish (size_t)nmp->b_rptr; 36944961713Sgirish if (mblk_len >= 37044961713Sgirish (sizeof (hdrs_buf) - hdrs_size)) 37144961713Sgirish mblk_len = sizeof (hdrs_buf) - 37244961713Sgirish hdrs_size; 37344961713Sgirish bcopy(nmp->b_rptr, 37444961713Sgirish &hdrs_buf[hdrs_size], mblk_len); 37544961713Sgirish hdrs_size += mblk_len; 37644961713Sgirish nmp = nmp->b_cont; 37744961713Sgirish } 37844961713Sgirish ip_buf = hdrs_buf; 37944961713Sgirish ip_buf += eth_hdr_size; 38044961713Sgirish iph_len = ((*ip_buf) & 0x0f); 38144961713Sgirish } 38244961713Sgirish 38344961713Sgirish ipproto = ip_buf[9]; 38444961713Sgirish 38544961713Sgirish tmp = (uint64_t)iph_len; 38644961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_IHL_SHIFT); 38744961713Sgirish tmp = (uint64_t)(eth_hdr_size >> 1); 38844961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_L3START_SHIFT); 38944961713Sgirish 39044961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: IPv4 " 39144961713Sgirish " iph_len %d l3start %d eth_hdr_size %d proto 0x%x" 39244961713Sgirish "tmp 0x%x", 39344961713Sgirish iph_len, hdrp->bits.hdw.l3start, eth_hdr_size, 39444961713Sgirish ipproto, tmp)); 39544961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: IP " 39644961713Sgirish "value 0x%llx", hdrp->value)); 39744961713Sgirish 39844961713Sgirish break; 39944961713Sgirish 40044961713Sgirish case ETHERTYPE_IPV6: 40144961713Sgirish hdrs_size = 0; 40244961713Sgirish ((p_ether_header_t)hdrs_buf)->ether_type = 0; 40344961713Sgirish while ((nmp) && (hdrs_size < 40444961713Sgirish sizeof (hdrs_buf))) { 40544961713Sgirish mblk_len = (size_t)nmp->b_wptr - (size_t)nmp->b_rptr; 40644961713Sgirish if (mblk_len >= 40744961713Sgirish (sizeof (hdrs_buf) - hdrs_size)) 40844961713Sgirish mblk_len = sizeof (hdrs_buf) - 40944961713Sgirish hdrs_size; 41044961713Sgirish bcopy(nmp->b_rptr, 41144961713Sgirish &hdrs_buf[hdrs_size], mblk_len); 41244961713Sgirish hdrs_size += mblk_len; 41344961713Sgirish nmp = nmp->b_cont; 41444961713Sgirish } 41544961713Sgirish ip_buf = hdrs_buf; 41644961713Sgirish ip_buf += eth_hdr_size; 41744961713Sgirish 41844961713Sgirish tmp = 1ull; 41944961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_IP_VER_SHIFT); 42044961713Sgirish 42144961713Sgirish tmp = (eth_hdr_size >> 1); 42244961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_L3START_SHIFT); 42344961713Sgirish 42444961713Sgirish /* byte 6 is the next header protocol */ 42544961713Sgirish ipproto = ip_buf[6]; 42644961713Sgirish 42744961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: IPv6 " 42844961713Sgirish " iph_len %d l3start %d eth_hdr_size %d proto 0x%x", 42944961713Sgirish iph_len, hdrp->bits.hdw.l3start, eth_hdr_size, 43044961713Sgirish ipproto)); 43144961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: IPv6 " 43244961713Sgirish "value 0x%llx", hdrp->value)); 43344961713Sgirish 43444961713Sgirish break; 43544961713Sgirish 43644961713Sgirish default: 43744961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: non-IP")); 43844961713Sgirish goto fill_tx_header_done; 43944961713Sgirish } 44044961713Sgirish 44144961713Sgirish switch (ipproto) { 44244961713Sgirish case IPPROTO_TCP: 44344961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 44444961713Sgirish "==> nxge_fill_tx_hdr: TCP (cksum flag %d)", l4_cksum)); 44544961713Sgirish if (l4_cksum) { 44644961713Sgirish tmp = 1ull; 44744961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_PKT_TYPE_SHIFT); 44844961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 44944961713Sgirish "==> nxge_tx_pkt_hdr_init: TCP CKSUM" 45044961713Sgirish "value 0x%llx", hdrp->value)); 45144961713Sgirish } 45244961713Sgirish 45344961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_hdr_init: TCP " 45444961713Sgirish "value 0x%llx", hdrp->value)); 45544961713Sgirish break; 45644961713Sgirish 45744961713Sgirish case IPPROTO_UDP: 45844961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_fill_tx_hdr: UDP")); 45944961713Sgirish if (l4_cksum) { 46044961713Sgirish tmp = 0x2ull; 46144961713Sgirish hdrp->value |= (tmp << TX_PKT_HEADER_PKT_TYPE_SHIFT); 46244961713Sgirish } 46344961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 46444961713Sgirish "==> nxge_tx_pkt_hdr_init: UDP" 46544961713Sgirish "value 0x%llx", hdrp->value)); 46644961713Sgirish break; 46744961713Sgirish 46844961713Sgirish default: 46944961713Sgirish goto fill_tx_header_done; 47044961713Sgirish } 47144961713Sgirish 47244961713Sgirish fill_tx_header_done: 47344961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 47444961713Sgirish "==> nxge_fill_tx_hdr: pkt_len %d " 47544961713Sgirish "npads %d value 0x%llx", pkt_len, npads, hdrp->value)); 47644961713Sgirish 47744961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "<== nxge_fill_tx_hdr")); 47844961713Sgirish } 47944961713Sgirish 48044961713Sgirish /*ARGSUSED*/ 48144961713Sgirish p_mblk_t 48244961713Sgirish nxge_tx_pkt_header_reserve(p_mblk_t mp, uint8_t *npads) 48344961713Sgirish { 48444961713Sgirish p_mblk_t newmp = NULL; 48544961713Sgirish 48644961713Sgirish if ((newmp = allocb(TX_PKT_HEADER_SIZE, BPRI_MED)) == NULL) { 48744961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 48844961713Sgirish "<== nxge_tx_pkt_header_reserve: allocb failed")); 48944961713Sgirish return (NULL); 49044961713Sgirish } 49144961713Sgirish 49244961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 49344961713Sgirish "==> nxge_tx_pkt_header_reserve: get new mp")); 49444961713Sgirish DB_TYPE(newmp) = M_DATA; 49544961713Sgirish newmp->b_rptr = newmp->b_wptr = DB_LIM(newmp); 49644961713Sgirish linkb(newmp, mp); 49744961713Sgirish newmp->b_rptr -= TX_PKT_HEADER_SIZE; 49844961713Sgirish 49944961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==>nxge_tx_pkt_header_reserve: " 50044961713Sgirish "b_rptr $%p b_wptr $%p", 50144961713Sgirish newmp->b_rptr, newmp->b_wptr)); 50244961713Sgirish 50344961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 50444961713Sgirish "<== nxge_tx_pkt_header_reserve: use new mp")); 50544961713Sgirish 50644961713Sgirish return (newmp); 50744961713Sgirish } 50844961713Sgirish 50944961713Sgirish int 51044961713Sgirish nxge_tx_pkt_nmblocks(p_mblk_t mp, int *tot_xfer_len_p) 51144961713Sgirish { 51244961713Sgirish uint_t nmblks; 51344961713Sgirish ssize_t len; 51444961713Sgirish uint_t pkt_len; 51544961713Sgirish p_mblk_t nmp, bmp, tmp; 51644961713Sgirish uint8_t *b_wptr; 51744961713Sgirish 51844961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 51944961713Sgirish "==> nxge_tx_pkt_nmblocks: mp $%p rptr $%p wptr $%p " 52044961713Sgirish "len %d", mp, mp->b_rptr, mp->b_wptr, MBLKL(mp))); 52144961713Sgirish 52244961713Sgirish nmp = mp; 52344961713Sgirish bmp = mp; 52444961713Sgirish nmblks = 0; 52544961713Sgirish pkt_len = 0; 52644961713Sgirish *tot_xfer_len_p = 0; 52744961713Sgirish 52844961713Sgirish while (nmp) { 52944961713Sgirish len = MBLKL(nmp); 53044961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_nmblocks: " 53144961713Sgirish "len %d pkt_len %d nmblks %d tot_xfer_len %d", 53244961713Sgirish len, pkt_len, nmblks, 53344961713Sgirish *tot_xfer_len_p)); 53444961713Sgirish 53544961713Sgirish if (len <= 0) { 53644961713Sgirish bmp = nmp; 53744961713Sgirish nmp = nmp->b_cont; 53844961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 53944961713Sgirish "==> nxge_tx_pkt_nmblocks: " 54044961713Sgirish "len (0) pkt_len %d nmblks %d", 54144961713Sgirish pkt_len, nmblks)); 54244961713Sgirish continue; 54344961713Sgirish } 54444961713Sgirish 54544961713Sgirish *tot_xfer_len_p += len; 54644961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, "==> nxge_tx_pkt_nmblocks: " 54744961713Sgirish "len %d pkt_len %d nmblks %d tot_xfer_len %d", 54844961713Sgirish len, pkt_len, nmblks, 54944961713Sgirish *tot_xfer_len_p)); 55044961713Sgirish 55144961713Sgirish if (len < nxge_bcopy_thresh) { 55244961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 55344961713Sgirish "==> nxge_tx_pkt_nmblocks: " 55444961713Sgirish "len %d (< thresh) pkt_len %d nmblks %d", 55544961713Sgirish len, pkt_len, nmblks)); 55644961713Sgirish if (pkt_len == 0) 55744961713Sgirish nmblks++; 55844961713Sgirish pkt_len += len; 55944961713Sgirish if (pkt_len >= nxge_bcopy_thresh) { 56044961713Sgirish pkt_len = 0; 56144961713Sgirish len = 0; 56244961713Sgirish nmp = bmp; 56344961713Sgirish } 56444961713Sgirish } else { 56544961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 56644961713Sgirish "==> nxge_tx_pkt_nmblocks: " 56744961713Sgirish "len %d (> thresh) pkt_len %d nmblks %d", 56844961713Sgirish len, pkt_len, nmblks)); 56944961713Sgirish pkt_len = 0; 57044961713Sgirish nmblks++; 57144961713Sgirish /* 57244961713Sgirish * Hardware limits the transfer length to 4K. 57344961713Sgirish * If len is more than 4K, we need to break 57444961713Sgirish * it up to at most 2 more blocks. 57544961713Sgirish */ 57644961713Sgirish if (len > TX_MAX_TRANSFER_LENGTH) { 57744961713Sgirish uint32_t nsegs; 57844961713Sgirish 57944961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 58044961713Sgirish "==> nxge_tx_pkt_nmblocks: " 58144961713Sgirish "len %d pkt_len %d nmblks %d nsegs %d", 58244961713Sgirish len, pkt_len, nmblks, nsegs)); 58344961713Sgirish nsegs = 1; 58444961713Sgirish if (len % (TX_MAX_TRANSFER_LENGTH * 2)) { 58544961713Sgirish ++nsegs; 58644961713Sgirish } 58744961713Sgirish do { 58844961713Sgirish b_wptr = nmp->b_rptr + 58944961713Sgirish TX_MAX_TRANSFER_LENGTH; 59044961713Sgirish nmp->b_wptr = b_wptr; 59144961713Sgirish if ((tmp = dupb(nmp)) == NULL) { 59244961713Sgirish return (0); 59344961713Sgirish } 59444961713Sgirish tmp->b_rptr = b_wptr; 59544961713Sgirish tmp->b_wptr = nmp->b_wptr; 59644961713Sgirish tmp->b_cont = nmp->b_cont; 59744961713Sgirish nmp->b_cont = tmp; 59844961713Sgirish nmblks++; 59944961713Sgirish if (--nsegs) { 60044961713Sgirish nmp = tmp; 60144961713Sgirish } 60244961713Sgirish } while (nsegs); 60344961713Sgirish nmp = tmp; 60444961713Sgirish } 60544961713Sgirish } 60644961713Sgirish 60744961713Sgirish /* 60844961713Sgirish * Hardware limits the transmit gather pointers to 15. 60944961713Sgirish */ 61044961713Sgirish if (nmp->b_cont && (nmblks + TX_GATHER_POINTERS_THRESHOLD) > 61144961713Sgirish TX_MAX_GATHER_POINTERS) { 61244961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 61344961713Sgirish "==> nxge_tx_pkt_nmblocks: pull msg - " 61444961713Sgirish "len %d pkt_len %d nmblks %d", 61544961713Sgirish len, pkt_len, nmblks)); 61644961713Sgirish /* Pull all message blocks from b_cont */ 61744961713Sgirish if ((tmp = msgpullup(nmp->b_cont, -1)) == NULL) { 61844961713Sgirish return (0); 61944961713Sgirish } 62044961713Sgirish freemsg(nmp->b_cont); 62144961713Sgirish nmp->b_cont = tmp; 62244961713Sgirish pkt_len = 0; 62344961713Sgirish } 62444961713Sgirish bmp = nmp; 62544961713Sgirish nmp = nmp->b_cont; 62644961713Sgirish } 62744961713Sgirish 62844961713Sgirish NXGE_DEBUG_MSG((NULL, TX_CTL, 62944961713Sgirish "<== nxge_tx_pkt_nmblocks: rptr $%p wptr $%p " 63044961713Sgirish "nmblks %d len %d tot_xfer_len %d", 63144961713Sgirish mp->b_rptr, mp->b_wptr, nmblks, 63244961713Sgirish MBLKL(mp), *tot_xfer_len_p)); 63344961713Sgirish 63444961713Sgirish return (nmblks); 63544961713Sgirish } 63644961713Sgirish 63744961713Sgirish boolean_t 63844961713Sgirish nxge_txdma_reclaim(p_nxge_t nxgep, p_tx_ring_t tx_ring_p, int nmblks) 63944961713Sgirish { 64044961713Sgirish boolean_t status = B_TRUE; 64144961713Sgirish p_nxge_dma_common_t tx_desc_dma_p; 64244961713Sgirish nxge_dma_common_t desc_area; 64344961713Sgirish p_tx_desc_t tx_desc_ring_vp; 64444961713Sgirish p_tx_desc_t tx_desc_p; 64544961713Sgirish p_tx_desc_t tx_desc_pp; 64644961713Sgirish tx_desc_t r_tx_desc; 64744961713Sgirish p_tx_msg_t tx_msg_ring; 64844961713Sgirish p_tx_msg_t tx_msg_p; 64944961713Sgirish npi_handle_t handle; 65044961713Sgirish tx_ring_hdl_t tx_head; 65144961713Sgirish uint32_t pkt_len; 65244961713Sgirish uint_t tx_rd_index; 65344961713Sgirish uint16_t head_index, tail_index; 65444961713Sgirish uint8_t tdc; 65544961713Sgirish boolean_t head_wrap, tail_wrap; 65644961713Sgirish p_nxge_tx_ring_stats_t tdc_stats; 65744961713Sgirish int rc; 65844961713Sgirish 65944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_reclaim")); 66044961713Sgirish 66144961713Sgirish status = ((tx_ring_p->descs_pending < nxge_reclaim_pending) && 66244961713Sgirish (nmblks != 0)); 66344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 66444961713Sgirish "==> nxge_txdma_reclaim: pending %d reclaim %d nmblks %d", 66544961713Sgirish tx_ring_p->descs_pending, nxge_reclaim_pending, 66644961713Sgirish nmblks)); 66744961713Sgirish if (!status) { 66844961713Sgirish tx_desc_dma_p = &tx_ring_p->tdc_desc; 66944961713Sgirish desc_area = tx_ring_p->tdc_desc; 67044961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 67144961713Sgirish tx_desc_ring_vp = tx_desc_dma_p->kaddrp; 67244961713Sgirish tx_desc_ring_vp = 67344961713Sgirish (p_tx_desc_t)DMA_COMMON_VPTR(desc_area); 67444961713Sgirish tx_rd_index = tx_ring_p->rd_index; 67544961713Sgirish tx_desc_p = &tx_desc_ring_vp[tx_rd_index]; 67644961713Sgirish tx_msg_ring = tx_ring_p->tx_msg_ring; 67744961713Sgirish tx_msg_p = &tx_msg_ring[tx_rd_index]; 67844961713Sgirish tdc = tx_ring_p->tdc; 67944961713Sgirish tdc_stats = tx_ring_p->tdc_stats; 68044961713Sgirish if (tx_ring_p->descs_pending > tdc_stats->tx_max_pend) { 68144961713Sgirish tdc_stats->tx_max_pend = tx_ring_p->descs_pending; 68244961713Sgirish } 68344961713Sgirish 68444961713Sgirish tail_index = tx_ring_p->wr_index; 68544961713Sgirish tail_wrap = tx_ring_p->wr_index_wrap; 68644961713Sgirish 68744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 68844961713Sgirish "==> nxge_txdma_reclaim: tdc %d tx_rd_index %d " 68944961713Sgirish "tail_index %d tail_wrap %d " 69044961713Sgirish "tx_desc_p $%p ($%p) ", 69144961713Sgirish tdc, tx_rd_index, tail_index, tail_wrap, 69244961713Sgirish tx_desc_p, (*(uint64_t *)tx_desc_p))); 69344961713Sgirish /* 69444961713Sgirish * Read the hardware maintained transmit head 69544961713Sgirish * and wrap around bit. 69644961713Sgirish */ 69744961713Sgirish TXDMA_REG_READ64(handle, TX_RING_HDL_REG, tdc, &tx_head.value); 69844961713Sgirish head_index = tx_head.bits.ldw.head; 69944961713Sgirish head_wrap = tx_head.bits.ldw.wrap; 70044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 70144961713Sgirish "==> nxge_txdma_reclaim: " 70244961713Sgirish "tx_rd_index %d tail %d tail_wrap %d " 70344961713Sgirish "head %d wrap %d", 70444961713Sgirish tx_rd_index, tail_index, tail_wrap, 70544961713Sgirish head_index, head_wrap)); 70644961713Sgirish 70744961713Sgirish if (head_index == tail_index) { 70844961713Sgirish if (TXDMA_RING_EMPTY(head_index, head_wrap, 70944961713Sgirish tail_index, tail_wrap) && 71044961713Sgirish (head_index == tx_rd_index)) { 71144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 71244961713Sgirish "==> nxge_txdma_reclaim: EMPTY")); 71344961713Sgirish return (B_TRUE); 71444961713Sgirish } 71544961713Sgirish 71644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 71744961713Sgirish "==> nxge_txdma_reclaim: Checking " 71844961713Sgirish "if ring full")); 71944961713Sgirish if (TXDMA_RING_FULL(head_index, head_wrap, tail_index, 72044961713Sgirish tail_wrap)) { 72144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 72244961713Sgirish "==> nxge_txdma_reclaim: full")); 72344961713Sgirish return (B_FALSE); 72444961713Sgirish } 72544961713Sgirish } 72644961713Sgirish 72744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 72844961713Sgirish "==> nxge_txdma_reclaim: tx_rd_index and head_index")); 72944961713Sgirish 73044961713Sgirish tx_desc_pp = &r_tx_desc; 73144961713Sgirish while ((tx_rd_index != head_index) && 73244961713Sgirish (tx_ring_p->descs_pending != 0)) { 73344961713Sgirish 73444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 73544961713Sgirish "==> nxge_txdma_reclaim: Checking if pending")); 73644961713Sgirish 73744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 73844961713Sgirish "==> nxge_txdma_reclaim: " 73944961713Sgirish "descs_pending %d ", 74044961713Sgirish tx_ring_p->descs_pending)); 74144961713Sgirish 74244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 74344961713Sgirish "==> nxge_txdma_reclaim: " 74444961713Sgirish "(tx_rd_index %d head_index %d " 74544961713Sgirish "(tx_desc_p $%p)", 74644961713Sgirish tx_rd_index, head_index, 74744961713Sgirish tx_desc_p)); 74844961713Sgirish 74944961713Sgirish tx_desc_pp->value = tx_desc_p->value; 75044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 75144961713Sgirish "==> nxge_txdma_reclaim: " 75244961713Sgirish "(tx_rd_index %d head_index %d " 75344961713Sgirish "tx_desc_p $%p (desc value 0x%llx) ", 75444961713Sgirish tx_rd_index, head_index, 75544961713Sgirish tx_desc_pp, (*(uint64_t *)tx_desc_pp))); 75644961713Sgirish 75744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 75844961713Sgirish "==> nxge_txdma_reclaim: dump desc:")); 75944961713Sgirish 76044961713Sgirish pkt_len = tx_desc_pp->bits.hdw.tr_len; 76144961713Sgirish tdc_stats->obytes += pkt_len; 76244961713Sgirish tdc_stats->opackets += tx_desc_pp->bits.hdw.sop; 76344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 76444961713Sgirish "==> nxge_txdma_reclaim: pkt_len %d " 76544961713Sgirish "tdc channel %d opackets %d", 76644961713Sgirish pkt_len, 76744961713Sgirish tdc, 76844961713Sgirish tdc_stats->opackets)); 76944961713Sgirish 77044961713Sgirish if (tx_msg_p->flags.dma_type == USE_DVMA) { 77144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 77244961713Sgirish "tx_desc_p = $%p " 77344961713Sgirish "tx_desc_pp = $%p " 77444961713Sgirish "index = %d", 77544961713Sgirish tx_desc_p, 77644961713Sgirish tx_desc_pp, 77744961713Sgirish tx_ring_p->rd_index)); 77844961713Sgirish (void) dvma_unload(tx_msg_p->dvma_handle, 77944961713Sgirish 0, -1); 78044961713Sgirish tx_msg_p->dvma_handle = NULL; 78144961713Sgirish if (tx_ring_p->dvma_wr_index == 78244961713Sgirish tx_ring_p->dvma_wrap_mask) { 78344961713Sgirish tx_ring_p->dvma_wr_index = 0; 78444961713Sgirish } else { 78544961713Sgirish tx_ring_p->dvma_wr_index++; 78644961713Sgirish } 78744961713Sgirish tx_ring_p->dvma_pending--; 78844961713Sgirish } else if (tx_msg_p->flags.dma_type == 78944961713Sgirish USE_DMA) { 79044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 79144961713Sgirish "==> nxge_txdma_reclaim: " 79244961713Sgirish "USE DMA")); 79344961713Sgirish if (rc = ddi_dma_unbind_handle 79444961713Sgirish (tx_msg_p->dma_handle)) { 79544961713Sgirish cmn_err(CE_WARN, "!nxge_reclaim: " 79644961713Sgirish "ddi_dma_unbind_handle " 79744961713Sgirish "failed. status %d", rc); 79844961713Sgirish } 79944961713Sgirish } 80044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 80144961713Sgirish "==> nxge_txdma_reclaim: count packets")); 80244961713Sgirish /* 80344961713Sgirish * count a chained packet only once. 80444961713Sgirish */ 80544961713Sgirish if (tx_msg_p->tx_message != NULL) { 80644961713Sgirish freemsg(tx_msg_p->tx_message); 80744961713Sgirish tx_msg_p->tx_message = NULL; 80844961713Sgirish } 80944961713Sgirish 81044961713Sgirish tx_msg_p->flags.dma_type = USE_NONE; 81144961713Sgirish tx_rd_index = tx_ring_p->rd_index; 81244961713Sgirish tx_rd_index = (tx_rd_index + 1) & 81344961713Sgirish tx_ring_p->tx_wrap_mask; 81444961713Sgirish tx_ring_p->rd_index = tx_rd_index; 81544961713Sgirish tx_ring_p->descs_pending--; 81644961713Sgirish tx_desc_p = &tx_desc_ring_vp[tx_rd_index]; 81744961713Sgirish tx_msg_p = &tx_msg_ring[tx_rd_index]; 81844961713Sgirish } 81944961713Sgirish 82044961713Sgirish status = (nmblks <= (tx_ring_p->tx_ring_size - 82144961713Sgirish tx_ring_p->descs_pending - 82244961713Sgirish TX_FULL_MARK)); 82344961713Sgirish if (status) { 82444961713Sgirish cas32((uint32_t *)&tx_ring_p->queueing, 1, 0); 82544961713Sgirish } 82644961713Sgirish } else { 82744961713Sgirish status = (nmblks <= 82844961713Sgirish (tx_ring_p->tx_ring_size - 82944961713Sgirish tx_ring_p->descs_pending - 83044961713Sgirish TX_FULL_MARK)); 83144961713Sgirish } 83244961713Sgirish 83344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 83444961713Sgirish "<== nxge_txdma_reclaim status = 0x%08x", status)); 83544961713Sgirish 83644961713Sgirish return (status); 83744961713Sgirish } 83844961713Sgirish 83944961713Sgirish uint_t 84044961713Sgirish nxge_tx_intr(void *arg1, void *arg2) 84144961713Sgirish { 84244961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 84344961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 84444961713Sgirish p_nxge_ldg_t ldgp; 84544961713Sgirish uint8_t channel; 84644961713Sgirish uint32_t vindex; 84744961713Sgirish npi_handle_t handle; 84844961713Sgirish tx_cs_t cs; 84944961713Sgirish p_tx_ring_t *tx_rings; 85044961713Sgirish p_tx_ring_t tx_ring_p; 85144961713Sgirish npi_status_t rs = NPI_SUCCESS; 85244961713Sgirish uint_t serviced = DDI_INTR_UNCLAIMED; 85344961713Sgirish nxge_status_t status = NXGE_OK; 85444961713Sgirish 85544961713Sgirish if (ldvp == NULL) { 85644961713Sgirish NXGE_DEBUG_MSG((NULL, INT_CTL, 85744961713Sgirish "<== nxge_tx_intr: nxgep $%p ldvp $%p", 85844961713Sgirish nxgep, ldvp)); 85944961713Sgirish return (DDI_INTR_UNCLAIMED); 86044961713Sgirish } 86144961713Sgirish 86244961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 86344961713Sgirish nxgep = ldvp->nxgep; 86444961713Sgirish } 86544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 86644961713Sgirish "==> nxge_tx_intr: nxgep(arg2) $%p ldvp(arg1) $%p", 86744961713Sgirish nxgep, ldvp)); 86844961713Sgirish /* 86944961713Sgirish * This interrupt handler is for a specific 87044961713Sgirish * transmit dma channel. 87144961713Sgirish */ 87244961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 87344961713Sgirish /* Get the control and status for this channel. */ 87444961713Sgirish channel = ldvp->channel; 87544961713Sgirish ldgp = ldvp->ldgp; 87644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 87744961713Sgirish "==> nxge_tx_intr: nxgep $%p ldvp (ldvp) $%p " 87844961713Sgirish "channel %d", 87944961713Sgirish nxgep, ldvp, channel)); 88044961713Sgirish 88144961713Sgirish rs = npi_txdma_control_status(handle, OP_GET, channel, &cs); 88244961713Sgirish vindex = ldvp->vdma_index; 88344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 88444961713Sgirish "==> nxge_tx_intr:channel %d ring index %d status 0x%08x", 88544961713Sgirish channel, vindex, rs)); 88644961713Sgirish if (!rs && cs.bits.ldw.mk) { 88744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 88844961713Sgirish "==> nxge_tx_intr:channel %d ring index %d " 88944961713Sgirish "status 0x%08x (mk bit set)", 89044961713Sgirish channel, vindex, rs)); 89144961713Sgirish tx_rings = nxgep->tx_rings->rings; 89244961713Sgirish tx_ring_p = tx_rings[vindex]; 89344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 89444961713Sgirish "==> nxge_tx_intr:channel %d ring index %d " 89544961713Sgirish "status 0x%08x (mk bit set, calling reclaim)", 89644961713Sgirish channel, vindex, rs)); 89744961713Sgirish 89844961713Sgirish MUTEX_ENTER(&tx_ring_p->lock); 89944961713Sgirish (void) nxge_txdma_reclaim(nxgep, tx_rings[vindex], 0); 90044961713Sgirish MUTEX_EXIT(&tx_ring_p->lock); 90144961713Sgirish mac_tx_update(nxgep->mach); 90244961713Sgirish } 90344961713Sgirish 90444961713Sgirish /* 90544961713Sgirish * Process other transmit control and status. 90644961713Sgirish * Check the ldv state. 90744961713Sgirish */ 90844961713Sgirish status = nxge_tx_err_evnts(nxgep, ldvp->vdma_index, ldvp, cs); 90944961713Sgirish /* 91044961713Sgirish * Rearm this logical group if this is a single device 91144961713Sgirish * group. 91244961713Sgirish */ 91344961713Sgirish if (ldgp->nldvs == 1) { 91444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 91544961713Sgirish "==> nxge_tx_intr: rearm")); 91644961713Sgirish if (status == NXGE_OK) { 91744961713Sgirish (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 91844961713Sgirish B_TRUE, ldgp->ldg_timer); 91944961713Sgirish } 92044961713Sgirish } 92144961713Sgirish 92244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_tx_intr")); 92344961713Sgirish serviced = DDI_INTR_CLAIMED; 92444961713Sgirish return (serviced); 92544961713Sgirish } 92644961713Sgirish 92744961713Sgirish void 92844961713Sgirish nxge_txdma_stop(p_nxge_t nxgep) 92944961713Sgirish { 93044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop")); 93144961713Sgirish 93244961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 93344961713Sgirish 93444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop")); 93544961713Sgirish } 93644961713Sgirish 93744961713Sgirish void 93844961713Sgirish nxge_txdma_stop_start(p_nxge_t nxgep) 93944961713Sgirish { 94044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop_start")); 94144961713Sgirish 94244961713Sgirish (void) nxge_txdma_stop(nxgep); 94344961713Sgirish 94444961713Sgirish (void) nxge_fixup_txdma_rings(nxgep); 94544961713Sgirish (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_START); 94644961713Sgirish (void) nxge_tx_mac_enable(nxgep); 94744961713Sgirish (void) nxge_txdma_hw_kick(nxgep); 94844961713Sgirish 94944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop_start")); 95044961713Sgirish } 95144961713Sgirish 95244961713Sgirish nxge_status_t 95344961713Sgirish nxge_txdma_hw_mode(p_nxge_t nxgep, boolean_t enable) 95444961713Sgirish { 95544961713Sgirish int i, ndmas; 95644961713Sgirish uint16_t channel; 95744961713Sgirish p_tx_rings_t tx_rings; 95844961713Sgirish p_tx_ring_t *tx_desc_rings; 95944961713Sgirish npi_handle_t handle; 96044961713Sgirish npi_status_t rs = NPI_SUCCESS; 96144961713Sgirish nxge_status_t status = NXGE_OK; 96244961713Sgirish 96344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 96444961713Sgirish "==> nxge_txdma_hw_mode: enable mode %d", enable)); 96544961713Sgirish 96644961713Sgirish if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 96744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 96844961713Sgirish "<== nxge_txdma_mode: not initialized")); 96944961713Sgirish return (NXGE_ERROR); 97044961713Sgirish } 97144961713Sgirish 97244961713Sgirish tx_rings = nxgep->tx_rings; 97344961713Sgirish if (tx_rings == NULL) { 97444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 97544961713Sgirish "<== nxge_txdma_hw_mode: NULL global ring pointer")); 97644961713Sgirish return (NXGE_ERROR); 97744961713Sgirish } 97844961713Sgirish 97944961713Sgirish tx_desc_rings = tx_rings->rings; 98044961713Sgirish if (tx_desc_rings == NULL) { 98144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 98244961713Sgirish "<== nxge_txdma_hw_mode: NULL rings pointer")); 98344961713Sgirish return (NXGE_ERROR); 98444961713Sgirish } 98544961713Sgirish 98644961713Sgirish ndmas = tx_rings->ndmas; 98744961713Sgirish if (!ndmas) { 98844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 98944961713Sgirish "<== nxge_txdma_hw_mode: no dma channel allocated")); 99044961713Sgirish return (NXGE_ERROR); 99144961713Sgirish } 99244961713Sgirish 99344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_mode: " 99444961713Sgirish "tx_rings $%p tx_desc_rings $%p ndmas %d", 99544961713Sgirish tx_rings, tx_desc_rings, ndmas)); 99644961713Sgirish 99744961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 99844961713Sgirish for (i = 0; i < ndmas; i++) { 99944961713Sgirish if (tx_desc_rings[i] == NULL) { 100044961713Sgirish continue; 100144961713Sgirish } 100244961713Sgirish channel = tx_desc_rings[i]->tdc; 100344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 100444961713Sgirish "==> nxge_txdma_hw_mode: channel %d", channel)); 100544961713Sgirish if (enable) { 100644961713Sgirish rs = npi_txdma_channel_enable(handle, channel); 100744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 100844961713Sgirish "==> nxge_txdma_hw_mode: channel %d (enable) " 100944961713Sgirish "rs 0x%x", channel, rs)); 101044961713Sgirish } else { 101144961713Sgirish /* 101244961713Sgirish * Stop the dma channel and waits for the stop done. 101344961713Sgirish * If the stop done bit is not set, then force 101444961713Sgirish * an error so TXC will stop. 101544961713Sgirish * All channels bound to this port need to be stopped 101644961713Sgirish * and reset after injecting an interrupt error. 101744961713Sgirish */ 101844961713Sgirish rs = npi_txdma_channel_disable(handle, channel); 101944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 102044961713Sgirish "==> nxge_txdma_hw_mode: channel %d (disable) " 102144961713Sgirish "rs 0x%x", channel, rs)); 102244961713Sgirish { 102344961713Sgirish tdmc_intr_dbg_t intr_dbg; 102444961713Sgirish 102544961713Sgirish if (rs != NPI_SUCCESS) { 102644961713Sgirish /* Inject any error */ 102744961713Sgirish intr_dbg.value = 0; 102844961713Sgirish intr_dbg.bits.ldw.nack_pref = 1; 102944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 103044961713Sgirish "==> nxge_txdma_hw_mode: " 103144961713Sgirish "channel %d (stop failed 0x%x) " 103244961713Sgirish "(inject err)", rs, channel)); 103344961713Sgirish (void) npi_txdma_inj_int_error_set( 103444961713Sgirish handle, channel, &intr_dbg); 103544961713Sgirish rs = npi_txdma_channel_disable(handle, 103644961713Sgirish channel); 103744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 103844961713Sgirish "==> nxge_txdma_hw_mode: " 103944961713Sgirish "channel %d (stop again 0x%x) " 104044961713Sgirish "(after inject err)", 104144961713Sgirish rs, channel)); 104244961713Sgirish } 104344961713Sgirish } 104444961713Sgirish } 104544961713Sgirish } 104644961713Sgirish 104744961713Sgirish status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs); 104844961713Sgirish 104944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 105044961713Sgirish "<== nxge_txdma_hw_mode: status 0x%x", status)); 105144961713Sgirish 105244961713Sgirish return (status); 105344961713Sgirish } 105444961713Sgirish 105544961713Sgirish void 105644961713Sgirish nxge_txdma_enable_channel(p_nxge_t nxgep, uint16_t channel) 105744961713Sgirish { 105844961713Sgirish npi_handle_t handle; 105944961713Sgirish 106044961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 106144961713Sgirish "==> nxge_txdma_enable_channel: channel %d", channel)); 106244961713Sgirish 106344961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 106444961713Sgirish /* enable the transmit dma channels */ 106544961713Sgirish (void) npi_txdma_channel_enable(handle, channel); 106644961713Sgirish 106744961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, "<== nxge_txdma_enable_channel")); 106844961713Sgirish } 106944961713Sgirish 107044961713Sgirish void 107144961713Sgirish nxge_txdma_disable_channel(p_nxge_t nxgep, uint16_t channel) 107244961713Sgirish { 107344961713Sgirish npi_handle_t handle; 107444961713Sgirish 107544961713Sgirish NXGE_DEBUG_MSG((nxgep, DMA_CTL, 107644961713Sgirish "==> nxge_txdma_disable_channel: channel %d", channel)); 107744961713Sgirish 107844961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 107944961713Sgirish /* stop the transmit dma channels */ 108044961713Sgirish (void) npi_txdma_channel_disable(handle, channel); 108144961713Sgirish 108244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_disable_channel")); 108344961713Sgirish } 108444961713Sgirish 108544961713Sgirish int 108644961713Sgirish nxge_txdma_stop_inj_err(p_nxge_t nxgep, int channel) 108744961713Sgirish { 108844961713Sgirish npi_handle_t handle; 108944961713Sgirish tdmc_intr_dbg_t intr_dbg; 109044961713Sgirish int status; 109144961713Sgirish npi_status_t rs = NPI_SUCCESS; 109244961713Sgirish 109344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_stop_inj_err")); 109444961713Sgirish /* 109544961713Sgirish * Stop the dma channel waits for the stop done. 109644961713Sgirish * If the stop done bit is not set, then create 109744961713Sgirish * an error. 109844961713Sgirish */ 109944961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 110044961713Sgirish rs = npi_txdma_channel_disable(handle, channel); 110144961713Sgirish status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs); 110244961713Sgirish if (status == NXGE_OK) { 110344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 110444961713Sgirish "<== nxge_txdma_stop_inj_err (channel %d): " 110544961713Sgirish "stopped OK", channel)); 110644961713Sgirish return (status); 110744961713Sgirish } 110844961713Sgirish 110944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 111044961713Sgirish "==> nxge_txdma_stop_inj_err (channel %d): stop failed (0x%x) " 111144961713Sgirish "injecting error", channel, rs)); 111244961713Sgirish /* Inject any error */ 111344961713Sgirish intr_dbg.value = 0; 111444961713Sgirish intr_dbg.bits.ldw.nack_pref = 1; 111544961713Sgirish (void) npi_txdma_inj_int_error_set(handle, channel, &intr_dbg); 111644961713Sgirish 111744961713Sgirish /* Stop done bit will be set as a result of error injection */ 111844961713Sgirish rs = npi_txdma_channel_disable(handle, channel); 111944961713Sgirish status = ((rs == NPI_SUCCESS) ? NXGE_OK : NXGE_ERROR | rs); 112044961713Sgirish if (!(rs & NPI_TXDMA_STOP_FAILED)) { 112144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 112244961713Sgirish "<== nxge_txdma_stop_inj_err (channel %d): " 112344961713Sgirish "stopped OK ", channel)); 112444961713Sgirish return (status); 112544961713Sgirish } 112644961713Sgirish 112744961713Sgirish #if defined(NXGE_DEBUG) 112844961713Sgirish nxge_txdma_regs_dump_channels(nxgep); 112944961713Sgirish #endif 113044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 113144961713Sgirish "==> nxge_txdma_stop_inj_err (channel): stop failed (0x%x) " 113244961713Sgirish " (injected error but still not stopped)", channel, rs)); 113344961713Sgirish 113444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_stop_inj_err")); 113544961713Sgirish return (status); 113644961713Sgirish } 113744961713Sgirish 113844961713Sgirish void 113944961713Sgirish nxge_hw_start_tx(p_nxge_t nxgep) 114044961713Sgirish { 114144961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_start_tx")); 114244961713Sgirish 114344961713Sgirish (void) nxge_txdma_hw_start(nxgep); 114444961713Sgirish (void) nxge_tx_mac_enable(nxgep); 114544961713Sgirish 114644961713Sgirish NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_start_tx")); 114744961713Sgirish } 114844961713Sgirish 114944961713Sgirish /*ARGSUSED*/ 115044961713Sgirish void 115144961713Sgirish nxge_fixup_txdma_rings(p_nxge_t nxgep) 115244961713Sgirish { 115344961713Sgirish int index, ndmas; 115444961713Sgirish uint16_t channel; 115544961713Sgirish p_tx_rings_t tx_rings; 115644961713Sgirish 115744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_fixup_txdma_rings")); 115844961713Sgirish 115944961713Sgirish /* 116044961713Sgirish * For each transmit channel, reclaim each descriptor and 116144961713Sgirish * free buffers. 116244961713Sgirish */ 116344961713Sgirish tx_rings = nxgep->tx_rings; 116444961713Sgirish if (tx_rings == NULL) { 116544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 116644961713Sgirish "<== nxge_fixup_txdma_rings: NULL ring pointer")); 116744961713Sgirish return; 116844961713Sgirish } 116944961713Sgirish 117044961713Sgirish ndmas = tx_rings->ndmas; 117144961713Sgirish if (!ndmas) { 117244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 117344961713Sgirish "<== nxge_fixup_txdma_rings: no channel allocated")); 117444961713Sgirish return; 117544961713Sgirish } 117644961713Sgirish 117744961713Sgirish if (tx_rings->rings == NULL) { 117844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 117944961713Sgirish "<== nxge_fixup_txdma_rings: NULL rings pointer")); 118044961713Sgirish return; 118144961713Sgirish } 118244961713Sgirish 118344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_fixup_txdma_rings: " 118444961713Sgirish "tx_rings $%p tx_desc_rings $%p ndmas %d", 118544961713Sgirish tx_rings, tx_rings->rings, ndmas)); 118644961713Sgirish 118744961713Sgirish for (index = 0; index < ndmas; index++) { 118844961713Sgirish channel = tx_rings->rings[index]->tdc; 118944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 119044961713Sgirish "==> nxge_fixup_txdma_rings: channel %d", channel)); 119144961713Sgirish 119244961713Sgirish nxge_txdma_fixup_channel(nxgep, tx_rings->rings[index], 119344961713Sgirish channel); 119444961713Sgirish } 119544961713Sgirish 119644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_fixup_txdma_rings")); 119744961713Sgirish } 119844961713Sgirish 119944961713Sgirish /*ARGSUSED*/ 120044961713Sgirish void 120144961713Sgirish nxge_txdma_fix_channel(p_nxge_t nxgep, uint16_t channel) 120244961713Sgirish { 120344961713Sgirish p_tx_ring_t ring_p; 120444961713Sgirish 120544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fix_channel")); 120644961713Sgirish ring_p = nxge_txdma_get_ring(nxgep, channel); 120744961713Sgirish if (ring_p == NULL) { 120844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_channel")); 120944961713Sgirish return; 121044961713Sgirish } 121144961713Sgirish 121244961713Sgirish if (ring_p->tdc != channel) { 121344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 121444961713Sgirish "<== nxge_txdma_fix_channel: channel not matched " 121544961713Sgirish "ring tdc %d passed channel", 121644961713Sgirish ring_p->tdc, channel)); 121744961713Sgirish return; 121844961713Sgirish } 121944961713Sgirish 122044961713Sgirish nxge_txdma_fixup_channel(nxgep, ring_p, channel); 122144961713Sgirish 122244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_channel")); 122344961713Sgirish } 122444961713Sgirish 122544961713Sgirish /*ARGSUSED*/ 122644961713Sgirish void 122744961713Sgirish nxge_txdma_fixup_channel(p_nxge_t nxgep, p_tx_ring_t ring_p, uint16_t channel) 122844961713Sgirish { 122944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fixup_channel")); 123044961713Sgirish 123144961713Sgirish if (ring_p == NULL) { 123244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 123344961713Sgirish "<== nxge_txdma_fixup_channel: NULL ring pointer")); 123444961713Sgirish return; 123544961713Sgirish } 123644961713Sgirish 123744961713Sgirish if (ring_p->tdc != channel) { 123844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 123944961713Sgirish "<== nxge_txdma_fixup_channel: channel not matched " 124044961713Sgirish "ring tdc %d passed channel", 124144961713Sgirish ring_p->tdc, channel)); 124244961713Sgirish return; 124344961713Sgirish } 124444961713Sgirish 124544961713Sgirish MUTEX_ENTER(&ring_p->lock); 124644961713Sgirish (void) nxge_txdma_reclaim(nxgep, ring_p, 0); 124744961713Sgirish ring_p->rd_index = 0; 124844961713Sgirish ring_p->wr_index = 0; 124944961713Sgirish ring_p->ring_head.value = 0; 125044961713Sgirish ring_p->ring_kick_tail.value = 0; 125144961713Sgirish ring_p->descs_pending = 0; 125244961713Sgirish MUTEX_EXIT(&ring_p->lock); 125344961713Sgirish 125444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fixup_channel")); 125544961713Sgirish } 125644961713Sgirish 125744961713Sgirish /*ARGSUSED*/ 125844961713Sgirish void 125944961713Sgirish nxge_txdma_hw_kick(p_nxge_t nxgep) 126044961713Sgirish { 126144961713Sgirish int index, ndmas; 126244961713Sgirish uint16_t channel; 126344961713Sgirish p_tx_rings_t tx_rings; 126444961713Sgirish 126544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hw_kick")); 126644961713Sgirish 126744961713Sgirish tx_rings = nxgep->tx_rings; 126844961713Sgirish if (tx_rings == NULL) { 126944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 127044961713Sgirish "<== nxge_txdma_hw_kick: NULL ring pointer")); 127144961713Sgirish return; 127244961713Sgirish } 127344961713Sgirish 127444961713Sgirish ndmas = tx_rings->ndmas; 127544961713Sgirish if (!ndmas) { 127644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 127744961713Sgirish "<== nxge_txdma_hw_kick: no channel allocated")); 127844961713Sgirish return; 127944961713Sgirish } 128044961713Sgirish 128144961713Sgirish if (tx_rings->rings == NULL) { 128244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 128344961713Sgirish "<== nxge_txdma_hw_kick: NULL rings pointer")); 128444961713Sgirish return; 128544961713Sgirish } 128644961713Sgirish 128744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_kick: " 128844961713Sgirish "tx_rings $%p tx_desc_rings $%p ndmas %d", 128944961713Sgirish tx_rings, tx_rings->rings, ndmas)); 129044961713Sgirish 129144961713Sgirish for (index = 0; index < ndmas; index++) { 129244961713Sgirish channel = tx_rings->rings[index]->tdc; 129344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 129444961713Sgirish "==> nxge_txdma_hw_kick: channel %d", channel)); 129544961713Sgirish nxge_txdma_hw_kick_channel(nxgep, tx_rings->rings[index], 129644961713Sgirish channel); 129744961713Sgirish } 129844961713Sgirish 129944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hw_kick")); 130044961713Sgirish } 130144961713Sgirish 130244961713Sgirish /*ARGSUSED*/ 130344961713Sgirish void 130444961713Sgirish nxge_txdma_kick_channel(p_nxge_t nxgep, uint16_t channel) 130544961713Sgirish { 130644961713Sgirish p_tx_ring_t ring_p; 130744961713Sgirish 130844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_kick_channel")); 130944961713Sgirish 131044961713Sgirish ring_p = nxge_txdma_get_ring(nxgep, channel); 131144961713Sgirish if (ring_p == NULL) { 131244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 131344961713Sgirish " nxge_txdma_kick_channel")); 131444961713Sgirish return; 131544961713Sgirish } 131644961713Sgirish 131744961713Sgirish if (ring_p->tdc != channel) { 131844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 131944961713Sgirish "<== nxge_txdma_kick_channel: channel not matched " 132044961713Sgirish "ring tdc %d passed channel", 132144961713Sgirish ring_p->tdc, channel)); 132244961713Sgirish return; 132344961713Sgirish } 132444961713Sgirish 132544961713Sgirish nxge_txdma_hw_kick_channel(nxgep, ring_p, channel); 132644961713Sgirish 132744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_kick_channel")); 132844961713Sgirish } 1329a3c5bd6dSspeer 133044961713Sgirish /*ARGSUSED*/ 133144961713Sgirish void 133244961713Sgirish nxge_txdma_hw_kick_channel(p_nxge_t nxgep, p_tx_ring_t ring_p, uint16_t channel) 133344961713Sgirish { 133444961713Sgirish 133544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hw_kick_channel")); 133644961713Sgirish 133744961713Sgirish if (ring_p == NULL) { 133844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 133944961713Sgirish "<== nxge_txdma_hw_kick_channel: NULL ring pointer")); 134044961713Sgirish return; 134144961713Sgirish } 134244961713Sgirish 134344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hw_kick_channel")); 134444961713Sgirish } 134544961713Sgirish 134644961713Sgirish /*ARGSUSED*/ 134744961713Sgirish void 134844961713Sgirish nxge_check_tx_hang(p_nxge_t nxgep) 134944961713Sgirish { 135044961713Sgirish 135144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_check_tx_hang")); 135244961713Sgirish 135344961713Sgirish /* 135444961713Sgirish * Needs inputs from hardware for regs: 135544961713Sgirish * head index had not moved since last timeout. 135644961713Sgirish * packets not transmitted or stuffed registers. 135744961713Sgirish */ 135844961713Sgirish if (nxge_txdma_hung(nxgep)) { 135944961713Sgirish nxge_fixup_hung_txdma_rings(nxgep); 136044961713Sgirish } 136144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_check_tx_hang")); 136244961713Sgirish } 136344961713Sgirish 136444961713Sgirish int 136544961713Sgirish nxge_txdma_hung(p_nxge_t nxgep) 136644961713Sgirish { 136744961713Sgirish int index, ndmas; 136844961713Sgirish uint16_t channel; 136944961713Sgirish p_tx_rings_t tx_rings; 137044961713Sgirish p_tx_ring_t tx_ring_p; 137144961713Sgirish 137244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_hung")); 137344961713Sgirish tx_rings = nxgep->tx_rings; 137444961713Sgirish if (tx_rings == NULL) { 137544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 137644961713Sgirish "<== nxge_txdma_hung: NULL ring pointer")); 137744961713Sgirish return (B_FALSE); 137844961713Sgirish } 137944961713Sgirish 138044961713Sgirish ndmas = tx_rings->ndmas; 138144961713Sgirish if (!ndmas) { 138244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 138344961713Sgirish "<== nxge_txdma_hung: no channel " 138444961713Sgirish "allocated")); 138544961713Sgirish return (B_FALSE); 138644961713Sgirish } 138744961713Sgirish 138844961713Sgirish if (tx_rings->rings == NULL) { 138944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 139044961713Sgirish "<== nxge_txdma_hung: NULL rings pointer")); 139144961713Sgirish return (B_FALSE); 139244961713Sgirish } 139344961713Sgirish 139444961713Sgirish for (index = 0; index < ndmas; index++) { 139544961713Sgirish channel = tx_rings->rings[index]->tdc; 139644961713Sgirish tx_ring_p = tx_rings->rings[index]; 139744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 139844961713Sgirish "==> nxge_txdma_hung: channel %d", channel)); 139944961713Sgirish if (nxge_txdma_channel_hung(nxgep, tx_ring_p, channel)) { 140044961713Sgirish return (B_TRUE); 140144961713Sgirish } 140244961713Sgirish } 140344961713Sgirish 140444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_hung")); 140544961713Sgirish 140644961713Sgirish return (B_FALSE); 140744961713Sgirish } 140844961713Sgirish 140944961713Sgirish int 141044961713Sgirish nxge_txdma_channel_hung(p_nxge_t nxgep, p_tx_ring_t tx_ring_p, uint16_t channel) 141144961713Sgirish { 141244961713Sgirish uint16_t head_index, tail_index; 141344961713Sgirish boolean_t head_wrap, tail_wrap; 141444961713Sgirish npi_handle_t handle; 141544961713Sgirish tx_ring_hdl_t tx_head; 141644961713Sgirish uint_t tx_rd_index; 141744961713Sgirish 141844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_channel_hung")); 141944961713Sgirish 142044961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 142144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 142244961713Sgirish "==> nxge_txdma_channel_hung: channel %d", channel)); 142344961713Sgirish MUTEX_ENTER(&tx_ring_p->lock); 142444961713Sgirish (void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0); 142544961713Sgirish 142644961713Sgirish tail_index = tx_ring_p->wr_index; 142744961713Sgirish tail_wrap = tx_ring_p->wr_index_wrap; 142844961713Sgirish tx_rd_index = tx_ring_p->rd_index; 142944961713Sgirish MUTEX_EXIT(&tx_ring_p->lock); 143044961713Sgirish 143144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 143244961713Sgirish "==> nxge_txdma_channel_hung: tdc %d tx_rd_index %d " 143344961713Sgirish "tail_index %d tail_wrap %d ", 143444961713Sgirish channel, tx_rd_index, tail_index, tail_wrap)); 143544961713Sgirish /* 143644961713Sgirish * Read the hardware maintained transmit head 143744961713Sgirish * and wrap around bit. 143844961713Sgirish */ 143944961713Sgirish (void) npi_txdma_ring_head_get(handle, channel, &tx_head); 144044961713Sgirish head_index = tx_head.bits.ldw.head; 144144961713Sgirish head_wrap = tx_head.bits.ldw.wrap; 144244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 144344961713Sgirish "==> nxge_txdma_channel_hung: " 144444961713Sgirish "tx_rd_index %d tail %d tail_wrap %d " 144544961713Sgirish "head %d wrap %d", 144644961713Sgirish tx_rd_index, tail_index, tail_wrap, 144744961713Sgirish head_index, head_wrap)); 144844961713Sgirish 144944961713Sgirish if (TXDMA_RING_EMPTY(head_index, head_wrap, 145044961713Sgirish tail_index, tail_wrap) && 145144961713Sgirish (head_index == tx_rd_index)) { 145244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 145344961713Sgirish "==> nxge_txdma_channel_hung: EMPTY")); 145444961713Sgirish return (B_FALSE); 145544961713Sgirish } 145644961713Sgirish 145744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 145844961713Sgirish "==> nxge_txdma_channel_hung: Checking if ring full")); 145944961713Sgirish if (TXDMA_RING_FULL(head_index, head_wrap, tail_index, 146044961713Sgirish tail_wrap)) { 146144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 146244961713Sgirish "==> nxge_txdma_channel_hung: full")); 146344961713Sgirish return (B_TRUE); 146444961713Sgirish } 146544961713Sgirish 146644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_channel_hung")); 146744961713Sgirish 146844961713Sgirish return (B_FALSE); 146944961713Sgirish } 147044961713Sgirish 147144961713Sgirish /*ARGSUSED*/ 147244961713Sgirish void 147344961713Sgirish nxge_fixup_hung_txdma_rings(p_nxge_t nxgep) 147444961713Sgirish { 147544961713Sgirish int index, ndmas; 147644961713Sgirish uint16_t channel; 147744961713Sgirish p_tx_rings_t tx_rings; 147844961713Sgirish 147944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_fixup_hung_txdma_rings")); 148044961713Sgirish tx_rings = nxgep->tx_rings; 148144961713Sgirish if (tx_rings == NULL) { 148244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 148344961713Sgirish "<== nxge_fixup_hung_txdma_rings: NULL ring pointer")); 148444961713Sgirish return; 148544961713Sgirish } 148644961713Sgirish 148744961713Sgirish ndmas = tx_rings->ndmas; 148844961713Sgirish if (!ndmas) { 148944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 149044961713Sgirish "<== nxge_fixup_hung_txdma_rings: no channel " 149144961713Sgirish "allocated")); 149244961713Sgirish return; 149344961713Sgirish } 149444961713Sgirish 149544961713Sgirish if (tx_rings->rings == NULL) { 149644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 149744961713Sgirish "<== nxge_fixup_hung_txdma_rings: NULL rings pointer")); 149844961713Sgirish return; 149944961713Sgirish } 150044961713Sgirish 150144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_fixup_hung_txdma_rings: " 150244961713Sgirish "tx_rings $%p tx_desc_rings $%p ndmas %d", 150344961713Sgirish tx_rings, tx_rings->rings, ndmas)); 150444961713Sgirish 150544961713Sgirish for (index = 0; index < ndmas; index++) { 150644961713Sgirish channel = tx_rings->rings[index]->tdc; 150744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 150844961713Sgirish "==> nxge_fixup_hung_txdma_rings: channel %d", 150944961713Sgirish channel)); 151044961713Sgirish 151144961713Sgirish nxge_txdma_fixup_hung_channel(nxgep, tx_rings->rings[index], 151244961713Sgirish channel); 151344961713Sgirish } 151444961713Sgirish 151544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_fixup_hung_txdma_rings")); 151644961713Sgirish } 151744961713Sgirish 151844961713Sgirish /*ARGSUSED*/ 151944961713Sgirish void 152044961713Sgirish nxge_txdma_fix_hung_channel(p_nxge_t nxgep, uint16_t channel) 152144961713Sgirish { 152244961713Sgirish p_tx_ring_t ring_p; 152344961713Sgirish 152444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fix_hung_channel")); 152544961713Sgirish ring_p = nxge_txdma_get_ring(nxgep, channel); 152644961713Sgirish if (ring_p == NULL) { 152744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 152844961713Sgirish "<== nxge_txdma_fix_hung_channel")); 152944961713Sgirish return; 153044961713Sgirish } 153144961713Sgirish 153244961713Sgirish if (ring_p->tdc != channel) { 153344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 153444961713Sgirish "<== nxge_txdma_fix_hung_channel: channel not matched " 153544961713Sgirish "ring tdc %d passed channel", 153644961713Sgirish ring_p->tdc, channel)); 153744961713Sgirish return; 153844961713Sgirish } 153944961713Sgirish 154044961713Sgirish nxge_txdma_fixup_channel(nxgep, ring_p, channel); 154144961713Sgirish 154244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fix_hung_channel")); 154344961713Sgirish } 154444961713Sgirish 154544961713Sgirish /*ARGSUSED*/ 154644961713Sgirish void 154744961713Sgirish nxge_txdma_fixup_hung_channel(p_nxge_t nxgep, p_tx_ring_t ring_p, 154844961713Sgirish uint16_t channel) 154944961713Sgirish { 155044961713Sgirish npi_handle_t handle; 155144961713Sgirish tdmc_intr_dbg_t intr_dbg; 155244961713Sgirish int status = NXGE_OK; 155344961713Sgirish 155444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fixup_hung_channel")); 155544961713Sgirish 155644961713Sgirish if (ring_p == NULL) { 155744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 155844961713Sgirish "<== nxge_txdma_fixup_channel: NULL ring pointer")); 155944961713Sgirish return; 156044961713Sgirish } 156144961713Sgirish 156244961713Sgirish if (ring_p->tdc != channel) { 156344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 156444961713Sgirish "<== nxge_txdma_fixup_hung_channel: channel " 156544961713Sgirish "not matched " 156644961713Sgirish "ring tdc %d passed channel", 156744961713Sgirish ring_p->tdc, channel)); 156844961713Sgirish return; 156944961713Sgirish } 157044961713Sgirish 157144961713Sgirish /* Reclaim descriptors */ 157244961713Sgirish MUTEX_ENTER(&ring_p->lock); 157344961713Sgirish (void) nxge_txdma_reclaim(nxgep, ring_p, 0); 157444961713Sgirish MUTEX_EXIT(&ring_p->lock); 157544961713Sgirish 157644961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 157744961713Sgirish /* 157844961713Sgirish * Stop the dma channel waits for the stop done. 157944961713Sgirish * If the stop done bit is not set, then force 158044961713Sgirish * an error. 158144961713Sgirish */ 158244961713Sgirish status = npi_txdma_channel_disable(handle, channel); 158344961713Sgirish if (!(status & NPI_TXDMA_STOP_FAILED)) { 158444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 158544961713Sgirish "<== nxge_txdma_fixup_hung_channel: stopped OK " 158644961713Sgirish "ring tdc %d passed channel %d", 158744961713Sgirish ring_p->tdc, channel)); 158844961713Sgirish return; 158944961713Sgirish } 159044961713Sgirish 159144961713Sgirish /* Inject any error */ 159244961713Sgirish intr_dbg.value = 0; 159344961713Sgirish intr_dbg.bits.ldw.nack_pref = 1; 159444961713Sgirish (void) npi_txdma_inj_int_error_set(handle, channel, &intr_dbg); 159544961713Sgirish 159644961713Sgirish /* Stop done bit will be set as a result of error injection */ 159744961713Sgirish status = npi_txdma_channel_disable(handle, channel); 159844961713Sgirish if (!(status & NPI_TXDMA_STOP_FAILED)) { 159944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 160044961713Sgirish "<== nxge_txdma_fixup_hung_channel: stopped again" 160144961713Sgirish "ring tdc %d passed channel", 160244961713Sgirish ring_p->tdc, channel)); 160344961713Sgirish return; 160444961713Sgirish } 160544961713Sgirish 160644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 160744961713Sgirish "<== nxge_txdma_fixup_hung_channel: stop done still not set!! " 160844961713Sgirish "ring tdc %d passed channel", 160944961713Sgirish ring_p->tdc, channel)); 161044961713Sgirish 161144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fixup_hung_channel")); 161244961713Sgirish } 161344961713Sgirish 161444961713Sgirish /*ARGSUSED*/ 161544961713Sgirish void 161644961713Sgirish nxge_reclaim_rings(p_nxge_t nxgep) 161744961713Sgirish { 161844961713Sgirish int index, ndmas; 161944961713Sgirish uint16_t channel; 162044961713Sgirish p_tx_rings_t tx_rings; 162144961713Sgirish p_tx_ring_t tx_ring_p; 162244961713Sgirish 162344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_reclaim_ring")); 162444961713Sgirish tx_rings = nxgep->tx_rings; 162544961713Sgirish if (tx_rings == NULL) { 162644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 162744961713Sgirish "<== nxge_reclain_rimgs: NULL ring pointer")); 162844961713Sgirish return; 162944961713Sgirish } 163044961713Sgirish 163144961713Sgirish ndmas = tx_rings->ndmas; 163244961713Sgirish if (!ndmas) { 163344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 163444961713Sgirish "<== nxge_reclain_rimgs: no channel " 163544961713Sgirish "allocated")); 163644961713Sgirish return; 163744961713Sgirish } 163844961713Sgirish 163944961713Sgirish if (tx_rings->rings == NULL) { 164044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 164144961713Sgirish "<== nxge_reclain_rimgs: NULL rings pointer")); 164244961713Sgirish return; 164344961713Sgirish } 164444961713Sgirish 164544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_reclain_rimgs: " 164644961713Sgirish "tx_rings $%p tx_desc_rings $%p ndmas %d", 164744961713Sgirish tx_rings, tx_rings->rings, ndmas)); 164844961713Sgirish 164944961713Sgirish for (index = 0; index < ndmas; index++) { 165044961713Sgirish channel = tx_rings->rings[index]->tdc; 165144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 165244961713Sgirish "==> reclain_rimgs: channel %d", 165344961713Sgirish channel)); 165444961713Sgirish tx_ring_p = tx_rings->rings[index]; 165544961713Sgirish MUTEX_ENTER(&tx_ring_p->lock); 165644961713Sgirish (void) nxge_txdma_reclaim(nxgep, tx_ring_p, channel); 165744961713Sgirish MUTEX_EXIT(&tx_ring_p->lock); 165844961713Sgirish } 165944961713Sgirish 166044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_reclaim_rings")); 166144961713Sgirish } 166244961713Sgirish 166344961713Sgirish void 166444961713Sgirish nxge_txdma_regs_dump_channels(p_nxge_t nxgep) 166544961713Sgirish { 166644961713Sgirish int index, ndmas; 166744961713Sgirish uint16_t channel; 166844961713Sgirish p_tx_rings_t tx_rings; 166944961713Sgirish npi_handle_t handle; 167044961713Sgirish 167144961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_txdma_regs_dump_channels")); 167244961713Sgirish 167344961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 167444961713Sgirish (void) npi_txdma_dump_fzc_regs(handle); 167544961713Sgirish 167644961713Sgirish tx_rings = nxgep->tx_rings; 167744961713Sgirish if (tx_rings == NULL) { 167844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 167944961713Sgirish "<== nxge_txdma_regs_dump_channels: NULL ring")); 168044961713Sgirish return; 168144961713Sgirish } 168244961713Sgirish 168344961713Sgirish ndmas = tx_rings->ndmas; 168444961713Sgirish if (!ndmas) { 168544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 168644961713Sgirish "<== nxge_txdma_regs_dump_channels: " 168744961713Sgirish "no channel allocated")); 168844961713Sgirish return; 168944961713Sgirish } 169044961713Sgirish 169144961713Sgirish if (tx_rings->rings == NULL) { 169244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 169344961713Sgirish "<== nxge_txdma_regs_dump_channels: NULL rings")); 169444961713Sgirish return; 169544961713Sgirish } 169644961713Sgirish 169744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_regs_dump_channels: " 169844961713Sgirish "tx_rings $%p tx_desc_rings $%p ndmas %d", 169944961713Sgirish tx_rings, tx_rings->rings, ndmas)); 170044961713Sgirish 170144961713Sgirish for (index = 0; index < ndmas; index++) { 170244961713Sgirish channel = tx_rings->rings[index]->tdc; 170344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 170444961713Sgirish "==> nxge_txdma_regs_dump_channels: channel %d", 170544961713Sgirish channel)); 170644961713Sgirish (void) npi_txdma_dump_tdc_regs(handle, channel); 170744961713Sgirish } 170844961713Sgirish 170944961713Sgirish /* Dump TXC registers */ 171044961713Sgirish (void) npi_txc_dump_fzc_regs(handle); 171144961713Sgirish (void) npi_txc_dump_port_fzc_regs(handle, nxgep->function_num); 171244961713Sgirish 171344961713Sgirish for (index = 0; index < ndmas; index++) { 171444961713Sgirish channel = tx_rings->rings[index]->tdc; 171544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 171644961713Sgirish "==> nxge_txdma_regs_dump_channels: channel %d", 171744961713Sgirish channel)); 171844961713Sgirish (void) npi_txc_dump_tdc_fzc_regs(handle, channel); 171944961713Sgirish } 172044961713Sgirish 172144961713Sgirish for (index = 0; index < ndmas; index++) { 172244961713Sgirish channel = tx_rings->rings[index]->tdc; 172344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 172444961713Sgirish "==> nxge_txdma_regs_dump_channels: channel %d", 172544961713Sgirish channel)); 172644961713Sgirish nxge_txdma_regs_dump(nxgep, channel); 172744961713Sgirish } 172844961713Sgirish 172944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_regs_dump")); 173044961713Sgirish 173144961713Sgirish } 173244961713Sgirish 173344961713Sgirish void 173444961713Sgirish nxge_txdma_regs_dump(p_nxge_t nxgep, int channel) 173544961713Sgirish { 173644961713Sgirish npi_handle_t handle; 173744961713Sgirish tx_ring_hdl_t hdl; 173844961713Sgirish tx_ring_kick_t kick; 173944961713Sgirish tx_cs_t cs; 174044961713Sgirish txc_control_t control; 174144961713Sgirish uint32_t bitmap = 0; 174244961713Sgirish uint32_t burst = 0; 174344961713Sgirish uint32_t bytes = 0; 174444961713Sgirish dma_log_page_t cfg; 174544961713Sgirish 174644961713Sgirish printf("\n\tfunc # %d tdc %d ", 174744961713Sgirish nxgep->function_num, channel); 174844961713Sgirish cfg.page_num = 0; 174944961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 175044961713Sgirish (void) npi_txdma_log_page_get(handle, channel, &cfg); 175144961713Sgirish printf("\n\tlog page func %d valid page 0 %d", 175244961713Sgirish cfg.func_num, cfg.valid); 175344961713Sgirish cfg.page_num = 1; 175444961713Sgirish (void) npi_txdma_log_page_get(handle, channel, &cfg); 175544961713Sgirish printf("\n\tlog page func %d valid page 1 %d", 175644961713Sgirish cfg.func_num, cfg.valid); 175744961713Sgirish 175844961713Sgirish (void) npi_txdma_ring_head_get(handle, channel, &hdl); 175944961713Sgirish (void) npi_txdma_desc_kick_reg_get(handle, channel, &kick); 176044961713Sgirish printf("\n\thead value is 0x%0llx", 176144961713Sgirish (long long)hdl.value); 176244961713Sgirish printf("\n\thead index %d", hdl.bits.ldw.head); 176344961713Sgirish printf("\n\tkick value is 0x%0llx", 176444961713Sgirish (long long)kick.value); 176544961713Sgirish printf("\n\ttail index %d\n", kick.bits.ldw.tail); 176644961713Sgirish 176744961713Sgirish (void) npi_txdma_control_status(handle, OP_GET, channel, &cs); 176844961713Sgirish printf("\n\tControl statue is 0x%0llx", (long long)cs.value); 176944961713Sgirish printf("\n\tControl status RST state %d", cs.bits.ldw.rst); 177044961713Sgirish 177144961713Sgirish (void) npi_txc_control(handle, OP_GET, &control); 177244961713Sgirish (void) npi_txc_port_dma_list_get(handle, nxgep->function_num, &bitmap); 177344961713Sgirish (void) npi_txc_dma_max_burst(handle, OP_GET, channel, &burst); 177444961713Sgirish (void) npi_txc_dma_bytes_transmitted(handle, channel, &bytes); 177544961713Sgirish 177644961713Sgirish printf("\n\tTXC port control 0x%0llx", 177744961713Sgirish (long long)control.value); 177844961713Sgirish printf("\n\tTXC port bitmap 0x%x", bitmap); 177944961713Sgirish printf("\n\tTXC max burst %d", burst); 178044961713Sgirish printf("\n\tTXC bytes xmt %d\n", bytes); 178144961713Sgirish 178244961713Sgirish { 178344961713Sgirish ipp_status_t status; 178444961713Sgirish 178544961713Sgirish (void) npi_ipp_get_status(handle, nxgep->function_num, &status); 178644961713Sgirish printf("\n\tIPP status 0x%lux\n", (uint64_t)status.value); 178744961713Sgirish } 178844961713Sgirish } 178944961713Sgirish 179044961713Sgirish /* 179144961713Sgirish * Static functions start here. 179244961713Sgirish */ 179344961713Sgirish static nxge_status_t 179444961713Sgirish nxge_map_txdma(p_nxge_t nxgep) 179544961713Sgirish { 179644961713Sgirish int i, ndmas; 179744961713Sgirish uint16_t channel; 179844961713Sgirish p_tx_rings_t tx_rings; 179944961713Sgirish p_tx_ring_t *tx_desc_rings; 180044961713Sgirish p_tx_mbox_areas_t tx_mbox_areas_p; 180144961713Sgirish p_tx_mbox_t *tx_mbox_p; 180244961713Sgirish p_nxge_dma_pool_t dma_buf_poolp; 180344961713Sgirish p_nxge_dma_pool_t dma_cntl_poolp; 180444961713Sgirish p_nxge_dma_common_t *dma_buf_p; 180544961713Sgirish p_nxge_dma_common_t *dma_cntl_p; 180644961713Sgirish nxge_status_t status = NXGE_OK; 180744961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 180844961713Sgirish p_nxge_dma_common_t t_dma_buf_p; 180944961713Sgirish p_nxge_dma_common_t t_dma_cntl_p; 181044961713Sgirish #endif 181144961713Sgirish 181244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma")); 181344961713Sgirish 181444961713Sgirish dma_buf_poolp = nxgep->tx_buf_pool_p; 181544961713Sgirish dma_cntl_poolp = nxgep->tx_cntl_pool_p; 181644961713Sgirish 181744961713Sgirish if (!dma_buf_poolp->buf_allocated || !dma_cntl_poolp->buf_allocated) { 181844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 181944961713Sgirish "==> nxge_map_txdma: buf not allocated")); 182044961713Sgirish return (NXGE_ERROR); 182144961713Sgirish } 182244961713Sgirish 182344961713Sgirish ndmas = dma_buf_poolp->ndmas; 182444961713Sgirish if (!ndmas) { 182544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 182644961713Sgirish "<== nxge_map_txdma: no dma allocated")); 182744961713Sgirish return (NXGE_ERROR); 182844961713Sgirish } 182944961713Sgirish 183044961713Sgirish dma_buf_p = dma_buf_poolp->dma_buf_pool_p; 183144961713Sgirish dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p; 183244961713Sgirish 183344961713Sgirish tx_rings = (p_tx_rings_t) 183444961713Sgirish KMEM_ZALLOC(sizeof (tx_rings_t), KM_SLEEP); 183544961713Sgirish tx_desc_rings = (p_tx_ring_t *)KMEM_ZALLOC( 183644961713Sgirish sizeof (p_tx_ring_t) * ndmas, KM_SLEEP); 183744961713Sgirish 183844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma: " 183944961713Sgirish "tx_rings $%p tx_desc_rings $%p", 184044961713Sgirish tx_rings, tx_desc_rings)); 184144961713Sgirish 184244961713Sgirish tx_mbox_areas_p = (p_tx_mbox_areas_t) 184344961713Sgirish KMEM_ZALLOC(sizeof (tx_mbox_areas_t), KM_SLEEP); 184444961713Sgirish tx_mbox_p = (p_tx_mbox_t *)KMEM_ZALLOC( 184544961713Sgirish sizeof (p_tx_mbox_t) * ndmas, KM_SLEEP); 184644961713Sgirish 184744961713Sgirish /* 184844961713Sgirish * Map descriptors from the buffer pools for each dma channel. 184944961713Sgirish */ 185044961713Sgirish for (i = 0; i < ndmas; i++) { 185144961713Sgirish /* 185244961713Sgirish * Set up and prepare buffer blocks, descriptors 185344961713Sgirish * and mailbox. 185444961713Sgirish */ 185544961713Sgirish channel = ((p_nxge_dma_common_t)dma_buf_p[i])->dma_channel; 185644961713Sgirish status = nxge_map_txdma_channel(nxgep, channel, 185744961713Sgirish (p_nxge_dma_common_t *)&dma_buf_p[i], 185844961713Sgirish (p_tx_ring_t *)&tx_desc_rings[i], 185944961713Sgirish dma_buf_poolp->num_chunks[i], 186044961713Sgirish (p_nxge_dma_common_t *)&dma_cntl_p[i], 186144961713Sgirish (p_tx_mbox_t *)&tx_mbox_p[i]); 186244961713Sgirish if (status != NXGE_OK) { 186344961713Sgirish goto nxge_map_txdma_fail1; 186444961713Sgirish } 186544961713Sgirish tx_desc_rings[i]->index = (uint16_t)i; 186644961713Sgirish tx_desc_rings[i]->tdc_stats = &nxgep->statsp->tdc_stats[i]; 186744961713Sgirish 186844961713Sgirish #if defined(sun4v) && defined(NIU_LP_WORKAROUND) 186944961713Sgirish if (nxgep->niu_type == N2_NIU && NXGE_DMA_BLOCK == 1) { 187044961713Sgirish tx_desc_rings[i]->hv_set = B_FALSE; 187144961713Sgirish t_dma_buf_p = (p_nxge_dma_common_t)dma_buf_p[i]; 187244961713Sgirish t_dma_cntl_p = (p_nxge_dma_common_t)dma_cntl_p[i]; 187344961713Sgirish 187444961713Sgirish tx_desc_rings[i]->hv_tx_buf_base_ioaddr_pp = 187544961713Sgirish (uint64_t)t_dma_buf_p->orig_ioaddr_pp; 187644961713Sgirish tx_desc_rings[i]->hv_tx_buf_ioaddr_size = 187744961713Sgirish (uint64_t)t_dma_buf_p->orig_alength; 187844961713Sgirish 187944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 188044961713Sgirish "==> nxge_map_txdma_channel: " 188144961713Sgirish "hv data buf base io $%p " 188244961713Sgirish "size 0x%llx (%d) " 188344961713Sgirish "buf base io $%p " 188444961713Sgirish "orig vatopa base io $%p " 188544961713Sgirish "orig_len 0x%llx (%d)", 188644961713Sgirish tx_desc_rings[i]->hv_tx_buf_base_ioaddr_pp, 188744961713Sgirish tx_desc_rings[i]->hv_tx_buf_ioaddr_size, 188844961713Sgirish tx_desc_rings[i]->hv_tx_buf_ioaddr_size, 188944961713Sgirish t_dma_buf_p->ioaddr_pp, 189044961713Sgirish t_dma_buf_p->orig_vatopa, 189144961713Sgirish t_dma_buf_p->orig_alength, 189244961713Sgirish t_dma_buf_p->orig_alength)); 189344961713Sgirish 189444961713Sgirish tx_desc_rings[i]->hv_tx_cntl_base_ioaddr_pp = 189544961713Sgirish (uint64_t)t_dma_cntl_p->orig_ioaddr_pp; 189644961713Sgirish tx_desc_rings[i]->hv_tx_cntl_ioaddr_size = 189744961713Sgirish (uint64_t)t_dma_cntl_p->orig_alength; 189844961713Sgirish 189944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 190044961713Sgirish "==> nxge_map_txdma_channel: " 190144961713Sgirish "hv cntl base io $%p " 190244961713Sgirish "orig ioaddr_pp ($%p) " 190344961713Sgirish "orig vatopa ($%p) " 190444961713Sgirish "size 0x%llx (%d 0x%x)", 190544961713Sgirish tx_desc_rings[i]->hv_tx_cntl_base_ioaddr_pp, 190644961713Sgirish t_dma_cntl_p->orig_ioaddr_pp, 190744961713Sgirish t_dma_cntl_p->orig_vatopa, 190844961713Sgirish tx_desc_rings[i]->hv_tx_cntl_ioaddr_size, 190944961713Sgirish t_dma_cntl_p->orig_alength, 191044961713Sgirish t_dma_cntl_p->orig_alength)); 191144961713Sgirish } 191244961713Sgirish #endif 191344961713Sgirish } 191444961713Sgirish 191544961713Sgirish tx_rings->ndmas = ndmas; 191644961713Sgirish tx_rings->rings = tx_desc_rings; 191744961713Sgirish nxgep->tx_rings = tx_rings; 191844961713Sgirish tx_mbox_areas_p->txmbox_areas_p = tx_mbox_p; 191944961713Sgirish nxgep->tx_mbox_areas_p = tx_mbox_areas_p; 192044961713Sgirish 192144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma: " 192244961713Sgirish "tx_rings $%p rings $%p", 192344961713Sgirish nxgep->tx_rings, nxgep->tx_rings->rings)); 192444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma: " 192544961713Sgirish "tx_rings $%p tx_desc_rings $%p", 192644961713Sgirish nxgep->tx_rings, tx_desc_rings)); 192744961713Sgirish 192844961713Sgirish goto nxge_map_txdma_exit; 192944961713Sgirish 193044961713Sgirish nxge_map_txdma_fail1: 193144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 193244961713Sgirish "==> nxge_map_txdma: uninit tx desc " 193344961713Sgirish "(status 0x%x channel %d i %d)", 193444961713Sgirish nxgep, status, channel, i)); 193544961713Sgirish i--; 193644961713Sgirish for (; i >= 0; i--) { 193744961713Sgirish channel = ((p_nxge_dma_common_t)dma_buf_p[i])->dma_channel; 193844961713Sgirish nxge_unmap_txdma_channel(nxgep, channel, 193944961713Sgirish tx_desc_rings[i], 194044961713Sgirish tx_mbox_p[i]); 194144961713Sgirish } 194244961713Sgirish 194344961713Sgirish KMEM_FREE(tx_desc_rings, sizeof (p_tx_ring_t) * ndmas); 194444961713Sgirish KMEM_FREE(tx_rings, sizeof (tx_rings_t)); 194544961713Sgirish KMEM_FREE(tx_mbox_p, sizeof (p_tx_mbox_t) * ndmas); 194644961713Sgirish KMEM_FREE(tx_mbox_areas_p, sizeof (tx_mbox_areas_t)); 194744961713Sgirish 194844961713Sgirish nxge_map_txdma_exit: 194944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 195044961713Sgirish "==> nxge_map_txdma: " 195144961713Sgirish "(status 0x%x channel %d)", 195244961713Sgirish status, channel)); 195344961713Sgirish 195444961713Sgirish return (status); 195544961713Sgirish } 195644961713Sgirish 195744961713Sgirish static void 195844961713Sgirish nxge_unmap_txdma(p_nxge_t nxgep) 195944961713Sgirish { 196044961713Sgirish int i, ndmas; 196144961713Sgirish uint8_t channel; 196244961713Sgirish p_tx_rings_t tx_rings; 196344961713Sgirish p_tx_ring_t *tx_desc_rings; 196444961713Sgirish p_tx_mbox_areas_t tx_mbox_areas_p; 196544961713Sgirish p_tx_mbox_t *tx_mbox_p; 196644961713Sgirish p_nxge_dma_pool_t dma_buf_poolp; 196744961713Sgirish 196844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_unmap_txdma")); 196944961713Sgirish 197044961713Sgirish dma_buf_poolp = nxgep->tx_buf_pool_p; 197144961713Sgirish if (!dma_buf_poolp->buf_allocated) { 197244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 197344961713Sgirish "==> nxge_unmap_txdma: buf not allocated")); 197444961713Sgirish return; 197544961713Sgirish } 197644961713Sgirish 197744961713Sgirish ndmas = dma_buf_poolp->ndmas; 197844961713Sgirish if (!ndmas) { 197944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 198044961713Sgirish "<== nxge_unmap_txdma: no dma allocated")); 198144961713Sgirish return; 198244961713Sgirish } 198344961713Sgirish 198444961713Sgirish tx_rings = nxgep->tx_rings; 198544961713Sgirish tx_desc_rings = tx_rings->rings; 198644961713Sgirish if (tx_rings == NULL) { 198744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 198844961713Sgirish "<== nxge_unmap_txdma: NULL ring pointer")); 198944961713Sgirish return; 199044961713Sgirish } 199144961713Sgirish 199244961713Sgirish tx_desc_rings = tx_rings->rings; 199344961713Sgirish if (tx_desc_rings == NULL) { 199444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 199544961713Sgirish "<== nxge_unmap_txdma: NULL ring pointers")); 199644961713Sgirish return; 199744961713Sgirish } 199844961713Sgirish 199944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_unmap_txdma: " 200044961713Sgirish "tx_rings $%p tx_desc_rings $%p ndmas %d", 200144961713Sgirish tx_rings, tx_desc_rings, ndmas)); 200244961713Sgirish 200344961713Sgirish tx_mbox_areas_p = nxgep->tx_mbox_areas_p; 200444961713Sgirish tx_mbox_p = tx_mbox_areas_p->txmbox_areas_p; 200544961713Sgirish 200644961713Sgirish for (i = 0; i < ndmas; i++) { 200744961713Sgirish channel = tx_desc_rings[i]->tdc; 200844961713Sgirish (void) nxge_unmap_txdma_channel(nxgep, channel, 200944961713Sgirish (p_tx_ring_t)tx_desc_rings[i], 201044961713Sgirish (p_tx_mbox_t)tx_mbox_p[i]); 201144961713Sgirish } 201244961713Sgirish 201344961713Sgirish KMEM_FREE(tx_desc_rings, sizeof (p_tx_ring_t) * ndmas); 201444961713Sgirish KMEM_FREE(tx_rings, sizeof (tx_rings_t)); 201544961713Sgirish KMEM_FREE(tx_mbox_p, sizeof (p_tx_mbox_t) * ndmas); 201644961713Sgirish KMEM_FREE(tx_mbox_areas_p, sizeof (tx_mbox_areas_t)); 201744961713Sgirish 201844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 201944961713Sgirish "<== nxge_unmap_txdma")); 202044961713Sgirish } 202144961713Sgirish 202244961713Sgirish static nxge_status_t 202344961713Sgirish nxge_map_txdma_channel(p_nxge_t nxgep, uint16_t channel, 202444961713Sgirish p_nxge_dma_common_t *dma_buf_p, 202544961713Sgirish p_tx_ring_t *tx_desc_p, 202644961713Sgirish uint32_t num_chunks, 202744961713Sgirish p_nxge_dma_common_t *dma_cntl_p, 202844961713Sgirish p_tx_mbox_t *tx_mbox_p) 202944961713Sgirish { 203044961713Sgirish int status = NXGE_OK; 203144961713Sgirish 203244961713Sgirish /* 203344961713Sgirish * Set up and prepare buffer blocks, descriptors 203444961713Sgirish * and mailbox. 203544961713Sgirish */ 203644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 203744961713Sgirish "==> nxge_map_txdma_channel (channel %d)", channel)); 203844961713Sgirish /* 203944961713Sgirish * Transmit buffer blocks 204044961713Sgirish */ 204144961713Sgirish status = nxge_map_txdma_channel_buf_ring(nxgep, channel, 204244961713Sgirish dma_buf_p, tx_desc_p, num_chunks); 204344961713Sgirish if (status != NXGE_OK) { 204444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 204544961713Sgirish "==> nxge_map_txdma_channel (channel %d): " 204644961713Sgirish "map buffer failed 0x%x", channel, status)); 204744961713Sgirish goto nxge_map_txdma_channel_exit; 204844961713Sgirish } 204944961713Sgirish 205044961713Sgirish /* 205144961713Sgirish * Transmit block ring, and mailbox. 205244961713Sgirish */ 205344961713Sgirish nxge_map_txdma_channel_cfg_ring(nxgep, channel, dma_cntl_p, *tx_desc_p, 205444961713Sgirish tx_mbox_p); 205544961713Sgirish 205644961713Sgirish goto nxge_map_txdma_channel_exit; 205744961713Sgirish 205844961713Sgirish nxge_map_txdma_channel_fail1: 205944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 206044961713Sgirish "==> nxge_map_txdma_channel: unmap buf" 206144961713Sgirish "(status 0x%x channel %d)", 206244961713Sgirish status, channel)); 206344961713Sgirish nxge_unmap_txdma_channel_buf_ring(nxgep, *tx_desc_p); 206444961713Sgirish 206544961713Sgirish nxge_map_txdma_channel_exit: 206644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 206744961713Sgirish "<== nxge_map_txdma_channel: " 206844961713Sgirish "(status 0x%x channel %d)", 206944961713Sgirish status, channel)); 207044961713Sgirish 207144961713Sgirish return (status); 207244961713Sgirish } 207344961713Sgirish 207444961713Sgirish /*ARGSUSED*/ 207544961713Sgirish static void 207644961713Sgirish nxge_unmap_txdma_channel(p_nxge_t nxgep, uint16_t channel, 207744961713Sgirish p_tx_ring_t tx_ring_p, 207844961713Sgirish p_tx_mbox_t tx_mbox_p) 207944961713Sgirish { 208044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 208144961713Sgirish "==> nxge_unmap_txdma_channel (channel %d)", channel)); 208244961713Sgirish /* 208344961713Sgirish * unmap tx block ring, and mailbox. 208444961713Sgirish */ 208544961713Sgirish (void) nxge_unmap_txdma_channel_cfg_ring(nxgep, 208644961713Sgirish tx_ring_p, tx_mbox_p); 208744961713Sgirish 208844961713Sgirish /* unmap buffer blocks */ 208944961713Sgirish (void) nxge_unmap_txdma_channel_buf_ring(nxgep, tx_ring_p); 209044961713Sgirish 209144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_unmap_txdma_channel")); 209244961713Sgirish } 209344961713Sgirish 209444961713Sgirish /*ARGSUSED*/ 209544961713Sgirish static void 209644961713Sgirish nxge_map_txdma_channel_cfg_ring(p_nxge_t nxgep, uint16_t dma_channel, 209744961713Sgirish p_nxge_dma_common_t *dma_cntl_p, 209844961713Sgirish p_tx_ring_t tx_ring_p, 209944961713Sgirish p_tx_mbox_t *tx_mbox_p) 210044961713Sgirish { 210144961713Sgirish p_tx_mbox_t mboxp; 210244961713Sgirish p_nxge_dma_common_t cntl_dmap; 210344961713Sgirish p_nxge_dma_common_t dmap; 210444961713Sgirish p_tx_rng_cfig_t tx_ring_cfig_p; 210544961713Sgirish p_tx_ring_kick_t tx_ring_kick_p; 210644961713Sgirish p_tx_cs_t tx_cs_p; 210744961713Sgirish p_tx_dma_ent_msk_t tx_evmask_p; 210844961713Sgirish p_txdma_mbh_t mboxh_p; 210944961713Sgirish p_txdma_mbl_t mboxl_p; 211044961713Sgirish uint64_t tx_desc_len; 211144961713Sgirish 211244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 211344961713Sgirish "==> nxge_map_txdma_channel_cfg_ring")); 211444961713Sgirish 211544961713Sgirish cntl_dmap = *dma_cntl_p; 211644961713Sgirish 211744961713Sgirish dmap = (p_nxge_dma_common_t)&tx_ring_p->tdc_desc; 211844961713Sgirish nxge_setup_dma_common(dmap, cntl_dmap, tx_ring_p->tx_ring_size, 211944961713Sgirish sizeof (tx_desc_t)); 212044961713Sgirish /* 212144961713Sgirish * Zero out transmit ring descriptors. 212244961713Sgirish */ 212344961713Sgirish bzero((caddr_t)dmap->kaddrp, dmap->alength); 212444961713Sgirish tx_ring_cfig_p = &(tx_ring_p->tx_ring_cfig); 212544961713Sgirish tx_ring_kick_p = &(tx_ring_p->tx_ring_kick); 212644961713Sgirish tx_cs_p = &(tx_ring_p->tx_cs); 212744961713Sgirish tx_evmask_p = &(tx_ring_p->tx_evmask); 212844961713Sgirish tx_ring_cfig_p->value = 0; 212944961713Sgirish tx_ring_kick_p->value = 0; 213044961713Sgirish tx_cs_p->value = 0; 213144961713Sgirish tx_evmask_p->value = 0; 213244961713Sgirish 213344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 213444961713Sgirish "==> nxge_map_txdma_channel_cfg_ring: channel %d des $%p", 213544961713Sgirish dma_channel, 213644961713Sgirish dmap->dma_cookie.dmac_laddress)); 213744961713Sgirish 213844961713Sgirish tx_ring_cfig_p->value = 0; 213944961713Sgirish tx_desc_len = (uint64_t)(tx_ring_p->tx_ring_size >> 3); 214044961713Sgirish tx_ring_cfig_p->value = 214144961713Sgirish (dmap->dma_cookie.dmac_laddress & TX_RNG_CFIG_ADDR_MASK) | 214244961713Sgirish (tx_desc_len << TX_RNG_CFIG_LEN_SHIFT); 214344961713Sgirish 214444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 214544961713Sgirish "==> nxge_map_txdma_channel_cfg_ring: channel %d cfg 0x%llx", 214644961713Sgirish dma_channel, 214744961713Sgirish tx_ring_cfig_p->value)); 214844961713Sgirish 214944961713Sgirish tx_cs_p->bits.ldw.rst = 1; 215044961713Sgirish 215144961713Sgirish /* Map in mailbox */ 215244961713Sgirish mboxp = (p_tx_mbox_t) 215344961713Sgirish KMEM_ZALLOC(sizeof (tx_mbox_t), KM_SLEEP); 215444961713Sgirish dmap = (p_nxge_dma_common_t)&mboxp->tx_mbox; 215544961713Sgirish nxge_setup_dma_common(dmap, cntl_dmap, 1, sizeof (txdma_mailbox_t)); 215644961713Sgirish mboxh_p = (p_txdma_mbh_t)&tx_ring_p->tx_mbox_mbh; 215744961713Sgirish mboxl_p = (p_txdma_mbl_t)&tx_ring_p->tx_mbox_mbl; 215844961713Sgirish mboxh_p->value = mboxl_p->value = 0; 215944961713Sgirish 216044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 216144961713Sgirish "==> nxge_map_txdma_channel_cfg_ring: mbox 0x%lx", 216244961713Sgirish dmap->dma_cookie.dmac_laddress)); 216344961713Sgirish 216444961713Sgirish mboxh_p->bits.ldw.mbaddr = ((dmap->dma_cookie.dmac_laddress >> 216544961713Sgirish TXDMA_MBH_ADDR_SHIFT) & TXDMA_MBH_MASK); 216644961713Sgirish 216744961713Sgirish mboxl_p->bits.ldw.mbaddr = ((dmap->dma_cookie.dmac_laddress & 216844961713Sgirish TXDMA_MBL_MASK) >> TXDMA_MBL_SHIFT); 216944961713Sgirish 217044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 217144961713Sgirish "==> nxge_map_txdma_channel_cfg_ring: mbox 0x%lx", 217244961713Sgirish dmap->dma_cookie.dmac_laddress)); 217344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 217444961713Sgirish "==> nxge_map_txdma_channel_cfg_ring: hmbox $%p " 217544961713Sgirish "mbox $%p", 217644961713Sgirish mboxh_p->bits.ldw.mbaddr, mboxl_p->bits.ldw.mbaddr)); 217744961713Sgirish tx_ring_p->page_valid.value = 0; 217844961713Sgirish tx_ring_p->page_mask_1.value = tx_ring_p->page_mask_2.value = 0; 217944961713Sgirish tx_ring_p->page_value_1.value = tx_ring_p->page_value_2.value = 0; 218044961713Sgirish tx_ring_p->page_reloc_1.value = tx_ring_p->page_reloc_2.value = 0; 218144961713Sgirish tx_ring_p->page_hdl.value = 0; 218244961713Sgirish 218344961713Sgirish tx_ring_p->page_valid.bits.ldw.page0 = 1; 218444961713Sgirish tx_ring_p->page_valid.bits.ldw.page1 = 1; 218544961713Sgirish 218644961713Sgirish tx_ring_p->max_burst.value = 0; 218744961713Sgirish tx_ring_p->max_burst.bits.ldw.dma_max_burst = TXC_DMA_MAX_BURST_DEFAULT; 218844961713Sgirish 218944961713Sgirish *tx_mbox_p = mboxp; 219044961713Sgirish 219144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 219244961713Sgirish "<== nxge_map_txdma_channel_cfg_ring")); 219344961713Sgirish } 219444961713Sgirish 219544961713Sgirish /*ARGSUSED*/ 219644961713Sgirish static void 219744961713Sgirish nxge_unmap_txdma_channel_cfg_ring(p_nxge_t nxgep, 219844961713Sgirish p_tx_ring_t tx_ring_p, p_tx_mbox_t tx_mbox_p) 219944961713Sgirish { 220044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 220144961713Sgirish "==> nxge_unmap_txdma_channel_cfg_ring: channel %d", 220244961713Sgirish tx_ring_p->tdc)); 220344961713Sgirish 220444961713Sgirish KMEM_FREE(tx_mbox_p, sizeof (tx_mbox_t)); 220544961713Sgirish 220644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 220744961713Sgirish "<== nxge_unmap_txdma_channel_cfg_ring")); 220844961713Sgirish } 220944961713Sgirish 221044961713Sgirish static nxge_status_t 221144961713Sgirish nxge_map_txdma_channel_buf_ring(p_nxge_t nxgep, uint16_t channel, 221244961713Sgirish p_nxge_dma_common_t *dma_buf_p, 221344961713Sgirish p_tx_ring_t *tx_desc_p, uint32_t num_chunks) 221444961713Sgirish { 221544961713Sgirish p_nxge_dma_common_t dma_bufp, tmp_bufp; 221644961713Sgirish p_nxge_dma_common_t dmap; 221744961713Sgirish nxge_os_dma_handle_t tx_buf_dma_handle; 221844961713Sgirish p_tx_ring_t tx_ring_p; 221944961713Sgirish p_tx_msg_t tx_msg_ring; 222044961713Sgirish nxge_status_t status = NXGE_OK; 222144961713Sgirish int ddi_status = DDI_SUCCESS; 222244961713Sgirish int i, j, index; 222344961713Sgirish uint32_t size, bsize; 222444961713Sgirish uint32_t nblocks, nmsgs; 222544961713Sgirish 222644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 222744961713Sgirish "==> nxge_map_txdma_channel_buf_ring")); 222844961713Sgirish 222944961713Sgirish dma_bufp = tmp_bufp = *dma_buf_p; 223044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 223144961713Sgirish " nxge_map_txdma_channel_buf_ring: channel %d to map %d " 223244961713Sgirish "chunks bufp $%p", 223344961713Sgirish channel, num_chunks, dma_bufp)); 223444961713Sgirish 223544961713Sgirish nmsgs = 0; 223644961713Sgirish for (i = 0; i < num_chunks; i++, tmp_bufp++) { 223744961713Sgirish nmsgs += tmp_bufp->nblocks; 223844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 223944961713Sgirish "==> nxge_map_txdma_channel_buf_ring: channel %d " 224044961713Sgirish "bufp $%p nblocks %d nmsgs %d", 224144961713Sgirish channel, tmp_bufp, tmp_bufp->nblocks, nmsgs)); 224244961713Sgirish } 224344961713Sgirish if (!nmsgs) { 224444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 224544961713Sgirish "<== nxge_map_txdma_channel_buf_ring: channel %d " 224644961713Sgirish "no msg blocks", 224744961713Sgirish channel)); 224844961713Sgirish status = NXGE_ERROR; 224944961713Sgirish goto nxge_map_txdma_channel_buf_ring_exit; 225044961713Sgirish } 225144961713Sgirish 225244961713Sgirish tx_ring_p = (p_tx_ring_t) 225344961713Sgirish KMEM_ZALLOC(sizeof (tx_ring_t), KM_SLEEP); 225444961713Sgirish MUTEX_INIT(&tx_ring_p->lock, NULL, MUTEX_DRIVER, 225544961713Sgirish (void *)nxgep->interrupt_cookie); 22561f8914d5Sml 22571f8914d5Sml tx_ring_p->nxgep = nxgep; 22581f8914d5Sml tx_ring_p->serial = nxge_serialize_create(nmsgs, 22591f8914d5Sml nxge_serial_tx, tx_ring_p); 226044961713Sgirish /* 226144961713Sgirish * Allocate transmit message rings and handles for packets 226244961713Sgirish * not to be copied to premapped buffers. 226344961713Sgirish */ 226444961713Sgirish size = nmsgs * sizeof (tx_msg_t); 226544961713Sgirish tx_msg_ring = KMEM_ZALLOC(size, KM_SLEEP); 226644961713Sgirish for (i = 0; i < nmsgs; i++) { 226744961713Sgirish ddi_status = ddi_dma_alloc_handle(nxgep->dip, &nxge_tx_dma_attr, 226844961713Sgirish DDI_DMA_DONTWAIT, 0, 226944961713Sgirish &tx_msg_ring[i].dma_handle); 227044961713Sgirish if (ddi_status != DDI_SUCCESS) { 227144961713Sgirish status |= NXGE_DDI_FAILED; 227244961713Sgirish break; 227344961713Sgirish } 227444961713Sgirish } 227544961713Sgirish if (i < nmsgs) { 2276*56d930aeSspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2277*56d930aeSspeer "Allocate handles failed.")); 227844961713Sgirish goto nxge_map_txdma_channel_buf_ring_fail1; 227944961713Sgirish } 228044961713Sgirish 228144961713Sgirish tx_ring_p->tdc = channel; 228244961713Sgirish tx_ring_p->tx_msg_ring = tx_msg_ring; 228344961713Sgirish tx_ring_p->tx_ring_size = nmsgs; 228444961713Sgirish tx_ring_p->num_chunks = num_chunks; 228544961713Sgirish if (!nxge_tx_intr_thres) { 228644961713Sgirish nxge_tx_intr_thres = tx_ring_p->tx_ring_size/4; 228744961713Sgirish } 228844961713Sgirish tx_ring_p->tx_wrap_mask = tx_ring_p->tx_ring_size - 1; 228944961713Sgirish tx_ring_p->rd_index = 0; 229044961713Sgirish tx_ring_p->wr_index = 0; 229144961713Sgirish tx_ring_p->ring_head.value = 0; 229244961713Sgirish tx_ring_p->ring_kick_tail.value = 0; 229344961713Sgirish tx_ring_p->descs_pending = 0; 229444961713Sgirish 229544961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 229644961713Sgirish "==> nxge_map_txdma_channel_buf_ring: channel %d " 229744961713Sgirish "actual tx desc max %d nmsgs %d " 229844961713Sgirish "(config nxge_tx_ring_size %d)", 229944961713Sgirish channel, tx_ring_p->tx_ring_size, nmsgs, 230044961713Sgirish nxge_tx_ring_size)); 230144961713Sgirish 230244961713Sgirish /* 230344961713Sgirish * Map in buffers from the buffer pool. 230444961713Sgirish */ 230544961713Sgirish index = 0; 230644961713Sgirish bsize = dma_bufp->block_size; 230744961713Sgirish 230844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_map_txdma_channel_buf_ring: " 230944961713Sgirish "dma_bufp $%p tx_rng_p $%p " 231044961713Sgirish "tx_msg_rng_p $%p bsize %d", 231144961713Sgirish dma_bufp, tx_ring_p, tx_msg_ring, bsize)); 231244961713Sgirish 231344961713Sgirish tx_buf_dma_handle = dma_bufp->dma_handle; 231444961713Sgirish for (i = 0; i < num_chunks; i++, dma_bufp++) { 231544961713Sgirish bsize = dma_bufp->block_size; 231644961713Sgirish nblocks = dma_bufp->nblocks; 231744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 231844961713Sgirish "==> nxge_map_txdma_channel_buf_ring: dma chunk %d " 231944961713Sgirish "size %d dma_bufp $%p", 232044961713Sgirish i, sizeof (nxge_dma_common_t), dma_bufp)); 232144961713Sgirish 232244961713Sgirish for (j = 0; j < nblocks; j++) { 232344961713Sgirish tx_msg_ring[index].buf_dma_handle = tx_buf_dma_handle; 232444961713Sgirish dmap = &tx_msg_ring[index++].buf_dma; 232544961713Sgirish #ifdef TX_MEM_DEBUG 232644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 232744961713Sgirish "==> nxge_map_txdma_channel_buf_ring: j %d" 232844961713Sgirish "dmap $%p", i, dmap)); 232944961713Sgirish #endif 233044961713Sgirish nxge_setup_dma_common(dmap, dma_bufp, 1, 233144961713Sgirish bsize); 233244961713Sgirish } 233344961713Sgirish } 233444961713Sgirish 233544961713Sgirish if (i < num_chunks) { 2336*56d930aeSspeer status = NXGE_ERROR; 233744961713Sgirish goto nxge_map_txdma_channel_buf_ring_fail1; 233844961713Sgirish } 233944961713Sgirish 234044961713Sgirish *tx_desc_p = tx_ring_p; 234144961713Sgirish 234244961713Sgirish goto nxge_map_txdma_channel_buf_ring_exit; 234344961713Sgirish 234444961713Sgirish nxge_map_txdma_channel_buf_ring_fail1: 23451f8914d5Sml if (tx_ring_p->serial) { 23461f8914d5Sml nxge_serialize_destroy(tx_ring_p->serial); 23471f8914d5Sml tx_ring_p->serial = NULL; 23481f8914d5Sml } 23491f8914d5Sml 235044961713Sgirish index--; 235144961713Sgirish for (; index >= 0; index--) { 2352*56d930aeSspeer if (tx_msg_ring[index].dma_handle != NULL) { 2353*56d930aeSspeer ddi_dma_free_handle(&tx_msg_ring[index].dma_handle); 235444961713Sgirish } 235544961713Sgirish } 235644961713Sgirish MUTEX_DESTROY(&tx_ring_p->lock); 2357*56d930aeSspeer KMEM_FREE(tx_msg_ring, size); 235844961713Sgirish KMEM_FREE(tx_ring_p, sizeof (tx_ring_t)); 235944961713Sgirish 2360*56d930aeSspeer status = NXGE_ERROR; 2361*56d930aeSspeer 236244961713Sgirish nxge_map_txdma_channel_buf_ring_exit: 236344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 236444961713Sgirish "<== nxge_map_txdma_channel_buf_ring status 0x%x", status)); 236544961713Sgirish 236644961713Sgirish return (status); 236744961713Sgirish } 236844961713Sgirish 236944961713Sgirish /*ARGSUSED*/ 237044961713Sgirish static void 237144961713Sgirish nxge_unmap_txdma_channel_buf_ring(p_nxge_t nxgep, p_tx_ring_t tx_ring_p) 237244961713Sgirish { 237344961713Sgirish p_tx_msg_t tx_msg_ring; 237444961713Sgirish p_tx_msg_t tx_msg_p; 237544961713Sgirish int i; 237644961713Sgirish 237744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 237844961713Sgirish "==> nxge_unmap_txdma_channel_buf_ring")); 237944961713Sgirish if (tx_ring_p == NULL) { 238044961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 238144961713Sgirish "<== nxge_unmap_txdma_channel_buf_ring: NULL ringp")); 238244961713Sgirish return; 238344961713Sgirish } 238444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 238544961713Sgirish "==> nxge_unmap_txdma_channel_buf_ring: channel %d", 238644961713Sgirish tx_ring_p->tdc)); 238744961713Sgirish 238844961713Sgirish tx_msg_ring = tx_ring_p->tx_msg_ring; 238944961713Sgirish for (i = 0; i < tx_ring_p->tx_ring_size; i++) { 239044961713Sgirish tx_msg_p = &tx_msg_ring[i]; 239144961713Sgirish if (tx_msg_p->flags.dma_type == USE_DVMA) { 239244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 239344961713Sgirish "entry = %d", 239444961713Sgirish i)); 239544961713Sgirish (void) dvma_unload(tx_msg_p->dvma_handle, 239644961713Sgirish 0, -1); 239744961713Sgirish tx_msg_p->dvma_handle = NULL; 239844961713Sgirish if (tx_ring_p->dvma_wr_index == 239944961713Sgirish tx_ring_p->dvma_wrap_mask) { 240044961713Sgirish tx_ring_p->dvma_wr_index = 0; 240144961713Sgirish } else { 240244961713Sgirish tx_ring_p->dvma_wr_index++; 240344961713Sgirish } 240444961713Sgirish tx_ring_p->dvma_pending--; 240544961713Sgirish } else if (tx_msg_p->flags.dma_type == 240644961713Sgirish USE_DMA) { 240744961713Sgirish if (ddi_dma_unbind_handle 240844961713Sgirish (tx_msg_p->dma_handle)) { 240944961713Sgirish cmn_err(CE_WARN, "!nxge_unmap_tx_bug_ring: " 241044961713Sgirish "ddi_dma_unbind_handle " 241144961713Sgirish "failed."); 241244961713Sgirish } 241344961713Sgirish } 241444961713Sgirish 241544961713Sgirish if (tx_msg_p->tx_message != NULL) { 241644961713Sgirish freemsg(tx_msg_p->tx_message); 241744961713Sgirish tx_msg_p->tx_message = NULL; 241844961713Sgirish } 241944961713Sgirish } 242044961713Sgirish 242144961713Sgirish for (i = 0; i < tx_ring_p->tx_ring_size; i++) { 242244961713Sgirish if (tx_msg_ring[i].dma_handle != NULL) { 242344961713Sgirish ddi_dma_free_handle(&tx_msg_ring[i].dma_handle); 242444961713Sgirish } 242544961713Sgirish } 242644961713Sgirish 24271f8914d5Sml if (tx_ring_p->serial) { 24281f8914d5Sml nxge_serialize_destroy(tx_ring_p->serial); 24291f8914d5Sml tx_ring_p->serial = NULL; 24301f8914d5Sml } 24311f8914d5Sml 243244961713Sgirish MUTEX_DESTROY(&tx_ring_p->lock); 243344961713Sgirish KMEM_FREE(tx_msg_ring, sizeof (tx_msg_t) * tx_ring_p->tx_ring_size); 243444961713Sgirish KMEM_FREE(tx_ring_p, sizeof (tx_ring_t)); 243544961713Sgirish 243644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 243744961713Sgirish "<== nxge_unmap_txdma_channel_buf_ring")); 243844961713Sgirish } 243944961713Sgirish 244044961713Sgirish static nxge_status_t 244144961713Sgirish nxge_txdma_hw_start(p_nxge_t nxgep) 244244961713Sgirish { 244344961713Sgirish int i, ndmas; 244444961713Sgirish uint16_t channel; 244544961713Sgirish p_tx_rings_t tx_rings; 244644961713Sgirish p_tx_ring_t *tx_desc_rings; 244744961713Sgirish p_tx_mbox_areas_t tx_mbox_areas_p; 244844961713Sgirish p_tx_mbox_t *tx_mbox_p; 244944961713Sgirish nxge_status_t status = NXGE_OK; 245044961713Sgirish 245144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start")); 245244961713Sgirish 245344961713Sgirish tx_rings = nxgep->tx_rings; 245444961713Sgirish if (tx_rings == NULL) { 245544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 245644961713Sgirish "<== nxge_txdma_hw_start: NULL ring pointer")); 245744961713Sgirish return (NXGE_ERROR); 245844961713Sgirish } 245944961713Sgirish tx_desc_rings = tx_rings->rings; 246044961713Sgirish if (tx_desc_rings == NULL) { 246144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 246244961713Sgirish "<== nxge_txdma_hw_start: NULL ring pointers")); 246344961713Sgirish return (NXGE_ERROR); 246444961713Sgirish } 246544961713Sgirish 246644961713Sgirish ndmas = tx_rings->ndmas; 246744961713Sgirish if (!ndmas) { 246844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 246944961713Sgirish "<== nxge_txdma_hw_start: no dma channel allocated")); 247044961713Sgirish return (NXGE_ERROR); 247144961713Sgirish } 247244961713Sgirish 247344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: " 247444961713Sgirish "tx_rings $%p tx_desc_rings $%p ndmas %d", 247544961713Sgirish tx_rings, tx_desc_rings, ndmas)); 247644961713Sgirish 247744961713Sgirish tx_mbox_areas_p = nxgep->tx_mbox_areas_p; 247844961713Sgirish tx_mbox_p = tx_mbox_areas_p->txmbox_areas_p; 247944961713Sgirish 248044961713Sgirish for (i = 0; i < ndmas; i++) { 248144961713Sgirish channel = tx_desc_rings[i]->tdc, 248244961713Sgirish status = nxge_txdma_start_channel(nxgep, channel, 248344961713Sgirish (p_tx_ring_t)tx_desc_rings[i], 248444961713Sgirish (p_tx_mbox_t)tx_mbox_p[i]); 248544961713Sgirish if (status != NXGE_OK) { 248644961713Sgirish goto nxge_txdma_hw_start_fail1; 248744961713Sgirish } 248844961713Sgirish } 248944961713Sgirish 249044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: " 249144961713Sgirish "tx_rings $%p rings $%p", 249244961713Sgirish nxgep->tx_rings, nxgep->tx_rings->rings)); 249344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_start: " 249444961713Sgirish "tx_rings $%p tx_desc_rings $%p", 249544961713Sgirish nxgep->tx_rings, tx_desc_rings)); 249644961713Sgirish 249744961713Sgirish goto nxge_txdma_hw_start_exit; 249844961713Sgirish 249944961713Sgirish nxge_txdma_hw_start_fail1: 250044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 250144961713Sgirish "==> nxge_txdma_hw_start: disable " 250244961713Sgirish "(status 0x%x channel %d i %d)", status, channel, i)); 250344961713Sgirish for (; i >= 0; i--) { 250444961713Sgirish channel = tx_desc_rings[i]->tdc, 250544961713Sgirish (void) nxge_txdma_stop_channel(nxgep, channel, 250644961713Sgirish (p_tx_ring_t)tx_desc_rings[i], 250744961713Sgirish (p_tx_mbox_t)tx_mbox_p[i]); 250844961713Sgirish } 250944961713Sgirish 251044961713Sgirish nxge_txdma_hw_start_exit: 251144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 251244961713Sgirish "==> nxge_txdma_hw_start: (status 0x%x)", status)); 251344961713Sgirish 251444961713Sgirish return (status); 251544961713Sgirish } 251644961713Sgirish 251744961713Sgirish static void 251844961713Sgirish nxge_txdma_hw_stop(p_nxge_t nxgep) 251944961713Sgirish { 252044961713Sgirish int i, ndmas; 252144961713Sgirish uint16_t channel; 252244961713Sgirish p_tx_rings_t tx_rings; 252344961713Sgirish p_tx_ring_t *tx_desc_rings; 252444961713Sgirish p_tx_mbox_areas_t tx_mbox_areas_p; 252544961713Sgirish p_tx_mbox_t *tx_mbox_p; 252644961713Sgirish 252744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_stop")); 252844961713Sgirish 252944961713Sgirish tx_rings = nxgep->tx_rings; 253044961713Sgirish if (tx_rings == NULL) { 253144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 253244961713Sgirish "<== nxge_txdma_hw_stop: NULL ring pointer")); 253344961713Sgirish return; 253444961713Sgirish } 253544961713Sgirish tx_desc_rings = tx_rings->rings; 253644961713Sgirish if (tx_desc_rings == NULL) { 253744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 253844961713Sgirish "<== nxge_txdma_hw_stop: NULL ring pointers")); 253944961713Sgirish return; 254044961713Sgirish } 254144961713Sgirish 254244961713Sgirish ndmas = tx_rings->ndmas; 254344961713Sgirish if (!ndmas) { 254444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 254544961713Sgirish "<== nxge_txdma_hw_stop: no dma channel allocated")); 254644961713Sgirish return; 254744961713Sgirish } 254844961713Sgirish 254944961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_stop: " 255044961713Sgirish "tx_rings $%p tx_desc_rings $%p", 255144961713Sgirish tx_rings, tx_desc_rings)); 255244961713Sgirish 255344961713Sgirish tx_mbox_areas_p = nxgep->tx_mbox_areas_p; 255444961713Sgirish tx_mbox_p = tx_mbox_areas_p->txmbox_areas_p; 255544961713Sgirish 255644961713Sgirish for (i = 0; i < ndmas; i++) { 255744961713Sgirish channel = tx_desc_rings[i]->tdc; 255844961713Sgirish (void) nxge_txdma_stop_channel(nxgep, channel, 255944961713Sgirish (p_tx_ring_t)tx_desc_rings[i], 256044961713Sgirish (p_tx_mbox_t)tx_mbox_p[i]); 256144961713Sgirish } 256244961713Sgirish 256344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_hw_stop: " 256444961713Sgirish "tx_rings $%p tx_desc_rings $%p", 256544961713Sgirish tx_rings, tx_desc_rings)); 256644961713Sgirish 256744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_txdma_hw_stop")); 256844961713Sgirish } 256944961713Sgirish 257044961713Sgirish static nxge_status_t 257144961713Sgirish nxge_txdma_start_channel(p_nxge_t nxgep, uint16_t channel, 257244961713Sgirish p_tx_ring_t tx_ring_p, p_tx_mbox_t tx_mbox_p) 257344961713Sgirish 257444961713Sgirish { 257544961713Sgirish nxge_status_t status = NXGE_OK; 257644961713Sgirish 257744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 257844961713Sgirish "==> nxge_txdma_start_channel (channel %d)", channel)); 257944961713Sgirish /* 258044961713Sgirish * TXDMA/TXC must be in stopped state. 258144961713Sgirish */ 258244961713Sgirish (void) nxge_txdma_stop_inj_err(nxgep, channel); 258344961713Sgirish 258444961713Sgirish /* 258544961713Sgirish * Reset TXDMA channel 258644961713Sgirish */ 258744961713Sgirish tx_ring_p->tx_cs.value = 0; 258844961713Sgirish tx_ring_p->tx_cs.bits.ldw.rst = 1; 258944961713Sgirish status = nxge_reset_txdma_channel(nxgep, channel, 259044961713Sgirish tx_ring_p->tx_cs.value); 259144961713Sgirish if (status != NXGE_OK) { 259244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 259344961713Sgirish "==> nxge_txdma_start_channel (channel %d)" 259444961713Sgirish " reset channel failed 0x%x", channel, status)); 259544961713Sgirish goto nxge_txdma_start_channel_exit; 259644961713Sgirish } 259744961713Sgirish 259844961713Sgirish /* 259944961713Sgirish * Initialize the TXDMA channel specific FZC control 260044961713Sgirish * configurations. These FZC registers are pertaining 260144961713Sgirish * to each TX channel (i.e. logical pages). 260244961713Sgirish */ 260344961713Sgirish status = nxge_init_fzc_txdma_channel(nxgep, channel, 260444961713Sgirish tx_ring_p, tx_mbox_p); 260544961713Sgirish if (status != NXGE_OK) { 260644961713Sgirish goto nxge_txdma_start_channel_exit; 260744961713Sgirish } 260844961713Sgirish 260944961713Sgirish /* 261044961713Sgirish * Initialize the event masks. 261144961713Sgirish */ 261244961713Sgirish tx_ring_p->tx_evmask.value = 0; 261344961713Sgirish status = nxge_init_txdma_channel_event_mask(nxgep, 261444961713Sgirish channel, &tx_ring_p->tx_evmask); 261544961713Sgirish if (status != NXGE_OK) { 261644961713Sgirish goto nxge_txdma_start_channel_exit; 261744961713Sgirish } 261844961713Sgirish 261944961713Sgirish /* 262044961713Sgirish * Load TXDMA descriptors, buffers, mailbox, 262144961713Sgirish * initialise the DMA channels and 262244961713Sgirish * enable each DMA channel. 262344961713Sgirish */ 262444961713Sgirish status = nxge_enable_txdma_channel(nxgep, channel, 262544961713Sgirish tx_ring_p, tx_mbox_p); 262644961713Sgirish if (status != NXGE_OK) { 262744961713Sgirish goto nxge_txdma_start_channel_exit; 262844961713Sgirish } 262944961713Sgirish 263044961713Sgirish nxge_txdma_start_channel_exit: 263144961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_txdma_start_channel")); 263244961713Sgirish 263344961713Sgirish return (status); 263444961713Sgirish } 263544961713Sgirish 263644961713Sgirish /*ARGSUSED*/ 263744961713Sgirish static nxge_status_t 263844961713Sgirish nxge_txdma_stop_channel(p_nxge_t nxgep, uint16_t channel, 263944961713Sgirish p_tx_ring_t tx_ring_p, p_tx_mbox_t tx_mbox_p) 264044961713Sgirish { 264144961713Sgirish int status = NXGE_OK; 264244961713Sgirish 264344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 264444961713Sgirish "==> nxge_txdma_stop_channel: channel %d", channel)); 264544961713Sgirish 264644961713Sgirish /* 264744961713Sgirish * Stop (disable) TXDMA and TXC (if stop bit is set 264844961713Sgirish * and STOP_N_GO bit not set, the TXDMA reset state will 264944961713Sgirish * not be set if reset TXDMA. 265044961713Sgirish */ 265144961713Sgirish (void) nxge_txdma_stop_inj_err(nxgep, channel); 265244961713Sgirish 265344961713Sgirish /* 265444961713Sgirish * Reset TXDMA channel 265544961713Sgirish */ 265644961713Sgirish tx_ring_p->tx_cs.value = 0; 265744961713Sgirish tx_ring_p->tx_cs.bits.ldw.rst = 1; 265844961713Sgirish status = nxge_reset_txdma_channel(nxgep, channel, 265944961713Sgirish tx_ring_p->tx_cs.value); 266044961713Sgirish if (status != NXGE_OK) { 266144961713Sgirish goto nxge_txdma_stop_channel_exit; 266244961713Sgirish } 266344961713Sgirish 266444961713Sgirish #ifdef HARDWARE_REQUIRED 266544961713Sgirish /* Set up the interrupt event masks. */ 266644961713Sgirish tx_ring_p->tx_evmask.value = 0; 266744961713Sgirish status = nxge_init_txdma_channel_event_mask(nxgep, 266844961713Sgirish channel, &tx_ring_p->tx_evmask); 266944961713Sgirish if (status != NXGE_OK) { 267044961713Sgirish goto nxge_txdma_stop_channel_exit; 267144961713Sgirish } 267244961713Sgirish 267344961713Sgirish /* Initialize the DMA control and status register */ 267444961713Sgirish tx_ring_p->tx_cs.value = TX_ENT_MSK_MK_ALL; 267544961713Sgirish status = nxge_init_txdma_channel_cntl_stat(nxgep, channel, 267644961713Sgirish tx_ring_p->tx_cs.value); 267744961713Sgirish if (status != NXGE_OK) { 267844961713Sgirish goto nxge_txdma_stop_channel_exit; 267944961713Sgirish } 268044961713Sgirish 268144961713Sgirish /* Disable channel */ 268244961713Sgirish status = nxge_disable_txdma_channel(nxgep, channel, 268344961713Sgirish tx_ring_p, tx_mbox_p); 268444961713Sgirish if (status != NXGE_OK) { 268544961713Sgirish goto nxge_txdma_start_channel_exit; 268644961713Sgirish } 268744961713Sgirish 268844961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 268944961713Sgirish "==> nxge_txdma_stop_channel: event done")); 269044961713Sgirish 269144961713Sgirish #endif 269244961713Sgirish 269344961713Sgirish nxge_txdma_stop_channel_exit: 269444961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_txdma_stop_channel")); 269544961713Sgirish return (status); 269644961713Sgirish } 269744961713Sgirish 269844961713Sgirish static p_tx_ring_t 269944961713Sgirish nxge_txdma_get_ring(p_nxge_t nxgep, uint16_t channel) 270044961713Sgirish { 270144961713Sgirish int index, ndmas; 270244961713Sgirish uint16_t tdc; 270344961713Sgirish p_tx_rings_t tx_rings; 270444961713Sgirish 270544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_get_ring")); 270644961713Sgirish 270744961713Sgirish tx_rings = nxgep->tx_rings; 270844961713Sgirish if (tx_rings == NULL) { 270944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 271044961713Sgirish "<== nxge_txdma_get_ring: NULL ring pointer")); 271144961713Sgirish return (NULL); 271244961713Sgirish } 271344961713Sgirish 271444961713Sgirish ndmas = tx_rings->ndmas; 271544961713Sgirish if (!ndmas) { 271644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 271744961713Sgirish "<== nxge_txdma_get_ring: no channel allocated")); 271844961713Sgirish return (NULL); 271944961713Sgirish } 272044961713Sgirish 272144961713Sgirish if (tx_rings->rings == NULL) { 272244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 272344961713Sgirish "<== nxge_txdma_get_ring: NULL rings pointer")); 272444961713Sgirish return (NULL); 272544961713Sgirish } 272644961713Sgirish 272744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_get_ring: " 272844961713Sgirish "tx_rings $%p tx_desc_rings $%p ndmas %d", 272944961713Sgirish tx_rings, tx_rings, ndmas)); 273044961713Sgirish 273144961713Sgirish for (index = 0; index < ndmas; index++) { 273244961713Sgirish tdc = tx_rings->rings[index]->tdc; 273344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 273444961713Sgirish "==> nxge_fixup_txdma_rings: channel %d", tdc)); 273544961713Sgirish if (channel == tdc) { 273644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 273744961713Sgirish "<== nxge_txdma_get_ring: tdc %d " 273844961713Sgirish "ring $%p", 273944961713Sgirish tdc, tx_rings->rings[index])); 274044961713Sgirish return (p_tx_ring_t)(tx_rings->rings[index]); 274144961713Sgirish } 274244961713Sgirish } 274344961713Sgirish 274444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_get_ring")); 274544961713Sgirish return (NULL); 274644961713Sgirish } 274744961713Sgirish 274844961713Sgirish static p_tx_mbox_t 274944961713Sgirish nxge_txdma_get_mbox(p_nxge_t nxgep, uint16_t channel) 275044961713Sgirish { 275144961713Sgirish int index, tdc, ndmas; 275244961713Sgirish p_tx_rings_t tx_rings; 275344961713Sgirish p_tx_mbox_areas_t tx_mbox_areas_p; 275444961713Sgirish p_tx_mbox_t *tx_mbox_p; 275544961713Sgirish 275644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_get_mbox")); 275744961713Sgirish 275844961713Sgirish tx_rings = nxgep->tx_rings; 275944961713Sgirish if (tx_rings == NULL) { 276044961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 276144961713Sgirish "<== nxge_txdma_get_mbox: NULL ring pointer")); 276244961713Sgirish return (NULL); 276344961713Sgirish } 276444961713Sgirish 276544961713Sgirish tx_mbox_areas_p = nxgep->tx_mbox_areas_p; 276644961713Sgirish if (tx_mbox_areas_p == NULL) { 276744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 276844961713Sgirish "<== nxge_txdma_get_mbox: NULL mbox pointer")); 276944961713Sgirish return (NULL); 277044961713Sgirish } 277144961713Sgirish 277244961713Sgirish tx_mbox_p = tx_mbox_areas_p->txmbox_areas_p; 277344961713Sgirish 277444961713Sgirish ndmas = tx_rings->ndmas; 277544961713Sgirish if (!ndmas) { 277644961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 277744961713Sgirish "<== nxge_txdma_get_mbox: no channel allocated")); 277844961713Sgirish return (NULL); 277944961713Sgirish } 278044961713Sgirish 278144961713Sgirish if (tx_rings->rings == NULL) { 278244961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 278344961713Sgirish "<== nxge_txdma_get_mbox: NULL rings pointer")); 278444961713Sgirish return (NULL); 278544961713Sgirish } 278644961713Sgirish 278744961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "==> nxge_txdma_get_mbox: " 278844961713Sgirish "tx_rings $%p tx_desc_rings $%p ndmas %d", 278944961713Sgirish tx_rings, tx_rings, ndmas)); 279044961713Sgirish 279144961713Sgirish for (index = 0; index < ndmas; index++) { 279244961713Sgirish tdc = tx_rings->rings[index]->tdc; 279344961713Sgirish NXGE_DEBUG_MSG((nxgep, MEM3_CTL, 279444961713Sgirish "==> nxge_txdma_get_mbox: channel %d", tdc)); 279544961713Sgirish if (channel == tdc) { 279644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 279744961713Sgirish "<== nxge_txdma_get_mbox: tdc %d " 279844961713Sgirish "ring $%p", 279944961713Sgirish tdc, tx_rings->rings[index])); 280044961713Sgirish return (p_tx_mbox_t)(tx_mbox_p[index]); 280144961713Sgirish } 280244961713Sgirish } 280344961713Sgirish 280444961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_get_mbox")); 280544961713Sgirish return (NULL); 280644961713Sgirish } 280744961713Sgirish 280844961713Sgirish /*ARGSUSED*/ 280944961713Sgirish static nxge_status_t 281044961713Sgirish nxge_tx_err_evnts(p_nxge_t nxgep, uint_t index, p_nxge_ldv_t ldvp, tx_cs_t cs) 281144961713Sgirish { 281244961713Sgirish npi_handle_t handle; 281344961713Sgirish npi_status_t rs; 281444961713Sgirish uint8_t channel; 281544961713Sgirish p_tx_ring_t *tx_rings; 281644961713Sgirish p_tx_ring_t tx_ring_p; 281744961713Sgirish p_nxge_tx_ring_stats_t tdc_stats; 281844961713Sgirish boolean_t txchan_fatal = B_FALSE; 281944961713Sgirish nxge_status_t status = NXGE_OK; 282044961713Sgirish tdmc_inj_par_err_t par_err; 282144961713Sgirish uint32_t value; 282244961713Sgirish 282344961713Sgirish NXGE_DEBUG_MSG((nxgep, RX2_CTL, "==> nxge_tx_err_evnts")); 282444961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 282544961713Sgirish channel = ldvp->channel; 282644961713Sgirish 282744961713Sgirish tx_rings = nxgep->tx_rings->rings; 282844961713Sgirish tx_ring_p = tx_rings[index]; 282944961713Sgirish tdc_stats = tx_ring_p->tdc_stats; 283044961713Sgirish if ((cs.bits.ldw.pkt_size_err) || (cs.bits.ldw.pref_buf_par_err) || 283144961713Sgirish (cs.bits.ldw.nack_pref) || (cs.bits.ldw.nack_pkt_rd) || 283244961713Sgirish (cs.bits.ldw.conf_part_err) || (cs.bits.ldw.pkt_prt_err)) { 283344961713Sgirish if ((rs = npi_txdma_ring_error_get(handle, channel, 283444961713Sgirish &tdc_stats->errlog)) != NPI_SUCCESS) 283544961713Sgirish return (NXGE_ERROR | rs); 283644961713Sgirish } 283744961713Sgirish 283844961713Sgirish if (cs.bits.ldw.mbox_err) { 283944961713Sgirish tdc_stats->mbox_err++; 284044961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 284144961713Sgirish NXGE_FM_EREPORT_TDMC_MBOX_ERR); 284244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 284344961713Sgirish "==> nxge_tx_err_evnts(channel %d): " 284444961713Sgirish "fatal error: mailbox", channel)); 284544961713Sgirish txchan_fatal = B_TRUE; 284644961713Sgirish } 284744961713Sgirish if (cs.bits.ldw.pkt_size_err) { 284844961713Sgirish tdc_stats->pkt_size_err++; 284944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 285044961713Sgirish NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR); 285144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 285244961713Sgirish "==> nxge_tx_err_evnts(channel %d): " 285344961713Sgirish "fatal error: pkt_size_err", channel)); 285444961713Sgirish txchan_fatal = B_TRUE; 285544961713Sgirish } 285644961713Sgirish if (cs.bits.ldw.tx_ring_oflow) { 285744961713Sgirish tdc_stats->tx_ring_oflow++; 285844961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 285944961713Sgirish NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW); 286044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 286144961713Sgirish "==> nxge_tx_err_evnts(channel %d): " 286244961713Sgirish "fatal error: tx_ring_oflow", channel)); 286344961713Sgirish txchan_fatal = B_TRUE; 286444961713Sgirish } 286544961713Sgirish if (cs.bits.ldw.pref_buf_par_err) { 286644961713Sgirish tdc_stats->pre_buf_par_err++; 286744961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 286844961713Sgirish NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR); 286944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 287044961713Sgirish "==> nxge_tx_err_evnts(channel %d): " 287144961713Sgirish "fatal error: pre_buf_par_err", channel)); 287244961713Sgirish /* Clear error injection source for parity error */ 287344961713Sgirish (void) npi_txdma_inj_par_error_get(handle, &value); 287444961713Sgirish par_err.value = value; 287544961713Sgirish par_err.bits.ldw.inject_parity_error &= ~(1 << channel); 287644961713Sgirish (void) npi_txdma_inj_par_error_set(handle, par_err.value); 287744961713Sgirish txchan_fatal = B_TRUE; 287844961713Sgirish } 287944961713Sgirish if (cs.bits.ldw.nack_pref) { 288044961713Sgirish tdc_stats->nack_pref++; 288144961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 288244961713Sgirish NXGE_FM_EREPORT_TDMC_NACK_PREF); 288344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 288444961713Sgirish "==> nxge_tx_err_evnts(channel %d): " 288544961713Sgirish "fatal error: nack_pref", channel)); 288644961713Sgirish txchan_fatal = B_TRUE; 288744961713Sgirish } 288844961713Sgirish if (cs.bits.ldw.nack_pkt_rd) { 288944961713Sgirish tdc_stats->nack_pkt_rd++; 289044961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 289144961713Sgirish NXGE_FM_EREPORT_TDMC_NACK_PKT_RD); 289244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 289344961713Sgirish "==> nxge_tx_err_evnts(channel %d): " 289444961713Sgirish "fatal error: nack_pkt_rd", channel)); 289544961713Sgirish txchan_fatal = B_TRUE; 289644961713Sgirish } 289744961713Sgirish if (cs.bits.ldw.conf_part_err) { 289844961713Sgirish tdc_stats->conf_part_err++; 289944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 290044961713Sgirish NXGE_FM_EREPORT_TDMC_CONF_PART_ERR); 290144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 290244961713Sgirish "==> nxge_tx_err_evnts(channel %d): " 290344961713Sgirish "fatal error: config_partition_err", channel)); 290444961713Sgirish txchan_fatal = B_TRUE; 290544961713Sgirish } 290644961713Sgirish if (cs.bits.ldw.pkt_prt_err) { 290744961713Sgirish tdc_stats->pkt_part_err++; 290844961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, nxgep->mac.portnum, channel, 290944961713Sgirish NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR); 291044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 291144961713Sgirish "==> nxge_tx_err_evnts(channel %d): " 291244961713Sgirish "fatal error: pkt_prt_err", channel)); 291344961713Sgirish txchan_fatal = B_TRUE; 291444961713Sgirish } 291544961713Sgirish 291644961713Sgirish /* Clear error injection source in case this is an injected error */ 291744961713Sgirish TXDMA_REG_WRITE64(nxgep->npi_handle, TDMC_INTR_DBG_REG, channel, 0); 291844961713Sgirish 291944961713Sgirish if (txchan_fatal) { 292044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 292144961713Sgirish " nxge_tx_err_evnts: " 292244961713Sgirish " fatal error on channel %d cs 0x%llx\n", 292344961713Sgirish channel, cs.value)); 292444961713Sgirish status = nxge_txdma_fatal_err_recover(nxgep, channel, 292544961713Sgirish tx_ring_p); 292644961713Sgirish if (status == NXGE_OK) { 292744961713Sgirish FM_SERVICE_RESTORED(nxgep); 292844961713Sgirish } 292944961713Sgirish } 293044961713Sgirish 293144961713Sgirish NXGE_DEBUG_MSG((nxgep, RX2_CTL, "<== nxge_tx_err_evnts")); 293244961713Sgirish 293344961713Sgirish return (status); 293444961713Sgirish } 293544961713Sgirish 293644961713Sgirish static nxge_status_t 293744961713Sgirish nxge_txdma_fatal_err_recover(p_nxge_t nxgep, uint16_t channel, 293844961713Sgirish p_tx_ring_t tx_ring_p) 293944961713Sgirish { 294044961713Sgirish npi_handle_t handle; 294144961713Sgirish npi_status_t rs = NPI_SUCCESS; 294244961713Sgirish p_tx_mbox_t tx_mbox_p; 294344961713Sgirish nxge_status_t status = NXGE_OK; 294444961713Sgirish 294544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txdma_fatal_err_recover")); 294644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 294744961713Sgirish "Recovering from TxDMAChannel#%d error...", channel)); 294844961713Sgirish 294944961713Sgirish /* 295044961713Sgirish * Stop the dma channel waits for the stop done. 295144961713Sgirish * If the stop done bit is not set, then create 295244961713Sgirish * an error. 295344961713Sgirish */ 295444961713Sgirish 295544961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 295644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel stop...")); 295744961713Sgirish MUTEX_ENTER(&tx_ring_p->lock); 295844961713Sgirish rs = npi_txdma_channel_control(handle, TXDMA_STOP, channel); 295944961713Sgirish if (rs != NPI_SUCCESS) { 296044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 296144961713Sgirish "==> nxge_txdma_fatal_err_recover (channel %d): " 296244961713Sgirish "stop failed ", channel)); 296344961713Sgirish goto fail; 296444961713Sgirish } 296544961713Sgirish 296644961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel reclaim...")); 296744961713Sgirish (void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0); 296844961713Sgirish 296944961713Sgirish /* 297044961713Sgirish * Reset TXDMA channel 297144961713Sgirish */ 297244961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel reset...")); 297344961713Sgirish if ((rs = npi_txdma_channel_control(handle, TXDMA_RESET, channel)) != 297444961713Sgirish NPI_SUCCESS) { 297544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 297644961713Sgirish "==> nxge_txdma_fatal_err_recover (channel %d)" 297744961713Sgirish " reset channel failed 0x%x", channel, rs)); 297844961713Sgirish goto fail; 297944961713Sgirish } 298044961713Sgirish 298144961713Sgirish /* 298244961713Sgirish * Reset the tail (kick) register to 0. 298344961713Sgirish * (Hardware will not reset it. Tx overflow fatal 298444961713Sgirish * error if tail is not set to 0 after reset! 298544961713Sgirish */ 298644961713Sgirish TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, 0); 298744961713Sgirish 298844961713Sgirish /* Restart TXDMA channel */ 298944961713Sgirish 299044961713Sgirish /* 299144961713Sgirish * Initialize the TXDMA channel specific FZC control 299244961713Sgirish * configurations. These FZC registers are pertaining 299344961713Sgirish * to each TX channel (i.e. logical pages). 299444961713Sgirish */ 299544961713Sgirish tx_mbox_p = nxge_txdma_get_mbox(nxgep, channel); 299644961713Sgirish 299744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel restart...")); 299844961713Sgirish status = nxge_init_fzc_txdma_channel(nxgep, channel, 299944961713Sgirish tx_ring_p, tx_mbox_p); 300044961713Sgirish if (status != NXGE_OK) 300144961713Sgirish goto fail; 300244961713Sgirish 300344961713Sgirish /* 300444961713Sgirish * Initialize the event masks. 300544961713Sgirish */ 300644961713Sgirish tx_ring_p->tx_evmask.value = 0; 300744961713Sgirish status = nxge_init_txdma_channel_event_mask(nxgep, channel, 300844961713Sgirish &tx_ring_p->tx_evmask); 300944961713Sgirish if (status != NXGE_OK) 301044961713Sgirish goto fail; 301144961713Sgirish 301244961713Sgirish tx_ring_p->wr_index_wrap = B_FALSE; 301344961713Sgirish tx_ring_p->wr_index = 0; 301444961713Sgirish tx_ring_p->rd_index = 0; 301544961713Sgirish 301644961713Sgirish /* 301744961713Sgirish * Load TXDMA descriptors, buffers, mailbox, 301844961713Sgirish * initialise the DMA channels and 301944961713Sgirish * enable each DMA channel. 302044961713Sgirish */ 302144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxDMA channel enable...")); 302244961713Sgirish status = nxge_enable_txdma_channel(nxgep, channel, 302344961713Sgirish tx_ring_p, tx_mbox_p); 302444961713Sgirish MUTEX_EXIT(&tx_ring_p->lock); 302544961713Sgirish if (status != NXGE_OK) 302644961713Sgirish goto fail; 302744961713Sgirish 302844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 302944961713Sgirish "Recovery Successful, TxDMAChannel#%d Restored", 303044961713Sgirish channel)); 303144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txdma_fatal_err_recover")); 303244961713Sgirish 303344961713Sgirish return (NXGE_OK); 303444961713Sgirish 303544961713Sgirish fail: 303644961713Sgirish MUTEX_EXIT(&tx_ring_p->lock); 303744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 303844961713Sgirish "nxge_txdma_fatal_err_recover (channel %d): " 303944961713Sgirish "failed to recover this txdma channel", channel)); 304044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed")); 304144961713Sgirish 304244961713Sgirish return (status); 304344961713Sgirish } 304444961713Sgirish 304544961713Sgirish nxge_status_t 304644961713Sgirish nxge_tx_port_fatal_err_recover(p_nxge_t nxgep) 304744961713Sgirish { 304844961713Sgirish npi_handle_t handle; 304944961713Sgirish npi_status_t rs = NPI_SUCCESS; 305044961713Sgirish nxge_status_t status = NXGE_OK; 305144961713Sgirish p_tx_ring_t *tx_desc_rings; 305244961713Sgirish p_tx_rings_t tx_rings; 305344961713Sgirish p_tx_ring_t tx_ring_p; 305444961713Sgirish p_tx_mbox_t tx_mbox_p; 305544961713Sgirish int i, ndmas; 305644961713Sgirish uint16_t channel; 305744961713Sgirish 305844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_tx_port_fatal_err_recover")); 305944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 306044961713Sgirish "Recovering from TxPort error...")); 306144961713Sgirish 306244961713Sgirish /* 306344961713Sgirish * Stop the dma channel waits for the stop done. 306444961713Sgirish * If the stop done bit is not set, then create 306544961713Sgirish * an error. 306644961713Sgirish */ 306744961713Sgirish 306844961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 306944961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxPort stop all DMA channels...")); 307044961713Sgirish 307144961713Sgirish tx_rings = nxgep->tx_rings; 307244961713Sgirish tx_desc_rings = tx_rings->rings; 307344961713Sgirish ndmas = tx_rings->ndmas; 307444961713Sgirish 307544961713Sgirish for (i = 0; i < ndmas; i++) { 307644961713Sgirish if (tx_desc_rings[i] == NULL) { 307744961713Sgirish continue; 307844961713Sgirish } 307944961713Sgirish tx_ring_p = tx_rings->rings[i]; 308044961713Sgirish MUTEX_ENTER(&tx_ring_p->lock); 308144961713Sgirish } 308244961713Sgirish 308344961713Sgirish for (i = 0; i < ndmas; i++) { 308444961713Sgirish if (tx_desc_rings[i] == NULL) { 308544961713Sgirish continue; 308644961713Sgirish } 308744961713Sgirish channel = tx_desc_rings[i]->tdc; 308844961713Sgirish tx_ring_p = tx_rings->rings[i]; 308944961713Sgirish rs = npi_txdma_channel_control(handle, TXDMA_STOP, channel); 309044961713Sgirish if (rs != NPI_SUCCESS) { 309144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 309244961713Sgirish "==> nxge_txdma_fatal_err_recover (channel %d): " 309344961713Sgirish "stop failed ", channel)); 309444961713Sgirish goto fail; 309544961713Sgirish } 309644961713Sgirish } 309744961713Sgirish 309844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxPort reclaim all DMA channels...")); 309944961713Sgirish 310044961713Sgirish for (i = 0; i < ndmas; i++) { 310144961713Sgirish if (tx_desc_rings[i] == NULL) { 310244961713Sgirish continue; 310344961713Sgirish } 310444961713Sgirish tx_ring_p = tx_rings->rings[i]; 310544961713Sgirish (void) nxge_txdma_reclaim(nxgep, tx_ring_p, 0); 310644961713Sgirish } 310744961713Sgirish 310844961713Sgirish /* 310944961713Sgirish * Reset TXDMA channel 311044961713Sgirish */ 311144961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxPort reset all DMA channels...")); 311244961713Sgirish 311344961713Sgirish for (i = 0; i < ndmas; i++) { 311444961713Sgirish if (tx_desc_rings[i] == NULL) { 311544961713Sgirish continue; 311644961713Sgirish } 311744961713Sgirish channel = tx_desc_rings[i]->tdc; 311844961713Sgirish tx_ring_p = tx_rings->rings[i]; 311944961713Sgirish if ((rs = npi_txdma_channel_control(handle, TXDMA_RESET, 312044961713Sgirish channel)) != NPI_SUCCESS) { 312144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 312244961713Sgirish "==> nxge_txdma_fatal_err_recover (channel %d)" 312344961713Sgirish " reset channel failed 0x%x", channel, rs)); 312444961713Sgirish goto fail; 312544961713Sgirish } 312644961713Sgirish 312744961713Sgirish /* 312844961713Sgirish * Reset the tail (kick) register to 0. 312944961713Sgirish * (Hardware will not reset it. Tx overflow fatal 313044961713Sgirish * error if tail is not set to 0 after reset! 313144961713Sgirish */ 313244961713Sgirish 313344961713Sgirish TXDMA_REG_WRITE64(handle, TX_RING_KICK_REG, channel, 0); 313444961713Sgirish 313544961713Sgirish } 313644961713Sgirish 313744961713Sgirish /* 313844961713Sgirish * Initialize the TXDMA channel specific FZC control 313944961713Sgirish * configurations. These FZC registers are pertaining 314044961713Sgirish * to each TX channel (i.e. logical pages). 314144961713Sgirish */ 314244961713Sgirish 314344961713Sgirish /* Restart TXDMA channels */ 314444961713Sgirish 314544961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxPort re-start all DMA channels...")); 314644961713Sgirish 314744961713Sgirish for (i = 0; i < ndmas; i++) { 314844961713Sgirish if (tx_desc_rings[i] == NULL) { 314944961713Sgirish continue; 315044961713Sgirish } 315144961713Sgirish channel = tx_desc_rings[i]->tdc; 315244961713Sgirish tx_ring_p = tx_rings->rings[i]; 315344961713Sgirish tx_mbox_p = nxge_txdma_get_mbox(nxgep, channel); 315444961713Sgirish status = nxge_init_fzc_txdma_channel(nxgep, channel, 315544961713Sgirish tx_ring_p, tx_mbox_p); 315644961713Sgirish tx_ring_p->tx_evmask.value = 0; 315744961713Sgirish /* 315844961713Sgirish * Initialize the event masks. 315944961713Sgirish */ 316044961713Sgirish status = nxge_init_txdma_channel_event_mask(nxgep, channel, 316144961713Sgirish &tx_ring_p->tx_evmask); 316244961713Sgirish 316344961713Sgirish tx_ring_p->wr_index_wrap = B_FALSE; 316444961713Sgirish tx_ring_p->wr_index = 0; 316544961713Sgirish tx_ring_p->rd_index = 0; 316644961713Sgirish 316744961713Sgirish if (status != NXGE_OK) 316844961713Sgirish goto fail; 316944961713Sgirish if (status != NXGE_OK) 317044961713Sgirish goto fail; 317144961713Sgirish } 317244961713Sgirish 317344961713Sgirish /* 317444961713Sgirish * Load TXDMA descriptors, buffers, mailbox, 317544961713Sgirish * initialise the DMA channels and 317644961713Sgirish * enable each DMA channel. 317744961713Sgirish */ 317844961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "TxPort re-enable all DMA channels...")); 317944961713Sgirish 318044961713Sgirish for (i = 0; i < ndmas; i++) { 318144961713Sgirish if (tx_desc_rings[i] == NULL) { 318244961713Sgirish continue; 318344961713Sgirish } 318444961713Sgirish channel = tx_desc_rings[i]->tdc; 318544961713Sgirish tx_ring_p = tx_rings->rings[i]; 318644961713Sgirish tx_mbox_p = nxge_txdma_get_mbox(nxgep, channel); 318744961713Sgirish status = nxge_enable_txdma_channel(nxgep, channel, 318844961713Sgirish tx_ring_p, tx_mbox_p); 318944961713Sgirish if (status != NXGE_OK) 319044961713Sgirish goto fail; 319144961713Sgirish } 319244961713Sgirish 319344961713Sgirish for (i = 0; i < ndmas; i++) { 319444961713Sgirish if (tx_desc_rings[i] == NULL) { 319544961713Sgirish continue; 319644961713Sgirish } 319744961713Sgirish tx_ring_p = tx_rings->rings[i]; 319844961713Sgirish MUTEX_EXIT(&tx_ring_p->lock); 319944961713Sgirish } 320044961713Sgirish 320144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 320244961713Sgirish "Recovery Successful, TxPort Restored")); 320344961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_tx_port_fatal_err_recover")); 320444961713Sgirish 320544961713Sgirish return (NXGE_OK); 320644961713Sgirish 320744961713Sgirish fail: 320844961713Sgirish for (i = 0; i < ndmas; i++) { 320944961713Sgirish if (tx_desc_rings[i] == NULL) { 321044961713Sgirish continue; 321144961713Sgirish } 321244961713Sgirish tx_ring_p = tx_rings->rings[i]; 321344961713Sgirish MUTEX_EXIT(&tx_ring_p->lock); 321444961713Sgirish } 321544961713Sgirish 321644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed")); 321744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 321844961713Sgirish "nxge_txdma_fatal_err_recover (channel %d): " 321944961713Sgirish "failed to recover this txdma channel")); 322044961713Sgirish 322144961713Sgirish return (status); 322244961713Sgirish } 322344961713Sgirish 322444961713Sgirish void 322544961713Sgirish nxge_txdma_inject_err(p_nxge_t nxgep, uint32_t err_id, uint8_t chan) 322644961713Sgirish { 322744961713Sgirish tdmc_intr_dbg_t tdi; 322844961713Sgirish tdmc_inj_par_err_t par_err; 322944961713Sgirish uint32_t value; 323044961713Sgirish npi_handle_t handle; 323144961713Sgirish 323244961713Sgirish switch (err_id) { 323344961713Sgirish 323444961713Sgirish case NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR: 323544961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 323644961713Sgirish /* Clear error injection source for parity error */ 323744961713Sgirish (void) npi_txdma_inj_par_error_get(handle, &value); 323844961713Sgirish par_err.value = value; 323944961713Sgirish par_err.bits.ldw.inject_parity_error &= ~(1 << chan); 324044961713Sgirish (void) npi_txdma_inj_par_error_set(handle, par_err.value); 324144961713Sgirish 324244961713Sgirish par_err.bits.ldw.inject_parity_error = (1 << chan); 324344961713Sgirish (void) npi_txdma_inj_par_error_get(handle, &value); 324444961713Sgirish par_err.value = value; 324544961713Sgirish par_err.bits.ldw.inject_parity_error |= (1 << chan); 324644961713Sgirish cmn_err(CE_NOTE, "!Write 0x%llx to TDMC_INJ_PAR_ERR_REG\n", 324744961713Sgirish (unsigned long long)par_err.value); 324844961713Sgirish (void) npi_txdma_inj_par_error_set(handle, par_err.value); 324944961713Sgirish break; 325044961713Sgirish 325144961713Sgirish case NXGE_FM_EREPORT_TDMC_MBOX_ERR: 325244961713Sgirish case NXGE_FM_EREPORT_TDMC_NACK_PREF: 325344961713Sgirish case NXGE_FM_EREPORT_TDMC_NACK_PKT_RD: 325444961713Sgirish case NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR: 325544961713Sgirish case NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW: 325644961713Sgirish case NXGE_FM_EREPORT_TDMC_CONF_PART_ERR: 325744961713Sgirish case NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR: 325844961713Sgirish TXDMA_REG_READ64(nxgep->npi_handle, TDMC_INTR_DBG_REG, 325944961713Sgirish chan, &tdi.value); 326044961713Sgirish if (err_id == NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR) 326144961713Sgirish tdi.bits.ldw.pref_buf_par_err = 1; 326244961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_MBOX_ERR) 326344961713Sgirish tdi.bits.ldw.mbox_err = 1; 326444961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_NACK_PREF) 326544961713Sgirish tdi.bits.ldw.nack_pref = 1; 326644961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_NACK_PKT_RD) 326744961713Sgirish tdi.bits.ldw.nack_pkt_rd = 1; 326844961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR) 326944961713Sgirish tdi.bits.ldw.pkt_size_err = 1; 327044961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW) 327144961713Sgirish tdi.bits.ldw.tx_ring_oflow = 1; 327244961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_CONF_PART_ERR) 327344961713Sgirish tdi.bits.ldw.conf_part_err = 1; 327444961713Sgirish else if (err_id == NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR) 327544961713Sgirish tdi.bits.ldw.pkt_part_err = 1; 327644961713Sgirish cmn_err(CE_NOTE, "!Write 0x%lx to TDMC_INTR_DBG_REG\n", 327744961713Sgirish tdi.value); 327844961713Sgirish TXDMA_REG_WRITE64(nxgep->npi_handle, TDMC_INTR_DBG_REG, 327944961713Sgirish chan, tdi.value); 328044961713Sgirish 328144961713Sgirish break; 328244961713Sgirish } 328344961713Sgirish } 3284