13526Sxy150489 /*
23526Sxy150489 * This file is provided under a CDDLv1 license. When using or
33526Sxy150489 * redistributing this file, you may do so under this license.
43526Sxy150489 * In redistributing this file this license must be included
53526Sxy150489 * and no other modification of this header file is permitted.
63526Sxy150489 *
73526Sxy150489 * CDDL LICENSE SUMMARY
83526Sxy150489 *
98850SMin.Xu@Sun.COM * Copyright(c) 1999 - 2009 Intel Corporation. All rights reserved.
103526Sxy150489 *
113526Sxy150489 * The contents of this file are subject to the terms of Version
123526Sxy150489 * 1.0 of the Common Development and Distribution License (the "License").
133526Sxy150489 *
143526Sxy150489 * You should have received a copy of the License with this software.
153526Sxy150489 * You can obtain a copy of the License at
163526Sxy150489 * http://www.opensolaris.org/os/licensing.
173526Sxy150489 * See the License for the specific language governing permissions
183526Sxy150489 * and limitations under the License.
193526Sxy150489 */
203526Sxy150489
213526Sxy150489 /*
22*12853SChangqing.Li@Sun.COM * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
233526Sxy150489 */
243526Sxy150489
253526Sxy150489 /*
263526Sxy150489 * **********************************************************************
273526Sxy150489 * Module Name: *
284919Sxy150489 * e1000g_alloc.c *
293526Sxy150489 * *
303526Sxy150489 * Abstract: *
314919Sxy150489 * This file contains some routines that take care of *
324919Sxy150489 * memory allocation for descriptors and buffers. *
333526Sxy150489 * *
343526Sxy150489 * **********************************************************************
353526Sxy150489 */
363526Sxy150489
373526Sxy150489 #include "e1000g_sw.h"
383526Sxy150489 #include "e1000g_debug.h"
393526Sxy150489
403526Sxy150489 #define TX_SW_PKT_AREA_SZ \
414919Sxy150489 (sizeof (tx_sw_packet_t) * Adapter->tx_freelist_num)
423526Sxy150489
433526Sxy150489 static int e1000g_alloc_tx_descriptors(e1000g_tx_ring_t *);
448850SMin.Xu@Sun.COM static int e1000g_alloc_rx_descriptors(e1000g_rx_data_t *);
453526Sxy150489 static void e1000g_free_tx_descriptors(e1000g_tx_ring_t *);
468850SMin.Xu@Sun.COM static void e1000g_free_rx_descriptors(e1000g_rx_data_t *);
473526Sxy150489 static int e1000g_alloc_tx_packets(e1000g_tx_ring_t *);
488850SMin.Xu@Sun.COM static int e1000g_alloc_rx_packets(e1000g_rx_data_t *);
493526Sxy150489 static void e1000g_free_tx_packets(e1000g_tx_ring_t *);
50*12853SChangqing.Li@Sun.COM static void e1000g_free_rx_packets(e1000g_rx_data_t *, boolean_t);
514919Sxy150489 static int e1000g_alloc_dma_buffer(struct e1000g *,
524919Sxy150489 dma_buffer_t *, size_t, ddi_dma_attr_t *p_dma_attr);
538178SChenlu.Chen@Sun.COM
548178SChenlu.Chen@Sun.COM /*
558178SChenlu.Chen@Sun.COM * In order to avoid address error crossing 64KB boundary
568178SChenlu.Chen@Sun.COM * during PCI-X packets receving, e1000g_alloc_dma_buffer_82546
578178SChenlu.Chen@Sun.COM * is used by some necessary adapter types.
588178SChenlu.Chen@Sun.COM */
598178SChenlu.Chen@Sun.COM static int e1000g_alloc_dma_buffer_82546(struct e1000g *,
608178SChenlu.Chen@Sun.COM dma_buffer_t *, size_t, ddi_dma_attr_t *p_dma_attr);
618178SChenlu.Chen@Sun.COM static int e1000g_dma_mem_alloc_82546(dma_buffer_t *buf,
628178SChenlu.Chen@Sun.COM size_t size, size_t *len);
638178SChenlu.Chen@Sun.COM static boolean_t e1000g_cross_64k_bound(void *, uintptr_t);
648178SChenlu.Chen@Sun.COM
653526Sxy150489 static void e1000g_free_dma_buffer(dma_buffer_t *);
663526Sxy150489 #ifdef __sparc
673526Sxy150489 static int e1000g_alloc_dvma_buffer(struct e1000g *, dma_buffer_t *, size_t);
683526Sxy150489 static void e1000g_free_dvma_buffer(dma_buffer_t *);
693526Sxy150489 #endif
703526Sxy150489 static int e1000g_alloc_descriptors(struct e1000g *Adapter);
714919Sxy150489 static void e1000g_free_descriptors(struct e1000g *Adapter);
723526Sxy150489 static int e1000g_alloc_packets(struct e1000g *Adapter);
734919Sxy150489 static void e1000g_free_packets(struct e1000g *Adapter);
748850SMin.Xu@Sun.COM static p_rx_sw_packet_t e1000g_alloc_rx_sw_packet(e1000g_rx_data_t *,
754919Sxy150489 ddi_dma_attr_t *p_dma_attr);
764919Sxy150489
774919Sxy150489 /* DMA access attributes for descriptors <Little Endian> */
784919Sxy150489 static ddi_device_acc_attr_t e1000g_desc_acc_attr = {
794919Sxy150489 DDI_DEVICE_ATTR_V0,
804919Sxy150489 DDI_STRUCTURE_LE_ACC,
8111236SStephen.Hanson@Sun.COM DDI_STRICTORDER_ACC
824919Sxy150489 };
834919Sxy150489
844919Sxy150489 /* DMA access attributes for DMA buffers */
854919Sxy150489 #ifdef __sparc
864919Sxy150489 static ddi_device_acc_attr_t e1000g_buf_acc_attr = {
874919Sxy150489 DDI_DEVICE_ATTR_V0,
884919Sxy150489 DDI_STRUCTURE_BE_ACC,
894919Sxy150489 DDI_STRICTORDER_ACC,
904919Sxy150489 };
914919Sxy150489 #else
924919Sxy150489 static ddi_device_acc_attr_t e1000g_buf_acc_attr = {
934919Sxy150489 DDI_DEVICE_ATTR_V0,
944919Sxy150489 DDI_STRUCTURE_LE_ACC,
954919Sxy150489 DDI_STRICTORDER_ACC,
964919Sxy150489 };
974919Sxy150489 #endif
984919Sxy150489
994919Sxy150489 /* DMA attributes for tx mblk buffers */
1004919Sxy150489 static ddi_dma_attr_t e1000g_tx_dma_attr = {
1014919Sxy150489 DMA_ATTR_V0, /* version of this structure */
1024919Sxy150489 0, /* lowest usable address */
1034919Sxy150489 0xffffffffffffffffULL, /* highest usable address */
1044919Sxy150489 0x7fffffff, /* maximum DMAable byte count */
1054919Sxy150489 1, /* alignment in bytes */
1064919Sxy150489 0x7ff, /* burst sizes (any?) */
1074919Sxy150489 1, /* minimum transfer */
1084919Sxy150489 0xffffffffU, /* maximum transfer */
1094919Sxy150489 0xffffffffffffffffULL, /* maximum segment length */
1107607STed.You@Sun.COM MAX_COOKIES, /* maximum number of segments */
1114919Sxy150489 1, /* granularity */
1125273Sgl147354 DDI_DMA_FLAGERR, /* dma_attr_flags */
1134919Sxy150489 };
1144919Sxy150489
1154919Sxy150489 /* DMA attributes for pre-allocated rx/tx buffers */
1164919Sxy150489 static ddi_dma_attr_t e1000g_buf_dma_attr = {
1174919Sxy150489 DMA_ATTR_V0, /* version of this structure */
1184919Sxy150489 0, /* lowest usable address */
1194919Sxy150489 0xffffffffffffffffULL, /* highest usable address */
1204919Sxy150489 0x7fffffff, /* maximum DMAable byte count */
1214919Sxy150489 1, /* alignment in bytes */
1224919Sxy150489 0x7ff, /* burst sizes (any?) */
1234919Sxy150489 1, /* minimum transfer */
1244919Sxy150489 0xffffffffU, /* maximum transfer */
1254919Sxy150489 0xffffffffffffffffULL, /* maximum segment length */
1264919Sxy150489 1, /* maximum number of segments */
1274919Sxy150489 1, /* granularity */
1285273Sgl147354 DDI_DMA_FLAGERR, /* dma_attr_flags */
1294919Sxy150489 };
1304919Sxy150489
1314919Sxy150489 /* DMA attributes for rx/tx descriptors */
1324919Sxy150489 static ddi_dma_attr_t e1000g_desc_dma_attr = {
1334919Sxy150489 DMA_ATTR_V0, /* version of this structure */
1344919Sxy150489 0, /* lowest usable address */
1354919Sxy150489 0xffffffffffffffffULL, /* highest usable address */
1364919Sxy150489 0x7fffffff, /* maximum DMAable byte count */
1378178SChenlu.Chen@Sun.COM E1000_MDALIGN, /* default alignment is 4k but can be changed */
1384919Sxy150489 0x7ff, /* burst sizes (any?) */
1394919Sxy150489 1, /* minimum transfer */
1404919Sxy150489 0xffffffffU, /* maximum transfer */
1414919Sxy150489 0xffffffffffffffffULL, /* maximum segment length */
1424919Sxy150489 1, /* maximum number of segments */
1434919Sxy150489 1, /* granularity */
1445273Sgl147354 DDI_DMA_FLAGERR, /* dma_attr_flags */
1454919Sxy150489 };
1463526Sxy150489
1473526Sxy150489 #ifdef __sparc
1483526Sxy150489 static ddi_dma_lim_t e1000g_dma_limits = {
1493526Sxy150489 (uint_t)0, /* dlim_addr_lo */
1503526Sxy150489 (uint_t)0xffffffff, /* dlim_addr_hi */
1513526Sxy150489 (uint_t)0xffffffff, /* dlim_cntr_max */
1523526Sxy150489 (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */
1533526Sxy150489 0x1, /* dlim_minxfer */
1543526Sxy150489 1024 /* dlim_speed */
1553526Sxy150489 };
1563526Sxy150489 #endif
1573526Sxy150489
1583526Sxy150489 #ifdef __sparc
1593526Sxy150489 static dma_type_t e1000g_dma_type = USE_DVMA;
1603526Sxy150489 #else
1613526Sxy150489 static dma_type_t e1000g_dma_type = USE_DMA;
1623526Sxy150489 #endif
1633526Sxy150489
1643526Sxy150489 extern krwlock_t e1000g_dma_type_lock;
1653526Sxy150489
1664919Sxy150489
1673526Sxy150489 int
e1000g_alloc_dma_resources(struct e1000g * Adapter)1683526Sxy150489 e1000g_alloc_dma_resources(struct e1000g *Adapter)
1693526Sxy150489 {
1704919Sxy150489 int result;
1714919Sxy150489
1724919Sxy150489 result = DDI_FAILURE;
1733526Sxy150489
1744919Sxy150489 while ((result != DDI_SUCCESS) &&
1754919Sxy150489 (Adapter->tx_desc_num >= MIN_NUM_TX_DESCRIPTOR) &&
1764919Sxy150489 (Adapter->rx_desc_num >= MIN_NUM_RX_DESCRIPTOR) &&
177*12853SChangqing.Li@Sun.COM (Adapter->tx_freelist_num >= MIN_NUM_TX_FREELIST)) {
1784919Sxy150489
1794919Sxy150489 result = e1000g_alloc_descriptors(Adapter);
1804919Sxy150489
1814919Sxy150489 if (result == DDI_SUCCESS) {
1824919Sxy150489 result = e1000g_alloc_packets(Adapter);
1834919Sxy150489
1844919Sxy150489 if (result != DDI_SUCCESS)
1854919Sxy150489 e1000g_free_descriptors(Adapter);
1864919Sxy150489 }
1873526Sxy150489
1884919Sxy150489 /*
1894919Sxy150489 * If the allocation fails due to resource shortage,
1904919Sxy150489 * we'll reduce the numbers of descriptors/buffers by
1914919Sxy150489 * half, and try the allocation again.
1924919Sxy150489 */
1934919Sxy150489 if (result != DDI_SUCCESS) {
1944919Sxy150489 /*
1954919Sxy150489 * We must ensure the number of descriptors
1964919Sxy150489 * is always a multiple of 8.
1974919Sxy150489 */
1984919Sxy150489 Adapter->tx_desc_num =
1994919Sxy150489 (Adapter->tx_desc_num >> 4) << 3;
2004919Sxy150489 Adapter->rx_desc_num =
2014919Sxy150489 (Adapter->rx_desc_num >> 4) << 3;
2023526Sxy150489
2034919Sxy150489 Adapter->tx_freelist_num >>= 1;
2044919Sxy150489 }
2053526Sxy150489 }
2063526Sxy150489
2074919Sxy150489 return (result);
2083526Sxy150489 }
2093526Sxy150489
2103526Sxy150489 /*
2114919Sxy150489 * e1000g_alloc_descriptors - allocate DMA buffers for descriptors
2124919Sxy150489 *
2134919Sxy150489 * This routine allocates neccesary DMA buffers for
2144919Sxy150489 * Transmit Descriptor Area
2154919Sxy150489 * Receive Descrpitor Area
2163526Sxy150489 */
2173526Sxy150489 static int
e1000g_alloc_descriptors(struct e1000g * Adapter)2183526Sxy150489 e1000g_alloc_descriptors(struct e1000g *Adapter)
2193526Sxy150489 {
2203526Sxy150489 int result;
2213526Sxy150489 e1000g_tx_ring_t *tx_ring;
2228850SMin.Xu@Sun.COM e1000g_rx_data_t *rx_data;
2233526Sxy150489
2248417SChenlu.Chen@Sun.COM if (Adapter->mem_workaround_82546 &&
2258417SChenlu.Chen@Sun.COM ((Adapter->shared.mac.type == e1000_82545) ||
2268178SChenlu.Chen@Sun.COM (Adapter->shared.mac.type == e1000_82546) ||
2278417SChenlu.Chen@Sun.COM (Adapter->shared.mac.type == e1000_82546_rev_3))) {
2288178SChenlu.Chen@Sun.COM /* Align on a 64k boundary for these adapter types */
2298178SChenlu.Chen@Sun.COM Adapter->desc_align = E1000_MDALIGN_82546;
2308178SChenlu.Chen@Sun.COM } else {
2318178SChenlu.Chen@Sun.COM /* Align on a 4k boundary for all other adapter types */
2328178SChenlu.Chen@Sun.COM Adapter->desc_align = E1000_MDALIGN;
2338178SChenlu.Chen@Sun.COM }
2348178SChenlu.Chen@Sun.COM
2353526Sxy150489 tx_ring = Adapter->tx_ring;
2363526Sxy150489
2373526Sxy150489 result = e1000g_alloc_tx_descriptors(tx_ring);
2383526Sxy150489 if (result != DDI_SUCCESS)
2393526Sxy150489 return (DDI_FAILURE);
2403526Sxy150489
2418850SMin.Xu@Sun.COM rx_data = Adapter->rx_ring->rx_data;
2423526Sxy150489
2438850SMin.Xu@Sun.COM result = e1000g_alloc_rx_descriptors(rx_data);
2443526Sxy150489 if (result != DDI_SUCCESS) {
2453526Sxy150489 e1000g_free_tx_descriptors(tx_ring);
2463526Sxy150489 return (DDI_FAILURE);
2473526Sxy150489 }
2483526Sxy150489
2493526Sxy150489 return (DDI_SUCCESS);
2503526Sxy150489 }
2513526Sxy150489
2524919Sxy150489 static void
e1000g_free_descriptors(struct e1000g * Adapter)2534919Sxy150489 e1000g_free_descriptors(struct e1000g *Adapter)
2544919Sxy150489 {
2554919Sxy150489 e1000g_tx_ring_t *tx_ring;
2568850SMin.Xu@Sun.COM e1000g_rx_data_t *rx_data;
2574919Sxy150489
2584919Sxy150489 tx_ring = Adapter->tx_ring;
2598850SMin.Xu@Sun.COM rx_data = Adapter->rx_ring->rx_data;
2604919Sxy150489
2614919Sxy150489 e1000g_free_tx_descriptors(tx_ring);
2628850SMin.Xu@Sun.COM e1000g_free_rx_descriptors(rx_data);
2634919Sxy150489 }
2644919Sxy150489
2653526Sxy150489 static int
e1000g_alloc_tx_descriptors(e1000g_tx_ring_t * tx_ring)2663526Sxy150489 e1000g_alloc_tx_descriptors(e1000g_tx_ring_t *tx_ring)
2673526Sxy150489 {
2683526Sxy150489 int mystat;
2693526Sxy150489 boolean_t alloc_flag;
2703526Sxy150489 size_t size;
2713526Sxy150489 size_t len;
2723526Sxy150489 uintptr_t templong;
2733526Sxy150489 uint_t cookie_count;
2743526Sxy150489 dev_info_t *devinfo;
2753526Sxy150489 ddi_dma_cookie_t cookie;
2763526Sxy150489 struct e1000g *Adapter;
2774919Sxy150489 ddi_dma_attr_t dma_attr;
2783526Sxy150489
2793526Sxy150489 Adapter = tx_ring->adapter;
2804919Sxy150489 devinfo = Adapter->dip;
2813526Sxy150489
2823526Sxy150489 alloc_flag = B_FALSE;
2834919Sxy150489 dma_attr = e1000g_desc_dma_attr;
2843526Sxy150489
2853526Sxy150489 /*
2863526Sxy150489 * Solaris 7 has a problem with allocating physically contiguous memory
2873526Sxy150489 * that is aligned on a 4K boundary. The transmit and rx descriptors
2883526Sxy150489 * need to aligned on a 4kbyte boundary. We first try to allocate the
2893526Sxy150489 * memory with DMA attributes set to 4K alignment and also no scatter/
2903526Sxy150489 * gather mechanism specified. In most cases, this does not allocate
2913526Sxy150489 * memory aligned at a 4Kbyte boundary. We then try asking for memory
2923526Sxy150489 * aligned on 4K boundary with scatter/gather set to 2. This works when
2933526Sxy150489 * the amount of memory is less than 4k i.e a page size. If neither of
2943526Sxy150489 * these options work or if the number of descriptors is greater than
2953526Sxy150489 * 4K, ie more than 256 descriptors, we allocate 4k extra memory and
2963526Sxy150489 * and then align the memory at a 4k boundary.
2973526Sxy150489 */
2984919Sxy150489 size = sizeof (struct e1000_tx_desc) * Adapter->tx_desc_num;
2993526Sxy150489
3003526Sxy150489 /*
3013526Sxy150489 * Memory allocation for the transmit buffer descriptors.
3023526Sxy150489 */
3034919Sxy150489 dma_attr.dma_attr_sgllen = 1;
3048178SChenlu.Chen@Sun.COM dma_attr.dma_attr_align = Adapter->desc_align;
3053526Sxy150489
3063526Sxy150489 /*
3073526Sxy150489 * Allocate a new DMA handle for the transmit descriptor
3083526Sxy150489 * memory area.
3093526Sxy150489 */
3104919Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, &dma_attr,
3113526Sxy150489 DDI_DMA_DONTWAIT, 0,
3123526Sxy150489 &tx_ring->tbd_dma_handle);
3133526Sxy150489
3143526Sxy150489 if (mystat != DDI_SUCCESS) {
3154919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
3163526Sxy150489 "Could not allocate tbd dma handle: %d", mystat);
3173526Sxy150489 tx_ring->tbd_dma_handle = NULL;
3183526Sxy150489 return (DDI_FAILURE);
3193526Sxy150489 }
3203526Sxy150489
3213526Sxy150489 /*
3223526Sxy150489 * Allocate memory to DMA data to and from the transmit
3233526Sxy150489 * descriptors.
3243526Sxy150489 */
3253526Sxy150489 mystat = ddi_dma_mem_alloc(tx_ring->tbd_dma_handle,
3263526Sxy150489 size,
3274919Sxy150489 &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT,
3283526Sxy150489 DDI_DMA_DONTWAIT, 0,
3293526Sxy150489 (caddr_t *)&tx_ring->tbd_area,
3303526Sxy150489 &len, &tx_ring->tbd_acc_handle);
3313526Sxy150489
3323526Sxy150489 if ((mystat != DDI_SUCCESS) ||
3338178SChenlu.Chen@Sun.COM ((uintptr_t)tx_ring->tbd_area & (Adapter->desc_align - 1))) {
3343526Sxy150489 if (mystat == DDI_SUCCESS) {
3353526Sxy150489 ddi_dma_mem_free(&tx_ring->tbd_acc_handle);
3363526Sxy150489 tx_ring->tbd_acc_handle = NULL;
3373526Sxy150489 tx_ring->tbd_area = NULL;
3383526Sxy150489 }
3393526Sxy150489 if (tx_ring->tbd_dma_handle != NULL) {
3403526Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_dma_handle);
3413526Sxy150489 tx_ring->tbd_dma_handle = NULL;
3423526Sxy150489 }
3433526Sxy150489 alloc_flag = B_FALSE;
3443526Sxy150489 } else
3453526Sxy150489 alloc_flag = B_TRUE;
3463526Sxy150489
3473526Sxy150489 /*
3483526Sxy150489 * Initialize the entire transmit buffer descriptor area to zero
3493526Sxy150489 */
3503526Sxy150489 if (alloc_flag)
3513526Sxy150489 bzero(tx_ring->tbd_area, len);
3523526Sxy150489
3533526Sxy150489 /*
3543526Sxy150489 * If the previous DMA attributes setting could not give us contiguous
3553526Sxy150489 * memory or the number of descriptors is greater than the page size,
3568178SChenlu.Chen@Sun.COM * we allocate extra memory and then align it at appropriate boundary.
3573526Sxy150489 */
3583526Sxy150489 if (!alloc_flag) {
3598178SChenlu.Chen@Sun.COM size = size + Adapter->desc_align;
3603526Sxy150489
3613526Sxy150489 /*
3623526Sxy150489 * DMA attributes set to no scatter/gather and 16 bit alignment
3633526Sxy150489 */
3644919Sxy150489 dma_attr.dma_attr_align = 1;
3654919Sxy150489 dma_attr.dma_attr_sgllen = 1;
3663526Sxy150489
3673526Sxy150489 /*
3683526Sxy150489 * Allocate a new DMA handle for the transmit descriptor memory
3693526Sxy150489 * area.
3703526Sxy150489 */
3714919Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, &dma_attr,
3723526Sxy150489 DDI_DMA_DONTWAIT, 0,
3733526Sxy150489 &tx_ring->tbd_dma_handle);
3743526Sxy150489
3753526Sxy150489 if (mystat != DDI_SUCCESS) {
3764919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
3773526Sxy150489 "Could not re-allocate tbd dma handle: %d", mystat);
3783526Sxy150489 tx_ring->tbd_dma_handle = NULL;
3793526Sxy150489 return (DDI_FAILURE);
3803526Sxy150489 }
3813526Sxy150489
3823526Sxy150489 /*
3833526Sxy150489 * Allocate memory to DMA data to and from the transmit
3843526Sxy150489 * descriptors.
3853526Sxy150489 */
3863526Sxy150489 mystat = ddi_dma_mem_alloc(tx_ring->tbd_dma_handle,
3873526Sxy150489 size,
3884919Sxy150489 &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT,
3893526Sxy150489 DDI_DMA_DONTWAIT, 0,
3903526Sxy150489 (caddr_t *)&tx_ring->tbd_area,
3913526Sxy150489 &len, &tx_ring->tbd_acc_handle);
3923526Sxy150489
3933526Sxy150489 if (mystat != DDI_SUCCESS) {
3944919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
3953526Sxy150489 "Could not allocate tbd dma memory: %d", mystat);
3963526Sxy150489 tx_ring->tbd_acc_handle = NULL;
3973526Sxy150489 tx_ring->tbd_area = NULL;
3983526Sxy150489 if (tx_ring->tbd_dma_handle != NULL) {
3993526Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_dma_handle);
4003526Sxy150489 tx_ring->tbd_dma_handle = NULL;
4013526Sxy150489 }
4023526Sxy150489 return (DDI_FAILURE);
4033526Sxy150489 } else
4043526Sxy150489 alloc_flag = B_TRUE;
4053526Sxy150489
4063526Sxy150489 /*
4073526Sxy150489 * Initialize the entire transmit buffer descriptor area to zero
4083526Sxy150489 */
4093526Sxy150489 bzero(tx_ring->tbd_area, len);
4103526Sxy150489 /*
4113526Sxy150489 * Memory has been allocated with the ddi_dma_mem_alloc call,
4128178SChenlu.Chen@Sun.COM * but has not been aligned.
4138178SChenlu.Chen@Sun.COM * We now align it on the appropriate boundary.
4143526Sxy150489 */
4158178SChenlu.Chen@Sun.COM templong = P2NPHASE((uintptr_t)tx_ring->tbd_area,
4168178SChenlu.Chen@Sun.COM Adapter->desc_align);
4173526Sxy150489 len = size - templong;
4183526Sxy150489 templong += (uintptr_t)tx_ring->tbd_area;
4193526Sxy150489 tx_ring->tbd_area = (struct e1000_tx_desc *)templong;
4203526Sxy150489 } /* alignment workaround */
4213526Sxy150489
4223526Sxy150489 /*
4233526Sxy150489 * Transmit buffer descriptor memory allocation succeeded
4243526Sxy150489 */
4253526Sxy150489 ASSERT(alloc_flag);
4263526Sxy150489
4273526Sxy150489 /*
4283526Sxy150489 * Allocates DMA resources for the memory that was allocated by
4293526Sxy150489 * the ddi_dma_mem_alloc call. The DMA resources then get bound to the
4303526Sxy150489 * the memory address
4313526Sxy150489 */
4323526Sxy150489 mystat = ddi_dma_addr_bind_handle(tx_ring->tbd_dma_handle,
4333526Sxy150489 (struct as *)NULL, (caddr_t)tx_ring->tbd_area,
4343526Sxy150489 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
4354919Sxy150489 DDI_DMA_DONTWAIT, 0, &cookie, &cookie_count);
4363526Sxy150489
4373526Sxy150489 if (mystat != DDI_SUCCESS) {
4384919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
4393526Sxy150489 "Could not bind tbd dma resource: %d", mystat);
4403526Sxy150489 if (tx_ring->tbd_acc_handle != NULL) {
4413526Sxy150489 ddi_dma_mem_free(&tx_ring->tbd_acc_handle);
4423526Sxy150489 tx_ring->tbd_acc_handle = NULL;
4433526Sxy150489 tx_ring->tbd_area = NULL;
4443526Sxy150489 }
4453526Sxy150489 if (tx_ring->tbd_dma_handle != NULL) {
4463526Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_dma_handle);
4473526Sxy150489 tx_ring->tbd_dma_handle = NULL;
4483526Sxy150489 }
4493526Sxy150489 return (DDI_FAILURE);
4503526Sxy150489 }
4513526Sxy150489
4523526Sxy150489 ASSERT(cookie_count == 1); /* 1 cookie */
4533526Sxy150489
4543526Sxy150489 if (cookie_count != 1) {
4554919Sxy150489 E1000G_DEBUGLOG_2(Adapter, E1000G_WARN_LEVEL,
4563526Sxy150489 "Could not bind tbd dma resource in a single frag. "
4573526Sxy150489 "Count - %d Len - %d", cookie_count, len);
4583526Sxy150489 e1000g_free_tx_descriptors(tx_ring);
4593526Sxy150489 return (DDI_FAILURE);
4603526Sxy150489 }
4613526Sxy150489
4623526Sxy150489 tx_ring->tbd_dma_addr = cookie.dmac_laddress;
4633526Sxy150489 tx_ring->tbd_first = tx_ring->tbd_area;
4643526Sxy150489 tx_ring->tbd_last = tx_ring->tbd_first +
4654919Sxy150489 (Adapter->tx_desc_num - 1);
4663526Sxy150489
4673526Sxy150489 return (DDI_SUCCESS);
4683526Sxy150489 }
4693526Sxy150489
4703526Sxy150489 static int
e1000g_alloc_rx_descriptors(e1000g_rx_data_t * rx_data)4718850SMin.Xu@Sun.COM e1000g_alloc_rx_descriptors(e1000g_rx_data_t *rx_data)
4723526Sxy150489 {
4733526Sxy150489 int mystat;
4743526Sxy150489 boolean_t alloc_flag;
4753526Sxy150489 size_t size;
4763526Sxy150489 size_t len;
4773526Sxy150489 uintptr_t templong;
4783526Sxy150489 uint_t cookie_count;
4793526Sxy150489 dev_info_t *devinfo;
4803526Sxy150489 ddi_dma_cookie_t cookie;
4813526Sxy150489 struct e1000g *Adapter;
4824919Sxy150489 ddi_dma_attr_t dma_attr;
4833526Sxy150489
4848850SMin.Xu@Sun.COM Adapter = rx_data->rx_ring->adapter;
4854919Sxy150489 devinfo = Adapter->dip;
4863526Sxy150489
4873526Sxy150489 alloc_flag = B_FALSE;
4884919Sxy150489 dma_attr = e1000g_desc_dma_attr;
4893526Sxy150489
4903526Sxy150489 /*
4913526Sxy150489 * Memory allocation for the receive buffer descriptors.
4923526Sxy150489 */
4934919Sxy150489 size = (sizeof (struct e1000_rx_desc)) * Adapter->rx_desc_num;
4943526Sxy150489
4953526Sxy150489 /*
4968178SChenlu.Chen@Sun.COM * Asking for aligned memory with DMA attributes set for suitable value
4973526Sxy150489 */
4984919Sxy150489 dma_attr.dma_attr_sgllen = 1;
4998178SChenlu.Chen@Sun.COM dma_attr.dma_attr_align = Adapter->desc_align;
5003526Sxy150489
5013526Sxy150489 /*
5024919Sxy150489 * Allocate a new DMA handle for the receive descriptors
5033526Sxy150489 */
5044919Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, &dma_attr,
5053526Sxy150489 DDI_DMA_DONTWAIT, 0,
5068850SMin.Xu@Sun.COM &rx_data->rbd_dma_handle);
5073526Sxy150489
5083526Sxy150489 if (mystat != DDI_SUCCESS) {
5094919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
5103526Sxy150489 "Could not allocate rbd dma handle: %d", mystat);
5118850SMin.Xu@Sun.COM rx_data->rbd_dma_handle = NULL;
5123526Sxy150489 return (DDI_FAILURE);
5133526Sxy150489 }
5143526Sxy150489 /*
5153526Sxy150489 * Allocate memory to DMA data to and from the receive
5163526Sxy150489 * descriptors.
5173526Sxy150489 */
5188850SMin.Xu@Sun.COM mystat = ddi_dma_mem_alloc(rx_data->rbd_dma_handle,
5193526Sxy150489 size,
5204919Sxy150489 &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT,
5213526Sxy150489 DDI_DMA_DONTWAIT, 0,
5228850SMin.Xu@Sun.COM (caddr_t *)&rx_data->rbd_area,
5238850SMin.Xu@Sun.COM &len, &rx_data->rbd_acc_handle);
5243526Sxy150489
5253526Sxy150489 /*
5263526Sxy150489 * Check if memory allocation succeeded and also if the
5273526Sxy150489 * allocated memory is aligned correctly.
5283526Sxy150489 */
5293526Sxy150489 if ((mystat != DDI_SUCCESS) ||
5308850SMin.Xu@Sun.COM ((uintptr_t)rx_data->rbd_area & (Adapter->desc_align - 1))) {
5313526Sxy150489 if (mystat == DDI_SUCCESS) {
5328850SMin.Xu@Sun.COM ddi_dma_mem_free(&rx_data->rbd_acc_handle);
5338850SMin.Xu@Sun.COM rx_data->rbd_acc_handle = NULL;
5348850SMin.Xu@Sun.COM rx_data->rbd_area = NULL;
5353526Sxy150489 }
5368850SMin.Xu@Sun.COM if (rx_data->rbd_dma_handle != NULL) {
5378850SMin.Xu@Sun.COM ddi_dma_free_handle(&rx_data->rbd_dma_handle);
5388850SMin.Xu@Sun.COM rx_data->rbd_dma_handle = NULL;
5393526Sxy150489 }
5403526Sxy150489 alloc_flag = B_FALSE;
5413526Sxy150489 } else
5423526Sxy150489 alloc_flag = B_TRUE;
5433526Sxy150489
5443526Sxy150489 /*
5453526Sxy150489 * Initialize the allocated receive descriptor memory to zero.
5463526Sxy150489 */
5473526Sxy150489 if (alloc_flag)
5488850SMin.Xu@Sun.COM bzero((caddr_t)rx_data->rbd_area, len);
5493526Sxy150489
5503526Sxy150489 /*
5514919Sxy150489 * If memory allocation did not succeed, do the alignment ourselves
5523526Sxy150489 */
5533526Sxy150489 if (!alloc_flag) {
5544919Sxy150489 dma_attr.dma_attr_align = 1;
5554919Sxy150489 dma_attr.dma_attr_sgllen = 1;
5568178SChenlu.Chen@Sun.COM size = size + Adapter->desc_align;
5573526Sxy150489 /*
5584919Sxy150489 * Allocate a new DMA handle for the receive descriptor.
5593526Sxy150489 */
5604919Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, &dma_attr,
5613526Sxy150489 DDI_DMA_DONTWAIT, 0,
5628850SMin.Xu@Sun.COM &rx_data->rbd_dma_handle);
5633526Sxy150489
5643526Sxy150489 if (mystat != DDI_SUCCESS) {
5654919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
5663526Sxy150489 "Could not re-allocate rbd dma handle: %d", mystat);
5678850SMin.Xu@Sun.COM rx_data->rbd_dma_handle = NULL;
5683526Sxy150489 return (DDI_FAILURE);
5693526Sxy150489 }
5703526Sxy150489 /*
5713526Sxy150489 * Allocate memory to DMA data to and from the receive
5723526Sxy150489 * descriptors.
5733526Sxy150489 */
5748850SMin.Xu@Sun.COM mystat = ddi_dma_mem_alloc(rx_data->rbd_dma_handle,
5753526Sxy150489 size,
5764919Sxy150489 &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT,
5773526Sxy150489 DDI_DMA_DONTWAIT, 0,
5788850SMin.Xu@Sun.COM (caddr_t *)&rx_data->rbd_area,
5798850SMin.Xu@Sun.COM &len, &rx_data->rbd_acc_handle);
5803526Sxy150489
5813526Sxy150489 if (mystat != DDI_SUCCESS) {
5824919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
5833526Sxy150489 "Could not allocate rbd dma memory: %d", mystat);
5848850SMin.Xu@Sun.COM rx_data->rbd_acc_handle = NULL;
5858850SMin.Xu@Sun.COM rx_data->rbd_area = NULL;
5868850SMin.Xu@Sun.COM if (rx_data->rbd_dma_handle != NULL) {
5878850SMin.Xu@Sun.COM ddi_dma_free_handle(&rx_data->rbd_dma_handle);
5888850SMin.Xu@Sun.COM rx_data->rbd_dma_handle = NULL;
5893526Sxy150489 }
5903526Sxy150489 return (DDI_FAILURE);
5913526Sxy150489 } else
5923526Sxy150489 alloc_flag = B_TRUE;
5933526Sxy150489
5943526Sxy150489 /*
5953526Sxy150489 * Initialize the allocated receive descriptor memory to zero.
5963526Sxy150489 */
5978850SMin.Xu@Sun.COM bzero((caddr_t)rx_data->rbd_area, len);
5988850SMin.Xu@Sun.COM templong = P2NPHASE((uintptr_t)rx_data->rbd_area,
5998178SChenlu.Chen@Sun.COM Adapter->desc_align);
6003526Sxy150489 len = size - templong;
6018850SMin.Xu@Sun.COM templong += (uintptr_t)rx_data->rbd_area;
6028850SMin.Xu@Sun.COM rx_data->rbd_area = (struct e1000_rx_desc *)templong;
6033526Sxy150489 } /* alignment workaround */
6043526Sxy150489
6053526Sxy150489 /*
6063526Sxy150489 * The memory allocation of the receive descriptors succeeded
6073526Sxy150489 */
6083526Sxy150489 ASSERT(alloc_flag);
6093526Sxy150489
6103526Sxy150489 /*
6113526Sxy150489 * Allocates DMA resources for the memory that was allocated by
6123526Sxy150489 * the ddi_dma_mem_alloc call.
6133526Sxy150489 */
6148850SMin.Xu@Sun.COM mystat = ddi_dma_addr_bind_handle(rx_data->rbd_dma_handle,
6158850SMin.Xu@Sun.COM (struct as *)NULL, (caddr_t)rx_data->rbd_area,
6164349Sxy150489 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
6174919Sxy150489 DDI_DMA_DONTWAIT, 0, &cookie, &cookie_count);
6183526Sxy150489
6193526Sxy150489 if (mystat != DDI_SUCCESS) {
6204919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
6213526Sxy150489 "Could not bind rbd dma resource: %d", mystat);
6228850SMin.Xu@Sun.COM if (rx_data->rbd_acc_handle != NULL) {
6238850SMin.Xu@Sun.COM ddi_dma_mem_free(&rx_data->rbd_acc_handle);
6248850SMin.Xu@Sun.COM rx_data->rbd_acc_handle = NULL;
6258850SMin.Xu@Sun.COM rx_data->rbd_area = NULL;
6263526Sxy150489 }
6278850SMin.Xu@Sun.COM if (rx_data->rbd_dma_handle != NULL) {
6288850SMin.Xu@Sun.COM ddi_dma_free_handle(&rx_data->rbd_dma_handle);
6298850SMin.Xu@Sun.COM rx_data->rbd_dma_handle = NULL;
6303526Sxy150489 }
6313526Sxy150489 return (DDI_FAILURE);
6323526Sxy150489 }
6333526Sxy150489
6343526Sxy150489 ASSERT(cookie_count == 1);
6353526Sxy150489 if (cookie_count != 1) {
6364919Sxy150489 E1000G_DEBUGLOG_2(Adapter, E1000G_WARN_LEVEL,
6373526Sxy150489 "Could not bind rbd dma resource in a single frag. "
6383526Sxy150489 "Count - %d Len - %d", cookie_count, len);
6398850SMin.Xu@Sun.COM e1000g_free_rx_descriptors(rx_data);
6403526Sxy150489 return (DDI_FAILURE);
6413526Sxy150489 }
6424919Sxy150489
6438850SMin.Xu@Sun.COM rx_data->rbd_dma_addr = cookie.dmac_laddress;
6448850SMin.Xu@Sun.COM rx_data->rbd_first = rx_data->rbd_area;
6458850SMin.Xu@Sun.COM rx_data->rbd_last = rx_data->rbd_first +
6464919Sxy150489 (Adapter->rx_desc_num - 1);
6473526Sxy150489
6483526Sxy150489 return (DDI_SUCCESS);
6493526Sxy150489 }
6503526Sxy150489
6513526Sxy150489 static void
e1000g_free_rx_descriptors(e1000g_rx_data_t * rx_data)6528850SMin.Xu@Sun.COM e1000g_free_rx_descriptors(e1000g_rx_data_t *rx_data)
6533526Sxy150489 {
6548850SMin.Xu@Sun.COM if (rx_data->rbd_dma_handle != NULL) {
6558850SMin.Xu@Sun.COM (void) ddi_dma_unbind_handle(rx_data->rbd_dma_handle);
6563526Sxy150489 }
6578850SMin.Xu@Sun.COM if (rx_data->rbd_acc_handle != NULL) {
6588850SMin.Xu@Sun.COM ddi_dma_mem_free(&rx_data->rbd_acc_handle);
6598850SMin.Xu@Sun.COM rx_data->rbd_acc_handle = NULL;
6608850SMin.Xu@Sun.COM rx_data->rbd_area = NULL;
6613526Sxy150489 }
6628850SMin.Xu@Sun.COM if (rx_data->rbd_dma_handle != NULL) {
6638850SMin.Xu@Sun.COM ddi_dma_free_handle(&rx_data->rbd_dma_handle);
6648850SMin.Xu@Sun.COM rx_data->rbd_dma_handle = NULL;
6653526Sxy150489 }
6668850SMin.Xu@Sun.COM rx_data->rbd_dma_addr = NULL;
6678850SMin.Xu@Sun.COM rx_data->rbd_first = NULL;
6688850SMin.Xu@Sun.COM rx_data->rbd_last = NULL;
6693526Sxy150489 }
6703526Sxy150489
6713526Sxy150489 static void
e1000g_free_tx_descriptors(e1000g_tx_ring_t * tx_ring)6723526Sxy150489 e1000g_free_tx_descriptors(e1000g_tx_ring_t *tx_ring)
6733526Sxy150489 {
6743526Sxy150489 if (tx_ring->tbd_dma_handle != NULL) {
6757426SChenliang.Xu@Sun.COM (void) ddi_dma_unbind_handle(tx_ring->tbd_dma_handle);
6763526Sxy150489 }
6773526Sxy150489 if (tx_ring->tbd_acc_handle != NULL) {
6783526Sxy150489 ddi_dma_mem_free(&tx_ring->tbd_acc_handle);
6793526Sxy150489 tx_ring->tbd_acc_handle = NULL;
6803526Sxy150489 tx_ring->tbd_area = NULL;
6813526Sxy150489 }
6823526Sxy150489 if (tx_ring->tbd_dma_handle != NULL) {
6833526Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_dma_handle);
6843526Sxy150489 tx_ring->tbd_dma_handle = NULL;
6853526Sxy150489 }
6863526Sxy150489 tx_ring->tbd_dma_addr = NULL;
6873526Sxy150489 tx_ring->tbd_first = NULL;
6883526Sxy150489 tx_ring->tbd_last = NULL;
6893526Sxy150489 }
6903526Sxy150489
6913526Sxy150489
6923526Sxy150489 /*
6934919Sxy150489 * e1000g_alloc_packets - allocate DMA buffers for rx/tx
6944919Sxy150489 *
6954919Sxy150489 * This routine allocates neccesary buffers for
6964919Sxy150489 * Transmit sw packet structure
6974919Sxy150489 * DMA handle for Transmit
6984919Sxy150489 * DMA buffer for Transmit
6994919Sxy150489 * Receive sw packet structure
7004919Sxy150489 * DMA buffer for Receive
7013526Sxy150489 */
7023526Sxy150489 static int
e1000g_alloc_packets(struct e1000g * Adapter)7033526Sxy150489 e1000g_alloc_packets(struct e1000g *Adapter)
7043526Sxy150489 {
7053526Sxy150489 int result;
7063526Sxy150489 e1000g_tx_ring_t *tx_ring;
7078850SMin.Xu@Sun.COM e1000g_rx_data_t *rx_data;
7083526Sxy150489
7093526Sxy150489 tx_ring = Adapter->tx_ring;
7108850SMin.Xu@Sun.COM rx_data = Adapter->rx_ring->rx_data;
7113526Sxy150489
7123526Sxy150489 again:
7133526Sxy150489 rw_enter(&e1000g_dma_type_lock, RW_READER);
7143526Sxy150489
7153526Sxy150489 result = e1000g_alloc_tx_packets(tx_ring);
7163526Sxy150489 if (result != DDI_SUCCESS) {
7173526Sxy150489 if (e1000g_dma_type == USE_DVMA) {
7183526Sxy150489 rw_exit(&e1000g_dma_type_lock);
7193526Sxy150489
7203526Sxy150489 rw_enter(&e1000g_dma_type_lock, RW_WRITER);
7213526Sxy150489 e1000g_dma_type = USE_DMA;
7223526Sxy150489 rw_exit(&e1000g_dma_type_lock);
7233526Sxy150489
7244919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL,
7253526Sxy150489 "No enough dvma resource for Tx packets, "
7263526Sxy150489 "trying to allocate dma buffers...\n");
7273526Sxy150489 goto again;
7283526Sxy150489 }
7293526Sxy150489 rw_exit(&e1000g_dma_type_lock);
7303526Sxy150489
7314919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL,
7323526Sxy150489 "Failed to allocate dma buffers for Tx packets\n");
7333526Sxy150489 return (DDI_FAILURE);
7343526Sxy150489 }
7353526Sxy150489
7368850SMin.Xu@Sun.COM result = e1000g_alloc_rx_packets(rx_data);
7373526Sxy150489 if (result != DDI_SUCCESS) {
7383526Sxy150489 e1000g_free_tx_packets(tx_ring);
7393526Sxy150489 if (e1000g_dma_type == USE_DVMA) {
7403526Sxy150489 rw_exit(&e1000g_dma_type_lock);
7413526Sxy150489
7423526Sxy150489 rw_enter(&e1000g_dma_type_lock, RW_WRITER);
7433526Sxy150489 e1000g_dma_type = USE_DMA;
7443526Sxy150489 rw_exit(&e1000g_dma_type_lock);
7453526Sxy150489
7464919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL,
7473526Sxy150489 "No enough dvma resource for Rx packets, "
7483526Sxy150489 "trying to allocate dma buffers...\n");
7493526Sxy150489 goto again;
7503526Sxy150489 }
7513526Sxy150489 rw_exit(&e1000g_dma_type_lock);
7523526Sxy150489
7534919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL,
7543526Sxy150489 "Failed to allocate dma buffers for Rx packets\n");
7553526Sxy150489 return (DDI_FAILURE);
7563526Sxy150489 }
7573526Sxy150489
7583526Sxy150489 rw_exit(&e1000g_dma_type_lock);
7593526Sxy150489
7603526Sxy150489 return (DDI_SUCCESS);
7613526Sxy150489 }
7623526Sxy150489
7634919Sxy150489 static void
e1000g_free_packets(struct e1000g * Adapter)7644919Sxy150489 e1000g_free_packets(struct e1000g *Adapter)
7654919Sxy150489 {
7664919Sxy150489 e1000g_tx_ring_t *tx_ring;
7678850SMin.Xu@Sun.COM e1000g_rx_data_t *rx_data;
7684919Sxy150489
7694919Sxy150489 tx_ring = Adapter->tx_ring;
7708850SMin.Xu@Sun.COM rx_data = Adapter->rx_ring->rx_data;
7714919Sxy150489
7724919Sxy150489 e1000g_free_tx_packets(tx_ring);
773*12853SChangqing.Li@Sun.COM e1000g_free_rx_packets(rx_data, B_FALSE);
7744919Sxy150489 }
7754919Sxy150489
7763526Sxy150489 #ifdef __sparc
7773526Sxy150489 static int
e1000g_alloc_dvma_buffer(struct e1000g * Adapter,dma_buffer_t * buf,size_t size)7783526Sxy150489 e1000g_alloc_dvma_buffer(struct e1000g *Adapter,
7793526Sxy150489 dma_buffer_t *buf, size_t size)
7803526Sxy150489 {
7813526Sxy150489 int mystat;
7823526Sxy150489 dev_info_t *devinfo;
7833526Sxy150489 ddi_dma_cookie_t cookie;
7843526Sxy150489
7854349Sxy150489 if (e1000g_force_detach)
7864349Sxy150489 devinfo = Adapter->priv_dip;
7874349Sxy150489 else
7884349Sxy150489 devinfo = Adapter->dip;
7893526Sxy150489
7903526Sxy150489 mystat = dvma_reserve(devinfo,
7913526Sxy150489 &e1000g_dma_limits,
7923526Sxy150489 Adapter->dvma_page_num,
7933526Sxy150489 &buf->dma_handle);
7943526Sxy150489
7953526Sxy150489 if (mystat != DDI_SUCCESS) {
7963526Sxy150489 buf->dma_handle = NULL;
7974919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
7983526Sxy150489 "Could not allocate dvma buffer handle: %d\n", mystat);
7993526Sxy150489 return (DDI_FAILURE);
8003526Sxy150489 }
8013526Sxy150489
8023526Sxy150489 buf->address = kmem_alloc(size, KM_NOSLEEP);
8033526Sxy150489
8043526Sxy150489 if (buf->address == NULL) {
8053526Sxy150489 if (buf->dma_handle != NULL) {
8063526Sxy150489 dvma_release(buf->dma_handle);
8073526Sxy150489 buf->dma_handle = NULL;
8083526Sxy150489 }
8094919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL,
8103526Sxy150489 "Could not allocate dvma buffer memory\n");
8113526Sxy150489 return (DDI_FAILURE);
8123526Sxy150489 }
8133526Sxy150489
8143526Sxy150489 dvma_kaddr_load(buf->dma_handle,
8153526Sxy150489 buf->address, size, 0, &cookie);
8163526Sxy150489
8173526Sxy150489 buf->dma_address = cookie.dmac_laddress;
8183526Sxy150489 buf->size = size;
8193526Sxy150489 buf->len = 0;
8203526Sxy150489
8213526Sxy150489 return (DDI_SUCCESS);
8223526Sxy150489 }
8233526Sxy150489
8243526Sxy150489 static void
e1000g_free_dvma_buffer(dma_buffer_t * buf)8253526Sxy150489 e1000g_free_dvma_buffer(dma_buffer_t *buf)
8263526Sxy150489 {
8273526Sxy150489 if (buf->dma_handle != NULL) {
8283526Sxy150489 dvma_unload(buf->dma_handle, 0, -1);
8293526Sxy150489 } else {
8303526Sxy150489 return;
8313526Sxy150489 }
8323526Sxy150489
8333526Sxy150489 buf->dma_address = NULL;
8343526Sxy150489
8353526Sxy150489 if (buf->address != NULL) {
8363526Sxy150489 kmem_free(buf->address, buf->size);
8373526Sxy150489 buf->address = NULL;
8383526Sxy150489 }
8393526Sxy150489
8403526Sxy150489 if (buf->dma_handle != NULL) {
8413526Sxy150489 dvma_release(buf->dma_handle);
8423526Sxy150489 buf->dma_handle = NULL;
8433526Sxy150489 }
8443526Sxy150489
8453526Sxy150489 buf->size = 0;
8463526Sxy150489 buf->len = 0;
8473526Sxy150489 }
8483526Sxy150489 #endif
8493526Sxy150489
8503526Sxy150489 static int
e1000g_alloc_dma_buffer(struct e1000g * Adapter,dma_buffer_t * buf,size_t size,ddi_dma_attr_t * p_dma_attr)8513526Sxy150489 e1000g_alloc_dma_buffer(struct e1000g *Adapter,
8524919Sxy150489 dma_buffer_t *buf, size_t size, ddi_dma_attr_t *p_dma_attr)
8533526Sxy150489 {
8543526Sxy150489 int mystat;
8553526Sxy150489 dev_info_t *devinfo;
8563526Sxy150489 ddi_dma_cookie_t cookie;
8573526Sxy150489 size_t len;
8583526Sxy150489 uint_t count;
8593526Sxy150489
8604349Sxy150489 if (e1000g_force_detach)
8614349Sxy150489 devinfo = Adapter->priv_dip;
8624349Sxy150489 else
8634349Sxy150489 devinfo = Adapter->dip;
8643526Sxy150489
8653526Sxy150489 mystat = ddi_dma_alloc_handle(devinfo,
8664919Sxy150489 p_dma_attr,
8673526Sxy150489 DDI_DMA_DONTWAIT, 0,
8683526Sxy150489 &buf->dma_handle);
8693526Sxy150489
8703526Sxy150489 if (mystat != DDI_SUCCESS) {
8713526Sxy150489 buf->dma_handle = NULL;
8724919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
8733526Sxy150489 "Could not allocate dma buffer handle: %d\n", mystat);
8743526Sxy150489 return (DDI_FAILURE);
8753526Sxy150489 }
8763526Sxy150489
8773526Sxy150489 mystat = ddi_dma_mem_alloc(buf->dma_handle,
8784919Sxy150489 size, &e1000g_buf_acc_attr, DDI_DMA_STREAMING,
8793526Sxy150489 DDI_DMA_DONTWAIT, 0,
8803526Sxy150489 &buf->address,
8813526Sxy150489 &len, &buf->acc_handle);
8823526Sxy150489
8833526Sxy150489 if (mystat != DDI_SUCCESS) {
8843526Sxy150489 buf->acc_handle = NULL;
8853526Sxy150489 buf->address = NULL;
8863526Sxy150489 if (buf->dma_handle != NULL) {
8873526Sxy150489 ddi_dma_free_handle(&buf->dma_handle);
8883526Sxy150489 buf->dma_handle = NULL;
8893526Sxy150489 }
8904919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
8913526Sxy150489 "Could not allocate dma buffer memory: %d\n", mystat);
8923526Sxy150489 return (DDI_FAILURE);
8933526Sxy150489 }
8943526Sxy150489
8953526Sxy150489 mystat = ddi_dma_addr_bind_handle(buf->dma_handle,
8963526Sxy150489 (struct as *)NULL,
8973526Sxy150489 buf->address,
89811402SChangqing.Li@Sun.COM len, DDI_DMA_RDWR | DDI_DMA_STREAMING,
8994919Sxy150489 DDI_DMA_DONTWAIT, 0, &cookie, &count);
9003526Sxy150489
9013526Sxy150489 if (mystat != DDI_SUCCESS) {
9023526Sxy150489 if (buf->acc_handle != NULL) {
9033526Sxy150489 ddi_dma_mem_free(&buf->acc_handle);
9043526Sxy150489 buf->acc_handle = NULL;
9053526Sxy150489 buf->address = NULL;
9063526Sxy150489 }
9073526Sxy150489 if (buf->dma_handle != NULL) {
9083526Sxy150489 ddi_dma_free_handle(&buf->dma_handle);
9093526Sxy150489 buf->dma_handle = NULL;
9103526Sxy150489 }
9114919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
9123526Sxy150489 "Could not bind buffer dma handle: %d\n", mystat);
9133526Sxy150489 return (DDI_FAILURE);
9143526Sxy150489 }
9153526Sxy150489
9163526Sxy150489 ASSERT(count == 1);
9173526Sxy150489 if (count != 1) {
9183526Sxy150489 if (buf->dma_handle != NULL) {
9197426SChenliang.Xu@Sun.COM (void) ddi_dma_unbind_handle(buf->dma_handle);
9203526Sxy150489 }
9213526Sxy150489 if (buf->acc_handle != NULL) {
9223526Sxy150489 ddi_dma_mem_free(&buf->acc_handle);
9233526Sxy150489 buf->acc_handle = NULL;
9243526Sxy150489 buf->address = NULL;
9253526Sxy150489 }
9263526Sxy150489 if (buf->dma_handle != NULL) {
9273526Sxy150489 ddi_dma_free_handle(&buf->dma_handle);
9283526Sxy150489 buf->dma_handle = NULL;
9293526Sxy150489 }
9304919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
9313526Sxy150489 "Could not bind buffer as a single frag. "
9323526Sxy150489 "Count = %d\n", count);
9333526Sxy150489 return (DDI_FAILURE);
9343526Sxy150489 }
9353526Sxy150489
9363526Sxy150489 buf->dma_address = cookie.dmac_laddress;
9373526Sxy150489 buf->size = len;
9383526Sxy150489 buf->len = 0;
9393526Sxy150489
9403526Sxy150489 return (DDI_SUCCESS);
9413526Sxy150489 }
9423526Sxy150489
9438178SChenlu.Chen@Sun.COM /*
9448178SChenlu.Chen@Sun.COM * e1000g_alloc_dma_buffer_82546 - allocate a dma buffer along with all
9458178SChenlu.Chen@Sun.COM * necessary handles. Same as e1000g_alloc_dma_buffer() except ensure
9468178SChenlu.Chen@Sun.COM * that buffer that doesn't cross a 64k boundary.
9478178SChenlu.Chen@Sun.COM */
9488178SChenlu.Chen@Sun.COM static int
e1000g_alloc_dma_buffer_82546(struct e1000g * Adapter,dma_buffer_t * buf,size_t size,ddi_dma_attr_t * p_dma_attr)9498178SChenlu.Chen@Sun.COM e1000g_alloc_dma_buffer_82546(struct e1000g *Adapter,
9508178SChenlu.Chen@Sun.COM dma_buffer_t *buf, size_t size, ddi_dma_attr_t *p_dma_attr)
9518178SChenlu.Chen@Sun.COM {
9528178SChenlu.Chen@Sun.COM int mystat;
9538178SChenlu.Chen@Sun.COM dev_info_t *devinfo;
9548178SChenlu.Chen@Sun.COM ddi_dma_cookie_t cookie;
9558178SChenlu.Chen@Sun.COM size_t len;
9568178SChenlu.Chen@Sun.COM uint_t count;
9578178SChenlu.Chen@Sun.COM
9588178SChenlu.Chen@Sun.COM if (e1000g_force_detach)
9598178SChenlu.Chen@Sun.COM devinfo = Adapter->priv_dip;
9608178SChenlu.Chen@Sun.COM else
9618178SChenlu.Chen@Sun.COM devinfo = Adapter->dip;
9628178SChenlu.Chen@Sun.COM
9638178SChenlu.Chen@Sun.COM mystat = ddi_dma_alloc_handle(devinfo,
9648178SChenlu.Chen@Sun.COM p_dma_attr,
9658178SChenlu.Chen@Sun.COM DDI_DMA_DONTWAIT, 0,
9668178SChenlu.Chen@Sun.COM &buf->dma_handle);
9678178SChenlu.Chen@Sun.COM
9688178SChenlu.Chen@Sun.COM if (mystat != DDI_SUCCESS) {
9698178SChenlu.Chen@Sun.COM buf->dma_handle = NULL;
9708178SChenlu.Chen@Sun.COM E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
9718178SChenlu.Chen@Sun.COM "Could not allocate dma buffer handle: %d\n", mystat);
9728178SChenlu.Chen@Sun.COM return (DDI_FAILURE);
9738178SChenlu.Chen@Sun.COM }
9748178SChenlu.Chen@Sun.COM
9758178SChenlu.Chen@Sun.COM mystat = e1000g_dma_mem_alloc_82546(buf, size, &len);
9768178SChenlu.Chen@Sun.COM if (mystat != DDI_SUCCESS) {
9778178SChenlu.Chen@Sun.COM buf->acc_handle = NULL;
9788178SChenlu.Chen@Sun.COM buf->address = NULL;
9798178SChenlu.Chen@Sun.COM if (buf->dma_handle != NULL) {
9808178SChenlu.Chen@Sun.COM ddi_dma_free_handle(&buf->dma_handle);
9818178SChenlu.Chen@Sun.COM buf->dma_handle = NULL;
9828178SChenlu.Chen@Sun.COM }
9838178SChenlu.Chen@Sun.COM E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
9848178SChenlu.Chen@Sun.COM "Could not allocate dma buffer memory: %d\n", mystat);
9858178SChenlu.Chen@Sun.COM return (DDI_FAILURE);
9868178SChenlu.Chen@Sun.COM }
9878178SChenlu.Chen@Sun.COM
9888178SChenlu.Chen@Sun.COM mystat = ddi_dma_addr_bind_handle(buf->dma_handle,
9898178SChenlu.Chen@Sun.COM (struct as *)NULL,
9908178SChenlu.Chen@Sun.COM buf->address,
9918178SChenlu.Chen@Sun.COM len, DDI_DMA_READ | DDI_DMA_STREAMING,
9928178SChenlu.Chen@Sun.COM DDI_DMA_DONTWAIT, 0, &cookie, &count);
9938178SChenlu.Chen@Sun.COM
9948178SChenlu.Chen@Sun.COM if (mystat != DDI_SUCCESS) {
9958178SChenlu.Chen@Sun.COM if (buf->acc_handle != NULL) {
9968178SChenlu.Chen@Sun.COM ddi_dma_mem_free(&buf->acc_handle);
9978178SChenlu.Chen@Sun.COM buf->acc_handle = NULL;
9988178SChenlu.Chen@Sun.COM buf->address = NULL;
9998178SChenlu.Chen@Sun.COM }
10008178SChenlu.Chen@Sun.COM if (buf->dma_handle != NULL) {
10018178SChenlu.Chen@Sun.COM ddi_dma_free_handle(&buf->dma_handle);
10028178SChenlu.Chen@Sun.COM buf->dma_handle = NULL;
10038178SChenlu.Chen@Sun.COM }
10048178SChenlu.Chen@Sun.COM E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
10058178SChenlu.Chen@Sun.COM "Could not bind buffer dma handle: %d\n", mystat);
10068178SChenlu.Chen@Sun.COM return (DDI_FAILURE);
10078178SChenlu.Chen@Sun.COM }
10088178SChenlu.Chen@Sun.COM
10098178SChenlu.Chen@Sun.COM ASSERT(count == 1);
10108178SChenlu.Chen@Sun.COM if (count != 1) {
10118178SChenlu.Chen@Sun.COM if (buf->dma_handle != NULL) {
101211143SGuoqing.Zhu@Sun.COM (void) ddi_dma_unbind_handle(buf->dma_handle);
10138178SChenlu.Chen@Sun.COM }
10148178SChenlu.Chen@Sun.COM if (buf->acc_handle != NULL) {
10158178SChenlu.Chen@Sun.COM ddi_dma_mem_free(&buf->acc_handle);
10168178SChenlu.Chen@Sun.COM buf->acc_handle = NULL;
10178178SChenlu.Chen@Sun.COM buf->address = NULL;
10188178SChenlu.Chen@Sun.COM }
10198178SChenlu.Chen@Sun.COM if (buf->dma_handle != NULL) {
10208178SChenlu.Chen@Sun.COM ddi_dma_free_handle(&buf->dma_handle);
10218178SChenlu.Chen@Sun.COM buf->dma_handle = NULL;
10228178SChenlu.Chen@Sun.COM }
10238178SChenlu.Chen@Sun.COM E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
10248178SChenlu.Chen@Sun.COM "Could not bind buffer as a single frag. "
10258178SChenlu.Chen@Sun.COM "Count = %d\n", count);
10268178SChenlu.Chen@Sun.COM return (DDI_FAILURE);
10278178SChenlu.Chen@Sun.COM }
10288178SChenlu.Chen@Sun.COM
10298178SChenlu.Chen@Sun.COM buf->dma_address = cookie.dmac_laddress;
10308178SChenlu.Chen@Sun.COM buf->size = len;
10318178SChenlu.Chen@Sun.COM buf->len = 0;
10328178SChenlu.Chen@Sun.COM
10338178SChenlu.Chen@Sun.COM return (DDI_SUCCESS);
10348178SChenlu.Chen@Sun.COM }
10358178SChenlu.Chen@Sun.COM
10368178SChenlu.Chen@Sun.COM /*
10378178SChenlu.Chen@Sun.COM * e1000g_dma_mem_alloc_82546 - allocate a dma buffer, making up to
10388178SChenlu.Chen@Sun.COM * ALLOC_RETRY attempts to get a buffer that doesn't cross a 64k boundary.
10398178SChenlu.Chen@Sun.COM */
10408178SChenlu.Chen@Sun.COM static int
e1000g_dma_mem_alloc_82546(dma_buffer_t * buf,size_t size,size_t * len)10418178SChenlu.Chen@Sun.COM e1000g_dma_mem_alloc_82546(dma_buffer_t *buf, size_t size, size_t *len)
10428178SChenlu.Chen@Sun.COM {
10438178SChenlu.Chen@Sun.COM #define ALLOC_RETRY 10
10448178SChenlu.Chen@Sun.COM int stat;
10458178SChenlu.Chen@Sun.COM int cnt = 0;
10468178SChenlu.Chen@Sun.COM ddi_acc_handle_t hold[ALLOC_RETRY];
10478178SChenlu.Chen@Sun.COM
10488178SChenlu.Chen@Sun.COM while (cnt < ALLOC_RETRY) {
10498178SChenlu.Chen@Sun.COM hold[cnt] = NULL;
10508178SChenlu.Chen@Sun.COM
10518178SChenlu.Chen@Sun.COM /* allocate memory */
10528178SChenlu.Chen@Sun.COM stat = ddi_dma_mem_alloc(buf->dma_handle, size,
10538178SChenlu.Chen@Sun.COM &e1000g_buf_acc_attr, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT,
10548178SChenlu.Chen@Sun.COM 0, &buf->address, len, &buf->acc_handle);
10558178SChenlu.Chen@Sun.COM
10568178SChenlu.Chen@Sun.COM if (stat != DDI_SUCCESS) {
10578178SChenlu.Chen@Sun.COM break;
10588178SChenlu.Chen@Sun.COM }
10598178SChenlu.Chen@Sun.COM
10608178SChenlu.Chen@Sun.COM /*
10618178SChenlu.Chen@Sun.COM * Check 64k bounday:
10628178SChenlu.Chen@Sun.COM * if it is bad, hold it and retry
10638178SChenlu.Chen@Sun.COM * if it is good, exit loop
10648178SChenlu.Chen@Sun.COM */
10658178SChenlu.Chen@Sun.COM if (e1000g_cross_64k_bound(buf->address, *len)) {
10668178SChenlu.Chen@Sun.COM hold[cnt] = buf->acc_handle;
10678178SChenlu.Chen@Sun.COM stat = DDI_FAILURE;
10688178SChenlu.Chen@Sun.COM } else {
10698178SChenlu.Chen@Sun.COM break;
10708178SChenlu.Chen@Sun.COM }
10718178SChenlu.Chen@Sun.COM
10728178SChenlu.Chen@Sun.COM cnt++;
10738178SChenlu.Chen@Sun.COM }
10748178SChenlu.Chen@Sun.COM
10758178SChenlu.Chen@Sun.COM /* Release any held buffers crossing 64k bounday */
10768178SChenlu.Chen@Sun.COM for (--cnt; cnt >= 0; cnt--) {
10778178SChenlu.Chen@Sun.COM if (hold[cnt])
10788178SChenlu.Chen@Sun.COM ddi_dma_mem_free(&hold[cnt]);
10798178SChenlu.Chen@Sun.COM }
10808178SChenlu.Chen@Sun.COM
10818178SChenlu.Chen@Sun.COM return (stat);
10828178SChenlu.Chen@Sun.COM }
10838178SChenlu.Chen@Sun.COM
10848178SChenlu.Chen@Sun.COM /*
10858178SChenlu.Chen@Sun.COM * e1000g_cross_64k_bound - If starting and ending address cross a 64k boundary
10868178SChenlu.Chen@Sun.COM * return true; otherwise return false
10878178SChenlu.Chen@Sun.COM */
10888178SChenlu.Chen@Sun.COM static boolean_t
e1000g_cross_64k_bound(void * addr,uintptr_t len)10898178SChenlu.Chen@Sun.COM e1000g_cross_64k_bound(void *addr, uintptr_t len)
10908178SChenlu.Chen@Sun.COM {
10918178SChenlu.Chen@Sun.COM uintptr_t start = (uintptr_t)addr;
10928178SChenlu.Chen@Sun.COM uintptr_t end = start + len - 1;
10938178SChenlu.Chen@Sun.COM
10948178SChenlu.Chen@Sun.COM return (((start ^ end) >> 16) == 0 ? B_FALSE : B_TRUE);
10958178SChenlu.Chen@Sun.COM }
10968178SChenlu.Chen@Sun.COM
10973526Sxy150489 static void
e1000g_free_dma_buffer(dma_buffer_t * buf)10983526Sxy150489 e1000g_free_dma_buffer(dma_buffer_t *buf)
10993526Sxy150489 {
11003526Sxy150489 if (buf->dma_handle != NULL) {
11017426SChenliang.Xu@Sun.COM (void) ddi_dma_unbind_handle(buf->dma_handle);
11023526Sxy150489 } else {
11033526Sxy150489 return;
11043526Sxy150489 }
11053526Sxy150489
11063526Sxy150489 buf->dma_address = NULL;
11073526Sxy150489
11083526Sxy150489 if (buf->acc_handle != NULL) {
11093526Sxy150489 ddi_dma_mem_free(&buf->acc_handle);
11103526Sxy150489 buf->acc_handle = NULL;
11113526Sxy150489 buf->address = NULL;
11123526Sxy150489 }
11133526Sxy150489
11143526Sxy150489 if (buf->dma_handle != NULL) {
11153526Sxy150489 ddi_dma_free_handle(&buf->dma_handle);
11163526Sxy150489 buf->dma_handle = NULL;
11173526Sxy150489 }
11183526Sxy150489
11193526Sxy150489 buf->size = 0;
11203526Sxy150489 buf->len = 0;
11213526Sxy150489 }
11223526Sxy150489
11233526Sxy150489 static int
e1000g_alloc_tx_packets(e1000g_tx_ring_t * tx_ring)11243526Sxy150489 e1000g_alloc_tx_packets(e1000g_tx_ring_t *tx_ring)
11253526Sxy150489 {
11263526Sxy150489 int j;
11274919Sxy150489 p_tx_sw_packet_t packet;
11283526Sxy150489 int mystat;
11293526Sxy150489 dma_buffer_t *tx_buf;
11304919Sxy150489 struct e1000g *Adapter;
11314919Sxy150489 dev_info_t *devinfo;
11324919Sxy150489 ddi_dma_attr_t dma_attr;
11334919Sxy150489
11344919Sxy150489 Adapter = tx_ring->adapter;
11354919Sxy150489 devinfo = Adapter->dip;
11364919Sxy150489 dma_attr = e1000g_buf_dma_attr;
11373526Sxy150489
11383526Sxy150489 /*
11393526Sxy150489 * Memory allocation for the Transmit software structure, the transmit
11403526Sxy150489 * software packet. This structure stores all the relevant information
11413526Sxy150489 * for transmitting a single packet.
11423526Sxy150489 */
11433526Sxy150489 tx_ring->packet_area =
11443526Sxy150489 kmem_zalloc(TX_SW_PKT_AREA_SZ, KM_NOSLEEP);
11453526Sxy150489
11463526Sxy150489 if (tx_ring->packet_area == NULL)
11473526Sxy150489 return (DDI_FAILURE);
11483526Sxy150489
11493526Sxy150489 for (j = 0, packet = tx_ring->packet_area;
11504919Sxy150489 j < Adapter->tx_freelist_num; j++, packet++) {
11513526Sxy150489
11523526Sxy150489 ASSERT(packet != NULL);
11533526Sxy150489
11543526Sxy150489 /*
11553526Sxy150489 * Pre-allocate dma handles for transmit. These dma handles
11563526Sxy150489 * will be dynamically bound to the data buffers passed down
11573526Sxy150489 * from the upper layers at the time of transmitting. The
11583526Sxy150489 * dynamic binding only applies for the packets that are larger
11593526Sxy150489 * than the tx_bcopy_thresh.
11603526Sxy150489 */
11613526Sxy150489 switch (e1000g_dma_type) {
11623526Sxy150489 #ifdef __sparc
11633526Sxy150489 case USE_DVMA:
11643526Sxy150489 mystat = dvma_reserve(devinfo,
11653526Sxy150489 &e1000g_dma_limits,
11663526Sxy150489 Adapter->dvma_page_num,
11673526Sxy150489 &packet->tx_dma_handle);
11683526Sxy150489 break;
11693526Sxy150489 #endif
11703526Sxy150489 case USE_DMA:
11713526Sxy150489 mystat = ddi_dma_alloc_handle(devinfo,
11724919Sxy150489 &e1000g_tx_dma_attr,
11733526Sxy150489 DDI_DMA_DONTWAIT, 0,
11743526Sxy150489 &packet->tx_dma_handle);
11753526Sxy150489 break;
11763526Sxy150489 default:
11773526Sxy150489 ASSERT(B_FALSE);
11783526Sxy150489 break;
11793526Sxy150489 }
11803526Sxy150489 if (mystat != DDI_SUCCESS) {
11813526Sxy150489 packet->tx_dma_handle = NULL;
11824919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL,
11833526Sxy150489 "Could not allocate tx dma handle: %d\n", mystat);
11843526Sxy150489 goto tx_pkt_fail;
11853526Sxy150489 }
11863526Sxy150489
11873526Sxy150489 /*
11883526Sxy150489 * Pre-allocate transmit buffers for small packets that the
11893526Sxy150489 * size is less than tx_bcopy_thresh. The data of those small
11903526Sxy150489 * packets will be bcopy() to the transmit buffers instead of
11913526Sxy150489 * using dynamical DMA binding. For small packets, bcopy will
11923526Sxy150489 * bring better performance than DMA binding.
11933526Sxy150489 */
11943526Sxy150489 tx_buf = packet->tx_buf;
11953526Sxy150489
11963526Sxy150489 switch (e1000g_dma_type) {
11973526Sxy150489 #ifdef __sparc
11983526Sxy150489 case USE_DVMA:
11993526Sxy150489 mystat = e1000g_alloc_dvma_buffer(Adapter,
12004919Sxy150489 tx_buf, Adapter->tx_buffer_size);
12013526Sxy150489 break;
12023526Sxy150489 #endif
12033526Sxy150489 case USE_DMA:
12043526Sxy150489 mystat = e1000g_alloc_dma_buffer(Adapter,
12054919Sxy150489 tx_buf, Adapter->tx_buffer_size, &dma_attr);
12063526Sxy150489 break;
12073526Sxy150489 default:
12083526Sxy150489 ASSERT(B_FALSE);
12093526Sxy150489 break;
12103526Sxy150489 }
12113526Sxy150489 if (mystat != DDI_SUCCESS) {
12123526Sxy150489 ASSERT(packet->tx_dma_handle != NULL);
12133526Sxy150489 switch (e1000g_dma_type) {
12143526Sxy150489 #ifdef __sparc
12153526Sxy150489 case USE_DVMA:
12163526Sxy150489 dvma_release(packet->tx_dma_handle);
12173526Sxy150489 break;
12183526Sxy150489 #endif
12193526Sxy150489 case USE_DMA:
12203526Sxy150489 ddi_dma_free_handle(&packet->tx_dma_handle);
12213526Sxy150489 break;
12223526Sxy150489 default:
12233526Sxy150489 ASSERT(B_FALSE);
12243526Sxy150489 break;
12253526Sxy150489 }
12263526Sxy150489 packet->tx_dma_handle = NULL;
12274919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL,
12283526Sxy150489 "Allocate Tx buffer fail\n");
12293526Sxy150489 goto tx_pkt_fail;
12303526Sxy150489 }
12313526Sxy150489
12323526Sxy150489 packet->dma_type = e1000g_dma_type;
12333526Sxy150489 } /* for */
12343526Sxy150489
12353526Sxy150489 return (DDI_SUCCESS);
12363526Sxy150489
12373526Sxy150489 tx_pkt_fail:
12383526Sxy150489 e1000g_free_tx_packets(tx_ring);
12393526Sxy150489
12403526Sxy150489 return (DDI_FAILURE);
12413526Sxy150489 }
12423526Sxy150489
1243*12853SChangqing.Li@Sun.COM
1244*12853SChangqing.Li@Sun.COM int
e1000g_increase_rx_packets(e1000g_rx_data_t * rx_data)1245*12853SChangqing.Li@Sun.COM e1000g_increase_rx_packets(e1000g_rx_data_t *rx_data)
1246*12853SChangqing.Li@Sun.COM {
1247*12853SChangqing.Li@Sun.COM int i;
1248*12853SChangqing.Li@Sun.COM p_rx_sw_packet_t packet;
1249*12853SChangqing.Li@Sun.COM p_rx_sw_packet_t cur, next;
1250*12853SChangqing.Li@Sun.COM struct e1000g *Adapter;
1251*12853SChangqing.Li@Sun.COM ddi_dma_attr_t dma_attr;
1252*12853SChangqing.Li@Sun.COM
1253*12853SChangqing.Li@Sun.COM Adapter = rx_data->rx_ring->adapter;
1254*12853SChangqing.Li@Sun.COM dma_attr = e1000g_buf_dma_attr;
1255*12853SChangqing.Li@Sun.COM dma_attr.dma_attr_align = Adapter->rx_buf_align;
1256*12853SChangqing.Li@Sun.COM cur = NULL;
1257*12853SChangqing.Li@Sun.COM
1258*12853SChangqing.Li@Sun.COM for (i = 0; i < RX_FREELIST_INCREASE_SIZE; i++) {
1259*12853SChangqing.Li@Sun.COM packet = e1000g_alloc_rx_sw_packet(rx_data, &dma_attr);
1260*12853SChangqing.Li@Sun.COM if (packet == NULL)
1261*12853SChangqing.Li@Sun.COM break;
1262*12853SChangqing.Li@Sun.COM packet->next = cur;
1263*12853SChangqing.Li@Sun.COM cur = packet;
1264*12853SChangqing.Li@Sun.COM }
1265*12853SChangqing.Li@Sun.COM Adapter->rx_freelist_num += i;
1266*12853SChangqing.Li@Sun.COM rx_data->avail_freepkt += i;
1267*12853SChangqing.Li@Sun.COM
1268*12853SChangqing.Li@Sun.COM while (cur != NULL) {
1269*12853SChangqing.Li@Sun.COM QUEUE_PUSH_TAIL(&rx_data->free_list, &cur->Link);
1270*12853SChangqing.Li@Sun.COM next = cur->next;
1271*12853SChangqing.Li@Sun.COM cur->next = rx_data->packet_area;
1272*12853SChangqing.Li@Sun.COM rx_data->packet_area = cur;
1273*12853SChangqing.Li@Sun.COM
1274*12853SChangqing.Li@Sun.COM cur = next;
1275*12853SChangqing.Li@Sun.COM }
1276*12853SChangqing.Li@Sun.COM
1277*12853SChangqing.Li@Sun.COM return (DDI_SUCCESS);
1278*12853SChangqing.Li@Sun.COM }
1279*12853SChangqing.Li@Sun.COM
1280*12853SChangqing.Li@Sun.COM
12813526Sxy150489 static int
e1000g_alloc_rx_packets(e1000g_rx_data_t * rx_data)12828850SMin.Xu@Sun.COM e1000g_alloc_rx_packets(e1000g_rx_data_t *rx_data)
12833526Sxy150489 {
12843526Sxy150489 int i;
12854919Sxy150489 p_rx_sw_packet_t packet;
12863526Sxy150489 struct e1000g *Adapter;
12873526Sxy150489 uint32_t packet_num;
12884919Sxy150489 ddi_dma_attr_t dma_attr;
12893526Sxy150489
12908850SMin.Xu@Sun.COM Adapter = rx_data->rx_ring->adapter;
12914919Sxy150489 dma_attr = e1000g_buf_dma_attr;
12926735Scc210113 dma_attr.dma_attr_align = Adapter->rx_buf_align;
12933526Sxy150489
12943526Sxy150489 /*
12954919Sxy150489 * Allocate memory for the rx_sw_packet structures. Each one of these
12963526Sxy150489 * structures will contain a virtual and physical address to an actual
12974919Sxy150489 * receive buffer in host memory. Since we use one rx_sw_packet per
12984919Sxy150489 * received packet, the maximum number of rx_sw_packet that we'll
12998850SMin.Xu@Sun.COM * need is equal to the number of receive descriptors plus the freelist
13008850SMin.Xu@Sun.COM * size.
13013526Sxy150489 */
1302*12853SChangqing.Li@Sun.COM packet_num = Adapter->rx_desc_num + RX_FREELIST_INCREASE_SIZE;
13038850SMin.Xu@Sun.COM rx_data->packet_area = NULL;
13043526Sxy150489
13053526Sxy150489 for (i = 0; i < packet_num; i++) {
13068850SMin.Xu@Sun.COM packet = e1000g_alloc_rx_sw_packet(rx_data, &dma_attr);
13073526Sxy150489 if (packet == NULL)
13083526Sxy150489 goto rx_pkt_fail;
13093526Sxy150489
13108850SMin.Xu@Sun.COM packet->next = rx_data->packet_area;
13118850SMin.Xu@Sun.COM rx_data->packet_area = packet;
13123526Sxy150489 }
13133526Sxy150489
1314*12853SChangqing.Li@Sun.COM Adapter->rx_freelist_num = RX_FREELIST_INCREASE_SIZE;
13153526Sxy150489 return (DDI_SUCCESS);
13163526Sxy150489
13173526Sxy150489 rx_pkt_fail:
1318*12853SChangqing.Li@Sun.COM e1000g_free_rx_packets(rx_data, B_TRUE);
13193526Sxy150489 return (DDI_FAILURE);
13203526Sxy150489 }
13213526Sxy150489
1322*12853SChangqing.Li@Sun.COM
13234919Sxy150489 static p_rx_sw_packet_t
e1000g_alloc_rx_sw_packet(e1000g_rx_data_t * rx_data,ddi_dma_attr_t * p_dma_attr)13248850SMin.Xu@Sun.COM e1000g_alloc_rx_sw_packet(e1000g_rx_data_t *rx_data, ddi_dma_attr_t *p_dma_attr)
13253526Sxy150489 {
13263526Sxy150489 int mystat;
13274919Sxy150489 p_rx_sw_packet_t packet;
13283526Sxy150489 dma_buffer_t *rx_buf;
13293526Sxy150489 struct e1000g *Adapter;
13303526Sxy150489
13318850SMin.Xu@Sun.COM Adapter = rx_data->rx_ring->adapter;
13323526Sxy150489
13334919Sxy150489 packet = kmem_zalloc(sizeof (rx_sw_packet_t), KM_NOSLEEP);
13343526Sxy150489 if (packet == NULL) {
13354919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL,
13363526Sxy150489 "Cound not allocate memory for Rx SwPacket\n");
13373526Sxy150489 return (NULL);
13383526Sxy150489 }
13393526Sxy150489
13403526Sxy150489 rx_buf = packet->rx_buf;
13413526Sxy150489
13423526Sxy150489 switch (e1000g_dma_type) {
13433526Sxy150489 #ifdef __sparc
13443526Sxy150489 case USE_DVMA:
13453526Sxy150489 mystat = e1000g_alloc_dvma_buffer(Adapter,
13464919Sxy150489 rx_buf, Adapter->rx_buffer_size);
13473526Sxy150489 break;
13483526Sxy150489 #endif
13493526Sxy150489 case USE_DMA:
13508417SChenlu.Chen@Sun.COM if (Adapter->mem_workaround_82546 &&
13518417SChenlu.Chen@Sun.COM ((Adapter->shared.mac.type == e1000_82545) ||
13528178SChenlu.Chen@Sun.COM (Adapter->shared.mac.type == e1000_82546) ||
13538417SChenlu.Chen@Sun.COM (Adapter->shared.mac.type == e1000_82546_rev_3))) {
13548178SChenlu.Chen@Sun.COM mystat = e1000g_alloc_dma_buffer_82546(Adapter,
13558178SChenlu.Chen@Sun.COM rx_buf, Adapter->rx_buffer_size, p_dma_attr);
13568178SChenlu.Chen@Sun.COM } else {
13578178SChenlu.Chen@Sun.COM mystat = e1000g_alloc_dma_buffer(Adapter,
13588178SChenlu.Chen@Sun.COM rx_buf, Adapter->rx_buffer_size, p_dma_attr);
13598178SChenlu.Chen@Sun.COM }
13603526Sxy150489 break;
13613526Sxy150489 default:
13623526Sxy150489 ASSERT(B_FALSE);
13633526Sxy150489 break;
13643526Sxy150489 }
13653526Sxy150489
13663526Sxy150489 if (mystat != DDI_SUCCESS) {
13673526Sxy150489 if (packet != NULL)
13684919Sxy150489 kmem_free(packet, sizeof (rx_sw_packet_t));
13693526Sxy150489
13704919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL,
13713526Sxy150489 "Failed to allocate Rx buffer\n");
13723526Sxy150489 return (NULL);
13733526Sxy150489 }
13743526Sxy150489
13753526Sxy150489 rx_buf->size -= E1000G_IPALIGNROOM;
13763526Sxy150489 rx_buf->address += E1000G_IPALIGNROOM;
13773526Sxy150489 rx_buf->dma_address += E1000G_IPALIGNROOM;
13783526Sxy150489
13798850SMin.Xu@Sun.COM packet->rx_data = (caddr_t)rx_data;
13803526Sxy150489 packet->free_rtn.free_func = e1000g_rxfree_func;
13813526Sxy150489 packet->free_rtn.free_arg = (char *)packet;
13823526Sxy150489 /*
13833526Sxy150489 * esballoc is changed to desballoc which
13843526Sxy150489 * is undocumented call but as per sun,
13853526Sxy150489 * we can use it. It gives better efficiency.
13863526Sxy150489 */
13873526Sxy150489 packet->mp = desballoc((unsigned char *)
13888995SMin.Xu@Sun.COM rx_buf->address,
13898995SMin.Xu@Sun.COM rx_buf->size,
13903526Sxy150489 BPRI_MED, &packet->free_rtn);
13913526Sxy150489
13923526Sxy150489 packet->dma_type = e1000g_dma_type;
13938850SMin.Xu@Sun.COM packet->ref_cnt = 1;
13943526Sxy150489
13953526Sxy150489 return (packet);
13963526Sxy150489 }
13973526Sxy150489
13983526Sxy150489 void
e1000g_free_rx_sw_packet(p_rx_sw_packet_t packet,boolean_t full_release)13998850SMin.Xu@Sun.COM e1000g_free_rx_sw_packet(p_rx_sw_packet_t packet, boolean_t full_release)
14003526Sxy150489 {
14013526Sxy150489 dma_buffer_t *rx_buf;
14023526Sxy150489
14033526Sxy150489 if (packet->mp != NULL) {
14043526Sxy150489 freemsg(packet->mp);
14053526Sxy150489 packet->mp = NULL;
14063526Sxy150489 }
14073526Sxy150489
14083526Sxy150489 rx_buf = packet->rx_buf;
14093526Sxy150489
14103526Sxy150489 switch (packet->dma_type) {
14113526Sxy150489 #ifdef __sparc
14123526Sxy150489 case USE_DVMA:
14138850SMin.Xu@Sun.COM if (rx_buf->address != NULL) {
14148850SMin.Xu@Sun.COM rx_buf->size += E1000G_IPALIGNROOM;
14158850SMin.Xu@Sun.COM rx_buf->address -= E1000G_IPALIGNROOM;
14168850SMin.Xu@Sun.COM }
14173526Sxy150489 e1000g_free_dvma_buffer(rx_buf);
14183526Sxy150489 break;
14193526Sxy150489 #endif
14203526Sxy150489 case USE_DMA:
14213526Sxy150489 e1000g_free_dma_buffer(rx_buf);
14223526Sxy150489 break;
14233526Sxy150489 default:
14243526Sxy150489 break;
14253526Sxy150489 }
14263526Sxy150489
14273526Sxy150489 packet->dma_type = USE_NONE;
14283526Sxy150489
14298850SMin.Xu@Sun.COM if (!full_release)
14308850SMin.Xu@Sun.COM return;
14318850SMin.Xu@Sun.COM
14324919Sxy150489 kmem_free(packet, sizeof (rx_sw_packet_t));
14333526Sxy150489 }
14343526Sxy150489
14353526Sxy150489 static void
e1000g_free_rx_packets(e1000g_rx_data_t * rx_data,boolean_t full_release)1436*12853SChangqing.Li@Sun.COM e1000g_free_rx_packets(e1000g_rx_data_t *rx_data, boolean_t full_release)
14373526Sxy150489 {
14388850SMin.Xu@Sun.COM p_rx_sw_packet_t packet, next_packet;
14398850SMin.Xu@Sun.COM uint32_t ref_cnt;
14403526Sxy150489
14418850SMin.Xu@Sun.COM mutex_enter(&e1000g_rx_detach_lock);
14424349Sxy150489
14438850SMin.Xu@Sun.COM packet = rx_data->packet_area;
14448850SMin.Xu@Sun.COM while (packet != NULL) {
14454349Sxy150489 next_packet = packet->next;
14464349Sxy150489
14478850SMin.Xu@Sun.COM ref_cnt = atomic_dec_32_nv(&packet->ref_cnt);
14488850SMin.Xu@Sun.COM if (ref_cnt > 0) {
14498850SMin.Xu@Sun.COM atomic_inc_32(&rx_data->pending_count);
14508850SMin.Xu@Sun.COM atomic_inc_32(&e1000g_mblks_pending);
14514349Sxy150489 } else {
1452*12853SChangqing.Li@Sun.COM e1000g_free_rx_sw_packet(packet, full_release);
14533526Sxy150489 }
14548850SMin.Xu@Sun.COM
14558850SMin.Xu@Sun.COM packet = next_packet;
14563526Sxy150489 }
14573526Sxy150489
14588850SMin.Xu@Sun.COM mutex_exit(&e1000g_rx_detach_lock);
14598850SMin.Xu@Sun.COM }
14603526Sxy150489
14613526Sxy150489
14623526Sxy150489 static void
e1000g_free_tx_packets(e1000g_tx_ring_t * tx_ring)14633526Sxy150489 e1000g_free_tx_packets(e1000g_tx_ring_t *tx_ring)
14643526Sxy150489 {
14653526Sxy150489 int j;
14663526Sxy150489 struct e1000g *Adapter;
14674919Sxy150489 p_tx_sw_packet_t packet;
14683526Sxy150489 dma_buffer_t *tx_buf;
14693526Sxy150489
14703526Sxy150489 Adapter = tx_ring->adapter;
14713526Sxy150489
14723526Sxy150489 for (j = 0, packet = tx_ring->packet_area;
14734919Sxy150489 j < Adapter->tx_freelist_num; j++, packet++) {
14743526Sxy150489
14753526Sxy150489 if (packet == NULL)
14763526Sxy150489 break;
14773526Sxy150489
14783526Sxy150489 /* Free the Tx DMA handle for dynamical binding */
14793526Sxy150489 if (packet->tx_dma_handle != NULL) {
14803526Sxy150489 switch (packet->dma_type) {
14813526Sxy150489 #ifdef __sparc
14823526Sxy150489 case USE_DVMA:
14833526Sxy150489 dvma_release(packet->tx_dma_handle);
14843526Sxy150489 break;
14853526Sxy150489 #endif
14863526Sxy150489 case USE_DMA:
14873526Sxy150489 ddi_dma_free_handle(&packet->tx_dma_handle);
14883526Sxy150489 break;
14893526Sxy150489 default:
14903526Sxy150489 ASSERT(B_FALSE);
14913526Sxy150489 break;
14923526Sxy150489 }
14933526Sxy150489 packet->tx_dma_handle = NULL;
14943526Sxy150489 } else {
14953526Sxy150489 /*
14963526Sxy150489 * If the dma handle is NULL, then we don't
14973526Sxy150489 * need to check the packets left. For they
14983526Sxy150489 * have not been initialized or have been freed.
14993526Sxy150489 */
15003526Sxy150489 break;
15013526Sxy150489 }
15023526Sxy150489
15033526Sxy150489 tx_buf = packet->tx_buf;
15043526Sxy150489
15053526Sxy150489 switch (packet->dma_type) {
15063526Sxy150489 #ifdef __sparc
15073526Sxy150489 case USE_DVMA:
15083526Sxy150489 e1000g_free_dvma_buffer(tx_buf);
15093526Sxy150489 break;
15103526Sxy150489 #endif
15113526Sxy150489 case USE_DMA:
15123526Sxy150489 e1000g_free_dma_buffer(tx_buf);
15133526Sxy150489 break;
15143526Sxy150489 default:
15153526Sxy150489 ASSERT(B_FALSE);
15163526Sxy150489 break;
15173526Sxy150489 }
15183526Sxy150489
15193526Sxy150489 packet->dma_type = USE_NONE;
15203526Sxy150489 }
15213526Sxy150489 if (tx_ring->packet_area != NULL) {
15223526Sxy150489 kmem_free(tx_ring->packet_area, TX_SW_PKT_AREA_SZ);
15233526Sxy150489 tx_ring->packet_area = NULL;
15243526Sxy150489 }
15253526Sxy150489 }
15263526Sxy150489
15273526Sxy150489 /*
15284919Sxy150489 * e1000g_release_dma_resources - release allocated DMA resources
15294919Sxy150489 *
15304919Sxy150489 * This function releases any pending buffers that has been
15314919Sxy150489 * previously allocated
15323526Sxy150489 */
15333526Sxy150489 void
e1000g_release_dma_resources(struct e1000g * Adapter)15344919Sxy150489 e1000g_release_dma_resources(struct e1000g *Adapter)
15353526Sxy150489 {
15364919Sxy150489 e1000g_free_descriptors(Adapter);
15374919Sxy150489 e1000g_free_packets(Adapter);
15383526Sxy150489 }
15395273Sgl147354
15407426SChenliang.Xu@Sun.COM /* ARGSUSED */
15415273Sgl147354 void
e1000g_set_fma_flags(int dma_flag)154211236SStephen.Hanson@Sun.COM e1000g_set_fma_flags(int dma_flag)
15435273Sgl147354 {
15445273Sgl147354 if (dma_flag) {
15455273Sgl147354 e1000g_tx_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
15465273Sgl147354 e1000g_buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
15475273Sgl147354 e1000g_desc_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
15485273Sgl147354 } else {
15495273Sgl147354 e1000g_tx_dma_attr.dma_attr_flags = 0;
15505273Sgl147354 e1000g_buf_dma_attr.dma_attr_flags = 0;
15515273Sgl147354 e1000g_desc_dma_attr.dma_attr_flags = 0;
15525273Sgl147354 }
15535273Sgl147354 }
1554