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
e1000g_alloc_dma_resources(struct e1000g * Adapter)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
e1000g_alloc_descriptors(struct e1000g * Adapter)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
e1000g_free_descriptors(struct e1000g * Adapter)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
e1000g_alloc_tx_descriptors(e1000g_tx_ring_t * tx_ring)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
e1000g_alloc_rx_descriptors(e1000g_rx_data_t * rx_data)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
e1000g_free_rx_descriptors(e1000g_rx_data_t * rx_data)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
e1000g_free_tx_descriptors(e1000g_tx_ring_t * tx_ring)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
e1000g_alloc_packets(struct e1000g * Adapter)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
e1000g_free_packets(struct e1000g * Adapter)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
e1000g_alloc_dvma_buffer(struct e1000g * Adapter,dma_buffer_t * buf,size_t size)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
e1000g_free_dvma_buffer(dma_buffer_t * buf)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
e1000g_alloc_dma_buffer(struct e1000g * Adapter,dma_buffer_t * buf,size_t size,ddi_dma_attr_t * p_dma_attr)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
e1000g_alloc_dma_buffer_82546(struct e1000g * Adapter,dma_buffer_t * buf,size_t size,ddi_dma_attr_t * p_dma_attr)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
e1000g_dma_mem_alloc_82546(dma_buffer_t * buf,size_t size,size_t * len)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
e1000g_cross_64k_bound(void * addr,uintptr_t len)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
e1000g_free_dma_buffer(dma_buffer_t * buf)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
e1000g_alloc_tx_packets(e1000g_tx_ring_t * tx_ring)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
e1000g_increase_rx_packets(e1000g_rx_data_t * rx_data)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
e1000g_alloc_rx_packets(e1000g_rx_data_t * rx_data)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
e1000g_alloc_rx_sw_packet(e1000g_rx_data_t * rx_data,ddi_dma_attr_t * p_dma_attr)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
e1000g_free_rx_sw_packet(p_rx_sw_packet_t packet,boolean_t full_release)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
e1000g_free_rx_packets(e1000g_rx_data_t * rx_data,boolean_t full_release)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
e1000g_free_tx_packets(e1000g_tx_ring_t * tx_ring)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
e1000g_release_dma_resources(struct e1000g * Adapter)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
e1000g_set_fma_flags(int dma_flag)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