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 /* 273526Sxy150489 * ********************************************************************** 283526Sxy150489 * * 293526Sxy150489 * Module Name: * 303526Sxy150489 * e1000g_rx.c * 313526Sxy150489 * * 323526Sxy150489 * Abstract: * 334919Sxy150489 * This file contains some routines that take care of Receive * 344919Sxy150489 * interrupt and also for the received packets it sends up to * 354919Sxy150489 * upper layer. * 363526Sxy150489 * It tries to do a zero copy if free buffers are available in * 374919Sxy150489 * the pool. * 383526Sxy150489 * * 393526Sxy150489 * ********************************************************************** 403526Sxy150489 */ 413526Sxy150489 423526Sxy150489 #include "e1000g_sw.h" 433526Sxy150489 #include "e1000g_debug.h" 443526Sxy150489 454919Sxy150489 static p_rx_sw_packet_t e1000g_get_buf(e1000g_rx_ring_t *rx_ring); 463526Sxy150489 #pragma inline(e1000g_get_buf) 474982Syy150190 static void e1000g_priv_devi_list_clean(); 483526Sxy150489 493526Sxy150489 /* 504919Sxy150489 * e1000g_rxfree_func - the call-back function to reclaim rx buffer 514919Sxy150489 * 524919Sxy150489 * This function is called when an mp is freed by the user thru 534919Sxy150489 * freeb call (Only for mp constructed through desballoc call) 544919Sxy150489 * It returns back the freed buffer to the freelist 553526Sxy150489 */ 563526Sxy150489 void 574919Sxy150489 e1000g_rxfree_func(p_rx_sw_packet_t packet) 583526Sxy150489 { 593526Sxy150489 e1000g_rx_ring_t *rx_ring; 603526Sxy150489 617426SChenliang.Xu@Sun.COM rx_ring = (e1000g_rx_ring_t *)(uintptr_t)packet->rx_ring; 624919Sxy150489 633526Sxy150489 /* 643526Sxy150489 * Here the rx recycling processes different rx packets in different 653526Sxy150489 * threads, so we protect it with RW_READER to ensure it won't block 663526Sxy150489 * other rx recycling threads. 673526Sxy150489 */ 683526Sxy150489 rw_enter(&e1000g_rx_detach_lock, RW_READER); 693526Sxy150489 704919Sxy150489 if (packet->flag == E1000G_RX_SW_FREE) { 713526Sxy150489 rw_exit(&e1000g_rx_detach_lock); 723526Sxy150489 return; 733526Sxy150489 } 743526Sxy150489 754919Sxy150489 if (packet->flag == E1000G_RX_SW_STOP) { 764919Sxy150489 packet->flag = E1000G_RX_SW_FREE; 774919Sxy150489 rw_exit(&e1000g_rx_detach_lock); 784919Sxy150489 794919Sxy150489 rw_enter(&e1000g_rx_detach_lock, RW_WRITER); 804919Sxy150489 rx_ring->pending_count--; 814919Sxy150489 e1000g_mblks_pending--; 824919Sxy150489 834919Sxy150489 if (rx_ring->pending_count == 0) { 844919Sxy150489 while (rx_ring->pending_list != NULL) { 854919Sxy150489 packet = rx_ring->pending_list; 864919Sxy150489 rx_ring->pending_list = 874919Sxy150489 rx_ring->pending_list->next; 884919Sxy150489 894919Sxy150489 ASSERT(packet->mp == NULL); 904919Sxy150489 e1000g_free_rx_sw_packet(packet); 914919Sxy150489 } 924919Sxy150489 } 934982Syy150190 944982Syy150190 /* 954982Syy150190 * If e1000g_force_detach is enabled, we need to clean up 964982Syy150190 * the idle priv_dip entries in the private dip list while 974982Syy150190 * e1000g_mblks_pending is zero. 984982Syy150190 */ 994982Syy150190 if (e1000g_force_detach && (e1000g_mblks_pending == 0)) 1004982Syy150190 e1000g_priv_devi_list_clean(); 1014919Sxy150489 rw_exit(&e1000g_rx_detach_lock); 1024919Sxy150489 return; 1034919Sxy150489 } 1044919Sxy150489 1054919Sxy150489 if (packet->flag == E1000G_RX_SW_DETACH) { 1064919Sxy150489 packet->flag = E1000G_RX_SW_FREE; 1073526Sxy150489 rw_exit(&e1000g_rx_detach_lock); 1083526Sxy150489 1093526Sxy150489 ASSERT(packet->mp == NULL); 1103526Sxy150489 e1000g_free_rx_sw_packet(packet); 1113526Sxy150489 1123526Sxy150489 /* 1133526Sxy150489 * Here the e1000g_mblks_pending may be modified by different 1143526Sxy150489 * rx recycling threads simultaneously, so we need to protect 1153526Sxy150489 * it with RW_WRITER. 1163526Sxy150489 */ 1173526Sxy150489 rw_enter(&e1000g_rx_detach_lock, RW_WRITER); 1183526Sxy150489 e1000g_mblks_pending--; 1194982Syy150190 1204982Syy150190 /* 1214982Syy150190 * If e1000g_force_detach is enabled, we need to clean up 1224982Syy150190 * the idle priv_dip entries in the private dip list while 1234982Syy150190 * e1000g_mblks_pending is zero. 1244982Syy150190 */ 1254982Syy150190 if (e1000g_force_detach && (e1000g_mblks_pending == 0)) 1264982Syy150190 e1000g_priv_devi_list_clean(); 1273526Sxy150489 rw_exit(&e1000g_rx_detach_lock); 1283526Sxy150489 return; 1293526Sxy150489 } 1303526Sxy150489 1314919Sxy150489 packet->flag = E1000G_RX_SW_FREE; 1323526Sxy150489 1333526Sxy150489 if (packet->mp == NULL) { 1343526Sxy150489 /* 1353526Sxy150489 * Allocate a mblk that binds to the data buffer 1363526Sxy150489 */ 1373526Sxy150489 packet->mp = desballoc((unsigned char *) 1383526Sxy150489 packet->rx_buf->address - E1000G_IPALIGNROOM, 1393526Sxy150489 packet->rx_buf->size + E1000G_IPALIGNROOM, 1403526Sxy150489 BPRI_MED, &packet->free_rtn); 1413526Sxy150489 1423526Sxy150489 if (packet->mp != NULL) { 1433526Sxy150489 packet->mp->b_rptr += E1000G_IPALIGNROOM; 1443526Sxy150489 packet->mp->b_wptr += E1000G_IPALIGNROOM; 1453526Sxy150489 } else { 1464919Sxy150489 E1000G_STAT(rx_ring->stat_esballoc_fail); 1473526Sxy150489 } 1483526Sxy150489 } 1493526Sxy150489 1503526Sxy150489 mutex_enter(&rx_ring->freelist_lock); 1513526Sxy150489 QUEUE_PUSH_TAIL(&rx_ring->free_list, &packet->Link); 1524919Sxy150489 rx_ring->avail_freepkt++; 1533526Sxy150489 mutex_exit(&rx_ring->freelist_lock); 1543526Sxy150489 1553526Sxy150489 rw_exit(&e1000g_rx_detach_lock); 1563526Sxy150489 } 1573526Sxy150489 1583526Sxy150489 /* 1594982Syy150190 * e1000g_priv_devi_list_clean - clean up e1000g_private_devi_list 1604982Syy150190 * 1614982Syy150190 * We will walk the e1000g_private_devi_list to free the entry marked 1624982Syy150190 * with the E1000G_PRIV_DEVI_DETACH flag. 1634982Syy150190 */ 1644982Syy150190 static void 1654982Syy150190 e1000g_priv_devi_list_clean() 1664982Syy150190 { 1674982Syy150190 private_devi_list_t *devi_node, *devi_del; 1684982Syy150190 1694982Syy150190 if (e1000g_private_devi_list == NULL) 1704982Syy150190 return; 1714982Syy150190 1724982Syy150190 devi_node = e1000g_private_devi_list; 1734982Syy150190 while ((devi_node != NULL) && 1744982Syy150190 (devi_node->flag == E1000G_PRIV_DEVI_DETACH)) { 1754982Syy150190 e1000g_private_devi_list = devi_node->next; 1764982Syy150190 kmem_free(devi_node->priv_dip, 1774982Syy150190 sizeof (struct dev_info)); 1784982Syy150190 kmem_free(devi_node, 1794982Syy150190 sizeof (private_devi_list_t)); 1804982Syy150190 devi_node = e1000g_private_devi_list; 1814982Syy150190 } 1824982Syy150190 if (e1000g_private_devi_list == NULL) 1834982Syy150190 return; 1844982Syy150190 while (devi_node->next != NULL) { 1854982Syy150190 if (devi_node->next->flag == E1000G_PRIV_DEVI_DETACH) { 1864982Syy150190 devi_del = devi_node->next; 1874982Syy150190 devi_node->next = devi_del->next; 1884982Syy150190 kmem_free(devi_del->priv_dip, 1894982Syy150190 sizeof (struct dev_info)); 1904982Syy150190 kmem_free(devi_del, 1914982Syy150190 sizeof (private_devi_list_t)); 1924982Syy150190 } else { 1934982Syy150190 devi_node = devi_node->next; 1944982Syy150190 } 1954982Syy150190 } 1964982Syy150190 } 1974982Syy150190 1984982Syy150190 /* 1994919Sxy150489 * e1000g_rx_setup - setup rx data structures 2004919Sxy150489 * 2014919Sxy150489 * This routine initializes all of the receive related 2024919Sxy150489 * structures. This includes the receive descriptors, the 2034919Sxy150489 * actual receive buffers, and the rx_sw_packet software 2044919Sxy150489 * structures. 2053526Sxy150489 */ 2063526Sxy150489 void 2074919Sxy150489 e1000g_rx_setup(struct e1000g *Adapter) 2083526Sxy150489 { 2094919Sxy150489 struct e1000_hw *hw; 2104919Sxy150489 p_rx_sw_packet_t packet; 2113526Sxy150489 struct e1000_rx_desc *descriptor; 2124919Sxy150489 uint32_t buf_low; 2134919Sxy150489 uint32_t buf_high; 2143526Sxy150489 uint32_t reg_val; 2157607STed.You@Sun.COM uint32_t rctl; 2167607STed.You@Sun.COM uint32_t rxdctl; 2177607STed.You@Sun.COM uint32_t ert; 2183526Sxy150489 int i; 2193526Sxy150489 int size; 2203526Sxy150489 e1000g_rx_ring_t *rx_ring; 2213526Sxy150489 2224919Sxy150489 hw = &Adapter->shared; 2233526Sxy150489 rx_ring = Adapter->rx_ring; 2243526Sxy150489 2253526Sxy150489 /* 2263526Sxy150489 * zero out all of the receive buffer descriptor memory 2273526Sxy150489 * assures any previous data or status is erased 2283526Sxy150489 */ 2293526Sxy150489 bzero(rx_ring->rbd_area, 2304919Sxy150489 sizeof (struct e1000_rx_desc) * Adapter->rx_desc_num); 2313526Sxy150489 2324919Sxy150489 if (!Adapter->rx_buffer_setup) { 2333526Sxy150489 /* Init the list of "Receive Buffer" */ 2343526Sxy150489 QUEUE_INIT_LIST(&rx_ring->recv_list); 2353526Sxy150489 2363526Sxy150489 /* Init the list of "Free Receive Buffer" */ 2373526Sxy150489 QUEUE_INIT_LIST(&rx_ring->free_list); 2383526Sxy150489 2393526Sxy150489 /* 2403526Sxy150489 * Setup Receive list and the Free list. Note that 2413526Sxy150489 * the both were allocated in one packet area. 2423526Sxy150489 */ 2433526Sxy150489 packet = rx_ring->packet_area; 2443526Sxy150489 descriptor = rx_ring->rbd_first; 2453526Sxy150489 2464919Sxy150489 for (i = 0; i < Adapter->rx_desc_num; 2473526Sxy150489 i++, packet = packet->next, descriptor++) { 2483526Sxy150489 ASSERT(packet != NULL); 2493526Sxy150489 ASSERT(descriptor != NULL); 2503526Sxy150489 descriptor->buffer_addr = 2513526Sxy150489 packet->rx_buf->dma_address; 2524919Sxy150489 2534919Sxy150489 /* Add this rx_sw_packet to the receive list */ 2543526Sxy150489 QUEUE_PUSH_TAIL(&rx_ring->recv_list, 2553526Sxy150489 &packet->Link); 2563526Sxy150489 } 2573526Sxy150489 2584919Sxy150489 for (i = 0; i < Adapter->rx_freelist_num; 2593526Sxy150489 i++, packet = packet->next) { 2603526Sxy150489 ASSERT(packet != NULL); 2614919Sxy150489 /* Add this rx_sw_packet to the free list */ 2623526Sxy150489 QUEUE_PUSH_TAIL(&rx_ring->free_list, 2633526Sxy150489 &packet->Link); 2643526Sxy150489 } 2654919Sxy150489 rx_ring->avail_freepkt = Adapter->rx_freelist_num; 2664919Sxy150489 2674919Sxy150489 Adapter->rx_buffer_setup = B_TRUE; 2683526Sxy150489 } else { 2693526Sxy150489 /* Setup the initial pointer to the first rx descriptor */ 2704919Sxy150489 packet = (p_rx_sw_packet_t) 2713526Sxy150489 QUEUE_GET_HEAD(&rx_ring->recv_list); 2723526Sxy150489 descriptor = rx_ring->rbd_first; 2733526Sxy150489 2744919Sxy150489 for (i = 0; i < Adapter->rx_desc_num; i++) { 2753526Sxy150489 ASSERT(packet != NULL); 2763526Sxy150489 ASSERT(descriptor != NULL); 2773526Sxy150489 descriptor->buffer_addr = 2783526Sxy150489 packet->rx_buf->dma_address; 2794919Sxy150489 2804919Sxy150489 /* Get next rx_sw_packet */ 2814919Sxy150489 packet = (p_rx_sw_packet_t) 2823526Sxy150489 QUEUE_GET_NEXT(&rx_ring->recv_list, &packet->Link); 2833526Sxy150489 descriptor++; 2843526Sxy150489 } 2853526Sxy150489 } 2863526Sxy150489 2875882Syy150190 E1000_WRITE_REG(&Adapter->shared, E1000_RDTR, Adapter->rx_intr_delay); 2885882Syy150190 E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL, 2895882Syy150190 "E1000_RDTR: 0x%x\n", Adapter->rx_intr_delay); 2905882Syy150190 if (hw->mac.type >= e1000_82540) { 2915882Syy150190 E1000_WRITE_REG(&Adapter->shared, E1000_RADV, 2925882Syy150190 Adapter->rx_intr_abs_delay); 2935882Syy150190 E1000G_DEBUGLOG_1(Adapter, E1000G_INFO_LEVEL, 2945882Syy150190 "E1000_RADV: 0x%x\n", Adapter->rx_intr_abs_delay); 2955882Syy150190 } 2965882Syy150190 2973526Sxy150489 /* 2983526Sxy150489 * Setup our descriptor pointers 2993526Sxy150489 */ 3003526Sxy150489 rx_ring->rbd_next = rx_ring->rbd_first; 3013526Sxy150489 3024919Sxy150489 size = Adapter->rx_desc_num * sizeof (struct e1000_rx_desc); 3036735Scc210113 E1000_WRITE_REG(hw, E1000_RDLEN(0), size); 3046735Scc210113 size = E1000_READ_REG(hw, E1000_RDLEN(0)); 3053526Sxy150489 3063526Sxy150489 /* To get lower order bits */ 3074919Sxy150489 buf_low = (uint32_t)rx_ring->rbd_dma_addr; 3083526Sxy150489 /* To get the higher order bits */ 3094919Sxy150489 buf_high = (uint32_t)(rx_ring->rbd_dma_addr >> 32); 3103526Sxy150489 3116735Scc210113 E1000_WRITE_REG(hw, E1000_RDBAH(0), buf_high); 3126735Scc210113 E1000_WRITE_REG(hw, E1000_RDBAL(0), buf_low); 3133526Sxy150489 3143526Sxy150489 /* 3153526Sxy150489 * Setup our HW Rx Head & Tail descriptor pointers 3163526Sxy150489 */ 3176735Scc210113 E1000_WRITE_REG(hw, E1000_RDT(0), 3183526Sxy150489 (uint32_t)(rx_ring->rbd_last - rx_ring->rbd_first)); 3196735Scc210113 E1000_WRITE_REG(hw, E1000_RDH(0), 0); 3203526Sxy150489 3213526Sxy150489 /* 3223526Sxy150489 * Setup the Receive Control Register (RCTL), and ENABLE the 3233526Sxy150489 * receiver. The initial configuration is to: Enable the receiver, 3243526Sxy150489 * accept broadcasts, discard bad packets (and long packets), 3253526Sxy150489 * disable VLAN filter checking, set the receive descriptor 3263526Sxy150489 * minimum threshold size to 1/2, and the receive buffer size to 3273526Sxy150489 * 2k. 3283526Sxy150489 */ 3297607STed.You@Sun.COM rctl = E1000_RCTL_EN | /* Enable Receive Unit */ 3303526Sxy150489 E1000_RCTL_BAM | /* Accept Broadcast Packets */ 3313526Sxy150489 E1000_RCTL_LPE | /* Large Packet Enable bit */ 3324919Sxy150489 (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT) | 3333526Sxy150489 E1000_RCTL_RDMTS_HALF | 3343526Sxy150489 E1000_RCTL_LBM_NO; /* Loopback Mode = none */ 3353526Sxy150489 3364608Syy150190 if (Adapter->strip_crc) 3377607STed.You@Sun.COM rctl |= E1000_RCTL_SECRC; /* Strip Ethernet CRC */ 3384608Syy150190 339*8178SChenlu.Chen@Sun.COM if ((hw->mac.type == e1000_82545) || 340*8178SChenlu.Chen@Sun.COM (hw->mac.type == e1000_82546) || 341*8178SChenlu.Chen@Sun.COM (hw->mac.type == e1000_82546_rev_3)) { 3427607STed.You@Sun.COM rctl |= E1000_RCTL_SZ_2048; 343*8178SChenlu.Chen@Sun.COM } else { 344*8178SChenlu.Chen@Sun.COM if ((Adapter->max_frame_size > FRAME_SIZE_UPTO_2K) && 345*8178SChenlu.Chen@Sun.COM (Adapter->max_frame_size <= FRAME_SIZE_UPTO_4K)) 346*8178SChenlu.Chen@Sun.COM rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX; 347*8178SChenlu.Chen@Sun.COM else if ((Adapter->max_frame_size > FRAME_SIZE_UPTO_4K) && 348*8178SChenlu.Chen@Sun.COM (Adapter->max_frame_size <= FRAME_SIZE_UPTO_8K)) 349*8178SChenlu.Chen@Sun.COM rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX; 350*8178SChenlu.Chen@Sun.COM else if ((Adapter->max_frame_size > FRAME_SIZE_UPTO_8K) && 351*8178SChenlu.Chen@Sun.COM (Adapter->max_frame_size <= FRAME_SIZE_UPTO_16K)) 352*8178SChenlu.Chen@Sun.COM rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX; 353*8178SChenlu.Chen@Sun.COM else 354*8178SChenlu.Chen@Sun.COM rctl |= E1000_RCTL_SZ_2048; 355*8178SChenlu.Chen@Sun.COM } 3563526Sxy150489 3574919Sxy150489 if (e1000_tbi_sbp_enabled_82543(hw)) 3587607STed.You@Sun.COM rctl |= E1000_RCTL_SBP; 3593526Sxy150489 3604919Sxy150489 /* 3614919Sxy150489 * Enable early receives on supported devices, only takes effect when 3624919Sxy150489 * packet size is equal or larger than the specified value (in 8 byte 3634919Sxy150489 * units), e.g. using jumbo frames when setting to E1000_ERT_2048 3644919Sxy150489 */ 3657607STed.You@Sun.COM if ((hw->mac.type == e1000_82573) || 3667607STed.You@Sun.COM (hw->mac.type == e1000_82574) || 3677607STed.You@Sun.COM (hw->mac.type == e1000_ich9lan) || 3687607STed.You@Sun.COM (hw->mac.type == e1000_ich10lan)) { 3697607STed.You@Sun.COM 3707607STed.You@Sun.COM ert = E1000_ERT_2048; 3714919Sxy150489 3727607STed.You@Sun.COM /* 3737607STed.You@Sun.COM * Special modification when ERT and 3747607STed.You@Sun.COM * jumbo frames are enabled 3757607STed.You@Sun.COM */ 3767607STed.You@Sun.COM if (Adapter->default_mtu > ETHERMTU) { 3777607STed.You@Sun.COM rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0)); 3787607STed.You@Sun.COM E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl | 0x3); 3797607STed.You@Sun.COM ert |= (1 << 13); 3807607STed.You@Sun.COM } 3817607STed.You@Sun.COM 3827607STed.You@Sun.COM E1000_WRITE_REG(hw, E1000_ERT, ert); 3837607STed.You@Sun.COM } 3843526Sxy150489 3853526Sxy150489 reg_val = 3863526Sxy150489 E1000_RXCSUM_TUOFL | /* TCP/UDP checksum offload Enable */ 3873526Sxy150489 E1000_RXCSUM_IPOFL; /* IP checksum offload Enable */ 3883526Sxy150489 3894919Sxy150489 E1000_WRITE_REG(hw, E1000_RXCSUM, reg_val); 3906871Szx151633 3916871Szx151633 /* 3926871Szx151633 * Workaround: Set bit 16 (IPv6_ExDIS) to disable the 3936871Szx151633 * processing of received IPV6 extension headers 3946871Szx151633 */ 3956871Szx151633 if ((hw->mac.type == e1000_82571) || (hw->mac.type == e1000_82572)) { 3966871Szx151633 reg_val = E1000_READ_REG(hw, E1000_RFCTL); 3976871Szx151633 reg_val |= (E1000_RFCTL_IPV6_EX_DIS | 3986871Szx151633 E1000_RFCTL_NEW_IPV6_EXT_DIS); 3996871Szx151633 E1000_WRITE_REG(hw, E1000_RFCTL, reg_val); 4006871Szx151633 } 4017607STed.You@Sun.COM 4027607STed.You@Sun.COM /* Write to enable the receive unit */ 4037607STed.You@Sun.COM E1000_WRITE_REG(hw, E1000_RCTL, rctl); 4043526Sxy150489 } 4053526Sxy150489 4063526Sxy150489 /* 4074919Sxy150489 * e1000g_get_buf - get an rx sw packet from the free_list 4083526Sxy150489 */ 4094919Sxy150489 static p_rx_sw_packet_t 4103526Sxy150489 e1000g_get_buf(e1000g_rx_ring_t *rx_ring) 4113526Sxy150489 { 4124919Sxy150489 p_rx_sw_packet_t packet; 4133526Sxy150489 4143526Sxy150489 mutex_enter(&rx_ring->freelist_lock); 4154919Sxy150489 packet = (p_rx_sw_packet_t) 4163526Sxy150489 QUEUE_POP_HEAD(&rx_ring->free_list); 4173526Sxy150489 if (packet != NULL) 4184919Sxy150489 rx_ring->avail_freepkt--; 4193526Sxy150489 mutex_exit(&rx_ring->freelist_lock); 4203526Sxy150489 4213526Sxy150489 return (packet); 4223526Sxy150489 } 4233526Sxy150489 4243526Sxy150489 /* 4254919Sxy150489 * e1000g_receive - main receive routine 4264919Sxy150489 * 4274919Sxy150489 * This routine will process packets received in an interrupt 4283526Sxy150489 */ 4293526Sxy150489 mblk_t * 4303526Sxy150489 e1000g_receive(struct e1000g *Adapter) 4313526Sxy150489 { 4324919Sxy150489 struct e1000_hw *hw; 4333526Sxy150489 mblk_t *nmp; 4343526Sxy150489 mblk_t *ret_mp; 4353526Sxy150489 mblk_t *ret_nmp; 4363526Sxy150489 struct e1000_rx_desc *current_desc; 4373526Sxy150489 struct e1000_rx_desc *last_desc; 4384919Sxy150489 p_rx_sw_packet_t packet; 4394919Sxy150489 p_rx_sw_packet_t newpkt; 4407607STed.You@Sun.COM uint16_t length; 4413526Sxy150489 uint32_t pkt_count; 4423526Sxy150489 uint32_t desc_count; 4434919Sxy150489 boolean_t accept_frame; 4443526Sxy150489 boolean_t end_of_packet; 4453526Sxy150489 boolean_t need_copy; 4463526Sxy150489 e1000g_rx_ring_t *rx_ring; 4473526Sxy150489 dma_buffer_t *rx_buf; 4483526Sxy150489 uint16_t cksumflags; 4493526Sxy150489 4503526Sxy150489 ret_mp = NULL; 4513526Sxy150489 ret_nmp = NULL; 4523526Sxy150489 pkt_count = 0; 4533526Sxy150489 desc_count = 0; 4543526Sxy150489 cksumflags = 0; 4553526Sxy150489 4564919Sxy150489 hw = &Adapter->shared; 4573526Sxy150489 rx_ring = Adapter->rx_ring; 4583526Sxy150489 4593526Sxy150489 /* Sync the Rx descriptor DMA buffers */ 4603526Sxy150489 (void) ddi_dma_sync(rx_ring->rbd_dma_handle, 4614919Sxy150489 0, 0, DDI_DMA_SYNC_FORKERNEL); 4623526Sxy150489 4635273Sgl147354 if (e1000g_check_dma_handle(rx_ring->rbd_dma_handle) != DDI_FM_OK) { 4645273Sgl147354 ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED); 4655273Sgl147354 Adapter->chip_state = E1000G_ERROR; 4665273Sgl147354 } 4675273Sgl147354 4683526Sxy150489 current_desc = rx_ring->rbd_next; 4693526Sxy150489 if (!(current_desc->status & E1000_RXD_STAT_DD)) { 4703526Sxy150489 /* 4713526Sxy150489 * don't send anything up. just clear the RFD 4723526Sxy150489 */ 4734919Sxy150489 E1000G_DEBUG_STAT(rx_ring->stat_none); 4743526Sxy150489 return (ret_mp); 4753526Sxy150489 } 4763526Sxy150489 4773526Sxy150489 /* 4783526Sxy150489 * Loop through the receive descriptors starting at the last known 4793526Sxy150489 * descriptor owned by the hardware that begins a packet. 4803526Sxy150489 */ 4813526Sxy150489 while ((current_desc->status & E1000_RXD_STAT_DD) && 4824919Sxy150489 (pkt_count < Adapter->rx_limit_onintr)) { 4833526Sxy150489 4843526Sxy150489 desc_count++; 4853526Sxy150489 /* 4863526Sxy150489 * Now this can happen in Jumbo frame situation. 4873526Sxy150489 */ 4883526Sxy150489 if (current_desc->status & E1000_RXD_STAT_EOP) { 4893526Sxy150489 /* packet has EOP set */ 4903526Sxy150489 end_of_packet = B_TRUE; 4913526Sxy150489 } else { 4923526Sxy150489 /* 4933526Sxy150489 * If this received buffer does not have the 4943526Sxy150489 * End-Of-Packet bit set, the received packet 4953526Sxy150489 * will consume multiple buffers. We won't send this 4963526Sxy150489 * packet upstack till we get all the related buffers. 4973526Sxy150489 */ 4983526Sxy150489 end_of_packet = B_FALSE; 4993526Sxy150489 } 5003526Sxy150489 5013526Sxy150489 /* 5023526Sxy150489 * Get a pointer to the actual receive buffer 5033526Sxy150489 * The mp->b_rptr is mapped to The CurrentDescriptor 5043526Sxy150489 * Buffer Address. 5053526Sxy150489 */ 5063526Sxy150489 packet = 5074919Sxy150489 (p_rx_sw_packet_t)QUEUE_GET_HEAD(&rx_ring->recv_list); 5083526Sxy150489 ASSERT(packet != NULL); 5093526Sxy150489 5103526Sxy150489 rx_buf = packet->rx_buf; 5113526Sxy150489 5123526Sxy150489 length = current_desc->length; 5133526Sxy150489 5143526Sxy150489 #ifdef __sparc 5154919Sxy150489 if (packet->dma_type == USE_DVMA) 5163526Sxy150489 dvma_sync(rx_buf->dma_handle, 0, 5173526Sxy150489 DDI_DMA_SYNC_FORKERNEL); 5184919Sxy150489 else 5193526Sxy150489 (void) ddi_dma_sync(rx_buf->dma_handle, 5203526Sxy150489 E1000G_IPALIGNROOM, length, 5214919Sxy150489 DDI_DMA_SYNC_FORKERNEL); 5224919Sxy150489 #else 5234919Sxy150489 (void) ddi_dma_sync(rx_buf->dma_handle, 5244919Sxy150489 E1000G_IPALIGNROOM, length, 5254919Sxy150489 DDI_DMA_SYNC_FORKERNEL); 5264919Sxy150489 #endif 5274919Sxy150489 5285273Sgl147354 if (e1000g_check_dma_handle( 5295273Sgl147354 rx_buf->dma_handle) != DDI_FM_OK) { 5305273Sgl147354 ddi_fm_service_impact(Adapter->dip, 5315273Sgl147354 DDI_SERVICE_DEGRADED); 5325273Sgl147354 Adapter->chip_state = E1000G_ERROR; 5335273Sgl147354 } 5345273Sgl147354 5354919Sxy150489 accept_frame = (current_desc->errors == 0) || 5364919Sxy150489 ((current_desc->errors & 5374919Sxy150489 (E1000_RXD_ERR_TCPE | E1000_RXD_ERR_IPE)) != 0); 5384919Sxy150489 5394919Sxy150489 if (hw->mac.type == e1000_82543) { 5404919Sxy150489 unsigned char last_byte; 5414919Sxy150489 5424919Sxy150489 last_byte = 5434919Sxy150489 *((unsigned char *)rx_buf->address + length - 1); 5444919Sxy150489 5454919Sxy150489 if (TBI_ACCEPT(hw, 5464919Sxy150489 current_desc->status, current_desc->errors, 5476735Scc210113 current_desc->length, last_byte, 5486735Scc210113 Adapter->min_frame_size, Adapter->max_frame_size)) { 5494919Sxy150489 5504919Sxy150489 e1000_tbi_adjust_stats(Adapter, 5514919Sxy150489 length, hw->mac.addr); 5524919Sxy150489 5534919Sxy150489 length--; 5544919Sxy150489 accept_frame = B_TRUE; 5554919Sxy150489 } else if (e1000_tbi_sbp_enabled_82543(hw) && 5564919Sxy150489 (current_desc->errors == E1000_RXD_ERR_CE)) { 5574919Sxy150489 accept_frame = B_TRUE; 5584919Sxy150489 } 5593526Sxy150489 } 5603526Sxy150489 5613526Sxy150489 /* 5623526Sxy150489 * Indicate the packet to the NOS if it was good. 5633526Sxy150489 * Normally, hardware will discard bad packets for us. 5643526Sxy150489 * Check for the packet to be a valid Ethernet packet 5653526Sxy150489 */ 5664919Sxy150489 if (!accept_frame) { 5673526Sxy150489 /* 5683526Sxy150489 * error in incoming packet, either the packet is not a 5693526Sxy150489 * ethernet size packet, or the packet has an error. In 5703526Sxy150489 * either case, the packet will simply be discarded. 5713526Sxy150489 */ 5724919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL, 5733526Sxy150489 "Process Receive Interrupts: Error in Packet\n"); 5743526Sxy150489 5754919Sxy150489 E1000G_STAT(rx_ring->stat_error); 5763526Sxy150489 /* 5773526Sxy150489 * Returning here as we are done here. There is 5783526Sxy150489 * no point in waiting for while loop to elapse 5793526Sxy150489 * and the things which were done. More efficient 5803526Sxy150489 * and less error prone... 5813526Sxy150489 */ 5823526Sxy150489 goto rx_drop; 5833526Sxy150489 } 5843526Sxy150489 5854608Syy150190 /* 5864608Syy150190 * If the Ethernet CRC is not stripped by the hardware, 5874608Syy150190 * we need to strip it before sending it up to the stack. 5884608Syy150190 */ 5894608Syy150190 if (end_of_packet && !Adapter->strip_crc) { 5906394Scc210113 if (length > ETHERFCSL) { 5916394Scc210113 length -= ETHERFCSL; 5924608Syy150190 } else { 5934608Syy150190 /* 5944608Syy150190 * If the fragment is smaller than the CRC, 5954608Syy150190 * drop this fragment, do the processing of 5964608Syy150190 * the end of the packet. 5974608Syy150190 */ 5984919Sxy150489 ASSERT(rx_ring->rx_mblk_tail != NULL); 5994919Sxy150489 rx_ring->rx_mblk_tail->b_wptr -= 6006394Scc210113 ETHERFCSL - length; 6014919Sxy150489 rx_ring->rx_mblk_len -= 6026394Scc210113 ETHERFCSL - length; 6034608Syy150190 6044608Syy150190 QUEUE_POP_HEAD(&rx_ring->recv_list); 6054608Syy150190 6064608Syy150190 goto rx_end_of_packet; 6074608Syy150190 } 6084608Syy150190 } 6094608Syy150190 6103526Sxy150489 need_copy = B_TRUE; 6113526Sxy150489 6123526Sxy150489 if (length <= Adapter->rx_bcopy_thresh) 6133526Sxy150489 goto rx_copy; 6143526Sxy150489 6153526Sxy150489 /* 6163526Sxy150489 * Get the pre-constructed mblk that was associated 6173526Sxy150489 * to the receive data buffer. 6183526Sxy150489 */ 6193526Sxy150489 if (packet->mp == NULL) { 6203526Sxy150489 packet->mp = desballoc((unsigned char *) 6213526Sxy150489 rx_buf->address - E1000G_IPALIGNROOM, 6223526Sxy150489 length + E1000G_IPALIGNROOM, 6233526Sxy150489 BPRI_MED, &packet->free_rtn); 6243526Sxy150489 6253526Sxy150489 if (packet->mp != NULL) { 6263526Sxy150489 packet->mp->b_rptr += E1000G_IPALIGNROOM; 6273526Sxy150489 packet->mp->b_wptr += E1000G_IPALIGNROOM; 6283526Sxy150489 } else { 6294919Sxy150489 E1000G_STAT(rx_ring->stat_esballoc_fail); 6303526Sxy150489 } 6313526Sxy150489 } 6323526Sxy150489 6333526Sxy150489 if (packet->mp != NULL) { 6343526Sxy150489 /* 6353526Sxy150489 * We have two sets of buffer pool. One associated with 6363526Sxy150489 * the Rxdescriptors and other a freelist buffer pool. 6373526Sxy150489 * Each time we get a good packet, Try to get a buffer 6383526Sxy150489 * from the freelist pool using e1000g_get_buf. If we 6393526Sxy150489 * get free buffer, then replace the descriptor buffer 6403526Sxy150489 * address with the free buffer we just got, and pass 6413526Sxy150489 * the pre-constructed mblk upstack. (note no copying) 6423526Sxy150489 * 6433526Sxy150489 * If we failed to get a free buffer, then try to 6443526Sxy150489 * allocate a new buffer(mp) and copy the recv buffer 6453526Sxy150489 * content to our newly allocated buffer(mp). Don't 6463526Sxy150489 * disturb the desriptor buffer address. (note copying) 6473526Sxy150489 */ 6483526Sxy150489 newpkt = e1000g_get_buf(rx_ring); 6493526Sxy150489 6503526Sxy150489 if (newpkt != NULL) { 6513526Sxy150489 /* 6523526Sxy150489 * Get the mblk associated to the data, 6533526Sxy150489 * and strip it off the sw packet. 6543526Sxy150489 */ 6553526Sxy150489 nmp = packet->mp; 6563526Sxy150489 packet->mp = NULL; 6574982Syy150190 packet->flag = E1000G_RX_SW_SENDUP; 6583526Sxy150489 6593526Sxy150489 /* 6603526Sxy150489 * Now replace old buffer with the new 6613526Sxy150489 * one we got from free list 6623526Sxy150489 * Both the RxSwPacket as well as the 6633526Sxy150489 * Receive Buffer Descriptor will now 6643526Sxy150489 * point to this new packet. 6653526Sxy150489 */ 6663526Sxy150489 packet = newpkt; 6674919Sxy150489 6683526Sxy150489 current_desc->buffer_addr = 6693526Sxy150489 newpkt->rx_buf->dma_address; 6704919Sxy150489 6713526Sxy150489 need_copy = B_FALSE; 6723526Sxy150489 } else { 6734919Sxy150489 E1000G_DEBUG_STAT(rx_ring->stat_no_freepkt); 6743526Sxy150489 } 6753526Sxy150489 } 6763526Sxy150489 6773526Sxy150489 rx_copy: 6783526Sxy150489 if (need_copy) { 6793526Sxy150489 /* 6803526Sxy150489 * No buffers available on free list, 6813526Sxy150489 * bcopy the data from the buffer and 6823526Sxy150489 * keep the original buffer. Dont want to 6833526Sxy150489 * do this.. Yack but no other way 6843526Sxy150489 */ 6854919Sxy150489 if ((nmp = allocb(length + E1000G_IPALIGNROOM, 6864608Syy150190 BPRI_MED)) == NULL) { 6873526Sxy150489 /* 6883526Sxy150489 * The system has no buffers available 6893526Sxy150489 * to send up the incoming packet, hence 6903526Sxy150489 * the packet will have to be processed 6913526Sxy150489 * when there're more buffers available. 6923526Sxy150489 */ 6934919Sxy150489 E1000G_STAT(rx_ring->stat_allocb_fail); 6943526Sxy150489 goto rx_drop; 6953526Sxy150489 } 6963526Sxy150489 nmp->b_rptr += E1000G_IPALIGNROOM; 6973526Sxy150489 nmp->b_wptr += E1000G_IPALIGNROOM; 6983526Sxy150489 /* 6993526Sxy150489 * The free list did not have any buffers 7003526Sxy150489 * available, so, the received packet will 7013526Sxy150489 * have to be copied into a mp and the original 7023526Sxy150489 * buffer will have to be retained for future 7033526Sxy150489 * packet reception. 7043526Sxy150489 */ 7054919Sxy150489 bcopy(rx_buf->address, nmp->b_wptr, length); 7063526Sxy150489 } 7073526Sxy150489 7083526Sxy150489 /* 7094919Sxy150489 * The rx_sw_packet MUST be popped off the 7103526Sxy150489 * RxSwPacketList before either a putnext or freemsg 7113526Sxy150489 * is done on the mp that has now been created by the 7123526Sxy150489 * desballoc. If not, it is possible that the free 7133526Sxy150489 * routine will get called from the interrupt context 7143526Sxy150489 * and try to put this packet on the free list 7153526Sxy150489 */ 7164919Sxy150489 (p_rx_sw_packet_t)QUEUE_POP_HEAD(&rx_ring->recv_list); 7173526Sxy150489 7183526Sxy150489 ASSERT(nmp != NULL); 7193526Sxy150489 nmp->b_wptr += length; 7203526Sxy150489 7214919Sxy150489 if (rx_ring->rx_mblk == NULL) { 7223526Sxy150489 /* 7233526Sxy150489 * TCP/UDP checksum offload and 7243526Sxy150489 * IP checksum offload 7253526Sxy150489 */ 7264919Sxy150489 if (!(current_desc->status & E1000_RXD_STAT_IXSM)) { 7273526Sxy150489 /* 7283526Sxy150489 * Check TCP/UDP checksum 7293526Sxy150489 */ 7303526Sxy150489 if ((current_desc->status & 7314608Syy150190 E1000_RXD_STAT_TCPCS) && 7323526Sxy150489 !(current_desc->errors & 7334608Syy150190 E1000_RXD_ERR_TCPE)) 7343526Sxy150489 cksumflags |= HCK_FULLCKSUM | 7354608Syy150190 HCK_FULLCKSUM_OK; 7363526Sxy150489 /* 7373526Sxy150489 * Check IP Checksum 7383526Sxy150489 */ 7393526Sxy150489 if ((current_desc->status & 7404608Syy150190 E1000_RXD_STAT_IPCS) && 7413526Sxy150489 !(current_desc->errors & 7424608Syy150190 E1000_RXD_ERR_IPE)) 7433526Sxy150489 cksumflags |= HCK_IPV4_HDRCKSUM; 7443526Sxy150489 } 7453526Sxy150489 } 7463526Sxy150489 7473526Sxy150489 /* 7483526Sxy150489 * We need to maintain our packet chain in the global 7493526Sxy150489 * Adapter structure, for the Rx processing can end 7503526Sxy150489 * with a fragment that has no EOP set. 7513526Sxy150489 */ 7524919Sxy150489 if (rx_ring->rx_mblk == NULL) { 7533526Sxy150489 /* Get the head of the message chain */ 7544919Sxy150489 rx_ring->rx_mblk = nmp; 7554919Sxy150489 rx_ring->rx_mblk_tail = nmp; 7564919Sxy150489 rx_ring->rx_mblk_len = length; 7573526Sxy150489 } else { /* Not the first packet */ 7583526Sxy150489 /* Continue adding buffers */ 7594919Sxy150489 rx_ring->rx_mblk_tail->b_cont = nmp; 7604919Sxy150489 rx_ring->rx_mblk_tail = nmp; 7614919Sxy150489 rx_ring->rx_mblk_len += length; 7623526Sxy150489 } 7634919Sxy150489 ASSERT(rx_ring->rx_mblk != NULL); 7644919Sxy150489 ASSERT(rx_ring->rx_mblk_tail != NULL); 7654919Sxy150489 ASSERT(rx_ring->rx_mblk_tail->b_cont == NULL); 7663526Sxy150489 7673526Sxy150489 /* 7683526Sxy150489 * Now this MP is ready to travel upwards but some more 7693526Sxy150489 * fragments are coming. 7703526Sxy150489 * We will send packet upwards as soon as we get EOP 7713526Sxy150489 * set on the packet. 7723526Sxy150489 */ 7733526Sxy150489 if (!end_of_packet) { 7743526Sxy150489 /* 7753526Sxy150489 * continue to get the next descriptor, 7763526Sxy150489 * Tail would be advanced at the end 7773526Sxy150489 */ 7783526Sxy150489 goto rx_next_desc; 7793526Sxy150489 } 7803526Sxy150489 7814608Syy150190 rx_end_of_packet: 7823526Sxy150489 /* 7833526Sxy150489 * Found packet with EOP 7843526Sxy150489 * Process the last fragment. 7853526Sxy150489 */ 7863526Sxy150489 if (cksumflags != 0) { 7874919Sxy150489 (void) hcksum_assoc(rx_ring->rx_mblk, 7883526Sxy150489 NULL, NULL, 0, 0, 0, 0, cksumflags, 0); 7893526Sxy150489 cksumflags = 0; 7903526Sxy150489 } 7913526Sxy150489 7923526Sxy150489 /* 7933526Sxy150489 * Count packets that span multi-descriptors 7943526Sxy150489 */ 7954919Sxy150489 E1000G_DEBUG_STAT_COND(rx_ring->stat_multi_desc, 7964919Sxy150489 (rx_ring->rx_mblk->b_cont != NULL)); 7973526Sxy150489 7983526Sxy150489 /* 7993526Sxy150489 * Append to list to send upstream 8003526Sxy150489 */ 8013526Sxy150489 if (ret_mp == NULL) { 8024919Sxy150489 ret_mp = ret_nmp = rx_ring->rx_mblk; 8033526Sxy150489 } else { 8044919Sxy150489 ret_nmp->b_next = rx_ring->rx_mblk; 8054919Sxy150489 ret_nmp = rx_ring->rx_mblk; 8063526Sxy150489 } 8073526Sxy150489 ret_nmp->b_next = NULL; 8083526Sxy150489 8094919Sxy150489 rx_ring->rx_mblk = NULL; 8104919Sxy150489 rx_ring->rx_mblk_tail = NULL; 8114919Sxy150489 rx_ring->rx_mblk_len = 0; 8123526Sxy150489 8133526Sxy150489 pkt_count++; 8143526Sxy150489 8153526Sxy150489 rx_next_desc: 8163526Sxy150489 /* 8173526Sxy150489 * Zero out the receive descriptors status 8183526Sxy150489 */ 8193526Sxy150489 current_desc->status = 0; 8203526Sxy150489 8213526Sxy150489 if (current_desc == rx_ring->rbd_last) 8223526Sxy150489 rx_ring->rbd_next = rx_ring->rbd_first; 8233526Sxy150489 else 8243526Sxy150489 rx_ring->rbd_next++; 8253526Sxy150489 8263526Sxy150489 last_desc = current_desc; 8273526Sxy150489 current_desc = rx_ring->rbd_next; 8283526Sxy150489 8293526Sxy150489 /* 8303526Sxy150489 * Put the buffer that we just indicated back 8313526Sxy150489 * at the end of our list 8323526Sxy150489 */ 8333526Sxy150489 QUEUE_PUSH_TAIL(&rx_ring->recv_list, 8343526Sxy150489 &packet->Link); 8353526Sxy150489 } /* while loop */ 8363526Sxy150489 8373526Sxy150489 /* Sync the Rx descriptor DMA buffers */ 8384919Sxy150489 (void) ddi_dma_sync(rx_ring->rbd_dma_handle, 8394919Sxy150489 0, 0, DDI_DMA_SYNC_FORDEV); 8403526Sxy150489 8413526Sxy150489 /* 8423526Sxy150489 * Advance the E1000's Receive Queue #0 "Tail Pointer". 8433526Sxy150489 */ 8446735Scc210113 E1000_WRITE_REG(hw, E1000_RDT(0), 8453526Sxy150489 (uint32_t)(last_desc - rx_ring->rbd_first)); 8463526Sxy150489 8475273Sgl147354 if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK) { 8485273Sgl147354 ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED); 8495273Sgl147354 Adapter->chip_state = E1000G_ERROR; 8505273Sgl147354 } 8515273Sgl147354 8525882Syy150190 Adapter->rx_pkt_cnt = pkt_count; 8535882Syy150190 8543526Sxy150489 return (ret_mp); 8553526Sxy150489 8563526Sxy150489 rx_drop: 8573526Sxy150489 /* 8583526Sxy150489 * Zero out the receive descriptors status 8593526Sxy150489 */ 8603526Sxy150489 current_desc->status = 0; 8613526Sxy150489 8623526Sxy150489 /* Sync the Rx descriptor DMA buffers */ 8634919Sxy150489 (void) ddi_dma_sync(rx_ring->rbd_dma_handle, 8644919Sxy150489 0, 0, DDI_DMA_SYNC_FORDEV); 8653526Sxy150489 8663526Sxy150489 if (current_desc == rx_ring->rbd_last) 8673526Sxy150489 rx_ring->rbd_next = rx_ring->rbd_first; 8683526Sxy150489 else 8693526Sxy150489 rx_ring->rbd_next++; 8703526Sxy150489 8713526Sxy150489 last_desc = current_desc; 8723526Sxy150489 8734919Sxy150489 (p_rx_sw_packet_t)QUEUE_POP_HEAD(&rx_ring->recv_list); 8743526Sxy150489 8753526Sxy150489 QUEUE_PUSH_TAIL(&rx_ring->recv_list, &packet->Link); 8763526Sxy150489 /* 8773526Sxy150489 * Reclaim all old buffers already allocated during 8783526Sxy150489 * Jumbo receives.....for incomplete reception 8793526Sxy150489 */ 8804919Sxy150489 if (rx_ring->rx_mblk != NULL) { 8814919Sxy150489 freemsg(rx_ring->rx_mblk); 8824919Sxy150489 rx_ring->rx_mblk = NULL; 8834919Sxy150489 rx_ring->rx_mblk_tail = NULL; 8844919Sxy150489 rx_ring->rx_mblk_len = 0; 8853526Sxy150489 } 8863526Sxy150489 /* 8873526Sxy150489 * Advance the E1000's Receive Queue #0 "Tail Pointer". 8883526Sxy150489 */ 8896735Scc210113 E1000_WRITE_REG(hw, E1000_RDT(0), 8903526Sxy150489 (uint32_t)(last_desc - rx_ring->rbd_first)); 8913526Sxy150489 8925273Sgl147354 if (e1000g_check_acc_handle(Adapter->osdep.reg_handle) != DDI_FM_OK) { 8935273Sgl147354 ddi_fm_service_impact(Adapter->dip, DDI_SERVICE_DEGRADED); 8945273Sgl147354 Adapter->chip_state = E1000G_ERROR; 8955273Sgl147354 } 8965273Sgl147354 8973526Sxy150489 return (ret_mp); 8983526Sxy150489 } 899