13526Sxy150489 /* 23526Sxy150489 * This file is provided under a CDDLv1 license. When using or 33526Sxy150489 * redistributing this file, you may do so under this license. 43526Sxy150489 * In redistributing this file this license must be included 53526Sxy150489 * and no other modification of this header file is permitted. 63526Sxy150489 * 73526Sxy150489 * CDDL LICENSE SUMMARY 83526Sxy150489 * 95882Syy150190 * Copyright(c) 1999 - 2008 Intel Corporation. All rights reserved. 103526Sxy150489 * 113526Sxy150489 * The contents of this file are subject to the terms of Version 123526Sxy150489 * 1.0 of the Common Development and Distribution License (the "License"). 133526Sxy150489 * 143526Sxy150489 * You should have received a copy of the License with this software. 153526Sxy150489 * You can obtain a copy of the License at 163526Sxy150489 * http://www.opensolaris.org/os/licensing. 173526Sxy150489 * See the License for the specific language governing permissions 183526Sxy150489 * and limitations under the License. 193526Sxy150489 */ 203526Sxy150489 213526Sxy150489 /* 225882Syy150190 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 233526Sxy150489 * Use is subject to license terms of the CDDLv1. 243526Sxy150489 */ 253526Sxy150489 263526Sxy150489 #pragma ident "%Z%%M% %I% %E% SMI" 273526Sxy150489 283526Sxy150489 /* 293526Sxy150489 * ********************************************************************** 303526Sxy150489 * * 313526Sxy150489 * Module Name: * 323526Sxy150489 * e1000g_rx.c * 333526Sxy150489 * * 343526Sxy150489 * Abstract: * 354919Sxy150489 * This file contains some routines that take care of Receive * 364919Sxy150489 * interrupt and also for the received packets it sends up to * 374919Sxy150489 * upper layer. * 383526Sxy150489 * It tries to do a zero copy if free buffers are available in * 394919Sxy150489 * the pool. * 403526Sxy150489 * * 413526Sxy150489 * ********************************************************************** 423526Sxy150489 */ 433526Sxy150489 443526Sxy150489 #include "e1000g_sw.h" 453526Sxy150489 #include "e1000g_debug.h" 463526Sxy150489 474919Sxy150489 static p_rx_sw_packet_t e1000g_get_buf(e1000g_rx_ring_t *rx_ring); 483526Sxy150489 #pragma inline(e1000g_get_buf) 494982Syy150190 static void e1000g_priv_devi_list_clean(); 503526Sxy150489 513526Sxy150489 /* 524919Sxy150489 * e1000g_rxfree_func - the call-back function to reclaim rx buffer 534919Sxy150489 * 544919Sxy150489 * This function is called when an mp is freed by the user thru 554919Sxy150489 * freeb call (Only for mp constructed through desballoc call) 564919Sxy150489 * It returns back the freed buffer to the freelist 573526Sxy150489 */ 583526Sxy150489 void 594919Sxy150489 e1000g_rxfree_func(p_rx_sw_packet_t packet) 603526Sxy150489 { 613526Sxy150489 struct e1000g *Adapter; 623526Sxy150489 e1000g_rx_ring_t *rx_ring; 633526Sxy150489 644919Sxy150489 rx_ring = (e1000g_rx_ring_t *)packet->rx_ring; 654919Sxy150489 Adapter = rx_ring->adapter; 664919Sxy150489 673526Sxy150489 /* 683526Sxy150489 * Here the rx recycling processes different rx packets in different 693526Sxy150489 * threads, so we protect it with RW_READER to ensure it won't block 703526Sxy150489 * other rx recycling threads. 713526Sxy150489 */ 723526Sxy150489 rw_enter(&e1000g_rx_detach_lock, RW_READER); 733526Sxy150489 744919Sxy150489 if (packet->flag == E1000G_RX_SW_FREE) { 753526Sxy150489 rw_exit(&e1000g_rx_detach_lock); 763526Sxy150489 return; 773526Sxy150489 } 783526Sxy150489 794919Sxy150489 if (packet->flag == E1000G_RX_SW_STOP) { 804919Sxy150489 packet->flag = E1000G_RX_SW_FREE; 814919Sxy150489 rw_exit(&e1000g_rx_detach_lock); 824919Sxy150489 834919Sxy150489 rw_enter(&e1000g_rx_detach_lock, RW_WRITER); 844919Sxy150489 rx_ring->pending_count--; 854919Sxy150489 e1000g_mblks_pending--; 864919Sxy150489 874919Sxy150489 if (rx_ring->pending_count == 0) { 884919Sxy150489 while (rx_ring->pending_list != NULL) { 894919Sxy150489 packet = rx_ring->pending_list; 904919Sxy150489 rx_ring->pending_list = 914919Sxy150489 rx_ring->pending_list->next; 924919Sxy150489 934919Sxy150489 ASSERT(packet->mp == NULL); 944919Sxy150489 e1000g_free_rx_sw_packet(packet); 954919Sxy150489 } 964919Sxy150489 } 974982Syy150190 984982Syy150190 /* 994982Syy150190 * If e1000g_force_detach is enabled, we need to clean up 1004982Syy150190 * the idle priv_dip entries in the private dip list while 1014982Syy150190 * e1000g_mblks_pending is zero. 1024982Syy150190 */ 1034982Syy150190 if (e1000g_force_detach && (e1000g_mblks_pending == 0)) 1044982Syy150190 e1000g_priv_devi_list_clean(); 1054919Sxy150489 rw_exit(&e1000g_rx_detach_lock); 1064919Sxy150489 return; 1074919Sxy150489 } 1084919Sxy150489 1094919Sxy150489 if (packet->flag == E1000G_RX_SW_DETACH) { 1104919Sxy150489 packet->flag = E1000G_RX_SW_FREE; 1113526Sxy150489 rw_exit(&e1000g_rx_detach_lock); 1123526Sxy150489 1133526Sxy150489 ASSERT(packet->mp == NULL); 1143526Sxy150489 e1000g_free_rx_sw_packet(packet); 1153526Sxy150489 1163526Sxy150489 /* 1173526Sxy150489 * Here the e1000g_mblks_pending may be modified by different 1183526Sxy150489 * rx recycling threads simultaneously, so we need to protect 1193526Sxy150489 * it with RW_WRITER. 1203526Sxy150489 */ 1213526Sxy150489 rw_enter(&e1000g_rx_detach_lock, RW_WRITER); 1223526Sxy150489 e1000g_mblks_pending--; 1234982Syy150190 1244982Syy150190 /* 1254982Syy150190 * If e1000g_force_detach is enabled, we need to clean up 1264982Syy150190 * the idle priv_dip entries in the private dip list while 1274982Syy150190 * e1000g_mblks_pending is zero. 1284982Syy150190 */ 1294982Syy150190 if (e1000g_force_detach && (e1000g_mblks_pending == 0)) 1304982Syy150190 e1000g_priv_devi_list_clean(); 1313526Sxy150489 rw_exit(&e1000g_rx_detach_lock); 1323526Sxy150489 return; 1333526Sxy150489 } 1343526Sxy150489 1354919Sxy150489 packet->flag = E1000G_RX_SW_FREE; 1363526Sxy150489 1373526Sxy150489 if (packet->mp == NULL) { 1383526Sxy150489 /* 1393526Sxy150489 * Allocate a mblk that binds to the data buffer 1403526Sxy150489 */ 1413526Sxy150489 packet->mp = desballoc((unsigned char *) 1423526Sxy150489 packet->rx_buf->address - E1000G_IPALIGNROOM, 1433526Sxy150489 packet->rx_buf->size + E1000G_IPALIGNROOM, 1443526Sxy150489 BPRI_MED, &packet->free_rtn); 1453526Sxy150489 1463526Sxy150489 if (packet->mp != NULL) { 1473526Sxy150489 packet->mp->b_rptr += E1000G_IPALIGNROOM; 1483526Sxy150489 packet->mp->b_wptr += E1000G_IPALIGNROOM; 1493526Sxy150489 } else { 1504919Sxy150489 E1000G_STAT(rx_ring->stat_esballoc_fail); 1513526Sxy150489 } 1523526Sxy150489 } 1533526Sxy150489 1543526Sxy150489 mutex_enter(&rx_ring->freelist_lock); 1553526Sxy150489 QUEUE_PUSH_TAIL(&rx_ring->free_list, &packet->Link); 1564919Sxy150489 rx_ring->avail_freepkt++; 1573526Sxy150489 mutex_exit(&rx_ring->freelist_lock); 1583526Sxy150489 1593526Sxy150489 rw_exit(&e1000g_rx_detach_lock); 1603526Sxy150489 } 1613526Sxy150489 1623526Sxy150489 /* 1634982Syy150190 * e1000g_priv_devi_list_clean - clean up e1000g_private_devi_list 1644982Syy150190 * 1654982Syy150190 * We will walk the e1000g_private_devi_list to free the entry marked 1664982Syy150190 * with the E1000G_PRIV_DEVI_DETACH flag. 1674982Syy150190 */ 1684982Syy150190 static void 1694982Syy150190 e1000g_priv_devi_list_clean() 1704982Syy150190 { 1714982Syy150190 private_devi_list_t *devi_node, *devi_del; 1724982Syy150190 1734982Syy150190 if (e1000g_private_devi_list == NULL) 1744982Syy150190 return; 1754982Syy150190 1764982Syy150190 devi_node = e1000g_private_devi_list; 1774982Syy150190 while ((devi_node != NULL) && 1784982Syy150190 (devi_node->flag == E1000G_PRIV_DEVI_DETACH)) { 1794982Syy150190 e1000g_private_devi_list = devi_node->next; 1804982Syy150190 kmem_free(devi_node->priv_dip, 1814982Syy150190 sizeof (struct dev_info)); 1824982Syy150190 kmem_free(devi_node, 1834982Syy150190 sizeof (private_devi_list_t)); 1844982Syy150190 devi_node = e1000g_private_devi_list; 1854982Syy150190 } 1864982Syy150190 if (e1000g_private_devi_list == NULL) 1874982Syy150190 return; 1884982Syy150190 while (devi_node->next != NULL) { 1894982Syy150190 if (devi_node->next->flag == E1000G_PRIV_DEVI_DETACH) { 1904982Syy150190 devi_del = devi_node->next; 1914982Syy150190 devi_node->next = devi_del->next; 1924982Syy150190 kmem_free(devi_del->priv_dip, 1934982Syy150190 sizeof (struct dev_info)); 1944982Syy150190 kmem_free(devi_del, 1954982Syy150190 sizeof (private_devi_list_t)); 1964982Syy150190 } else { 1974982Syy150190 devi_node = devi_node->next; 1984982Syy150190 } 1994982Syy150190 } 2004982Syy150190 } 2014982Syy150190 2024982Syy150190 /* 2034919Sxy150489 * e1000g_rx_setup - setup rx data structures 2044919Sxy150489 * 2054919Sxy150489 * This routine initializes all of the receive related 2064919Sxy150489 * structures. This includes the receive descriptors, the 2074919Sxy150489 * actual receive buffers, and the rx_sw_packet software 2084919Sxy150489 * structures. 2093526Sxy150489 */ 2103526Sxy150489 void 2114919Sxy150489 e1000g_rx_setup(struct e1000g *Adapter) 2123526Sxy150489 { 2134919Sxy150489 struct e1000_hw *hw; 2144919Sxy150489 p_rx_sw_packet_t packet; 2153526Sxy150489 struct e1000_rx_desc *descriptor; 2164919Sxy150489 uint32_t buf_low; 2174919Sxy150489 uint32_t buf_high; 2183526Sxy150489 uint32_t reg_val; 2193526Sxy150489 int i; 2203526Sxy150489 int size; 2213526Sxy150489 e1000g_rx_ring_t *rx_ring; 2223526Sxy150489 2234919Sxy150489 hw = &Adapter->shared; 2243526Sxy150489 rx_ring = Adapter->rx_ring; 2253526Sxy150489 2263526Sxy150489 /* 2273526Sxy150489 * zero out all of the receive buffer descriptor memory 2283526Sxy150489 * assures any previous data or status is erased 2293526Sxy150489 */ 2303526Sxy150489 bzero(rx_ring->rbd_area, 2314919Sxy150489 sizeof (struct e1000_rx_desc) * Adapter->rx_desc_num); 2323526Sxy150489 2334919Sxy150489 if (!Adapter->rx_buffer_setup) { 2343526Sxy150489 /* Init the list of "Receive Buffer" */ 2353526Sxy150489 QUEUE_INIT_LIST(&rx_ring->recv_list); 2363526Sxy150489 2373526Sxy150489 /* Init the list of "Free Receive Buffer" */ 2383526Sxy150489 QUEUE_INIT_LIST(&rx_ring->free_list); 2393526Sxy150489 2403526Sxy150489 /* 2413526Sxy150489 * Setup Receive list and the Free list. Note that 2423526Sxy150489 * the both were allocated in one packet area. 2433526Sxy150489 */ 2443526Sxy150489 packet = rx_ring->packet_area; 2453526Sxy150489 descriptor = rx_ring->rbd_first; 2463526Sxy150489 2474919Sxy150489 for (i = 0; i < Adapter->rx_desc_num; 2483526Sxy150489 i++, packet = packet->next, descriptor++) { 2493526Sxy150489 ASSERT(packet != NULL); 2503526Sxy150489 ASSERT(descriptor != NULL); 2513526Sxy150489 descriptor->buffer_addr = 2523526Sxy150489 packet->rx_buf->dma_address; 2534919Sxy150489 2544919Sxy150489 /* Add this rx_sw_packet to the receive list */ 2553526Sxy150489 QUEUE_PUSH_TAIL(&rx_ring->recv_list, 2563526Sxy150489 &packet->Link); 2573526Sxy150489 } 2583526Sxy150489 2594919Sxy150489 for (i = 0; i < Adapter->rx_freelist_num; 2603526Sxy150489 i++, packet = packet->next) { 2613526Sxy150489 ASSERT(packet != NULL); 2624919Sxy150489 /* Add this rx_sw_packet to the free list */ 2633526Sxy150489 QUEUE_PUSH_TAIL(&rx_ring->free_list, 2643526Sxy150489 &packet->Link); 2653526Sxy150489 } 2664919Sxy150489 rx_ring->avail_freepkt = Adapter->rx_freelist_num; 2674919Sxy150489 2684919Sxy150489 Adapter->rx_buffer_setup = B_TRUE; 2693526Sxy150489 } else { 2703526Sxy150489 /* Setup the initial pointer to the first rx descriptor */ 2714919Sxy150489 packet = (p_rx_sw_packet_t) 2723526Sxy150489 QUEUE_GET_HEAD(&rx_ring->recv_list); 2733526Sxy150489 descriptor = rx_ring->rbd_first; 2743526Sxy150489 2754919Sxy150489 for (i = 0; i < Adapter->rx_desc_num; i++) { 2763526Sxy150489 ASSERT(packet != NULL); 2773526Sxy150489 ASSERT(descriptor != NULL); 2783526Sxy150489 descriptor->buffer_addr = 2793526Sxy150489 packet->rx_buf->dma_address; 2804919Sxy150489 2814919Sxy150489 /* Get next rx_sw_packet */ 2824919Sxy150489 packet = (p_rx_sw_packet_t) 2833526Sxy150489 QUEUE_GET_NEXT(&rx_ring->recv_list, &packet->Link); 2843526Sxy150489 descriptor++; 2853526Sxy150489 } 2863526Sxy150489 } 2873526Sxy150489 2885882Syy150190 E1000_WRITE_REG(&Adapter->shared, E1000_RDTR, Adapter->rx_intr_delay); 2895882Syy150190 E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL, 2905882Syy150190 "E1000_RDTR: 0x%x\n", Adapter->rx_intr_delay); 2915882Syy150190 if (hw->mac.type >= e1000_82540) { 2925882Syy150190 E1000_WRITE_REG(&Adapter->shared, E1000_RADV, 2935882Syy150190 Adapter->rx_intr_abs_delay); 2945882Syy150190 E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL, 2955882Syy150190 "E1000_RADV: 0x%x\n", Adapter->rx_intr_abs_delay); 2965882Syy150190 } 2975882Syy150190 2983526Sxy150489 /* 2993526Sxy150489 * Setup our descriptor pointers 3003526Sxy150489 */ 3013526Sxy150489 rx_ring->rbd_next = rx_ring->rbd_first; 3023526Sxy150489 3034919Sxy150489 size = Adapter->rx_desc_num * sizeof (struct e1000_rx_desc); 304*6735Scc210113 E1000_WRITE_REG(hw, E1000_RDLEN(0), size); 305*6735Scc210113 size = E1000_READ_REG(hw, E1000_RDLEN(0)); 3063526Sxy150489 3073526Sxy150489 /* To get lower order bits */ 3084919Sxy150489 buf_low = (uint32_t)rx_ring->rbd_dma_addr; 3093526Sxy150489 /* To get the higher order bits */ 3104919Sxy150489 buf_high = (uint32_t)(rx_ring->rbd_dma_addr >> 32); 3113526Sxy150489 312*6735Scc210113 E1000_WRITE_REG(hw, E1000_RDBAH(0), buf_high); 313*6735Scc210113 E1000_WRITE_REG(hw, E1000_RDBAL(0), buf_low); 3143526Sxy150489 3153526Sxy150489 /* 3163526Sxy150489 * Setup our HW Rx Head & Tail descriptor pointers 3173526Sxy150489 */ 318*6735Scc210113 E1000_WRITE_REG(hw, E1000_RDT(0), 3193526Sxy150489 (uint32_t)(rx_ring->rbd_last - rx_ring->rbd_first)); 320*6735Scc210113 E1000_WRITE_REG(hw, E1000_RDH(0), 0); 3213526Sxy150489 3223526Sxy150489 /* 3233526Sxy150489 * Setup the Receive Control Register (RCTL), and ENABLE the 3243526Sxy150489 * receiver. The initial configuration is to: Enable the receiver, 3253526Sxy150489 * accept broadcasts, discard bad packets (and long packets), 3263526Sxy150489 * disable VLAN filter checking, set the receive descriptor 3273526Sxy150489 * minimum threshold size to 1/2, and the receive buffer size to 3283526Sxy150489 * 2k. 3293526Sxy150489 */ 3303526Sxy150489 reg_val = E1000_RCTL_EN | /* Enable Receive Unit */ 3313526Sxy150489 E1000_RCTL_BAM | /* Accept Broadcast Packets */ 3323526Sxy150489 E1000_RCTL_LPE | /* Large Packet Enable bit */ 3334919Sxy150489 (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT) | 3343526Sxy150489 E1000_RCTL_RDMTS_HALF | 3353526Sxy150489 E1000_RCTL_LBM_NO; /* Loopback Mode = none */ 3363526Sxy150489 3374608Syy150190 if (Adapter->strip_crc) 3384919Sxy150489 reg_val |= E1000_RCTL_SECRC; /* Strip Ethernet CRC */ 3394608Syy150190 340*6735Scc210113 if ((Adapter->max_frame_size > FRAME_SIZE_UPTO_2K) && 341*6735Scc210113 (Adapter->max_frame_size <= FRAME_SIZE_UPTO_4K)) 3423526Sxy150489 reg_val |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX; 343*6735Scc210113 else if ((Adapter->max_frame_size > FRAME_SIZE_UPTO_4K) && 344*6735Scc210113 (Adapter->max_frame_size <= FRAME_SIZE_UPTO_8K)) 3453526Sxy150489 reg_val |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX; 346*6735Scc210113 else if ((Adapter->max_frame_size > FRAME_SIZE_UPTO_8K) && 347*6735Scc210113 (Adapter->max_frame_size <= FRAME_SIZE_UPTO_16K)) 3483526Sxy150489 reg_val |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX; 3496394Scc210113 else 3503526Sxy150489 reg_val |= E1000_RCTL_SZ_2048; 3513526Sxy150489 3524919Sxy150489 if (e1000_tbi_sbp_enabled_82543(hw)) 3533526Sxy150489 reg_val |= E1000_RCTL_SBP; 3543526Sxy150489 3554919Sxy150489 /* 3564919Sxy150489 * Enable early receives on supported devices, only takes effect when 3574919Sxy150489 * packet size is equal or larger than the specified value (in 8 byte 3584919Sxy150489 * units), e.g. using jumbo frames when setting to E1000_ERT_2048 3594919Sxy150489 */ 3604919Sxy150489 if ((hw->mac.type == e1000_82573) || (hw->mac.type == e1000_ich9lan)) 3614919Sxy150489 E1000_WRITE_REG(hw, E1000_ERT, E1000_ERT_2048); 3624919Sxy150489 3634919Sxy150489 E1000_WRITE_REG(hw, E1000_RCTL, reg_val); 3643526Sxy150489 3653526Sxy150489 reg_val = 3663526Sxy150489 E1000_RXCSUM_TUOFL | /* TCP/UDP checksum offload Enable */ 3673526Sxy150489 E1000_RXCSUM_IPOFL; /* IP checksum offload Enable */ 3683526Sxy150489 3694919Sxy150489 E1000_WRITE_REG(hw, E1000_RXCSUM, reg_val); 3703526Sxy150489 } 3713526Sxy150489 3723526Sxy150489 /* 3734919Sxy150489 * e1000g_get_buf - get an rx sw packet from the free_list 3743526Sxy150489 */ 3754919Sxy150489 static p_rx_sw_packet_t 3763526Sxy150489 e1000g_get_buf(e1000g_rx_ring_t *rx_ring) 3773526Sxy150489 { 3783526Sxy150489 struct e1000g *Adapter; 3794919Sxy150489 p_rx_sw_packet_t packet; 3803526Sxy150489 3813526Sxy150489 Adapter = rx_ring->adapter; 3823526Sxy150489 3833526Sxy150489 mutex_enter(&rx_ring->freelist_lock); 3844919Sxy150489 packet = (p_rx_sw_packet_t) 3853526Sxy150489 QUEUE_POP_HEAD(&rx_ring->free_list); 3863526Sxy150489 if (packet != NULL) 3874919Sxy150489 rx_ring->avail_freepkt--; 3883526Sxy150489 mutex_exit(&rx_ring->freelist_lock); 3893526Sxy150489 3903526Sxy150489 return (packet); 3913526Sxy150489 } 3923526Sxy150489 3933526Sxy150489 /* 3944919Sxy150489 * e1000g_receive - main receive routine 3954919Sxy150489 * 3964919Sxy150489 * This routine will process packets received in an interrupt 3973526Sxy150489 */ 3983526Sxy150489 mblk_t * 3993526Sxy150489 e1000g_receive(struct e1000g *Adapter) 4003526Sxy150489 { 4014919Sxy150489 struct e1000_hw *hw; 4023526Sxy150489 mblk_t *nmp; 4033526Sxy150489 mblk_t *ret_mp; 4043526Sxy150489 mblk_t *ret_nmp; 4053526Sxy150489 struct e1000_rx_desc *current_desc; 4063526Sxy150489 struct e1000_rx_desc *last_desc; 4074919Sxy150489 p_rx_sw_packet_t packet; 4084919Sxy150489 p_rx_sw_packet_t newpkt; 4093526Sxy150489 USHORT length; 4103526Sxy150489 uint32_t pkt_count; 4113526Sxy150489 uint32_t desc_count; 4124919Sxy150489 boolean_t accept_frame; 4133526Sxy150489 boolean_t end_of_packet; 4143526Sxy150489 boolean_t need_copy; 4153526Sxy150489 e1000g_rx_ring_t *rx_ring; 4163526Sxy150489 dma_buffer_t *rx_buf; 4173526Sxy150489 uint16_t cksumflags; 4183526Sxy150489 4193526Sxy150489 ret_mp = NULL; 4203526Sxy150489 ret_nmp = NULL; 4213526Sxy150489 pkt_count = 0; 4223526Sxy150489 desc_count = 0; 4233526Sxy150489 cksumflags = 0; 4243526Sxy150489 4254919Sxy150489 hw = &Adapter->shared; 4263526Sxy150489 rx_ring = Adapter->rx_ring; 4273526Sxy150489 4283526Sxy150489 /* Sync the Rx descriptor DMA buffers */ 4293526Sxy150489 (void) ddi_dma_sync(rx_ring->rbd_dma_handle, 4304919Sxy150489 0, 0, DDI_DMA_SYNC_FORKERNEL); 4313526Sxy150489 4325273Sgl147354 if (e1000g_check_dma_handle(rx_ring->rbd_dma_handle) != DDI_FM_OK) { 4335273Sgl147354 ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED); 4345273Sgl147354 Adapter->chip_state = E1000G_ERROR; 4355273Sgl147354 } 4365273Sgl147354 4373526Sxy150489 current_desc = rx_ring->rbd_next; 4383526Sxy150489 if (!(current_desc->status & E1000_RXD_STAT_DD)) { 4393526Sxy150489 /* 4403526Sxy150489 * don't send anything up. just clear the RFD 4413526Sxy150489 */ 4424919Sxy150489 E1000G_DEBUG_STAT(rx_ring->stat_none); 4433526Sxy150489 return (ret_mp); 4443526Sxy150489 } 4453526Sxy150489 4463526Sxy150489 /* 4473526Sxy150489 * Loop through the receive descriptors starting at the last known 4483526Sxy150489 * descriptor owned by the hardware that begins a packet. 4493526Sxy150489 */ 4503526Sxy150489 while ((current_desc->status & E1000_RXD_STAT_DD) && 4514919Sxy150489 (pkt_count < Adapter->rx_limit_onintr)) { 4523526Sxy150489 4533526Sxy150489 desc_count++; 4543526Sxy150489 /* 4553526Sxy150489 * Now this can happen in Jumbo frame situation. 4563526Sxy150489 */ 4573526Sxy150489 if (current_desc->status & E1000_RXD_STAT_EOP) { 4583526Sxy150489 /* packet has EOP set */ 4593526Sxy150489 end_of_packet = B_TRUE; 4603526Sxy150489 } else { 4613526Sxy150489 /* 4623526Sxy150489 * If this received buffer does not have the 4633526Sxy150489 * End-Of-Packet bit set, the received packet 4643526Sxy150489 * will consume multiple buffers. We won't send this 4653526Sxy150489 * packet upstack till we get all the related buffers. 4663526Sxy150489 */ 4673526Sxy150489 end_of_packet = B_FALSE; 4683526Sxy150489 } 4693526Sxy150489 4703526Sxy150489 /* 4713526Sxy150489 * Get a pointer to the actual receive buffer 4723526Sxy150489 * The mp->b_rptr is mapped to The CurrentDescriptor 4733526Sxy150489 * Buffer Address. 4743526Sxy150489 */ 4753526Sxy150489 packet = 4764919Sxy150489 (p_rx_sw_packet_t)QUEUE_GET_HEAD(&rx_ring->recv_list); 4773526Sxy150489 ASSERT(packet != NULL); 4783526Sxy150489 4793526Sxy150489 rx_buf = packet->rx_buf; 4803526Sxy150489 4813526Sxy150489 length = current_desc->length; 4823526Sxy150489 4833526Sxy150489 #ifdef __sparc 4844919Sxy150489 if (packet->dma_type == USE_DVMA) 4853526Sxy150489 dvma_sync(rx_buf->dma_handle, 0, 4863526Sxy150489 DDI_DMA_SYNC_FORKERNEL); 4874919Sxy150489 else 4883526Sxy150489 (void) ddi_dma_sync(rx_buf->dma_handle, 4893526Sxy150489 E1000G_IPALIGNROOM, length, 4904919Sxy150489 DDI_DMA_SYNC_FORKERNEL); 4914919Sxy150489 #else 4924919Sxy150489 (void) ddi_dma_sync(rx_buf->dma_handle, 4934919Sxy150489 E1000G_IPALIGNROOM, length, 4944919Sxy150489 DDI_DMA_SYNC_FORKERNEL); 4954919Sxy150489 #endif 4964919Sxy150489 4975273Sgl147354 if (e1000g_check_dma_handle( 4985273Sgl147354 rx_buf->dma_handle) != DDI_FM_OK) { 4995273Sgl147354 ddi_fm_service_impact(Adapter->dip, 5005273Sgl147354 DDI_SERVICE_DEGRADED); 5015273Sgl147354 Adapter->chip_state = E1000G_ERROR; 5025273Sgl147354 } 5035273Sgl147354 5044919Sxy150489 accept_frame = (current_desc->errors == 0) || 5054919Sxy150489 ((current_desc->errors & 5064919Sxy150489 (E1000_RXD_ERR_TCPE | E1000_RXD_ERR_IPE)) != 0); 5074919Sxy150489 5084919Sxy150489 if (hw->mac.type == e1000_82543) { 5094919Sxy150489 unsigned char last_byte; 5104919Sxy150489 5114919Sxy150489 last_byte = 5124919Sxy150489 *((unsigned char *)rx_buf->address + length - 1); 5134919Sxy150489 5144919Sxy150489 if (TBI_ACCEPT(hw, 5154919Sxy150489 current_desc->status, current_desc->errors, 516*6735Scc210113 current_desc->length, last_byte, 517*6735Scc210113 Adapter->min_frame_size, Adapter->max_frame_size)) { 5184919Sxy150489 5194919Sxy150489 e1000_tbi_adjust_stats(Adapter, 5204919Sxy150489 length, hw->mac.addr); 5214919Sxy150489 5224919Sxy150489 length--; 5234919Sxy150489 accept_frame = B_TRUE; 5244919Sxy150489 } else if (e1000_tbi_sbp_enabled_82543(hw) && 5254919Sxy150489 (current_desc->errors == E1000_RXD_ERR_CE)) { 5264919Sxy150489 accept_frame = B_TRUE; 5274919Sxy150489 } 5283526Sxy150489 } 5293526Sxy150489 5303526Sxy150489 /* 5313526Sxy150489 * Indicate the packet to the NOS if it was good. 5323526Sxy150489 * Normally, hardware will discard bad packets for us. 5333526Sxy150489 * Check for the packet to be a valid Ethernet packet 5343526Sxy150489 */ 5354919Sxy150489 if (!accept_frame) { 5363526Sxy150489 /* 5373526Sxy150489 * error in incoming packet, either the packet is not a 5383526Sxy150489 * ethernet size packet, or the packet has an error. In 5393526Sxy150489 * either case, the packet will simply be discarded. 5403526Sxy150489 */ 5414919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL, 5423526Sxy150489 "Process Receive Interrupts: Error in Packet\n"); 5433526Sxy150489 5444919Sxy150489 E1000G_STAT(rx_ring->stat_error); 5453526Sxy150489 /* 5463526Sxy150489 * Returning here as we are done here. There is 5473526Sxy150489 * no point in waiting for while loop to elapse 5483526Sxy150489 * and the things which were done. More efficient 5493526Sxy150489 * and less error prone... 5503526Sxy150489 */ 5513526Sxy150489 goto rx_drop; 5523526Sxy150489 } 5533526Sxy150489 5544608Syy150190 /* 5554608Syy150190 * If the Ethernet CRC is not stripped by the hardware, 5564608Syy150190 * we need to strip it before sending it up to the stack. 5574608Syy150190 */ 5584608Syy150190 if (end_of_packet && !Adapter->strip_crc) { 5596394Scc210113 if (length > ETHERFCSL) { 5606394Scc210113 length -= ETHERFCSL; 5614608Syy150190 } else { 5624608Syy150190 /* 5634608Syy150190 * If the fragment is smaller than the CRC, 5644608Syy150190 * drop this fragment, do the processing of 5654608Syy150190 * the end of the packet. 5664608Syy150190 */ 5674919Sxy150489 ASSERT(rx_ring->rx_mblk_tail != NULL); 5684919Sxy150489 rx_ring->rx_mblk_tail->b_wptr -= 5696394Scc210113 ETHERFCSL - length; 5704919Sxy150489 rx_ring->rx_mblk_len -= 5716394Scc210113 ETHERFCSL - length; 5724608Syy150190 5734608Syy150190 QUEUE_POP_HEAD(&rx_ring->recv_list); 5744608Syy150190 5754608Syy150190 goto rx_end_of_packet; 5764608Syy150190 } 5774608Syy150190 } 5784608Syy150190 5793526Sxy150489 need_copy = B_TRUE; 5803526Sxy150489 5813526Sxy150489 if (length <= Adapter->rx_bcopy_thresh) 5823526Sxy150489 goto rx_copy; 5833526Sxy150489 5843526Sxy150489 /* 5853526Sxy150489 * Get the pre-constructed mblk that was associated 5863526Sxy150489 * to the receive data buffer. 5873526Sxy150489 */ 5883526Sxy150489 if (packet->mp == NULL) { 5893526Sxy150489 packet->mp = desballoc((unsigned char *) 5903526Sxy150489 rx_buf->address - E1000G_IPALIGNROOM, 5913526Sxy150489 length + E1000G_IPALIGNROOM, 5923526Sxy150489 BPRI_MED, &packet->free_rtn); 5933526Sxy150489 5943526Sxy150489 if (packet->mp != NULL) { 5953526Sxy150489 packet->mp->b_rptr += E1000G_IPALIGNROOM; 5963526Sxy150489 packet->mp->b_wptr += E1000G_IPALIGNROOM; 5973526Sxy150489 } else { 5984919Sxy150489 E1000G_STAT(rx_ring->stat_esballoc_fail); 5993526Sxy150489 } 6003526Sxy150489 } 6013526Sxy150489 6023526Sxy150489 if (packet->mp != NULL) { 6033526Sxy150489 /* 6043526Sxy150489 * We have two sets of buffer pool. One associated with 6053526Sxy150489 * the Rxdescriptors and other a freelist buffer pool. 6063526Sxy150489 * Each time we get a good packet, Try to get a buffer 6073526Sxy150489 * from the freelist pool using e1000g_get_buf. If we 6083526Sxy150489 * get free buffer, then replace the descriptor buffer 6093526Sxy150489 * address with the free buffer we just got, and pass 6103526Sxy150489 * the pre-constructed mblk upstack. (note no copying) 6113526Sxy150489 * 6123526Sxy150489 * If we failed to get a free buffer, then try to 6133526Sxy150489 * allocate a new buffer(mp) and copy the recv buffer 6143526Sxy150489 * content to our newly allocated buffer(mp). Don't 6153526Sxy150489 * disturb the desriptor buffer address. (note copying) 6163526Sxy150489 */ 6173526Sxy150489 newpkt = e1000g_get_buf(rx_ring); 6183526Sxy150489 6193526Sxy150489 if (newpkt != NULL) { 6203526Sxy150489 /* 6213526Sxy150489 * Get the mblk associated to the data, 6223526Sxy150489 * and strip it off the sw packet. 6233526Sxy150489 */ 6243526Sxy150489 nmp = packet->mp; 6253526Sxy150489 packet->mp = NULL; 6264982Syy150190 packet->flag = E1000G_RX_SW_SENDUP; 6273526Sxy150489 6283526Sxy150489 /* 6293526Sxy150489 * Now replace old buffer with the new 6303526Sxy150489 * one we got from free list 6313526Sxy150489 * Both the RxSwPacket as well as the 6323526Sxy150489 * Receive Buffer Descriptor will now 6333526Sxy150489 * point to this new packet. 6343526Sxy150489 */ 6353526Sxy150489 packet = newpkt; 6364919Sxy150489 6373526Sxy150489 current_desc->buffer_addr = 6383526Sxy150489 newpkt->rx_buf->dma_address; 6394919Sxy150489 6403526Sxy150489 need_copy = B_FALSE; 6413526Sxy150489 } else { 6424919Sxy150489 E1000G_DEBUG_STAT(rx_ring->stat_no_freepkt); 6433526Sxy150489 } 6443526Sxy150489 } 6453526Sxy150489 6463526Sxy150489 rx_copy: 6473526Sxy150489 if (need_copy) { 6483526Sxy150489 /* 6493526Sxy150489 * No buffers available on free list, 6503526Sxy150489 * bcopy the data from the buffer and 6513526Sxy150489 * keep the original buffer. Dont want to 6523526Sxy150489 * do this.. Yack but no other way 6533526Sxy150489 */ 6544919Sxy150489 if ((nmp = allocb(length + E1000G_IPALIGNROOM, 6554608Syy150190 BPRI_MED)) == NULL) { 6563526Sxy150489 /* 6573526Sxy150489 * The system has no buffers available 6583526Sxy150489 * to send up the incoming packet, hence 6593526Sxy150489 * the packet will have to be processed 6603526Sxy150489 * when there're more buffers available. 6613526Sxy150489 */ 6624919Sxy150489 E1000G_STAT(rx_ring->stat_allocb_fail); 6633526Sxy150489 goto rx_drop; 6643526Sxy150489 } 6653526Sxy150489 nmp->b_rptr += E1000G_IPALIGNROOM; 6663526Sxy150489 nmp->b_wptr += E1000G_IPALIGNROOM; 6673526Sxy150489 /* 6683526Sxy150489 * The free list did not have any buffers 6693526Sxy150489 * available, so, the received packet will 6703526Sxy150489 * have to be copied into a mp and the original 6713526Sxy150489 * buffer will have to be retained for future 6723526Sxy150489 * packet reception. 6733526Sxy150489 */ 6744919Sxy150489 bcopy(rx_buf->address, nmp->b_wptr, length); 6753526Sxy150489 } 6763526Sxy150489 6773526Sxy150489 /* 6784919Sxy150489 * The rx_sw_packet MUST be popped off the 6793526Sxy150489 * RxSwPacketList before either a putnext or freemsg 6803526Sxy150489 * is done on the mp that has now been created by the 6813526Sxy150489 * desballoc. If not, it is possible that the free 6823526Sxy150489 * routine will get called from the interrupt context 6833526Sxy150489 * and try to put this packet on the free list 6843526Sxy150489 */ 6854919Sxy150489 (p_rx_sw_packet_t)QUEUE_POP_HEAD(&rx_ring->recv_list); 6863526Sxy150489 6873526Sxy150489 ASSERT(nmp != NULL); 6883526Sxy150489 nmp->b_wptr += length; 6893526Sxy150489 6904919Sxy150489 if (rx_ring->rx_mblk == NULL) { 6913526Sxy150489 /* 6923526Sxy150489 * TCP/UDP checksum offload and 6933526Sxy150489 * IP checksum offload 6943526Sxy150489 */ 6954919Sxy150489 if (!(current_desc->status & E1000_RXD_STAT_IXSM)) { 6963526Sxy150489 /* 6973526Sxy150489 * Check TCP/UDP checksum 6983526Sxy150489 */ 6993526Sxy150489 if ((current_desc->status & 7004608Syy150190 E1000_RXD_STAT_TCPCS) && 7013526Sxy150489 !(current_desc->errors & 7024608Syy150190 E1000_RXD_ERR_TCPE)) 7033526Sxy150489 cksumflags |= HCK_FULLCKSUM | 7044608Syy150190 HCK_FULLCKSUM_OK; 7053526Sxy150489 /* 7063526Sxy150489 * Check IP Checksum 7073526Sxy150489 */ 7083526Sxy150489 if ((current_desc->status & 7094608Syy150190 E1000_RXD_STAT_IPCS) && 7103526Sxy150489 !(current_desc->errors & 7114608Syy150190 E1000_RXD_ERR_IPE)) 7123526Sxy150489 cksumflags |= HCK_IPV4_HDRCKSUM; 7133526Sxy150489 } 7143526Sxy150489 } 7153526Sxy150489 7163526Sxy150489 /* 7173526Sxy150489 * We need to maintain our packet chain in the global 7183526Sxy150489 * Adapter structure, for the Rx processing can end 7193526Sxy150489 * with a fragment that has no EOP set. 7203526Sxy150489 */ 7214919Sxy150489 if (rx_ring->rx_mblk == NULL) { 7223526Sxy150489 /* Get the head of the message chain */ 7234919Sxy150489 rx_ring->rx_mblk = nmp; 7244919Sxy150489 rx_ring->rx_mblk_tail = nmp; 7254919Sxy150489 rx_ring->rx_mblk_len = length; 7263526Sxy150489 } else { /* Not the first packet */ 7273526Sxy150489 /* Continue adding buffers */ 7284919Sxy150489 rx_ring->rx_mblk_tail->b_cont = nmp; 7294919Sxy150489 rx_ring->rx_mblk_tail = nmp; 7304919Sxy150489 rx_ring->rx_mblk_len += length; 7313526Sxy150489 } 7324919Sxy150489 ASSERT(rx_ring->rx_mblk != NULL); 7334919Sxy150489 ASSERT(rx_ring->rx_mblk_tail != NULL); 7344919Sxy150489 ASSERT(rx_ring->rx_mblk_tail->b_cont == NULL); 7353526Sxy150489 7363526Sxy150489 /* 7373526Sxy150489 * Now this MP is ready to travel upwards but some more 7383526Sxy150489 * fragments are coming. 7393526Sxy150489 * We will send packet upwards as soon as we get EOP 7403526Sxy150489 * set on the packet. 7413526Sxy150489 */ 7423526Sxy150489 if (!end_of_packet) { 7433526Sxy150489 /* 7443526Sxy150489 * continue to get the next descriptor, 7453526Sxy150489 * Tail would be advanced at the end 7463526Sxy150489 */ 7473526Sxy150489 goto rx_next_desc; 7483526Sxy150489 } 7493526Sxy150489 7504608Syy150190 rx_end_of_packet: 7513526Sxy150489 /* 7523526Sxy150489 * Found packet with EOP 7533526Sxy150489 * Process the last fragment. 7543526Sxy150489 */ 7553526Sxy150489 if (cksumflags != 0) { 7564919Sxy150489 (void) hcksum_assoc(rx_ring->rx_mblk, 7573526Sxy150489 NULL, NULL, 0, 0, 0, 0, cksumflags, 0); 7583526Sxy150489 cksumflags = 0; 7593526Sxy150489 } 7603526Sxy150489 7613526Sxy150489 /* 7623526Sxy150489 * Count packets that span multi-descriptors 7633526Sxy150489 */ 7644919Sxy150489 E1000G_DEBUG_STAT_COND(rx_ring->stat_multi_desc, 7654919Sxy150489 (rx_ring->rx_mblk->b_cont != NULL)); 7663526Sxy150489 7673526Sxy150489 /* 7683526Sxy150489 * Append to list to send upstream 7693526Sxy150489 */ 7703526Sxy150489 if (ret_mp == NULL) { 7714919Sxy150489 ret_mp = ret_nmp = rx_ring->rx_mblk; 7723526Sxy150489 } else { 7734919Sxy150489 ret_nmp->b_next = rx_ring->rx_mblk; 7744919Sxy150489 ret_nmp = rx_ring->rx_mblk; 7753526Sxy150489 } 7763526Sxy150489 ret_nmp->b_next = NULL; 7773526Sxy150489 7784919Sxy150489 rx_ring->rx_mblk = NULL; 7794919Sxy150489 rx_ring->rx_mblk_tail = NULL; 7804919Sxy150489 rx_ring->rx_mblk_len = 0; 7813526Sxy150489 7823526Sxy150489 pkt_count++; 7833526Sxy150489 7843526Sxy150489 rx_next_desc: 7853526Sxy150489 /* 7863526Sxy150489 * Zero out the receive descriptors status 7873526Sxy150489 */ 7883526Sxy150489 current_desc->status = 0; 7893526Sxy150489 7903526Sxy150489 if (current_desc == rx_ring->rbd_last) 7913526Sxy150489 rx_ring->rbd_next = rx_ring->rbd_first; 7923526Sxy150489 else 7933526Sxy150489 rx_ring->rbd_next++; 7943526Sxy150489 7953526Sxy150489 last_desc = current_desc; 7963526Sxy150489 current_desc = rx_ring->rbd_next; 7973526Sxy150489 7983526Sxy150489 /* 7993526Sxy150489 * Put the buffer that we just indicated back 8003526Sxy150489 * at the end of our list 8013526Sxy150489 */ 8023526Sxy150489 QUEUE_PUSH_TAIL(&rx_ring->recv_list, 8033526Sxy150489 &packet->Link); 8043526Sxy150489 } /* while loop */ 8053526Sxy150489 8063526Sxy150489 /* Sync the Rx descriptor DMA buffers */ 8074919Sxy150489 (void) ddi_dma_sync(rx_ring->rbd_dma_handle, 8084919Sxy150489 0, 0, DDI_DMA_SYNC_FORDEV); 8093526Sxy150489 8103526Sxy150489 /* 8113526Sxy150489 * Advance the E1000's Receive Queue #0 "Tail Pointer". 8123526Sxy150489 */ 813*6735Scc210113 E1000_WRITE_REG(hw, E1000_RDT(0), 8143526Sxy150489 (uint32_t)(last_desc - rx_ring->rbd_first)); 8153526Sxy150489 8165273Sgl147354 if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK) { 8175273Sgl147354 ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED); 8185273Sgl147354 Adapter->chip_state = E1000G_ERROR; 8195273Sgl147354 } 8205273Sgl147354 8215882Syy150190 Adapter->rx_pkt_cnt = pkt_count; 8225882Syy150190 8233526Sxy150489 return (ret_mp); 8243526Sxy150489 8253526Sxy150489 rx_drop: 8263526Sxy150489 /* 8273526Sxy150489 * Zero out the receive descriptors status 8283526Sxy150489 */ 8293526Sxy150489 current_desc->status = 0; 8303526Sxy150489 8313526Sxy150489 /* Sync the Rx descriptor DMA buffers */ 8324919Sxy150489 (void) ddi_dma_sync(rx_ring->rbd_dma_handle, 8334919Sxy150489 0, 0, DDI_DMA_SYNC_FORDEV); 8343526Sxy150489 8353526Sxy150489 if (current_desc == rx_ring->rbd_last) 8363526Sxy150489 rx_ring->rbd_next = rx_ring->rbd_first; 8373526Sxy150489 else 8383526Sxy150489 rx_ring->rbd_next++; 8393526Sxy150489 8403526Sxy150489 last_desc = current_desc; 8413526Sxy150489 8424919Sxy150489 (p_rx_sw_packet_t)QUEUE_POP_HEAD(&rx_ring->recv_list); 8433526Sxy150489 8443526Sxy150489 QUEUE_PUSH_TAIL(&rx_ring->recv_list, &packet->Link); 8453526Sxy150489 /* 8463526Sxy150489 * Reclaim all old buffers already allocated during 8473526Sxy150489 * Jumbo receives.....for incomplete reception 8483526Sxy150489 */ 8494919Sxy150489 if (rx_ring->rx_mblk != NULL) { 8504919Sxy150489 freemsg(rx_ring->rx_mblk); 8514919Sxy150489 rx_ring->rx_mblk = NULL; 8524919Sxy150489 rx_ring->rx_mblk_tail = NULL; 8534919Sxy150489 rx_ring->rx_mblk_len = 0; 8543526Sxy150489 } 8553526Sxy150489 /* 8563526Sxy150489 * Advance the E1000's Receive Queue #0 "Tail Pointer". 8573526Sxy150489 */ 858*6735Scc210113 E1000_WRITE_REG(hw, E1000_RDT(0), 8593526Sxy150489 (uint32_t)(last_desc - rx_ring->rbd_first)); 8603526Sxy150489 8615273Sgl147354 if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK) { 8625273Sgl147354 ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED); 8635273Sgl147354 Adapter->chip_state = E1000G_ERROR; 8645273Sgl147354 } 8655273Sgl147354 8663526Sxy150489 return (ret_mp); 8673526Sxy150489 } 868