13dec9fcdSqs148142 /* 23dec9fcdSqs148142 * CDDL HEADER START 33dec9fcdSqs148142 * 43dec9fcdSqs148142 * The contents of this file are subject to the terms of the 53dec9fcdSqs148142 * Common Development and Distribution License (the "License"). 63dec9fcdSqs148142 * You may not use this file except in compliance with the License. 73dec9fcdSqs148142 * 83dec9fcdSqs148142 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93dec9fcdSqs148142 * or http://www.opensolaris.org/os/licensing. 103dec9fcdSqs148142 * See the License for the specific language governing permissions 113dec9fcdSqs148142 * and limitations under the License. 123dec9fcdSqs148142 * 133dec9fcdSqs148142 * When distributing Covered Code, include this CDDL HEADER in each 143dec9fcdSqs148142 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153dec9fcdSqs148142 * If applicable, add the following below this CDDL HEADER, with the 163dec9fcdSqs148142 * fields enclosed by brackets "[]" replaced with your own identifying 173dec9fcdSqs148142 * information: Portions Copyright [yyyy] [name of copyright owner] 183dec9fcdSqs148142 * 193dec9fcdSqs148142 * CDDL HEADER END 203dec9fcdSqs148142 */ 213dec9fcdSqs148142 /* 220dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 233dec9fcdSqs148142 * Use is subject to license terms. 243dec9fcdSqs148142 */ 253dec9fcdSqs148142 263dec9fcdSqs148142 #include <hxge_impl.h> 273dec9fcdSqs148142 #include <hxge_rxdma.h> 286ffca240SMichael Speer #include <hpi.h> 296ffca240SMichael Speer #include <hpi_vir.h> 303dec9fcdSqs148142 313dec9fcdSqs148142 /* 32b83cd2c3SMichael Speer * Number of blocks to accumulate before re-enabling DMA 33b83cd2c3SMichael Speer * when we get RBR empty. 34b83cd2c3SMichael Speer */ 35676f0400SMichael Speer #define HXGE_RBR_EMPTY_THRESHOLD 64 36b83cd2c3SMichael Speer 37b83cd2c3SMichael Speer /* 383dec9fcdSqs148142 * Globals: tunable parameters (/etc/system or adb) 393dec9fcdSqs148142 * 403dec9fcdSqs148142 */ 413dec9fcdSqs148142 extern uint32_t hxge_rbr_size; 423dec9fcdSqs148142 extern uint32_t hxge_rcr_size; 433dec9fcdSqs148142 extern uint32_t hxge_rbr_spare_size; 443dec9fcdSqs148142 extern uint32_t hxge_mblks_pending; 453dec9fcdSqs148142 463dec9fcdSqs148142 /* 473dec9fcdSqs148142 * Tunables to manage the receive buffer blocks. 483dec9fcdSqs148142 * 493dec9fcdSqs148142 * hxge_rx_threshold_hi: copy all buffers. 503dec9fcdSqs148142 * hxge_rx_bcopy_size_type: receive buffer block size type. 513dec9fcdSqs148142 * hxge_rx_threshold_lo: copy only up to tunable block size type. 523dec9fcdSqs148142 */ 533dec9fcdSqs148142 extern hxge_rxbuf_threshold_t hxge_rx_threshold_hi; 543dec9fcdSqs148142 extern hxge_rxbuf_type_t hxge_rx_buf_size_type; 553dec9fcdSqs148142 extern hxge_rxbuf_threshold_t hxge_rx_threshold_lo; 563dec9fcdSqs148142 57b83cd2c3SMichael Speer /* 58b83cd2c3SMichael Speer * Static local functions. 59b83cd2c3SMichael Speer */ 603dec9fcdSqs148142 static hxge_status_t hxge_map_rxdma(p_hxge_t hxgep); 613dec9fcdSqs148142 static void hxge_unmap_rxdma(p_hxge_t hxgep); 623dec9fcdSqs148142 static hxge_status_t hxge_rxdma_hw_start_common(p_hxge_t hxgep); 633dec9fcdSqs148142 static hxge_status_t hxge_rxdma_hw_start(p_hxge_t hxgep); 643dec9fcdSqs148142 static void hxge_rxdma_hw_stop(p_hxge_t hxgep); 653dec9fcdSqs148142 static hxge_status_t hxge_map_rxdma_channel(p_hxge_t hxgep, uint16_t channel, 663dec9fcdSqs148142 p_hxge_dma_common_t *dma_buf_p, p_rx_rbr_ring_t *rbr_p, 678ad8db65SMichael Speer uint32_t num_chunks, p_hxge_dma_common_t *dma_rbr_cntl_p, 688ad8db65SMichael Speer p_hxge_dma_common_t *dma_rcr_cntl_p, p_hxge_dma_common_t *dma_mbox_cntl_p, 693dec9fcdSqs148142 p_rx_rcr_ring_t *rcr_p, p_rx_mbox_t *rx_mbox_p); 703dec9fcdSqs148142 static void hxge_unmap_rxdma_channel(p_hxge_t hxgep, uint16_t channel, 713dec9fcdSqs148142 p_rx_rbr_ring_t rbr_p, p_rx_rcr_ring_t rcr_p, p_rx_mbox_t rx_mbox_p); 723dec9fcdSqs148142 static hxge_status_t hxge_map_rxdma_channel_cfg_ring(p_hxge_t hxgep, 738ad8db65SMichael Speer uint16_t dma_channel, p_hxge_dma_common_t *dma_rbr_cntl_p, 748ad8db65SMichael Speer p_hxge_dma_common_t *dma_rcr_cntl_p, p_hxge_dma_common_t *dma_mbox_cntl_p, 753dec9fcdSqs148142 p_rx_rbr_ring_t *rbr_p, p_rx_rcr_ring_t *rcr_p, p_rx_mbox_t *rx_mbox_p); 763dec9fcdSqs148142 static void hxge_unmap_rxdma_channel_cfg_ring(p_hxge_t hxgep, 773dec9fcdSqs148142 p_rx_rcr_ring_t rcr_p, p_rx_mbox_t rx_mbox_p); 783dec9fcdSqs148142 static hxge_status_t hxge_map_rxdma_channel_buf_ring(p_hxge_t hxgep, 793dec9fcdSqs148142 uint16_t channel, p_hxge_dma_common_t *dma_buf_p, 803dec9fcdSqs148142 p_rx_rbr_ring_t *rbr_p, uint32_t num_chunks); 813dec9fcdSqs148142 static void hxge_unmap_rxdma_channel_buf_ring(p_hxge_t hxgep, 823dec9fcdSqs148142 p_rx_rbr_ring_t rbr_p); 833dec9fcdSqs148142 static hxge_status_t hxge_rxdma_start_channel(p_hxge_t hxgep, uint16_t channel, 84fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States p_rx_rbr_ring_t rbr_p, p_rx_rcr_ring_t rcr_p, p_rx_mbox_t mbox_p, 85fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States int n_init_kick); 863dec9fcdSqs148142 static hxge_status_t hxge_rxdma_stop_channel(p_hxge_t hxgep, uint16_t channel); 873dec9fcdSqs148142 static mblk_t *hxge_rx_pkts(p_hxge_t hxgep, uint_t vindex, p_hxge_ldv_t ldvp, 881ed83081SMichael Speer p_rx_rcr_ring_t rcr_p, rdc_stat_t cs, int bytes_to_read); 8941307000SQiyan Sun - Sun Microsystems - San Diego United States static uint32_t hxge_scan_for_last_eop(p_rx_rcr_ring_t rcr_p, 9041307000SQiyan Sun - Sun Microsystems - San Diego United States p_rcr_entry_t rcr_desc_rd_head_p, uint32_t num_rcrs); 913dec9fcdSqs148142 static void hxge_receive_packet(p_hxge_t hxgep, p_rx_rcr_ring_t rcr_p, 923dec9fcdSqs148142 p_rcr_entry_t rcr_desc_rd_head_p, boolean_t *multi_p, 93fe930412Sqs148142 mblk_t ** mp, mblk_t ** mp_cont, uint32_t *invalid_rcr_entry); 943dec9fcdSqs148142 static hxge_status_t hxge_disable_rxdma_channel(p_hxge_t hxgep, 953dec9fcdSqs148142 uint16_t channel); 963dec9fcdSqs148142 static p_rx_msg_t hxge_allocb(size_t, uint32_t, p_hxge_dma_common_t); 973dec9fcdSqs148142 static void hxge_freeb(p_rx_msg_t); 983dec9fcdSqs148142 static hxge_status_t hxge_rx_err_evnts(p_hxge_t hxgep, uint_t index, 993dec9fcdSqs148142 p_hxge_ldv_t ldvp, rdc_stat_t cs); 1003dec9fcdSqs148142 static hxge_status_t hxge_rxbuf_index_info_init(p_hxge_t hxgep, 1013dec9fcdSqs148142 p_rx_rbr_ring_t rx_dmap); 1023dec9fcdSqs148142 static hxge_status_t hxge_rxdma_fatal_err_recover(p_hxge_t hxgep, 1033dec9fcdSqs148142 uint16_t channel); 1043dec9fcdSqs148142 static hxge_status_t hxge_rx_port_fatal_err_recover(p_hxge_t hxgep); 1051c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States static void hxge_rbr_empty_restore(p_hxge_t hxgep, 1061c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States p_rx_rbr_ring_t rx_rbr_p); 1073dec9fcdSqs148142 1083dec9fcdSqs148142 hxge_status_t 1093dec9fcdSqs148142 hxge_init_rxdma_channels(p_hxge_t hxgep) 1103dec9fcdSqs148142 { 1113dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 112fe930412Sqs148142 block_reset_t reset_reg; 113676f0400SMichael Speer int i; 1143dec9fcdSqs148142 1153dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_init_rxdma_channels")); 1163dec9fcdSqs148142 117676f0400SMichael Speer for (i = 0; i < HXGE_MAX_RDCS; i++) 118676f0400SMichael Speer hxgep->rdc_first_intr[i] = B_TRUE; 119676f0400SMichael Speer 120fe930412Sqs148142 /* Reset RDC block from PEU to clear any previous state */ 121fe930412Sqs148142 reset_reg.value = 0; 122fe930412Sqs148142 reset_reg.bits.rdc_rst = 1; 123fe930412Sqs148142 HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, reset_reg.value); 124fe930412Sqs148142 HXGE_DELAY(1000); 125fe930412Sqs148142 1263dec9fcdSqs148142 status = hxge_map_rxdma(hxgep); 1273dec9fcdSqs148142 if (status != HXGE_OK) { 1283dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 1293dec9fcdSqs148142 "<== hxge_init_rxdma: status 0x%x", status)); 1303dec9fcdSqs148142 return (status); 1313dec9fcdSqs148142 } 1323dec9fcdSqs148142 1333dec9fcdSqs148142 status = hxge_rxdma_hw_start_common(hxgep); 1343dec9fcdSqs148142 if (status != HXGE_OK) { 1353dec9fcdSqs148142 hxge_unmap_rxdma(hxgep); 1363dec9fcdSqs148142 } 1373dec9fcdSqs148142 1383dec9fcdSqs148142 status = hxge_rxdma_hw_start(hxgep); 1393dec9fcdSqs148142 if (status != HXGE_OK) { 1403dec9fcdSqs148142 hxge_unmap_rxdma(hxgep); 1413dec9fcdSqs148142 } 1423dec9fcdSqs148142 1433dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 1443dec9fcdSqs148142 "<== hxge_init_rxdma_channels: status 0x%x", status)); 1453dec9fcdSqs148142 return (status); 1463dec9fcdSqs148142 } 1473dec9fcdSqs148142 1483dec9fcdSqs148142 void 1493dec9fcdSqs148142 hxge_uninit_rxdma_channels(p_hxge_t hxgep) 1503dec9fcdSqs148142 { 1513dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_uninit_rxdma_channels")); 1523dec9fcdSqs148142 1533dec9fcdSqs148142 hxge_rxdma_hw_stop(hxgep); 1543dec9fcdSqs148142 hxge_unmap_rxdma(hxgep); 1553dec9fcdSqs148142 1563dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_uinit_rxdma_channels")); 1573dec9fcdSqs148142 } 1583dec9fcdSqs148142 1593dec9fcdSqs148142 hxge_status_t 1603dec9fcdSqs148142 hxge_init_rxdma_channel_cntl_stat(p_hxge_t hxgep, uint16_t channel, 1613dec9fcdSqs148142 rdc_stat_t *cs_p) 1623dec9fcdSqs148142 { 1633dec9fcdSqs148142 hpi_handle_t handle; 1643dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 1653dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 1663dec9fcdSqs148142 1673dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 1683dec9fcdSqs148142 "<== hxge_init_rxdma_channel_cntl_stat")); 1693dec9fcdSqs148142 1703dec9fcdSqs148142 handle = HXGE_DEV_HPI_HANDLE(hxgep); 1713dec9fcdSqs148142 rs = hpi_rxdma_control_status(handle, OP_SET, channel, cs_p); 1723dec9fcdSqs148142 1733dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 1743dec9fcdSqs148142 status = HXGE_ERROR | rs; 1753dec9fcdSqs148142 } 1763dec9fcdSqs148142 return (status); 1773dec9fcdSqs148142 } 1783dec9fcdSqs148142 1793dec9fcdSqs148142 1803dec9fcdSqs148142 hxge_status_t 1813dec9fcdSqs148142 hxge_enable_rxdma_channel(p_hxge_t hxgep, uint16_t channel, 182fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States p_rx_rbr_ring_t rbr_p, p_rx_rcr_ring_t rcr_p, p_rx_mbox_t mbox_p, 183fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States int n_init_kick) 1843dec9fcdSqs148142 { 1853dec9fcdSqs148142 hpi_handle_t handle; 1863dec9fcdSqs148142 rdc_desc_cfg_t rdc_desc; 1873dec9fcdSqs148142 rdc_rcr_cfg_b_t *cfgb_p; 1883dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 1893dec9fcdSqs148142 1903dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_enable_rxdma_channel")); 1913dec9fcdSqs148142 handle = HXGE_DEV_HPI_HANDLE(hxgep); 1923dec9fcdSqs148142 1933dec9fcdSqs148142 /* 1943dec9fcdSqs148142 * Use configuration data composed at init time. Write to hardware the 1953dec9fcdSqs148142 * receive ring configurations. 1963dec9fcdSqs148142 */ 1973dec9fcdSqs148142 rdc_desc.mbox_enable = 1; 1983dec9fcdSqs148142 rdc_desc.mbox_addr = mbox_p->mbox_addr; 1993dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 2003dec9fcdSqs148142 "==> hxge_enable_rxdma_channel: mboxp $%p($%p)", 2013dec9fcdSqs148142 mbox_p->mbox_addr, rdc_desc.mbox_addr)); 2023dec9fcdSqs148142 2033dec9fcdSqs148142 rdc_desc.rbr_len = rbr_p->rbb_max; 2043dec9fcdSqs148142 rdc_desc.rbr_addr = rbr_p->rbr_addr; 2053dec9fcdSqs148142 2063dec9fcdSqs148142 switch (hxgep->rx_bksize_code) { 2073dec9fcdSqs148142 case RBR_BKSIZE_4K: 2083dec9fcdSqs148142 rdc_desc.page_size = SIZE_4KB; 2093dec9fcdSqs148142 break; 2103dec9fcdSqs148142 case RBR_BKSIZE_8K: 2113dec9fcdSqs148142 rdc_desc.page_size = SIZE_8KB; 2123dec9fcdSqs148142 break; 2133dec9fcdSqs148142 } 2143dec9fcdSqs148142 2153dec9fcdSqs148142 rdc_desc.size0 = rbr_p->hpi_pkt_buf_size0; 2163dec9fcdSqs148142 rdc_desc.valid0 = 1; 2173dec9fcdSqs148142 2183dec9fcdSqs148142 rdc_desc.size1 = rbr_p->hpi_pkt_buf_size1; 2193dec9fcdSqs148142 rdc_desc.valid1 = 1; 2203dec9fcdSqs148142 2213dec9fcdSqs148142 rdc_desc.size2 = rbr_p->hpi_pkt_buf_size2; 2223dec9fcdSqs148142 rdc_desc.valid2 = 1; 2233dec9fcdSqs148142 2243dec9fcdSqs148142 rdc_desc.full_hdr = rcr_p->full_hdr_flag; 2253dec9fcdSqs148142 rdc_desc.offset = rcr_p->sw_priv_hdr_len; 2263dec9fcdSqs148142 2273dec9fcdSqs148142 rdc_desc.rcr_len = rcr_p->comp_size; 2283dec9fcdSqs148142 rdc_desc.rcr_addr = rcr_p->rcr_addr; 2293dec9fcdSqs148142 2303dec9fcdSqs148142 cfgb_p = &(rcr_p->rcr_cfgb); 2313dec9fcdSqs148142 rdc_desc.rcr_threshold = cfgb_p->bits.pthres; 2323dec9fcdSqs148142 rdc_desc.rcr_timeout = cfgb_p->bits.timeout; 2333dec9fcdSqs148142 rdc_desc.rcr_timeout_enable = cfgb_p->bits.entout; 2343dec9fcdSqs148142 2353dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_enable_rxdma_channel: " 2363dec9fcdSqs148142 "rbr_len qlen %d pagesize code %d rcr_len %d", 2373dec9fcdSqs148142 rdc_desc.rbr_len, rdc_desc.page_size, rdc_desc.rcr_len)); 2383dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_enable_rxdma_channel: " 2393dec9fcdSqs148142 "size 0 %d size 1 %d size 2 %d", 2403dec9fcdSqs148142 rbr_p->hpi_pkt_buf_size0, rbr_p->hpi_pkt_buf_size1, 2413dec9fcdSqs148142 rbr_p->hpi_pkt_buf_size2)); 2423dec9fcdSqs148142 2433dec9fcdSqs148142 rs = hpi_rxdma_cfg_rdc_ring(handle, rbr_p->rdc, &rdc_desc); 2443dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 2453dec9fcdSqs148142 return (HXGE_ERROR | rs); 2463dec9fcdSqs148142 } 2473dec9fcdSqs148142 2483dec9fcdSqs148142 /* 2493dec9fcdSqs148142 * Enable the timeout and threshold. 2503dec9fcdSqs148142 */ 2513dec9fcdSqs148142 rs = hpi_rxdma_cfg_rdc_rcr_threshold(handle, channel, 2523dec9fcdSqs148142 rdc_desc.rcr_threshold); 2533dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 2543dec9fcdSqs148142 return (HXGE_ERROR | rs); 2553dec9fcdSqs148142 } 2563dec9fcdSqs148142 2573dec9fcdSqs148142 rs = hpi_rxdma_cfg_rdc_rcr_timeout(handle, channel, 2583dec9fcdSqs148142 rdc_desc.rcr_timeout); 2593dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 2603dec9fcdSqs148142 return (HXGE_ERROR | rs); 2613dec9fcdSqs148142 } 2623dec9fcdSqs148142 2633a109ad9SQiyan Sun - Sun Microsystems - San Diego United States /* Kick the DMA engine */ 264fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States hpi_rxdma_rdc_rbr_kick(handle, channel, n_init_kick); 265dc10a9c2SMichael Speer 2663dec9fcdSqs148142 /* Clear the rbr empty bit */ 2673dec9fcdSqs148142 (void) hpi_rxdma_channel_rbr_empty_clear(handle, channel); 2683dec9fcdSqs148142 2696ffca240SMichael Speer /* 2706ffca240SMichael Speer * Enable the DMA 2716ffca240SMichael Speer */ 2726ffca240SMichael Speer rs = hpi_rxdma_cfg_rdc_enable(handle, channel); 2736ffca240SMichael Speer if (rs != HPI_SUCCESS) { 2746ffca240SMichael Speer return (HXGE_ERROR | rs); 2756ffca240SMichael Speer } 2766ffca240SMichael Speer 2773dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_enable_rxdma_channel")); 2783dec9fcdSqs148142 2793dec9fcdSqs148142 return (HXGE_OK); 2803dec9fcdSqs148142 } 2813dec9fcdSqs148142 2823dec9fcdSqs148142 static hxge_status_t 2833dec9fcdSqs148142 hxge_disable_rxdma_channel(p_hxge_t hxgep, uint16_t channel) 2843dec9fcdSqs148142 { 2853dec9fcdSqs148142 hpi_handle_t handle; 2863dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 2873dec9fcdSqs148142 2883dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_disable_rxdma_channel")); 2893dec9fcdSqs148142 2903dec9fcdSqs148142 handle = HXGE_DEV_HPI_HANDLE(hxgep); 2913dec9fcdSqs148142 2923dec9fcdSqs148142 /* disable the DMA */ 2933dec9fcdSqs148142 rs = hpi_rxdma_cfg_rdc_disable(handle, channel); 2943dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 2953dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 2963dec9fcdSqs148142 "<== hxge_disable_rxdma_channel:failed (0x%x)", rs)); 2973dec9fcdSqs148142 return (HXGE_ERROR | rs); 2983dec9fcdSqs148142 } 2993dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_disable_rxdma_channel")); 3003dec9fcdSqs148142 return (HXGE_OK); 3013dec9fcdSqs148142 } 3023dec9fcdSqs148142 3033dec9fcdSqs148142 hxge_status_t 3043dec9fcdSqs148142 hxge_rxdma_channel_rcrflush(p_hxge_t hxgep, uint8_t channel) 3053dec9fcdSqs148142 { 3063dec9fcdSqs148142 hpi_handle_t handle; 3073dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 3083dec9fcdSqs148142 3093dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 3103dec9fcdSqs148142 "==> hxge_rxdma_channel_rcrflush")); 3113dec9fcdSqs148142 3123dec9fcdSqs148142 handle = HXGE_DEV_HPI_HANDLE(hxgep); 3133dec9fcdSqs148142 hpi_rxdma_rdc_rcr_flush(handle, channel); 3143dec9fcdSqs148142 3153dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 3163dec9fcdSqs148142 "<== hxge_rxdma_channel_rcrflush")); 3173dec9fcdSqs148142 return (status); 3183dec9fcdSqs148142 3193dec9fcdSqs148142 } 3203dec9fcdSqs148142 3213dec9fcdSqs148142 #define MID_INDEX(l, r) ((r + l + 1) >> 1) 3223dec9fcdSqs148142 3233dec9fcdSqs148142 #define TO_LEFT -1 3243dec9fcdSqs148142 #define TO_RIGHT 1 3253dec9fcdSqs148142 #define BOTH_RIGHT (TO_RIGHT + TO_RIGHT) 3263dec9fcdSqs148142 #define BOTH_LEFT (TO_LEFT + TO_LEFT) 3273dec9fcdSqs148142 #define IN_MIDDLE (TO_RIGHT + TO_LEFT) 3283dec9fcdSqs148142 #define NO_HINT 0xffffffff 3293dec9fcdSqs148142 3303dec9fcdSqs148142 /*ARGSUSED*/ 3313dec9fcdSqs148142 hxge_status_t 3323dec9fcdSqs148142 hxge_rxbuf_pp_to_vp(p_hxge_t hxgep, p_rx_rbr_ring_t rbr_p, 3333dec9fcdSqs148142 uint8_t pktbufsz_type, uint64_t *pkt_buf_addr_pp, 3343dec9fcdSqs148142 uint64_t **pkt_buf_addr_p, uint32_t *bufoffset, uint32_t *msg_index) 3353dec9fcdSqs148142 { 3363dec9fcdSqs148142 int bufsize; 3373dec9fcdSqs148142 uint64_t pktbuf_pp; 3383dec9fcdSqs148142 uint64_t dvma_addr; 3393dec9fcdSqs148142 rxring_info_t *ring_info; 3403dec9fcdSqs148142 int base_side, end_side; 3413dec9fcdSqs148142 int r_index, l_index, anchor_index; 3423dec9fcdSqs148142 int found, search_done; 3433dec9fcdSqs148142 uint32_t offset, chunk_size, block_size, page_size_mask; 3443dec9fcdSqs148142 uint32_t chunk_index, block_index, total_index; 3453dec9fcdSqs148142 int max_iterations, iteration; 3463dec9fcdSqs148142 rxbuf_index_info_t *bufinfo; 3473dec9fcdSqs148142 3483dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, "==> hxge_rxbuf_pp_to_vp")); 3493dec9fcdSqs148142 3503dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 3513dec9fcdSqs148142 "==> hxge_rxbuf_pp_to_vp: buf_pp $%p btype %d", 3523dec9fcdSqs148142 pkt_buf_addr_pp, pktbufsz_type)); 3533dec9fcdSqs148142 354fe930412Sqs148142 #if defined(__i386) 355fe930412Sqs148142 pktbuf_pp = (uint64_t)(uint32_t)pkt_buf_addr_pp; 356fe930412Sqs148142 #else 3573dec9fcdSqs148142 pktbuf_pp = (uint64_t)pkt_buf_addr_pp; 358fe930412Sqs148142 #endif 3593dec9fcdSqs148142 3603dec9fcdSqs148142 switch (pktbufsz_type) { 3613dec9fcdSqs148142 case 0: 3623dec9fcdSqs148142 bufsize = rbr_p->pkt_buf_size0; 3633dec9fcdSqs148142 break; 3643dec9fcdSqs148142 case 1: 3653dec9fcdSqs148142 bufsize = rbr_p->pkt_buf_size1; 3663dec9fcdSqs148142 break; 3673dec9fcdSqs148142 case 2: 3683dec9fcdSqs148142 bufsize = rbr_p->pkt_buf_size2; 3693dec9fcdSqs148142 break; 3703dec9fcdSqs148142 case RCR_SINGLE_BLOCK: 3713dec9fcdSqs148142 bufsize = 0; 3723dec9fcdSqs148142 anchor_index = 0; 3733dec9fcdSqs148142 break; 3743dec9fcdSqs148142 default: 3753dec9fcdSqs148142 return (HXGE_ERROR); 3763dec9fcdSqs148142 } 3773dec9fcdSqs148142 3783dec9fcdSqs148142 if (rbr_p->num_blocks == 1) { 3793dec9fcdSqs148142 anchor_index = 0; 3803dec9fcdSqs148142 ring_info = rbr_p->ring_info; 3813dec9fcdSqs148142 bufinfo = (rxbuf_index_info_t *)ring_info->buffer; 3823dec9fcdSqs148142 3833dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 3843dec9fcdSqs148142 "==> hxge_rxbuf_pp_to_vp: (found, 1 block) " 3853dec9fcdSqs148142 "buf_pp $%p btype %d anchor_index %d bufinfo $%p", 3863dec9fcdSqs148142 pkt_buf_addr_pp, pktbufsz_type, anchor_index, bufinfo)); 3873dec9fcdSqs148142 3883dec9fcdSqs148142 goto found_index; 3893dec9fcdSqs148142 } 3903dec9fcdSqs148142 3913dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 3923dec9fcdSqs148142 "==> hxge_rxbuf_pp_to_vp: buf_pp $%p btype %d anchor_index %d", 3933dec9fcdSqs148142 pkt_buf_addr_pp, pktbufsz_type, anchor_index)); 3943dec9fcdSqs148142 3953dec9fcdSqs148142 ring_info = rbr_p->ring_info; 3963dec9fcdSqs148142 found = B_FALSE; 3973dec9fcdSqs148142 bufinfo = (rxbuf_index_info_t *)ring_info->buffer; 3983dec9fcdSqs148142 iteration = 0; 3993dec9fcdSqs148142 max_iterations = ring_info->max_iterations; 4003dec9fcdSqs148142 4013dec9fcdSqs148142 /* 4023dec9fcdSqs148142 * First check if this block have been seen recently. This is indicated 4033dec9fcdSqs148142 * by a hint which is initialized when the first buffer of the block is 4043dec9fcdSqs148142 * seen. The hint is reset when the last buffer of the block has been 4053dec9fcdSqs148142 * processed. As three block sizes are supported, three hints are kept. 4063dec9fcdSqs148142 * The idea behind the hints is that once the hardware uses a block 4073dec9fcdSqs148142 * for a buffer of that size, it will use it exclusively for that size 4083dec9fcdSqs148142 * and will use it until it is exhausted. It is assumed that there 4093dec9fcdSqs148142 * would a single block being used for the same buffer sizes at any 4103dec9fcdSqs148142 * given time. 4113dec9fcdSqs148142 */ 4123dec9fcdSqs148142 if (ring_info->hint[pktbufsz_type] != NO_HINT) { 4133dec9fcdSqs148142 anchor_index = ring_info->hint[pktbufsz_type]; 4143dec9fcdSqs148142 dvma_addr = bufinfo[anchor_index].dvma_addr; 4153dec9fcdSqs148142 chunk_size = bufinfo[anchor_index].buf_size; 4163dec9fcdSqs148142 if ((pktbuf_pp >= dvma_addr) && 4173dec9fcdSqs148142 (pktbuf_pp < (dvma_addr + chunk_size))) { 4183dec9fcdSqs148142 found = B_TRUE; 4193dec9fcdSqs148142 /* 4203dec9fcdSqs148142 * check if this is the last buffer in the block If so, 4213dec9fcdSqs148142 * then reset the hint for the size; 4223dec9fcdSqs148142 */ 4233dec9fcdSqs148142 4243dec9fcdSqs148142 if ((pktbuf_pp + bufsize) >= (dvma_addr + chunk_size)) 4253dec9fcdSqs148142 ring_info->hint[pktbufsz_type] = NO_HINT; 4263dec9fcdSqs148142 } 4273dec9fcdSqs148142 } 4283dec9fcdSqs148142 4293dec9fcdSqs148142 if (found == B_FALSE) { 4303dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 4313dec9fcdSqs148142 "==> hxge_rxbuf_pp_to_vp: (!found)" 4323dec9fcdSqs148142 "buf_pp $%p btype %d anchor_index %d", 4333dec9fcdSqs148142 pkt_buf_addr_pp, pktbufsz_type, anchor_index)); 4343dec9fcdSqs148142 4353dec9fcdSqs148142 /* 4363dec9fcdSqs148142 * This is the first buffer of the block of this size. Need to 4373dec9fcdSqs148142 * search the whole information array. the search algorithm 4383dec9fcdSqs148142 * uses a binary tree search algorithm. It assumes that the 4393dec9fcdSqs148142 * information is already sorted with increasing order info[0] 4403dec9fcdSqs148142 * < info[1] < info[2] .... < info[n-1] where n is the size of 4413dec9fcdSqs148142 * the information array 4423dec9fcdSqs148142 */ 4433dec9fcdSqs148142 r_index = rbr_p->num_blocks - 1; 4443dec9fcdSqs148142 l_index = 0; 4453dec9fcdSqs148142 search_done = B_FALSE; 4463dec9fcdSqs148142 anchor_index = MID_INDEX(r_index, l_index); 4473dec9fcdSqs148142 while (search_done == B_FALSE) { 4483dec9fcdSqs148142 if ((r_index == l_index) || 4493dec9fcdSqs148142 (iteration >= max_iterations)) 4503dec9fcdSqs148142 search_done = B_TRUE; 4513dec9fcdSqs148142 4523dec9fcdSqs148142 end_side = TO_RIGHT; /* to the right */ 4533dec9fcdSqs148142 base_side = TO_LEFT; /* to the left */ 4543dec9fcdSqs148142 /* read the DVMA address information and sort it */ 4553dec9fcdSqs148142 dvma_addr = bufinfo[anchor_index].dvma_addr; 4563dec9fcdSqs148142 chunk_size = bufinfo[anchor_index].buf_size; 4573dec9fcdSqs148142 4583dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 4593dec9fcdSqs148142 "==> hxge_rxbuf_pp_to_vp: (searching)" 4603dec9fcdSqs148142 "buf_pp $%p btype %d " 4613dec9fcdSqs148142 "anchor_index %d chunk_size %d dvmaaddr $%p", 4623dec9fcdSqs148142 pkt_buf_addr_pp, pktbufsz_type, anchor_index, 4633dec9fcdSqs148142 chunk_size, dvma_addr)); 4643dec9fcdSqs148142 4653dec9fcdSqs148142 if (pktbuf_pp >= dvma_addr) 4663dec9fcdSqs148142 base_side = TO_RIGHT; /* to the right */ 4673dec9fcdSqs148142 if (pktbuf_pp < (dvma_addr + chunk_size)) 4683dec9fcdSqs148142 end_side = TO_LEFT; /* to the left */ 4693dec9fcdSqs148142 4703dec9fcdSqs148142 switch (base_side + end_side) { 4713dec9fcdSqs148142 case IN_MIDDLE: 4723dec9fcdSqs148142 /* found */ 4733dec9fcdSqs148142 found = B_TRUE; 4743dec9fcdSqs148142 search_done = B_TRUE; 4753dec9fcdSqs148142 if ((pktbuf_pp + bufsize) < 4763dec9fcdSqs148142 (dvma_addr + chunk_size)) 4773dec9fcdSqs148142 ring_info->hint[pktbufsz_type] = 4783dec9fcdSqs148142 bufinfo[anchor_index].buf_index; 4793dec9fcdSqs148142 break; 4803dec9fcdSqs148142 case BOTH_RIGHT: 4813dec9fcdSqs148142 /* not found: go to the right */ 4823dec9fcdSqs148142 l_index = anchor_index + 1; 4833dec9fcdSqs148142 anchor_index = MID_INDEX(r_index, l_index); 4843dec9fcdSqs148142 break; 4853dec9fcdSqs148142 4863dec9fcdSqs148142 case BOTH_LEFT: 4873dec9fcdSqs148142 /* not found: go to the left */ 4883dec9fcdSqs148142 r_index = anchor_index - 1; 4893dec9fcdSqs148142 anchor_index = MID_INDEX(r_index, l_index); 4903dec9fcdSqs148142 break; 4913dec9fcdSqs148142 default: /* should not come here */ 4923dec9fcdSqs148142 return (HXGE_ERROR); 4933dec9fcdSqs148142 } 4943dec9fcdSqs148142 iteration++; 4953dec9fcdSqs148142 } 4963dec9fcdSqs148142 4973dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 4983dec9fcdSqs148142 "==> hxge_rxbuf_pp_to_vp: (search done)" 4993dec9fcdSqs148142 "buf_pp $%p btype %d anchor_index %d", 5003dec9fcdSqs148142 pkt_buf_addr_pp, pktbufsz_type, anchor_index)); 5013dec9fcdSqs148142 } 5023dec9fcdSqs148142 5033dec9fcdSqs148142 if (found == B_FALSE) { 5043dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 5053dec9fcdSqs148142 "==> hxge_rxbuf_pp_to_vp: (search failed)" 5063dec9fcdSqs148142 "buf_pp $%p btype %d anchor_index %d", 5073dec9fcdSqs148142 pkt_buf_addr_pp, pktbufsz_type, anchor_index)); 5083dec9fcdSqs148142 return (HXGE_ERROR); 5093dec9fcdSqs148142 } 5103dec9fcdSqs148142 5113dec9fcdSqs148142 found_index: 5123dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 5133dec9fcdSqs148142 "==> hxge_rxbuf_pp_to_vp: (FOUND1)" 5143dec9fcdSqs148142 "buf_pp $%p btype %d bufsize %d anchor_index %d", 5153dec9fcdSqs148142 pkt_buf_addr_pp, pktbufsz_type, bufsize, anchor_index)); 5163dec9fcdSqs148142 5173dec9fcdSqs148142 /* index of the first block in this chunk */ 5183dec9fcdSqs148142 chunk_index = bufinfo[anchor_index].start_index; 5193dec9fcdSqs148142 dvma_addr = bufinfo[anchor_index].dvma_addr; 5203dec9fcdSqs148142 page_size_mask = ring_info->block_size_mask; 5213dec9fcdSqs148142 5223dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 5233dec9fcdSqs148142 "==> hxge_rxbuf_pp_to_vp: (FOUND3), get chunk)" 5243dec9fcdSqs148142 "buf_pp $%p btype %d bufsize %d " 5253dec9fcdSqs148142 "anchor_index %d chunk_index %d dvma $%p", 5263dec9fcdSqs148142 pkt_buf_addr_pp, pktbufsz_type, bufsize, 5273dec9fcdSqs148142 anchor_index, chunk_index, dvma_addr)); 5283dec9fcdSqs148142 5293dec9fcdSqs148142 offset = pktbuf_pp - dvma_addr; /* offset within the chunk */ 5303dec9fcdSqs148142 block_size = rbr_p->block_size; /* System block(page) size */ 5313dec9fcdSqs148142 5323dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 5333dec9fcdSqs148142 "==> hxge_rxbuf_pp_to_vp: (FOUND4), get chunk)" 5343dec9fcdSqs148142 "buf_pp $%p btype %d bufsize %d " 5353dec9fcdSqs148142 "anchor_index %d chunk_index %d dvma $%p " 5363dec9fcdSqs148142 "offset %d block_size %d", 5373dec9fcdSqs148142 pkt_buf_addr_pp, pktbufsz_type, bufsize, anchor_index, 5383dec9fcdSqs148142 chunk_index, dvma_addr, offset, block_size)); 5393dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, "==> getting total index")); 5403dec9fcdSqs148142 5413dec9fcdSqs148142 block_index = (offset / block_size); /* index within chunk */ 5423dec9fcdSqs148142 total_index = chunk_index + block_index; 5433dec9fcdSqs148142 5443dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 5453dec9fcdSqs148142 "==> hxge_rxbuf_pp_to_vp: " 5463dec9fcdSqs148142 "total_index %d dvma_addr $%p " 5473dec9fcdSqs148142 "offset %d block_size %d " 5483dec9fcdSqs148142 "block_index %d ", 5493dec9fcdSqs148142 total_index, dvma_addr, offset, block_size, block_index)); 5503dec9fcdSqs148142 551fe930412Sqs148142 #if defined(__i386) 552fe930412Sqs148142 *pkt_buf_addr_p = (uint64_t *)((uint32_t)bufinfo[anchor_index].kaddr + 553fe930412Sqs148142 (uint32_t)offset); 554fe930412Sqs148142 #else 5553dec9fcdSqs148142 *pkt_buf_addr_p = (uint64_t *)((uint64_t)bufinfo[anchor_index].kaddr + 5563dec9fcdSqs148142 offset); 557fe930412Sqs148142 #endif 5583dec9fcdSqs148142 5593dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 5603dec9fcdSqs148142 "==> hxge_rxbuf_pp_to_vp: " 5613dec9fcdSqs148142 "total_index %d dvma_addr $%p " 5623dec9fcdSqs148142 "offset %d block_size %d " 5633dec9fcdSqs148142 "block_index %d " 5643dec9fcdSqs148142 "*pkt_buf_addr_p $%p", 5653dec9fcdSqs148142 total_index, dvma_addr, offset, block_size, 5663dec9fcdSqs148142 block_index, *pkt_buf_addr_p)); 5673dec9fcdSqs148142 5683dec9fcdSqs148142 *msg_index = total_index; 5693dec9fcdSqs148142 *bufoffset = (offset & page_size_mask); 5703dec9fcdSqs148142 5713dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 5723dec9fcdSqs148142 "==> hxge_rxbuf_pp_to_vp: get msg index: " 5733dec9fcdSqs148142 "msg_index %d bufoffset_index %d", 5743dec9fcdSqs148142 *msg_index, *bufoffset)); 5753dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, "<== hxge_rxbuf_pp_to_vp")); 5763dec9fcdSqs148142 5773dec9fcdSqs148142 return (HXGE_OK); 5783dec9fcdSqs148142 } 5793dec9fcdSqs148142 5803dec9fcdSqs148142 5813dec9fcdSqs148142 /* 5823dec9fcdSqs148142 * used by quick sort (qsort) function 5833dec9fcdSqs148142 * to perform comparison 5843dec9fcdSqs148142 */ 5853dec9fcdSqs148142 static int 5863dec9fcdSqs148142 hxge_sort_compare(const void *p1, const void *p2) 5873dec9fcdSqs148142 { 5883dec9fcdSqs148142 5893dec9fcdSqs148142 rxbuf_index_info_t *a, *b; 5903dec9fcdSqs148142 5913dec9fcdSqs148142 a = (rxbuf_index_info_t *)p1; 5923dec9fcdSqs148142 b = (rxbuf_index_info_t *)p2; 5933dec9fcdSqs148142 5943dec9fcdSqs148142 if (a->dvma_addr > b->dvma_addr) 5953dec9fcdSqs148142 return (1); 5963dec9fcdSqs148142 if (a->dvma_addr < b->dvma_addr) 5973dec9fcdSqs148142 return (-1); 5983dec9fcdSqs148142 return (0); 5993dec9fcdSqs148142 } 6003dec9fcdSqs148142 6013dec9fcdSqs148142 /* 6023dec9fcdSqs148142 * Grabbed this sort implementation from common/syscall/avl.c 6033dec9fcdSqs148142 * 6043dec9fcdSqs148142 * Generic shellsort, from K&R (1st ed, p 58.), somewhat modified. 6053dec9fcdSqs148142 * v = Ptr to array/vector of objs 6063dec9fcdSqs148142 * n = # objs in the array 6073dec9fcdSqs148142 * s = size of each obj (must be multiples of a word size) 6083dec9fcdSqs148142 * f = ptr to function to compare two objs 6093dec9fcdSqs148142 * returns (-1 = less than, 0 = equal, 1 = greater than 6103dec9fcdSqs148142 */ 6113dec9fcdSqs148142 void 6123dec9fcdSqs148142 hxge_ksort(caddr_t v, int n, int s, int (*f) ()) 6133dec9fcdSqs148142 { 6143dec9fcdSqs148142 int g, i, j, ii; 6153dec9fcdSqs148142 unsigned int *p1, *p2; 6163dec9fcdSqs148142 unsigned int tmp; 6173dec9fcdSqs148142 6183dec9fcdSqs148142 /* No work to do */ 6193dec9fcdSqs148142 if (v == NULL || n <= 1) 6203dec9fcdSqs148142 return; 6213dec9fcdSqs148142 /* Sanity check on arguments */ 6223dec9fcdSqs148142 ASSERT(((uintptr_t)v & 0x3) == 0 && (s & 0x3) == 0); 6233dec9fcdSqs148142 ASSERT(s > 0); 6243dec9fcdSqs148142 6253dec9fcdSqs148142 for (g = n / 2; g > 0; g /= 2) { 6263dec9fcdSqs148142 for (i = g; i < n; i++) { 6273dec9fcdSqs148142 for (j = i - g; j >= 0 && 6283dec9fcdSqs148142 (*f) (v + j * s, v + (j + g) * s) == 1; j -= g) { 6293dec9fcdSqs148142 p1 = (unsigned *)(v + j * s); 6303dec9fcdSqs148142 p2 = (unsigned *)(v + (j + g) * s); 6313dec9fcdSqs148142 for (ii = 0; ii < s / 4; ii++) { 6323dec9fcdSqs148142 tmp = *p1; 6333dec9fcdSqs148142 *p1++ = *p2; 6343dec9fcdSqs148142 *p2++ = tmp; 6353dec9fcdSqs148142 } 6363dec9fcdSqs148142 } 6373dec9fcdSqs148142 } 6383dec9fcdSqs148142 } 6393dec9fcdSqs148142 } 6403dec9fcdSqs148142 6413dec9fcdSqs148142 /* 6423dec9fcdSqs148142 * Initialize data structures required for rxdma 6433dec9fcdSqs148142 * buffer dvma->vmem address lookup 6443dec9fcdSqs148142 */ 6453dec9fcdSqs148142 /*ARGSUSED*/ 6463dec9fcdSqs148142 static hxge_status_t 6473dec9fcdSqs148142 hxge_rxbuf_index_info_init(p_hxge_t hxgep, p_rx_rbr_ring_t rbrp) 6483dec9fcdSqs148142 { 6493dec9fcdSqs148142 int index; 6503dec9fcdSqs148142 rxring_info_t *ring_info; 6513dec9fcdSqs148142 int max_iteration = 0, max_index = 0; 6523dec9fcdSqs148142 6533dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_rxbuf_index_info_init")); 6543dec9fcdSqs148142 6553dec9fcdSqs148142 ring_info = rbrp->ring_info; 6563dec9fcdSqs148142 ring_info->hint[0] = NO_HINT; 6573dec9fcdSqs148142 ring_info->hint[1] = NO_HINT; 6583dec9fcdSqs148142 ring_info->hint[2] = NO_HINT; 659f043ebedSMichael Speer ring_info->hint[3] = NO_HINT; 6603dec9fcdSqs148142 max_index = rbrp->num_blocks; 6613dec9fcdSqs148142 6623dec9fcdSqs148142 /* read the DVMA address information and sort it */ 6633dec9fcdSqs148142 /* do init of the information array */ 6643dec9fcdSqs148142 6653dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA2_CTL, 6663dec9fcdSqs148142 " hxge_rxbuf_index_info_init Sort ptrs")); 6673dec9fcdSqs148142 6683dec9fcdSqs148142 /* sort the array */ 6693dec9fcdSqs148142 hxge_ksort((void *) ring_info->buffer, max_index, 6703dec9fcdSqs148142 sizeof (rxbuf_index_info_t), hxge_sort_compare); 6713dec9fcdSqs148142 6723dec9fcdSqs148142 for (index = 0; index < max_index; index++) { 6733dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA2_CTL, 6743dec9fcdSqs148142 " hxge_rxbuf_index_info_init: sorted chunk %d " 6753dec9fcdSqs148142 " ioaddr $%p kaddr $%p size %x", 6763dec9fcdSqs148142 index, ring_info->buffer[index].dvma_addr, 6773dec9fcdSqs148142 ring_info->buffer[index].kaddr, 6783dec9fcdSqs148142 ring_info->buffer[index].buf_size)); 6793dec9fcdSqs148142 } 6803dec9fcdSqs148142 6813dec9fcdSqs148142 max_iteration = 0; 6823dec9fcdSqs148142 while (max_index >= (1ULL << max_iteration)) 6833dec9fcdSqs148142 max_iteration++; 6843dec9fcdSqs148142 ring_info->max_iterations = max_iteration + 1; 6853dec9fcdSqs148142 6863dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA2_CTL, 6873dec9fcdSqs148142 " hxge_rxbuf_index_info_init Find max iter %d", 6883dec9fcdSqs148142 ring_info->max_iterations)); 6893dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_rxbuf_index_info_init")); 6903dec9fcdSqs148142 6913dec9fcdSqs148142 return (HXGE_OK); 6923dec9fcdSqs148142 } 6933dec9fcdSqs148142 6943dec9fcdSqs148142 /*ARGSUSED*/ 6953dec9fcdSqs148142 void 6963dec9fcdSqs148142 hxge_dump_rcr_entry(p_hxge_t hxgep, p_rcr_entry_t entry_p) 6973dec9fcdSqs148142 { 6983dec9fcdSqs148142 #ifdef HXGE_DEBUG 6993dec9fcdSqs148142 7003dec9fcdSqs148142 uint32_t bptr; 7013dec9fcdSqs148142 uint64_t pp; 7023dec9fcdSqs148142 7033dec9fcdSqs148142 bptr = entry_p->bits.pkt_buf_addr; 7043dec9fcdSqs148142 7053dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 7063dec9fcdSqs148142 "\trcr entry $%p " 7073dec9fcdSqs148142 "\trcr entry 0x%0llx " 7083dec9fcdSqs148142 "\trcr entry 0x%08x " 7093dec9fcdSqs148142 "\trcr entry 0x%08x " 7103dec9fcdSqs148142 "\tvalue 0x%0llx\n" 7113dec9fcdSqs148142 "\tmulti = %d\n" 7123dec9fcdSqs148142 "\tpkt_type = 0x%x\n" 7133dec9fcdSqs148142 "\terror = 0x%04x\n" 7143dec9fcdSqs148142 "\tl2_len = %d\n" 7153dec9fcdSqs148142 "\tpktbufsize = %d\n" 7163dec9fcdSqs148142 "\tpkt_buf_addr = $%p\n" 7173dec9fcdSqs148142 "\tpkt_buf_addr (<< 6) = $%p\n", 7183dec9fcdSqs148142 entry_p, 7193dec9fcdSqs148142 *(int64_t *)entry_p, 7203dec9fcdSqs148142 *(int32_t *)entry_p, 7213dec9fcdSqs148142 *(int32_t *)((char *)entry_p + 32), 7223dec9fcdSqs148142 entry_p->value, 7233dec9fcdSqs148142 entry_p->bits.multi, 7243dec9fcdSqs148142 entry_p->bits.pkt_type, 7253dec9fcdSqs148142 entry_p->bits.error, 7263dec9fcdSqs148142 entry_p->bits.l2_len, 7273dec9fcdSqs148142 entry_p->bits.pktbufsz, 7283dec9fcdSqs148142 bptr, 729fe930412Sqs148142 entry_p->bits.pkt_buf_addr_l)); 7303dec9fcdSqs148142 7313dec9fcdSqs148142 pp = (entry_p->value & RCR_PKT_BUF_ADDR_MASK) << 7323dec9fcdSqs148142 RCR_PKT_BUF_ADDR_SHIFT; 7333dec9fcdSqs148142 7343dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "rcr pp 0x%llx l2 len %d", 7353dec9fcdSqs148142 pp, (*(int64_t *)entry_p >> 40) & 0x3fff)); 7363dec9fcdSqs148142 #endif 7373dec9fcdSqs148142 } 7383dec9fcdSqs148142 7393dec9fcdSqs148142 /*ARGSUSED*/ 7403dec9fcdSqs148142 void 7413dec9fcdSqs148142 hxge_rxdma_stop(p_hxge_t hxgep) 7423dec9fcdSqs148142 { 7433dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_rxdma_stop")); 7443dec9fcdSqs148142 7456ffca240SMichael Speer MUTEX_ENTER(&hxgep->vmac_lock); 7463dec9fcdSqs148142 (void) hxge_rx_vmac_disable(hxgep); 7473dec9fcdSqs148142 (void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_STOP); 7486ffca240SMichael Speer MUTEX_EXIT(&hxgep->vmac_lock); 7493dec9fcdSqs148142 7503dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "<== hxge_rxdma_stop")); 7513dec9fcdSqs148142 } 7523dec9fcdSqs148142 7533dec9fcdSqs148142 void 7543dec9fcdSqs148142 hxge_rxdma_stop_reinit(p_hxge_t hxgep) 7553dec9fcdSqs148142 { 7563dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_rxdma_stop_reinit")); 7573dec9fcdSqs148142 7583dec9fcdSqs148142 (void) hxge_rxdma_stop(hxgep); 7593dec9fcdSqs148142 (void) hxge_uninit_rxdma_channels(hxgep); 7603dec9fcdSqs148142 (void) hxge_init_rxdma_channels(hxgep); 7613dec9fcdSqs148142 7626ffca240SMichael Speer MUTEX_ENTER(&hxgep->vmac_lock); 7633dec9fcdSqs148142 (void) hxge_rx_vmac_enable(hxgep); 7646ffca240SMichael Speer MUTEX_EXIT(&hxgep->vmac_lock); 7653dec9fcdSqs148142 7663dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "<== hxge_rxdma_stop_reinit")); 7673dec9fcdSqs148142 } 7683dec9fcdSqs148142 7693dec9fcdSqs148142 hxge_status_t 7703dec9fcdSqs148142 hxge_rxdma_hw_mode(p_hxge_t hxgep, boolean_t enable) 7713dec9fcdSqs148142 { 7723dec9fcdSqs148142 int i, ndmas; 7733dec9fcdSqs148142 uint16_t channel; 7743dec9fcdSqs148142 p_rx_rbr_rings_t rx_rbr_rings; 7753dec9fcdSqs148142 p_rx_rbr_ring_t *rbr_rings; 7763dec9fcdSqs148142 hpi_handle_t handle; 7773dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 7783dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 7793dec9fcdSqs148142 7803dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 7813dec9fcdSqs148142 "==> hxge_rxdma_hw_mode: mode %d", enable)); 7823dec9fcdSqs148142 7833dec9fcdSqs148142 if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 7843dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 7853dec9fcdSqs148142 "<== hxge_rxdma_mode: not initialized")); 7863dec9fcdSqs148142 return (HXGE_ERROR); 7873dec9fcdSqs148142 } 7883dec9fcdSqs148142 7893dec9fcdSqs148142 rx_rbr_rings = hxgep->rx_rbr_rings; 7903dec9fcdSqs148142 if (rx_rbr_rings == NULL) { 7913dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 7923dec9fcdSqs148142 "<== hxge_rxdma_mode: NULL ring pointer")); 7933dec9fcdSqs148142 return (HXGE_ERROR); 7943dec9fcdSqs148142 } 7953dec9fcdSqs148142 7963dec9fcdSqs148142 if (rx_rbr_rings->rbr_rings == NULL) { 7973dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 7983dec9fcdSqs148142 "<== hxge_rxdma_mode: NULL rbr rings pointer")); 7993dec9fcdSqs148142 return (HXGE_ERROR); 8003dec9fcdSqs148142 } 8013dec9fcdSqs148142 8023dec9fcdSqs148142 ndmas = rx_rbr_rings->ndmas; 8033dec9fcdSqs148142 if (!ndmas) { 8043dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 8053dec9fcdSqs148142 "<== hxge_rxdma_mode: no channel")); 8063dec9fcdSqs148142 return (HXGE_ERROR); 8073dec9fcdSqs148142 } 8083dec9fcdSqs148142 8093dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 8103dec9fcdSqs148142 "==> hxge_rxdma_mode (ndmas %d)", ndmas)); 8113dec9fcdSqs148142 8123dec9fcdSqs148142 rbr_rings = rx_rbr_rings->rbr_rings; 8133dec9fcdSqs148142 8143dec9fcdSqs148142 handle = HXGE_DEV_HPI_HANDLE(hxgep); 8153dec9fcdSqs148142 8163dec9fcdSqs148142 for (i = 0; i < ndmas; i++) { 8173dec9fcdSqs148142 if (rbr_rings == NULL || rbr_rings[i] == NULL) { 8183dec9fcdSqs148142 continue; 8193dec9fcdSqs148142 } 8203dec9fcdSqs148142 channel = rbr_rings[i]->rdc; 8213dec9fcdSqs148142 if (enable) { 8223dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 8233dec9fcdSqs148142 "==> hxge_rxdma_hw_mode: channel %d (enable)", 8243dec9fcdSqs148142 channel)); 8253dec9fcdSqs148142 rs = hpi_rxdma_cfg_rdc_enable(handle, channel); 8263dec9fcdSqs148142 } else { 8273dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 8283dec9fcdSqs148142 "==> hxge_rxdma_hw_mode: channel %d (disable)", 8293dec9fcdSqs148142 channel)); 8303dec9fcdSqs148142 rs = hpi_rxdma_cfg_rdc_disable(handle, channel); 8313dec9fcdSqs148142 } 8323dec9fcdSqs148142 } 8333dec9fcdSqs148142 8343dec9fcdSqs148142 status = ((rs == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR | rs); 8353dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 8363dec9fcdSqs148142 "<== hxge_rxdma_hw_mode: status 0x%x", status)); 8373dec9fcdSqs148142 8383dec9fcdSqs148142 return (status); 8393dec9fcdSqs148142 } 8403dec9fcdSqs148142 8413dec9fcdSqs148142 /* 8423dec9fcdSqs148142 * Static functions start here. 8433dec9fcdSqs148142 */ 8443dec9fcdSqs148142 static p_rx_msg_t 8453dec9fcdSqs148142 hxge_allocb(size_t size, uint32_t pri, p_hxge_dma_common_t dmabuf_p) 8463dec9fcdSqs148142 { 8473dec9fcdSqs148142 p_rx_msg_t hxge_mp = NULL; 8483dec9fcdSqs148142 p_hxge_dma_common_t dmamsg_p; 8493dec9fcdSqs148142 uchar_t *buffer; 8503dec9fcdSqs148142 8513dec9fcdSqs148142 hxge_mp = KMEM_ZALLOC(sizeof (rx_msg_t), KM_NOSLEEP); 8523dec9fcdSqs148142 if (hxge_mp == NULL) { 8533dec9fcdSqs148142 HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, 8543dec9fcdSqs148142 "Allocation of a rx msg failed.")); 8553dec9fcdSqs148142 goto hxge_allocb_exit; 8563dec9fcdSqs148142 } 8573dec9fcdSqs148142 8583dec9fcdSqs148142 hxge_mp->use_buf_pool = B_FALSE; 8593dec9fcdSqs148142 if (dmabuf_p) { 8603dec9fcdSqs148142 hxge_mp->use_buf_pool = B_TRUE; 8613dec9fcdSqs148142 8623dec9fcdSqs148142 dmamsg_p = (p_hxge_dma_common_t)&hxge_mp->buf_dma; 8633dec9fcdSqs148142 *dmamsg_p = *dmabuf_p; 8643dec9fcdSqs148142 dmamsg_p->nblocks = 1; 8653dec9fcdSqs148142 dmamsg_p->block_size = size; 8663dec9fcdSqs148142 dmamsg_p->alength = size; 8673dec9fcdSqs148142 buffer = (uchar_t *)dmabuf_p->kaddrp; 8683dec9fcdSqs148142 8693dec9fcdSqs148142 dmabuf_p->kaddrp = (void *)((char *)dmabuf_p->kaddrp + size); 8703dec9fcdSqs148142 dmabuf_p->ioaddr_pp = (void *) 8713dec9fcdSqs148142 ((char *)dmabuf_p->ioaddr_pp + size); 8723dec9fcdSqs148142 8733dec9fcdSqs148142 dmabuf_p->alength -= size; 8743dec9fcdSqs148142 dmabuf_p->offset += size; 8753dec9fcdSqs148142 dmabuf_p->dma_cookie.dmac_laddress += size; 8763dec9fcdSqs148142 dmabuf_p->dma_cookie.dmac_size -= size; 8773dec9fcdSqs148142 } else { 8783dec9fcdSqs148142 buffer = KMEM_ALLOC(size, KM_NOSLEEP); 8793dec9fcdSqs148142 if (buffer == NULL) { 8803dec9fcdSqs148142 HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, 8813dec9fcdSqs148142 "Allocation of a receive page failed.")); 8823dec9fcdSqs148142 goto hxge_allocb_fail1; 8833dec9fcdSqs148142 } 8843dec9fcdSqs148142 } 8853dec9fcdSqs148142 8863dec9fcdSqs148142 hxge_mp->rx_mblk_p = desballoc(buffer, size, pri, &hxge_mp->freeb); 8873dec9fcdSqs148142 if (hxge_mp->rx_mblk_p == NULL) { 8883dec9fcdSqs148142 HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, "desballoc failed.")); 8893dec9fcdSqs148142 goto hxge_allocb_fail2; 8903dec9fcdSqs148142 } 8913dec9fcdSqs148142 hxge_mp->buffer = buffer; 8923dec9fcdSqs148142 hxge_mp->block_size = size; 8933dec9fcdSqs148142 hxge_mp->freeb.free_func = (void (*) ()) hxge_freeb; 8943dec9fcdSqs148142 hxge_mp->freeb.free_arg = (caddr_t)hxge_mp; 8953dec9fcdSqs148142 hxge_mp->ref_cnt = 1; 8963dec9fcdSqs148142 hxge_mp->free = B_TRUE; 8973dec9fcdSqs148142 hxge_mp->rx_use_bcopy = B_FALSE; 8983dec9fcdSqs148142 899dc10a9c2SMichael Speer atomic_inc_32(&hxge_mblks_pending); 9003dec9fcdSqs148142 9013dec9fcdSqs148142 goto hxge_allocb_exit; 9023dec9fcdSqs148142 9033dec9fcdSqs148142 hxge_allocb_fail2: 9043dec9fcdSqs148142 if (!hxge_mp->use_buf_pool) { 9053dec9fcdSqs148142 KMEM_FREE(buffer, size); 9063dec9fcdSqs148142 } 9073dec9fcdSqs148142 hxge_allocb_fail1: 9083dec9fcdSqs148142 KMEM_FREE(hxge_mp, sizeof (rx_msg_t)); 9093dec9fcdSqs148142 hxge_mp = NULL; 9103dec9fcdSqs148142 9113dec9fcdSqs148142 hxge_allocb_exit: 9123dec9fcdSqs148142 return (hxge_mp); 9133dec9fcdSqs148142 } 9143dec9fcdSqs148142 9153dec9fcdSqs148142 p_mblk_t 9163dec9fcdSqs148142 hxge_dupb(p_rx_msg_t hxge_mp, uint_t offset, size_t size) 9173dec9fcdSqs148142 { 9183dec9fcdSqs148142 p_mblk_t mp; 9193dec9fcdSqs148142 9203dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, MEM_CTL, "==> hxge_dupb")); 9213dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, MEM_CTL, "hxge_mp = $%p " 9223dec9fcdSqs148142 "offset = 0x%08X " "size = 0x%08X", hxge_mp, offset, size)); 9233dec9fcdSqs148142 9243dec9fcdSqs148142 mp = desballoc(&hxge_mp->buffer[offset], size, 0, &hxge_mp->freeb); 9253dec9fcdSqs148142 if (mp == NULL) { 9263dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, RX_CTL, "desballoc failed")); 9273dec9fcdSqs148142 goto hxge_dupb_exit; 9283dec9fcdSqs148142 } 9293dec9fcdSqs148142 9303dec9fcdSqs148142 atomic_inc_32(&hxge_mp->ref_cnt); 9313dec9fcdSqs148142 9323dec9fcdSqs148142 hxge_dupb_exit: 9333dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, MEM_CTL, "<== hxge_dupb mp = $%p", hxge_mp)); 9343dec9fcdSqs148142 return (mp); 9353dec9fcdSqs148142 } 9363dec9fcdSqs148142 9373dec9fcdSqs148142 p_mblk_t 9383dec9fcdSqs148142 hxge_dupb_bcopy(p_rx_msg_t hxge_mp, uint_t offset, size_t size) 9393dec9fcdSqs148142 { 9403dec9fcdSqs148142 p_mblk_t mp; 9413dec9fcdSqs148142 uchar_t *dp; 9423dec9fcdSqs148142 9433dec9fcdSqs148142 mp = allocb(size + HXGE_RXBUF_EXTRA, 0); 9443dec9fcdSqs148142 if (mp == NULL) { 9453dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, RX_CTL, "desballoc failed")); 9463dec9fcdSqs148142 goto hxge_dupb_bcopy_exit; 9473dec9fcdSqs148142 } 9483dec9fcdSqs148142 dp = mp->b_rptr = mp->b_rptr + HXGE_RXBUF_EXTRA; 9493dec9fcdSqs148142 bcopy((void *) &hxge_mp->buffer[offset], dp, size); 9503dec9fcdSqs148142 mp->b_wptr = dp + size; 9513dec9fcdSqs148142 9523dec9fcdSqs148142 hxge_dupb_bcopy_exit: 9533dec9fcdSqs148142 9543dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, MEM_CTL, "<== hxge_dupb mp = $%p", hxge_mp)); 9553dec9fcdSqs148142 9563dec9fcdSqs148142 return (mp); 9573dec9fcdSqs148142 } 9583dec9fcdSqs148142 9593dec9fcdSqs148142 void hxge_post_page(p_hxge_t hxgep, p_rx_rbr_ring_t rx_rbr_p, 9603dec9fcdSqs148142 p_rx_msg_t rx_msg_p); 9613dec9fcdSqs148142 9623dec9fcdSqs148142 void 9633dec9fcdSqs148142 hxge_post_page(p_hxge_t hxgep, p_rx_rbr_ring_t rx_rbr_p, p_rx_msg_t rx_msg_p) 9643dec9fcdSqs148142 { 9653dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_post_page")); 9663dec9fcdSqs148142 9673dec9fcdSqs148142 /* Reuse this buffer */ 9683dec9fcdSqs148142 rx_msg_p->free = B_FALSE; 9693dec9fcdSqs148142 rx_msg_p->cur_usage_cnt = 0; 9703dec9fcdSqs148142 rx_msg_p->max_usage_cnt = 0; 9713dec9fcdSqs148142 rx_msg_p->pkt_buf_size = 0; 9723dec9fcdSqs148142 9733dec9fcdSqs148142 if (rx_rbr_p->rbr_use_bcopy) { 9743dec9fcdSqs148142 rx_msg_p->rx_use_bcopy = B_FALSE; 9753dec9fcdSqs148142 atomic_dec_32(&rx_rbr_p->rbr_consumed); 9763dec9fcdSqs148142 } 97757c5371aSQiyan Sun - Sun Microsystems - San Diego United States atomic_dec_32(&rx_rbr_p->rbr_used); 9783dec9fcdSqs148142 9793dec9fcdSqs148142 /* 9803dec9fcdSqs148142 * Get the rbr header pointer and its offset index. 9813dec9fcdSqs148142 */ 9823dec9fcdSqs148142 rx_rbr_p->rbr_wr_index = ((rx_rbr_p->rbr_wr_index + 1) & 9833dec9fcdSqs148142 rx_rbr_p->rbr_wrap_mask); 9843dec9fcdSqs148142 rx_rbr_p->rbr_desc_vp[rx_rbr_p->rbr_wr_index] = rx_msg_p->shifted_addr; 9853dec9fcdSqs148142 986b83cd2c3SMichael Speer /* 987b83cd2c3SMichael Speer * Accumulate some buffers in the ring before re-enabling the 988b83cd2c3SMichael Speer * DMA channel, if rbr empty was signaled. 989b83cd2c3SMichael Speer */ 9901c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States hpi_rxdma_rdc_rbr_kick(HXGE_DEV_HPI_HANDLE(hxgep), rx_rbr_p->rdc, 1); 991f043ebedSMichael Speer if (rx_rbr_p->rbr_is_empty && (rx_rbr_p->rbb_max - 992f043ebedSMichael Speer rx_rbr_p->rbr_used) >= HXGE_RBR_EMPTY_THRESHOLD) { 9931c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States hxge_rbr_empty_restore(hxgep, rx_rbr_p); 994b83cd2c3SMichael Speer } 9953a109ad9SQiyan Sun - Sun Microsystems - San Diego United States 9963dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 9973dec9fcdSqs148142 "<== hxge_post_page (channel %d post_next_index %d)", 9983dec9fcdSqs148142 rx_rbr_p->rdc, rx_rbr_p->rbr_wr_index)); 9993dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "<== hxge_post_page")); 10003dec9fcdSqs148142 } 10013dec9fcdSqs148142 10023dec9fcdSqs148142 void 10033dec9fcdSqs148142 hxge_freeb(p_rx_msg_t rx_msg_p) 10043dec9fcdSqs148142 { 10053dec9fcdSqs148142 size_t size; 10063dec9fcdSqs148142 uchar_t *buffer = NULL; 10073dec9fcdSqs148142 int ref_cnt; 10083dec9fcdSqs148142 boolean_t free_state = B_FALSE; 10093dec9fcdSqs148142 rx_rbr_ring_t *ring = rx_msg_p->rx_rbr_p; 10103dec9fcdSqs148142 10113dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, MEM2_CTL, "==> hxge_freeb")); 10123dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, MEM2_CTL, 10133dec9fcdSqs148142 "hxge_freeb:rx_msg_p = $%p (block pending %d)", 10143dec9fcdSqs148142 rx_msg_p, hxge_mblks_pending)); 10153dec9fcdSqs148142 1016fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States if (ring == NULL) 1017fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States return; 1018fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States 1019fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States /* 1020fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States * This is to prevent posting activities while we are recovering 1021fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States * from fatal errors. This should not be a performance drag since 1022fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States * ref_cnt != 0 most times. 1023fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States */ 102414648441SQiyan Sun - Sun Microsystems - San Diego United States if (ring->rbr_state == RBR_POSTING) 1025fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States MUTEX_ENTER(&ring->post_lock); 1026fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States 10273dec9fcdSqs148142 /* 10283dec9fcdSqs148142 * First we need to get the free state, then 10293dec9fcdSqs148142 * atomic decrement the reference count to prevent 10303dec9fcdSqs148142 * the race condition with the interrupt thread that 10313dec9fcdSqs148142 * is processing a loaned up buffer block. 10323dec9fcdSqs148142 */ 10333dec9fcdSqs148142 free_state = rx_msg_p->free; 1034*1a5e258fSJosef 'Jeff' Sipek ref_cnt = atomic_dec_32_nv(&rx_msg_p->ref_cnt); 10353dec9fcdSqs148142 if (!ref_cnt) { 1036dc10a9c2SMichael Speer atomic_dec_32(&hxge_mblks_pending); 1037dc10a9c2SMichael Speer 10383dec9fcdSqs148142 buffer = rx_msg_p->buffer; 10393dec9fcdSqs148142 size = rx_msg_p->block_size; 10403dec9fcdSqs148142 10413dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, MEM2_CTL, "hxge_freeb: " 10423dec9fcdSqs148142 "will free: rx_msg_p = $%p (block pending %d)", 10433dec9fcdSqs148142 rx_msg_p, hxge_mblks_pending)); 10443dec9fcdSqs148142 10453dec9fcdSqs148142 if (!rx_msg_p->use_buf_pool) { 10463dec9fcdSqs148142 KMEM_FREE(buffer, size); 10473dec9fcdSqs148142 } 10483dec9fcdSqs148142 10493dec9fcdSqs148142 KMEM_FREE(rx_msg_p, sizeof (rx_msg_t)); 10501667122dSMichael Speer /* 10511667122dSMichael Speer * Decrement the receive buffer ring's reference 10521667122dSMichael Speer * count, too. 10531667122dSMichael Speer */ 10543dec9fcdSqs148142 atomic_dec_32(&ring->rbr_ref_cnt); 10553dec9fcdSqs148142 10563dec9fcdSqs148142 /* 10573dec9fcdSqs148142 * Free the receive buffer ring, iff 10583dec9fcdSqs148142 * 1. all the receive buffers have been freed 10593dec9fcdSqs148142 * 2. and we are in the proper state (that is, 10603dec9fcdSqs148142 * we are not UNMAPPING). 10613dec9fcdSqs148142 */ 10621667122dSMichael Speer if (ring->rbr_ref_cnt == 0 && 10631667122dSMichael Speer ring->rbr_state == RBR_UNMAPPED) { 10643dec9fcdSqs148142 KMEM_FREE(ring, sizeof (*ring)); 106514648441SQiyan Sun - Sun Microsystems - San Diego United States /* post_lock has been destroyed already */ 106614648441SQiyan Sun - Sun Microsystems - San Diego United States return; 10673dec9fcdSqs148142 } 10681667122dSMichael Speer } 10693dec9fcdSqs148142 10703dec9fcdSqs148142 /* 10713dec9fcdSqs148142 * Repost buffer. 10723dec9fcdSqs148142 */ 1073fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States if (free_state && (ref_cnt == 1)) { 10743dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, RX_CTL, 10753dec9fcdSqs148142 "hxge_freeb: post page $%p:", rx_msg_p)); 10763dec9fcdSqs148142 if (ring->rbr_state == RBR_POSTING) 10773dec9fcdSqs148142 hxge_post_page(rx_msg_p->hxgep, ring, rx_msg_p); 10783dec9fcdSqs148142 } 10793dec9fcdSqs148142 108014648441SQiyan Sun - Sun Microsystems - San Diego United States if (ring->rbr_state == RBR_POSTING) 1081fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States MUTEX_EXIT(&ring->post_lock); 1082fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States 10833dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, MEM2_CTL, "<== hxge_freeb")); 10843dec9fcdSqs148142 } 10853dec9fcdSqs148142 10863dec9fcdSqs148142 uint_t 10873dec9fcdSqs148142 hxge_rx_intr(caddr_t arg1, caddr_t arg2) 10883dec9fcdSqs148142 { 10891ed83081SMichael Speer p_hxge_ring_handle_t rhp; 10903dec9fcdSqs148142 p_hxge_ldv_t ldvp = (p_hxge_ldv_t)arg1; 10913dec9fcdSqs148142 p_hxge_t hxgep = (p_hxge_t)arg2; 10923dec9fcdSqs148142 p_hxge_ldg_t ldgp; 10933dec9fcdSqs148142 uint8_t channel; 10943dec9fcdSqs148142 hpi_handle_t handle; 109541307000SQiyan Sun - Sun Microsystems - San Diego United States rdc_stat_t cs; 10961ed83081SMichael Speer p_rx_rcr_ring_t ring; 1097f043ebedSMichael Speer p_rx_rbr_ring_t rbrp; 10984d9de298SMichael Speer mblk_t *mp = NULL; 10993dec9fcdSqs148142 11003dec9fcdSqs148142 if (ldvp == NULL) { 11013dec9fcdSqs148142 HXGE_DEBUG_MSG((NULL, RX_INT_CTL, 11023dec9fcdSqs148142 "<== hxge_rx_intr: arg2 $%p arg1 $%p", hxgep, ldvp)); 1103dc10a9c2SMichael Speer return (DDI_INTR_UNCLAIMED); 11043dec9fcdSqs148142 } 11053dec9fcdSqs148142 11063dec9fcdSqs148142 if (arg2 == NULL || (void *) ldvp->hxgep != arg2) { 11073dec9fcdSqs148142 hxgep = ldvp->hxgep; 11083dec9fcdSqs148142 } 11093dec9fcdSqs148142 11103dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_INT_CTL, 11113dec9fcdSqs148142 "==> hxge_rx_intr: arg2 $%p arg1 $%p", hxgep, ldvp)); 11123dec9fcdSqs148142 11133dec9fcdSqs148142 /* 11143dec9fcdSqs148142 * This interrupt handler is for a specific receive dma channel. 11153dec9fcdSqs148142 */ 11163dec9fcdSqs148142 handle = HXGE_DEV_HPI_HANDLE(hxgep); 11173dec9fcdSqs148142 11183dec9fcdSqs148142 /* 11193dec9fcdSqs148142 * Get the control and status for this channel. 11203dec9fcdSqs148142 */ 11211ed83081SMichael Speer channel = ldvp->vdma_index; 11221ed83081SMichael Speer ring = hxgep->rx_rcr_rings->rcr_rings[channel]; 11231ed83081SMichael Speer rhp = &hxgep->rx_ring_handles[channel]; 11244d9de298SMichael Speer ldgp = ldvp->ldgp; 11254d9de298SMichael Speer 11264d9de298SMichael Speer ASSERT(ring != NULL); 1127f043ebedSMichael Speer #if defined(DEBUG) 1128f043ebedSMichael Speer if (rhp->started) { 11294d9de298SMichael Speer ASSERT(ring->ldgp == ldgp); 11304d9de298SMichael Speer ASSERT(ring->ldvp == ldvp); 1131f043ebedSMichael Speer } 1132f043ebedSMichael Speer #endif 11331ed83081SMichael Speer 11341ed83081SMichael Speer MUTEX_ENTER(&ring->lock); 11351ed83081SMichael Speer 11366ffca240SMichael Speer if (!ring->poll_flag) { 11373dec9fcdSqs148142 RXDMA_REG_READ64(handle, RDC_STAT, channel, &cs.value); 1138676f0400SMichael Speer cs.bits.ptrread = 0; 1139676f0400SMichael Speer cs.bits.pktread = 0; 1140676f0400SMichael Speer RXDMA_REG_WRITE64(handle, RDC_STAT, channel, cs.value); 11413dec9fcdSqs148142 11424d9de298SMichael Speer /* 11436ffca240SMichael Speer * Process packets, if we are not in polling mode, the ring is 11446ffca240SMichael Speer * started and the interface is started. The MAC layer under 11456ffca240SMichael Speer * load will be operating in polling mode for RX traffic. 11464d9de298SMichael Speer */ 11476ffca240SMichael Speer if ((rhp->started) && 11486ffca240SMichael Speer (hxgep->hxge_mac_state == HXGE_MAC_STARTED)) { 11496ffca240SMichael Speer mp = hxge_rx_pkts(hxgep, ldvp->vdma_index, 11506ffca240SMichael Speer ldvp, ring, cs, -1); 11514d9de298SMichael Speer } 11523dec9fcdSqs148142 11536ffca240SMichael Speer /* Process error events. */ 11543dec9fcdSqs148142 if (cs.value & RDC_STAT_ERROR) { 11556ffca240SMichael Speer MUTEX_EXIT(&ring->lock); 11566ffca240SMichael Speer (void) hxge_rx_err_evnts(hxgep, channel, ldvp, cs); 11576ffca240SMichael Speer MUTEX_ENTER(&ring->lock); 11583dec9fcdSqs148142 } 11593dec9fcdSqs148142 11603dec9fcdSqs148142 /* 11616ffca240SMichael Speer * Enable the mailbox update interrupt if we want to use 11626ffca240SMichael Speer * mailbox. We probably don't need to use mailbox as it only 11636ffca240SMichael Speer * saves us one pio read. Also write 1 to rcrthres and 11646ffca240SMichael Speer * rcrto to clear these two edge triggered bits. 11653dec9fcdSqs148142 */ 1166f043ebedSMichael Speer rbrp = hxgep->rx_rbr_rings->rbr_rings[channel]; 1167f043ebedSMichael Speer MUTEX_ENTER(&rbrp->post_lock); 1168f043ebedSMichael Speer if (!rbrp->rbr_is_empty) { 1169f043ebedSMichael Speer cs.value = 0; 117041307000SQiyan Sun - Sun Microsystems - San Diego United States cs.bits.mex = 1; 117141307000SQiyan Sun - Sun Microsystems - San Diego United States cs.bits.ptrread = 0; 117241307000SQiyan Sun - Sun Microsystems - San Diego United States cs.bits.pktread = 0; 117341307000SQiyan Sun - Sun Microsystems - San Diego United States RXDMA_REG_WRITE64(handle, RDC_STAT, channel, cs.value); 1174f043ebedSMichael Speer } 1175f043ebedSMichael Speer MUTEX_EXIT(&rbrp->post_lock); 11763dec9fcdSqs148142 11771ed83081SMichael Speer if (ldgp->nldvs == 1) { 11786ffca240SMichael Speer /* 11796ffca240SMichael Speer * Re-arm the group. 11806ffca240SMichael Speer */ 11816ffca240SMichael Speer (void) hpi_intr_ldg_mgmt_set(handle, ldgp->ldg, B_TRUE, 11826ffca240SMichael Speer ldgp->ldg_timer); 11831ed83081SMichael Speer } 11846ffca240SMichael Speer } else if ((ldgp->nldvs == 1) && (ring->poll_flag)) { 11856ffca240SMichael Speer /* 11866ffca240SMichael Speer * Disarm the group, if we are not a shared interrupt. 11876ffca240SMichael Speer */ 11886ffca240SMichael Speer (void) hpi_intr_ldg_mgmt_set(handle, ldgp->ldg, B_FALSE, 0); 11896ffca240SMichael Speer } else if (ring->poll_flag) { 11906ffca240SMichael Speer /* 11916ffca240SMichael Speer * Mask-off this device from the group. 11926ffca240SMichael Speer */ 11936ffca240SMichael Speer (void) hpi_intr_mask_set(handle, ldvp->ldv, 1); 11941ed83081SMichael Speer } 11956ffca240SMichael Speer 11961ed83081SMichael Speer MUTEX_EXIT(&ring->lock); 11971ed83081SMichael Speer 11981ed83081SMichael Speer /* 11991ed83081SMichael Speer * Send the packets up the stack. 12001ed83081SMichael Speer */ 12011ed83081SMichael Speer if (mp != NULL) { 12021ed83081SMichael Speer mac_rx_ring(hxgep->mach, ring->rcr_mac_handle, mp, 12031ed83081SMichael Speer ring->rcr_gen_num); 12041ed83081SMichael Speer } 12051ed83081SMichael Speer 12066ffca240SMichael Speer HXGE_DEBUG_MSG((NULL, RX_INT_CTL, "<== hxge_rx_intr")); 12076ffca240SMichael Speer return (DDI_INTR_CLAIMED); 12081ed83081SMichael Speer } 12091ed83081SMichael Speer 12101ed83081SMichael Speer /* 12111ed83081SMichael Speer * Enable polling for a ring. Interrupt for the ring is disabled when 12121ed83081SMichael Speer * the hxge interrupt comes (see hxge_rx_intr). 12131ed83081SMichael Speer */ 12141ed83081SMichael Speer int 12151ed83081SMichael Speer hxge_enable_poll(void *arg) 12161ed83081SMichael Speer { 12171ed83081SMichael Speer p_hxge_ring_handle_t ring_handle = (p_hxge_ring_handle_t)arg; 12181ed83081SMichael Speer p_rx_rcr_ring_t ringp; 12191ed83081SMichael Speer p_hxge_t hxgep; 12201ed83081SMichael Speer p_hxge_ldg_t ldgp; 12211ed83081SMichael Speer 12221ed83081SMichael Speer if (ring_handle == NULL) { 12236ffca240SMichael Speer ASSERT(ring_handle != NULL); 12246ffca240SMichael Speer return (1); 12251ed83081SMichael Speer } 12261ed83081SMichael Speer 12276ffca240SMichael Speer 12281ed83081SMichael Speer hxgep = ring_handle->hxgep; 12291ed83081SMichael Speer ringp = hxgep->rx_rcr_rings->rcr_rings[ring_handle->index]; 12301ed83081SMichael Speer 12311ed83081SMichael Speer MUTEX_ENTER(&ringp->lock); 12321ed83081SMichael Speer 12336ffca240SMichael Speer /* 12346ffca240SMichael Speer * Are we already polling ? 12356ffca240SMichael Speer */ 12366ffca240SMichael Speer if (ringp->poll_flag) { 12376ffca240SMichael Speer MUTEX_EXIT(&ringp->lock); 12386ffca240SMichael Speer return (1); 12396ffca240SMichael Speer } 12406ffca240SMichael Speer 12411ed83081SMichael Speer ldgp = ringp->ldgp; 12421ed83081SMichael Speer if (ldgp == NULL) { 12431ed83081SMichael Speer MUTEX_EXIT(&ringp->lock); 12446ffca240SMichael Speer return (1); 12451ed83081SMichael Speer } 12461ed83081SMichael Speer 12471ed83081SMichael Speer /* 12481ed83081SMichael Speer * Enable polling 12491ed83081SMichael Speer */ 12506ffca240SMichael Speer ringp->poll_flag = B_TRUE; 12511ed83081SMichael Speer 12521ed83081SMichael Speer MUTEX_EXIT(&ringp->lock); 12531ed83081SMichael Speer return (0); 12541ed83081SMichael Speer } 12551ed83081SMichael Speer 12561ed83081SMichael Speer /* 12571ed83081SMichael Speer * Disable polling for a ring and enable its interrupt. 12581ed83081SMichael Speer */ 12591ed83081SMichael Speer int 12601ed83081SMichael Speer hxge_disable_poll(void *arg) 12611ed83081SMichael Speer { 12621ed83081SMichael Speer p_hxge_ring_handle_t ring_handle = (p_hxge_ring_handle_t)arg; 12631ed83081SMichael Speer p_rx_rcr_ring_t ringp; 12641ed83081SMichael Speer p_hxge_t hxgep; 12651ed83081SMichael Speer 12661ed83081SMichael Speer if (ring_handle == NULL) { 12676ffca240SMichael Speer ASSERT(ring_handle != NULL); 12681ed83081SMichael Speer return (0); 12691ed83081SMichael Speer } 12701ed83081SMichael Speer 12711ed83081SMichael Speer hxgep = ring_handle->hxgep; 12721ed83081SMichael Speer ringp = hxgep->rx_rcr_rings->rcr_rings[ring_handle->index]; 12731ed83081SMichael Speer 12741ed83081SMichael Speer MUTEX_ENTER(&ringp->lock); 12751ed83081SMichael Speer 12761ed83081SMichael Speer /* 12771ed83081SMichael Speer * Disable polling: enable interrupt 12781ed83081SMichael Speer */ 12791ed83081SMichael Speer if (ringp->poll_flag) { 12801ed83081SMichael Speer hpi_handle_t handle; 12811ed83081SMichael Speer rdc_stat_t cs; 12821ed83081SMichael Speer p_hxge_ldg_t ldgp; 12831ed83081SMichael Speer 12841ed83081SMichael Speer /* 12851ed83081SMichael Speer * Get the control and status for this channel. 12861ed83081SMichael Speer */ 12871ed83081SMichael Speer handle = HXGE_DEV_HPI_HANDLE(hxgep); 12881ed83081SMichael Speer 12891ed83081SMichael Speer /* 12901ed83081SMichael Speer * Rearm this logical group if this is a single device 12911ed83081SMichael Speer * group. 12921ed83081SMichael Speer */ 12931ed83081SMichael Speer ldgp = ringp->ldgp; 12941ed83081SMichael Speer if (ldgp == NULL) { 12951ed83081SMichael Speer MUTEX_EXIT(&ringp->lock); 12966ffca240SMichael Speer return (1); 12971ed83081SMichael Speer } 12981ed83081SMichael Speer 12996ffca240SMichael Speer ringp->poll_flag = B_FALSE; 13006ffca240SMichael Speer 13016ffca240SMichael Speer /* 13026ffca240SMichael Speer * Enable mailbox update, to start interrupts again. 13036ffca240SMichael Speer */ 13046ffca240SMichael Speer cs.value = 0ULL; 13056ffca240SMichael Speer cs.bits.mex = 1; 13066ffca240SMichael Speer cs.bits.pktread = 0; 13076ffca240SMichael Speer cs.bits.ptrread = 0; 13086ffca240SMichael Speer RXDMA_REG_WRITE64(handle, RDC_STAT, ringp->rdc, cs.value); 13096ffca240SMichael Speer 13103dec9fcdSqs148142 if (ldgp->nldvs == 1) { 13116ffca240SMichael Speer /* 13126ffca240SMichael Speer * Re-arm the group, since it is the only member 13136ffca240SMichael Speer * of the group. 13146ffca240SMichael Speer */ 13156ffca240SMichael Speer (void) hpi_intr_ldg_mgmt_set(handle, ldgp->ldg, B_TRUE, 13166ffca240SMichael Speer ldgp->ldg_timer); 13176ffca240SMichael Speer } else { 13186ffca240SMichael Speer /* 13196ffca240SMichael Speer * Mask-on interrupts for the device and re-arm 13206ffca240SMichael Speer * the group. 13216ffca240SMichael Speer */ 13226ffca240SMichael Speer (void) hpi_intr_mask_set(handle, ringp->ldvp->ldv, 0); 13236ffca240SMichael Speer (void) hpi_intr_ldg_mgmt_set(handle, ldgp->ldg, B_TRUE, 13246ffca240SMichael Speer ldgp->ldg_timer); 13253dec9fcdSqs148142 } 13261ed83081SMichael Speer } 13271ed83081SMichael Speer MUTEX_EXIT(&ringp->lock); 13281ed83081SMichael Speer return (0); 13293dec9fcdSqs148142 } 13303dec9fcdSqs148142 13311ed83081SMichael Speer /* 13321ed83081SMichael Speer * Poll 'bytes_to_pickup' bytes of message from the rx ring. 13331ed83081SMichael Speer */ 13341ed83081SMichael Speer mblk_t * 13351ed83081SMichael Speer hxge_rx_poll(void *arg, int bytes_to_pickup) 13363dec9fcdSqs148142 { 13371ed83081SMichael Speer p_hxge_ring_handle_t rhp = (p_hxge_ring_handle_t)arg; 13381ed83081SMichael Speer p_rx_rcr_ring_t ring; 13391ed83081SMichael Speer p_hxge_t hxgep; 13401ed83081SMichael Speer hpi_handle_t handle; 13411ed83081SMichael Speer rdc_stat_t cs; 13421ed83081SMichael Speer mblk_t *mblk; 13431ed83081SMichael Speer p_hxge_ldv_t ldvp; 13443dec9fcdSqs148142 13451ed83081SMichael Speer hxgep = rhp->hxgep; 13461ed83081SMichael Speer 13471ed83081SMichael Speer /* 13481ed83081SMichael Speer * Get the control and status for this channel. 13491ed83081SMichael Speer */ 13501ed83081SMichael Speer handle = HXGE_DEV_HPI_HANDLE(hxgep); 13511ed83081SMichael Speer ring = hxgep->rx_rcr_rings->rcr_rings[rhp->index]; 13521ed83081SMichael Speer 13531ed83081SMichael Speer MUTEX_ENTER(&ring->lock); 13546ffca240SMichael Speer ASSERT(ring->poll_flag == B_TRUE); 13551ed83081SMichael Speer ASSERT(rhp->started); 13561ed83081SMichael Speer 13576ffca240SMichael Speer if (!ring->poll_flag) { 13581ed83081SMichael Speer MUTEX_EXIT(&ring->lock); 13591ed83081SMichael Speer return ((mblk_t *)NULL); 13603dec9fcdSqs148142 } 13613dec9fcdSqs148142 13626ffca240SMichael Speer /* 13636ffca240SMichael Speer * Get the control and status bits for the ring. 13646ffca240SMichael Speer */ 13651ed83081SMichael Speer RXDMA_REG_READ64(handle, RDC_STAT, rhp->index, &cs.value); 13661ed83081SMichael Speer cs.bits.ptrread = 0; 13671ed83081SMichael Speer cs.bits.pktread = 0; 13681ed83081SMichael Speer RXDMA_REG_WRITE64(handle, RDC_STAT, rhp->index, cs.value); 136941307000SQiyan Sun - Sun Microsystems - San Diego United States 13706ffca240SMichael Speer /* 13716ffca240SMichael Speer * Process packets. 13726ffca240SMichael Speer */ 13731ed83081SMichael Speer mblk = hxge_rx_pkts(hxgep, ring->ldvp->vdma_index, 13741ed83081SMichael Speer ring->ldvp, ring, cs, bytes_to_pickup); 13751ed83081SMichael Speer ldvp = ring->ldvp; 13763dec9fcdSqs148142 13771ed83081SMichael Speer /* 13781ed83081SMichael Speer * Process Error Events. 13791ed83081SMichael Speer */ 13801ed83081SMichael Speer if (ldvp && (cs.value & RDC_STAT_ERROR)) { 13816ffca240SMichael Speer /* 13826ffca240SMichael Speer * Recovery routines will grab the RCR ring lock. 13836ffca240SMichael Speer */ 13846ffca240SMichael Speer MUTEX_EXIT(&ring->lock); 13851ed83081SMichael Speer (void) hxge_rx_err_evnts(hxgep, ldvp->vdma_index, ldvp, cs); 13866ffca240SMichael Speer MUTEX_ENTER(&ring->lock); 13873dec9fcdSqs148142 } 13883dec9fcdSqs148142 13891ed83081SMichael Speer MUTEX_EXIT(&ring->lock); 13901ed83081SMichael Speer return (mblk); 13913dec9fcdSqs148142 } 13923dec9fcdSqs148142 13933dec9fcdSqs148142 /*ARGSUSED*/ 13943dec9fcdSqs148142 mblk_t * 13953dec9fcdSqs148142 hxge_rx_pkts(p_hxge_t hxgep, uint_t vindex, p_hxge_ldv_t ldvp, 13961ed83081SMichael Speer p_rx_rcr_ring_t rcrp, rdc_stat_t cs, int bytes_to_read) 13973dec9fcdSqs148142 { 13983dec9fcdSqs148142 hpi_handle_t handle; 13993dec9fcdSqs148142 uint8_t channel; 14003dec9fcdSqs148142 uint32_t comp_rd_index; 14013dec9fcdSqs148142 p_rcr_entry_t rcr_desc_rd_head_p; 14023dec9fcdSqs148142 p_rcr_entry_t rcr_desc_rd_head_pp; 14033dec9fcdSqs148142 p_mblk_t nmp, mp_cont, head_mp, *tail_mp; 14043dec9fcdSqs148142 uint16_t qlen, nrcr_read, npkt_read; 1405f043ebedSMichael Speer uint32_t qlen_hw, npkts, num_rcrs; 1406fe930412Sqs148142 uint32_t invalid_rcr_entry; 14073dec9fcdSqs148142 boolean_t multi; 1408f043ebedSMichael Speer rdc_stat_t pktcs; 14093dec9fcdSqs148142 rdc_rcr_cfg_b_t rcr_cfg_b; 1410a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint64_t rcr_head_index, rcr_tail_index; 1411a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States uint64_t rcr_tail; 1412a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States rdc_rcr_tail_t rcr_tail_reg; 14138ad8db65SMichael Speer p_hxge_rx_ring_stats_t rdc_stats; 14141ed83081SMichael Speer int totallen = 0; 14153dec9fcdSqs148142 14163dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_INT_CTL, "==> hxge_rx_pkts:vindex %d " 14173dec9fcdSqs148142 "channel %d", vindex, ldvp->channel)); 14183dec9fcdSqs148142 14193dec9fcdSqs148142 handle = HXGE_DEV_HPI_HANDLE(hxgep); 14201ed83081SMichael Speer channel = rcrp->rdc; 14213dec9fcdSqs148142 if (channel != ldvp->channel) { 14223dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_INT_CTL, "==> hxge_rx_pkts:index %d " 14233dec9fcdSqs148142 "channel %d, and rcr channel %d not matched.", 14243dec9fcdSqs148142 vindex, ldvp->channel, channel)); 14253dec9fcdSqs148142 return (NULL); 14263dec9fcdSqs148142 } 14273dec9fcdSqs148142 14283dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_INT_CTL, 14293dec9fcdSqs148142 "==> hxge_rx_pkts: START: rcr channel %d " 14303dec9fcdSqs148142 "head_p $%p head_pp $%p index %d ", 14311ed83081SMichael Speer channel, rcrp->rcr_desc_rd_head_p, 14321ed83081SMichael Speer rcrp->rcr_desc_rd_head_pp, rcrp->comp_rd_index)); 14333dec9fcdSqs148142 1434a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States (void) hpi_rxdma_rdc_rcr_qlen_get(handle, channel, &qlen); 143541307000SQiyan Sun - Sun Microsystems - San Diego United States RXDMA_REG_READ64(handle, RDC_RCR_TAIL, channel, &rcr_tail_reg.value); 1436a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States rcr_tail = rcr_tail_reg.bits.tail; 1437fe930412Sqs148142 14383dec9fcdSqs148142 if (!qlen) { 14393dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_INT_CTL, 14403dec9fcdSqs148142 "<== hxge_rx_pkts:rcr channel %d qlen %d (no pkts)", 14413dec9fcdSqs148142 channel, qlen)); 14423dec9fcdSqs148142 return (NULL); 14433dec9fcdSqs148142 } 14443dec9fcdSqs148142 14453dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_rx_pkts:rcr channel %d " 14463dec9fcdSqs148142 "qlen %d", channel, qlen)); 14473dec9fcdSqs148142 14481ed83081SMichael Speer comp_rd_index = rcrp->comp_rd_index; 14493dec9fcdSqs148142 14501ed83081SMichael Speer rcr_desc_rd_head_p = rcrp->rcr_desc_rd_head_p; 14511ed83081SMichael Speer rcr_desc_rd_head_pp = rcrp->rcr_desc_rd_head_pp; 14523dec9fcdSqs148142 nrcr_read = npkt_read = 0; 14533dec9fcdSqs148142 145441307000SQiyan Sun - Sun Microsystems - San Diego United States if (hxgep->rdc_first_intr[channel]) 145557c5371aSQiyan Sun - Sun Microsystems - San Diego United States qlen_hw = qlen; 145657c5371aSQiyan Sun - Sun Microsystems - San Diego United States else 145741307000SQiyan Sun - Sun Microsystems - San Diego United States qlen_hw = qlen - 1; 145857c5371aSQiyan Sun - Sun Microsystems - San Diego United States 14593dec9fcdSqs148142 head_mp = NULL; 14603dec9fcdSqs148142 tail_mp = &head_mp; 14613dec9fcdSqs148142 nmp = mp_cont = NULL; 14623dec9fcdSqs148142 multi = B_FALSE; 14633dec9fcdSqs148142 14641ed83081SMichael Speer rcr_head_index = rcrp->rcr_desc_rd_head_p - rcrp->rcr_desc_first_p; 14651ed83081SMichael Speer rcr_tail_index = rcr_tail - rcrp->rcr_tail_begin; 1466a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 1467a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (rcr_tail_index >= rcr_head_index) { 146841307000SQiyan Sun - Sun Microsystems - San Diego United States num_rcrs = rcr_tail_index - rcr_head_index; 1469a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } else { 1470a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* rcr_tail has wrapped around */ 14711ed83081SMichael Speer num_rcrs = (rcrp->comp_size - rcr_head_index) + rcr_tail_index; 1472a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 1473a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 1474f043ebedSMichael Speer npkts = hxge_scan_for_last_eop(rcrp, rcr_desc_rd_head_p, num_rcrs); 1475f043ebedSMichael Speer if (!npkts) 147641307000SQiyan Sun - Sun Microsystems - San Diego United States return (NULL); 147741307000SQiyan Sun - Sun Microsystems - San Diego United States 1478f043ebedSMichael Speer if (qlen_hw > npkts) { 1479a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEBUG_MSG((hxgep, RX_INT_CTL, 1480a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States "Channel %d, rcr_qlen from reg %d and from rcr_tail %d\n", 1481a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States channel, qlen_hw, qlen_sw)); 1482f043ebedSMichael Speer qlen_hw = npkts; 1483a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States } 1484a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 14853dec9fcdSqs148142 while (qlen_hw) { 14863dec9fcdSqs148142 #ifdef HXGE_DEBUG 14873dec9fcdSqs148142 hxge_dump_rcr_entry(hxgep, rcr_desc_rd_head_p); 14883dec9fcdSqs148142 #endif 14893dec9fcdSqs148142 /* 14903dec9fcdSqs148142 * Process one completion ring entry. 14913dec9fcdSqs148142 */ 1492fe930412Sqs148142 invalid_rcr_entry = 0; 14933dec9fcdSqs148142 hxge_receive_packet(hxgep, 14941ed83081SMichael Speer rcrp, rcr_desc_rd_head_p, &multi, &nmp, &mp_cont, 1495fe930412Sqs148142 &invalid_rcr_entry); 1496fe930412Sqs148142 if (invalid_rcr_entry != 0) { 14971ed83081SMichael Speer rdc_stats = rcrp->rdc_stats; 14988ad8db65SMichael Speer rdc_stats->rcr_invalids++; 1499fe930412Sqs148142 HXGE_DEBUG_MSG((hxgep, RX_INT_CTL, 1500fe930412Sqs148142 "Channel %d could only read 0x%x packets, " 1501fe930412Sqs148142 "but 0x%x pending\n", channel, npkt_read, qlen_hw)); 1502fe930412Sqs148142 break; 1503fe930412Sqs148142 } 15043dec9fcdSqs148142 15053dec9fcdSqs148142 /* 15063dec9fcdSqs148142 * message chaining modes (nemo msg chaining) 15073dec9fcdSqs148142 */ 15083dec9fcdSqs148142 if (nmp) { 15093dec9fcdSqs148142 nmp->b_next = NULL; 15103dec9fcdSqs148142 if (!multi && !mp_cont) { /* frame fits a partition */ 15113dec9fcdSqs148142 *tail_mp = nmp; 15123dec9fcdSqs148142 tail_mp = &nmp->b_next; 15133dec9fcdSqs148142 nmp = NULL; 15143dec9fcdSqs148142 } else if (multi && !mp_cont) { /* first segment */ 15153dec9fcdSqs148142 *tail_mp = nmp; 15163dec9fcdSqs148142 tail_mp = &nmp->b_cont; 15173dec9fcdSqs148142 } else if (multi && mp_cont) { /* mid of multi segs */ 15183dec9fcdSqs148142 *tail_mp = mp_cont; 15193dec9fcdSqs148142 tail_mp = &mp_cont->b_cont; 15203dec9fcdSqs148142 } else if (!multi && mp_cont) { /* last segment */ 15213dec9fcdSqs148142 *tail_mp = mp_cont; 15223dec9fcdSqs148142 tail_mp = &nmp->b_next; 15231ed83081SMichael Speer totallen += MBLKL(mp_cont); 15243dec9fcdSqs148142 nmp = NULL; 15253dec9fcdSqs148142 } 15263dec9fcdSqs148142 } 15273dec9fcdSqs148142 15283dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_INT_CTL, 15293dec9fcdSqs148142 "==> hxge_rx_pkts: loop: rcr channel %d " 15303dec9fcdSqs148142 "before updating: multi %d " 15313dec9fcdSqs148142 "nrcr_read %d " 15323dec9fcdSqs148142 "npk read %d " 15333dec9fcdSqs148142 "head_pp $%p index %d ", 15343dec9fcdSqs148142 channel, multi, 15353dec9fcdSqs148142 nrcr_read, npkt_read, rcr_desc_rd_head_pp, comp_rd_index)); 15363dec9fcdSqs148142 15373dec9fcdSqs148142 if (!multi) { 15383dec9fcdSqs148142 qlen_hw--; 15393dec9fcdSqs148142 npkt_read++; 15403dec9fcdSqs148142 } 15413dec9fcdSqs148142 15423dec9fcdSqs148142 /* 15433dec9fcdSqs148142 * Update the next read entry. 15443dec9fcdSqs148142 */ 15453dec9fcdSqs148142 comp_rd_index = NEXT_ENTRY(comp_rd_index, 15461ed83081SMichael Speer rcrp->comp_wrap_mask); 15473dec9fcdSqs148142 15483dec9fcdSqs148142 rcr_desc_rd_head_p = NEXT_ENTRY_PTR(rcr_desc_rd_head_p, 15491ed83081SMichael Speer rcrp->rcr_desc_first_p, rcrp->rcr_desc_last_p); 15503dec9fcdSqs148142 15513dec9fcdSqs148142 nrcr_read++; 15523dec9fcdSqs148142 15533dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_INT_CTL, 15543dec9fcdSqs148142 "<== hxge_rx_pkts: (SAM, process one packet) " 15553dec9fcdSqs148142 "nrcr_read %d", nrcr_read)); 15563dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_INT_CTL, 15573dec9fcdSqs148142 "==> hxge_rx_pkts: loop: rcr channel %d " 15583dec9fcdSqs148142 "multi %d nrcr_read %d npk read %d head_pp $%p index %d ", 15593dec9fcdSqs148142 channel, multi, nrcr_read, npkt_read, rcr_desc_rd_head_pp, 15603dec9fcdSqs148142 comp_rd_index)); 15611ed83081SMichael Speer 15621ed83081SMichael Speer if ((bytes_to_read != -1) && 15631ed83081SMichael Speer (totallen >= bytes_to_read)) { 15641ed83081SMichael Speer break; 15651ed83081SMichael Speer } 15663dec9fcdSqs148142 } 15673dec9fcdSqs148142 15681ed83081SMichael Speer rcrp->rcr_desc_rd_head_pp = rcr_desc_rd_head_pp; 15691ed83081SMichael Speer rcrp->comp_rd_index = comp_rd_index; 15701ed83081SMichael Speer rcrp->rcr_desc_rd_head_p = rcr_desc_rd_head_p; 15713dec9fcdSqs148142 15721ed83081SMichael Speer if ((hxgep->intr_timeout != rcrp->intr_timeout) || 15731ed83081SMichael Speer (hxgep->intr_threshold != rcrp->intr_threshold)) { 15741ed83081SMichael Speer rcrp->intr_timeout = hxgep->intr_timeout; 15751ed83081SMichael Speer rcrp->intr_threshold = hxgep->intr_threshold; 15763dec9fcdSqs148142 rcr_cfg_b.value = 0x0ULL; 15771ed83081SMichael Speer if (rcrp->intr_timeout) 15783dec9fcdSqs148142 rcr_cfg_b.bits.entout = 1; 15791ed83081SMichael Speer rcr_cfg_b.bits.timeout = rcrp->intr_timeout; 15801ed83081SMichael Speer rcr_cfg_b.bits.pthres = rcrp->intr_threshold; 15813dec9fcdSqs148142 RXDMA_REG_WRITE64(handle, RDC_RCR_CFG_B, 15823dec9fcdSqs148142 channel, rcr_cfg_b.value); 15833dec9fcdSqs148142 } 15843dec9fcdSqs148142 1585f043ebedSMichael Speer pktcs.value = 0; 1586676f0400SMichael Speer if (hxgep->rdc_first_intr[channel] && (npkt_read > 0)) { 1587676f0400SMichael Speer hxgep->rdc_first_intr[channel] = B_FALSE; 1588f043ebedSMichael Speer pktcs.bits.pktread = npkt_read - 1; 1589676f0400SMichael Speer } else 1590f043ebedSMichael Speer pktcs.bits.pktread = npkt_read; 1591f043ebedSMichael Speer pktcs.bits.ptrread = nrcr_read; 1592f043ebedSMichael Speer RXDMA_REG_WRITE64(handle, RDC_STAT, channel, pktcs.value); 159357c5371aSQiyan Sun - Sun Microsystems - San Diego United States 15943dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_INT_CTL, 15953dec9fcdSqs148142 "==> hxge_rx_pkts: EXIT: rcr channel %d " 15963dec9fcdSqs148142 "head_pp $%p index %016llx ", 15971ed83081SMichael Speer channel, rcrp->rcr_desc_rd_head_pp, rcrp->comp_rd_index)); 15983dec9fcdSqs148142 15993dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_INT_CTL, "<== hxge_rx_pkts")); 16003dec9fcdSqs148142 return (head_mp); 16013dec9fcdSqs148142 } 16023dec9fcdSqs148142 1603fe930412Sqs148142 #define RCR_ENTRY_PATTERN 0x5a5a6b6b7c7c8d8dULL 160414648441SQiyan Sun - Sun Microsystems - San Diego United States #define NO_PORT_BIT 0x20 160557c5371aSQiyan Sun - Sun Microsystems - San Diego United States #define L4_CS_EQ_BIT 0x40 1606fe930412Sqs148142 16071ed83081SMichael Speer static uint32_t hxge_scan_for_last_eop(p_rx_rcr_ring_t rcrp, 160841307000SQiyan Sun - Sun Microsystems - San Diego United States p_rcr_entry_t rcr_desc_rd_head_p, uint32_t num_rcrs) 160941307000SQiyan Sun - Sun Microsystems - San Diego United States { 161041307000SQiyan Sun - Sun Microsystems - San Diego United States uint64_t rcr_entry; 161141307000SQiyan Sun - Sun Microsystems - San Diego United States uint32_t rcrs = 0; 161241307000SQiyan Sun - Sun Microsystems - San Diego United States uint32_t pkts = 0; 161341307000SQiyan Sun - Sun Microsystems - San Diego United States 1614f043ebedSMichael Speer while (rcrs < num_rcrs) { 161541307000SQiyan Sun - Sun Microsystems - San Diego United States rcr_entry = *((uint64_t *)rcr_desc_rd_head_p); 161641307000SQiyan Sun - Sun Microsystems - San Diego United States 161741307000SQiyan Sun - Sun Microsystems - San Diego United States if ((rcr_entry == 0x0) || (rcr_entry == RCR_ENTRY_PATTERN)) 161841307000SQiyan Sun - Sun Microsystems - San Diego United States break; 161941307000SQiyan Sun - Sun Microsystems - San Diego United States 162041307000SQiyan Sun - Sun Microsystems - San Diego United States if (!(rcr_entry & RCR_MULTI_MASK)) 162141307000SQiyan Sun - Sun Microsystems - San Diego United States pkts++; 162241307000SQiyan Sun - Sun Microsystems - San Diego United States 162341307000SQiyan Sun - Sun Microsystems - San Diego United States rcr_desc_rd_head_p = NEXT_ENTRY_PTR(rcr_desc_rd_head_p, 16241ed83081SMichael Speer rcrp->rcr_desc_first_p, rcrp->rcr_desc_last_p); 1625f043ebedSMichael Speer 1626f043ebedSMichael Speer rcrs++; 162741307000SQiyan Sun - Sun Microsystems - San Diego United States } 162841307000SQiyan Sun - Sun Microsystems - San Diego United States 162941307000SQiyan Sun - Sun Microsystems - San Diego United States return (pkts); 163041307000SQiyan Sun - Sun Microsystems - San Diego United States } 163141307000SQiyan Sun - Sun Microsystems - San Diego United States 16323dec9fcdSqs148142 /*ARGSUSED*/ 16333dec9fcdSqs148142 void 16341ed83081SMichael Speer hxge_receive_packet(p_hxge_t hxgep, p_rx_rcr_ring_t rcr_p, 16351ed83081SMichael Speer p_rcr_entry_t rcr_desc_rd_head_p, boolean_t *multi_p, mblk_t **mp, 16361ed83081SMichael Speer mblk_t **mp_cont, uint32_t *invalid_rcr_entry) 16373dec9fcdSqs148142 { 16383dec9fcdSqs148142 p_mblk_t nmp = NULL; 16393dec9fcdSqs148142 uint64_t multi; 16403dec9fcdSqs148142 uint8_t channel; 16413dec9fcdSqs148142 boolean_t first_entry = B_TRUE; 164257c5371aSQiyan Sun - Sun Microsystems - San Diego United States boolean_t is_tcp_udp = B_FALSE; 16433dec9fcdSqs148142 boolean_t buffer_free = B_FALSE; 16443dec9fcdSqs148142 boolean_t error_send_up = B_FALSE; 16453dec9fcdSqs148142 uint8_t error_type; 16463dec9fcdSqs148142 uint16_t l2_len; 16473dec9fcdSqs148142 uint16_t skip_len; 16483dec9fcdSqs148142 uint8_t pktbufsz_type; 16493dec9fcdSqs148142 uint64_t rcr_entry; 16503dec9fcdSqs148142 uint64_t *pkt_buf_addr_pp; 16513dec9fcdSqs148142 uint64_t *pkt_buf_addr_p; 16523dec9fcdSqs148142 uint32_t buf_offset; 16533dec9fcdSqs148142 uint32_t bsize; 16543dec9fcdSqs148142 uint32_t msg_index; 16553dec9fcdSqs148142 p_rx_rbr_ring_t rx_rbr_p; 16563dec9fcdSqs148142 p_rx_msg_t *rx_msg_ring_p; 16573dec9fcdSqs148142 p_rx_msg_t rx_msg_p; 16583dec9fcdSqs148142 uint16_t sw_offset_bytes = 0, hdr_size = 0; 16593dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 16603dec9fcdSqs148142 boolean_t is_valid = B_FALSE; 16613dec9fcdSqs148142 p_hxge_rx_ring_stats_t rdc_stats; 16623dec9fcdSqs148142 uint32_t bytes_read; 166357c5371aSQiyan Sun - Sun Microsystems - San Diego United States uint8_t header0 = 0; 166457c5371aSQiyan Sun - Sun Microsystems - San Diego United States uint8_t header1 = 0; 166557c5371aSQiyan Sun - Sun Microsystems - San Diego United States uint64_t pkt_type; 166657c5371aSQiyan Sun - Sun Microsystems - San Diego United States uint8_t no_port_bit = 0; 166757c5371aSQiyan Sun - Sun Microsystems - San Diego United States uint8_t l4_cs_eq_bit = 0; 16683dec9fcdSqs148142 1669fe930412Sqs148142 channel = rcr_p->rdc; 1670fe930412Sqs148142 16713dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, "==> hxge_receive_packet")); 16723dec9fcdSqs148142 16733dec9fcdSqs148142 first_entry = (*mp == NULL) ? B_TRUE : B_FALSE; 16743dec9fcdSqs148142 rcr_entry = *((uint64_t *)rcr_desc_rd_head_p); 16753dec9fcdSqs148142 1676fe930412Sqs148142 /* Verify the content of the rcr_entry for a hardware bug workaround */ 1677fe930412Sqs148142 if ((rcr_entry == 0x0) || (rcr_entry == RCR_ENTRY_PATTERN)) { 1678fe930412Sqs148142 *invalid_rcr_entry = 1; 1679fe930412Sqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, "hxge_receive_packet " 1680fe930412Sqs148142 "Channel %d invalid RCR entry 0x%llx found, returning\n", 1681fe930412Sqs148142 channel, (long long) rcr_entry)); 1682fe930412Sqs148142 return; 1683fe930412Sqs148142 } 1684fe930412Sqs148142 *((uint64_t *)rcr_desc_rd_head_p) = RCR_ENTRY_PATTERN; 1685fe930412Sqs148142 16863dec9fcdSqs148142 multi = (rcr_entry & RCR_MULTI_MASK); 168757c5371aSQiyan Sun - Sun Microsystems - San Diego United States pkt_type = (rcr_entry & RCR_PKT_TYPE_MASK); 16883dec9fcdSqs148142 16893dec9fcdSqs148142 error_type = ((rcr_entry & RCR_ERROR_MASK) >> RCR_ERROR_SHIFT); 16903dec9fcdSqs148142 l2_len = ((rcr_entry & RCR_L2_LEN_MASK) >> RCR_L2_LEN_SHIFT); 16913dec9fcdSqs148142 16923dec9fcdSqs148142 /* 16933dec9fcdSqs148142 * Hardware does not strip the CRC due bug ID 11451 where 16943dec9fcdSqs148142 * the hardware mis handles minimum size packets. 16953dec9fcdSqs148142 */ 16963dec9fcdSqs148142 l2_len -= ETHERFCSL; 16973dec9fcdSqs148142 16983dec9fcdSqs148142 pktbufsz_type = ((rcr_entry & RCR_PKTBUFSZ_MASK) >> 16993dec9fcdSqs148142 RCR_PKTBUFSZ_SHIFT); 1700fe930412Sqs148142 #if defined(__i386) 1701fe930412Sqs148142 pkt_buf_addr_pp = (uint64_t *)(uint32_t)((rcr_entry & 1702fe930412Sqs148142 RCR_PKT_BUF_ADDR_MASK) << RCR_PKT_BUF_ADDR_SHIFT); 1703fe930412Sqs148142 #else 17043dec9fcdSqs148142 pkt_buf_addr_pp = (uint64_t *)((rcr_entry & RCR_PKT_BUF_ADDR_MASK) << 17053dec9fcdSqs148142 RCR_PKT_BUF_ADDR_SHIFT); 1706fe930412Sqs148142 #endif 17073dec9fcdSqs148142 17083dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 17093dec9fcdSqs148142 "==> hxge_receive_packet: entryp $%p entry 0x%0llx " 17103dec9fcdSqs148142 "pkt_buf_addr_pp $%p l2_len %d multi %d " 171114648441SQiyan Sun - Sun Microsystems - San Diego United States "error_type 0x%x pktbufsz_type %d ", 17123dec9fcdSqs148142 rcr_desc_rd_head_p, rcr_entry, pkt_buf_addr_pp, l2_len, 171314648441SQiyan Sun - Sun Microsystems - San Diego United States multi, error_type, pktbufsz_type)); 17143dec9fcdSqs148142 17153dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 17163dec9fcdSqs148142 "==> hxge_receive_packet: entryp $%p entry 0x%0llx " 17173dec9fcdSqs148142 "pkt_buf_addr_pp $%p l2_len %d multi %d " 171814648441SQiyan Sun - Sun Microsystems - San Diego United States "error_type 0x%x ", rcr_desc_rd_head_p, 171914648441SQiyan Sun - Sun Microsystems - San Diego United States rcr_entry, pkt_buf_addr_pp, l2_len, multi, error_type)); 17203dec9fcdSqs148142 17213dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 17223dec9fcdSqs148142 "==> (rbr) hxge_receive_packet: entry 0x%0llx " 17233dec9fcdSqs148142 "full pkt_buf_addr_pp $%p l2_len %d", 17243dec9fcdSqs148142 rcr_entry, pkt_buf_addr_pp, l2_len)); 17253dec9fcdSqs148142 17263dec9fcdSqs148142 /* get the stats ptr */ 17273dec9fcdSqs148142 rdc_stats = rcr_p->rdc_stats; 17283dec9fcdSqs148142 17293dec9fcdSqs148142 if (!l2_len) { 17303dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 17313dec9fcdSqs148142 "<== hxge_receive_packet: failed: l2 length is 0.")); 17323dec9fcdSqs148142 return; 17333dec9fcdSqs148142 } 17343dec9fcdSqs148142 17353dec9fcdSqs148142 /* shift 6 bits to get the full io address */ 1736fe930412Sqs148142 #if defined(__i386) 1737fe930412Sqs148142 pkt_buf_addr_pp = (uint64_t *)((uint32_t)pkt_buf_addr_pp << 1738fe930412Sqs148142 RCR_PKT_BUF_ADDR_SHIFT_FULL); 1739fe930412Sqs148142 #else 17403dec9fcdSqs148142 pkt_buf_addr_pp = (uint64_t *)((uint64_t)pkt_buf_addr_pp << 17413dec9fcdSqs148142 RCR_PKT_BUF_ADDR_SHIFT_FULL); 1742fe930412Sqs148142 #endif 17433dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 17443dec9fcdSqs148142 "==> (rbr) hxge_receive_packet: entry 0x%0llx " 17453dec9fcdSqs148142 "full pkt_buf_addr_pp $%p l2_len %d", 17463dec9fcdSqs148142 rcr_entry, pkt_buf_addr_pp, l2_len)); 17473dec9fcdSqs148142 17483dec9fcdSqs148142 rx_rbr_p = rcr_p->rx_rbr_p; 17493dec9fcdSqs148142 rx_msg_ring_p = rx_rbr_p->rx_msg_ring; 17503dec9fcdSqs148142 17513dec9fcdSqs148142 if (first_entry) { 17523dec9fcdSqs148142 hdr_size = (rcr_p->full_hdr_flag ? RXDMA_HDR_SIZE_FULL : 17533dec9fcdSqs148142 RXDMA_HDR_SIZE_DEFAULT); 17543dec9fcdSqs148142 17553dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 17563dec9fcdSqs148142 "==> hxge_receive_packet: first entry 0x%016llx " 17573dec9fcdSqs148142 "pkt_buf_addr_pp $%p l2_len %d hdr %d", 17583dec9fcdSqs148142 rcr_entry, pkt_buf_addr_pp, l2_len, hdr_size)); 17593dec9fcdSqs148142 } 17603dec9fcdSqs148142 17613dec9fcdSqs148142 MUTEX_ENTER(&rx_rbr_p->lock); 17623dec9fcdSqs148142 17633dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 17643dec9fcdSqs148142 "==> (rbr 1) hxge_receive_packet: entry 0x%0llx " 17653dec9fcdSqs148142 "full pkt_buf_addr_pp $%p l2_len %d", 17663dec9fcdSqs148142 rcr_entry, pkt_buf_addr_pp, l2_len)); 17673dec9fcdSqs148142 17683dec9fcdSqs148142 /* 17693dec9fcdSqs148142 * Packet buffer address in the completion entry points to the starting 17703dec9fcdSqs148142 * buffer address (offset 0). Use the starting buffer address to locate 17713dec9fcdSqs148142 * the corresponding kernel address. 17723dec9fcdSqs148142 */ 17733dec9fcdSqs148142 status = hxge_rxbuf_pp_to_vp(hxgep, rx_rbr_p, 17743dec9fcdSqs148142 pktbufsz_type, pkt_buf_addr_pp, &pkt_buf_addr_p, 17753dec9fcdSqs148142 &buf_offset, &msg_index); 17763dec9fcdSqs148142 17773dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 17783dec9fcdSqs148142 "==> (rbr 2) hxge_receive_packet: entry 0x%0llx " 17793dec9fcdSqs148142 "full pkt_buf_addr_pp $%p l2_len %d", 17803dec9fcdSqs148142 rcr_entry, pkt_buf_addr_pp, l2_len)); 17813dec9fcdSqs148142 17823dec9fcdSqs148142 if (status != HXGE_OK) { 17833dec9fcdSqs148142 MUTEX_EXIT(&rx_rbr_p->lock); 17843dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 17853dec9fcdSqs148142 "<== hxge_receive_packet: found vaddr failed %d", status)); 17863dec9fcdSqs148142 return; 17873dec9fcdSqs148142 } 17883dec9fcdSqs148142 17893dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 17903dec9fcdSqs148142 "==> (rbr 3) hxge_receive_packet: entry 0x%0llx " 17913dec9fcdSqs148142 "full pkt_buf_addr_pp $%p l2_len %d", 17923dec9fcdSqs148142 rcr_entry, pkt_buf_addr_pp, l2_len)); 17933dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 17943dec9fcdSqs148142 "==> (rbr 4 msgindex %d) hxge_receive_packet: entry 0x%0llx " 17953dec9fcdSqs148142 "full pkt_buf_addr_pp $%p l2_len %d", 17963dec9fcdSqs148142 msg_index, rcr_entry, pkt_buf_addr_pp, l2_len)); 17973dec9fcdSqs148142 17983dec9fcdSqs148142 if (msg_index >= rx_rbr_p->tnblocks) { 17993dec9fcdSqs148142 MUTEX_EXIT(&rx_rbr_p->lock); 18003dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 18013dec9fcdSqs148142 "==> hxge_receive_packet: FATAL msg_index (%d) " 18023dec9fcdSqs148142 "should be smaller than tnblocks (%d)\n", 18033dec9fcdSqs148142 msg_index, rx_rbr_p->tnblocks)); 18043dec9fcdSqs148142 return; 18053dec9fcdSqs148142 } 18063dec9fcdSqs148142 18073dec9fcdSqs148142 rx_msg_p = rx_msg_ring_p[msg_index]; 18083dec9fcdSqs148142 18093dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 18103dec9fcdSqs148142 "==> (rbr 4 msgindex %d) hxge_receive_packet: entry 0x%0llx " 18113dec9fcdSqs148142 "full pkt_buf_addr_pp $%p l2_len %d", 18123dec9fcdSqs148142 msg_index, rcr_entry, pkt_buf_addr_pp, l2_len)); 18133dec9fcdSqs148142 18143dec9fcdSqs148142 switch (pktbufsz_type) { 18153dec9fcdSqs148142 case RCR_PKTBUFSZ_0: 18163dec9fcdSqs148142 bsize = rx_rbr_p->pkt_buf_size0_bytes; 18173dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 18183dec9fcdSqs148142 "==> hxge_receive_packet: 0 buf %d", bsize)); 18193dec9fcdSqs148142 break; 18203dec9fcdSqs148142 case RCR_PKTBUFSZ_1: 18213dec9fcdSqs148142 bsize = rx_rbr_p->pkt_buf_size1_bytes; 18223dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 18233dec9fcdSqs148142 "==> hxge_receive_packet: 1 buf %d", bsize)); 18243dec9fcdSqs148142 break; 18253dec9fcdSqs148142 case RCR_PKTBUFSZ_2: 18263dec9fcdSqs148142 bsize = rx_rbr_p->pkt_buf_size2_bytes; 18273dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 18283dec9fcdSqs148142 "==> hxge_receive_packet: 2 buf %d", bsize)); 18293dec9fcdSqs148142 break; 18303dec9fcdSqs148142 case RCR_SINGLE_BLOCK: 18313dec9fcdSqs148142 bsize = rx_msg_p->block_size; 18323dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 18333dec9fcdSqs148142 "==> hxge_receive_packet: single %d", bsize)); 18343dec9fcdSqs148142 18353dec9fcdSqs148142 break; 18363dec9fcdSqs148142 default: 18373dec9fcdSqs148142 MUTEX_EXIT(&rx_rbr_p->lock); 18383dec9fcdSqs148142 return; 18393dec9fcdSqs148142 } 18403dec9fcdSqs148142 18413dec9fcdSqs148142 DMA_COMMON_SYNC_OFFSET(rx_msg_p->buf_dma, 18423dec9fcdSqs148142 (buf_offset + sw_offset_bytes), (hdr_size + l2_len), 18433dec9fcdSqs148142 DDI_DMA_SYNC_FORCPU); 18443dec9fcdSqs148142 18453dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 18463dec9fcdSqs148142 "==> hxge_receive_packet: after first dump:usage count")); 18473dec9fcdSqs148142 18483dec9fcdSqs148142 if (rx_msg_p->cur_usage_cnt == 0) { 184957c5371aSQiyan Sun - Sun Microsystems - San Diego United States atomic_inc_32(&rx_rbr_p->rbr_used); 18503dec9fcdSqs148142 if (rx_rbr_p->rbr_use_bcopy) { 18513dec9fcdSqs148142 atomic_inc_32(&rx_rbr_p->rbr_consumed); 185257c5371aSQiyan Sun - Sun Microsystems - San Diego United States if (rx_rbr_p->rbr_consumed < 18533dec9fcdSqs148142 rx_rbr_p->rbr_threshold_hi) { 185457c5371aSQiyan Sun - Sun Microsystems - San Diego United States if (rx_rbr_p->rbr_threshold_lo == 0 || 185557c5371aSQiyan Sun - Sun Microsystems - San Diego United States ((rx_rbr_p->rbr_consumed >= 185657c5371aSQiyan Sun - Sun Microsystems - San Diego United States rx_rbr_p->rbr_threshold_lo) && 185757c5371aSQiyan Sun - Sun Microsystems - San Diego United States (rx_rbr_p->rbr_bufsize_type >= 185857c5371aSQiyan Sun - Sun Microsystems - San Diego United States pktbufsz_type))) { 185957c5371aSQiyan Sun - Sun Microsystems - San Diego United States rx_msg_p->rx_use_bcopy = B_TRUE; 186057c5371aSQiyan Sun - Sun Microsystems - San Diego United States } 186157c5371aSQiyan Sun - Sun Microsystems - San Diego United States } else { 18623dec9fcdSqs148142 rx_msg_p->rx_use_bcopy = B_TRUE; 18633dec9fcdSqs148142 } 18643dec9fcdSqs148142 } 18653dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 18663dec9fcdSqs148142 "==> hxge_receive_packet: buf %d (new block) ", bsize)); 18673dec9fcdSqs148142 18683dec9fcdSqs148142 rx_msg_p->pkt_buf_size_code = pktbufsz_type; 18693dec9fcdSqs148142 rx_msg_p->pkt_buf_size = bsize; 18703dec9fcdSqs148142 rx_msg_p->cur_usage_cnt = 1; 18713dec9fcdSqs148142 if (pktbufsz_type == RCR_SINGLE_BLOCK) { 18723dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 18733dec9fcdSqs148142 "==> hxge_receive_packet: buf %d (single block) ", 18743dec9fcdSqs148142 bsize)); 18753dec9fcdSqs148142 /* 18763dec9fcdSqs148142 * Buffer can be reused once the free function is 18773dec9fcdSqs148142 * called. 18783dec9fcdSqs148142 */ 18793dec9fcdSqs148142 rx_msg_p->max_usage_cnt = 1; 18803dec9fcdSqs148142 buffer_free = B_TRUE; 18813dec9fcdSqs148142 } else { 18823dec9fcdSqs148142 rx_msg_p->max_usage_cnt = rx_msg_p->block_size / bsize; 18833dec9fcdSqs148142 if (rx_msg_p->max_usage_cnt == 1) { 18843dec9fcdSqs148142 buffer_free = B_TRUE; 18853dec9fcdSqs148142 } 18863dec9fcdSqs148142 } 18873dec9fcdSqs148142 } else { 18883dec9fcdSqs148142 rx_msg_p->cur_usage_cnt++; 18893dec9fcdSqs148142 if (rx_msg_p->cur_usage_cnt == rx_msg_p->max_usage_cnt) { 18903dec9fcdSqs148142 buffer_free = B_TRUE; 18913dec9fcdSqs148142 } 18923dec9fcdSqs148142 } 18933dec9fcdSqs148142 18943dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 18953dec9fcdSqs148142 "msgbuf index = %d l2len %d bytes usage %d max_usage %d ", 18963dec9fcdSqs148142 msg_index, l2_len, 18973dec9fcdSqs148142 rx_msg_p->cur_usage_cnt, rx_msg_p->max_usage_cnt)); 18983dec9fcdSqs148142 18993dec9fcdSqs148142 if (error_type) { 19003dec9fcdSqs148142 rdc_stats->ierrors++; 19013dec9fcdSqs148142 /* Update error stats */ 19023dec9fcdSqs148142 rdc_stats->errlog.compl_err_type = error_type; 19033dec9fcdSqs148142 HXGE_FM_REPORT_ERROR(hxgep, NULL, HXGE_FM_EREPORT_RDMC_RCR_ERR); 19043dec9fcdSqs148142 19053dec9fcdSqs148142 if (error_type & RCR_CTRL_FIFO_DED) { 19063dec9fcdSqs148142 rdc_stats->ctrl_fifo_ecc_err++; 19073dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 19083dec9fcdSqs148142 " hxge_receive_packet: " 19093dec9fcdSqs148142 " channel %d RCR ctrl_fifo_ded error", channel)); 19103dec9fcdSqs148142 } else if (error_type & RCR_DATA_FIFO_DED) { 19113dec9fcdSqs148142 rdc_stats->data_fifo_ecc_err++; 19123dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 19133dec9fcdSqs148142 " hxge_receive_packet: channel %d" 19143dec9fcdSqs148142 " RCR data_fifo_ded error", channel)); 19153dec9fcdSqs148142 } 19163dec9fcdSqs148142 19173dec9fcdSqs148142 /* 19183dec9fcdSqs148142 * Update and repost buffer block if max usage count is 19193dec9fcdSqs148142 * reached. 19203dec9fcdSqs148142 */ 19213dec9fcdSqs148142 if (error_send_up == B_FALSE) { 19223dec9fcdSqs148142 atomic_inc_32(&rx_msg_p->ref_cnt); 19233dec9fcdSqs148142 if (buffer_free == B_TRUE) { 19243dec9fcdSqs148142 rx_msg_p->free = B_TRUE; 19253dec9fcdSqs148142 } 19263dec9fcdSqs148142 19273dec9fcdSqs148142 MUTEX_EXIT(&rx_rbr_p->lock); 19283dec9fcdSqs148142 hxge_freeb(rx_msg_p); 19293dec9fcdSqs148142 return; 19303dec9fcdSqs148142 } 19313dec9fcdSqs148142 } 19323dec9fcdSqs148142 19333dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 19343dec9fcdSqs148142 "==> hxge_receive_packet: DMA sync second ")); 19353dec9fcdSqs148142 19363dec9fcdSqs148142 bytes_read = rcr_p->rcvd_pkt_bytes; 19373dec9fcdSqs148142 skip_len = sw_offset_bytes + hdr_size; 193814648441SQiyan Sun - Sun Microsystems - San Diego United States 193914648441SQiyan Sun - Sun Microsystems - San Diego United States if (first_entry) { 194057c5371aSQiyan Sun - Sun Microsystems - San Diego United States header0 = rx_msg_p->buffer[buf_offset]; 194157c5371aSQiyan Sun - Sun Microsystems - San Diego United States no_port_bit = header0 & NO_PORT_BIT; 194257c5371aSQiyan Sun - Sun Microsystems - San Diego United States header1 = rx_msg_p->buffer[buf_offset + 1]; 194357c5371aSQiyan Sun - Sun Microsystems - San Diego United States l4_cs_eq_bit = header1 & L4_CS_EQ_BIT; 194414648441SQiyan Sun - Sun Microsystems - San Diego United States } 194514648441SQiyan Sun - Sun Microsystems - San Diego United States 19463dec9fcdSqs148142 if (!rx_msg_p->rx_use_bcopy) { 19473dec9fcdSqs148142 /* 19483dec9fcdSqs148142 * For loaned up buffers, the driver reference count 19493dec9fcdSqs148142 * will be incremented first and then the free state. 19503dec9fcdSqs148142 */ 19513dec9fcdSqs148142 if ((nmp = hxge_dupb(rx_msg_p, buf_offset, bsize)) != NULL) { 19523dec9fcdSqs148142 if (first_entry) { 19533dec9fcdSqs148142 nmp->b_rptr = &nmp->b_rptr[skip_len]; 19543dec9fcdSqs148142 if (l2_len < bsize - skip_len) { 19553dec9fcdSqs148142 nmp->b_wptr = &nmp->b_rptr[l2_len]; 19563dec9fcdSqs148142 } else { 19573dec9fcdSqs148142 nmp->b_wptr = &nmp->b_rptr[bsize 19583dec9fcdSqs148142 - skip_len]; 19593dec9fcdSqs148142 } 19603dec9fcdSqs148142 } else { 19613dec9fcdSqs148142 if (l2_len - bytes_read < bsize) { 19623dec9fcdSqs148142 nmp->b_wptr = 19633dec9fcdSqs148142 &nmp->b_rptr[l2_len - bytes_read]; 19643dec9fcdSqs148142 } else { 19653dec9fcdSqs148142 nmp->b_wptr = &nmp->b_rptr[bsize]; 19663dec9fcdSqs148142 } 19673dec9fcdSqs148142 } 19683dec9fcdSqs148142 } 19693dec9fcdSqs148142 } else { 19703dec9fcdSqs148142 if (first_entry) { 19713dec9fcdSqs148142 nmp = hxge_dupb_bcopy(rx_msg_p, buf_offset + skip_len, 19723dec9fcdSqs148142 l2_len < bsize - skip_len ? 19733dec9fcdSqs148142 l2_len : bsize - skip_len); 19743dec9fcdSqs148142 } else { 19753dec9fcdSqs148142 nmp = hxge_dupb_bcopy(rx_msg_p, buf_offset, 19763dec9fcdSqs148142 l2_len - bytes_read < bsize ? 19773dec9fcdSqs148142 l2_len - bytes_read : bsize); 19783dec9fcdSqs148142 } 19793dec9fcdSqs148142 } 19803dec9fcdSqs148142 19813dec9fcdSqs148142 if (nmp != NULL) { 19823dec9fcdSqs148142 if (first_entry) 19833dec9fcdSqs148142 bytes_read = nmp->b_wptr - nmp->b_rptr; 19843dec9fcdSqs148142 else 19853dec9fcdSqs148142 bytes_read += nmp->b_wptr - nmp->b_rptr; 19863dec9fcdSqs148142 19873dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 19883dec9fcdSqs148142 "==> hxge_receive_packet after dupb: " 19893dec9fcdSqs148142 "rbr consumed %d " 19903dec9fcdSqs148142 "pktbufsz_type %d " 19913dec9fcdSqs148142 "nmp $%p rptr $%p wptr $%p " 19923dec9fcdSqs148142 "buf_offset %d bzise %d l2_len %d skip_len %d", 19933dec9fcdSqs148142 rx_rbr_p->rbr_consumed, 19943dec9fcdSqs148142 pktbufsz_type, 19953dec9fcdSqs148142 nmp, nmp->b_rptr, nmp->b_wptr, 19963dec9fcdSqs148142 buf_offset, bsize, l2_len, skip_len)); 19973dec9fcdSqs148142 } else { 19983dec9fcdSqs148142 cmn_err(CE_WARN, "!hxge_receive_packet: update stats (error)"); 19993dec9fcdSqs148142 20003dec9fcdSqs148142 atomic_inc_32(&rx_msg_p->ref_cnt); 20013dec9fcdSqs148142 if (buffer_free == B_TRUE) { 20023dec9fcdSqs148142 rx_msg_p->free = B_TRUE; 20033dec9fcdSqs148142 } 20043dec9fcdSqs148142 20053dec9fcdSqs148142 MUTEX_EXIT(&rx_rbr_p->lock); 20063dec9fcdSqs148142 hxge_freeb(rx_msg_p); 20073dec9fcdSqs148142 return; 20083dec9fcdSqs148142 } 20093dec9fcdSqs148142 20103dec9fcdSqs148142 if (buffer_free == B_TRUE) { 20113dec9fcdSqs148142 rx_msg_p->free = B_TRUE; 20123dec9fcdSqs148142 } 20133dec9fcdSqs148142 20143dec9fcdSqs148142 /* 20153dec9fcdSqs148142 * ERROR, FRAG and PKT_TYPE are only reported in the first entry. If a 20163dec9fcdSqs148142 * packet is not fragmented and no error bit is set, then L4 checksum 20173dec9fcdSqs148142 * is OK. 20183dec9fcdSqs148142 */ 20193dec9fcdSqs148142 is_valid = (nmp != NULL); 20203dec9fcdSqs148142 if (first_entry) { 20213dec9fcdSqs148142 rdc_stats->ipackets++; /* count only 1st seg for jumbo */ 2022a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States if (l2_len > (STD_FRAME_SIZE - ETHERFCSL)) 2023a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States rdc_stats->jumbo_pkts++; 20243dec9fcdSqs148142 rdc_stats->ibytes += skip_len + l2_len < bsize ? 20253dec9fcdSqs148142 l2_len : bsize; 20263dec9fcdSqs148142 } else { 2027a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States /* 2028a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States * Add the current portion of the packet to the kstats. 2029a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States * The current portion of the packet is calculated by using 2030a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States * length of the packet and the previously received portion. 2031a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States */ 2032a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States rdc_stats->ibytes += l2_len - rcr_p->rcvd_pkt_bytes < bsize ? 2033a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States l2_len - rcr_p->rcvd_pkt_bytes : bsize; 20343dec9fcdSqs148142 } 20353dec9fcdSqs148142 20363dec9fcdSqs148142 rcr_p->rcvd_pkt_bytes = bytes_read; 20373dec9fcdSqs148142 20383dec9fcdSqs148142 if (rx_msg_p->free && rx_msg_p->rx_use_bcopy) { 20393dec9fcdSqs148142 atomic_inc_32(&rx_msg_p->ref_cnt); 2040dc10a9c2SMichael Speer MUTEX_EXIT(&rx_rbr_p->lock); 20413dec9fcdSqs148142 hxge_freeb(rx_msg_p); 20421ed83081SMichael Speer } else 2043dc10a9c2SMichael Speer MUTEX_EXIT(&rx_rbr_p->lock); 20443dec9fcdSqs148142 20453dec9fcdSqs148142 if (is_valid) { 20463dec9fcdSqs148142 nmp->b_cont = NULL; 20473dec9fcdSqs148142 if (first_entry) { 20483dec9fcdSqs148142 *mp = nmp; 20493dec9fcdSqs148142 *mp_cont = NULL; 20503dec9fcdSqs148142 } else { 20513dec9fcdSqs148142 *mp_cont = nmp; 20523dec9fcdSqs148142 } 20533dec9fcdSqs148142 } 20543dec9fcdSqs148142 20553dec9fcdSqs148142 /* 20563dec9fcdSqs148142 * Update stats and hardware checksuming. 20573dec9fcdSqs148142 */ 20583dec9fcdSqs148142 if (is_valid && !multi) { 205957c5371aSQiyan Sun - Sun Microsystems - San Diego United States is_tcp_udp = ((pkt_type == RCR_PKT_IS_TCP || 206057c5371aSQiyan Sun - Sun Microsystems - San Diego United States pkt_type == RCR_PKT_IS_UDP) ? B_TRUE : B_FALSE); 206157c5371aSQiyan Sun - Sun Microsystems - San Diego United States 206257c5371aSQiyan Sun - Sun Microsystems - San Diego United States if (!no_port_bit && l4_cs_eq_bit && is_tcp_udp && !error_type) { 20630dc2366fSVenugopal Iyer mac_hcksum_set(nmp, 0, 0, 0, 0, HCK_FULLCKSUM_OK); 20643dec9fcdSqs148142 20653dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 20663dec9fcdSqs148142 "==> hxge_receive_packet: Full tcp/udp cksum " 206714648441SQiyan Sun - Sun Microsystems - San Diego United States "is_valid 0x%x multi %d error %d", 206814648441SQiyan Sun - Sun Microsystems - San Diego United States is_valid, multi, error_type)); 20693dec9fcdSqs148142 } 20703dec9fcdSqs148142 } 20713dec9fcdSqs148142 20723dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX2_CTL, 20733dec9fcdSqs148142 "==> hxge_receive_packet: *mp 0x%016llx", *mp)); 20743dec9fcdSqs148142 20753dec9fcdSqs148142 *multi_p = (multi == RCR_MULTI_MASK); 20763dec9fcdSqs148142 20773dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "<== hxge_receive_packet: " 20783dec9fcdSqs148142 "multi %d nmp 0x%016llx *mp 0x%016llx *mp_cont 0x%016llx", 20793dec9fcdSqs148142 *multi_p, nmp, *mp, *mp_cont)); 20803dec9fcdSqs148142 } 20813dec9fcdSqs148142 2082b83cd2c3SMichael Speer static void 2083b83cd2c3SMichael Speer hxge_rx_rbr_empty_recover(p_hxge_t hxgep, uint8_t channel) 2084b83cd2c3SMichael Speer { 2085b83cd2c3SMichael Speer hpi_handle_t handle; 2086b83cd2c3SMichael Speer p_rx_rcr_ring_t rcrp; 2087b83cd2c3SMichael Speer p_rx_rbr_ring_t rbrp; 2088b83cd2c3SMichael Speer 2089b83cd2c3SMichael Speer rcrp = hxgep->rx_rcr_rings->rcr_rings[channel]; 2090b83cd2c3SMichael Speer rbrp = rcrp->rx_rbr_p; 2091b83cd2c3SMichael Speer handle = HXGE_DEV_HPI_HANDLE(hxgep); 2092b83cd2c3SMichael Speer 2093b83cd2c3SMichael Speer /* 2094b83cd2c3SMichael Speer * Wait for the channel to be quiet 2095b83cd2c3SMichael Speer */ 2096b83cd2c3SMichael Speer (void) hpi_rxdma_cfg_rdc_wait_for_qst(handle, channel); 2097b83cd2c3SMichael Speer 2098b83cd2c3SMichael Speer /* 2099b83cd2c3SMichael Speer * Post page will accumulate some buffers before re-enabling 2100b83cd2c3SMichael Speer * the DMA channel. 2101b83cd2c3SMichael Speer */ 210257c5371aSQiyan Sun - Sun Microsystems - San Diego United States 2103b83cd2c3SMichael Speer MUTEX_ENTER(&rbrp->post_lock); 210457c5371aSQiyan Sun - Sun Microsystems - San Diego United States if ((rbrp->rbb_max - rbrp->rbr_used) >= HXGE_RBR_EMPTY_THRESHOLD) { 21051c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States hxge_rbr_empty_restore(hxgep, rbrp); 21061c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States } else { 2107b83cd2c3SMichael Speer rbrp->rbr_is_empty = B_TRUE; 21081c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States } 2109b83cd2c3SMichael Speer MUTEX_EXIT(&rbrp->post_lock); 2110b83cd2c3SMichael Speer } 2111b83cd2c3SMichael Speer 21121ed83081SMichael Speer 21133dec9fcdSqs148142 /*ARGSUSED*/ 21143dec9fcdSqs148142 static hxge_status_t 21153dec9fcdSqs148142 hxge_rx_err_evnts(p_hxge_t hxgep, uint_t index, p_hxge_ldv_t ldvp, 21163dec9fcdSqs148142 rdc_stat_t cs) 21173dec9fcdSqs148142 { 21183dec9fcdSqs148142 p_hxge_rx_ring_stats_t rdc_stats; 21193dec9fcdSqs148142 hpi_handle_t handle; 21203dec9fcdSqs148142 boolean_t rxchan_fatal = B_FALSE; 21213dec9fcdSqs148142 uint8_t channel; 21223dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 21233dec9fcdSqs148142 21243dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_rx_err_evnts")); 21253dec9fcdSqs148142 21263dec9fcdSqs148142 handle = HXGE_DEV_HPI_HANDLE(hxgep); 21273dec9fcdSqs148142 channel = ldvp->channel; 21283dec9fcdSqs148142 21293dec9fcdSqs148142 rdc_stats = &hxgep->statsp->rdc_stats[ldvp->vdma_index]; 21303dec9fcdSqs148142 21313dec9fcdSqs148142 if (cs.bits.rbr_cpl_to) { 21323dec9fcdSqs148142 rdc_stats->rbr_tmout++; 21333dec9fcdSqs148142 HXGE_FM_REPORT_ERROR(hxgep, channel, 21343dec9fcdSqs148142 HXGE_FM_EREPORT_RDMC_RBR_CPL_TO); 21353dec9fcdSqs148142 rxchan_fatal = B_TRUE; 21363dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 21373dec9fcdSqs148142 "==> hxge_rx_err_evnts(channel %d): " 21383dec9fcdSqs148142 "fatal error: rx_rbr_timeout", channel)); 21393dec9fcdSqs148142 } 21403dec9fcdSqs148142 21413dec9fcdSqs148142 if ((cs.bits.rcr_shadow_par_err) || (cs.bits.rbr_prefetch_par_err)) { 21423dec9fcdSqs148142 (void) hpi_rxdma_ring_perr_stat_get(handle, 21433dec9fcdSqs148142 &rdc_stats->errlog.pre_par, &rdc_stats->errlog.sha_par); 21443dec9fcdSqs148142 } 21453dec9fcdSqs148142 21463dec9fcdSqs148142 if (cs.bits.rcr_shadow_par_err) { 21473dec9fcdSqs148142 rdc_stats->rcr_sha_par++; 21483dec9fcdSqs148142 HXGE_FM_REPORT_ERROR(hxgep, channel, 21493dec9fcdSqs148142 HXGE_FM_EREPORT_RDMC_RCR_SHA_PAR); 21503dec9fcdSqs148142 rxchan_fatal = B_TRUE; 21513dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 21523dec9fcdSqs148142 "==> hxge_rx_err_evnts(channel %d): " 21533dec9fcdSqs148142 "fatal error: rcr_shadow_par_err", channel)); 21543dec9fcdSqs148142 } 21553dec9fcdSqs148142 21563dec9fcdSqs148142 if (cs.bits.rbr_prefetch_par_err) { 21573dec9fcdSqs148142 rdc_stats->rbr_pre_par++; 21583dec9fcdSqs148142 HXGE_FM_REPORT_ERROR(hxgep, channel, 21593dec9fcdSqs148142 HXGE_FM_EREPORT_RDMC_RBR_PRE_PAR); 21603dec9fcdSqs148142 rxchan_fatal = B_TRUE; 21613dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 21623dec9fcdSqs148142 "==> hxge_rx_err_evnts(channel %d): " 21633dec9fcdSqs148142 "fatal error: rbr_prefetch_par_err", channel)); 21643dec9fcdSqs148142 } 21653dec9fcdSqs148142 21663dec9fcdSqs148142 if (cs.bits.rbr_pre_empty) { 21673dec9fcdSqs148142 rdc_stats->rbr_pre_empty++; 21683dec9fcdSqs148142 HXGE_FM_REPORT_ERROR(hxgep, channel, 21693dec9fcdSqs148142 HXGE_FM_EREPORT_RDMC_RBR_PRE_EMPTY); 21703dec9fcdSqs148142 rxchan_fatal = B_TRUE; 21713dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 21723dec9fcdSqs148142 "==> hxge_rx_err_evnts(channel %d): " 21733dec9fcdSqs148142 "fatal error: rbr_pre_empty", channel)); 21743dec9fcdSqs148142 } 21753dec9fcdSqs148142 21763dec9fcdSqs148142 if (cs.bits.peu_resp_err) { 21773dec9fcdSqs148142 rdc_stats->peu_resp_err++; 21783dec9fcdSqs148142 HXGE_FM_REPORT_ERROR(hxgep, channel, 21793dec9fcdSqs148142 HXGE_FM_EREPORT_RDMC_PEU_RESP_ERR); 21803dec9fcdSqs148142 rxchan_fatal = B_TRUE; 21813dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 21823dec9fcdSqs148142 "==> hxge_rx_err_evnts(channel %d): " 21833dec9fcdSqs148142 "fatal error: peu_resp_err", channel)); 21843dec9fcdSqs148142 } 21853dec9fcdSqs148142 21863dec9fcdSqs148142 if (cs.bits.rcr_thres) { 21873dec9fcdSqs148142 rdc_stats->rcr_thres++; 21883dec9fcdSqs148142 } 21893dec9fcdSqs148142 21903dec9fcdSqs148142 if (cs.bits.rcr_to) { 21913dec9fcdSqs148142 rdc_stats->rcr_to++; 21923dec9fcdSqs148142 } 21933dec9fcdSqs148142 21943dec9fcdSqs148142 if (cs.bits.rcr_shadow_full) { 21953dec9fcdSqs148142 rdc_stats->rcr_shadow_full++; 21963dec9fcdSqs148142 HXGE_FM_REPORT_ERROR(hxgep, channel, 21973dec9fcdSqs148142 HXGE_FM_EREPORT_RDMC_RCR_SHA_FULL); 21983dec9fcdSqs148142 rxchan_fatal = B_TRUE; 21993dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 22003dec9fcdSqs148142 "==> hxge_rx_err_evnts(channel %d): " 22013dec9fcdSqs148142 "fatal error: rcr_shadow_full", channel)); 22023dec9fcdSqs148142 } 22033dec9fcdSqs148142 22043dec9fcdSqs148142 if (cs.bits.rcr_full) { 22053dec9fcdSqs148142 rdc_stats->rcrfull++; 22063dec9fcdSqs148142 HXGE_FM_REPORT_ERROR(hxgep, channel, 22073dec9fcdSqs148142 HXGE_FM_EREPORT_RDMC_RCRFULL); 22083dec9fcdSqs148142 rxchan_fatal = B_TRUE; 22093dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 22103dec9fcdSqs148142 "==> hxge_rx_err_evnts(channel %d): " 22113dec9fcdSqs148142 "fatal error: rcrfull error", channel)); 22123dec9fcdSqs148142 } 22133dec9fcdSqs148142 22143dec9fcdSqs148142 if (cs.bits.rbr_empty) { 22153dec9fcdSqs148142 rdc_stats->rbr_empty++; 2216b83cd2c3SMichael Speer hxge_rx_rbr_empty_recover(hxgep, channel); 22173dec9fcdSqs148142 } 22183dec9fcdSqs148142 22193dec9fcdSqs148142 if (cs.bits.rbr_full) { 22203dec9fcdSqs148142 rdc_stats->rbrfull++; 22213dec9fcdSqs148142 HXGE_FM_REPORT_ERROR(hxgep, channel, 22223dec9fcdSqs148142 HXGE_FM_EREPORT_RDMC_RBRFULL); 22233dec9fcdSqs148142 rxchan_fatal = B_TRUE; 22243dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 22253dec9fcdSqs148142 "==> hxge_rx_err_evnts(channel %d): " 22263dec9fcdSqs148142 "fatal error: rbr_full error", channel)); 22273dec9fcdSqs148142 } 22283dec9fcdSqs148142 22293dec9fcdSqs148142 if (rxchan_fatal) { 22301c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States p_rx_rcr_ring_t rcrp; 22311c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States p_rx_rbr_ring_t rbrp; 22321c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States 22331c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States rcrp = hxgep->rx_rcr_rings->rcr_rings[channel]; 22341c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States rbrp = rcrp->rx_rbr_p; 22351c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States 22363dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 22373dec9fcdSqs148142 " hxge_rx_err_evnts: fatal error on Channel #%d\n", 22383dec9fcdSqs148142 channel)); 22396ffca240SMichael Speer 22401c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_ENTER(&rbrp->post_lock); 22411c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States /* This function needs to be inside the post_lock */ 22423dec9fcdSqs148142 status = hxge_rxdma_fatal_err_recover(hxgep, channel); 22431c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_EXIT(&rbrp->post_lock); 22443dec9fcdSqs148142 if (status == HXGE_OK) { 22453dec9fcdSqs148142 FM_SERVICE_RESTORED(hxgep); 22463dec9fcdSqs148142 } 22473dec9fcdSqs148142 } 22483dec9fcdSqs148142 22496ffca240SMichael Speer HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_rx_err_evnts")); 22503dec9fcdSqs148142 return (status); 22513dec9fcdSqs148142 } 22523dec9fcdSqs148142 22533dec9fcdSqs148142 static hxge_status_t 22543dec9fcdSqs148142 hxge_map_rxdma(p_hxge_t hxgep) 22553dec9fcdSqs148142 { 22563dec9fcdSqs148142 int i, ndmas; 22573dec9fcdSqs148142 uint16_t channel; 22583dec9fcdSqs148142 p_rx_rbr_rings_t rx_rbr_rings; 22593dec9fcdSqs148142 p_rx_rbr_ring_t *rbr_rings; 22603dec9fcdSqs148142 p_rx_rcr_rings_t rx_rcr_rings; 22613dec9fcdSqs148142 p_rx_rcr_ring_t *rcr_rings; 22623dec9fcdSqs148142 p_rx_mbox_areas_t rx_mbox_areas_p; 22633dec9fcdSqs148142 p_rx_mbox_t *rx_mbox_p; 22643dec9fcdSqs148142 p_hxge_dma_pool_t dma_buf_poolp; 22653dec9fcdSqs148142 p_hxge_dma_common_t *dma_buf_p; 22668ad8db65SMichael Speer p_hxge_dma_pool_t dma_rbr_cntl_poolp; 22678ad8db65SMichael Speer p_hxge_dma_common_t *dma_rbr_cntl_p; 22688ad8db65SMichael Speer p_hxge_dma_pool_t dma_rcr_cntl_poolp; 22698ad8db65SMichael Speer p_hxge_dma_common_t *dma_rcr_cntl_p; 22708ad8db65SMichael Speer p_hxge_dma_pool_t dma_mbox_cntl_poolp; 22718ad8db65SMichael Speer p_hxge_dma_common_t *dma_mbox_cntl_p; 22723dec9fcdSqs148142 uint32_t *num_chunks; 22733dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 22743dec9fcdSqs148142 22753dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_map_rxdma")); 22763dec9fcdSqs148142 22773dec9fcdSqs148142 dma_buf_poolp = hxgep->rx_buf_pool_p; 22788ad8db65SMichael Speer dma_rbr_cntl_poolp = hxgep->rx_rbr_cntl_pool_p; 22798ad8db65SMichael Speer dma_rcr_cntl_poolp = hxgep->rx_rcr_cntl_pool_p; 22808ad8db65SMichael Speer dma_mbox_cntl_poolp = hxgep->rx_mbox_cntl_pool_p; 22813dec9fcdSqs148142 22828ad8db65SMichael Speer if (!dma_buf_poolp->buf_allocated || 22838ad8db65SMichael Speer !dma_rbr_cntl_poolp->buf_allocated || 22848ad8db65SMichael Speer !dma_rcr_cntl_poolp->buf_allocated || 22858ad8db65SMichael Speer !dma_mbox_cntl_poolp->buf_allocated) { 22863dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 22873dec9fcdSqs148142 "<== hxge_map_rxdma: buf not allocated")); 22883dec9fcdSqs148142 return (HXGE_ERROR); 22893dec9fcdSqs148142 } 22903dec9fcdSqs148142 22913dec9fcdSqs148142 ndmas = dma_buf_poolp->ndmas; 22923dec9fcdSqs148142 if (!ndmas) { 22933dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 22943dec9fcdSqs148142 "<== hxge_map_rxdma: no dma allocated")); 22953dec9fcdSqs148142 return (HXGE_ERROR); 22963dec9fcdSqs148142 } 22973dec9fcdSqs148142 22983dec9fcdSqs148142 num_chunks = dma_buf_poolp->num_chunks; 22993dec9fcdSqs148142 dma_buf_p = dma_buf_poolp->dma_buf_pool_p; 23008ad8db65SMichael Speer dma_rbr_cntl_p = dma_rbr_cntl_poolp->dma_buf_pool_p; 23018ad8db65SMichael Speer dma_rcr_cntl_p = dma_rcr_cntl_poolp->dma_buf_pool_p; 23028ad8db65SMichael Speer dma_mbox_cntl_p = dma_mbox_cntl_poolp->dma_buf_pool_p; 23038ad8db65SMichael Speer 23043dec9fcdSqs148142 rx_rbr_rings = (p_rx_rbr_rings_t) 23053dec9fcdSqs148142 KMEM_ZALLOC(sizeof (rx_rbr_rings_t), KM_SLEEP); 23063dec9fcdSqs148142 rbr_rings = (p_rx_rbr_ring_t *)KMEM_ZALLOC( 23073dec9fcdSqs148142 sizeof (p_rx_rbr_ring_t) * ndmas, KM_SLEEP); 23083dec9fcdSqs148142 23093dec9fcdSqs148142 rx_rcr_rings = (p_rx_rcr_rings_t) 23103dec9fcdSqs148142 KMEM_ZALLOC(sizeof (rx_rcr_rings_t), KM_SLEEP); 23113dec9fcdSqs148142 rcr_rings = (p_rx_rcr_ring_t *)KMEM_ZALLOC( 23123dec9fcdSqs148142 sizeof (p_rx_rcr_ring_t) * ndmas, KM_SLEEP); 23133dec9fcdSqs148142 23143dec9fcdSqs148142 rx_mbox_areas_p = (p_rx_mbox_areas_t) 23153dec9fcdSqs148142 KMEM_ZALLOC(sizeof (rx_mbox_areas_t), KM_SLEEP); 23163dec9fcdSqs148142 rx_mbox_p = (p_rx_mbox_t *)KMEM_ZALLOC( 23173dec9fcdSqs148142 sizeof (p_rx_mbox_t) * ndmas, KM_SLEEP); 23183dec9fcdSqs148142 23193dec9fcdSqs148142 /* 23203dec9fcdSqs148142 * Timeout should be set based on the system clock divider. 23213dec9fcdSqs148142 * The following timeout value of 1 assumes that the 23223dec9fcdSqs148142 * granularity (1000) is 3 microseconds running at 300MHz. 23233dec9fcdSqs148142 */ 23243dec9fcdSqs148142 23253dec9fcdSqs148142 hxgep->intr_threshold = RXDMA_RCR_PTHRES_DEFAULT; 23263dec9fcdSqs148142 hxgep->intr_timeout = RXDMA_RCR_TO_DEFAULT; 23273dec9fcdSqs148142 23283dec9fcdSqs148142 /* 23293dec9fcdSqs148142 * Map descriptors from the buffer polls for each dam channel. 23303dec9fcdSqs148142 */ 23313dec9fcdSqs148142 for (i = 0; i < ndmas; i++) { 2332f043ebedSMichael Speer if (((p_hxge_dma_common_t)dma_buf_p[i]) == NULL) { 2333f043ebedSMichael Speer status = HXGE_ERROR; 2334f043ebedSMichael Speer goto hxge_map_rxdma_fail1; 2335f043ebedSMichael Speer } 2336f043ebedSMichael Speer 23373dec9fcdSqs148142 /* 23383dec9fcdSqs148142 * Set up and prepare buffer blocks, descriptors and mailbox. 23393dec9fcdSqs148142 */ 23403dec9fcdSqs148142 channel = ((p_hxge_dma_common_t)dma_buf_p[i])->dma_channel; 23413dec9fcdSqs148142 status = hxge_map_rxdma_channel(hxgep, channel, 23423dec9fcdSqs148142 (p_hxge_dma_common_t *)&dma_buf_p[i], 23433dec9fcdSqs148142 (p_rx_rbr_ring_t *)&rbr_rings[i], 23448ad8db65SMichael Speer num_chunks[i], 23458ad8db65SMichael Speer (p_hxge_dma_common_t *)&dma_rbr_cntl_p[i], 23468ad8db65SMichael Speer (p_hxge_dma_common_t *)&dma_rcr_cntl_p[i], 23478ad8db65SMichael Speer (p_hxge_dma_common_t *)&dma_mbox_cntl_p[i], 23483dec9fcdSqs148142 (p_rx_rcr_ring_t *)&rcr_rings[i], 23493dec9fcdSqs148142 (p_rx_mbox_t *)&rx_mbox_p[i]); 23503dec9fcdSqs148142 if (status != HXGE_OK) { 23513dec9fcdSqs148142 goto hxge_map_rxdma_fail1; 23523dec9fcdSqs148142 } 23533dec9fcdSqs148142 rbr_rings[i]->index = (uint16_t)i; 23543dec9fcdSqs148142 rcr_rings[i]->index = (uint16_t)i; 23553dec9fcdSqs148142 rcr_rings[i]->rdc_stats = &hxgep->statsp->rdc_stats[i]; 23563dec9fcdSqs148142 } 23573dec9fcdSqs148142 23583dec9fcdSqs148142 rx_rbr_rings->ndmas = rx_rcr_rings->ndmas = ndmas; 23593dec9fcdSqs148142 rx_rbr_rings->rbr_rings = rbr_rings; 23603dec9fcdSqs148142 hxgep->rx_rbr_rings = rx_rbr_rings; 23613dec9fcdSqs148142 rx_rcr_rings->rcr_rings = rcr_rings; 23623dec9fcdSqs148142 hxgep->rx_rcr_rings = rx_rcr_rings; 23633dec9fcdSqs148142 23643dec9fcdSqs148142 rx_mbox_areas_p->rxmbox_areas = rx_mbox_p; 23653dec9fcdSqs148142 hxgep->rx_mbox_areas_p = rx_mbox_areas_p; 23663dec9fcdSqs148142 23673dec9fcdSqs148142 goto hxge_map_rxdma_exit; 23683dec9fcdSqs148142 23693dec9fcdSqs148142 hxge_map_rxdma_fail1: 23703dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 23713dec9fcdSqs148142 "==> hxge_map_rxdma: unmap rbr,rcr (status 0x%x channel %d i %d)", 23723dec9fcdSqs148142 status, channel, i)); 23733dec9fcdSqs148142 i--; 23743dec9fcdSqs148142 for (; i >= 0; i--) { 23753dec9fcdSqs148142 channel = ((p_hxge_dma_common_t)dma_buf_p[i])->dma_channel; 23763dec9fcdSqs148142 hxge_unmap_rxdma_channel(hxgep, channel, 23773dec9fcdSqs148142 rbr_rings[i], rcr_rings[i], rx_mbox_p[i]); 23783dec9fcdSqs148142 } 23793dec9fcdSqs148142 23803dec9fcdSqs148142 KMEM_FREE(rbr_rings, sizeof (p_rx_rbr_ring_t) * ndmas); 23813dec9fcdSqs148142 KMEM_FREE(rx_rbr_rings, sizeof (rx_rbr_rings_t)); 23823dec9fcdSqs148142 KMEM_FREE(rcr_rings, sizeof (p_rx_rcr_ring_t) * ndmas); 23833dec9fcdSqs148142 KMEM_FREE(rx_rcr_rings, sizeof (rx_rcr_rings_t)); 23843dec9fcdSqs148142 KMEM_FREE(rx_mbox_p, sizeof (p_rx_mbox_t) * ndmas); 23853dec9fcdSqs148142 KMEM_FREE(rx_mbox_areas_p, sizeof (rx_mbox_areas_t)); 23863dec9fcdSqs148142 23873dec9fcdSqs148142 hxge_map_rxdma_exit: 23883dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 23893dec9fcdSqs148142 "<== hxge_map_rxdma: (status 0x%x channel %d)", status, channel)); 23903dec9fcdSqs148142 23913dec9fcdSqs148142 return (status); 23923dec9fcdSqs148142 } 23933dec9fcdSqs148142 23943dec9fcdSqs148142 static void 23953dec9fcdSqs148142 hxge_unmap_rxdma(p_hxge_t hxgep) 23963dec9fcdSqs148142 { 23973dec9fcdSqs148142 int i, ndmas; 23983dec9fcdSqs148142 uint16_t channel; 23993dec9fcdSqs148142 p_rx_rbr_rings_t rx_rbr_rings; 24003dec9fcdSqs148142 p_rx_rbr_ring_t *rbr_rings; 24013dec9fcdSqs148142 p_rx_rcr_rings_t rx_rcr_rings; 24023dec9fcdSqs148142 p_rx_rcr_ring_t *rcr_rings; 24033dec9fcdSqs148142 p_rx_mbox_areas_t rx_mbox_areas_p; 24043dec9fcdSqs148142 p_rx_mbox_t *rx_mbox_p; 24053dec9fcdSqs148142 p_hxge_dma_pool_t dma_buf_poolp; 24068ad8db65SMichael Speer p_hxge_dma_pool_t dma_rbr_cntl_poolp; 24078ad8db65SMichael Speer p_hxge_dma_pool_t dma_rcr_cntl_poolp; 24088ad8db65SMichael Speer p_hxge_dma_pool_t dma_mbox_cntl_poolp; 24093dec9fcdSqs148142 p_hxge_dma_common_t *dma_buf_p; 24103dec9fcdSqs148142 24113dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_unmap_rxdma")); 24123dec9fcdSqs148142 24133dec9fcdSqs148142 dma_buf_poolp = hxgep->rx_buf_pool_p; 24148ad8db65SMichael Speer dma_rbr_cntl_poolp = hxgep->rx_rbr_cntl_pool_p; 24158ad8db65SMichael Speer dma_rcr_cntl_poolp = hxgep->rx_rcr_cntl_pool_p; 24168ad8db65SMichael Speer dma_mbox_cntl_poolp = hxgep->rx_mbox_cntl_pool_p; 24173dec9fcdSqs148142 24188ad8db65SMichael Speer if (!dma_buf_poolp->buf_allocated || 24198ad8db65SMichael Speer !dma_rbr_cntl_poolp->buf_allocated || 24208ad8db65SMichael Speer !dma_rcr_cntl_poolp->buf_allocated || 24218ad8db65SMichael Speer !dma_mbox_cntl_poolp->buf_allocated) { 24223dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 24233dec9fcdSqs148142 "<== hxge_unmap_rxdma: NULL buf pointers")); 24243dec9fcdSqs148142 return; 24253dec9fcdSqs148142 } 24263dec9fcdSqs148142 24273dec9fcdSqs148142 rx_rbr_rings = hxgep->rx_rbr_rings; 24283dec9fcdSqs148142 rx_rcr_rings = hxgep->rx_rcr_rings; 24293dec9fcdSqs148142 if (rx_rbr_rings == NULL || rx_rcr_rings == NULL) { 24303dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 24318ad8db65SMichael Speer "<== hxge_unmap_rxdma: NULL pointers")); 24323dec9fcdSqs148142 return; 24333dec9fcdSqs148142 } 24343dec9fcdSqs148142 24353dec9fcdSqs148142 ndmas = rx_rbr_rings->ndmas; 24363dec9fcdSqs148142 if (!ndmas) { 24373dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 24383dec9fcdSqs148142 "<== hxge_unmap_rxdma: no channel")); 24393dec9fcdSqs148142 return; 24403dec9fcdSqs148142 } 24413dec9fcdSqs148142 24423dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 24433dec9fcdSqs148142 "==> hxge_unmap_rxdma (ndmas %d)", ndmas)); 24443dec9fcdSqs148142 24453dec9fcdSqs148142 rbr_rings = rx_rbr_rings->rbr_rings; 24463dec9fcdSqs148142 rcr_rings = rx_rcr_rings->rcr_rings; 24473dec9fcdSqs148142 rx_mbox_areas_p = hxgep->rx_mbox_areas_p; 24483dec9fcdSqs148142 rx_mbox_p = rx_mbox_areas_p->rxmbox_areas; 24493dec9fcdSqs148142 dma_buf_p = dma_buf_poolp->dma_buf_pool_p; 24503dec9fcdSqs148142 24513dec9fcdSqs148142 for (i = 0; i < ndmas; i++) { 24523dec9fcdSqs148142 channel = ((p_hxge_dma_common_t)dma_buf_p[i])->dma_channel; 24533dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 24543dec9fcdSqs148142 "==> hxge_unmap_rxdma (ndmas %d) channel %d", 24553dec9fcdSqs148142 ndmas, channel)); 24563dec9fcdSqs148142 (void) hxge_unmap_rxdma_channel(hxgep, channel, 24573dec9fcdSqs148142 (p_rx_rbr_ring_t)rbr_rings[i], 24583dec9fcdSqs148142 (p_rx_rcr_ring_t)rcr_rings[i], 24593dec9fcdSqs148142 (p_rx_mbox_t)rx_mbox_p[i]); 24603dec9fcdSqs148142 } 24613dec9fcdSqs148142 24623dec9fcdSqs148142 KMEM_FREE(rx_rbr_rings, sizeof (rx_rbr_rings_t)); 24633dec9fcdSqs148142 KMEM_FREE(rbr_rings, sizeof (p_rx_rbr_ring_t) * ndmas); 24643dec9fcdSqs148142 KMEM_FREE(rx_rcr_rings, sizeof (rx_rcr_rings_t)); 24653dec9fcdSqs148142 KMEM_FREE(rcr_rings, sizeof (p_rx_rcr_ring_t) * ndmas); 24663dec9fcdSqs148142 KMEM_FREE(rx_mbox_areas_p, sizeof (rx_mbox_areas_t)); 24673dec9fcdSqs148142 KMEM_FREE(rx_mbox_p, sizeof (p_rx_mbox_t) * ndmas); 24683dec9fcdSqs148142 24693dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_unmap_rxdma")); 24703dec9fcdSqs148142 } 24713dec9fcdSqs148142 24723dec9fcdSqs148142 hxge_status_t 24733dec9fcdSqs148142 hxge_map_rxdma_channel(p_hxge_t hxgep, uint16_t channel, 24743dec9fcdSqs148142 p_hxge_dma_common_t *dma_buf_p, p_rx_rbr_ring_t *rbr_p, 24758ad8db65SMichael Speer uint32_t num_chunks, p_hxge_dma_common_t *dma_rbr_cntl_p, 24768ad8db65SMichael Speer p_hxge_dma_common_t *dma_rcr_cntl_p, p_hxge_dma_common_t *dma_mbox_cntl_p, 24773dec9fcdSqs148142 p_rx_rcr_ring_t *rcr_p, p_rx_mbox_t *rx_mbox_p) 24783dec9fcdSqs148142 { 24793dec9fcdSqs148142 int status = HXGE_OK; 24803dec9fcdSqs148142 24813dec9fcdSqs148142 /* 24823dec9fcdSqs148142 * Set up and prepare buffer blocks, descriptors and mailbox. 24833dec9fcdSqs148142 */ 24843dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 24853dec9fcdSqs148142 "==> hxge_map_rxdma_channel (channel %d)", channel)); 24863dec9fcdSqs148142 24873dec9fcdSqs148142 /* 24883dec9fcdSqs148142 * Receive buffer blocks 24893dec9fcdSqs148142 */ 24903dec9fcdSqs148142 status = hxge_map_rxdma_channel_buf_ring(hxgep, channel, 24913dec9fcdSqs148142 dma_buf_p, rbr_p, num_chunks); 24923dec9fcdSqs148142 if (status != HXGE_OK) { 24933dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 24943dec9fcdSqs148142 "==> hxge_map_rxdma_channel (channel %d): " 24953dec9fcdSqs148142 "map buffer failed 0x%x", channel, status)); 24963dec9fcdSqs148142 goto hxge_map_rxdma_channel_exit; 24973dec9fcdSqs148142 } 24983dec9fcdSqs148142 24993dec9fcdSqs148142 /* 25003dec9fcdSqs148142 * Receive block ring, completion ring and mailbox. 25013dec9fcdSqs148142 */ 25023dec9fcdSqs148142 status = hxge_map_rxdma_channel_cfg_ring(hxgep, channel, 25038ad8db65SMichael Speer dma_rbr_cntl_p, dma_rcr_cntl_p, dma_mbox_cntl_p, 25048ad8db65SMichael Speer rbr_p, rcr_p, rx_mbox_p); 25053dec9fcdSqs148142 if (status != HXGE_OK) { 25063dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 25073dec9fcdSqs148142 "==> hxge_map_rxdma_channel (channel %d): " 25083dec9fcdSqs148142 "map config failed 0x%x", channel, status)); 25093dec9fcdSqs148142 goto hxge_map_rxdma_channel_fail2; 25103dec9fcdSqs148142 } 25113dec9fcdSqs148142 goto hxge_map_rxdma_channel_exit; 25123dec9fcdSqs148142 25133dec9fcdSqs148142 hxge_map_rxdma_channel_fail3: 25143dec9fcdSqs148142 /* Free rbr, rcr */ 25153dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 25163dec9fcdSqs148142 "==> hxge_map_rxdma_channel: free rbr/rcr (status 0x%x channel %d)", 25173dec9fcdSqs148142 status, channel)); 25183dec9fcdSqs148142 hxge_unmap_rxdma_channel_cfg_ring(hxgep, *rcr_p, *rx_mbox_p); 25193dec9fcdSqs148142 25203dec9fcdSqs148142 hxge_map_rxdma_channel_fail2: 25213dec9fcdSqs148142 /* Free buffer blocks */ 25223dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 25233dec9fcdSqs148142 "==> hxge_map_rxdma_channel: free rx buffers" 25243dec9fcdSqs148142 "(hxgep 0x%x status 0x%x channel %d)", 25253dec9fcdSqs148142 hxgep, status, channel)); 25263dec9fcdSqs148142 hxge_unmap_rxdma_channel_buf_ring(hxgep, *rbr_p); 25273dec9fcdSqs148142 25283dec9fcdSqs148142 status = HXGE_ERROR; 25293dec9fcdSqs148142 25303dec9fcdSqs148142 hxge_map_rxdma_channel_exit: 25313dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 25323dec9fcdSqs148142 "<== hxge_map_rxdma_channel: (hxgep 0x%x status 0x%x channel %d)", 25333dec9fcdSqs148142 hxgep, status, channel)); 25343dec9fcdSqs148142 25353dec9fcdSqs148142 return (status); 25363dec9fcdSqs148142 } 25373dec9fcdSqs148142 25383dec9fcdSqs148142 /*ARGSUSED*/ 25393dec9fcdSqs148142 static void 25403dec9fcdSqs148142 hxge_unmap_rxdma_channel(p_hxge_t hxgep, uint16_t channel, 25413dec9fcdSqs148142 p_rx_rbr_ring_t rbr_p, p_rx_rcr_ring_t rcr_p, p_rx_mbox_t rx_mbox_p) 25423dec9fcdSqs148142 { 25433dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 25443dec9fcdSqs148142 "==> hxge_unmap_rxdma_channel (channel %d)", channel)); 25453dec9fcdSqs148142 25463dec9fcdSqs148142 /* 25473dec9fcdSqs148142 * unmap receive block ring, completion ring and mailbox. 25483dec9fcdSqs148142 */ 25493dec9fcdSqs148142 (void) hxge_unmap_rxdma_channel_cfg_ring(hxgep, rcr_p, rx_mbox_p); 25503dec9fcdSqs148142 25513dec9fcdSqs148142 /* unmap buffer blocks */ 25523dec9fcdSqs148142 (void) hxge_unmap_rxdma_channel_buf_ring(hxgep, rbr_p); 25533dec9fcdSqs148142 25543dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_unmap_rxdma_channel")); 25553dec9fcdSqs148142 } 25563dec9fcdSqs148142 25573dec9fcdSqs148142 /*ARGSUSED*/ 25583dec9fcdSqs148142 static hxge_status_t 25593dec9fcdSqs148142 hxge_map_rxdma_channel_cfg_ring(p_hxge_t hxgep, uint16_t dma_channel, 25608ad8db65SMichael Speer p_hxge_dma_common_t *dma_rbr_cntl_p, p_hxge_dma_common_t *dma_rcr_cntl_p, 25618ad8db65SMichael Speer p_hxge_dma_common_t *dma_mbox_cntl_p, p_rx_rbr_ring_t *rbr_p, 25623dec9fcdSqs148142 p_rx_rcr_ring_t *rcr_p, p_rx_mbox_t *rx_mbox_p) 25633dec9fcdSqs148142 { 25643dec9fcdSqs148142 p_rx_rbr_ring_t rbrp; 25653dec9fcdSqs148142 p_rx_rcr_ring_t rcrp; 25663dec9fcdSqs148142 p_rx_mbox_t mboxp; 25673dec9fcdSqs148142 p_hxge_dma_common_t cntl_dmap; 25683dec9fcdSqs148142 p_hxge_dma_common_t dmap; 25693dec9fcdSqs148142 p_rx_msg_t *rx_msg_ring; 25703dec9fcdSqs148142 p_rx_msg_t rx_msg_p; 25713dec9fcdSqs148142 rdc_rbr_cfg_a_t *rcfga_p; 25723dec9fcdSqs148142 rdc_rbr_cfg_b_t *rcfgb_p; 25733dec9fcdSqs148142 rdc_rcr_cfg_a_t *cfga_p; 25743dec9fcdSqs148142 rdc_rcr_cfg_b_t *cfgb_p; 25753dec9fcdSqs148142 rdc_rx_cfg1_t *cfig1_p; 25763dec9fcdSqs148142 rdc_rx_cfg2_t *cfig2_p; 25773dec9fcdSqs148142 rdc_rbr_kick_t *kick_p; 25783dec9fcdSqs148142 uint32_t dmaaddrp; 25793dec9fcdSqs148142 uint32_t *rbr_vaddrp; 25803dec9fcdSqs148142 uint32_t bkaddr; 25813dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 25823dec9fcdSqs148142 int i; 25833dec9fcdSqs148142 uint32_t hxge_port_rcr_size; 25843dec9fcdSqs148142 25853dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 25863dec9fcdSqs148142 "==> hxge_map_rxdma_channel_cfg_ring")); 25873dec9fcdSqs148142 25888ad8db65SMichael Speer cntl_dmap = *dma_rbr_cntl_p; 25893dec9fcdSqs148142 25908ad8db65SMichael Speer /* 25918ad8db65SMichael Speer * Map in the receive block ring 25928ad8db65SMichael Speer */ 25933dec9fcdSqs148142 rbrp = *rbr_p; 25943dec9fcdSqs148142 dmap = (p_hxge_dma_common_t)&rbrp->rbr_desc; 25953dec9fcdSqs148142 hxge_setup_dma_common(dmap, cntl_dmap, rbrp->rbb_max, 4); 25963dec9fcdSqs148142 25973dec9fcdSqs148142 /* 25983dec9fcdSqs148142 * Zero out buffer block ring descriptors. 25993dec9fcdSqs148142 */ 26003dec9fcdSqs148142 bzero((caddr_t)dmap->kaddrp, dmap->alength); 26013dec9fcdSqs148142 26023dec9fcdSqs148142 rcfga_p = &(rbrp->rbr_cfga); 26033dec9fcdSqs148142 rcfgb_p = &(rbrp->rbr_cfgb); 26043dec9fcdSqs148142 kick_p = &(rbrp->rbr_kick); 26053dec9fcdSqs148142 rcfga_p->value = 0; 26063dec9fcdSqs148142 rcfgb_p->value = 0; 26073dec9fcdSqs148142 kick_p->value = 0; 26083dec9fcdSqs148142 rbrp->rbr_addr = dmap->dma_cookie.dmac_laddress; 26093dec9fcdSqs148142 rcfga_p->value = (rbrp->rbr_addr & 26103dec9fcdSqs148142 (RBR_CFIG_A_STDADDR_MASK | RBR_CFIG_A_STDADDR_BASE_MASK)); 26113dec9fcdSqs148142 rcfga_p->value |= ((uint64_t)rbrp->rbb_max << RBR_CFIG_A_LEN_SHIFT); 26123dec9fcdSqs148142 26133dec9fcdSqs148142 /* XXXX: how to choose packet buffer sizes */ 26143dec9fcdSqs148142 rcfgb_p->bits.bufsz0 = rbrp->pkt_buf_size0; 26153dec9fcdSqs148142 rcfgb_p->bits.vld0 = 1; 26163dec9fcdSqs148142 rcfgb_p->bits.bufsz1 = rbrp->pkt_buf_size1; 26173dec9fcdSqs148142 rcfgb_p->bits.vld1 = 1; 26183dec9fcdSqs148142 rcfgb_p->bits.bufsz2 = rbrp->pkt_buf_size2; 26193dec9fcdSqs148142 rcfgb_p->bits.vld2 = 1; 26203dec9fcdSqs148142 rcfgb_p->bits.bksize = hxgep->rx_bksize_code; 26213dec9fcdSqs148142 26223dec9fcdSqs148142 /* 26233dec9fcdSqs148142 * For each buffer block, enter receive block address to the ring. 26243dec9fcdSqs148142 */ 26253dec9fcdSqs148142 rbr_vaddrp = (uint32_t *)dmap->kaddrp; 26263dec9fcdSqs148142 rbrp->rbr_desc_vp = (uint32_t *)dmap->kaddrp; 26273dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 26283dec9fcdSqs148142 "==> hxge_map_rxdma_channel_cfg_ring: channel %d " 26293dec9fcdSqs148142 "rbr_vaddrp $%p", dma_channel, rbr_vaddrp)); 26303dec9fcdSqs148142 26313dec9fcdSqs148142 rx_msg_ring = rbrp->rx_msg_ring; 26323dec9fcdSqs148142 for (i = 0; i < rbrp->tnblocks; i++) { 26333dec9fcdSqs148142 rx_msg_p = rx_msg_ring[i]; 26343dec9fcdSqs148142 rx_msg_p->hxgep = hxgep; 26353dec9fcdSqs148142 rx_msg_p->rx_rbr_p = rbrp; 26363dec9fcdSqs148142 bkaddr = (uint32_t) 26373dec9fcdSqs148142 ((rx_msg_p->buf_dma.dma_cookie.dmac_laddress >> 26383dec9fcdSqs148142 RBR_BKADDR_SHIFT)); 26393dec9fcdSqs148142 rx_msg_p->free = B_FALSE; 26403dec9fcdSqs148142 rx_msg_p->max_usage_cnt = 0xbaddcafe; 26413dec9fcdSqs148142 26423dec9fcdSqs148142 *rbr_vaddrp++ = bkaddr; 26433dec9fcdSqs148142 } 26443dec9fcdSqs148142 26453dec9fcdSqs148142 kick_p->bits.bkadd = rbrp->rbb_max; 26463dec9fcdSqs148142 rbrp->rbr_wr_index = (rbrp->rbb_max - 1); 26473dec9fcdSqs148142 26483dec9fcdSqs148142 rbrp->rbr_rd_index = 0; 26493dec9fcdSqs148142 26503dec9fcdSqs148142 rbrp->rbr_consumed = 0; 265157c5371aSQiyan Sun - Sun Microsystems - San Diego United States rbrp->rbr_used = 0; 26523dec9fcdSqs148142 rbrp->rbr_use_bcopy = B_TRUE; 26533dec9fcdSqs148142 rbrp->rbr_bufsize_type = RCR_PKTBUFSZ_0; 26543dec9fcdSqs148142 26553dec9fcdSqs148142 /* 26563dec9fcdSqs148142 * Do bcopy on packets greater than bcopy size once the lo threshold is 26573dec9fcdSqs148142 * reached. This lo threshold should be less than the hi threshold. 26583dec9fcdSqs148142 * 26593dec9fcdSqs148142 * Do bcopy on every packet once the hi threshold is reached. 26603dec9fcdSqs148142 */ 26613dec9fcdSqs148142 if (hxge_rx_threshold_lo >= hxge_rx_threshold_hi) { 26623dec9fcdSqs148142 /* default it to use hi */ 26633dec9fcdSqs148142 hxge_rx_threshold_lo = hxge_rx_threshold_hi; 26643dec9fcdSqs148142 } 26653dec9fcdSqs148142 if (hxge_rx_buf_size_type > HXGE_RBR_TYPE2) { 26663dec9fcdSqs148142 hxge_rx_buf_size_type = HXGE_RBR_TYPE2; 26673dec9fcdSqs148142 } 26683dec9fcdSqs148142 rbrp->rbr_bufsize_type = hxge_rx_buf_size_type; 26693dec9fcdSqs148142 26703dec9fcdSqs148142 switch (hxge_rx_threshold_hi) { 26713dec9fcdSqs148142 default: 26723dec9fcdSqs148142 case HXGE_RX_COPY_NONE: 26733dec9fcdSqs148142 /* Do not do bcopy at all */ 26743dec9fcdSqs148142 rbrp->rbr_use_bcopy = B_FALSE; 26753dec9fcdSqs148142 rbrp->rbr_threshold_hi = rbrp->rbb_max; 26763dec9fcdSqs148142 break; 26773dec9fcdSqs148142 26783dec9fcdSqs148142 case HXGE_RX_COPY_1: 26793dec9fcdSqs148142 case HXGE_RX_COPY_2: 26803dec9fcdSqs148142 case HXGE_RX_COPY_3: 26813dec9fcdSqs148142 case HXGE_RX_COPY_4: 26823dec9fcdSqs148142 case HXGE_RX_COPY_5: 26833dec9fcdSqs148142 case HXGE_RX_COPY_6: 26843dec9fcdSqs148142 case HXGE_RX_COPY_7: 26853dec9fcdSqs148142 rbrp->rbr_threshold_hi = 26863dec9fcdSqs148142 rbrp->rbb_max * (hxge_rx_threshold_hi) / 26873dec9fcdSqs148142 HXGE_RX_BCOPY_SCALE; 26883dec9fcdSqs148142 break; 26893dec9fcdSqs148142 26903dec9fcdSqs148142 case HXGE_RX_COPY_ALL: 26913dec9fcdSqs148142 rbrp->rbr_threshold_hi = 0; 26923dec9fcdSqs148142 break; 26933dec9fcdSqs148142 } 26943dec9fcdSqs148142 26953dec9fcdSqs148142 switch (hxge_rx_threshold_lo) { 26963dec9fcdSqs148142 default: 26973dec9fcdSqs148142 case HXGE_RX_COPY_NONE: 26983dec9fcdSqs148142 /* Do not do bcopy at all */ 26993dec9fcdSqs148142 if (rbrp->rbr_use_bcopy) { 27003dec9fcdSqs148142 rbrp->rbr_use_bcopy = B_FALSE; 27013dec9fcdSqs148142 } 27023dec9fcdSqs148142 rbrp->rbr_threshold_lo = rbrp->rbb_max; 27033dec9fcdSqs148142 break; 27043dec9fcdSqs148142 27053dec9fcdSqs148142 case HXGE_RX_COPY_1: 27063dec9fcdSqs148142 case HXGE_RX_COPY_2: 27073dec9fcdSqs148142 case HXGE_RX_COPY_3: 27083dec9fcdSqs148142 case HXGE_RX_COPY_4: 27093dec9fcdSqs148142 case HXGE_RX_COPY_5: 27103dec9fcdSqs148142 case HXGE_RX_COPY_6: 27113dec9fcdSqs148142 case HXGE_RX_COPY_7: 27123dec9fcdSqs148142 rbrp->rbr_threshold_lo = 27133dec9fcdSqs148142 rbrp->rbb_max * (hxge_rx_threshold_lo) / 27143dec9fcdSqs148142 HXGE_RX_BCOPY_SCALE; 27153dec9fcdSqs148142 break; 27163dec9fcdSqs148142 27173dec9fcdSqs148142 case HXGE_RX_COPY_ALL: 27183dec9fcdSqs148142 rbrp->rbr_threshold_lo = 0; 27193dec9fcdSqs148142 break; 27203dec9fcdSqs148142 } 27213dec9fcdSqs148142 27223dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 27233dec9fcdSqs148142 "hxge_map_rxdma_channel_cfg_ring: channel %d rbb_max %d " 27243dec9fcdSqs148142 "rbrp->rbr_bufsize_type %d rbb_threshold_hi %d " 27253dec9fcdSqs148142 "rbb_threshold_lo %d", 27263dec9fcdSqs148142 dma_channel, rbrp->rbb_max, rbrp->rbr_bufsize_type, 27273dec9fcdSqs148142 rbrp->rbr_threshold_hi, rbrp->rbr_threshold_lo)); 27283dec9fcdSqs148142 27293dec9fcdSqs148142 /* Map in the receive completion ring */ 27303dec9fcdSqs148142 rcrp = (p_rx_rcr_ring_t)KMEM_ZALLOC(sizeof (rx_rcr_ring_t), KM_SLEEP); 27316ffca240SMichael Speer MUTEX_INIT(&rcrp->lock, NULL, MUTEX_DRIVER, 27326ffca240SMichael Speer (void *) hxgep->interrupt_cookie); 27333dec9fcdSqs148142 rcrp->rdc = dma_channel; 2734069fd767SMichael Speer rcrp->hxgep = hxgep; 27353dec9fcdSqs148142 27363dec9fcdSqs148142 hxge_port_rcr_size = hxgep->hxge_port_rcr_size; 27373dec9fcdSqs148142 rcrp->comp_size = hxge_port_rcr_size; 27383dec9fcdSqs148142 rcrp->comp_wrap_mask = hxge_port_rcr_size - 1; 27393dec9fcdSqs148142 27408ad8db65SMichael Speer cntl_dmap = *dma_rcr_cntl_p; 27418ad8db65SMichael Speer 27423dec9fcdSqs148142 dmap = (p_hxge_dma_common_t)&rcrp->rcr_desc; 27433dec9fcdSqs148142 hxge_setup_dma_common(dmap, cntl_dmap, rcrp->comp_size, 27443dec9fcdSqs148142 sizeof (rcr_entry_t)); 27453dec9fcdSqs148142 rcrp->comp_rd_index = 0; 27463dec9fcdSqs148142 rcrp->comp_wt_index = 0; 27473dec9fcdSqs148142 rcrp->rcr_desc_rd_head_p = rcrp->rcr_desc_first_p = 27483dec9fcdSqs148142 (p_rcr_entry_t)DMA_COMMON_VPTR(rcrp->rcr_desc); 2749fe930412Sqs148142 #if defined(__i386) 2750fe930412Sqs148142 rcrp->rcr_desc_rd_head_pp = rcrp->rcr_desc_first_pp = 2751fe930412Sqs148142 (p_rcr_entry_t)(uint32_t)DMA_COMMON_IOADDR(rcrp->rcr_desc); 2752fe930412Sqs148142 #else 27533dec9fcdSqs148142 rcrp->rcr_desc_rd_head_pp = rcrp->rcr_desc_first_pp = 27543dec9fcdSqs148142 (p_rcr_entry_t)DMA_COMMON_IOADDR(rcrp->rcr_desc); 2755fe930412Sqs148142 #endif 27563dec9fcdSqs148142 rcrp->rcr_desc_last_p = rcrp->rcr_desc_rd_head_p + 27573dec9fcdSqs148142 (hxge_port_rcr_size - 1); 27583dec9fcdSqs148142 rcrp->rcr_desc_last_pp = rcrp->rcr_desc_rd_head_pp + 27593dec9fcdSqs148142 (hxge_port_rcr_size - 1); 27603dec9fcdSqs148142 2761a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States rcrp->rcr_tail_begin = DMA_COMMON_IOADDR(rcrp->rcr_desc); 2762a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States rcrp->rcr_tail_begin = (rcrp->rcr_tail_begin & 0x7ffffULL) >> 3; 2763a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 27643dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 27653dec9fcdSqs148142 "==> hxge_map_rxdma_channel_cfg_ring: channel %d " 27663dec9fcdSqs148142 "rbr_vaddrp $%p rcr_desc_rd_head_p $%p " 27673dec9fcdSqs148142 "rcr_desc_rd_head_pp $%p rcr_desc_rd_last_p $%p " 27683dec9fcdSqs148142 "rcr_desc_rd_last_pp $%p ", 27693dec9fcdSqs148142 dma_channel, rbr_vaddrp, rcrp->rcr_desc_rd_head_p, 27703dec9fcdSqs148142 rcrp->rcr_desc_rd_head_pp, rcrp->rcr_desc_last_p, 27713dec9fcdSqs148142 rcrp->rcr_desc_last_pp)); 27723dec9fcdSqs148142 27733dec9fcdSqs148142 /* 27743dec9fcdSqs148142 * Zero out buffer block ring descriptors. 27753dec9fcdSqs148142 */ 27763dec9fcdSqs148142 bzero((caddr_t)dmap->kaddrp, dmap->alength); 27773dec9fcdSqs148142 rcrp->intr_timeout = hxgep->intr_timeout; 27783dec9fcdSqs148142 rcrp->intr_threshold = hxgep->intr_threshold; 27793dec9fcdSqs148142 rcrp->full_hdr_flag = B_FALSE; 27803dec9fcdSqs148142 rcrp->sw_priv_hdr_len = 0; 27813dec9fcdSqs148142 27823dec9fcdSqs148142 cfga_p = &(rcrp->rcr_cfga); 27833dec9fcdSqs148142 cfgb_p = &(rcrp->rcr_cfgb); 27843dec9fcdSqs148142 cfga_p->value = 0; 27853dec9fcdSqs148142 cfgb_p->value = 0; 27863dec9fcdSqs148142 rcrp->rcr_addr = dmap->dma_cookie.dmac_laddress; 27873dec9fcdSqs148142 27883dec9fcdSqs148142 cfga_p->value = (rcrp->rcr_addr & 27893dec9fcdSqs148142 (RCRCFIG_A_STADDR_MASK | RCRCFIG_A_STADDR_BASE_MASK)); 27903dec9fcdSqs148142 27913dec9fcdSqs148142 cfga_p->value |= ((uint64_t)rcrp->comp_size << RCRCFIG_A_LEN_SHIF); 27923dec9fcdSqs148142 27933dec9fcdSqs148142 /* 27943dec9fcdSqs148142 * Timeout should be set based on the system clock divider. The 27953dec9fcdSqs148142 * following timeout value of 1 assumes that the granularity (1000) is 27963dec9fcdSqs148142 * 3 microseconds running at 300MHz. 27973dec9fcdSqs148142 */ 27983dec9fcdSqs148142 cfgb_p->bits.pthres = rcrp->intr_threshold; 27993dec9fcdSqs148142 cfgb_p->bits.timeout = rcrp->intr_timeout; 28003dec9fcdSqs148142 cfgb_p->bits.entout = 1; 28013dec9fcdSqs148142 28023dec9fcdSqs148142 /* Map in the mailbox */ 28038ad8db65SMichael Speer cntl_dmap = *dma_mbox_cntl_p; 28043dec9fcdSqs148142 mboxp = (p_rx_mbox_t)KMEM_ZALLOC(sizeof (rx_mbox_t), KM_SLEEP); 28053dec9fcdSqs148142 dmap = (p_hxge_dma_common_t)&mboxp->rx_mbox; 28063dec9fcdSqs148142 hxge_setup_dma_common(dmap, cntl_dmap, 1, sizeof (rxdma_mailbox_t)); 28073dec9fcdSqs148142 cfig1_p = (rdc_rx_cfg1_t *)&mboxp->rx_cfg1; 28083dec9fcdSqs148142 cfig2_p = (rdc_rx_cfg2_t *)&mboxp->rx_cfg2; 28093dec9fcdSqs148142 cfig1_p->value = cfig2_p->value = 0; 28103dec9fcdSqs148142 28113dec9fcdSqs148142 mboxp->mbox_addr = dmap->dma_cookie.dmac_laddress; 28123dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 28133dec9fcdSqs148142 "==> hxge_map_rxdma_channel_cfg_ring: " 28143dec9fcdSqs148142 "channel %d cfg1 0x%016llx cfig2 0x%016llx cookie 0x%016llx", 28153dec9fcdSqs148142 dma_channel, cfig1_p->value, cfig2_p->value, 28163dec9fcdSqs148142 mboxp->mbox_addr)); 28173dec9fcdSqs148142 28183dec9fcdSqs148142 dmaaddrp = (uint32_t)((dmap->dma_cookie.dmac_laddress >> 32) & 0xfff); 28193dec9fcdSqs148142 cfig1_p->bits.mbaddr_h = dmaaddrp; 28203dec9fcdSqs148142 28213dec9fcdSqs148142 dmaaddrp = (uint32_t)(dmap->dma_cookie.dmac_laddress & 0xffffffff); 28223dec9fcdSqs148142 dmaaddrp = (uint32_t)(dmap->dma_cookie.dmac_laddress & 28233dec9fcdSqs148142 RXDMA_CFIG2_MBADDR_L_MASK); 28243dec9fcdSqs148142 28253dec9fcdSqs148142 cfig2_p->bits.mbaddr_l = (dmaaddrp >> RXDMA_CFIG2_MBADDR_L_SHIFT); 28263dec9fcdSqs148142 28273dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 28283dec9fcdSqs148142 "==> hxge_map_rxdma_channel_cfg_ring: channel %d damaddrp $%p " 28293dec9fcdSqs148142 "cfg1 0x%016llx cfig2 0x%016llx", 28303dec9fcdSqs148142 dma_channel, dmaaddrp, cfig1_p->value, cfig2_p->value)); 28313dec9fcdSqs148142 28323dec9fcdSqs148142 cfig2_p->bits.full_hdr = rcrp->full_hdr_flag; 28333dec9fcdSqs148142 cfig2_p->bits.offset = rcrp->sw_priv_hdr_len; 28343dec9fcdSqs148142 28353dec9fcdSqs148142 rbrp->rx_rcr_p = rcrp; 28363dec9fcdSqs148142 rcrp->rx_rbr_p = rbrp; 28373dec9fcdSqs148142 *rcr_p = rcrp; 28383dec9fcdSqs148142 *rx_mbox_p = mboxp; 28393dec9fcdSqs148142 28403dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 28413dec9fcdSqs148142 "<== hxge_map_rxdma_channel_cfg_ring status 0x%08x", status)); 28423dec9fcdSqs148142 return (status); 28433dec9fcdSqs148142 } 28443dec9fcdSqs148142 28453dec9fcdSqs148142 /*ARGSUSED*/ 28463dec9fcdSqs148142 static void 28473dec9fcdSqs148142 hxge_unmap_rxdma_channel_cfg_ring(p_hxge_t hxgep, 28483dec9fcdSqs148142 p_rx_rcr_ring_t rcr_p, p_rx_mbox_t rx_mbox_p) 28493dec9fcdSqs148142 { 28503dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 28513dec9fcdSqs148142 "==> hxge_unmap_rxdma_channel_cfg_ring: channel %d", rcr_p->rdc)); 28523dec9fcdSqs148142 28536ffca240SMichael Speer MUTEX_DESTROY(&rcr_p->lock); 28543dec9fcdSqs148142 KMEM_FREE(rcr_p, sizeof (rx_rcr_ring_t)); 28553dec9fcdSqs148142 KMEM_FREE(rx_mbox_p, sizeof (rx_mbox_t)); 28563dec9fcdSqs148142 28573dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 28583dec9fcdSqs148142 "<== hxge_unmap_rxdma_channel_cfg_ring")); 28593dec9fcdSqs148142 } 28603dec9fcdSqs148142 28613dec9fcdSqs148142 static hxge_status_t 28623dec9fcdSqs148142 hxge_map_rxdma_channel_buf_ring(p_hxge_t hxgep, uint16_t channel, 28633dec9fcdSqs148142 p_hxge_dma_common_t *dma_buf_p, 28643dec9fcdSqs148142 p_rx_rbr_ring_t *rbr_p, uint32_t num_chunks) 28653dec9fcdSqs148142 { 28663dec9fcdSqs148142 p_rx_rbr_ring_t rbrp; 28673dec9fcdSqs148142 p_hxge_dma_common_t dma_bufp, tmp_bufp; 28683dec9fcdSqs148142 p_rx_msg_t *rx_msg_ring; 28693dec9fcdSqs148142 p_rx_msg_t rx_msg_p; 28703dec9fcdSqs148142 p_mblk_t mblk_p; 28713dec9fcdSqs148142 28723dec9fcdSqs148142 rxring_info_t *ring_info; 28733dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 28743dec9fcdSqs148142 int i, j, index; 28753dec9fcdSqs148142 uint32_t size, bsize, nblocks, nmsgs; 28763dec9fcdSqs148142 28773dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 28783dec9fcdSqs148142 "==> hxge_map_rxdma_channel_buf_ring: channel %d", channel)); 28793dec9fcdSqs148142 28803dec9fcdSqs148142 dma_bufp = tmp_bufp = *dma_buf_p; 28813dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 28823dec9fcdSqs148142 " hxge_map_rxdma_channel_buf_ring: channel %d to map %d " 28833dec9fcdSqs148142 "chunks bufp 0x%016llx", channel, num_chunks, dma_bufp)); 28843dec9fcdSqs148142 28853dec9fcdSqs148142 nmsgs = 0; 28863dec9fcdSqs148142 for (i = 0; i < num_chunks; i++, tmp_bufp++) { 28873dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 28883dec9fcdSqs148142 "==> hxge_map_rxdma_channel_buf_ring: channel %d " 28893dec9fcdSqs148142 "bufp 0x%016llx nblocks %d nmsgs %d", 28903dec9fcdSqs148142 channel, tmp_bufp, tmp_bufp->nblocks, nmsgs)); 28913dec9fcdSqs148142 nmsgs += tmp_bufp->nblocks; 28923dec9fcdSqs148142 } 28933dec9fcdSqs148142 if (!nmsgs) { 28943dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 28953dec9fcdSqs148142 "<== hxge_map_rxdma_channel_buf_ring: channel %d " 28963dec9fcdSqs148142 "no msg blocks", channel)); 28973dec9fcdSqs148142 status = HXGE_ERROR; 28983dec9fcdSqs148142 goto hxge_map_rxdma_channel_buf_ring_exit; 28993dec9fcdSqs148142 } 29003dec9fcdSqs148142 rbrp = (p_rx_rbr_ring_t)KMEM_ZALLOC(sizeof (rx_rbr_ring_t), KM_SLEEP); 29013dec9fcdSqs148142 29023dec9fcdSqs148142 size = nmsgs * sizeof (p_rx_msg_t); 29033dec9fcdSqs148142 rx_msg_ring = KMEM_ZALLOC(size, KM_SLEEP); 29043dec9fcdSqs148142 ring_info = (rxring_info_t *)KMEM_ZALLOC(sizeof (rxring_info_t), 29053dec9fcdSqs148142 KM_SLEEP); 29063dec9fcdSqs148142 29073dec9fcdSqs148142 MUTEX_INIT(&rbrp->lock, NULL, MUTEX_DRIVER, 29083dec9fcdSqs148142 (void *) hxgep->interrupt_cookie); 29093dec9fcdSqs148142 MUTEX_INIT(&rbrp->post_lock, NULL, MUTEX_DRIVER, 29103dec9fcdSqs148142 (void *) hxgep->interrupt_cookie); 2911069fd767SMichael Speer 29123dec9fcdSqs148142 rbrp->rdc = channel; 29133dec9fcdSqs148142 rbrp->num_blocks = num_chunks; 29143dec9fcdSqs148142 rbrp->tnblocks = nmsgs; 29153dec9fcdSqs148142 rbrp->rbb_max = nmsgs; 29163dec9fcdSqs148142 rbrp->rbr_max_size = nmsgs; 29173dec9fcdSqs148142 rbrp->rbr_wrap_mask = (rbrp->rbb_max - 1); 29183dec9fcdSqs148142 29193dec9fcdSqs148142 /* 2920f043ebedSMichael Speer * Buffer sizes: 256, 1K, and 2K. 2921f043ebedSMichael Speer * 2922f043ebedSMichael Speer * Blk 0 size. 29233dec9fcdSqs148142 */ 29243dec9fcdSqs148142 rbrp->pkt_buf_size0 = RBR_BUFSZ0_256B; 29253dec9fcdSqs148142 rbrp->pkt_buf_size0_bytes = RBR_BUFSZ0_256_BYTES; 29263dec9fcdSqs148142 rbrp->hpi_pkt_buf_size0 = SIZE_256B; 29273dec9fcdSqs148142 2928f043ebedSMichael Speer /* 2929f043ebedSMichael Speer * Blk 1 size. 2930f043ebedSMichael Speer */ 29313dec9fcdSqs148142 rbrp->pkt_buf_size1 = RBR_BUFSZ1_1K; 29323dec9fcdSqs148142 rbrp->pkt_buf_size1_bytes = RBR_BUFSZ1_1K_BYTES; 29333dec9fcdSqs148142 rbrp->hpi_pkt_buf_size1 = SIZE_1KB; 29343dec9fcdSqs148142 2935f043ebedSMichael Speer /* 2936f043ebedSMichael Speer * Blk 2 size. 2937f043ebedSMichael Speer */ 29383dec9fcdSqs148142 rbrp->pkt_buf_size2 = RBR_BUFSZ2_2K; 29393dec9fcdSqs148142 rbrp->pkt_buf_size2_bytes = RBR_BUFSZ2_2K_BYTES; 29403dec9fcdSqs148142 rbrp->hpi_pkt_buf_size2 = SIZE_2KB; 2941f043ebedSMichael Speer 2942f043ebedSMichael Speer rbrp->block_size = hxgep->rx_default_block_size; 29433dec9fcdSqs148142 29443dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 29453dec9fcdSqs148142 "==> hxge_map_rxdma_channel_buf_ring: channel %d " 29463dec9fcdSqs148142 "actual rbr max %d rbb_max %d nmsgs %d " 29473dec9fcdSqs148142 "rbrp->block_size %d default_block_size %d " 29483dec9fcdSqs148142 "(config hxge_rbr_size %d hxge_rbr_spare_size %d)", 29493dec9fcdSqs148142 channel, rbrp->rbr_max_size, rbrp->rbb_max, nmsgs, 29503dec9fcdSqs148142 rbrp->block_size, hxgep->rx_default_block_size, 29513dec9fcdSqs148142 hxge_rbr_size, hxge_rbr_spare_size)); 29523dec9fcdSqs148142 29533dec9fcdSqs148142 /* 29543dec9fcdSqs148142 * Map in buffers from the buffer pool. 29553dec9fcdSqs148142 * Note that num_blocks is the num_chunks. For Sparc, there is likely 29563dec9fcdSqs148142 * only one chunk. For x86, there will be many chunks. 29573dec9fcdSqs148142 * Loop over chunks. 29583dec9fcdSqs148142 */ 29593dec9fcdSqs148142 index = 0; 29603dec9fcdSqs148142 for (i = 0; i < rbrp->num_blocks; i++, dma_bufp++) { 29613dec9fcdSqs148142 bsize = dma_bufp->block_size; 29623dec9fcdSqs148142 nblocks = dma_bufp->nblocks; 2963fe930412Sqs148142 #if defined(__i386) 2964fe930412Sqs148142 ring_info->buffer[i].dvma_addr = (uint32_t)dma_bufp->ioaddr_pp; 2965fe930412Sqs148142 #else 29663dec9fcdSqs148142 ring_info->buffer[i].dvma_addr = (uint64_t)dma_bufp->ioaddr_pp; 2967fe930412Sqs148142 #endif 29683dec9fcdSqs148142 ring_info->buffer[i].buf_index = i; 29693dec9fcdSqs148142 ring_info->buffer[i].buf_size = dma_bufp->alength; 29703dec9fcdSqs148142 ring_info->buffer[i].start_index = index; 2971fe930412Sqs148142 #if defined(__i386) 2972fe930412Sqs148142 ring_info->buffer[i].kaddr = (uint32_t)dma_bufp->kaddrp; 2973fe930412Sqs148142 #else 29743dec9fcdSqs148142 ring_info->buffer[i].kaddr = (uint64_t)dma_bufp->kaddrp; 2975fe930412Sqs148142 #endif 29763dec9fcdSqs148142 29773dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 29783dec9fcdSqs148142 " hxge_map_rxdma_channel_buf_ring: map channel %d " 29793dec9fcdSqs148142 "chunk %d nblocks %d chunk_size %x block_size 0x%x " 29803dec9fcdSqs148142 "dma_bufp $%p dvma_addr $%p", channel, i, 29813dec9fcdSqs148142 dma_bufp->nblocks, 29823dec9fcdSqs148142 ring_info->buffer[i].buf_size, bsize, dma_bufp, 29833dec9fcdSqs148142 ring_info->buffer[i].dvma_addr)); 29843dec9fcdSqs148142 29853dec9fcdSqs148142 /* loop over blocks within a chunk */ 29863dec9fcdSqs148142 for (j = 0; j < nblocks; j++) { 29873dec9fcdSqs148142 if ((rx_msg_p = hxge_allocb(bsize, BPRI_LO, 29883dec9fcdSqs148142 dma_bufp)) == NULL) { 29893dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 29903dec9fcdSqs148142 "allocb failed (index %d i %d j %d)", 29913dec9fcdSqs148142 index, i, j)); 29923dec9fcdSqs148142 goto hxge_map_rxdma_channel_buf_ring_fail1; 29933dec9fcdSqs148142 } 29943dec9fcdSqs148142 rx_msg_ring[index] = rx_msg_p; 29953dec9fcdSqs148142 rx_msg_p->block_index = index; 29963dec9fcdSqs148142 rx_msg_p->shifted_addr = (uint32_t) 29973dec9fcdSqs148142 ((rx_msg_p->buf_dma.dma_cookie.dmac_laddress >> 29983dec9fcdSqs148142 RBR_BKADDR_SHIFT)); 29993dec9fcdSqs148142 /* 30003dec9fcdSqs148142 * Too much output 30013dec9fcdSqs148142 * HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 30023dec9fcdSqs148142 * "index %d j %d rx_msg_p $%p mblk %p", 30033dec9fcdSqs148142 * index, j, rx_msg_p, rx_msg_p->rx_mblk_p)); 30043dec9fcdSqs148142 */ 30053dec9fcdSqs148142 mblk_p = rx_msg_p->rx_mblk_p; 30063dec9fcdSqs148142 mblk_p->b_wptr = mblk_p->b_rptr + bsize; 30073dec9fcdSqs148142 30083dec9fcdSqs148142 rbrp->rbr_ref_cnt++; 30093dec9fcdSqs148142 index++; 30103dec9fcdSqs148142 rx_msg_p->buf_dma.dma_channel = channel; 30113dec9fcdSqs148142 } 30123dec9fcdSqs148142 } 30133dec9fcdSqs148142 if (i < rbrp->num_blocks) { 30143dec9fcdSqs148142 goto hxge_map_rxdma_channel_buf_ring_fail1; 30153dec9fcdSqs148142 } 30163dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 30173dec9fcdSqs148142 "hxge_map_rxdma_channel_buf_ring: done buf init " 30183dec9fcdSqs148142 "channel %d msg block entries %d", channel, index)); 30193dec9fcdSqs148142 ring_info->block_size_mask = bsize - 1; 30203dec9fcdSqs148142 rbrp->rx_msg_ring = rx_msg_ring; 30213dec9fcdSqs148142 rbrp->dma_bufp = dma_buf_p; 30223dec9fcdSqs148142 rbrp->ring_info = ring_info; 30233dec9fcdSqs148142 30243dec9fcdSqs148142 status = hxge_rxbuf_index_info_init(hxgep, rbrp); 30253dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, " hxge_map_rxdma_channel_buf_ring: " 30263dec9fcdSqs148142 "channel %d done buf info init", channel)); 30273dec9fcdSqs148142 30283dec9fcdSqs148142 /* 30293dec9fcdSqs148142 * Finally, permit hxge_freeb() to call hxge_post_page(). 30303dec9fcdSqs148142 */ 30313dec9fcdSqs148142 rbrp->rbr_state = RBR_POSTING; 30323dec9fcdSqs148142 30333dec9fcdSqs148142 *rbr_p = rbrp; 30343dec9fcdSqs148142 30353dec9fcdSqs148142 goto hxge_map_rxdma_channel_buf_ring_exit; 30363dec9fcdSqs148142 30373dec9fcdSqs148142 hxge_map_rxdma_channel_buf_ring_fail1: 30383dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 30393dec9fcdSqs148142 " hxge_map_rxdma_channel_buf_ring: failed channel (0x%x)", 30403dec9fcdSqs148142 channel, status)); 30413dec9fcdSqs148142 30423dec9fcdSqs148142 index--; 30433dec9fcdSqs148142 for (; index >= 0; index--) { 30443dec9fcdSqs148142 rx_msg_p = rx_msg_ring[index]; 30453dec9fcdSqs148142 if (rx_msg_p != NULL) { 304614648441SQiyan Sun - Sun Microsystems - San Diego United States freeb(rx_msg_p->rx_mblk_p); 30473dec9fcdSqs148142 rx_msg_ring[index] = NULL; 30483dec9fcdSqs148142 } 30493dec9fcdSqs148142 } 30503dec9fcdSqs148142 30513dec9fcdSqs148142 hxge_map_rxdma_channel_buf_ring_fail: 30523dec9fcdSqs148142 MUTEX_DESTROY(&rbrp->post_lock); 30533dec9fcdSqs148142 MUTEX_DESTROY(&rbrp->lock); 30543dec9fcdSqs148142 KMEM_FREE(ring_info, sizeof (rxring_info_t)); 30553dec9fcdSqs148142 KMEM_FREE(rx_msg_ring, size); 30563dec9fcdSqs148142 KMEM_FREE(rbrp, sizeof (rx_rbr_ring_t)); 30573dec9fcdSqs148142 30583dec9fcdSqs148142 status = HXGE_ERROR; 30593dec9fcdSqs148142 30603dec9fcdSqs148142 hxge_map_rxdma_channel_buf_ring_exit: 30613dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 30623dec9fcdSqs148142 "<== hxge_map_rxdma_channel_buf_ring status 0x%08x", status)); 30633dec9fcdSqs148142 30643dec9fcdSqs148142 return (status); 30653dec9fcdSqs148142 } 30663dec9fcdSqs148142 30673dec9fcdSqs148142 /*ARGSUSED*/ 30683dec9fcdSqs148142 static void 30693dec9fcdSqs148142 hxge_unmap_rxdma_channel_buf_ring(p_hxge_t hxgep, 30703dec9fcdSqs148142 p_rx_rbr_ring_t rbr_p) 30713dec9fcdSqs148142 { 30723dec9fcdSqs148142 p_rx_msg_t *rx_msg_ring; 30733dec9fcdSqs148142 p_rx_msg_t rx_msg_p; 30743dec9fcdSqs148142 rxring_info_t *ring_info; 30753dec9fcdSqs148142 int i; 30763dec9fcdSqs148142 uint32_t size; 30773dec9fcdSqs148142 30783dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 30793dec9fcdSqs148142 "==> hxge_unmap_rxdma_channel_buf_ring")); 30803dec9fcdSqs148142 if (rbr_p == NULL) { 30813dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 30823dec9fcdSqs148142 "<== hxge_unmap_rxdma_channel_buf_ring: NULL rbrp")); 30833dec9fcdSqs148142 return; 30843dec9fcdSqs148142 } 30853dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 30863dec9fcdSqs148142 "==> hxge_unmap_rxdma_channel_buf_ring: channel %d", rbr_p->rdc)); 30873dec9fcdSqs148142 30883dec9fcdSqs148142 rx_msg_ring = rbr_p->rx_msg_ring; 30893dec9fcdSqs148142 ring_info = rbr_p->ring_info; 30903dec9fcdSqs148142 30913dec9fcdSqs148142 if (rx_msg_ring == NULL || ring_info == NULL) { 30923dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 30933dec9fcdSqs148142 "<== hxge_unmap_rxdma_channel_buf_ring: " 30943dec9fcdSqs148142 "rx_msg_ring $%p ring_info $%p", rx_msg_p, ring_info)); 30953dec9fcdSqs148142 return; 30963dec9fcdSqs148142 } 30973dec9fcdSqs148142 30983dec9fcdSqs148142 size = rbr_p->tnblocks * sizeof (p_rx_msg_t); 30993dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 31003dec9fcdSqs148142 " hxge_unmap_rxdma_channel_buf_ring: channel %d chunks %d " 31013dec9fcdSqs148142 "tnblocks %d (max %d) size ptrs %d ", rbr_p->rdc, rbr_p->num_blocks, 31023dec9fcdSqs148142 rbr_p->tnblocks, rbr_p->rbr_max_size, size)); 31033dec9fcdSqs148142 31043dec9fcdSqs148142 for (i = 0; i < rbr_p->tnblocks; i++) { 31053dec9fcdSqs148142 rx_msg_p = rx_msg_ring[i]; 31063dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 31073dec9fcdSqs148142 " hxge_unmap_rxdma_channel_buf_ring: " 31083dec9fcdSqs148142 "rx_msg_p $%p", rx_msg_p)); 31093dec9fcdSqs148142 if (rx_msg_p != NULL) { 311014648441SQiyan Sun - Sun Microsystems - San Diego United States freeb(rx_msg_p->rx_mblk_p); 31113dec9fcdSqs148142 rx_msg_ring[i] = NULL; 31123dec9fcdSqs148142 } 31133dec9fcdSqs148142 } 31143dec9fcdSqs148142 31153dec9fcdSqs148142 /* 31163dec9fcdSqs148142 * We no longer may use the mutex <post_lock>. By setting 31173dec9fcdSqs148142 * <rbr_state> to anything but POSTING, we prevent 31183dec9fcdSqs148142 * hxge_post_page() from accessing a dead mutex. 31193dec9fcdSqs148142 */ 31203dec9fcdSqs148142 rbr_p->rbr_state = RBR_UNMAPPING; 31213dec9fcdSqs148142 MUTEX_DESTROY(&rbr_p->post_lock); 31223dec9fcdSqs148142 31233dec9fcdSqs148142 MUTEX_DESTROY(&rbr_p->lock); 31243dec9fcdSqs148142 KMEM_FREE(ring_info, sizeof (rxring_info_t)); 31253dec9fcdSqs148142 KMEM_FREE(rx_msg_ring, size); 31263dec9fcdSqs148142 31273dec9fcdSqs148142 if (rbr_p->rbr_ref_cnt == 0) { 31283dec9fcdSqs148142 /* This is the normal state of affairs. */ 31293dec9fcdSqs148142 KMEM_FREE(rbr_p, sizeof (*rbr_p)); 31303dec9fcdSqs148142 } else { 31313dec9fcdSqs148142 /* 31323dec9fcdSqs148142 * Some of our buffers are still being used. 31333dec9fcdSqs148142 * Therefore, tell hxge_freeb() this ring is 31343dec9fcdSqs148142 * unmapped, so it may free <rbr_p> for us. 31353dec9fcdSqs148142 */ 31363dec9fcdSqs148142 rbr_p->rbr_state = RBR_UNMAPPED; 31376ffca240SMichael Speer HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 31383dec9fcdSqs148142 "unmap_rxdma_buf_ring: %d %s outstanding.", 31393dec9fcdSqs148142 rbr_p->rbr_ref_cnt, 31403dec9fcdSqs148142 rbr_p->rbr_ref_cnt == 1 ? "msg" : "msgs")); 31413dec9fcdSqs148142 } 31423dec9fcdSqs148142 31433dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 31443dec9fcdSqs148142 "<== hxge_unmap_rxdma_channel_buf_ring")); 31453dec9fcdSqs148142 } 31463dec9fcdSqs148142 31473dec9fcdSqs148142 static hxge_status_t 31483dec9fcdSqs148142 hxge_rxdma_hw_start_common(p_hxge_t hxgep) 31493dec9fcdSqs148142 { 31503dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 31513dec9fcdSqs148142 31523dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_rxdma_hw_start_common")); 31533dec9fcdSqs148142 31543dec9fcdSqs148142 /* 31553dec9fcdSqs148142 * Load the sharable parameters by writing to the function zero control 31563dec9fcdSqs148142 * registers. These FZC registers should be initialized only once for 31573dec9fcdSqs148142 * the entire chip. 31583dec9fcdSqs148142 */ 31593dec9fcdSqs148142 (void) hxge_init_fzc_rx_common(hxgep); 31603dec9fcdSqs148142 31613dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_rxdma_hw_start_common")); 31623dec9fcdSqs148142 31633dec9fcdSqs148142 return (status); 31643dec9fcdSqs148142 } 31653dec9fcdSqs148142 31663dec9fcdSqs148142 static hxge_status_t 31673dec9fcdSqs148142 hxge_rxdma_hw_start(p_hxge_t hxgep) 31683dec9fcdSqs148142 { 31693dec9fcdSqs148142 int i, ndmas; 31703dec9fcdSqs148142 uint16_t channel; 31713dec9fcdSqs148142 p_rx_rbr_rings_t rx_rbr_rings; 31723dec9fcdSqs148142 p_rx_rbr_ring_t *rbr_rings; 31733dec9fcdSqs148142 p_rx_rcr_rings_t rx_rcr_rings; 31743dec9fcdSqs148142 p_rx_rcr_ring_t *rcr_rings; 31753dec9fcdSqs148142 p_rx_mbox_areas_t rx_mbox_areas_p; 31763dec9fcdSqs148142 p_rx_mbox_t *rx_mbox_p; 31773dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 31783dec9fcdSqs148142 31793dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_rxdma_hw_start")); 31803dec9fcdSqs148142 31813dec9fcdSqs148142 rx_rbr_rings = hxgep->rx_rbr_rings; 31823dec9fcdSqs148142 rx_rcr_rings = hxgep->rx_rcr_rings; 31833dec9fcdSqs148142 if (rx_rbr_rings == NULL || rx_rcr_rings == NULL) { 31843dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 31853dec9fcdSqs148142 "<== hxge_rxdma_hw_start: NULL ring pointers")); 31863dec9fcdSqs148142 return (HXGE_ERROR); 31873dec9fcdSqs148142 } 31883dec9fcdSqs148142 31893dec9fcdSqs148142 ndmas = rx_rbr_rings->ndmas; 31903dec9fcdSqs148142 if (ndmas == 0) { 31913dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 31923dec9fcdSqs148142 "<== hxge_rxdma_hw_start: no dma channel allocated")); 31933dec9fcdSqs148142 return (HXGE_ERROR); 31943dec9fcdSqs148142 } 31953dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 31963dec9fcdSqs148142 "==> hxge_rxdma_hw_start (ndmas %d)", ndmas)); 31973dec9fcdSqs148142 31983dec9fcdSqs148142 /* 31993dec9fcdSqs148142 * Scrub the RDC Rx DMA Prefetch Buffer Command. 32003dec9fcdSqs148142 */ 32013dec9fcdSqs148142 for (i = 0; i < 128; i++) { 32023dec9fcdSqs148142 HXGE_REG_WR64(hxgep->hpi_handle, RDC_PREF_CMD, i); 32033dec9fcdSqs148142 } 32043dec9fcdSqs148142 32053dec9fcdSqs148142 /* 32063dec9fcdSqs148142 * Scrub Rx DMA Shadow Tail Command. 32073dec9fcdSqs148142 */ 32083dec9fcdSqs148142 for (i = 0; i < 64; i++) { 32093dec9fcdSqs148142 HXGE_REG_WR64(hxgep->hpi_handle, RDC_SHADOW_CMD, i); 32103dec9fcdSqs148142 } 32113dec9fcdSqs148142 32123dec9fcdSqs148142 /* 32133dec9fcdSqs148142 * Scrub Rx DMA Control Fifo Command. 32143dec9fcdSqs148142 */ 32153dec9fcdSqs148142 for (i = 0; i < 512; i++) { 32163dec9fcdSqs148142 HXGE_REG_WR64(hxgep->hpi_handle, RDC_CTRL_FIFO_CMD, i); 32173dec9fcdSqs148142 } 32183dec9fcdSqs148142 32193dec9fcdSqs148142 /* 32203dec9fcdSqs148142 * Scrub Rx DMA Data Fifo Command. 32213dec9fcdSqs148142 */ 32223dec9fcdSqs148142 for (i = 0; i < 1536; i++) { 32233dec9fcdSqs148142 HXGE_REG_WR64(hxgep->hpi_handle, RDC_DATA_FIFO_CMD, i); 32243dec9fcdSqs148142 } 32253dec9fcdSqs148142 32263dec9fcdSqs148142 /* 32273dec9fcdSqs148142 * Reset the FIFO Error Stat. 32283dec9fcdSqs148142 */ 32293dec9fcdSqs148142 HXGE_REG_WR64(hxgep->hpi_handle, RDC_FIFO_ERR_STAT, 0xFF); 32303dec9fcdSqs148142 32313dec9fcdSqs148142 /* Set the error mask to receive interrupts */ 32323dec9fcdSqs148142 HXGE_REG_WR64(hxgep->hpi_handle, RDC_FIFO_ERR_INT_MASK, 0x0); 32333dec9fcdSqs148142 32343dec9fcdSqs148142 rbr_rings = rx_rbr_rings->rbr_rings; 32353dec9fcdSqs148142 rcr_rings = rx_rcr_rings->rcr_rings; 32363dec9fcdSqs148142 rx_mbox_areas_p = hxgep->rx_mbox_areas_p; 32373dec9fcdSqs148142 if (rx_mbox_areas_p) { 32383dec9fcdSqs148142 rx_mbox_p = rx_mbox_areas_p->rxmbox_areas; 32393dec9fcdSqs148142 } 32403dec9fcdSqs148142 32413dec9fcdSqs148142 for (i = 0; i < ndmas; i++) { 32423dec9fcdSqs148142 channel = rbr_rings[i]->rdc; 32433dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 32443dec9fcdSqs148142 "==> hxge_rxdma_hw_start (ndmas %d) channel %d", 32453dec9fcdSqs148142 ndmas, channel)); 32463dec9fcdSqs148142 status = hxge_rxdma_start_channel(hxgep, channel, 32473dec9fcdSqs148142 (p_rx_rbr_ring_t)rbr_rings[i], 32483dec9fcdSqs148142 (p_rx_rcr_ring_t)rcr_rings[i], 3249fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States (p_rx_mbox_t)rx_mbox_p[i], rbr_rings[i]->rbb_max); 32503dec9fcdSqs148142 if (status != HXGE_OK) { 32513dec9fcdSqs148142 goto hxge_rxdma_hw_start_fail1; 32523dec9fcdSqs148142 } 32533dec9fcdSqs148142 } 32543dec9fcdSqs148142 32553dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_rxdma_hw_start: " 32563dec9fcdSqs148142 "rx_rbr_rings 0x%016llx rings 0x%016llx", 32573dec9fcdSqs148142 rx_rbr_rings, rx_rcr_rings)); 32583dec9fcdSqs148142 goto hxge_rxdma_hw_start_exit; 32593dec9fcdSqs148142 32603dec9fcdSqs148142 hxge_rxdma_hw_start_fail1: 32613dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 32623dec9fcdSqs148142 "==> hxge_rxdma_hw_start: disable " 32633dec9fcdSqs148142 "(status 0x%x channel %d i %d)", status, channel, i)); 32643dec9fcdSqs148142 for (; i >= 0; i--) { 32653dec9fcdSqs148142 channel = rbr_rings[i]->rdc; 32663dec9fcdSqs148142 (void) hxge_rxdma_stop_channel(hxgep, channel); 32673dec9fcdSqs148142 } 32683dec9fcdSqs148142 32693dec9fcdSqs148142 hxge_rxdma_hw_start_exit: 32703dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 32713dec9fcdSqs148142 "==> hxge_rxdma_hw_start: (status 0x%x)", status)); 32723dec9fcdSqs148142 return (status); 32733dec9fcdSqs148142 } 32743dec9fcdSqs148142 32753dec9fcdSqs148142 static void 32763dec9fcdSqs148142 hxge_rxdma_hw_stop(p_hxge_t hxgep) 32773dec9fcdSqs148142 { 32783dec9fcdSqs148142 int i, ndmas; 32793dec9fcdSqs148142 uint16_t channel; 32803dec9fcdSqs148142 p_rx_rbr_rings_t rx_rbr_rings; 32813dec9fcdSqs148142 p_rx_rbr_ring_t *rbr_rings; 32823dec9fcdSqs148142 p_rx_rcr_rings_t rx_rcr_rings; 32833dec9fcdSqs148142 32843dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_rxdma_hw_stop")); 32853dec9fcdSqs148142 32863dec9fcdSqs148142 rx_rbr_rings = hxgep->rx_rbr_rings; 32873dec9fcdSqs148142 rx_rcr_rings = hxgep->rx_rcr_rings; 32883dec9fcdSqs148142 32893dec9fcdSqs148142 if (rx_rbr_rings == NULL || rx_rcr_rings == NULL) { 32903dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 32913dec9fcdSqs148142 "<== hxge_rxdma_hw_stop: NULL ring pointers")); 32923dec9fcdSqs148142 return; 32933dec9fcdSqs148142 } 32943dec9fcdSqs148142 32953dec9fcdSqs148142 ndmas = rx_rbr_rings->ndmas; 32963dec9fcdSqs148142 if (!ndmas) { 32973dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 32983dec9fcdSqs148142 "<== hxge_rxdma_hw_stop: no dma channel allocated")); 32993dec9fcdSqs148142 return; 33003dec9fcdSqs148142 } 33013dec9fcdSqs148142 33023dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 33033dec9fcdSqs148142 "==> hxge_rxdma_hw_stop (ndmas %d)", ndmas)); 33043dec9fcdSqs148142 33053dec9fcdSqs148142 rbr_rings = rx_rbr_rings->rbr_rings; 33063dec9fcdSqs148142 for (i = 0; i < ndmas; i++) { 33073dec9fcdSqs148142 channel = rbr_rings[i]->rdc; 33083dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 33093dec9fcdSqs148142 "==> hxge_rxdma_hw_stop (ndmas %d) channel %d", 33103dec9fcdSqs148142 ndmas, channel)); 33113dec9fcdSqs148142 (void) hxge_rxdma_stop_channel(hxgep, channel); 33123dec9fcdSqs148142 } 33133dec9fcdSqs148142 33143dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_rxdma_hw_stop: " 33153dec9fcdSqs148142 "rx_rbr_rings 0x%016llx rings 0x%016llx", 33163dec9fcdSqs148142 rx_rbr_rings, rx_rcr_rings)); 33173dec9fcdSqs148142 33183dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_rxdma_hw_stop")); 33193dec9fcdSqs148142 } 33203dec9fcdSqs148142 33213dec9fcdSqs148142 static hxge_status_t 33223dec9fcdSqs148142 hxge_rxdma_start_channel(p_hxge_t hxgep, uint16_t channel, 3323fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States p_rx_rbr_ring_t rbr_p, p_rx_rcr_ring_t rcr_p, p_rx_mbox_t mbox_p, 3324fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States int n_init_kick) 33253dec9fcdSqs148142 { 33263dec9fcdSqs148142 hpi_handle_t handle; 33273dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 33283dec9fcdSqs148142 rdc_stat_t cs; 33293dec9fcdSqs148142 rdc_int_mask_t ent_mask; 33303dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 33313dec9fcdSqs148142 33323dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_rxdma_start_channel")); 33333dec9fcdSqs148142 33343dec9fcdSqs148142 handle = HXGE_DEV_HPI_HANDLE(hxgep); 33353dec9fcdSqs148142 33363dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "hxge_rxdma_start_channel: " 33373dec9fcdSqs148142 "hpi handle addr $%p acc $%p", 33383dec9fcdSqs148142 hxgep->hpi_handle.regp, hxgep->hpi_handle.regh)); 33393dec9fcdSqs148142 33403dec9fcdSqs148142 /* Reset RXDMA channel */ 33413dec9fcdSqs148142 rs = hpi_rxdma_cfg_rdc_reset(handle, channel); 33423dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 33433dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 33443dec9fcdSqs148142 "==> hxge_rxdma_start_channel: " 33453dec9fcdSqs148142 "reset rxdma failed (0x%08x channel %d)", 33463dec9fcdSqs148142 status, channel)); 33473dec9fcdSqs148142 return (HXGE_ERROR | rs); 33483dec9fcdSqs148142 } 33493dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 33503dec9fcdSqs148142 "==> hxge_rxdma_start_channel: reset done: channel %d", channel)); 33513dec9fcdSqs148142 33523dec9fcdSqs148142 /* 33533dec9fcdSqs148142 * Initialize the RXDMA channel specific FZC control configurations. 33543dec9fcdSqs148142 * These FZC registers are pertaining to each RX channel (logical 33553dec9fcdSqs148142 * pages). 33563dec9fcdSqs148142 */ 33573dec9fcdSqs148142 status = hxge_init_fzc_rxdma_channel(hxgep, 33583dec9fcdSqs148142 channel, rbr_p, rcr_p, mbox_p); 33593dec9fcdSqs148142 if (status != HXGE_OK) { 33603dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 33613dec9fcdSqs148142 "==> hxge_rxdma_start_channel: " 33623dec9fcdSqs148142 "init fzc rxdma failed (0x%08x channel %d)", 33633dec9fcdSqs148142 status, channel)); 33643dec9fcdSqs148142 return (status); 33653dec9fcdSqs148142 } 33663dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 33673dec9fcdSqs148142 "==> hxge_rxdma_start_channel: fzc done")); 33683dec9fcdSqs148142 33693dec9fcdSqs148142 /* 33703dec9fcdSqs148142 * Zero out the shadow and prefetch ram. 33713dec9fcdSqs148142 */ 33723dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 33733dec9fcdSqs148142 "==> hxge_rxdma_start_channel: ram done")); 33743dec9fcdSqs148142 33753dec9fcdSqs148142 /* Set up the interrupt event masks. */ 33763dec9fcdSqs148142 ent_mask.value = 0; 33773dec9fcdSqs148142 rs = hpi_rxdma_event_mask(handle, OP_SET, channel, &ent_mask); 33783dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 33793dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 33803dec9fcdSqs148142 "==> hxge_rxdma_start_channel: " 33813dec9fcdSqs148142 "init rxdma event masks failed (0x%08x channel %d)", 33823dec9fcdSqs148142 status, channel)); 33833dec9fcdSqs148142 return (HXGE_ERROR | rs); 33843dec9fcdSqs148142 } 33853dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_rxdma_start_channel: " 33863dec9fcdSqs148142 "event done: channel %d (mask 0x%016llx)", 33873dec9fcdSqs148142 channel, ent_mask.value)); 33883dec9fcdSqs148142 33893dec9fcdSqs148142 /* 33903dec9fcdSqs148142 * Load RXDMA descriptors, buffers, mailbox, initialise the receive DMA 33913dec9fcdSqs148142 * channels and enable each DMA channel. 33923dec9fcdSqs148142 */ 33933dec9fcdSqs148142 status = hxge_enable_rxdma_channel(hxgep, 3394fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States channel, rbr_p, rcr_p, mbox_p, n_init_kick); 33953dec9fcdSqs148142 if (status != HXGE_OK) { 33963dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 33973dec9fcdSqs148142 " hxge_rxdma_start_channel: " 33983dec9fcdSqs148142 " init enable rxdma failed (0x%08x channel %d)", 33993dec9fcdSqs148142 status, channel)); 34003dec9fcdSqs148142 return (status); 34013dec9fcdSqs148142 } 34023dec9fcdSqs148142 34033dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_rxdma_start_channel: " 34043dec9fcdSqs148142 "control done - channel %d cs 0x%016llx", channel, cs.value)); 34053dec9fcdSqs148142 34063dec9fcdSqs148142 /* 34073dec9fcdSqs148142 * Initialize the receive DMA control and status register 34083dec9fcdSqs148142 * Note that rdc_stat HAS to be set after RBR and RCR rings are set 34093dec9fcdSqs148142 */ 34103dec9fcdSqs148142 cs.value = 0; 34113dec9fcdSqs148142 cs.bits.mex = 1; 34123dec9fcdSqs148142 cs.bits.rcr_thres = 1; 34133dec9fcdSqs148142 cs.bits.rcr_to = 1; 34143dec9fcdSqs148142 cs.bits.rbr_empty = 1; 34153dec9fcdSqs148142 status = hxge_init_rxdma_channel_cntl_stat(hxgep, channel, &cs); 34163dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_rxdma_start_channel: " 34173dec9fcdSqs148142 "channel %d rx_dma_cntl_stat 0x%0016llx", channel, cs.value)); 34183dec9fcdSqs148142 if (status != HXGE_OK) { 34193dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 34203dec9fcdSqs148142 "==> hxge_rxdma_start_channel: " 34213dec9fcdSqs148142 "init rxdma control register failed (0x%08x channel %d", 34223dec9fcdSqs148142 status, channel)); 34233dec9fcdSqs148142 return (status); 34243dec9fcdSqs148142 } 34253dec9fcdSqs148142 34263dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_rxdma_start_channel: " 34273dec9fcdSqs148142 "control done - channel %d cs 0x%016llx", channel, cs.value)); 34283dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 34293dec9fcdSqs148142 "==> hxge_rxdma_start_channel: enable done")); 34303dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_rxdma_start_channel")); 34313dec9fcdSqs148142 return (HXGE_OK); 34323dec9fcdSqs148142 } 34333dec9fcdSqs148142 34343dec9fcdSqs148142 static hxge_status_t 34353dec9fcdSqs148142 hxge_rxdma_stop_channel(p_hxge_t hxgep, uint16_t channel) 34363dec9fcdSqs148142 { 34373dec9fcdSqs148142 hpi_handle_t handle; 34383dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 34393dec9fcdSqs148142 rdc_stat_t cs; 34403dec9fcdSqs148142 rdc_int_mask_t ent_mask; 34413dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 34423dec9fcdSqs148142 34433dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_rxdma_stop_channel")); 34443dec9fcdSqs148142 34453dec9fcdSqs148142 handle = HXGE_DEV_HPI_HANDLE(hxgep); 34463dec9fcdSqs148142 34473dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "hxge_rxdma_stop_channel: " 34483dec9fcdSqs148142 "hpi handle addr $%p acc $%p", 34493dec9fcdSqs148142 hxgep->hpi_handle.regp, hxgep->hpi_handle.regh)); 34503dec9fcdSqs148142 34513dec9fcdSqs148142 /* Reset RXDMA channel */ 34523dec9fcdSqs148142 rs = hpi_rxdma_cfg_rdc_reset(handle, channel); 34533dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 34543dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 34553dec9fcdSqs148142 " hxge_rxdma_stop_channel: " 34563dec9fcdSqs148142 " reset rxdma failed (0x%08x channel %d)", 34573dec9fcdSqs148142 rs, channel)); 34583dec9fcdSqs148142 return (HXGE_ERROR | rs); 34593dec9fcdSqs148142 } 34603dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 34613dec9fcdSqs148142 "==> hxge_rxdma_stop_channel: reset done")); 34623dec9fcdSqs148142 34633dec9fcdSqs148142 /* Set up the interrupt event masks. */ 34643dec9fcdSqs148142 ent_mask.value = RDC_INT_MASK_ALL; 34653dec9fcdSqs148142 rs = hpi_rxdma_event_mask(handle, OP_SET, channel, &ent_mask); 34663dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 34673dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 34683dec9fcdSqs148142 "==> hxge_rxdma_stop_channel: " 34693dec9fcdSqs148142 "set rxdma event masks failed (0x%08x channel %d)", 34703dec9fcdSqs148142 rs, channel)); 34713dec9fcdSqs148142 return (HXGE_ERROR | rs); 34723dec9fcdSqs148142 } 34733dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 34743dec9fcdSqs148142 "==> hxge_rxdma_stop_channel: event done")); 34753dec9fcdSqs148142 34763dec9fcdSqs148142 /* Initialize the receive DMA control and status register */ 34773dec9fcdSqs148142 cs.value = 0; 34783dec9fcdSqs148142 status = hxge_init_rxdma_channel_cntl_stat(hxgep, channel, &cs); 34793dec9fcdSqs148142 34803dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_rxdma_stop_channel: control " 34813dec9fcdSqs148142 " to default (all 0s) 0x%08x", cs.value)); 34823dec9fcdSqs148142 34833dec9fcdSqs148142 if (status != HXGE_OK) { 34843dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 34853dec9fcdSqs148142 " hxge_rxdma_stop_channel: init rxdma" 34863dec9fcdSqs148142 " control register failed (0x%08x channel %d", 34873dec9fcdSqs148142 status, channel)); 34883dec9fcdSqs148142 return (status); 34893dec9fcdSqs148142 } 34903dec9fcdSqs148142 34913dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 34923dec9fcdSqs148142 "==> hxge_rxdma_stop_channel: control done")); 34933dec9fcdSqs148142 34943dec9fcdSqs148142 /* disable dma channel */ 34953dec9fcdSqs148142 status = hxge_disable_rxdma_channel(hxgep, channel); 34963dec9fcdSqs148142 34973dec9fcdSqs148142 if (status != HXGE_OK) { 34983dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 34993dec9fcdSqs148142 " hxge_rxdma_stop_channel: " 35003dec9fcdSqs148142 " init enable rxdma failed (0x%08x channel %d)", 35013dec9fcdSqs148142 status, channel)); 35023dec9fcdSqs148142 return (status); 35033dec9fcdSqs148142 } 35043dec9fcdSqs148142 35053dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, 35063dec9fcdSqs148142 "==> hxge_rxdma_stop_channel: disable done")); 35073dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "<== hxge_rxdma_stop_channel")); 35083dec9fcdSqs148142 35093dec9fcdSqs148142 return (HXGE_OK); 35103dec9fcdSqs148142 } 35113dec9fcdSqs148142 35123dec9fcdSqs148142 hxge_status_t 35133dec9fcdSqs148142 hxge_rxdma_handle_sys_errors(p_hxge_t hxgep) 35143dec9fcdSqs148142 { 35153dec9fcdSqs148142 hpi_handle_t handle; 35163dec9fcdSqs148142 p_hxge_rdc_sys_stats_t statsp; 35173dec9fcdSqs148142 rdc_fifo_err_stat_t stat; 35183dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 35193dec9fcdSqs148142 35203dec9fcdSqs148142 handle = hxgep->hpi_handle; 35213dec9fcdSqs148142 statsp = (p_hxge_rdc_sys_stats_t)&hxgep->statsp->rdc_sys_stats; 35223dec9fcdSqs148142 35233dec9fcdSqs148142 /* Get the error status and clear the register */ 35243dec9fcdSqs148142 HXGE_REG_RD64(handle, RDC_FIFO_ERR_STAT, &stat.value); 35253dec9fcdSqs148142 HXGE_REG_WR64(handle, RDC_FIFO_ERR_STAT, stat.value); 35263dec9fcdSqs148142 35273dec9fcdSqs148142 if (stat.bits.rx_ctrl_fifo_sec) { 35283dec9fcdSqs148142 statsp->ctrl_fifo_sec++; 35293dec9fcdSqs148142 if (statsp->ctrl_fifo_sec == 1) 35303dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 35313dec9fcdSqs148142 "==> hxge_rxdma_handle_sys_errors: " 35323dec9fcdSqs148142 "rx_ctrl_fifo_sec")); 35333dec9fcdSqs148142 } 35343dec9fcdSqs148142 35353dec9fcdSqs148142 if (stat.bits.rx_ctrl_fifo_ded) { 35363dec9fcdSqs148142 /* Global fatal error encountered */ 35373dec9fcdSqs148142 statsp->ctrl_fifo_ded++; 35383dec9fcdSqs148142 HXGE_FM_REPORT_ERROR(hxgep, NULL, 35393dec9fcdSqs148142 HXGE_FM_EREPORT_RDMC_CTRL_FIFO_DED); 35403dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 35413dec9fcdSqs148142 "==> hxge_rxdma_handle_sys_errors: " 35423dec9fcdSqs148142 "fatal error: rx_ctrl_fifo_ded error")); 35433dec9fcdSqs148142 } 35443dec9fcdSqs148142 35453dec9fcdSqs148142 if (stat.bits.rx_data_fifo_sec) { 35463dec9fcdSqs148142 statsp->data_fifo_sec++; 35473dec9fcdSqs148142 if (statsp->data_fifo_sec == 1) 35483dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 35493dec9fcdSqs148142 "==> hxge_rxdma_handle_sys_errors: " 35503dec9fcdSqs148142 "rx_data_fifo_sec")); 35513dec9fcdSqs148142 } 35523dec9fcdSqs148142 35533dec9fcdSqs148142 if (stat.bits.rx_data_fifo_ded) { 35543dec9fcdSqs148142 /* Global fatal error encountered */ 35553dec9fcdSqs148142 statsp->data_fifo_ded++; 35563dec9fcdSqs148142 HXGE_FM_REPORT_ERROR(hxgep, NULL, 35573dec9fcdSqs148142 HXGE_FM_EREPORT_RDMC_DATA_FIFO_DED); 35583dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 35593dec9fcdSqs148142 "==> hxge_rxdma_handle_sys_errors: " 35603dec9fcdSqs148142 "fatal error: rx_data_fifo_ded error")); 35613dec9fcdSqs148142 } 35623dec9fcdSqs148142 35633dec9fcdSqs148142 if (stat.bits.rx_ctrl_fifo_ded || stat.bits.rx_data_fifo_ded) { 35643dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 35653dec9fcdSqs148142 " hxge_rxdma_handle_sys_errors: fatal error\n")); 35663dec9fcdSqs148142 status = hxge_rx_port_fatal_err_recover(hxgep); 35673dec9fcdSqs148142 if (status == HXGE_OK) { 35683dec9fcdSqs148142 FM_SERVICE_RESTORED(hxgep); 35693dec9fcdSqs148142 } 35703dec9fcdSqs148142 } 35713dec9fcdSqs148142 35723dec9fcdSqs148142 return (HXGE_OK); 35733dec9fcdSqs148142 } 35743dec9fcdSqs148142 35753dec9fcdSqs148142 static hxge_status_t 35763dec9fcdSqs148142 hxge_rxdma_fatal_err_recover(p_hxge_t hxgep, uint16_t channel) 35773dec9fcdSqs148142 { 35783dec9fcdSqs148142 hpi_handle_t handle; 35793dec9fcdSqs148142 hpi_status_t rs = HPI_SUCCESS; 35803dec9fcdSqs148142 p_rx_rbr_ring_t rbrp; 35813dec9fcdSqs148142 p_rx_rcr_ring_t rcrp; 35823dec9fcdSqs148142 p_rx_mbox_t mboxp; 35833dec9fcdSqs148142 rdc_int_mask_t ent_mask; 35843dec9fcdSqs148142 p_hxge_dma_common_t dmap; 35853dec9fcdSqs148142 p_rx_msg_t rx_msg_p; 35863dec9fcdSqs148142 int i; 35873dec9fcdSqs148142 uint32_t hxge_port_rcr_size; 35883dec9fcdSqs148142 uint64_t tmp; 3589fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States int n_init_kick = 0; 35903dec9fcdSqs148142 35913dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_rxdma_fatal_err_recover")); 35923dec9fcdSqs148142 35933dec9fcdSqs148142 /* 35943dec9fcdSqs148142 * Stop the dma channel waits for the stop done. If the stop done bit 35953dec9fcdSqs148142 * is not set, then create an error. 35963dec9fcdSqs148142 */ 35973dec9fcdSqs148142 35983dec9fcdSqs148142 handle = HXGE_DEV_HPI_HANDLE(hxgep); 35993dec9fcdSqs148142 36003dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "Rx DMA stop...")); 36013dec9fcdSqs148142 3602f043ebedSMichael Speer rbrp = (p_rx_rbr_ring_t)hxgep->rx_rbr_rings->rbr_rings[channel]; 3603f043ebedSMichael Speer rcrp = (p_rx_rcr_ring_t)hxgep->rx_rcr_rings->rcr_rings[channel]; 36043dec9fcdSqs148142 36053dec9fcdSqs148142 MUTEX_ENTER(&rcrp->lock); 36063dec9fcdSqs148142 MUTEX_ENTER(&rbrp->lock); 36073dec9fcdSqs148142 36083dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "Disable RxDMA channel...")); 36093dec9fcdSqs148142 36103dec9fcdSqs148142 rs = hpi_rxdma_cfg_rdc_disable(handle, channel); 36113dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 36123dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 36133dec9fcdSqs148142 "hxge_disable_rxdma_channel:failed")); 36143dec9fcdSqs148142 goto fail; 36153dec9fcdSqs148142 } 36163dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "Disable RxDMA interrupt...")); 36173dec9fcdSqs148142 36183dec9fcdSqs148142 /* Disable interrupt */ 36193dec9fcdSqs148142 ent_mask.value = RDC_INT_MASK_ALL; 36203dec9fcdSqs148142 rs = hpi_rxdma_event_mask(handle, OP_SET, channel, &ent_mask); 36213dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 36223dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 36233dec9fcdSqs148142 "Set rxdma event masks failed (channel %d)", channel)); 36243dec9fcdSqs148142 } 36253dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "RxDMA channel reset...")); 36263dec9fcdSqs148142 36273dec9fcdSqs148142 /* Reset RXDMA channel */ 36283dec9fcdSqs148142 rs = hpi_rxdma_cfg_rdc_reset(handle, channel); 36293dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 36303dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 36313dec9fcdSqs148142 "Reset rxdma failed (channel %d)", channel)); 36323dec9fcdSqs148142 goto fail; 36333dec9fcdSqs148142 } 36343dec9fcdSqs148142 hxge_port_rcr_size = hxgep->hxge_port_rcr_size; 3635f043ebedSMichael Speer mboxp = (p_rx_mbox_t)hxgep->rx_mbox_areas_p->rxmbox_areas[channel]; 36363dec9fcdSqs148142 36373dec9fcdSqs148142 rbrp->rbr_wr_index = (rbrp->rbb_max - 1); 36383dec9fcdSqs148142 rbrp->rbr_rd_index = 0; 36393dec9fcdSqs148142 36403dec9fcdSqs148142 rcrp->comp_rd_index = 0; 36413dec9fcdSqs148142 rcrp->comp_wt_index = 0; 36423dec9fcdSqs148142 rcrp->rcr_desc_rd_head_p = rcrp->rcr_desc_first_p = 36433dec9fcdSqs148142 (p_rcr_entry_t)DMA_COMMON_VPTR(rcrp->rcr_desc); 3644fe930412Sqs148142 #if defined(__i386) 3645fe930412Sqs148142 rcrp->rcr_desc_rd_head_pp = rcrp->rcr_desc_first_pp = 3646fe930412Sqs148142 (p_rcr_entry_t)(uint32_t)DMA_COMMON_IOADDR(rcrp->rcr_desc); 3647fe930412Sqs148142 #else 36483dec9fcdSqs148142 rcrp->rcr_desc_rd_head_pp = rcrp->rcr_desc_first_pp = 36493dec9fcdSqs148142 (p_rcr_entry_t)DMA_COMMON_IOADDR(rcrp->rcr_desc); 3650fe930412Sqs148142 #endif 36513dec9fcdSqs148142 36523dec9fcdSqs148142 rcrp->rcr_desc_last_p = rcrp->rcr_desc_rd_head_p + 36533dec9fcdSqs148142 (hxge_port_rcr_size - 1); 36543dec9fcdSqs148142 rcrp->rcr_desc_last_pp = rcrp->rcr_desc_rd_head_pp + 36553dec9fcdSqs148142 (hxge_port_rcr_size - 1); 36563dec9fcdSqs148142 3657a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States rcrp->rcr_tail_begin = DMA_COMMON_IOADDR(rcrp->rcr_desc); 3658a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States rcrp->rcr_tail_begin = (rcrp->rcr_tail_begin & 0x7ffffULL) >> 3; 3659a512c5d1SQiyan Sun - Sun Microsystems - San Diego United States 36603dec9fcdSqs148142 dmap = (p_hxge_dma_common_t)&rcrp->rcr_desc; 36613dec9fcdSqs148142 bzero((caddr_t)dmap->kaddrp, dmap->alength); 36623dec9fcdSqs148142 36633dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "rbr entries = %d\n", 36643dec9fcdSqs148142 rbrp->rbr_max_size)); 36653dec9fcdSqs148142 3666fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States /* Count the number of buffers owned by the hardware at this moment */ 36673dec9fcdSqs148142 for (i = 0; i < rbrp->rbr_max_size; i++) { 36683dec9fcdSqs148142 rx_msg_p = rbrp->rx_msg_ring[i]; 3669fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States if (rx_msg_p->ref_cnt == 1) { 3670fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States n_init_kick++; 3671fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States } 36723dec9fcdSqs148142 } 36733dec9fcdSqs148142 36743dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "RxDMA channel re-start...")); 36753dec9fcdSqs148142 3676fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States /* 3677fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States * This is error recover! Some buffers are owned by the hardware and 3678fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States * the rest are owned by the apps. We should only kick in those 3679fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States * owned by the hardware initially. The apps will post theirs 3680fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States * eventually. 3681fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States */ 36826ffca240SMichael Speer (void) hxge_rxdma_start_channel(hxgep, channel, rbrp, rcrp, mboxp, 3683fd9489ceSQiyan Sun - Sun Microsystems - San Diego United States n_init_kick); 36843dec9fcdSqs148142 36853dec9fcdSqs148142 /* 36863dec9fcdSqs148142 * The DMA channel may disable itself automatically. 36873dec9fcdSqs148142 * The following is a work-around. 36883dec9fcdSqs148142 */ 36893dec9fcdSqs148142 HXGE_REG_RD64(handle, RDC_RX_CFG1, &tmp); 36903dec9fcdSqs148142 rs = hpi_rxdma_cfg_rdc_enable(handle, channel); 36913dec9fcdSqs148142 if (rs != HPI_SUCCESS) { 36923dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 36933dec9fcdSqs148142 "hpi_rxdma_cfg_rdc_enable (channel %d)", channel)); 36943dec9fcdSqs148142 } 36953dec9fcdSqs148142 36966ffca240SMichael Speer /* 36976ffca240SMichael Speer * Delay a bit of time by doing reads. 36986ffca240SMichael Speer */ 36996ffca240SMichael Speer for (i = 0; i < 1024; i++) { 37006ffca240SMichael Speer uint64_t value; 37016ffca240SMichael Speer RXDMA_REG_READ64(HXGE_DEV_HPI_HANDLE(hxgep), 37026ffca240SMichael Speer RDC_INT_MASK, i & 3, &value); 37036ffca240SMichael Speer } 37046ffca240SMichael Speer 37053dec9fcdSqs148142 MUTEX_EXIT(&rbrp->lock); 37063dec9fcdSqs148142 MUTEX_EXIT(&rcrp->lock); 37073dec9fcdSqs148142 37083dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "<== hxge_rxdma_fatal_err_recover")); 37093dec9fcdSqs148142 return (HXGE_OK); 37103dec9fcdSqs148142 37113dec9fcdSqs148142 fail: 37123dec9fcdSqs148142 MUTEX_EXIT(&rbrp->lock); 37133dec9fcdSqs148142 MUTEX_EXIT(&rcrp->lock); 37146ffca240SMichael Speer HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 37156ffca240SMichael Speer "Error Recovery failed for channel(%d)", channel)); 37163dec9fcdSqs148142 return (HXGE_ERROR | rs); 37173dec9fcdSqs148142 } 37183dec9fcdSqs148142 37193dec9fcdSqs148142 static hxge_status_t 37203dec9fcdSqs148142 hxge_rx_port_fatal_err_recover(p_hxge_t hxgep) 37213dec9fcdSqs148142 { 37223dec9fcdSqs148142 hxge_status_t status = HXGE_OK; 37233dec9fcdSqs148142 p_hxge_dma_common_t *dma_buf_p; 37243dec9fcdSqs148142 uint16_t channel; 37253dec9fcdSqs148142 int ndmas; 37263dec9fcdSqs148142 int i; 37273dec9fcdSqs148142 block_reset_t reset_reg; 37281c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States p_rx_rcr_ring_t rcrp; 37291c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States p_rx_rbr_ring_t rbrp; 37303dec9fcdSqs148142 37313dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "==> hxge_rx_port_fatal_err_recover")); 37323dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "Recovering from RDC error ...")); 37333dec9fcdSqs148142 37343dec9fcdSqs148142 /* Disable RxMAC */ 37353dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "Disable RxMAC...\n")); 37366ffca240SMichael Speer MUTEX_ENTER(&hxgep->vmac_lock); 37373dec9fcdSqs148142 if (hxge_rx_vmac_disable(hxgep) != HXGE_OK) 37383dec9fcdSqs148142 goto fail; 37393dec9fcdSqs148142 37403dec9fcdSqs148142 HXGE_DELAY(1000); 37413dec9fcdSqs148142 3742f043ebedSMichael Speer /* 3743f043ebedSMichael Speer * Reset RDC block from PEU for this fatal error 3744f043ebedSMichael Speer */ 3745f043ebedSMichael Speer reset_reg.value = 0; 3746f043ebedSMichael Speer reset_reg.bits.rdc_rst = 1; 3747f043ebedSMichael Speer HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, reset_reg.value); 3748f043ebedSMichael Speer 3749f043ebedSMichael Speer HXGE_DELAY(1000); 3750f043ebedSMichael Speer 37513dec9fcdSqs148142 /* Restore any common settings after PEU reset */ 37523dec9fcdSqs148142 if (hxge_rxdma_hw_start_common(hxgep) != HXGE_OK) 37533dec9fcdSqs148142 goto fail; 37543dec9fcdSqs148142 37553dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "Stop all RxDMA channels...")); 37563dec9fcdSqs148142 37573dec9fcdSqs148142 ndmas = hxgep->rx_buf_pool_p->ndmas; 37583dec9fcdSqs148142 dma_buf_p = hxgep->rx_buf_pool_p->dma_buf_pool_p; 37593dec9fcdSqs148142 37603dec9fcdSqs148142 for (i = 0; i < ndmas; i++) { 37613dec9fcdSqs148142 channel = ((p_hxge_dma_common_t)dma_buf_p[i])->dma_channel; 37621c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States rcrp = hxgep->rx_rcr_rings->rcr_rings[channel]; 37631c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States rbrp = rcrp->rx_rbr_p; 37641c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States 37651c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_ENTER(&rbrp->post_lock); 3766f043ebedSMichael Speer 3767f043ebedSMichael Speer /* 3768f043ebedSMichael Speer * This function needs to be inside the post_lock 3769f043ebedSMichael Speer */ 37703dec9fcdSqs148142 if (hxge_rxdma_fatal_err_recover(hxgep, channel) != HXGE_OK) { 37713dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 37723dec9fcdSqs148142 "Could not recover channel %d", channel)); 37733dec9fcdSqs148142 } 37741c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States MUTEX_EXIT(&rbrp->post_lock); 37753dec9fcdSqs148142 } 37763dec9fcdSqs148142 37773dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "Reset RxMAC...")); 37783dec9fcdSqs148142 37793dec9fcdSqs148142 /* Reset RxMAC */ 37803dec9fcdSqs148142 if (hxge_rx_vmac_reset(hxgep) != HXGE_OK) { 37813dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 37823dec9fcdSqs148142 "hxge_rx_port_fatal_err_recover: Failed to reset RxMAC")); 37833dec9fcdSqs148142 goto fail; 37843dec9fcdSqs148142 } 37853dec9fcdSqs148142 37863dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "Re-initialize RxMAC...")); 37873dec9fcdSqs148142 37883dec9fcdSqs148142 /* Re-Initialize RxMAC */ 37893dec9fcdSqs148142 if ((status = hxge_rx_vmac_init(hxgep)) != HXGE_OK) { 37903dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 37913dec9fcdSqs148142 "hxge_rx_port_fatal_err_recover: Failed to reset RxMAC")); 37923dec9fcdSqs148142 goto fail; 37933dec9fcdSqs148142 } 37943dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "Re-enable RxMAC...")); 37953dec9fcdSqs148142 37963dec9fcdSqs148142 /* Re-enable RxMAC */ 37973dec9fcdSqs148142 if ((status = hxge_rx_vmac_enable(hxgep)) != HXGE_OK) { 37983dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 37993dec9fcdSqs148142 "hxge_rx_port_fatal_err_recover: Failed to enable RxMAC")); 38003dec9fcdSqs148142 goto fail; 38013dec9fcdSqs148142 } 38026ffca240SMichael Speer MUTEX_EXIT(&hxgep->vmac_lock); 38033dec9fcdSqs148142 38043dec9fcdSqs148142 /* Reset the error mask since PEU reset cleared it */ 38053dec9fcdSqs148142 HXGE_REG_WR64(hxgep->hpi_handle, RDC_FIFO_ERR_INT_MASK, 0x0); 38063dec9fcdSqs148142 38073dec9fcdSqs148142 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 38083dec9fcdSqs148142 "Recovery Successful, RxPort Restored")); 38093dec9fcdSqs148142 HXGE_DEBUG_MSG((hxgep, RX_CTL, "<== hxge_rx_port_fatal_err_recover")); 38103dec9fcdSqs148142 return (HXGE_OK); 38116ffca240SMichael Speer 38123dec9fcdSqs148142 fail: 38136ffca240SMichael Speer MUTEX_EXIT(&hxgep->vmac_lock); 38146ffca240SMichael Speer HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 38156ffca240SMichael Speer "Error Recovery failed for hxge(%d)", hxgep->instance)); 38163dec9fcdSqs148142 return (status); 38173dec9fcdSqs148142 } 38181c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States 38191c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States static void 38201c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States hxge_rbr_empty_restore(p_hxge_t hxgep, p_rx_rbr_ring_t rx_rbr_p) 38211c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States { 38221c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States hpi_status_t hpi_status; 38231c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States hxge_status_t status; 3824f043ebedSMichael Speer rdc_stat_t cs; 38251c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States p_hxge_rx_ring_stats_t rdc_stats; 38261c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States 38271c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States rdc_stats = &hxgep->statsp->rdc_stats[rx_rbr_p->rdc]; 38281c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States 38291c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States /* 38301c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States * Complete the processing for the RBR Empty by: 38311c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States * 0) kicking back HXGE_RBR_EMPTY_THRESHOLD 38321c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States * packets. 38331c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States * 1) Disable the RX vmac. 38341c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States * 2) Re-enable the affected DMA channel. 38351c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States * 3) Re-enable the RX vmac. 38361c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States */ 38371c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States 38381c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States /* 38391c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States * Disable the RX VMAC, but setting the framelength 38401c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States * to 0, since there is a hardware bug when disabling 38411c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States * the vmac. 38421c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States */ 38436ffca240SMichael Speer MUTEX_ENTER(&hxgep->vmac_lock); 38446ffca240SMichael Speer (void) hxge_rx_vmac_disable(hxgep); 38451c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States 3846f043ebedSMichael Speer /* 3847f043ebedSMichael Speer * Re-arm the mex bit for interrupts to be enabled. 3848f043ebedSMichael Speer */ 3849f043ebedSMichael Speer cs.value = 0; 3850f043ebedSMichael Speer cs.bits.mex = 1; 3851f043ebedSMichael Speer RXDMA_REG_WRITE64(HXGE_DEV_HPI_HANDLE(hxgep), RDC_STAT, 3852f043ebedSMichael Speer rx_rbr_p->rdc, cs.value); 3853f043ebedSMichael Speer 38541c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States hpi_status = hpi_rxdma_cfg_rdc_enable( 38551c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States HXGE_DEV_HPI_HANDLE(hxgep), rx_rbr_p->rdc); 38561c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States if (hpi_status != HPI_SUCCESS) { 38571c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States rdc_stats->rbr_empty_fail++; 38581c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States 38591c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States /* Assume we are already inside the post_lock */ 38601c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States status = hxge_rxdma_fatal_err_recover(hxgep, rx_rbr_p->rdc); 38611c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States if (status != HXGE_OK) { 38621c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 38631c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States "hxge(%d): channel(%d) is empty.", 38641c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States hxgep->instance, rx_rbr_p->rdc)); 38651c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States } 38661c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States } 38671c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States 38681c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States /* 38691c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States * Re-enable the RX VMAC. 38701c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States */ 38716ffca240SMichael Speer (void) hxge_rx_vmac_enable(hxgep); 38726ffca240SMichael Speer MUTEX_EXIT(&hxgep->vmac_lock); 3873f043ebedSMichael Speer 3874f043ebedSMichael Speer rdc_stats->rbr_empty_restore++; 3875f043ebedSMichael Speer rx_rbr_p->rbr_is_empty = B_FALSE; 38761c29f7e3SQiyan Sun - Sun Microsystems - San Diego United States } 3877