108057504Sxy150489 /* 208057504Sxy150489 * This file is provided under a CDDLv1 license. When using or 308057504Sxy150489 * redistributing this file, you may do so under this license. 408057504Sxy150489 * In redistributing this file this license must be included 508057504Sxy150489 * and no other modification of this header file is permitted. 608057504Sxy150489 * 708057504Sxy150489 * CDDL LICENSE SUMMARY 808057504Sxy150489 * 954e0d7a5SMiles Xu, Sun Microsystems * Copyright(c) 1999 - 2009 Intel Corporation. All rights reserved. 1008057504Sxy150489 * 1108057504Sxy150489 * The contents of this file are subject to the terms of Version 1208057504Sxy150489 * 1.0 of the Common Development and Distribution License (the "License"). 1308057504Sxy150489 * 1408057504Sxy150489 * You should have received a copy of the License with this software. 1508057504Sxy150489 * You can obtain a copy of the License at 1608057504Sxy150489 * http://www.opensolaris.org/os/licensing. 1708057504Sxy150489 * See the License for the specific language governing permissions 1808057504Sxy150489 * and limitations under the License. 1908057504Sxy150489 */ 2008057504Sxy150489 2108057504Sxy150489 /* 223fb4efefSchangqing li - Sun Microsystems - Beijing China * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 2308057504Sxy150489 */ 2408057504Sxy150489 2508057504Sxy150489 /* 2608057504Sxy150489 * ********************************************************************** 2708057504Sxy150489 * Module Name: * 2825f2d433Sxy150489 * e1000g_alloc.c * 2908057504Sxy150489 * * 3008057504Sxy150489 * Abstract: * 3125f2d433Sxy150489 * This file contains some routines that take care of * 3225f2d433Sxy150489 * memory allocation for descriptors and buffers. * 3308057504Sxy150489 * * 3408057504Sxy150489 * ********************************************************************** 3508057504Sxy150489 */ 3608057504Sxy150489 3708057504Sxy150489 #include "e1000g_sw.h" 3808057504Sxy150489 #include "e1000g_debug.h" 3908057504Sxy150489 4008057504Sxy150489 #define TX_SW_PKT_AREA_SZ \ 4125f2d433Sxy150489 (sizeof (tx_sw_packet_t) * Adapter->tx_freelist_num) 4208057504Sxy150489 4308057504Sxy150489 static int e1000g_alloc_tx_descriptors(e1000g_tx_ring_t *); 4454e0d7a5SMiles Xu, Sun Microsystems static int e1000g_alloc_rx_descriptors(e1000g_rx_data_t *); 4508057504Sxy150489 static void e1000g_free_tx_descriptors(e1000g_tx_ring_t *); 4654e0d7a5SMiles Xu, Sun Microsystems static void e1000g_free_rx_descriptors(e1000g_rx_data_t *); 4708057504Sxy150489 static int e1000g_alloc_tx_packets(e1000g_tx_ring_t *); 4854e0d7a5SMiles Xu, Sun Microsystems static int e1000g_alloc_rx_packets(e1000g_rx_data_t *); 4908057504Sxy150489 static void e1000g_free_tx_packets(e1000g_tx_ring_t *); 503fb4efefSchangqing li - Sun Microsystems - Beijing China static void e1000g_free_rx_packets(e1000g_rx_data_t *, boolean_t); 5125f2d433Sxy150489 static int e1000g_alloc_dma_buffer(struct e1000g *, 5225f2d433Sxy150489 dma_buffer_t *, size_t, ddi_dma_attr_t *p_dma_attr); 53ede5269eSchenlu chen - Sun Microsystems - Beijing China 54ede5269eSchenlu chen - Sun Microsystems - Beijing China /* 55ede5269eSchenlu chen - Sun Microsystems - Beijing China * In order to avoid address error crossing 64KB boundary 56ede5269eSchenlu chen - Sun Microsystems - Beijing China * during PCI-X packets receving, e1000g_alloc_dma_buffer_82546 57ede5269eSchenlu chen - Sun Microsystems - Beijing China * is used by some necessary adapter types. 58ede5269eSchenlu chen - Sun Microsystems - Beijing China */ 59ede5269eSchenlu chen - Sun Microsystems - Beijing China static int e1000g_alloc_dma_buffer_82546(struct e1000g *, 60ede5269eSchenlu chen - Sun Microsystems - Beijing China dma_buffer_t *, size_t, ddi_dma_attr_t *p_dma_attr); 61ede5269eSchenlu chen - Sun Microsystems - Beijing China static int e1000g_dma_mem_alloc_82546(dma_buffer_t *buf, 62ede5269eSchenlu chen - Sun Microsystems - Beijing China size_t size, size_t *len); 63ede5269eSchenlu chen - Sun Microsystems - Beijing China static boolean_t e1000g_cross_64k_bound(void *, uintptr_t); 64ede5269eSchenlu chen - Sun Microsystems - Beijing China 6508057504Sxy150489 static void e1000g_free_dma_buffer(dma_buffer_t *); 6608057504Sxy150489 #ifdef __sparc 6708057504Sxy150489 static int e1000g_alloc_dvma_buffer(struct e1000g *, dma_buffer_t *, size_t); 6808057504Sxy150489 static void e1000g_free_dvma_buffer(dma_buffer_t *); 6908057504Sxy150489 #endif 7008057504Sxy150489 static int e1000g_alloc_descriptors(struct e1000g *Adapter); 7125f2d433Sxy150489 static void e1000g_free_descriptors(struct e1000g *Adapter); 7208057504Sxy150489 static int e1000g_alloc_packets(struct e1000g *Adapter); 7325f2d433Sxy150489 static void e1000g_free_packets(struct e1000g *Adapter); 7454e0d7a5SMiles Xu, Sun Microsystems static p_rx_sw_packet_t e1000g_alloc_rx_sw_packet(e1000g_rx_data_t *, 7525f2d433Sxy150489 ddi_dma_attr_t *p_dma_attr); 7625f2d433Sxy150489 7725f2d433Sxy150489 /* DMA access attributes for descriptors <Little Endian> */ 7825f2d433Sxy150489 static ddi_device_acc_attr_t e1000g_desc_acc_attr = { 7925f2d433Sxy150489 DDI_DEVICE_ATTR_V0, 8025f2d433Sxy150489 DDI_STRUCTURE_LE_ACC, 81837c1ac4SStephen Hanson DDI_STRICTORDER_ACC 8225f2d433Sxy150489 }; 8325f2d433Sxy150489 8425f2d433Sxy150489 /* DMA access attributes for DMA buffers */ 8525f2d433Sxy150489 #ifdef __sparc 8625f2d433Sxy150489 static ddi_device_acc_attr_t e1000g_buf_acc_attr = { 8725f2d433Sxy150489 DDI_DEVICE_ATTR_V0, 8825f2d433Sxy150489 DDI_STRUCTURE_BE_ACC, 8925f2d433Sxy150489 DDI_STRICTORDER_ACC, 9025f2d433Sxy150489 }; 9125f2d433Sxy150489 #else 9225f2d433Sxy150489 static ddi_device_acc_attr_t e1000g_buf_acc_attr = { 9325f2d433Sxy150489 DDI_DEVICE_ATTR_V0, 9425f2d433Sxy150489 DDI_STRUCTURE_LE_ACC, 9525f2d433Sxy150489 DDI_STRICTORDER_ACC, 9625f2d433Sxy150489 }; 9725f2d433Sxy150489 #endif 9825f2d433Sxy150489 9925f2d433Sxy150489 /* DMA attributes for tx mblk buffers */ 10025f2d433Sxy150489 static ddi_dma_attr_t e1000g_tx_dma_attr = { 10125f2d433Sxy150489 DMA_ATTR_V0, /* version of this structure */ 10225f2d433Sxy150489 0, /* lowest usable address */ 10325f2d433Sxy150489 0xffffffffffffffffULL, /* highest usable address */ 10425f2d433Sxy150489 0x7fffffff, /* maximum DMAable byte count */ 10525f2d433Sxy150489 1, /* alignment in bytes */ 10625f2d433Sxy150489 0x7ff, /* burst sizes (any?) */ 10725f2d433Sxy150489 1, /* minimum transfer */ 10825f2d433Sxy150489 0xffffffffU, /* maximum transfer */ 10925f2d433Sxy150489 0xffffffffffffffffULL, /* maximum segment length */ 1104d737963Sxiangtao you - Sun Microsystems - Beijing China MAX_COOKIES, /* maximum number of segments */ 11125f2d433Sxy150489 1, /* granularity */ 1129b6541b3Sgl147354 DDI_DMA_FLAGERR, /* dma_attr_flags */ 11325f2d433Sxy150489 }; 11425f2d433Sxy150489 11525f2d433Sxy150489 /* DMA attributes for pre-allocated rx/tx buffers */ 11625f2d433Sxy150489 static ddi_dma_attr_t e1000g_buf_dma_attr = { 11725f2d433Sxy150489 DMA_ATTR_V0, /* version of this structure */ 11825f2d433Sxy150489 0, /* lowest usable address */ 11925f2d433Sxy150489 0xffffffffffffffffULL, /* highest usable address */ 12025f2d433Sxy150489 0x7fffffff, /* maximum DMAable byte count */ 12125f2d433Sxy150489 1, /* alignment in bytes */ 12225f2d433Sxy150489 0x7ff, /* burst sizes (any?) */ 12325f2d433Sxy150489 1, /* minimum transfer */ 12425f2d433Sxy150489 0xffffffffU, /* maximum transfer */ 12525f2d433Sxy150489 0xffffffffffffffffULL, /* maximum segment length */ 12625f2d433Sxy150489 1, /* maximum number of segments */ 12725f2d433Sxy150489 1, /* granularity */ 1289b6541b3Sgl147354 DDI_DMA_FLAGERR, /* dma_attr_flags */ 12925f2d433Sxy150489 }; 13025f2d433Sxy150489 13125f2d433Sxy150489 /* DMA attributes for rx/tx descriptors */ 13225f2d433Sxy150489 static ddi_dma_attr_t e1000g_desc_dma_attr = { 13325f2d433Sxy150489 DMA_ATTR_V0, /* version of this structure */ 13425f2d433Sxy150489 0, /* lowest usable address */ 13525f2d433Sxy150489 0xffffffffffffffffULL, /* highest usable address */ 13625f2d433Sxy150489 0x7fffffff, /* maximum DMAable byte count */ 137ede5269eSchenlu chen - Sun Microsystems - Beijing China E1000_MDALIGN, /* default alignment is 4k but can be changed */ 13825f2d433Sxy150489 0x7ff, /* burst sizes (any?) */ 13925f2d433Sxy150489 1, /* minimum transfer */ 14025f2d433Sxy150489 0xffffffffU, /* maximum transfer */ 14125f2d433Sxy150489 0xffffffffffffffffULL, /* maximum segment length */ 14225f2d433Sxy150489 1, /* maximum number of segments */ 14325f2d433Sxy150489 1, /* granularity */ 1449b6541b3Sgl147354 DDI_DMA_FLAGERR, /* dma_attr_flags */ 14525f2d433Sxy150489 }; 14608057504Sxy150489 14708057504Sxy150489 #ifdef __sparc 14808057504Sxy150489 static ddi_dma_lim_t e1000g_dma_limits = { 14908057504Sxy150489 (uint_t)0, /* dlim_addr_lo */ 15008057504Sxy150489 (uint_t)0xffffffff, /* dlim_addr_hi */ 15108057504Sxy150489 (uint_t)0xffffffff, /* dlim_cntr_max */ 15208057504Sxy150489 (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 15308057504Sxy150489 0x1, /* dlim_minxfer */ 15408057504Sxy150489 1024 /* dlim_speed */ 15508057504Sxy150489 }; 15608057504Sxy150489 #endif 15708057504Sxy150489 15808057504Sxy150489 #ifdef __sparc 15908057504Sxy150489 static dma_type_t e1000g_dma_type = USE_DVMA; 16008057504Sxy150489 #else 16108057504Sxy150489 static dma_type_t e1000g_dma_type = USE_DMA; 16208057504Sxy150489 #endif 16308057504Sxy150489 16408057504Sxy150489 extern krwlock_t e1000g_dma_type_lock; 16508057504Sxy150489 16625f2d433Sxy150489 16708057504Sxy150489 int 16808057504Sxy150489 e1000g_alloc_dma_resources(struct e1000g *Adapter) 16908057504Sxy150489 { 17025f2d433Sxy150489 int result; 17108057504Sxy150489 17225f2d433Sxy150489 result = DDI_FAILURE; 17308057504Sxy150489 17425f2d433Sxy150489 while ((result != DDI_SUCCESS) && 17525f2d433Sxy150489 (Adapter->tx_desc_num >= MIN_NUM_TX_DESCRIPTOR) && 17625f2d433Sxy150489 (Adapter->rx_desc_num >= MIN_NUM_RX_DESCRIPTOR) && 1773fb4efefSchangqing li - Sun Microsystems - Beijing China (Adapter->tx_freelist_num >= MIN_NUM_TX_FREELIST)) { 17808057504Sxy150489 17925f2d433Sxy150489 result = e1000g_alloc_descriptors(Adapter); 18008057504Sxy150489 18125f2d433Sxy150489 if (result == DDI_SUCCESS) { 18225f2d433Sxy150489 result = e1000g_alloc_packets(Adapter); 18325f2d433Sxy150489 18425f2d433Sxy150489 if (result != DDI_SUCCESS) 18525f2d433Sxy150489 e1000g_free_descriptors(Adapter); 18608057504Sxy150489 } 18708057504Sxy150489 18808057504Sxy150489 /* 18925f2d433Sxy150489 * If the allocation fails due to resource shortage, 19025f2d433Sxy150489 * we'll reduce the numbers of descriptors/buffers by 19125f2d433Sxy150489 * half, and try the allocation again. 19225f2d433Sxy150489 */ 19325f2d433Sxy150489 if (result != DDI_SUCCESS) { 19425f2d433Sxy150489 /* 19525f2d433Sxy150489 * We must ensure the number of descriptors 19625f2d433Sxy150489 * is always a multiple of 8. 19725f2d433Sxy150489 */ 19825f2d433Sxy150489 Adapter->tx_desc_num = 19925f2d433Sxy150489 (Adapter->tx_desc_num >> 4) << 3; 20025f2d433Sxy150489 Adapter->rx_desc_num = 20125f2d433Sxy150489 (Adapter->rx_desc_num >> 4) << 3; 20225f2d433Sxy150489 20325f2d433Sxy150489 Adapter->tx_freelist_num >>= 1; 20425f2d433Sxy150489 } 20525f2d433Sxy150489 } 20625f2d433Sxy150489 20725f2d433Sxy150489 return (result); 20825f2d433Sxy150489 } 20925f2d433Sxy150489 21025f2d433Sxy150489 /* 21125f2d433Sxy150489 * e1000g_alloc_descriptors - allocate DMA buffers for descriptors 21225f2d433Sxy150489 * 21325f2d433Sxy150489 * This routine allocates neccesary DMA buffers for 21425f2d433Sxy150489 * Transmit Descriptor Area 21525f2d433Sxy150489 * Receive Descrpitor Area 21608057504Sxy150489 */ 21708057504Sxy150489 static int 21808057504Sxy150489 e1000g_alloc_descriptors(struct e1000g *Adapter) 21908057504Sxy150489 { 22008057504Sxy150489 int result; 22108057504Sxy150489 e1000g_tx_ring_t *tx_ring; 22254e0d7a5SMiles Xu, Sun Microsystems e1000g_rx_data_t *rx_data; 22308057504Sxy150489 2243d15c084Schenlu chen - Sun Microsystems - Beijing China if (Adapter->mem_workaround_82546 && 2253d15c084Schenlu chen - Sun Microsystems - Beijing China ((Adapter->shared.mac.type == e1000_82545) || 226ede5269eSchenlu chen - Sun Microsystems - Beijing China (Adapter->shared.mac.type == e1000_82546) || 2273d15c084Schenlu chen - Sun Microsystems - Beijing China (Adapter->shared.mac.type == e1000_82546_rev_3))) { 228ede5269eSchenlu chen - Sun Microsystems - Beijing China /* Align on a 64k boundary for these adapter types */ 229ede5269eSchenlu chen - Sun Microsystems - Beijing China Adapter->desc_align = E1000_MDALIGN_82546; 230ede5269eSchenlu chen - Sun Microsystems - Beijing China } else { 231ede5269eSchenlu chen - Sun Microsystems - Beijing China /* Align on a 4k boundary for all other adapter types */ 232ede5269eSchenlu chen - Sun Microsystems - Beijing China Adapter->desc_align = E1000_MDALIGN; 233ede5269eSchenlu chen - Sun Microsystems - Beijing China } 234ede5269eSchenlu chen - Sun Microsystems - Beijing China 23508057504Sxy150489 tx_ring = Adapter->tx_ring; 23608057504Sxy150489 23708057504Sxy150489 result = e1000g_alloc_tx_descriptors(tx_ring); 23808057504Sxy150489 if (result != DDI_SUCCESS) 23908057504Sxy150489 return (DDI_FAILURE); 24008057504Sxy150489 24154e0d7a5SMiles Xu, Sun Microsystems rx_data = Adapter->rx_ring->rx_data; 24208057504Sxy150489 24354e0d7a5SMiles Xu, Sun Microsystems result = e1000g_alloc_rx_descriptors(rx_data); 24408057504Sxy150489 if (result != DDI_SUCCESS) { 24508057504Sxy150489 e1000g_free_tx_descriptors(tx_ring); 24608057504Sxy150489 return (DDI_FAILURE); 24708057504Sxy150489 } 24808057504Sxy150489 24908057504Sxy150489 return (DDI_SUCCESS); 25008057504Sxy150489 } 25108057504Sxy150489 25225f2d433Sxy150489 static void 25325f2d433Sxy150489 e1000g_free_descriptors(struct e1000g *Adapter) 25425f2d433Sxy150489 { 25525f2d433Sxy150489 e1000g_tx_ring_t *tx_ring; 25654e0d7a5SMiles Xu, Sun Microsystems e1000g_rx_data_t *rx_data; 25725f2d433Sxy150489 25825f2d433Sxy150489 tx_ring = Adapter->tx_ring; 25954e0d7a5SMiles Xu, Sun Microsystems rx_data = Adapter->rx_ring->rx_data; 26025f2d433Sxy150489 26125f2d433Sxy150489 e1000g_free_tx_descriptors(tx_ring); 26254e0d7a5SMiles Xu, Sun Microsystems e1000g_free_rx_descriptors(rx_data); 26325f2d433Sxy150489 } 26425f2d433Sxy150489 26508057504Sxy150489 static int 26608057504Sxy150489 e1000g_alloc_tx_descriptors(e1000g_tx_ring_t *tx_ring) 26708057504Sxy150489 { 26808057504Sxy150489 int mystat; 26908057504Sxy150489 boolean_t alloc_flag; 27008057504Sxy150489 size_t size; 27108057504Sxy150489 size_t len; 27208057504Sxy150489 uintptr_t templong; 27308057504Sxy150489 uint_t cookie_count; 27408057504Sxy150489 dev_info_t *devinfo; 27508057504Sxy150489 ddi_dma_cookie_t cookie; 27608057504Sxy150489 struct e1000g *Adapter; 27725f2d433Sxy150489 ddi_dma_attr_t dma_attr; 27808057504Sxy150489 27908057504Sxy150489 Adapter = tx_ring->adapter; 28025f2d433Sxy150489 devinfo = Adapter->dip; 28108057504Sxy150489 28208057504Sxy150489 alloc_flag = B_FALSE; 28325f2d433Sxy150489 dma_attr = e1000g_desc_dma_attr; 28408057504Sxy150489 28508057504Sxy150489 /* 28608057504Sxy150489 * Solaris 7 has a problem with allocating physically contiguous memory 28708057504Sxy150489 * that is aligned on a 4K boundary. The transmit and rx descriptors 28808057504Sxy150489 * need to aligned on a 4kbyte boundary. We first try to allocate the 28908057504Sxy150489 * memory with DMA attributes set to 4K alignment and also no scatter/ 29008057504Sxy150489 * gather mechanism specified. In most cases, this does not allocate 29108057504Sxy150489 * memory aligned at a 4Kbyte boundary. We then try asking for memory 29208057504Sxy150489 * aligned on 4K boundary with scatter/gather set to 2. This works when 29308057504Sxy150489 * the amount of memory is less than 4k i.e a page size. If neither of 29408057504Sxy150489 * these options work or if the number of descriptors is greater than 29508057504Sxy150489 * 4K, ie more than 256 descriptors, we allocate 4k extra memory and 29608057504Sxy150489 * and then align the memory at a 4k boundary. 29708057504Sxy150489 */ 29825f2d433Sxy150489 size = sizeof (struct e1000_tx_desc) * Adapter->tx_desc_num; 29908057504Sxy150489 30008057504Sxy150489 /* 30108057504Sxy150489 * Memory allocation for the transmit buffer descriptors. 30208057504Sxy150489 */ 30325f2d433Sxy150489 dma_attr.dma_attr_sgllen = 1; 304ede5269eSchenlu chen - Sun Microsystems - Beijing China dma_attr.dma_attr_align = Adapter->desc_align; 30508057504Sxy150489 30608057504Sxy150489 /* 30708057504Sxy150489 * Allocate a new DMA handle for the transmit descriptor 30808057504Sxy150489 * memory area. 30908057504Sxy150489 */ 31025f2d433Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, &dma_attr, 31108057504Sxy150489 DDI_DMA_DONTWAIT, 0, 31208057504Sxy150489 &tx_ring->tbd_dma_handle); 31308057504Sxy150489 31408057504Sxy150489 if (mystat != DDI_SUCCESS) { 31525f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 31608057504Sxy150489 "Could not allocate tbd dma handle: %d", mystat); 31708057504Sxy150489 tx_ring->tbd_dma_handle = NULL; 31808057504Sxy150489 return (DDI_FAILURE); 31908057504Sxy150489 } 32008057504Sxy150489 32108057504Sxy150489 /* 32208057504Sxy150489 * Allocate memory to DMA data to and from the transmit 32308057504Sxy150489 * descriptors. 32408057504Sxy150489 */ 32508057504Sxy150489 mystat = ddi_dma_mem_alloc(tx_ring->tbd_dma_handle, 32608057504Sxy150489 size, 32725f2d433Sxy150489 &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT, 32808057504Sxy150489 DDI_DMA_DONTWAIT, 0, 32908057504Sxy150489 (caddr_t *)&tx_ring->tbd_area, 33008057504Sxy150489 &len, &tx_ring->tbd_acc_handle); 33108057504Sxy150489 33208057504Sxy150489 if ((mystat != DDI_SUCCESS) || 333ede5269eSchenlu chen - Sun Microsystems - Beijing China ((uintptr_t)tx_ring->tbd_area & (Adapter->desc_align - 1))) { 33408057504Sxy150489 if (mystat == DDI_SUCCESS) { 33508057504Sxy150489 ddi_dma_mem_free(&tx_ring->tbd_acc_handle); 33608057504Sxy150489 tx_ring->tbd_acc_handle = NULL; 33708057504Sxy150489 tx_ring->tbd_area = NULL; 33808057504Sxy150489 } 33908057504Sxy150489 if (tx_ring->tbd_dma_handle != NULL) { 34008057504Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_dma_handle); 34108057504Sxy150489 tx_ring->tbd_dma_handle = NULL; 34208057504Sxy150489 } 34308057504Sxy150489 alloc_flag = B_FALSE; 34408057504Sxy150489 } else 34508057504Sxy150489 alloc_flag = B_TRUE; 34608057504Sxy150489 34708057504Sxy150489 /* 34808057504Sxy150489 * Initialize the entire transmit buffer descriptor area to zero 34908057504Sxy150489 */ 35008057504Sxy150489 if (alloc_flag) 35108057504Sxy150489 bzero(tx_ring->tbd_area, len); 35208057504Sxy150489 35308057504Sxy150489 /* 35408057504Sxy150489 * If the previous DMA attributes setting could not give us contiguous 35508057504Sxy150489 * memory or the number of descriptors is greater than the page size, 356ede5269eSchenlu chen - Sun Microsystems - Beijing China * we allocate extra memory and then align it at appropriate boundary. 35708057504Sxy150489 */ 35808057504Sxy150489 if (!alloc_flag) { 359ede5269eSchenlu chen - Sun Microsystems - Beijing China size = size + Adapter->desc_align; 36008057504Sxy150489 36108057504Sxy150489 /* 36208057504Sxy150489 * DMA attributes set to no scatter/gather and 16 bit alignment 36308057504Sxy150489 */ 36425f2d433Sxy150489 dma_attr.dma_attr_align = 1; 36525f2d433Sxy150489 dma_attr.dma_attr_sgllen = 1; 36608057504Sxy150489 36708057504Sxy150489 /* 36808057504Sxy150489 * Allocate a new DMA handle for the transmit descriptor memory 36908057504Sxy150489 * area. 37008057504Sxy150489 */ 37125f2d433Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, &dma_attr, 37208057504Sxy150489 DDI_DMA_DONTWAIT, 0, 37308057504Sxy150489 &tx_ring->tbd_dma_handle); 37408057504Sxy150489 37508057504Sxy150489 if (mystat != DDI_SUCCESS) { 37625f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 37708057504Sxy150489 "Could not re-allocate tbd dma handle: %d", mystat); 37808057504Sxy150489 tx_ring->tbd_dma_handle = NULL; 37908057504Sxy150489 return (DDI_FAILURE); 38008057504Sxy150489 } 38108057504Sxy150489 38208057504Sxy150489 /* 38308057504Sxy150489 * Allocate memory to DMA data to and from the transmit 38408057504Sxy150489 * descriptors. 38508057504Sxy150489 */ 38608057504Sxy150489 mystat = ddi_dma_mem_alloc(tx_ring->tbd_dma_handle, 38708057504Sxy150489 size, 38825f2d433Sxy150489 &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT, 38908057504Sxy150489 DDI_DMA_DONTWAIT, 0, 39008057504Sxy150489 (caddr_t *)&tx_ring->tbd_area, 39108057504Sxy150489 &len, &tx_ring->tbd_acc_handle); 39208057504Sxy150489 39308057504Sxy150489 if (mystat != DDI_SUCCESS) { 39425f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 39508057504Sxy150489 "Could not allocate tbd dma memory: %d", mystat); 39608057504Sxy150489 tx_ring->tbd_acc_handle = NULL; 39708057504Sxy150489 tx_ring->tbd_area = NULL; 39808057504Sxy150489 if (tx_ring->tbd_dma_handle != NULL) { 39908057504Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_dma_handle); 40008057504Sxy150489 tx_ring->tbd_dma_handle = NULL; 40108057504Sxy150489 } 40208057504Sxy150489 return (DDI_FAILURE); 40308057504Sxy150489 } else 40408057504Sxy150489 alloc_flag = B_TRUE; 40508057504Sxy150489 40608057504Sxy150489 /* 40708057504Sxy150489 * Initialize the entire transmit buffer descriptor area to zero 40808057504Sxy150489 */ 40908057504Sxy150489 bzero(tx_ring->tbd_area, len); 41008057504Sxy150489 /* 41108057504Sxy150489 * Memory has been allocated with the ddi_dma_mem_alloc call, 412ede5269eSchenlu chen - Sun Microsystems - Beijing China * but has not been aligned. 413ede5269eSchenlu chen - Sun Microsystems - Beijing China * We now align it on the appropriate boundary. 41408057504Sxy150489 */ 415ede5269eSchenlu chen - Sun Microsystems - Beijing China templong = P2NPHASE((uintptr_t)tx_ring->tbd_area, 416ede5269eSchenlu chen - Sun Microsystems - Beijing China Adapter->desc_align); 41708057504Sxy150489 len = size - templong; 41808057504Sxy150489 templong += (uintptr_t)tx_ring->tbd_area; 41908057504Sxy150489 tx_ring->tbd_area = (struct e1000_tx_desc *)templong; 42008057504Sxy150489 } /* alignment workaround */ 42108057504Sxy150489 42208057504Sxy150489 /* 42308057504Sxy150489 * Transmit buffer descriptor memory allocation succeeded 42408057504Sxy150489 */ 42508057504Sxy150489 ASSERT(alloc_flag); 42608057504Sxy150489 42708057504Sxy150489 /* 42808057504Sxy150489 * Allocates DMA resources for the memory that was allocated by 42908057504Sxy150489 * the ddi_dma_mem_alloc call. The DMA resources then get bound to the 43008057504Sxy150489 * the memory address 43108057504Sxy150489 */ 43208057504Sxy150489 mystat = ddi_dma_addr_bind_handle(tx_ring->tbd_dma_handle, 43308057504Sxy150489 (struct as *)NULL, (caddr_t)tx_ring->tbd_area, 43408057504Sxy150489 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 43525f2d433Sxy150489 DDI_DMA_DONTWAIT, 0, &cookie, &cookie_count); 43608057504Sxy150489 43708057504Sxy150489 if (mystat != DDI_SUCCESS) { 43825f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 43908057504Sxy150489 "Could not bind tbd dma resource: %d", mystat); 44008057504Sxy150489 if (tx_ring->tbd_acc_handle != NULL) { 44108057504Sxy150489 ddi_dma_mem_free(&tx_ring->tbd_acc_handle); 44208057504Sxy150489 tx_ring->tbd_acc_handle = NULL; 44308057504Sxy150489 tx_ring->tbd_area = NULL; 44408057504Sxy150489 } 44508057504Sxy150489 if (tx_ring->tbd_dma_handle != NULL) { 44608057504Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_dma_handle); 44708057504Sxy150489 tx_ring->tbd_dma_handle = NULL; 44808057504Sxy150489 } 44908057504Sxy150489 return (DDI_FAILURE); 45008057504Sxy150489 } 45108057504Sxy150489 45208057504Sxy150489 ASSERT(cookie_count == 1); /* 1 cookie */ 45308057504Sxy150489 45408057504Sxy150489 if (cookie_count != 1) { 45525f2d433Sxy150489 E1000G_DEBUGLOG_2(Adapter, E1000G_WARN_LEVEL, 45608057504Sxy150489 "Could not bind tbd dma resource in a single frag. " 45708057504Sxy150489 "Count - %d Len - %d", cookie_count, len); 45808057504Sxy150489 e1000g_free_tx_descriptors(tx_ring); 45908057504Sxy150489 return (DDI_FAILURE); 46008057504Sxy150489 } 46108057504Sxy150489 46208057504Sxy150489 tx_ring->tbd_dma_addr = cookie.dmac_laddress; 46308057504Sxy150489 tx_ring->tbd_first = tx_ring->tbd_area; 46408057504Sxy150489 tx_ring->tbd_last = tx_ring->tbd_first + 46525f2d433Sxy150489 (Adapter->tx_desc_num - 1); 46608057504Sxy150489 46708057504Sxy150489 return (DDI_SUCCESS); 46808057504Sxy150489 } 46908057504Sxy150489 47008057504Sxy150489 static int 47154e0d7a5SMiles Xu, Sun Microsystems e1000g_alloc_rx_descriptors(e1000g_rx_data_t *rx_data) 47208057504Sxy150489 { 47308057504Sxy150489 int mystat; 47408057504Sxy150489 boolean_t alloc_flag; 47508057504Sxy150489 size_t size; 47608057504Sxy150489 size_t len; 47708057504Sxy150489 uintptr_t templong; 47808057504Sxy150489 uint_t cookie_count; 47908057504Sxy150489 dev_info_t *devinfo; 48008057504Sxy150489 ddi_dma_cookie_t cookie; 48108057504Sxy150489 struct e1000g *Adapter; 48225f2d433Sxy150489 ddi_dma_attr_t dma_attr; 48308057504Sxy150489 48454e0d7a5SMiles Xu, Sun Microsystems Adapter = rx_data->rx_ring->adapter; 48525f2d433Sxy150489 devinfo = Adapter->dip; 48608057504Sxy150489 48708057504Sxy150489 alloc_flag = B_FALSE; 48825f2d433Sxy150489 dma_attr = e1000g_desc_dma_attr; 48908057504Sxy150489 49008057504Sxy150489 /* 49108057504Sxy150489 * Memory allocation for the receive buffer descriptors. 49208057504Sxy150489 */ 49325f2d433Sxy150489 size = (sizeof (struct e1000_rx_desc)) * Adapter->rx_desc_num; 49408057504Sxy150489 49508057504Sxy150489 /* 496ede5269eSchenlu chen - Sun Microsystems - Beijing China * Asking for aligned memory with DMA attributes set for suitable value 49708057504Sxy150489 */ 49825f2d433Sxy150489 dma_attr.dma_attr_sgllen = 1; 499ede5269eSchenlu chen - Sun Microsystems - Beijing China dma_attr.dma_attr_align = Adapter->desc_align; 50008057504Sxy150489 50108057504Sxy150489 /* 50225f2d433Sxy150489 * Allocate a new DMA handle for the receive descriptors 50308057504Sxy150489 */ 50425f2d433Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, &dma_attr, 50508057504Sxy150489 DDI_DMA_DONTWAIT, 0, 50654e0d7a5SMiles Xu, Sun Microsystems &rx_data->rbd_dma_handle); 50708057504Sxy150489 50808057504Sxy150489 if (mystat != DDI_SUCCESS) { 50925f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 51008057504Sxy150489 "Could not allocate rbd dma handle: %d", mystat); 51154e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_dma_handle = NULL; 51208057504Sxy150489 return (DDI_FAILURE); 51308057504Sxy150489 } 51408057504Sxy150489 /* 51508057504Sxy150489 * Allocate memory to DMA data to and from the receive 51608057504Sxy150489 * descriptors. 51708057504Sxy150489 */ 51854e0d7a5SMiles Xu, Sun Microsystems mystat = ddi_dma_mem_alloc(rx_data->rbd_dma_handle, 51908057504Sxy150489 size, 52025f2d433Sxy150489 &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT, 52108057504Sxy150489 DDI_DMA_DONTWAIT, 0, 52254e0d7a5SMiles Xu, Sun Microsystems (caddr_t *)&rx_data->rbd_area, 52354e0d7a5SMiles Xu, Sun Microsystems &len, &rx_data->rbd_acc_handle); 52408057504Sxy150489 52508057504Sxy150489 /* 52608057504Sxy150489 * Check if memory allocation succeeded and also if the 52708057504Sxy150489 * allocated memory is aligned correctly. 52808057504Sxy150489 */ 52908057504Sxy150489 if ((mystat != DDI_SUCCESS) || 53054e0d7a5SMiles Xu, Sun Microsystems ((uintptr_t)rx_data->rbd_area & (Adapter->desc_align - 1))) { 53108057504Sxy150489 if (mystat == DDI_SUCCESS) { 53254e0d7a5SMiles Xu, Sun Microsystems ddi_dma_mem_free(&rx_data->rbd_acc_handle); 53354e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_acc_handle = NULL; 53454e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_area = NULL; 53508057504Sxy150489 } 53654e0d7a5SMiles Xu, Sun Microsystems if (rx_data->rbd_dma_handle != NULL) { 53754e0d7a5SMiles Xu, Sun Microsystems ddi_dma_free_handle(&rx_data->rbd_dma_handle); 53854e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_dma_handle = NULL; 53908057504Sxy150489 } 54008057504Sxy150489 alloc_flag = B_FALSE; 54108057504Sxy150489 } else 54208057504Sxy150489 alloc_flag = B_TRUE; 54308057504Sxy150489 54408057504Sxy150489 /* 54508057504Sxy150489 * Initialize the allocated receive descriptor memory to zero. 54608057504Sxy150489 */ 54708057504Sxy150489 if (alloc_flag) 54854e0d7a5SMiles Xu, Sun Microsystems bzero((caddr_t)rx_data->rbd_area, len); 54908057504Sxy150489 55008057504Sxy150489 /* 55125f2d433Sxy150489 * If memory allocation did not succeed, do the alignment ourselves 55208057504Sxy150489 */ 55308057504Sxy150489 if (!alloc_flag) { 55425f2d433Sxy150489 dma_attr.dma_attr_align = 1; 55525f2d433Sxy150489 dma_attr.dma_attr_sgllen = 1; 556ede5269eSchenlu chen - Sun Microsystems - Beijing China size = size + Adapter->desc_align; 55708057504Sxy150489 /* 55825f2d433Sxy150489 * Allocate a new DMA handle for the receive descriptor. 55908057504Sxy150489 */ 56025f2d433Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, &dma_attr, 56108057504Sxy150489 DDI_DMA_DONTWAIT, 0, 56254e0d7a5SMiles Xu, Sun Microsystems &rx_data->rbd_dma_handle); 56308057504Sxy150489 56408057504Sxy150489 if (mystat != DDI_SUCCESS) { 56525f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 56608057504Sxy150489 "Could not re-allocate rbd dma handle: %d", mystat); 56754e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_dma_handle = NULL; 56808057504Sxy150489 return (DDI_FAILURE); 56908057504Sxy150489 } 57008057504Sxy150489 /* 57108057504Sxy150489 * Allocate memory to DMA data to and from the receive 57208057504Sxy150489 * descriptors. 57308057504Sxy150489 */ 57454e0d7a5SMiles Xu, Sun Microsystems mystat = ddi_dma_mem_alloc(rx_data->rbd_dma_handle, 57508057504Sxy150489 size, 57625f2d433Sxy150489 &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT, 57708057504Sxy150489 DDI_DMA_DONTWAIT, 0, 57854e0d7a5SMiles Xu, Sun Microsystems (caddr_t *)&rx_data->rbd_area, 57954e0d7a5SMiles Xu, Sun Microsystems &len, &rx_data->rbd_acc_handle); 58008057504Sxy150489 58108057504Sxy150489 if (mystat != DDI_SUCCESS) { 58225f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 58308057504Sxy150489 "Could not allocate rbd dma memory: %d", mystat); 58454e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_acc_handle = NULL; 58554e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_area = NULL; 58654e0d7a5SMiles Xu, Sun Microsystems if (rx_data->rbd_dma_handle != NULL) { 58754e0d7a5SMiles Xu, Sun Microsystems ddi_dma_free_handle(&rx_data->rbd_dma_handle); 58854e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_dma_handle = NULL; 58908057504Sxy150489 } 59008057504Sxy150489 return (DDI_FAILURE); 59108057504Sxy150489 } else 59208057504Sxy150489 alloc_flag = B_TRUE; 59308057504Sxy150489 59408057504Sxy150489 /* 59508057504Sxy150489 * Initialize the allocated receive descriptor memory to zero. 59608057504Sxy150489 */ 59754e0d7a5SMiles Xu, Sun Microsystems bzero((caddr_t)rx_data->rbd_area, len); 59854e0d7a5SMiles Xu, Sun Microsystems templong = P2NPHASE((uintptr_t)rx_data->rbd_area, 599ede5269eSchenlu chen - Sun Microsystems - Beijing China Adapter->desc_align); 60008057504Sxy150489 len = size - templong; 60154e0d7a5SMiles Xu, Sun Microsystems templong += (uintptr_t)rx_data->rbd_area; 60254e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_area = (struct e1000_rx_desc *)templong; 60308057504Sxy150489 } /* alignment workaround */ 60408057504Sxy150489 60508057504Sxy150489 /* 60608057504Sxy150489 * The memory allocation of the receive descriptors succeeded 60708057504Sxy150489 */ 60808057504Sxy150489 ASSERT(alloc_flag); 60908057504Sxy150489 61008057504Sxy150489 /* 61108057504Sxy150489 * Allocates DMA resources for the memory that was allocated by 61208057504Sxy150489 * the ddi_dma_mem_alloc call. 61308057504Sxy150489 */ 61454e0d7a5SMiles Xu, Sun Microsystems mystat = ddi_dma_addr_bind_handle(rx_data->rbd_dma_handle, 61554e0d7a5SMiles Xu, Sun Microsystems (struct as *)NULL, (caddr_t)rx_data->rbd_area, 61608057504Sxy150489 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 61725f2d433Sxy150489 DDI_DMA_DONTWAIT, 0, &cookie, &cookie_count); 61808057504Sxy150489 61908057504Sxy150489 if (mystat != DDI_SUCCESS) { 62025f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 62108057504Sxy150489 "Could not bind rbd dma resource: %d", mystat); 62254e0d7a5SMiles Xu, Sun Microsystems if (rx_data->rbd_acc_handle != NULL) { 62354e0d7a5SMiles Xu, Sun Microsystems ddi_dma_mem_free(&rx_data->rbd_acc_handle); 62454e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_acc_handle = NULL; 62554e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_area = NULL; 62608057504Sxy150489 } 62754e0d7a5SMiles Xu, Sun Microsystems if (rx_data->rbd_dma_handle != NULL) { 62854e0d7a5SMiles Xu, Sun Microsystems ddi_dma_free_handle(&rx_data->rbd_dma_handle); 62954e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_dma_handle = NULL; 63008057504Sxy150489 } 63108057504Sxy150489 return (DDI_FAILURE); 63208057504Sxy150489 } 63308057504Sxy150489 63408057504Sxy150489 ASSERT(cookie_count == 1); 63508057504Sxy150489 if (cookie_count != 1) { 63625f2d433Sxy150489 E1000G_DEBUGLOG_2(Adapter, E1000G_WARN_LEVEL, 63708057504Sxy150489 "Could not bind rbd dma resource in a single frag. " 63808057504Sxy150489 "Count - %d Len - %d", cookie_count, len); 63954e0d7a5SMiles Xu, Sun Microsystems e1000g_free_rx_descriptors(rx_data); 64008057504Sxy150489 return (DDI_FAILURE); 64108057504Sxy150489 } 64225f2d433Sxy150489 64354e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_dma_addr = cookie.dmac_laddress; 64454e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_first = rx_data->rbd_area; 64554e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_last = rx_data->rbd_first + 64625f2d433Sxy150489 (Adapter->rx_desc_num - 1); 64708057504Sxy150489 64808057504Sxy150489 return (DDI_SUCCESS); 64908057504Sxy150489 } 65008057504Sxy150489 65108057504Sxy150489 static void 65254e0d7a5SMiles Xu, Sun Microsystems e1000g_free_rx_descriptors(e1000g_rx_data_t *rx_data) 65308057504Sxy150489 { 65454e0d7a5SMiles Xu, Sun Microsystems if (rx_data->rbd_dma_handle != NULL) { 65554e0d7a5SMiles Xu, Sun Microsystems (void) ddi_dma_unbind_handle(rx_data->rbd_dma_handle); 65608057504Sxy150489 } 65754e0d7a5SMiles Xu, Sun Microsystems if (rx_data->rbd_acc_handle != NULL) { 65854e0d7a5SMiles Xu, Sun Microsystems ddi_dma_mem_free(&rx_data->rbd_acc_handle); 65954e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_acc_handle = NULL; 66054e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_area = NULL; 66108057504Sxy150489 } 66254e0d7a5SMiles Xu, Sun Microsystems if (rx_data->rbd_dma_handle != NULL) { 66354e0d7a5SMiles Xu, Sun Microsystems ddi_dma_free_handle(&rx_data->rbd_dma_handle); 66454e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_dma_handle = NULL; 66508057504Sxy150489 } 66654e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_dma_addr = NULL; 66754e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_first = NULL; 66854e0d7a5SMiles Xu, Sun Microsystems rx_data->rbd_last = NULL; 66908057504Sxy150489 } 67008057504Sxy150489 67108057504Sxy150489 static void 67208057504Sxy150489 e1000g_free_tx_descriptors(e1000g_tx_ring_t *tx_ring) 67308057504Sxy150489 { 67408057504Sxy150489 if (tx_ring->tbd_dma_handle != NULL) { 675fe62dec3SChen-Liang Xu (void) ddi_dma_unbind_handle(tx_ring->tbd_dma_handle); 67608057504Sxy150489 } 67708057504Sxy150489 if (tx_ring->tbd_acc_handle != NULL) { 67808057504Sxy150489 ddi_dma_mem_free(&tx_ring->tbd_acc_handle); 67908057504Sxy150489 tx_ring->tbd_acc_handle = NULL; 68008057504Sxy150489 tx_ring->tbd_area = NULL; 68108057504Sxy150489 } 68208057504Sxy150489 if (tx_ring->tbd_dma_handle != NULL) { 68308057504Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_dma_handle); 68408057504Sxy150489 tx_ring->tbd_dma_handle = NULL; 68508057504Sxy150489 } 68608057504Sxy150489 tx_ring->tbd_dma_addr = NULL; 68708057504Sxy150489 tx_ring->tbd_first = NULL; 68808057504Sxy150489 tx_ring->tbd_last = NULL; 68908057504Sxy150489 } 69008057504Sxy150489 69108057504Sxy150489 69208057504Sxy150489 /* 69325f2d433Sxy150489 * e1000g_alloc_packets - allocate DMA buffers for rx/tx 69425f2d433Sxy150489 * 69525f2d433Sxy150489 * This routine allocates neccesary buffers for 69625f2d433Sxy150489 * Transmit sw packet structure 69725f2d433Sxy150489 * DMA handle for Transmit 69825f2d433Sxy150489 * DMA buffer for Transmit 69925f2d433Sxy150489 * Receive sw packet structure 70025f2d433Sxy150489 * DMA buffer for Receive 70108057504Sxy150489 */ 70208057504Sxy150489 static int 70308057504Sxy150489 e1000g_alloc_packets(struct e1000g *Adapter) 70408057504Sxy150489 { 70508057504Sxy150489 int result; 70608057504Sxy150489 e1000g_tx_ring_t *tx_ring; 70754e0d7a5SMiles Xu, Sun Microsystems e1000g_rx_data_t *rx_data; 70808057504Sxy150489 70908057504Sxy150489 tx_ring = Adapter->tx_ring; 71054e0d7a5SMiles Xu, Sun Microsystems rx_data = Adapter->rx_ring->rx_data; 71108057504Sxy150489 71208057504Sxy150489 again: 71308057504Sxy150489 rw_enter(&e1000g_dma_type_lock, RW_READER); 71408057504Sxy150489 71508057504Sxy150489 result = e1000g_alloc_tx_packets(tx_ring); 71608057504Sxy150489 if (result != DDI_SUCCESS) { 71708057504Sxy150489 if (e1000g_dma_type == USE_DVMA) { 71808057504Sxy150489 rw_exit(&e1000g_dma_type_lock); 71908057504Sxy150489 72008057504Sxy150489 rw_enter(&e1000g_dma_type_lock, RW_WRITER); 72108057504Sxy150489 e1000g_dma_type = USE_DMA; 72208057504Sxy150489 rw_exit(&e1000g_dma_type_lock); 72308057504Sxy150489 72425f2d433Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL, 72508057504Sxy150489 "No enough dvma resource for Tx packets, " 72608057504Sxy150489 "trying to allocate dma buffers...\n"); 72708057504Sxy150489 goto again; 72808057504Sxy150489 } 72908057504Sxy150489 rw_exit(&e1000g_dma_type_lock); 73008057504Sxy150489 73125f2d433Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL, 73208057504Sxy150489 "Failed to allocate dma buffers for Tx packets\n"); 73308057504Sxy150489 return (DDI_FAILURE); 73408057504Sxy150489 } 73508057504Sxy150489 73654e0d7a5SMiles Xu, Sun Microsystems result = e1000g_alloc_rx_packets(rx_data); 73708057504Sxy150489 if (result != DDI_SUCCESS) { 73808057504Sxy150489 e1000g_free_tx_packets(tx_ring); 73908057504Sxy150489 if (e1000g_dma_type == USE_DVMA) { 74008057504Sxy150489 rw_exit(&e1000g_dma_type_lock); 74108057504Sxy150489 74208057504Sxy150489 rw_enter(&e1000g_dma_type_lock, RW_WRITER); 74308057504Sxy150489 e1000g_dma_type = USE_DMA; 74408057504Sxy150489 rw_exit(&e1000g_dma_type_lock); 74508057504Sxy150489 74625f2d433Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL, 74708057504Sxy150489 "No enough dvma resource for Rx packets, " 74808057504Sxy150489 "trying to allocate dma buffers...\n"); 74908057504Sxy150489 goto again; 75008057504Sxy150489 } 75108057504Sxy150489 rw_exit(&e1000g_dma_type_lock); 75208057504Sxy150489 75325f2d433Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL, 75408057504Sxy150489 "Failed to allocate dma buffers for Rx packets\n"); 75508057504Sxy150489 return (DDI_FAILURE); 75608057504Sxy150489 } 75708057504Sxy150489 75808057504Sxy150489 rw_exit(&e1000g_dma_type_lock); 75908057504Sxy150489 76008057504Sxy150489 return (DDI_SUCCESS); 76108057504Sxy150489 } 76208057504Sxy150489 76325f2d433Sxy150489 static void 76425f2d433Sxy150489 e1000g_free_packets(struct e1000g *Adapter) 76525f2d433Sxy150489 { 76625f2d433Sxy150489 e1000g_tx_ring_t *tx_ring; 76754e0d7a5SMiles Xu, Sun Microsystems e1000g_rx_data_t *rx_data; 76825f2d433Sxy150489 76925f2d433Sxy150489 tx_ring = Adapter->tx_ring; 77054e0d7a5SMiles Xu, Sun Microsystems rx_data = Adapter->rx_ring->rx_data; 77125f2d433Sxy150489 77225f2d433Sxy150489 e1000g_free_tx_packets(tx_ring); 7733fb4efefSchangqing li - Sun Microsystems - Beijing China e1000g_free_rx_packets(rx_data, B_FALSE); 77425f2d433Sxy150489 } 77525f2d433Sxy150489 77608057504Sxy150489 #ifdef __sparc 77708057504Sxy150489 static int 77808057504Sxy150489 e1000g_alloc_dvma_buffer(struct e1000g *Adapter, 77908057504Sxy150489 dma_buffer_t *buf, size_t size) 78008057504Sxy150489 { 78108057504Sxy150489 int mystat; 78208057504Sxy150489 dev_info_t *devinfo; 78308057504Sxy150489 ddi_dma_cookie_t cookie; 78408057504Sxy150489 7850f70fbf8Sxy150489 if (e1000g_force_detach) 7860f70fbf8Sxy150489 devinfo = Adapter->priv_dip; 7870f70fbf8Sxy150489 else 78808057504Sxy150489 devinfo = Adapter->dip; 78908057504Sxy150489 79008057504Sxy150489 mystat = dvma_reserve(devinfo, 79108057504Sxy150489 &e1000g_dma_limits, 79208057504Sxy150489 Adapter->dvma_page_num, 79308057504Sxy150489 &buf->dma_handle); 79408057504Sxy150489 79508057504Sxy150489 if (mystat != DDI_SUCCESS) { 79608057504Sxy150489 buf->dma_handle = NULL; 79725f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 79808057504Sxy150489 "Could not allocate dvma buffer handle: %d\n", mystat); 79908057504Sxy150489 return (DDI_FAILURE); 80008057504Sxy150489 } 80108057504Sxy150489 80208057504Sxy150489 buf->address = kmem_alloc(size, KM_NOSLEEP); 80308057504Sxy150489 80408057504Sxy150489 if (buf->address == NULL) { 80508057504Sxy150489 if (buf->dma_handle != NULL) { 80608057504Sxy150489 dvma_release(buf->dma_handle); 80708057504Sxy150489 buf->dma_handle = NULL; 80808057504Sxy150489 } 80925f2d433Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL, 81008057504Sxy150489 "Could not allocate dvma buffer memory\n"); 81108057504Sxy150489 return (DDI_FAILURE); 81208057504Sxy150489 } 81308057504Sxy150489 81408057504Sxy150489 dvma_kaddr_load(buf->dma_handle, 81508057504Sxy150489 buf->address, size, 0, &cookie); 81608057504Sxy150489 81708057504Sxy150489 buf->dma_address = cookie.dmac_laddress; 81808057504Sxy150489 buf->size = size; 81908057504Sxy150489 buf->len = 0; 82008057504Sxy150489 82108057504Sxy150489 return (DDI_SUCCESS); 82208057504Sxy150489 } 82308057504Sxy150489 82408057504Sxy150489 static void 82508057504Sxy150489 e1000g_free_dvma_buffer(dma_buffer_t *buf) 82608057504Sxy150489 { 82708057504Sxy150489 if (buf->dma_handle != NULL) { 82808057504Sxy150489 dvma_unload(buf->dma_handle, 0, -1); 82908057504Sxy150489 } else { 83008057504Sxy150489 return; 83108057504Sxy150489 } 83208057504Sxy150489 83308057504Sxy150489 buf->dma_address = NULL; 83408057504Sxy150489 83508057504Sxy150489 if (buf->address != NULL) { 83608057504Sxy150489 kmem_free(buf->address, buf->size); 83708057504Sxy150489 buf->address = NULL; 83808057504Sxy150489 } 83908057504Sxy150489 84008057504Sxy150489 if (buf->dma_handle != NULL) { 84108057504Sxy150489 dvma_release(buf->dma_handle); 84208057504Sxy150489 buf->dma_handle = NULL; 84308057504Sxy150489 } 84408057504Sxy150489 84508057504Sxy150489 buf->size = 0; 84608057504Sxy150489 buf->len = 0; 84708057504Sxy150489 } 84808057504Sxy150489 #endif 84908057504Sxy150489 85008057504Sxy150489 static int 85108057504Sxy150489 e1000g_alloc_dma_buffer(struct e1000g *Adapter, 85225f2d433Sxy150489 dma_buffer_t *buf, size_t size, ddi_dma_attr_t *p_dma_attr) 85308057504Sxy150489 { 85408057504Sxy150489 int mystat; 85508057504Sxy150489 dev_info_t *devinfo; 85608057504Sxy150489 ddi_dma_cookie_t cookie; 85708057504Sxy150489 size_t len; 85808057504Sxy150489 uint_t count; 85908057504Sxy150489 8600f70fbf8Sxy150489 if (e1000g_force_detach) 8610f70fbf8Sxy150489 devinfo = Adapter->priv_dip; 8620f70fbf8Sxy150489 else 86308057504Sxy150489 devinfo = Adapter->dip; 86408057504Sxy150489 86508057504Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, 86625f2d433Sxy150489 p_dma_attr, 86708057504Sxy150489 DDI_DMA_DONTWAIT, 0, 86808057504Sxy150489 &buf->dma_handle); 86908057504Sxy150489 87008057504Sxy150489 if (mystat != DDI_SUCCESS) { 87108057504Sxy150489 buf->dma_handle = NULL; 87225f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 87308057504Sxy150489 "Could not allocate dma buffer handle: %d\n", mystat); 87408057504Sxy150489 return (DDI_FAILURE); 87508057504Sxy150489 } 87608057504Sxy150489 87708057504Sxy150489 mystat = ddi_dma_mem_alloc(buf->dma_handle, 87825f2d433Sxy150489 size, &e1000g_buf_acc_attr, DDI_DMA_STREAMING, 87908057504Sxy150489 DDI_DMA_DONTWAIT, 0, 88008057504Sxy150489 &buf->address, 88108057504Sxy150489 &len, &buf->acc_handle); 88208057504Sxy150489 88308057504Sxy150489 if (mystat != DDI_SUCCESS) { 88408057504Sxy150489 buf->acc_handle = NULL; 88508057504Sxy150489 buf->address = NULL; 88608057504Sxy150489 if (buf->dma_handle != NULL) { 88708057504Sxy150489 ddi_dma_free_handle(&buf->dma_handle); 88808057504Sxy150489 buf->dma_handle = NULL; 88908057504Sxy150489 } 89025f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 89108057504Sxy150489 "Could not allocate dma buffer memory: %d\n", mystat); 89208057504Sxy150489 return (DDI_FAILURE); 89308057504Sxy150489 } 89408057504Sxy150489 89508057504Sxy150489 mystat = ddi_dma_addr_bind_handle(buf->dma_handle, 89608057504Sxy150489 (struct as *)NULL, 89708057504Sxy150489 buf->address, 8980c35404fSchangqing li - Sun Microsystems - Beijing China len, DDI_DMA_RDWR | DDI_DMA_STREAMING, 89925f2d433Sxy150489 DDI_DMA_DONTWAIT, 0, &cookie, &count); 90008057504Sxy150489 90108057504Sxy150489 if (mystat != DDI_SUCCESS) { 90208057504Sxy150489 if (buf->acc_handle != NULL) { 90308057504Sxy150489 ddi_dma_mem_free(&buf->acc_handle); 90408057504Sxy150489 buf->acc_handle = NULL; 90508057504Sxy150489 buf->address = NULL; 90608057504Sxy150489 } 90708057504Sxy150489 if (buf->dma_handle != NULL) { 90808057504Sxy150489 ddi_dma_free_handle(&buf->dma_handle); 90908057504Sxy150489 buf->dma_handle = NULL; 91008057504Sxy150489 } 91125f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 91208057504Sxy150489 "Could not bind buffer dma handle: %d\n", mystat); 91308057504Sxy150489 return (DDI_FAILURE); 91408057504Sxy150489 } 91508057504Sxy150489 91608057504Sxy150489 ASSERT(count == 1); 91708057504Sxy150489 if (count != 1) { 91808057504Sxy150489 if (buf->dma_handle != NULL) { 919fe62dec3SChen-Liang Xu (void) ddi_dma_unbind_handle(buf->dma_handle); 92008057504Sxy150489 } 92108057504Sxy150489 if (buf->acc_handle != NULL) { 92208057504Sxy150489 ddi_dma_mem_free(&buf->acc_handle); 92308057504Sxy150489 buf->acc_handle = NULL; 92408057504Sxy150489 buf->address = NULL; 92508057504Sxy150489 } 92608057504Sxy150489 if (buf->dma_handle != NULL) { 92708057504Sxy150489 ddi_dma_free_handle(&buf->dma_handle); 92808057504Sxy150489 buf->dma_handle = NULL; 92908057504Sxy150489 } 93025f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 93108057504Sxy150489 "Could not bind buffer as a single frag. " 93208057504Sxy150489 "Count = %d\n", count); 93308057504Sxy150489 return (DDI_FAILURE); 93408057504Sxy150489 } 93508057504Sxy150489 93608057504Sxy150489 buf->dma_address = cookie.dmac_laddress; 93708057504Sxy150489 buf->size = len; 93808057504Sxy150489 buf->len = 0; 93908057504Sxy150489 94008057504Sxy150489 return (DDI_SUCCESS); 94108057504Sxy150489 } 94208057504Sxy150489 943ede5269eSchenlu chen - Sun Microsystems - Beijing China /* 944ede5269eSchenlu chen - Sun Microsystems - Beijing China * e1000g_alloc_dma_buffer_82546 - allocate a dma buffer along with all 945ede5269eSchenlu chen - Sun Microsystems - Beijing China * necessary handles. Same as e1000g_alloc_dma_buffer() except ensure 946ede5269eSchenlu chen - Sun Microsystems - Beijing China * that buffer that doesn't cross a 64k boundary. 947ede5269eSchenlu chen - Sun Microsystems - Beijing China */ 948ede5269eSchenlu chen - Sun Microsystems - Beijing China static int 949ede5269eSchenlu chen - Sun Microsystems - Beijing China e1000g_alloc_dma_buffer_82546(struct e1000g *Adapter, 950ede5269eSchenlu chen - Sun Microsystems - Beijing China dma_buffer_t *buf, size_t size, ddi_dma_attr_t *p_dma_attr) 951ede5269eSchenlu chen - Sun Microsystems - Beijing China { 952ede5269eSchenlu chen - Sun Microsystems - Beijing China int mystat; 953ede5269eSchenlu chen - Sun Microsystems - Beijing China dev_info_t *devinfo; 954ede5269eSchenlu chen - Sun Microsystems - Beijing China ddi_dma_cookie_t cookie; 955ede5269eSchenlu chen - Sun Microsystems - Beijing China size_t len; 956ede5269eSchenlu chen - Sun Microsystems - Beijing China uint_t count; 957ede5269eSchenlu chen - Sun Microsystems - Beijing China 958ede5269eSchenlu chen - Sun Microsystems - Beijing China if (e1000g_force_detach) 959ede5269eSchenlu chen - Sun Microsystems - Beijing China devinfo = Adapter->priv_dip; 960ede5269eSchenlu chen - Sun Microsystems - Beijing China else 961ede5269eSchenlu chen - Sun Microsystems - Beijing China devinfo = Adapter->dip; 962ede5269eSchenlu chen - Sun Microsystems - Beijing China 963ede5269eSchenlu chen - Sun Microsystems - Beijing China mystat = ddi_dma_alloc_handle(devinfo, 964ede5269eSchenlu chen - Sun Microsystems - Beijing China p_dma_attr, 965ede5269eSchenlu chen - Sun Microsystems - Beijing China DDI_DMA_DONTWAIT, 0, 966ede5269eSchenlu chen - Sun Microsystems - Beijing China &buf->dma_handle); 967ede5269eSchenlu chen - Sun Microsystems - Beijing China 968ede5269eSchenlu chen - Sun Microsystems - Beijing China if (mystat != DDI_SUCCESS) { 969ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->dma_handle = NULL; 970ede5269eSchenlu chen - Sun Microsystems - Beijing China E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 971ede5269eSchenlu chen - Sun Microsystems - Beijing China "Could not allocate dma buffer handle: %d\n", mystat); 972ede5269eSchenlu chen - Sun Microsystems - Beijing China return (DDI_FAILURE); 973ede5269eSchenlu chen - Sun Microsystems - Beijing China } 974ede5269eSchenlu chen - Sun Microsystems - Beijing China 975ede5269eSchenlu chen - Sun Microsystems - Beijing China mystat = e1000g_dma_mem_alloc_82546(buf, size, &len); 976ede5269eSchenlu chen - Sun Microsystems - Beijing China if (mystat != DDI_SUCCESS) { 977ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->acc_handle = NULL; 978ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->address = NULL; 979ede5269eSchenlu chen - Sun Microsystems - Beijing China if (buf->dma_handle != NULL) { 980ede5269eSchenlu chen - Sun Microsystems - Beijing China ddi_dma_free_handle(&buf->dma_handle); 981ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->dma_handle = NULL; 982ede5269eSchenlu chen - Sun Microsystems - Beijing China } 983ede5269eSchenlu chen - Sun Microsystems - Beijing China E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 984ede5269eSchenlu chen - Sun Microsystems - Beijing China "Could not allocate dma buffer memory: %d\n", mystat); 985ede5269eSchenlu chen - Sun Microsystems - Beijing China return (DDI_FAILURE); 986ede5269eSchenlu chen - Sun Microsystems - Beijing China } 987ede5269eSchenlu chen - Sun Microsystems - Beijing China 988ede5269eSchenlu chen - Sun Microsystems - Beijing China mystat = ddi_dma_addr_bind_handle(buf->dma_handle, 989ede5269eSchenlu chen - Sun Microsystems - Beijing China (struct as *)NULL, 990ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->address, 991ede5269eSchenlu chen - Sun Microsystems - Beijing China len, DDI_DMA_READ | DDI_DMA_STREAMING, 992ede5269eSchenlu chen - Sun Microsystems - Beijing China DDI_DMA_DONTWAIT, 0, &cookie, &count); 993ede5269eSchenlu chen - Sun Microsystems - Beijing China 994ede5269eSchenlu chen - Sun Microsystems - Beijing China if (mystat != DDI_SUCCESS) { 995ede5269eSchenlu chen - Sun Microsystems - Beijing China if (buf->acc_handle != NULL) { 996ede5269eSchenlu chen - Sun Microsystems - Beijing China ddi_dma_mem_free(&buf->acc_handle); 997ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->acc_handle = NULL; 998ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->address = NULL; 999ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1000ede5269eSchenlu chen - Sun Microsystems - Beijing China if (buf->dma_handle != NULL) { 1001ede5269eSchenlu chen - Sun Microsystems - Beijing China ddi_dma_free_handle(&buf->dma_handle); 1002ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->dma_handle = NULL; 1003ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1004ede5269eSchenlu chen - Sun Microsystems - Beijing China E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 1005ede5269eSchenlu chen - Sun Microsystems - Beijing China "Could not bind buffer dma handle: %d\n", mystat); 1006ede5269eSchenlu chen - Sun Microsystems - Beijing China return (DDI_FAILURE); 1007ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1008ede5269eSchenlu chen - Sun Microsystems - Beijing China 1009ede5269eSchenlu chen - Sun Microsystems - Beijing China ASSERT(count == 1); 1010ede5269eSchenlu chen - Sun Microsystems - Beijing China if (count != 1) { 1011ede5269eSchenlu chen - Sun Microsystems - Beijing China if (buf->dma_handle != NULL) { 101257ef6f69Sguoqing zhu - Sun Microsystems - Beijing China (void) ddi_dma_unbind_handle(buf->dma_handle); 1013ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1014ede5269eSchenlu chen - Sun Microsystems - Beijing China if (buf->acc_handle != NULL) { 1015ede5269eSchenlu chen - Sun Microsystems - Beijing China ddi_dma_mem_free(&buf->acc_handle); 1016ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->acc_handle = NULL; 1017ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->address = NULL; 1018ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1019ede5269eSchenlu chen - Sun Microsystems - Beijing China if (buf->dma_handle != NULL) { 1020ede5269eSchenlu chen - Sun Microsystems - Beijing China ddi_dma_free_handle(&buf->dma_handle); 1021ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->dma_handle = NULL; 1022ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1023ede5269eSchenlu chen - Sun Microsystems - Beijing China E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 1024ede5269eSchenlu chen - Sun Microsystems - Beijing China "Could not bind buffer as a single frag. " 1025ede5269eSchenlu chen - Sun Microsystems - Beijing China "Count = %d\n", count); 1026ede5269eSchenlu chen - Sun Microsystems - Beijing China return (DDI_FAILURE); 1027ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1028ede5269eSchenlu chen - Sun Microsystems - Beijing China 1029ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->dma_address = cookie.dmac_laddress; 1030ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->size = len; 1031ede5269eSchenlu chen - Sun Microsystems - Beijing China buf->len = 0; 1032ede5269eSchenlu chen - Sun Microsystems - Beijing China 1033ede5269eSchenlu chen - Sun Microsystems - Beijing China return (DDI_SUCCESS); 1034ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1035ede5269eSchenlu chen - Sun Microsystems - Beijing China 1036ede5269eSchenlu chen - Sun Microsystems - Beijing China /* 1037ede5269eSchenlu chen - Sun Microsystems - Beijing China * e1000g_dma_mem_alloc_82546 - allocate a dma buffer, making up to 1038ede5269eSchenlu chen - Sun Microsystems - Beijing China * ALLOC_RETRY attempts to get a buffer that doesn't cross a 64k boundary. 1039ede5269eSchenlu chen - Sun Microsystems - Beijing China */ 1040ede5269eSchenlu chen - Sun Microsystems - Beijing China static int 1041ede5269eSchenlu chen - Sun Microsystems - Beijing China e1000g_dma_mem_alloc_82546(dma_buffer_t *buf, size_t size, size_t *len) 1042ede5269eSchenlu chen - Sun Microsystems - Beijing China { 1043ede5269eSchenlu chen - Sun Microsystems - Beijing China #define ALLOC_RETRY 10 1044ede5269eSchenlu chen - Sun Microsystems - Beijing China int stat; 1045ede5269eSchenlu chen - Sun Microsystems - Beijing China int cnt = 0; 1046ede5269eSchenlu chen - Sun Microsystems - Beijing China ddi_acc_handle_t hold[ALLOC_RETRY]; 1047ede5269eSchenlu chen - Sun Microsystems - Beijing China 1048ede5269eSchenlu chen - Sun Microsystems - Beijing China while (cnt < ALLOC_RETRY) { 1049ede5269eSchenlu chen - Sun Microsystems - Beijing China hold[cnt] = NULL; 1050ede5269eSchenlu chen - Sun Microsystems - Beijing China 1051ede5269eSchenlu chen - Sun Microsystems - Beijing China /* allocate memory */ 1052ede5269eSchenlu chen - Sun Microsystems - Beijing China stat = ddi_dma_mem_alloc(buf->dma_handle, size, 1053ede5269eSchenlu chen - Sun Microsystems - Beijing China &e1000g_buf_acc_attr, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 1054ede5269eSchenlu chen - Sun Microsystems - Beijing China 0, &buf->address, len, &buf->acc_handle); 1055ede5269eSchenlu chen - Sun Microsystems - Beijing China 1056ede5269eSchenlu chen - Sun Microsystems - Beijing China if (stat != DDI_SUCCESS) { 1057ede5269eSchenlu chen - Sun Microsystems - Beijing China break; 1058ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1059ede5269eSchenlu chen - Sun Microsystems - Beijing China 1060ede5269eSchenlu chen - Sun Microsystems - Beijing China /* 1061ede5269eSchenlu chen - Sun Microsystems - Beijing China * Check 64k bounday: 1062ede5269eSchenlu chen - Sun Microsystems - Beijing China * if it is bad, hold it and retry 1063ede5269eSchenlu chen - Sun Microsystems - Beijing China * if it is good, exit loop 1064ede5269eSchenlu chen - Sun Microsystems - Beijing China */ 1065ede5269eSchenlu chen - Sun Microsystems - Beijing China if (e1000g_cross_64k_bound(buf->address, *len)) { 1066ede5269eSchenlu chen - Sun Microsystems - Beijing China hold[cnt] = buf->acc_handle; 1067ede5269eSchenlu chen - Sun Microsystems - Beijing China stat = DDI_FAILURE; 1068ede5269eSchenlu chen - Sun Microsystems - Beijing China } else { 1069ede5269eSchenlu chen - Sun Microsystems - Beijing China break; 1070ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1071ede5269eSchenlu chen - Sun Microsystems - Beijing China 1072ede5269eSchenlu chen - Sun Microsystems - Beijing China cnt++; 1073ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1074ede5269eSchenlu chen - Sun Microsystems - Beijing China 1075ede5269eSchenlu chen - Sun Microsystems - Beijing China /* Release any held buffers crossing 64k bounday */ 1076ede5269eSchenlu chen - Sun Microsystems - Beijing China for (--cnt; cnt >= 0; cnt--) { 1077ede5269eSchenlu chen - Sun Microsystems - Beijing China if (hold[cnt]) 1078ede5269eSchenlu chen - Sun Microsystems - Beijing China ddi_dma_mem_free(&hold[cnt]); 1079ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1080ede5269eSchenlu chen - Sun Microsystems - Beijing China 1081ede5269eSchenlu chen - Sun Microsystems - Beijing China return (stat); 1082ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1083ede5269eSchenlu chen - Sun Microsystems - Beijing China 1084ede5269eSchenlu chen - Sun Microsystems - Beijing China /* 1085ede5269eSchenlu chen - Sun Microsystems - Beijing China * e1000g_cross_64k_bound - If starting and ending address cross a 64k boundary 1086ede5269eSchenlu chen - Sun Microsystems - Beijing China * return true; otherwise return false 1087ede5269eSchenlu chen - Sun Microsystems - Beijing China */ 1088ede5269eSchenlu chen - Sun Microsystems - Beijing China static boolean_t 1089ede5269eSchenlu chen - Sun Microsystems - Beijing China e1000g_cross_64k_bound(void *addr, uintptr_t len) 1090ede5269eSchenlu chen - Sun Microsystems - Beijing China { 1091ede5269eSchenlu chen - Sun Microsystems - Beijing China uintptr_t start = (uintptr_t)addr; 1092ede5269eSchenlu chen - Sun Microsystems - Beijing China uintptr_t end = start + len - 1; 1093ede5269eSchenlu chen - Sun Microsystems - Beijing China 1094ede5269eSchenlu chen - Sun Microsystems - Beijing China return (((start ^ end) >> 16) == 0 ? B_FALSE : B_TRUE); 1095ede5269eSchenlu chen - Sun Microsystems - Beijing China } 1096ede5269eSchenlu chen - Sun Microsystems - Beijing China 109708057504Sxy150489 static void 109808057504Sxy150489 e1000g_free_dma_buffer(dma_buffer_t *buf) 109908057504Sxy150489 { 110008057504Sxy150489 if (buf->dma_handle != NULL) { 1101fe62dec3SChen-Liang Xu (void) ddi_dma_unbind_handle(buf->dma_handle); 110208057504Sxy150489 } else { 110308057504Sxy150489 return; 110408057504Sxy150489 } 110508057504Sxy150489 110608057504Sxy150489 buf->dma_address = NULL; 110708057504Sxy150489 110808057504Sxy150489 if (buf->acc_handle != NULL) { 110908057504Sxy150489 ddi_dma_mem_free(&buf->acc_handle); 111008057504Sxy150489 buf->acc_handle = NULL; 111108057504Sxy150489 buf->address = NULL; 111208057504Sxy150489 } 111308057504Sxy150489 111408057504Sxy150489 if (buf->dma_handle != NULL) { 111508057504Sxy150489 ddi_dma_free_handle(&buf->dma_handle); 111608057504Sxy150489 buf->dma_handle = NULL; 111708057504Sxy150489 } 111808057504Sxy150489 111908057504Sxy150489 buf->size = 0; 112008057504Sxy150489 buf->len = 0; 112108057504Sxy150489 } 112208057504Sxy150489 112308057504Sxy150489 static int 112408057504Sxy150489 e1000g_alloc_tx_packets(e1000g_tx_ring_t *tx_ring) 112508057504Sxy150489 { 112608057504Sxy150489 int j; 112725f2d433Sxy150489 p_tx_sw_packet_t packet; 112808057504Sxy150489 int mystat; 112908057504Sxy150489 dma_buffer_t *tx_buf; 113025f2d433Sxy150489 struct e1000g *Adapter; 113125f2d433Sxy150489 dev_info_t *devinfo; 113225f2d433Sxy150489 ddi_dma_attr_t dma_attr; 113325f2d433Sxy150489 113425f2d433Sxy150489 Adapter = tx_ring->adapter; 113525f2d433Sxy150489 devinfo = Adapter->dip; 113625f2d433Sxy150489 dma_attr = e1000g_buf_dma_attr; 113708057504Sxy150489 113808057504Sxy150489 /* 113908057504Sxy150489 * Memory allocation for the Transmit software structure, the transmit 114008057504Sxy150489 * software packet. This structure stores all the relevant information 114108057504Sxy150489 * for transmitting a single packet. 114208057504Sxy150489 */ 114308057504Sxy150489 tx_ring->packet_area = 114408057504Sxy150489 kmem_zalloc(TX_SW_PKT_AREA_SZ, KM_NOSLEEP); 114508057504Sxy150489 114608057504Sxy150489 if (tx_ring->packet_area == NULL) 114708057504Sxy150489 return (DDI_FAILURE); 114808057504Sxy150489 114908057504Sxy150489 for (j = 0, packet = tx_ring->packet_area; 115025f2d433Sxy150489 j < Adapter->tx_freelist_num; j++, packet++) { 115108057504Sxy150489 115208057504Sxy150489 ASSERT(packet != NULL); 115308057504Sxy150489 115408057504Sxy150489 /* 115508057504Sxy150489 * Pre-allocate dma handles for transmit. These dma handles 115608057504Sxy150489 * will be dynamically bound to the data buffers passed down 115708057504Sxy150489 * from the upper layers at the time of transmitting. The 115808057504Sxy150489 * dynamic binding only applies for the packets that are larger 115908057504Sxy150489 * than the tx_bcopy_thresh. 116008057504Sxy150489 */ 116108057504Sxy150489 switch (e1000g_dma_type) { 116208057504Sxy150489 #ifdef __sparc 116308057504Sxy150489 case USE_DVMA: 116408057504Sxy150489 mystat = dvma_reserve(devinfo, 116508057504Sxy150489 &e1000g_dma_limits, 116608057504Sxy150489 Adapter->dvma_page_num, 116708057504Sxy150489 &packet->tx_dma_handle); 116808057504Sxy150489 break; 116908057504Sxy150489 #endif 117008057504Sxy150489 case USE_DMA: 117108057504Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, 117225f2d433Sxy150489 &e1000g_tx_dma_attr, 117308057504Sxy150489 DDI_DMA_DONTWAIT, 0, 117408057504Sxy150489 &packet->tx_dma_handle); 117508057504Sxy150489 break; 117608057504Sxy150489 default: 117708057504Sxy150489 ASSERT(B_FALSE); 117808057504Sxy150489 break; 117908057504Sxy150489 } 118008057504Sxy150489 if (mystat != DDI_SUCCESS) { 118108057504Sxy150489 packet->tx_dma_handle = NULL; 118225f2d433Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 118308057504Sxy150489 "Could not allocate tx dma handle: %d\n", mystat); 118408057504Sxy150489 goto tx_pkt_fail; 118508057504Sxy150489 } 118608057504Sxy150489 118708057504Sxy150489 /* 118808057504Sxy150489 * Pre-allocate transmit buffers for small packets that the 118908057504Sxy150489 * size is less than tx_bcopy_thresh. The data of those small 119008057504Sxy150489 * packets will be bcopy() to the transmit buffers instead of 119108057504Sxy150489 * using dynamical DMA binding. For small packets, bcopy will 119208057504Sxy150489 * bring better performance than DMA binding. 119308057504Sxy150489 */ 119408057504Sxy150489 tx_buf = packet->tx_buf; 119508057504Sxy150489 119608057504Sxy150489 switch (e1000g_dma_type) { 119708057504Sxy150489 #ifdef __sparc 119808057504Sxy150489 case USE_DVMA: 119908057504Sxy150489 mystat = e1000g_alloc_dvma_buffer(Adapter, 120025f2d433Sxy150489 tx_buf, Adapter->tx_buffer_size); 120108057504Sxy150489 break; 120208057504Sxy150489 #endif 120308057504Sxy150489 case USE_DMA: 120408057504Sxy150489 mystat = e1000g_alloc_dma_buffer(Adapter, 120525f2d433Sxy150489 tx_buf, Adapter->tx_buffer_size, &dma_attr); 120608057504Sxy150489 break; 120708057504Sxy150489 default: 120808057504Sxy150489 ASSERT(B_FALSE); 120908057504Sxy150489 break; 121008057504Sxy150489 } 121108057504Sxy150489 if (mystat != DDI_SUCCESS) { 121208057504Sxy150489 ASSERT(packet->tx_dma_handle != NULL); 121308057504Sxy150489 switch (e1000g_dma_type) { 121408057504Sxy150489 #ifdef __sparc 121508057504Sxy150489 case USE_DVMA: 121608057504Sxy150489 dvma_release(packet->tx_dma_handle); 121708057504Sxy150489 break; 121808057504Sxy150489 #endif 121908057504Sxy150489 case USE_DMA: 122008057504Sxy150489 ddi_dma_free_handle(&packet->tx_dma_handle); 122108057504Sxy150489 break; 122208057504Sxy150489 default: 122308057504Sxy150489 ASSERT(B_FALSE); 122408057504Sxy150489 break; 122508057504Sxy150489 } 122608057504Sxy150489 packet->tx_dma_handle = NULL; 122725f2d433Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL, 122808057504Sxy150489 "Allocate Tx buffer fail\n"); 122908057504Sxy150489 goto tx_pkt_fail; 123008057504Sxy150489 } 123108057504Sxy150489 123208057504Sxy150489 packet->dma_type = e1000g_dma_type; 123308057504Sxy150489 } /* for */ 123408057504Sxy150489 123508057504Sxy150489 return (DDI_SUCCESS); 123608057504Sxy150489 123708057504Sxy150489 tx_pkt_fail: 123808057504Sxy150489 e1000g_free_tx_packets(tx_ring); 123908057504Sxy150489 124008057504Sxy150489 return (DDI_FAILURE); 124108057504Sxy150489 } 124208057504Sxy150489 12433fb4efefSchangqing li - Sun Microsystems - Beijing China 12443fb4efefSchangqing li - Sun Microsystems - Beijing China int 12453fb4efefSchangqing li - Sun Microsystems - Beijing China e1000g_increase_rx_packets(e1000g_rx_data_t *rx_data) 12463fb4efefSchangqing li - Sun Microsystems - Beijing China { 12473fb4efefSchangqing li - Sun Microsystems - Beijing China int i; 12483fb4efefSchangqing li - Sun Microsystems - Beijing China p_rx_sw_packet_t packet; 12493fb4efefSchangqing li - Sun Microsystems - Beijing China p_rx_sw_packet_t cur, next; 12503fb4efefSchangqing li - Sun Microsystems - Beijing China struct e1000g *Adapter; 12513fb4efefSchangqing li - Sun Microsystems - Beijing China ddi_dma_attr_t dma_attr; 12523fb4efefSchangqing li - Sun Microsystems - Beijing China 12533fb4efefSchangqing li - Sun Microsystems - Beijing China Adapter = rx_data->rx_ring->adapter; 12543fb4efefSchangqing li - Sun Microsystems - Beijing China dma_attr = e1000g_buf_dma_attr; 12553fb4efefSchangqing li - Sun Microsystems - Beijing China dma_attr.dma_attr_align = Adapter->rx_buf_align; 12563fb4efefSchangqing li - Sun Microsystems - Beijing China cur = NULL; 12573fb4efefSchangqing li - Sun Microsystems - Beijing China 12583fb4efefSchangqing li - Sun Microsystems - Beijing China for (i = 0; i < RX_FREELIST_INCREASE_SIZE; i++) { 12593fb4efefSchangqing li - Sun Microsystems - Beijing China packet = e1000g_alloc_rx_sw_packet(rx_data, &dma_attr); 12603fb4efefSchangqing li - Sun Microsystems - Beijing China if (packet == NULL) 12613fb4efefSchangqing li - Sun Microsystems - Beijing China break; 12623fb4efefSchangqing li - Sun Microsystems - Beijing China packet->next = cur; 12633fb4efefSchangqing li - Sun Microsystems - Beijing China cur = packet; 12643fb4efefSchangqing li - Sun Microsystems - Beijing China } 12653fb4efefSchangqing li - Sun Microsystems - Beijing China Adapter->rx_freelist_num += i; 12663fb4efefSchangqing li - Sun Microsystems - Beijing China rx_data->avail_freepkt += i; 12673fb4efefSchangqing li - Sun Microsystems - Beijing China 12683fb4efefSchangqing li - Sun Microsystems - Beijing China while (cur != NULL) { 12693fb4efefSchangqing li - Sun Microsystems - Beijing China QUEUE_PUSH_TAIL(&rx_data->free_list, &cur->Link); 12703fb4efefSchangqing li - Sun Microsystems - Beijing China next = cur->next; 12713fb4efefSchangqing li - Sun Microsystems - Beijing China cur->next = rx_data->packet_area; 12723fb4efefSchangqing li - Sun Microsystems - Beijing China rx_data->packet_area = cur; 12733fb4efefSchangqing li - Sun Microsystems - Beijing China 12743fb4efefSchangqing li - Sun Microsystems - Beijing China cur = next; 12753fb4efefSchangqing li - Sun Microsystems - Beijing China } 12763fb4efefSchangqing li - Sun Microsystems - Beijing China 12773fb4efefSchangqing li - Sun Microsystems - Beijing China return (DDI_SUCCESS); 12783fb4efefSchangqing li - Sun Microsystems - Beijing China } 12793fb4efefSchangqing li - Sun Microsystems - Beijing China 12803fb4efefSchangqing li - Sun Microsystems - Beijing China 128108057504Sxy150489 static int 128254e0d7a5SMiles Xu, Sun Microsystems e1000g_alloc_rx_packets(e1000g_rx_data_t *rx_data) 128308057504Sxy150489 { 128408057504Sxy150489 int i; 128525f2d433Sxy150489 p_rx_sw_packet_t packet; 128608057504Sxy150489 struct e1000g *Adapter; 128708057504Sxy150489 uint32_t packet_num; 128825f2d433Sxy150489 ddi_dma_attr_t dma_attr; 128908057504Sxy150489 129054e0d7a5SMiles Xu, Sun Microsystems Adapter = rx_data->rx_ring->adapter; 129125f2d433Sxy150489 dma_attr = e1000g_buf_dma_attr; 129225f2d433Sxy150489 dma_attr.dma_attr_align = Adapter->rx_buf_align; 1293592a4d85Scc210113 129408057504Sxy150489 /* 129525f2d433Sxy150489 * Allocate memory for the rx_sw_packet structures. Each one of these 129608057504Sxy150489 * structures will contain a virtual and physical address to an actual 129725f2d433Sxy150489 * receive buffer in host memory. Since we use one rx_sw_packet per 129825f2d433Sxy150489 * received packet, the maximum number of rx_sw_packet that we'll 129954e0d7a5SMiles Xu, Sun Microsystems * need is equal to the number of receive descriptors plus the freelist 130054e0d7a5SMiles Xu, Sun Microsystems * size. 130108057504Sxy150489 */ 13023fb4efefSchangqing li - Sun Microsystems - Beijing China packet_num = Adapter->rx_desc_num + RX_FREELIST_INCREASE_SIZE; 130354e0d7a5SMiles Xu, Sun Microsystems rx_data->packet_area = NULL; 130408057504Sxy150489 130508057504Sxy150489 for (i = 0; i < packet_num; i++) { 130654e0d7a5SMiles Xu, Sun Microsystems packet = e1000g_alloc_rx_sw_packet(rx_data, &dma_attr); 130708057504Sxy150489 if (packet == NULL) 130808057504Sxy150489 goto rx_pkt_fail; 130908057504Sxy150489 131054e0d7a5SMiles Xu, Sun Microsystems packet->next = rx_data->packet_area; 131154e0d7a5SMiles Xu, Sun Microsystems rx_data->packet_area = packet; 131208057504Sxy150489 } 131308057504Sxy150489 13143fb4efefSchangqing li - Sun Microsystems - Beijing China Adapter->rx_freelist_num = RX_FREELIST_INCREASE_SIZE; 131508057504Sxy150489 return (DDI_SUCCESS); 131608057504Sxy150489 131708057504Sxy150489 rx_pkt_fail: 13183fb4efefSchangqing li - Sun Microsystems - Beijing China e1000g_free_rx_packets(rx_data, B_TRUE); 131908057504Sxy150489 return (DDI_FAILURE); 132008057504Sxy150489 } 132108057504Sxy150489 13223fb4efefSchangqing li - Sun Microsystems - Beijing China 132325f2d433Sxy150489 static p_rx_sw_packet_t 132454e0d7a5SMiles Xu, Sun Microsystems e1000g_alloc_rx_sw_packet(e1000g_rx_data_t *rx_data, ddi_dma_attr_t *p_dma_attr) 132508057504Sxy150489 { 132608057504Sxy150489 int mystat; 132725f2d433Sxy150489 p_rx_sw_packet_t packet; 132808057504Sxy150489 dma_buffer_t *rx_buf; 132908057504Sxy150489 struct e1000g *Adapter; 133008057504Sxy150489 133154e0d7a5SMiles Xu, Sun Microsystems Adapter = rx_data->rx_ring->adapter; 133208057504Sxy150489 133325f2d433Sxy150489 packet = kmem_zalloc(sizeof (rx_sw_packet_t), KM_NOSLEEP); 133408057504Sxy150489 if (packet == NULL) { 133525f2d433Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL, 133608057504Sxy150489 "Cound not allocate memory for Rx SwPacket\n"); 133708057504Sxy150489 return (NULL); 133808057504Sxy150489 } 133908057504Sxy150489 134008057504Sxy150489 rx_buf = packet->rx_buf; 134108057504Sxy150489 134208057504Sxy150489 switch (e1000g_dma_type) { 134308057504Sxy150489 #ifdef __sparc 134408057504Sxy150489 case USE_DVMA: 134508057504Sxy150489 mystat = e1000g_alloc_dvma_buffer(Adapter, 134625f2d433Sxy150489 rx_buf, Adapter->rx_buffer_size); 134708057504Sxy150489 break; 134808057504Sxy150489 #endif 134908057504Sxy150489 case USE_DMA: 13503d15c084Schenlu chen - Sun Microsystems - Beijing China if (Adapter->mem_workaround_82546 && 13513d15c084Schenlu chen - Sun Microsystems - Beijing China ((Adapter->shared.mac.type == e1000_82545) || 1352ede5269eSchenlu chen - Sun Microsystems - Beijing China (Adapter->shared.mac.type == e1000_82546) || 13533d15c084Schenlu chen - Sun Microsystems - Beijing China (Adapter->shared.mac.type == e1000_82546_rev_3))) { 1354ede5269eSchenlu chen - Sun Microsystems - Beijing China mystat = e1000g_alloc_dma_buffer_82546(Adapter, 1355ede5269eSchenlu chen - Sun Microsystems - Beijing China rx_buf, Adapter->rx_buffer_size, p_dma_attr); 1356ede5269eSchenlu chen - Sun Microsystems - Beijing China } else { 135708057504Sxy150489 mystat = e1000g_alloc_dma_buffer(Adapter, 135825f2d433Sxy150489 rx_buf, Adapter->rx_buffer_size, p_dma_attr); 1359ede5269eSchenlu chen - Sun Microsystems - Beijing China } 136008057504Sxy150489 break; 136108057504Sxy150489 default: 136208057504Sxy150489 ASSERT(B_FALSE); 136308057504Sxy150489 break; 136408057504Sxy150489 } 136508057504Sxy150489 136608057504Sxy150489 if (mystat != DDI_SUCCESS) { 136708057504Sxy150489 if (packet != NULL) 136825f2d433Sxy150489 kmem_free(packet, sizeof (rx_sw_packet_t)); 136908057504Sxy150489 137025f2d433Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL, 137108057504Sxy150489 "Failed to allocate Rx buffer\n"); 137208057504Sxy150489 return (NULL); 137308057504Sxy150489 } 137408057504Sxy150489 137508057504Sxy150489 rx_buf->size -= E1000G_IPALIGNROOM; 137608057504Sxy150489 rx_buf->address += E1000G_IPALIGNROOM; 137708057504Sxy150489 rx_buf->dma_address += E1000G_IPALIGNROOM; 137808057504Sxy150489 137954e0d7a5SMiles Xu, Sun Microsystems packet->rx_data = (caddr_t)rx_data; 138008057504Sxy150489 packet->free_rtn.free_func = e1000g_rxfree_func; 138108057504Sxy150489 packet->free_rtn.free_arg = (char *)packet; 138208057504Sxy150489 /* 138308057504Sxy150489 * esballoc is changed to desballoc which 138408057504Sxy150489 * is undocumented call but as per sun, 138508057504Sxy150489 * we can use it. It gives better efficiency. 138608057504Sxy150489 */ 138708057504Sxy150489 packet->mp = desballoc((unsigned char *) 138846ebaa55SMiles Xu, Sun Microsystems rx_buf->address, 138946ebaa55SMiles Xu, Sun Microsystems rx_buf->size, 139008057504Sxy150489 BPRI_MED, &packet->free_rtn); 139108057504Sxy150489 139208057504Sxy150489 packet->dma_type = e1000g_dma_type; 139354e0d7a5SMiles Xu, Sun Microsystems packet->ref_cnt = 1; 139408057504Sxy150489 139508057504Sxy150489 return (packet); 139608057504Sxy150489 } 139708057504Sxy150489 139808057504Sxy150489 void 139954e0d7a5SMiles Xu, Sun Microsystems e1000g_free_rx_sw_packet(p_rx_sw_packet_t packet, boolean_t full_release) 140008057504Sxy150489 { 140108057504Sxy150489 dma_buffer_t *rx_buf; 140208057504Sxy150489 140308057504Sxy150489 if (packet->mp != NULL) { 140408057504Sxy150489 freemsg(packet->mp); 140508057504Sxy150489 packet->mp = NULL; 140608057504Sxy150489 } 140708057504Sxy150489 140808057504Sxy150489 rx_buf = packet->rx_buf; 140908057504Sxy150489 141008057504Sxy150489 switch (packet->dma_type) { 141108057504Sxy150489 #ifdef __sparc 141208057504Sxy150489 case USE_DVMA: 141354e0d7a5SMiles Xu, Sun Microsystems if (rx_buf->address != NULL) { 141454e0d7a5SMiles Xu, Sun Microsystems rx_buf->size += E1000G_IPALIGNROOM; 141554e0d7a5SMiles Xu, Sun Microsystems rx_buf->address -= E1000G_IPALIGNROOM; 141654e0d7a5SMiles Xu, Sun Microsystems } 141708057504Sxy150489 e1000g_free_dvma_buffer(rx_buf); 141808057504Sxy150489 break; 141908057504Sxy150489 #endif 142008057504Sxy150489 case USE_DMA: 142108057504Sxy150489 e1000g_free_dma_buffer(rx_buf); 142208057504Sxy150489 break; 142308057504Sxy150489 default: 142408057504Sxy150489 break; 142508057504Sxy150489 } 142608057504Sxy150489 142708057504Sxy150489 packet->dma_type = USE_NONE; 142808057504Sxy150489 142954e0d7a5SMiles Xu, Sun Microsystems if (!full_release) 143054e0d7a5SMiles Xu, Sun Microsystems return; 143154e0d7a5SMiles Xu, Sun Microsystems 143225f2d433Sxy150489 kmem_free(packet, sizeof (rx_sw_packet_t)); 143308057504Sxy150489 } 143408057504Sxy150489 143508057504Sxy150489 static void 14363fb4efefSchangqing li - Sun Microsystems - Beijing China e1000g_free_rx_packets(e1000g_rx_data_t *rx_data, boolean_t full_release) 143708057504Sxy150489 { 143854e0d7a5SMiles Xu, Sun Microsystems p_rx_sw_packet_t packet, next_packet; 143954e0d7a5SMiles Xu, Sun Microsystems uint32_t ref_cnt; 144008057504Sxy150489 144154e0d7a5SMiles Xu, Sun Microsystems mutex_enter(&e1000g_rx_detach_lock); 144208057504Sxy150489 144354e0d7a5SMiles Xu, Sun Microsystems packet = rx_data->packet_area; 144454e0d7a5SMiles Xu, Sun Microsystems while (packet != NULL) { 144508057504Sxy150489 next_packet = packet->next; 144608057504Sxy150489 144754e0d7a5SMiles Xu, Sun Microsystems ref_cnt = atomic_dec_32_nv(&packet->ref_cnt); 144854e0d7a5SMiles Xu, Sun Microsystems if (ref_cnt > 0) { 144954e0d7a5SMiles Xu, Sun Microsystems atomic_inc_32(&rx_data->pending_count); 145054e0d7a5SMiles Xu, Sun Microsystems atomic_inc_32(&e1000g_mblks_pending); 14510f70fbf8Sxy150489 } else { 14523fb4efefSchangqing li - Sun Microsystems - Beijing China e1000g_free_rx_sw_packet(packet, full_release); 14530f70fbf8Sxy150489 } 145408057504Sxy150489 145554e0d7a5SMiles Xu, Sun Microsystems packet = next_packet; 145608057504Sxy150489 } 145754e0d7a5SMiles Xu, Sun Microsystems 1458*bcfab059SJosef 'Jeff' Sipek if (full_release) 1459*bcfab059SJosef 'Jeff' Sipek rx_data->packet_area = NULL; 1460*bcfab059SJosef 'Jeff' Sipek 146154e0d7a5SMiles Xu, Sun Microsystems mutex_exit(&e1000g_rx_detach_lock); 146208057504Sxy150489 } 146308057504Sxy150489 146454e0d7a5SMiles Xu, Sun Microsystems 146508057504Sxy150489 static void 146608057504Sxy150489 e1000g_free_tx_packets(e1000g_tx_ring_t *tx_ring) 146708057504Sxy150489 { 146808057504Sxy150489 int j; 146908057504Sxy150489 struct e1000g *Adapter; 147025f2d433Sxy150489 p_tx_sw_packet_t packet; 147108057504Sxy150489 dma_buffer_t *tx_buf; 147208057504Sxy150489 147308057504Sxy150489 Adapter = tx_ring->adapter; 147408057504Sxy150489 147508057504Sxy150489 for (j = 0, packet = tx_ring->packet_area; 147625f2d433Sxy150489 j < Adapter->tx_freelist_num; j++, packet++) { 147708057504Sxy150489 147808057504Sxy150489 if (packet == NULL) 147908057504Sxy150489 break; 148008057504Sxy150489 148108057504Sxy150489 /* Free the Tx DMA handle for dynamical binding */ 148208057504Sxy150489 if (packet->tx_dma_handle != NULL) { 148308057504Sxy150489 switch (packet->dma_type) { 148408057504Sxy150489 #ifdef __sparc 148508057504Sxy150489 case USE_DVMA: 148608057504Sxy150489 dvma_release(packet->tx_dma_handle); 148708057504Sxy150489 break; 148808057504Sxy150489 #endif 148908057504Sxy150489 case USE_DMA: 149008057504Sxy150489 ddi_dma_free_handle(&packet->tx_dma_handle); 149108057504Sxy150489 break; 149208057504Sxy150489 default: 149308057504Sxy150489 ASSERT(B_FALSE); 149408057504Sxy150489 break; 149508057504Sxy150489 } 149608057504Sxy150489 packet->tx_dma_handle = NULL; 149708057504Sxy150489 } else { 149808057504Sxy150489 /* 149908057504Sxy150489 * If the dma handle is NULL, then we don't 150008057504Sxy150489 * need to check the packets left. For they 150108057504Sxy150489 * have not been initialized or have been freed. 150208057504Sxy150489 */ 150308057504Sxy150489 break; 150408057504Sxy150489 } 150508057504Sxy150489 150608057504Sxy150489 tx_buf = packet->tx_buf; 150708057504Sxy150489 150808057504Sxy150489 switch (packet->dma_type) { 150908057504Sxy150489 #ifdef __sparc 151008057504Sxy150489 case USE_DVMA: 151108057504Sxy150489 e1000g_free_dvma_buffer(tx_buf); 151208057504Sxy150489 break; 151308057504Sxy150489 #endif 151408057504Sxy150489 case USE_DMA: 151508057504Sxy150489 e1000g_free_dma_buffer(tx_buf); 151608057504Sxy150489 break; 151708057504Sxy150489 default: 151808057504Sxy150489 ASSERT(B_FALSE); 151908057504Sxy150489 break; 152008057504Sxy150489 } 152108057504Sxy150489 152208057504Sxy150489 packet->dma_type = USE_NONE; 152308057504Sxy150489 } 152408057504Sxy150489 if (tx_ring->packet_area != NULL) { 152508057504Sxy150489 kmem_free(tx_ring->packet_area, TX_SW_PKT_AREA_SZ); 152608057504Sxy150489 tx_ring->packet_area = NULL; 152708057504Sxy150489 } 152808057504Sxy150489 } 152908057504Sxy150489 153008057504Sxy150489 /* 153125f2d433Sxy150489 * e1000g_release_dma_resources - release allocated DMA resources 153225f2d433Sxy150489 * 153325f2d433Sxy150489 * This function releases any pending buffers that has been 153425f2d433Sxy150489 * previously allocated 153508057504Sxy150489 */ 153608057504Sxy150489 void 153725f2d433Sxy150489 e1000g_release_dma_resources(struct e1000g *Adapter) 153808057504Sxy150489 { 153925f2d433Sxy150489 e1000g_free_descriptors(Adapter); 154025f2d433Sxy150489 e1000g_free_packets(Adapter); 154108057504Sxy150489 } 15429b6541b3Sgl147354 1543fe62dec3SChen-Liang Xu /* ARGSUSED */ 15449b6541b3Sgl147354 void 1545837c1ac4SStephen Hanson e1000g_set_fma_flags(int dma_flag) 15469b6541b3Sgl147354 { 15479b6541b3Sgl147354 if (dma_flag) { 15489b6541b3Sgl147354 e1000g_tx_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 15499b6541b3Sgl147354 e1000g_buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 15509b6541b3Sgl147354 e1000g_desc_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 15519b6541b3Sgl147354 } else { 15529b6541b3Sgl147354 e1000g_tx_dma_attr.dma_attr_flags = 0; 15539b6541b3Sgl147354 e1000g_buf_dma_attr.dma_attr_flags = 0; 15549b6541b3Sgl147354 e1000g_desc_dma_attr.dma_attr_flags = 0; 15559b6541b3Sgl147354 } 15569b6541b3Sgl147354 } 1557