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 /* 228850SMin.Xu@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2311236SStephen.Hanson@Sun.COM * Use is subject to license terms. 243526Sxy150489 */ 253526Sxy150489 263526Sxy150489 /* 273526Sxy150489 * ********************************************************************** 283526Sxy150489 * Module Name: * 294919Sxy150489 * e1000g_alloc.c * 303526Sxy150489 * * 313526Sxy150489 * Abstract: * 324919Sxy150489 * This file contains some routines that take care of * 334919Sxy150489 * memory allocation for descriptors and buffers. * 343526Sxy150489 * * 353526Sxy150489 * ********************************************************************** 363526Sxy150489 */ 373526Sxy150489 383526Sxy150489 #include "e1000g_sw.h" 393526Sxy150489 #include "e1000g_debug.h" 403526Sxy150489 413526Sxy150489 #define TX_SW_PKT_AREA_SZ \ 424919Sxy150489 (sizeof (tx_sw_packet_t) * Adapter->tx_freelist_num) 433526Sxy150489 443526Sxy150489 static int e1000g_alloc_tx_descriptors(e1000g_tx_ring_t *); 458850SMin.Xu@Sun.COM static int e1000g_alloc_rx_descriptors(e1000g_rx_data_t *); 463526Sxy150489 static void e1000g_free_tx_descriptors(e1000g_tx_ring_t *); 478850SMin.Xu@Sun.COM static void e1000g_free_rx_descriptors(e1000g_rx_data_t *); 483526Sxy150489 static int e1000g_alloc_tx_packets(e1000g_tx_ring_t *); 498850SMin.Xu@Sun.COM static int e1000g_alloc_rx_packets(e1000g_rx_data_t *); 503526Sxy150489 static void e1000g_free_tx_packets(e1000g_tx_ring_t *); 518850SMin.Xu@Sun.COM static void e1000g_free_rx_packets(e1000g_rx_data_t *); 524919Sxy150489 static int e1000g_alloc_dma_buffer(struct e1000g *, 534919Sxy150489 dma_buffer_t *, size_t, ddi_dma_attr_t *p_dma_attr); 548178SChenlu.Chen@Sun.COM 558178SChenlu.Chen@Sun.COM /* 568178SChenlu.Chen@Sun.COM * In order to avoid address error crossing 64KB boundary 578178SChenlu.Chen@Sun.COM * during PCI-X packets receving, e1000g_alloc_dma_buffer_82546 588178SChenlu.Chen@Sun.COM * is used by some necessary adapter types. 598178SChenlu.Chen@Sun.COM */ 608178SChenlu.Chen@Sun.COM static int e1000g_alloc_dma_buffer_82546(struct e1000g *, 618178SChenlu.Chen@Sun.COM dma_buffer_t *, size_t, ddi_dma_attr_t *p_dma_attr); 628178SChenlu.Chen@Sun.COM static int e1000g_dma_mem_alloc_82546(dma_buffer_t *buf, 638178SChenlu.Chen@Sun.COM size_t size, size_t *len); 648178SChenlu.Chen@Sun.COM static boolean_t e1000g_cross_64k_bound(void *, uintptr_t); 658178SChenlu.Chen@Sun.COM 663526Sxy150489 static void e1000g_free_dma_buffer(dma_buffer_t *); 673526Sxy150489 #ifdef __sparc 683526Sxy150489 static int e1000g_alloc_dvma_buffer(struct e1000g *, dma_buffer_t *, size_t); 693526Sxy150489 static void e1000g_free_dvma_buffer(dma_buffer_t *); 703526Sxy150489 #endif 713526Sxy150489 static int e1000g_alloc_descriptors(struct e1000g *Adapter); 724919Sxy150489 static void e1000g_free_descriptors(struct e1000g *Adapter); 733526Sxy150489 static int e1000g_alloc_packets(struct e1000g *Adapter); 744919Sxy150489 static void e1000g_free_packets(struct e1000g *Adapter); 758850SMin.Xu@Sun.COM static p_rx_sw_packet_t e1000g_alloc_rx_sw_packet(e1000g_rx_data_t *, 764919Sxy150489 ddi_dma_attr_t *p_dma_attr); 774919Sxy150489 784919Sxy150489 /* DMA access attributes for descriptors <Little Endian> */ 794919Sxy150489 static ddi_device_acc_attr_t e1000g_desc_acc_attr = { 804919Sxy150489 DDI_DEVICE_ATTR_V0, 814919Sxy150489 DDI_STRUCTURE_LE_ACC, 8211236SStephen.Hanson@Sun.COM DDI_STRICTORDER_ACC 834919Sxy150489 }; 844919Sxy150489 854919Sxy150489 /* DMA access attributes for DMA buffers */ 864919Sxy150489 #ifdef __sparc 874919Sxy150489 static ddi_device_acc_attr_t e1000g_buf_acc_attr = { 884919Sxy150489 DDI_DEVICE_ATTR_V0, 894919Sxy150489 DDI_STRUCTURE_BE_ACC, 904919Sxy150489 DDI_STRICTORDER_ACC, 914919Sxy150489 }; 924919Sxy150489 #else 934919Sxy150489 static ddi_device_acc_attr_t e1000g_buf_acc_attr = { 944919Sxy150489 DDI_DEVICE_ATTR_V0, 954919Sxy150489 DDI_STRUCTURE_LE_ACC, 964919Sxy150489 DDI_STRICTORDER_ACC, 974919Sxy150489 }; 984919Sxy150489 #endif 994919Sxy150489 1004919Sxy150489 /* DMA attributes for tx mblk buffers */ 1014919Sxy150489 static ddi_dma_attr_t e1000g_tx_dma_attr = { 1024919Sxy150489 DMA_ATTR_V0, /* version of this structure */ 1034919Sxy150489 0, /* lowest usable address */ 1044919Sxy150489 0xffffffffffffffffULL, /* highest usable address */ 1054919Sxy150489 0x7fffffff, /* maximum DMAable byte count */ 1064919Sxy150489 1, /* alignment in bytes */ 1074919Sxy150489 0x7ff, /* burst sizes (any?) */ 1084919Sxy150489 1, /* minimum transfer */ 1094919Sxy150489 0xffffffffU, /* maximum transfer */ 1104919Sxy150489 0xffffffffffffffffULL, /* maximum segment length */ 1117607STed.You@Sun.COM MAX_COOKIES, /* maximum number of segments */ 1124919Sxy150489 1, /* granularity */ 1135273Sgl147354 DDI_DMA_FLAGERR, /* dma_attr_flags */ 1144919Sxy150489 }; 1154919Sxy150489 1164919Sxy150489 /* DMA attributes for pre-allocated rx/tx buffers */ 1174919Sxy150489 static ddi_dma_attr_t e1000g_buf_dma_attr = { 1184919Sxy150489 DMA_ATTR_V0, /* version of this structure */ 1194919Sxy150489 0, /* lowest usable address */ 1204919Sxy150489 0xffffffffffffffffULL, /* highest usable address */ 1214919Sxy150489 0x7fffffff, /* maximum DMAable byte count */ 1224919Sxy150489 1, /* alignment in bytes */ 1234919Sxy150489 0x7ff, /* burst sizes (any?) */ 1244919Sxy150489 1, /* minimum transfer */ 1254919Sxy150489 0xffffffffU, /* maximum transfer */ 1264919Sxy150489 0xffffffffffffffffULL, /* maximum segment length */ 1274919Sxy150489 1, /* maximum number of segments */ 1284919Sxy150489 1, /* granularity */ 1295273Sgl147354 DDI_DMA_FLAGERR, /* dma_attr_flags */ 1304919Sxy150489 }; 1314919Sxy150489 1324919Sxy150489 /* DMA attributes for rx/tx descriptors */ 1334919Sxy150489 static ddi_dma_attr_t e1000g_desc_dma_attr = { 1344919Sxy150489 DMA_ATTR_V0, /* version of this structure */ 1354919Sxy150489 0, /* lowest usable address */ 1364919Sxy150489 0xffffffffffffffffULL, /* highest usable address */ 1374919Sxy150489 0x7fffffff, /* maximum DMAable byte count */ 1388178SChenlu.Chen@Sun.COM E1000_MDALIGN, /* default alignment is 4k but can be changed */ 1394919Sxy150489 0x7ff, /* burst sizes (any?) */ 1404919Sxy150489 1, /* minimum transfer */ 1414919Sxy150489 0xffffffffU, /* maximum transfer */ 1424919Sxy150489 0xffffffffffffffffULL, /* maximum segment length */ 1434919Sxy150489 1, /* maximum number of segments */ 1444919Sxy150489 1, /* granularity */ 1455273Sgl147354 DDI_DMA_FLAGERR, /* dma_attr_flags */ 1464919Sxy150489 }; 1473526Sxy150489 1483526Sxy150489 #ifdef __sparc 1493526Sxy150489 static ddi_dma_lim_t e1000g_dma_limits = { 1503526Sxy150489 (uint_t)0, /* dlim_addr_lo */ 1513526Sxy150489 (uint_t)0xffffffff, /* dlim_addr_hi */ 1523526Sxy150489 (uint_t)0xffffffff, /* dlim_cntr_max */ 1533526Sxy150489 (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 1543526Sxy150489 0x1, /* dlim_minxfer */ 1553526Sxy150489 1024 /* dlim_speed */ 1563526Sxy150489 }; 1573526Sxy150489 #endif 1583526Sxy150489 1593526Sxy150489 #ifdef __sparc 1603526Sxy150489 static dma_type_t e1000g_dma_type = USE_DVMA; 1613526Sxy150489 #else 1623526Sxy150489 static dma_type_t e1000g_dma_type = USE_DMA; 1633526Sxy150489 #endif 1643526Sxy150489 1653526Sxy150489 extern krwlock_t e1000g_dma_type_lock; 1663526Sxy150489 1674919Sxy150489 1683526Sxy150489 int 1693526Sxy150489 e1000g_alloc_dma_resources(struct e1000g *Adapter) 1703526Sxy150489 { 1714919Sxy150489 int result; 1724919Sxy150489 1734919Sxy150489 result = DDI_FAILURE; 1743526Sxy150489 1754919Sxy150489 while ((result != DDI_SUCCESS) && 1764919Sxy150489 (Adapter->tx_desc_num >= MIN_NUM_TX_DESCRIPTOR) && 1774919Sxy150489 (Adapter->rx_desc_num >= MIN_NUM_RX_DESCRIPTOR) && 1784919Sxy150489 (Adapter->tx_freelist_num >= MIN_NUM_TX_FREELIST) && 1794919Sxy150489 (Adapter->rx_freelist_num >= MIN_NUM_RX_FREELIST)) { 1804919Sxy150489 1814919Sxy150489 result = e1000g_alloc_descriptors(Adapter); 1824919Sxy150489 1834919Sxy150489 if (result == DDI_SUCCESS) { 1844919Sxy150489 result = e1000g_alloc_packets(Adapter); 1854919Sxy150489 1864919Sxy150489 if (result != DDI_SUCCESS) 1874919Sxy150489 e1000g_free_descriptors(Adapter); 1884919Sxy150489 } 1893526Sxy150489 1904919Sxy150489 /* 1914919Sxy150489 * If the allocation fails due to resource shortage, 1924919Sxy150489 * we'll reduce the numbers of descriptors/buffers by 1934919Sxy150489 * half, and try the allocation again. 1944919Sxy150489 */ 1954919Sxy150489 if (result != DDI_SUCCESS) { 1964919Sxy150489 /* 1974919Sxy150489 * We must ensure the number of descriptors 1984919Sxy150489 * is always a multiple of 8. 1994919Sxy150489 */ 2004919Sxy150489 Adapter->tx_desc_num = 2014919Sxy150489 (Adapter->tx_desc_num >> 4) << 3; 2024919Sxy150489 Adapter->rx_desc_num = 2034919Sxy150489 (Adapter->rx_desc_num >> 4) << 3; 2043526Sxy150489 2054919Sxy150489 Adapter->tx_freelist_num >>= 1; 2064919Sxy150489 Adapter->rx_freelist_num >>= 1; 2074919Sxy150489 } 2083526Sxy150489 } 2093526Sxy150489 2104919Sxy150489 return (result); 2113526Sxy150489 } 2123526Sxy150489 2133526Sxy150489 /* 2144919Sxy150489 * e1000g_alloc_descriptors - allocate DMA buffers for descriptors 2154919Sxy150489 * 2164919Sxy150489 * This routine allocates neccesary DMA buffers for 2174919Sxy150489 * Transmit Descriptor Area 2184919Sxy150489 * Receive Descrpitor Area 2193526Sxy150489 */ 2203526Sxy150489 static int 2213526Sxy150489 e1000g_alloc_descriptors(struct e1000g *Adapter) 2223526Sxy150489 { 2233526Sxy150489 int result; 2243526Sxy150489 e1000g_tx_ring_t *tx_ring; 2258850SMin.Xu@Sun.COM e1000g_rx_data_t *rx_data; 2263526Sxy150489 2278417SChenlu.Chen@Sun.COM if (Adapter->mem_workaround_82546 && 2288417SChenlu.Chen@Sun.COM ((Adapter->shared.mac.type == e1000_82545) || 2298178SChenlu.Chen@Sun.COM (Adapter->shared.mac.type == e1000_82546) || 2308417SChenlu.Chen@Sun.COM (Adapter->shared.mac.type == e1000_82546_rev_3))) { 2318178SChenlu.Chen@Sun.COM /* Align on a 64k boundary for these adapter types */ 2328178SChenlu.Chen@Sun.COM Adapter->desc_align = E1000_MDALIGN_82546; 2338178SChenlu.Chen@Sun.COM } else { 2348178SChenlu.Chen@Sun.COM /* Align on a 4k boundary for all other adapter types */ 2358178SChenlu.Chen@Sun.COM Adapter->desc_align = E1000_MDALIGN; 2368178SChenlu.Chen@Sun.COM } 2378178SChenlu.Chen@Sun.COM 2383526Sxy150489 tx_ring = Adapter->tx_ring; 2393526Sxy150489 2403526Sxy150489 result = e1000g_alloc_tx_descriptors(tx_ring); 2413526Sxy150489 if (result != DDI_SUCCESS) 2423526Sxy150489 return (DDI_FAILURE); 2433526Sxy150489 2448850SMin.Xu@Sun.COM rx_data = Adapter->rx_ring->rx_data; 2453526Sxy150489 2468850SMin.Xu@Sun.COM result = e1000g_alloc_rx_descriptors(rx_data); 2473526Sxy150489 if (result != DDI_SUCCESS) { 2483526Sxy150489 e1000g_free_tx_descriptors(tx_ring); 2493526Sxy150489 return (DDI_FAILURE); 2503526Sxy150489 } 2513526Sxy150489 2523526Sxy150489 return (DDI_SUCCESS); 2533526Sxy150489 } 2543526Sxy150489 2554919Sxy150489 static void 2564919Sxy150489 e1000g_free_descriptors(struct e1000g *Adapter) 2574919Sxy150489 { 2584919Sxy150489 e1000g_tx_ring_t *tx_ring; 2598850SMin.Xu@Sun.COM e1000g_rx_data_t *rx_data; 2604919Sxy150489 2614919Sxy150489 tx_ring = Adapter->tx_ring; 2628850SMin.Xu@Sun.COM rx_data = Adapter->rx_ring->rx_data; 2634919Sxy150489 2644919Sxy150489 e1000g_free_tx_descriptors(tx_ring); 2658850SMin.Xu@Sun.COM e1000g_free_rx_descriptors(rx_data); 2664919Sxy150489 } 2674919Sxy150489 2683526Sxy150489 static int 2693526Sxy150489 e1000g_alloc_tx_descriptors(e1000g_tx_ring_t *tx_ring) 2703526Sxy150489 { 2713526Sxy150489 int mystat; 2723526Sxy150489 boolean_t alloc_flag; 2733526Sxy150489 size_t size; 2743526Sxy150489 size_t len; 2753526Sxy150489 uintptr_t templong; 2763526Sxy150489 uint_t cookie_count; 2773526Sxy150489 dev_info_t *devinfo; 2783526Sxy150489 ddi_dma_cookie_t cookie; 2793526Sxy150489 struct e1000g *Adapter; 2804919Sxy150489 ddi_dma_attr_t dma_attr; 2813526Sxy150489 2823526Sxy150489 Adapter = tx_ring->adapter; 2834919Sxy150489 devinfo = Adapter->dip; 2843526Sxy150489 2853526Sxy150489 alloc_flag = B_FALSE; 2864919Sxy150489 dma_attr = e1000g_desc_dma_attr; 2873526Sxy150489 2883526Sxy150489 /* 2893526Sxy150489 * Solaris 7 has a problem with allocating physically contiguous memory 2903526Sxy150489 * that is aligned on a 4K boundary. The transmit and rx descriptors 2913526Sxy150489 * need to aligned on a 4kbyte boundary. We first try to allocate the 2923526Sxy150489 * memory with DMA attributes set to 4K alignment and also no scatter/ 2933526Sxy150489 * gather mechanism specified. In most cases, this does not allocate 2943526Sxy150489 * memory aligned at a 4Kbyte boundary. We then try asking for memory 2953526Sxy150489 * aligned on 4K boundary with scatter/gather set to 2. This works when 2963526Sxy150489 * the amount of memory is less than 4k i.e a page size. If neither of 2973526Sxy150489 * these options work or if the number of descriptors is greater than 2983526Sxy150489 * 4K, ie more than 256 descriptors, we allocate 4k extra memory and 2993526Sxy150489 * and then align the memory at a 4k boundary. 3003526Sxy150489 */ 3014919Sxy150489 size = sizeof (struct e1000_tx_desc) * Adapter->tx_desc_num; 3023526Sxy150489 3033526Sxy150489 /* 3043526Sxy150489 * Memory allocation for the transmit buffer descriptors. 3053526Sxy150489 */ 3064919Sxy150489 dma_attr.dma_attr_sgllen = 1; 3078178SChenlu.Chen@Sun.COM dma_attr.dma_attr_align = Adapter->desc_align; 3083526Sxy150489 3093526Sxy150489 /* 3103526Sxy150489 * Allocate a new DMA handle for the transmit descriptor 3113526Sxy150489 * memory area. 3123526Sxy150489 */ 3134919Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, &dma_attr, 3143526Sxy150489 DDI_DMA_DONTWAIT, 0, 3153526Sxy150489 &tx_ring->tbd_dma_handle); 3163526Sxy150489 3173526Sxy150489 if (mystat != DDI_SUCCESS) { 3184919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 3193526Sxy150489 "Could not allocate tbd dma handle: %d", mystat); 3203526Sxy150489 tx_ring->tbd_dma_handle = NULL; 3213526Sxy150489 return (DDI_FAILURE); 3223526Sxy150489 } 3233526Sxy150489 3243526Sxy150489 /* 3253526Sxy150489 * Allocate memory to DMA data to and from the transmit 3263526Sxy150489 * descriptors. 3273526Sxy150489 */ 3283526Sxy150489 mystat = ddi_dma_mem_alloc(tx_ring->tbd_dma_handle, 3293526Sxy150489 size, 3304919Sxy150489 &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT, 3313526Sxy150489 DDI_DMA_DONTWAIT, 0, 3323526Sxy150489 (caddr_t *)&tx_ring->tbd_area, 3333526Sxy150489 &len, &tx_ring->tbd_acc_handle); 3343526Sxy150489 3353526Sxy150489 if ((mystat != DDI_SUCCESS) || 3368178SChenlu.Chen@Sun.COM ((uintptr_t)tx_ring->tbd_area & (Adapter->desc_align - 1))) { 3373526Sxy150489 if (mystat == DDI_SUCCESS) { 3383526Sxy150489 ddi_dma_mem_free(&tx_ring->tbd_acc_handle); 3393526Sxy150489 tx_ring->tbd_acc_handle = NULL; 3403526Sxy150489 tx_ring->tbd_area = NULL; 3413526Sxy150489 } 3423526Sxy150489 if (tx_ring->tbd_dma_handle != NULL) { 3433526Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_dma_handle); 3443526Sxy150489 tx_ring->tbd_dma_handle = NULL; 3453526Sxy150489 } 3463526Sxy150489 alloc_flag = B_FALSE; 3473526Sxy150489 } else 3483526Sxy150489 alloc_flag = B_TRUE; 3493526Sxy150489 3503526Sxy150489 /* 3513526Sxy150489 * Initialize the entire transmit buffer descriptor area to zero 3523526Sxy150489 */ 3533526Sxy150489 if (alloc_flag) 3543526Sxy150489 bzero(tx_ring->tbd_area, len); 3553526Sxy150489 3563526Sxy150489 /* 3573526Sxy150489 * If the previous DMA attributes setting could not give us contiguous 3583526Sxy150489 * memory or the number of descriptors is greater than the page size, 3598178SChenlu.Chen@Sun.COM * we allocate extra memory and then align it at appropriate boundary. 3603526Sxy150489 */ 3613526Sxy150489 if (!alloc_flag) { 3628178SChenlu.Chen@Sun.COM size = size + Adapter->desc_align; 3633526Sxy150489 3643526Sxy150489 /* 3653526Sxy150489 * DMA attributes set to no scatter/gather and 16 bit alignment 3663526Sxy150489 */ 3674919Sxy150489 dma_attr.dma_attr_align = 1; 3684919Sxy150489 dma_attr.dma_attr_sgllen = 1; 3693526Sxy150489 3703526Sxy150489 /* 3713526Sxy150489 * Allocate a new DMA handle for the transmit descriptor memory 3723526Sxy150489 * area. 3733526Sxy150489 */ 3744919Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, &dma_attr, 3753526Sxy150489 DDI_DMA_DONTWAIT, 0, 3763526Sxy150489 &tx_ring->tbd_dma_handle); 3773526Sxy150489 3783526Sxy150489 if (mystat != DDI_SUCCESS) { 3794919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 3803526Sxy150489 "Could not re-allocate tbd dma handle: %d", mystat); 3813526Sxy150489 tx_ring->tbd_dma_handle = NULL; 3823526Sxy150489 return (DDI_FAILURE); 3833526Sxy150489 } 3843526Sxy150489 3853526Sxy150489 /* 3863526Sxy150489 * Allocate memory to DMA data to and from the transmit 3873526Sxy150489 * descriptors. 3883526Sxy150489 */ 3893526Sxy150489 mystat = ddi_dma_mem_alloc(tx_ring->tbd_dma_handle, 3903526Sxy150489 size, 3914919Sxy150489 &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT, 3923526Sxy150489 DDI_DMA_DONTWAIT, 0, 3933526Sxy150489 (caddr_t *)&tx_ring->tbd_area, 3943526Sxy150489 &len, &tx_ring->tbd_acc_handle); 3953526Sxy150489 3963526Sxy150489 if (mystat != DDI_SUCCESS) { 3974919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 3983526Sxy150489 "Could not allocate tbd dma memory: %d", mystat); 3993526Sxy150489 tx_ring->tbd_acc_handle = NULL; 4003526Sxy150489 tx_ring->tbd_area = NULL; 4013526Sxy150489 if (tx_ring->tbd_dma_handle != NULL) { 4023526Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_dma_handle); 4033526Sxy150489 tx_ring->tbd_dma_handle = NULL; 4043526Sxy150489 } 4053526Sxy150489 return (DDI_FAILURE); 4063526Sxy150489 } else 4073526Sxy150489 alloc_flag = B_TRUE; 4083526Sxy150489 4093526Sxy150489 /* 4103526Sxy150489 * Initialize the entire transmit buffer descriptor area to zero 4113526Sxy150489 */ 4123526Sxy150489 bzero(tx_ring->tbd_area, len); 4133526Sxy150489 /* 4143526Sxy150489 * Memory has been allocated with the ddi_dma_mem_alloc call, 4158178SChenlu.Chen@Sun.COM * but has not been aligned. 4168178SChenlu.Chen@Sun.COM * We now align it on the appropriate boundary. 4173526Sxy150489 */ 4188178SChenlu.Chen@Sun.COM templong = P2NPHASE((uintptr_t)tx_ring->tbd_area, 4198178SChenlu.Chen@Sun.COM Adapter->desc_align); 4203526Sxy150489 len = size - templong; 4213526Sxy150489 templong += (uintptr_t)tx_ring->tbd_area; 4223526Sxy150489 tx_ring->tbd_area = (struct e1000_tx_desc *)templong; 4233526Sxy150489 } /* alignment workaround */ 4243526Sxy150489 4253526Sxy150489 /* 4263526Sxy150489 * Transmit buffer descriptor memory allocation succeeded 4273526Sxy150489 */ 4283526Sxy150489 ASSERT(alloc_flag); 4293526Sxy150489 4303526Sxy150489 /* 4313526Sxy150489 * Allocates DMA resources for the memory that was allocated by 4323526Sxy150489 * the ddi_dma_mem_alloc call. The DMA resources then get bound to the 4333526Sxy150489 * the memory address 4343526Sxy150489 */ 4353526Sxy150489 mystat = ddi_dma_addr_bind_handle(tx_ring->tbd_dma_handle, 4363526Sxy150489 (struct as *)NULL, (caddr_t)tx_ring->tbd_area, 4373526Sxy150489 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 4384919Sxy150489 DDI_DMA_DONTWAIT, 0, &cookie, &cookie_count); 4393526Sxy150489 4403526Sxy150489 if (mystat != DDI_SUCCESS) { 4414919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 4423526Sxy150489 "Could not bind tbd dma resource: %d", mystat); 4433526Sxy150489 if (tx_ring->tbd_acc_handle != NULL) { 4443526Sxy150489 ddi_dma_mem_free(&tx_ring->tbd_acc_handle); 4453526Sxy150489 tx_ring->tbd_acc_handle = NULL; 4463526Sxy150489 tx_ring->tbd_area = NULL; 4473526Sxy150489 } 4483526Sxy150489 if (tx_ring->tbd_dma_handle != NULL) { 4493526Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_dma_handle); 4503526Sxy150489 tx_ring->tbd_dma_handle = NULL; 4513526Sxy150489 } 4523526Sxy150489 return (DDI_FAILURE); 4533526Sxy150489 } 4543526Sxy150489 4553526Sxy150489 ASSERT(cookie_count == 1); /* 1 cookie */ 4563526Sxy150489 4573526Sxy150489 if (cookie_count != 1) { 4584919Sxy150489 E1000G_DEBUGLOG_2(Adapter, E1000G_WARN_LEVEL, 4593526Sxy150489 "Could not bind tbd dma resource in a single frag. " 4603526Sxy150489 "Count - %d Len - %d", cookie_count, len); 4613526Sxy150489 e1000g_free_tx_descriptors(tx_ring); 4623526Sxy150489 return (DDI_FAILURE); 4633526Sxy150489 } 4643526Sxy150489 4653526Sxy150489 tx_ring->tbd_dma_addr = cookie.dmac_laddress; 4663526Sxy150489 tx_ring->tbd_first = tx_ring->tbd_area; 4673526Sxy150489 tx_ring->tbd_last = tx_ring->tbd_first + 4684919Sxy150489 (Adapter->tx_desc_num - 1); 4693526Sxy150489 4703526Sxy150489 return (DDI_SUCCESS); 4713526Sxy150489 } 4723526Sxy150489 4733526Sxy150489 static int 4748850SMin.Xu@Sun.COM e1000g_alloc_rx_descriptors(e1000g_rx_data_t *rx_data) 4753526Sxy150489 { 4763526Sxy150489 int mystat; 4773526Sxy150489 boolean_t alloc_flag; 4783526Sxy150489 size_t size; 4793526Sxy150489 size_t len; 4803526Sxy150489 uintptr_t templong; 4813526Sxy150489 uint_t cookie_count; 4823526Sxy150489 dev_info_t *devinfo; 4833526Sxy150489 ddi_dma_cookie_t cookie; 4843526Sxy150489 struct e1000g *Adapter; 4854919Sxy150489 ddi_dma_attr_t dma_attr; 4863526Sxy150489 4878850SMin.Xu@Sun.COM Adapter = rx_data->rx_ring->adapter; 4884919Sxy150489 devinfo = Adapter->dip; 4893526Sxy150489 4903526Sxy150489 alloc_flag = B_FALSE; 4914919Sxy150489 dma_attr = e1000g_desc_dma_attr; 4923526Sxy150489 4933526Sxy150489 /* 4943526Sxy150489 * Memory allocation for the receive buffer descriptors. 4953526Sxy150489 */ 4964919Sxy150489 size = (sizeof (struct e1000_rx_desc)) * Adapter->rx_desc_num; 4973526Sxy150489 4983526Sxy150489 /* 4998178SChenlu.Chen@Sun.COM * Asking for aligned memory with DMA attributes set for suitable value 5003526Sxy150489 */ 5014919Sxy150489 dma_attr.dma_attr_sgllen = 1; 5028178SChenlu.Chen@Sun.COM dma_attr.dma_attr_align = Adapter->desc_align; 5033526Sxy150489 5043526Sxy150489 /* 5054919Sxy150489 * Allocate a new DMA handle for the receive descriptors 5063526Sxy150489 */ 5074919Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, &dma_attr, 5083526Sxy150489 DDI_DMA_DONTWAIT, 0, 5098850SMin.Xu@Sun.COM &rx_data->rbd_dma_handle); 5103526Sxy150489 5113526Sxy150489 if (mystat != DDI_SUCCESS) { 5124919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 5133526Sxy150489 "Could not allocate rbd dma handle: %d", mystat); 5148850SMin.Xu@Sun.COM rx_data->rbd_dma_handle = NULL; 5153526Sxy150489 return (DDI_FAILURE); 5163526Sxy150489 } 5173526Sxy150489 /* 5183526Sxy150489 * Allocate memory to DMA data to and from the receive 5193526Sxy150489 * descriptors. 5203526Sxy150489 */ 5218850SMin.Xu@Sun.COM mystat = ddi_dma_mem_alloc(rx_data->rbd_dma_handle, 5223526Sxy150489 size, 5234919Sxy150489 &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT, 5243526Sxy150489 DDI_DMA_DONTWAIT, 0, 5258850SMin.Xu@Sun.COM (caddr_t *)&rx_data->rbd_area, 5268850SMin.Xu@Sun.COM &len, &rx_data->rbd_acc_handle); 5273526Sxy150489 5283526Sxy150489 /* 5293526Sxy150489 * Check if memory allocation succeeded and also if the 5303526Sxy150489 * allocated memory is aligned correctly. 5313526Sxy150489 */ 5323526Sxy150489 if ((mystat != DDI_SUCCESS) || 5338850SMin.Xu@Sun.COM ((uintptr_t)rx_data->rbd_area & (Adapter->desc_align - 1))) { 5343526Sxy150489 if (mystat == DDI_SUCCESS) { 5358850SMin.Xu@Sun.COM ddi_dma_mem_free(&rx_data->rbd_acc_handle); 5368850SMin.Xu@Sun.COM rx_data->rbd_acc_handle = NULL; 5378850SMin.Xu@Sun.COM rx_data->rbd_area = NULL; 5383526Sxy150489 } 5398850SMin.Xu@Sun.COM if (rx_data->rbd_dma_handle != NULL) { 5408850SMin.Xu@Sun.COM ddi_dma_free_handle(&rx_data->rbd_dma_handle); 5418850SMin.Xu@Sun.COM rx_data->rbd_dma_handle = NULL; 5423526Sxy150489 } 5433526Sxy150489 alloc_flag = B_FALSE; 5443526Sxy150489 } else 5453526Sxy150489 alloc_flag = B_TRUE; 5463526Sxy150489 5473526Sxy150489 /* 5483526Sxy150489 * Initialize the allocated receive descriptor memory to zero. 5493526Sxy150489 */ 5503526Sxy150489 if (alloc_flag) 5518850SMin.Xu@Sun.COM bzero((caddr_t)rx_data->rbd_area, len); 5523526Sxy150489 5533526Sxy150489 /* 5544919Sxy150489 * If memory allocation did not succeed, do the alignment ourselves 5553526Sxy150489 */ 5563526Sxy150489 if (!alloc_flag) { 5574919Sxy150489 dma_attr.dma_attr_align = 1; 5584919Sxy150489 dma_attr.dma_attr_sgllen = 1; 5598178SChenlu.Chen@Sun.COM size = size + Adapter->desc_align; 5603526Sxy150489 /* 5614919Sxy150489 * Allocate a new DMA handle for the receive descriptor. 5623526Sxy150489 */ 5634919Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, &dma_attr, 5643526Sxy150489 DDI_DMA_DONTWAIT, 0, 5658850SMin.Xu@Sun.COM &rx_data->rbd_dma_handle); 5663526Sxy150489 5673526Sxy150489 if (mystat != DDI_SUCCESS) { 5684919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 5693526Sxy150489 "Could not re-allocate rbd dma handle: %d", mystat); 5708850SMin.Xu@Sun.COM rx_data->rbd_dma_handle = NULL; 5713526Sxy150489 return (DDI_FAILURE); 5723526Sxy150489 } 5733526Sxy150489 /* 5743526Sxy150489 * Allocate memory to DMA data to and from the receive 5753526Sxy150489 * descriptors. 5763526Sxy150489 */ 5778850SMin.Xu@Sun.COM mystat = ddi_dma_mem_alloc(rx_data->rbd_dma_handle, 5783526Sxy150489 size, 5794919Sxy150489 &e1000g_desc_acc_attr, DDI_DMA_CONSISTENT, 5803526Sxy150489 DDI_DMA_DONTWAIT, 0, 5818850SMin.Xu@Sun.COM (caddr_t *)&rx_data->rbd_area, 5828850SMin.Xu@Sun.COM &len, &rx_data->rbd_acc_handle); 5833526Sxy150489 5843526Sxy150489 if (mystat != DDI_SUCCESS) { 5854919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 5863526Sxy150489 "Could not allocate rbd dma memory: %d", mystat); 5878850SMin.Xu@Sun.COM rx_data->rbd_acc_handle = NULL; 5888850SMin.Xu@Sun.COM rx_data->rbd_area = NULL; 5898850SMin.Xu@Sun.COM if (rx_data->rbd_dma_handle != NULL) { 5908850SMin.Xu@Sun.COM ddi_dma_free_handle(&rx_data->rbd_dma_handle); 5918850SMin.Xu@Sun.COM rx_data->rbd_dma_handle = NULL; 5923526Sxy150489 } 5933526Sxy150489 return (DDI_FAILURE); 5943526Sxy150489 } else 5953526Sxy150489 alloc_flag = B_TRUE; 5963526Sxy150489 5973526Sxy150489 /* 5983526Sxy150489 * Initialize the allocated receive descriptor memory to zero. 5993526Sxy150489 */ 6008850SMin.Xu@Sun.COM bzero((caddr_t)rx_data->rbd_area, len); 6018850SMin.Xu@Sun.COM templong = P2NPHASE((uintptr_t)rx_data->rbd_area, 6028178SChenlu.Chen@Sun.COM Adapter->desc_align); 6033526Sxy150489 len = size - templong; 6048850SMin.Xu@Sun.COM templong += (uintptr_t)rx_data->rbd_area; 6058850SMin.Xu@Sun.COM rx_data->rbd_area = (struct e1000_rx_desc *)templong; 6063526Sxy150489 } /* alignment workaround */ 6073526Sxy150489 6083526Sxy150489 /* 6093526Sxy150489 * The memory allocation of the receive descriptors succeeded 6103526Sxy150489 */ 6113526Sxy150489 ASSERT(alloc_flag); 6123526Sxy150489 6133526Sxy150489 /* 6143526Sxy150489 * Allocates DMA resources for the memory that was allocated by 6153526Sxy150489 * the ddi_dma_mem_alloc call. 6163526Sxy150489 */ 6178850SMin.Xu@Sun.COM mystat = ddi_dma_addr_bind_handle(rx_data->rbd_dma_handle, 6188850SMin.Xu@Sun.COM (struct as *)NULL, (caddr_t)rx_data->rbd_area, 6194349Sxy150489 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 6204919Sxy150489 DDI_DMA_DONTWAIT, 0, &cookie, &cookie_count); 6213526Sxy150489 6223526Sxy150489 if (mystat != DDI_SUCCESS) { 6234919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 6243526Sxy150489 "Could not bind rbd dma resource: %d", mystat); 6258850SMin.Xu@Sun.COM if (rx_data->rbd_acc_handle != NULL) { 6268850SMin.Xu@Sun.COM ddi_dma_mem_free(&rx_data->rbd_acc_handle); 6278850SMin.Xu@Sun.COM rx_data->rbd_acc_handle = NULL; 6288850SMin.Xu@Sun.COM rx_data->rbd_area = NULL; 6293526Sxy150489 } 6308850SMin.Xu@Sun.COM if (rx_data->rbd_dma_handle != NULL) { 6318850SMin.Xu@Sun.COM ddi_dma_free_handle(&rx_data->rbd_dma_handle); 6328850SMin.Xu@Sun.COM rx_data->rbd_dma_handle = NULL; 6333526Sxy150489 } 6343526Sxy150489 return (DDI_FAILURE); 6353526Sxy150489 } 6363526Sxy150489 6373526Sxy150489 ASSERT(cookie_count == 1); 6383526Sxy150489 if (cookie_count != 1) { 6394919Sxy150489 E1000G_DEBUGLOG_2(Adapter, E1000G_WARN_LEVEL, 6403526Sxy150489 "Could not bind rbd dma resource in a single frag. " 6413526Sxy150489 "Count - %d Len - %d", cookie_count, len); 6428850SMin.Xu@Sun.COM e1000g_free_rx_descriptors(rx_data); 6433526Sxy150489 return (DDI_FAILURE); 6443526Sxy150489 } 6454919Sxy150489 6468850SMin.Xu@Sun.COM rx_data->rbd_dma_addr = cookie.dmac_laddress; 6478850SMin.Xu@Sun.COM rx_data->rbd_first = rx_data->rbd_area; 6488850SMin.Xu@Sun.COM rx_data->rbd_last = rx_data->rbd_first + 6494919Sxy150489 (Adapter->rx_desc_num - 1); 6503526Sxy150489 6513526Sxy150489 return (DDI_SUCCESS); 6523526Sxy150489 } 6533526Sxy150489 6543526Sxy150489 static void 6558850SMin.Xu@Sun.COM e1000g_free_rx_descriptors(e1000g_rx_data_t *rx_data) 6563526Sxy150489 { 6578850SMin.Xu@Sun.COM if (rx_data->rbd_dma_handle != NULL) { 6588850SMin.Xu@Sun.COM (void) ddi_dma_unbind_handle(rx_data->rbd_dma_handle); 6593526Sxy150489 } 6608850SMin.Xu@Sun.COM if (rx_data->rbd_acc_handle != NULL) { 6618850SMin.Xu@Sun.COM ddi_dma_mem_free(&rx_data->rbd_acc_handle); 6628850SMin.Xu@Sun.COM rx_data->rbd_acc_handle = NULL; 6638850SMin.Xu@Sun.COM rx_data->rbd_area = NULL; 6643526Sxy150489 } 6658850SMin.Xu@Sun.COM if (rx_data->rbd_dma_handle != NULL) { 6668850SMin.Xu@Sun.COM ddi_dma_free_handle(&rx_data->rbd_dma_handle); 6678850SMin.Xu@Sun.COM rx_data->rbd_dma_handle = NULL; 6683526Sxy150489 } 6698850SMin.Xu@Sun.COM rx_data->rbd_dma_addr = NULL; 6708850SMin.Xu@Sun.COM rx_data->rbd_first = NULL; 6718850SMin.Xu@Sun.COM rx_data->rbd_last = NULL; 6723526Sxy150489 } 6733526Sxy150489 6743526Sxy150489 static void 6753526Sxy150489 e1000g_free_tx_descriptors(e1000g_tx_ring_t *tx_ring) 6763526Sxy150489 { 6773526Sxy150489 if (tx_ring->tbd_dma_handle != NULL) { 6787426SChenliang.Xu@Sun.COM (void) ddi_dma_unbind_handle(tx_ring->tbd_dma_handle); 6793526Sxy150489 } 6803526Sxy150489 if (tx_ring->tbd_acc_handle != NULL) { 6813526Sxy150489 ddi_dma_mem_free(&tx_ring->tbd_acc_handle); 6823526Sxy150489 tx_ring->tbd_acc_handle = NULL; 6833526Sxy150489 tx_ring->tbd_area = NULL; 6843526Sxy150489 } 6853526Sxy150489 if (tx_ring->tbd_dma_handle != NULL) { 6863526Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_dma_handle); 6873526Sxy150489 tx_ring->tbd_dma_handle = NULL; 6883526Sxy150489 } 6893526Sxy150489 tx_ring->tbd_dma_addr = NULL; 6903526Sxy150489 tx_ring->tbd_first = NULL; 6913526Sxy150489 tx_ring->tbd_last = NULL; 6923526Sxy150489 } 6933526Sxy150489 6943526Sxy150489 6953526Sxy150489 /* 6964919Sxy150489 * e1000g_alloc_packets - allocate DMA buffers for rx/tx 6974919Sxy150489 * 6984919Sxy150489 * This routine allocates neccesary buffers for 6994919Sxy150489 * Transmit sw packet structure 7004919Sxy150489 * DMA handle for Transmit 7014919Sxy150489 * DMA buffer for Transmit 7024919Sxy150489 * Receive sw packet structure 7034919Sxy150489 * DMA buffer for Receive 7043526Sxy150489 */ 7053526Sxy150489 static int 7063526Sxy150489 e1000g_alloc_packets(struct e1000g *Adapter) 7073526Sxy150489 { 7083526Sxy150489 int result; 7093526Sxy150489 e1000g_tx_ring_t *tx_ring; 7108850SMin.Xu@Sun.COM e1000g_rx_data_t *rx_data; 7113526Sxy150489 7123526Sxy150489 tx_ring = Adapter->tx_ring; 7138850SMin.Xu@Sun.COM rx_data = Adapter->rx_ring->rx_data; 7143526Sxy150489 7153526Sxy150489 again: 7163526Sxy150489 rw_enter(&e1000g_dma_type_lock, RW_READER); 7173526Sxy150489 7183526Sxy150489 result = e1000g_alloc_tx_packets(tx_ring); 7193526Sxy150489 if (result != DDI_SUCCESS) { 7203526Sxy150489 if (e1000g_dma_type == USE_DVMA) { 7213526Sxy150489 rw_exit(&e1000g_dma_type_lock); 7223526Sxy150489 7233526Sxy150489 rw_enter(&e1000g_dma_type_lock, RW_WRITER); 7243526Sxy150489 e1000g_dma_type = USE_DMA; 7253526Sxy150489 rw_exit(&e1000g_dma_type_lock); 7263526Sxy150489 7274919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL, 7283526Sxy150489 "No enough dvma resource for Tx packets, " 7293526Sxy150489 "trying to allocate dma buffers...\n"); 7303526Sxy150489 goto again; 7313526Sxy150489 } 7323526Sxy150489 rw_exit(&e1000g_dma_type_lock); 7333526Sxy150489 7344919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL, 7353526Sxy150489 "Failed to allocate dma buffers for Tx packets\n"); 7363526Sxy150489 return (DDI_FAILURE); 7373526Sxy150489 } 7383526Sxy150489 7398850SMin.Xu@Sun.COM result = e1000g_alloc_rx_packets(rx_data); 7403526Sxy150489 if (result != DDI_SUCCESS) { 7413526Sxy150489 e1000g_free_tx_packets(tx_ring); 7423526Sxy150489 if (e1000g_dma_type == USE_DVMA) { 7433526Sxy150489 rw_exit(&e1000g_dma_type_lock); 7443526Sxy150489 7453526Sxy150489 rw_enter(&e1000g_dma_type_lock, RW_WRITER); 7463526Sxy150489 e1000g_dma_type = USE_DMA; 7473526Sxy150489 rw_exit(&e1000g_dma_type_lock); 7483526Sxy150489 7494919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_INFO_LEVEL, 7503526Sxy150489 "No enough dvma resource for Rx packets, " 7513526Sxy150489 "trying to allocate dma buffers...\n"); 7523526Sxy150489 goto again; 7533526Sxy150489 } 7543526Sxy150489 rw_exit(&e1000g_dma_type_lock); 7553526Sxy150489 7564919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL, 7573526Sxy150489 "Failed to allocate dma buffers for Rx packets\n"); 7583526Sxy150489 return (DDI_FAILURE); 7593526Sxy150489 } 7603526Sxy150489 7613526Sxy150489 rw_exit(&e1000g_dma_type_lock); 7623526Sxy150489 7633526Sxy150489 return (DDI_SUCCESS); 7643526Sxy150489 } 7653526Sxy150489 7664919Sxy150489 static void 7674919Sxy150489 e1000g_free_packets(struct e1000g *Adapter) 7684919Sxy150489 { 7694919Sxy150489 e1000g_tx_ring_t *tx_ring; 7708850SMin.Xu@Sun.COM e1000g_rx_data_t *rx_data; 7714919Sxy150489 7724919Sxy150489 tx_ring = Adapter->tx_ring; 7738850SMin.Xu@Sun.COM rx_data = Adapter->rx_ring->rx_data; 7744919Sxy150489 7754919Sxy150489 e1000g_free_tx_packets(tx_ring); 7768850SMin.Xu@Sun.COM e1000g_free_rx_packets(rx_data); 7774919Sxy150489 } 7784919Sxy150489 7793526Sxy150489 #ifdef __sparc 7803526Sxy150489 static int 7813526Sxy150489 e1000g_alloc_dvma_buffer(struct e1000g *Adapter, 7823526Sxy150489 dma_buffer_t *buf, size_t size) 7833526Sxy150489 { 7843526Sxy150489 int mystat; 7853526Sxy150489 dev_info_t *devinfo; 7863526Sxy150489 ddi_dma_cookie_t cookie; 7873526Sxy150489 7884349Sxy150489 if (e1000g_force_detach) 7894349Sxy150489 devinfo = Adapter->priv_dip; 7904349Sxy150489 else 7914349Sxy150489 devinfo = Adapter->dip; 7923526Sxy150489 7933526Sxy150489 mystat = dvma_reserve(devinfo, 7943526Sxy150489 &e1000g_dma_limits, 7953526Sxy150489 Adapter->dvma_page_num, 7963526Sxy150489 &buf->dma_handle); 7973526Sxy150489 7983526Sxy150489 if (mystat != DDI_SUCCESS) { 7993526Sxy150489 buf->dma_handle = NULL; 8004919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 8013526Sxy150489 "Could not allocate dvma buffer handle: %d\n", mystat); 8023526Sxy150489 return (DDI_FAILURE); 8033526Sxy150489 } 8043526Sxy150489 8053526Sxy150489 buf->address = kmem_alloc(size, KM_NOSLEEP); 8063526Sxy150489 8073526Sxy150489 if (buf->address == NULL) { 8083526Sxy150489 if (buf->dma_handle != NULL) { 8093526Sxy150489 dvma_release(buf->dma_handle); 8103526Sxy150489 buf->dma_handle = NULL; 8113526Sxy150489 } 8124919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL, 8133526Sxy150489 "Could not allocate dvma buffer memory\n"); 8143526Sxy150489 return (DDI_FAILURE); 8153526Sxy150489 } 8163526Sxy150489 8173526Sxy150489 dvma_kaddr_load(buf->dma_handle, 8183526Sxy150489 buf->address, size, 0, &cookie); 8193526Sxy150489 8203526Sxy150489 buf->dma_address = cookie.dmac_laddress; 8213526Sxy150489 buf->size = size; 8223526Sxy150489 buf->len = 0; 8233526Sxy150489 8243526Sxy150489 return (DDI_SUCCESS); 8253526Sxy150489 } 8263526Sxy150489 8273526Sxy150489 static void 8283526Sxy150489 e1000g_free_dvma_buffer(dma_buffer_t *buf) 8293526Sxy150489 { 8303526Sxy150489 if (buf->dma_handle != NULL) { 8313526Sxy150489 dvma_unload(buf->dma_handle, 0, -1); 8323526Sxy150489 } else { 8333526Sxy150489 return; 8343526Sxy150489 } 8353526Sxy150489 8363526Sxy150489 buf->dma_address = NULL; 8373526Sxy150489 8383526Sxy150489 if (buf->address != NULL) { 8393526Sxy150489 kmem_free(buf->address, buf->size); 8403526Sxy150489 buf->address = NULL; 8413526Sxy150489 } 8423526Sxy150489 8433526Sxy150489 if (buf->dma_handle != NULL) { 8443526Sxy150489 dvma_release(buf->dma_handle); 8453526Sxy150489 buf->dma_handle = NULL; 8463526Sxy150489 } 8473526Sxy150489 8483526Sxy150489 buf->size = 0; 8493526Sxy150489 buf->len = 0; 8503526Sxy150489 } 8513526Sxy150489 #endif 8523526Sxy150489 8533526Sxy150489 static int 8543526Sxy150489 e1000g_alloc_dma_buffer(struct e1000g *Adapter, 8554919Sxy150489 dma_buffer_t *buf, size_t size, ddi_dma_attr_t *p_dma_attr) 8563526Sxy150489 { 8573526Sxy150489 int mystat; 8583526Sxy150489 dev_info_t *devinfo; 8593526Sxy150489 ddi_dma_cookie_t cookie; 8603526Sxy150489 size_t len; 8613526Sxy150489 uint_t count; 8623526Sxy150489 8634349Sxy150489 if (e1000g_force_detach) 8644349Sxy150489 devinfo = Adapter->priv_dip; 8654349Sxy150489 else 8664349Sxy150489 devinfo = Adapter->dip; 8673526Sxy150489 8683526Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, 8694919Sxy150489 p_dma_attr, 8703526Sxy150489 DDI_DMA_DONTWAIT, 0, 8713526Sxy150489 &buf->dma_handle); 8723526Sxy150489 8733526Sxy150489 if (mystat != DDI_SUCCESS) { 8743526Sxy150489 buf->dma_handle = NULL; 8754919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 8763526Sxy150489 "Could not allocate dma buffer handle: %d\n", mystat); 8773526Sxy150489 return (DDI_FAILURE); 8783526Sxy150489 } 8793526Sxy150489 8803526Sxy150489 mystat = ddi_dma_mem_alloc(buf->dma_handle, 8814919Sxy150489 size, &e1000g_buf_acc_attr, DDI_DMA_STREAMING, 8823526Sxy150489 DDI_DMA_DONTWAIT, 0, 8833526Sxy150489 &buf->address, 8843526Sxy150489 &len, &buf->acc_handle); 8853526Sxy150489 8863526Sxy150489 if (mystat != DDI_SUCCESS) { 8873526Sxy150489 buf->acc_handle = NULL; 8883526Sxy150489 buf->address = NULL; 8893526Sxy150489 if (buf->dma_handle != NULL) { 8903526Sxy150489 ddi_dma_free_handle(&buf->dma_handle); 8913526Sxy150489 buf->dma_handle = NULL; 8923526Sxy150489 } 8934919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 8943526Sxy150489 "Could not allocate dma buffer memory: %d\n", mystat); 8953526Sxy150489 return (DDI_FAILURE); 8963526Sxy150489 } 8973526Sxy150489 8983526Sxy150489 mystat = ddi_dma_addr_bind_handle(buf->dma_handle, 8993526Sxy150489 (struct as *)NULL, 9003526Sxy150489 buf->address, 901*11402SChangqing.Li@Sun.COM len, DDI_DMA_RDWR | DDI_DMA_STREAMING, 9024919Sxy150489 DDI_DMA_DONTWAIT, 0, &cookie, &count); 9033526Sxy150489 9043526Sxy150489 if (mystat != DDI_SUCCESS) { 9053526Sxy150489 if (buf->acc_handle != NULL) { 9063526Sxy150489 ddi_dma_mem_free(&buf->acc_handle); 9073526Sxy150489 buf->acc_handle = NULL; 9083526Sxy150489 buf->address = NULL; 9093526Sxy150489 } 9103526Sxy150489 if (buf->dma_handle != NULL) { 9113526Sxy150489 ddi_dma_free_handle(&buf->dma_handle); 9123526Sxy150489 buf->dma_handle = NULL; 9133526Sxy150489 } 9144919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 9153526Sxy150489 "Could not bind buffer dma handle: %d\n", mystat); 9163526Sxy150489 return (DDI_FAILURE); 9173526Sxy150489 } 9183526Sxy150489 9193526Sxy150489 ASSERT(count == 1); 9203526Sxy150489 if (count != 1) { 9213526Sxy150489 if (buf->dma_handle != NULL) { 9227426SChenliang.Xu@Sun.COM (void) ddi_dma_unbind_handle(buf->dma_handle); 9233526Sxy150489 } 9243526Sxy150489 if (buf->acc_handle != NULL) { 9253526Sxy150489 ddi_dma_mem_free(&buf->acc_handle); 9263526Sxy150489 buf->acc_handle = NULL; 9273526Sxy150489 buf->address = NULL; 9283526Sxy150489 } 9293526Sxy150489 if (buf->dma_handle != NULL) { 9303526Sxy150489 ddi_dma_free_handle(&buf->dma_handle); 9313526Sxy150489 buf->dma_handle = NULL; 9323526Sxy150489 } 9334919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 9343526Sxy150489 "Could not bind buffer as a single frag. " 9353526Sxy150489 "Count = %d\n", count); 9363526Sxy150489 return (DDI_FAILURE); 9373526Sxy150489 } 9383526Sxy150489 9393526Sxy150489 buf->dma_address = cookie.dmac_laddress; 9403526Sxy150489 buf->size = len; 9413526Sxy150489 buf->len = 0; 9423526Sxy150489 9433526Sxy150489 return (DDI_SUCCESS); 9443526Sxy150489 } 9453526Sxy150489 9468178SChenlu.Chen@Sun.COM /* 9478178SChenlu.Chen@Sun.COM * e1000g_alloc_dma_buffer_82546 - allocate a dma buffer along with all 9488178SChenlu.Chen@Sun.COM * necessary handles. Same as e1000g_alloc_dma_buffer() except ensure 9498178SChenlu.Chen@Sun.COM * that buffer that doesn't cross a 64k boundary. 9508178SChenlu.Chen@Sun.COM */ 9518178SChenlu.Chen@Sun.COM static int 9528178SChenlu.Chen@Sun.COM e1000g_alloc_dma_buffer_82546(struct e1000g *Adapter, 9538178SChenlu.Chen@Sun.COM dma_buffer_t *buf, size_t size, ddi_dma_attr_t *p_dma_attr) 9548178SChenlu.Chen@Sun.COM { 9558178SChenlu.Chen@Sun.COM int mystat; 9568178SChenlu.Chen@Sun.COM dev_info_t *devinfo; 9578178SChenlu.Chen@Sun.COM ddi_dma_cookie_t cookie; 9588178SChenlu.Chen@Sun.COM size_t len; 9598178SChenlu.Chen@Sun.COM uint_t count; 9608178SChenlu.Chen@Sun.COM 9618178SChenlu.Chen@Sun.COM if (e1000g_force_detach) 9628178SChenlu.Chen@Sun.COM devinfo = Adapter->priv_dip; 9638178SChenlu.Chen@Sun.COM else 9648178SChenlu.Chen@Sun.COM devinfo = Adapter->dip; 9658178SChenlu.Chen@Sun.COM 9668178SChenlu.Chen@Sun.COM mystat = ddi_dma_alloc_handle(devinfo, 9678178SChenlu.Chen@Sun.COM p_dma_attr, 9688178SChenlu.Chen@Sun.COM DDI_DMA_DONTWAIT, 0, 9698178SChenlu.Chen@Sun.COM &buf->dma_handle); 9708178SChenlu.Chen@Sun.COM 9718178SChenlu.Chen@Sun.COM if (mystat != DDI_SUCCESS) { 9728178SChenlu.Chen@Sun.COM buf->dma_handle = NULL; 9738178SChenlu.Chen@Sun.COM E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 9748178SChenlu.Chen@Sun.COM "Could not allocate dma buffer handle: %d\n", mystat); 9758178SChenlu.Chen@Sun.COM return (DDI_FAILURE); 9768178SChenlu.Chen@Sun.COM } 9778178SChenlu.Chen@Sun.COM 9788178SChenlu.Chen@Sun.COM mystat = e1000g_dma_mem_alloc_82546(buf, size, &len); 9798178SChenlu.Chen@Sun.COM if (mystat != DDI_SUCCESS) { 9808178SChenlu.Chen@Sun.COM buf->acc_handle = NULL; 9818178SChenlu.Chen@Sun.COM buf->address = NULL; 9828178SChenlu.Chen@Sun.COM if (buf->dma_handle != NULL) { 9838178SChenlu.Chen@Sun.COM ddi_dma_free_handle(&buf->dma_handle); 9848178SChenlu.Chen@Sun.COM buf->dma_handle = NULL; 9858178SChenlu.Chen@Sun.COM } 9868178SChenlu.Chen@Sun.COM E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 9878178SChenlu.Chen@Sun.COM "Could not allocate dma buffer memory: %d\n", mystat); 9888178SChenlu.Chen@Sun.COM return (DDI_FAILURE); 9898178SChenlu.Chen@Sun.COM } 9908178SChenlu.Chen@Sun.COM 9918178SChenlu.Chen@Sun.COM mystat = ddi_dma_addr_bind_handle(buf->dma_handle, 9928178SChenlu.Chen@Sun.COM (struct as *)NULL, 9938178SChenlu.Chen@Sun.COM buf->address, 9948178SChenlu.Chen@Sun.COM len, DDI_DMA_READ | DDI_DMA_STREAMING, 9958178SChenlu.Chen@Sun.COM DDI_DMA_DONTWAIT, 0, &cookie, &count); 9968178SChenlu.Chen@Sun.COM 9978178SChenlu.Chen@Sun.COM if (mystat != DDI_SUCCESS) { 9988178SChenlu.Chen@Sun.COM if (buf->acc_handle != NULL) { 9998178SChenlu.Chen@Sun.COM ddi_dma_mem_free(&buf->acc_handle); 10008178SChenlu.Chen@Sun.COM buf->acc_handle = NULL; 10018178SChenlu.Chen@Sun.COM buf->address = NULL; 10028178SChenlu.Chen@Sun.COM } 10038178SChenlu.Chen@Sun.COM if (buf->dma_handle != NULL) { 10048178SChenlu.Chen@Sun.COM ddi_dma_free_handle(&buf->dma_handle); 10058178SChenlu.Chen@Sun.COM buf->dma_handle = NULL; 10068178SChenlu.Chen@Sun.COM } 10078178SChenlu.Chen@Sun.COM E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 10088178SChenlu.Chen@Sun.COM "Could not bind buffer dma handle: %d\n", mystat); 10098178SChenlu.Chen@Sun.COM return (DDI_FAILURE); 10108178SChenlu.Chen@Sun.COM } 10118178SChenlu.Chen@Sun.COM 10128178SChenlu.Chen@Sun.COM ASSERT(count == 1); 10138178SChenlu.Chen@Sun.COM if (count != 1) { 10148178SChenlu.Chen@Sun.COM if (buf->dma_handle != NULL) { 101511143SGuoqing.Zhu@Sun.COM (void) ddi_dma_unbind_handle(buf->dma_handle); 10168178SChenlu.Chen@Sun.COM } 10178178SChenlu.Chen@Sun.COM if (buf->acc_handle != NULL) { 10188178SChenlu.Chen@Sun.COM ddi_dma_mem_free(&buf->acc_handle); 10198178SChenlu.Chen@Sun.COM buf->acc_handle = NULL; 10208178SChenlu.Chen@Sun.COM buf->address = NULL; 10218178SChenlu.Chen@Sun.COM } 10228178SChenlu.Chen@Sun.COM if (buf->dma_handle != NULL) { 10238178SChenlu.Chen@Sun.COM ddi_dma_free_handle(&buf->dma_handle); 10248178SChenlu.Chen@Sun.COM buf->dma_handle = NULL; 10258178SChenlu.Chen@Sun.COM } 10268178SChenlu.Chen@Sun.COM E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 10278178SChenlu.Chen@Sun.COM "Could not bind buffer as a single frag. " 10288178SChenlu.Chen@Sun.COM "Count = %d\n", count); 10298178SChenlu.Chen@Sun.COM return (DDI_FAILURE); 10308178SChenlu.Chen@Sun.COM } 10318178SChenlu.Chen@Sun.COM 10328178SChenlu.Chen@Sun.COM buf->dma_address = cookie.dmac_laddress; 10338178SChenlu.Chen@Sun.COM buf->size = len; 10348178SChenlu.Chen@Sun.COM buf->len = 0; 10358178SChenlu.Chen@Sun.COM 10368178SChenlu.Chen@Sun.COM return (DDI_SUCCESS); 10378178SChenlu.Chen@Sun.COM } 10388178SChenlu.Chen@Sun.COM 10398178SChenlu.Chen@Sun.COM /* 10408178SChenlu.Chen@Sun.COM * e1000g_dma_mem_alloc_82546 - allocate a dma buffer, making up to 10418178SChenlu.Chen@Sun.COM * ALLOC_RETRY attempts to get a buffer that doesn't cross a 64k boundary. 10428178SChenlu.Chen@Sun.COM */ 10438178SChenlu.Chen@Sun.COM static int 10448178SChenlu.Chen@Sun.COM e1000g_dma_mem_alloc_82546(dma_buffer_t *buf, size_t size, size_t *len) 10458178SChenlu.Chen@Sun.COM { 10468178SChenlu.Chen@Sun.COM #define ALLOC_RETRY 10 10478178SChenlu.Chen@Sun.COM int stat; 10488178SChenlu.Chen@Sun.COM int cnt = 0; 10498178SChenlu.Chen@Sun.COM ddi_acc_handle_t hold[ALLOC_RETRY]; 10508178SChenlu.Chen@Sun.COM 10518178SChenlu.Chen@Sun.COM while (cnt < ALLOC_RETRY) { 10528178SChenlu.Chen@Sun.COM hold[cnt] = NULL; 10538178SChenlu.Chen@Sun.COM 10548178SChenlu.Chen@Sun.COM /* allocate memory */ 10558178SChenlu.Chen@Sun.COM stat = ddi_dma_mem_alloc(buf->dma_handle, size, 10568178SChenlu.Chen@Sun.COM &e1000g_buf_acc_attr, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 10578178SChenlu.Chen@Sun.COM 0, &buf->address, len, &buf->acc_handle); 10588178SChenlu.Chen@Sun.COM 10598178SChenlu.Chen@Sun.COM if (stat != DDI_SUCCESS) { 10608178SChenlu.Chen@Sun.COM break; 10618178SChenlu.Chen@Sun.COM } 10628178SChenlu.Chen@Sun.COM 10638178SChenlu.Chen@Sun.COM /* 10648178SChenlu.Chen@Sun.COM * Check 64k bounday: 10658178SChenlu.Chen@Sun.COM * if it is bad, hold it and retry 10668178SChenlu.Chen@Sun.COM * if it is good, exit loop 10678178SChenlu.Chen@Sun.COM */ 10688178SChenlu.Chen@Sun.COM if (e1000g_cross_64k_bound(buf->address, *len)) { 10698178SChenlu.Chen@Sun.COM hold[cnt] = buf->acc_handle; 10708178SChenlu.Chen@Sun.COM stat = DDI_FAILURE; 10718178SChenlu.Chen@Sun.COM } else { 10728178SChenlu.Chen@Sun.COM break; 10738178SChenlu.Chen@Sun.COM } 10748178SChenlu.Chen@Sun.COM 10758178SChenlu.Chen@Sun.COM cnt++; 10768178SChenlu.Chen@Sun.COM } 10778178SChenlu.Chen@Sun.COM 10788178SChenlu.Chen@Sun.COM /* Release any held buffers crossing 64k bounday */ 10798178SChenlu.Chen@Sun.COM for (--cnt; cnt >= 0; cnt--) { 10808178SChenlu.Chen@Sun.COM if (hold[cnt]) 10818178SChenlu.Chen@Sun.COM ddi_dma_mem_free(&hold[cnt]); 10828178SChenlu.Chen@Sun.COM } 10838178SChenlu.Chen@Sun.COM 10848178SChenlu.Chen@Sun.COM return (stat); 10858178SChenlu.Chen@Sun.COM } 10868178SChenlu.Chen@Sun.COM 10878178SChenlu.Chen@Sun.COM /* 10888178SChenlu.Chen@Sun.COM * e1000g_cross_64k_bound - If starting and ending address cross a 64k boundary 10898178SChenlu.Chen@Sun.COM * return true; otherwise return false 10908178SChenlu.Chen@Sun.COM */ 10918178SChenlu.Chen@Sun.COM static boolean_t 10928178SChenlu.Chen@Sun.COM e1000g_cross_64k_bound(void *addr, uintptr_t len) 10938178SChenlu.Chen@Sun.COM { 10948178SChenlu.Chen@Sun.COM uintptr_t start = (uintptr_t)addr; 10958178SChenlu.Chen@Sun.COM uintptr_t end = start + len - 1; 10968178SChenlu.Chen@Sun.COM 10978178SChenlu.Chen@Sun.COM return (((start ^ end) >> 16) == 0 ? B_FALSE : B_TRUE); 10988178SChenlu.Chen@Sun.COM } 10998178SChenlu.Chen@Sun.COM 11003526Sxy150489 static void 11013526Sxy150489 e1000g_free_dma_buffer(dma_buffer_t *buf) 11023526Sxy150489 { 11033526Sxy150489 if (buf->dma_handle != NULL) { 11047426SChenliang.Xu@Sun.COM (void) ddi_dma_unbind_handle(buf->dma_handle); 11053526Sxy150489 } else { 11063526Sxy150489 return; 11073526Sxy150489 } 11083526Sxy150489 11093526Sxy150489 buf->dma_address = NULL; 11103526Sxy150489 11113526Sxy150489 if (buf->acc_handle != NULL) { 11123526Sxy150489 ddi_dma_mem_free(&buf->acc_handle); 11133526Sxy150489 buf->acc_handle = NULL; 11143526Sxy150489 buf->address = NULL; 11153526Sxy150489 } 11163526Sxy150489 11173526Sxy150489 if (buf->dma_handle != NULL) { 11183526Sxy150489 ddi_dma_free_handle(&buf->dma_handle); 11193526Sxy150489 buf->dma_handle = NULL; 11203526Sxy150489 } 11213526Sxy150489 11223526Sxy150489 buf->size = 0; 11233526Sxy150489 buf->len = 0; 11243526Sxy150489 } 11253526Sxy150489 11263526Sxy150489 static int 11273526Sxy150489 e1000g_alloc_tx_packets(e1000g_tx_ring_t *tx_ring) 11283526Sxy150489 { 11293526Sxy150489 int j; 11304919Sxy150489 p_tx_sw_packet_t packet; 11313526Sxy150489 int mystat; 11323526Sxy150489 dma_buffer_t *tx_buf; 11334919Sxy150489 struct e1000g *Adapter; 11344919Sxy150489 dev_info_t *devinfo; 11354919Sxy150489 ddi_dma_attr_t dma_attr; 11364919Sxy150489 11374919Sxy150489 Adapter = tx_ring->adapter; 11384919Sxy150489 devinfo = Adapter->dip; 11394919Sxy150489 dma_attr = e1000g_buf_dma_attr; 11403526Sxy150489 11413526Sxy150489 /* 11423526Sxy150489 * Memory allocation for the Transmit software structure, the transmit 11433526Sxy150489 * software packet. This structure stores all the relevant information 11443526Sxy150489 * for transmitting a single packet. 11453526Sxy150489 */ 11463526Sxy150489 tx_ring->packet_area = 11473526Sxy150489 kmem_zalloc(TX_SW_PKT_AREA_SZ, KM_NOSLEEP); 11483526Sxy150489 11493526Sxy150489 if (tx_ring->packet_area == NULL) 11503526Sxy150489 return (DDI_FAILURE); 11513526Sxy150489 11523526Sxy150489 for (j = 0, packet = tx_ring->packet_area; 11534919Sxy150489 j < Adapter->tx_freelist_num; j++, packet++) { 11543526Sxy150489 11553526Sxy150489 ASSERT(packet != NULL); 11563526Sxy150489 11573526Sxy150489 /* 11583526Sxy150489 * Pre-allocate dma handles for transmit. These dma handles 11593526Sxy150489 * will be dynamically bound to the data buffers passed down 11603526Sxy150489 * from the upper layers at the time of transmitting. The 11613526Sxy150489 * dynamic binding only applies for the packets that are larger 11623526Sxy150489 * than the tx_bcopy_thresh. 11633526Sxy150489 */ 11643526Sxy150489 switch (e1000g_dma_type) { 11653526Sxy150489 #ifdef __sparc 11663526Sxy150489 case USE_DVMA: 11673526Sxy150489 mystat = dvma_reserve(devinfo, 11683526Sxy150489 &e1000g_dma_limits, 11693526Sxy150489 Adapter->dvma_page_num, 11703526Sxy150489 &packet->tx_dma_handle); 11713526Sxy150489 break; 11723526Sxy150489 #endif 11733526Sxy150489 case USE_DMA: 11743526Sxy150489 mystat = ddi_dma_alloc_handle(devinfo, 11754919Sxy150489 &e1000g_tx_dma_attr, 11763526Sxy150489 DDI_DMA_DONTWAIT, 0, 11773526Sxy150489 &packet->tx_dma_handle); 11783526Sxy150489 break; 11793526Sxy150489 default: 11803526Sxy150489 ASSERT(B_FALSE); 11813526Sxy150489 break; 11823526Sxy150489 } 11833526Sxy150489 if (mystat != DDI_SUCCESS) { 11843526Sxy150489 packet->tx_dma_handle = NULL; 11854919Sxy150489 E1000G_DEBUGLOG_1(Adapter, E1000G_WARN_LEVEL, 11863526Sxy150489 "Could not allocate tx dma handle: %d\n", mystat); 11873526Sxy150489 goto tx_pkt_fail; 11883526Sxy150489 } 11893526Sxy150489 11903526Sxy150489 /* 11913526Sxy150489 * Pre-allocate transmit buffers for small packets that the 11923526Sxy150489 * size is less than tx_bcopy_thresh. The data of those small 11933526Sxy150489 * packets will be bcopy() to the transmit buffers instead of 11943526Sxy150489 * using dynamical DMA binding. For small packets, bcopy will 11953526Sxy150489 * bring better performance than DMA binding. 11963526Sxy150489 */ 11973526Sxy150489 tx_buf = packet->tx_buf; 11983526Sxy150489 11993526Sxy150489 switch (e1000g_dma_type) { 12003526Sxy150489 #ifdef __sparc 12013526Sxy150489 case USE_DVMA: 12023526Sxy150489 mystat = e1000g_alloc_dvma_buffer(Adapter, 12034919Sxy150489 tx_buf, Adapter->tx_buffer_size); 12043526Sxy150489 break; 12053526Sxy150489 #endif 12063526Sxy150489 case USE_DMA: 12073526Sxy150489 mystat = e1000g_alloc_dma_buffer(Adapter, 12084919Sxy150489 tx_buf, Adapter->tx_buffer_size, &dma_attr); 12093526Sxy150489 break; 12103526Sxy150489 default: 12113526Sxy150489 ASSERT(B_FALSE); 12123526Sxy150489 break; 12133526Sxy150489 } 12143526Sxy150489 if (mystat != DDI_SUCCESS) { 12153526Sxy150489 ASSERT(packet->tx_dma_handle != NULL); 12163526Sxy150489 switch (e1000g_dma_type) { 12173526Sxy150489 #ifdef __sparc 12183526Sxy150489 case USE_DVMA: 12193526Sxy150489 dvma_release(packet->tx_dma_handle); 12203526Sxy150489 break; 12213526Sxy150489 #endif 12223526Sxy150489 case USE_DMA: 12233526Sxy150489 ddi_dma_free_handle(&packet->tx_dma_handle); 12243526Sxy150489 break; 12253526Sxy150489 default: 12263526Sxy150489 ASSERT(B_FALSE); 12273526Sxy150489 break; 12283526Sxy150489 } 12293526Sxy150489 packet->tx_dma_handle = NULL; 12304919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL, 12313526Sxy150489 "Allocate Tx buffer fail\n"); 12323526Sxy150489 goto tx_pkt_fail; 12333526Sxy150489 } 12343526Sxy150489 12353526Sxy150489 packet->dma_type = e1000g_dma_type; 12363526Sxy150489 } /* for */ 12373526Sxy150489 12383526Sxy150489 return (DDI_SUCCESS); 12393526Sxy150489 12403526Sxy150489 tx_pkt_fail: 12413526Sxy150489 e1000g_free_tx_packets(tx_ring); 12423526Sxy150489 12433526Sxy150489 return (DDI_FAILURE); 12443526Sxy150489 } 12453526Sxy150489 12463526Sxy150489 static int 12478850SMin.Xu@Sun.COM e1000g_alloc_rx_packets(e1000g_rx_data_t *rx_data) 12483526Sxy150489 { 12493526Sxy150489 int i; 12504919Sxy150489 p_rx_sw_packet_t packet; 12513526Sxy150489 struct e1000g *Adapter; 12523526Sxy150489 uint32_t packet_num; 12534919Sxy150489 ddi_dma_attr_t dma_attr; 12543526Sxy150489 12558850SMin.Xu@Sun.COM Adapter = rx_data->rx_ring->adapter; 12564919Sxy150489 dma_attr = e1000g_buf_dma_attr; 12576735Scc210113 dma_attr.dma_attr_align = Adapter->rx_buf_align; 12583526Sxy150489 12593526Sxy150489 /* 12604919Sxy150489 * Allocate memory for the rx_sw_packet structures. Each one of these 12613526Sxy150489 * structures will contain a virtual and physical address to an actual 12624919Sxy150489 * receive buffer in host memory. Since we use one rx_sw_packet per 12634919Sxy150489 * received packet, the maximum number of rx_sw_packet that we'll 12648850SMin.Xu@Sun.COM * need is equal to the number of receive descriptors plus the freelist 12658850SMin.Xu@Sun.COM * size. 12663526Sxy150489 */ 12674919Sxy150489 packet_num = Adapter->rx_desc_num + Adapter->rx_freelist_num; 12688850SMin.Xu@Sun.COM rx_data->packet_area = NULL; 12693526Sxy150489 12703526Sxy150489 for (i = 0; i < packet_num; i++) { 12718850SMin.Xu@Sun.COM packet = e1000g_alloc_rx_sw_packet(rx_data, &dma_attr); 12723526Sxy150489 if (packet == NULL) 12733526Sxy150489 goto rx_pkt_fail; 12743526Sxy150489 12758850SMin.Xu@Sun.COM packet->next = rx_data->packet_area; 12768850SMin.Xu@Sun.COM rx_data->packet_area = packet; 12773526Sxy150489 } 12783526Sxy150489 12793526Sxy150489 return (DDI_SUCCESS); 12803526Sxy150489 12813526Sxy150489 rx_pkt_fail: 12828850SMin.Xu@Sun.COM e1000g_free_rx_packets(rx_data); 12833526Sxy150489 12843526Sxy150489 return (DDI_FAILURE); 12853526Sxy150489 } 12863526Sxy150489 12874919Sxy150489 static p_rx_sw_packet_t 12888850SMin.Xu@Sun.COM e1000g_alloc_rx_sw_packet(e1000g_rx_data_t *rx_data, ddi_dma_attr_t *p_dma_attr) 12893526Sxy150489 { 12903526Sxy150489 int mystat; 12914919Sxy150489 p_rx_sw_packet_t packet; 12923526Sxy150489 dma_buffer_t *rx_buf; 12933526Sxy150489 struct e1000g *Adapter; 12943526Sxy150489 12958850SMin.Xu@Sun.COM Adapter = rx_data->rx_ring->adapter; 12963526Sxy150489 12974919Sxy150489 packet = kmem_zalloc(sizeof (rx_sw_packet_t), KM_NOSLEEP); 12983526Sxy150489 if (packet == NULL) { 12994919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL, 13003526Sxy150489 "Cound not allocate memory for Rx SwPacket\n"); 13013526Sxy150489 return (NULL); 13023526Sxy150489 } 13033526Sxy150489 13043526Sxy150489 rx_buf = packet->rx_buf; 13053526Sxy150489 13063526Sxy150489 switch (e1000g_dma_type) { 13073526Sxy150489 #ifdef __sparc 13083526Sxy150489 case USE_DVMA: 13093526Sxy150489 mystat = e1000g_alloc_dvma_buffer(Adapter, 13104919Sxy150489 rx_buf, Adapter->rx_buffer_size); 13113526Sxy150489 break; 13123526Sxy150489 #endif 13133526Sxy150489 case USE_DMA: 13148417SChenlu.Chen@Sun.COM if (Adapter->mem_workaround_82546 && 13158417SChenlu.Chen@Sun.COM ((Adapter->shared.mac.type == e1000_82545) || 13168178SChenlu.Chen@Sun.COM (Adapter->shared.mac.type == e1000_82546) || 13178417SChenlu.Chen@Sun.COM (Adapter->shared.mac.type == e1000_82546_rev_3))) { 13188178SChenlu.Chen@Sun.COM mystat = e1000g_alloc_dma_buffer_82546(Adapter, 13198178SChenlu.Chen@Sun.COM rx_buf, Adapter->rx_buffer_size, p_dma_attr); 13208178SChenlu.Chen@Sun.COM } else { 13218178SChenlu.Chen@Sun.COM mystat = e1000g_alloc_dma_buffer(Adapter, 13228178SChenlu.Chen@Sun.COM rx_buf, Adapter->rx_buffer_size, p_dma_attr); 13238178SChenlu.Chen@Sun.COM } 13243526Sxy150489 break; 13253526Sxy150489 default: 13263526Sxy150489 ASSERT(B_FALSE); 13273526Sxy150489 break; 13283526Sxy150489 } 13293526Sxy150489 13303526Sxy150489 if (mystat != DDI_SUCCESS) { 13313526Sxy150489 if (packet != NULL) 13324919Sxy150489 kmem_free(packet, sizeof (rx_sw_packet_t)); 13333526Sxy150489 13344919Sxy150489 E1000G_DEBUGLOG_0(Adapter, E1000G_WARN_LEVEL, 13353526Sxy150489 "Failed to allocate Rx buffer\n"); 13363526Sxy150489 return (NULL); 13373526Sxy150489 } 13383526Sxy150489 13393526Sxy150489 rx_buf->size -= E1000G_IPALIGNROOM; 13403526Sxy150489 rx_buf->address += E1000G_IPALIGNROOM; 13413526Sxy150489 rx_buf->dma_address += E1000G_IPALIGNROOM; 13423526Sxy150489 13438850SMin.Xu@Sun.COM packet->rx_data = (caddr_t)rx_data; 13443526Sxy150489 packet->free_rtn.free_func = e1000g_rxfree_func; 13453526Sxy150489 packet->free_rtn.free_arg = (char *)packet; 13463526Sxy150489 /* 13473526Sxy150489 * esballoc is changed to desballoc which 13483526Sxy150489 * is undocumented call but as per sun, 13493526Sxy150489 * we can use it. It gives better efficiency. 13503526Sxy150489 */ 13513526Sxy150489 packet->mp = desballoc((unsigned char *) 13528995SMin.Xu@Sun.COM rx_buf->address, 13538995SMin.Xu@Sun.COM rx_buf->size, 13543526Sxy150489 BPRI_MED, &packet->free_rtn); 13553526Sxy150489 13563526Sxy150489 packet->dma_type = e1000g_dma_type; 13578850SMin.Xu@Sun.COM packet->ref_cnt = 1; 13583526Sxy150489 13593526Sxy150489 return (packet); 13603526Sxy150489 } 13613526Sxy150489 13623526Sxy150489 void 13638850SMin.Xu@Sun.COM e1000g_free_rx_sw_packet(p_rx_sw_packet_t packet, boolean_t full_release) 13643526Sxy150489 { 13653526Sxy150489 dma_buffer_t *rx_buf; 13663526Sxy150489 13673526Sxy150489 if (packet->mp != NULL) { 13683526Sxy150489 freemsg(packet->mp); 13693526Sxy150489 packet->mp = NULL; 13703526Sxy150489 } 13713526Sxy150489 13723526Sxy150489 rx_buf = packet->rx_buf; 13733526Sxy150489 13743526Sxy150489 switch (packet->dma_type) { 13753526Sxy150489 #ifdef __sparc 13763526Sxy150489 case USE_DVMA: 13778850SMin.Xu@Sun.COM if (rx_buf->address != NULL) { 13788850SMin.Xu@Sun.COM rx_buf->size += E1000G_IPALIGNROOM; 13798850SMin.Xu@Sun.COM rx_buf->address -= E1000G_IPALIGNROOM; 13808850SMin.Xu@Sun.COM } 13813526Sxy150489 e1000g_free_dvma_buffer(rx_buf); 13823526Sxy150489 break; 13833526Sxy150489 #endif 13843526Sxy150489 case USE_DMA: 13853526Sxy150489 e1000g_free_dma_buffer(rx_buf); 13863526Sxy150489 break; 13873526Sxy150489 default: 13883526Sxy150489 break; 13893526Sxy150489 } 13903526Sxy150489 13913526Sxy150489 packet->dma_type = USE_NONE; 13923526Sxy150489 13938850SMin.Xu@Sun.COM if (!full_release) 13948850SMin.Xu@Sun.COM return; 13958850SMin.Xu@Sun.COM 13964919Sxy150489 kmem_free(packet, sizeof (rx_sw_packet_t)); 13973526Sxy150489 } 13983526Sxy150489 13993526Sxy150489 static void 14008850SMin.Xu@Sun.COM e1000g_free_rx_packets(e1000g_rx_data_t *rx_data) 14013526Sxy150489 { 14028850SMin.Xu@Sun.COM p_rx_sw_packet_t packet, next_packet; 14038850SMin.Xu@Sun.COM uint32_t ref_cnt; 14043526Sxy150489 14058850SMin.Xu@Sun.COM mutex_enter(&e1000g_rx_detach_lock); 14064349Sxy150489 14078850SMin.Xu@Sun.COM packet = rx_data->packet_area; 14088850SMin.Xu@Sun.COM while (packet != NULL) { 14094349Sxy150489 next_packet = packet->next; 14104349Sxy150489 14118850SMin.Xu@Sun.COM ref_cnt = atomic_dec_32_nv(&packet->ref_cnt); 14128850SMin.Xu@Sun.COM if (ref_cnt > 0) { 14138850SMin.Xu@Sun.COM atomic_inc_32(&rx_data->pending_count); 14148850SMin.Xu@Sun.COM atomic_inc_32(&e1000g_mblks_pending); 14154349Sxy150489 } else { 14168850SMin.Xu@Sun.COM e1000g_free_rx_sw_packet(packet, B_FALSE); 14173526Sxy150489 } 14188850SMin.Xu@Sun.COM 14198850SMin.Xu@Sun.COM packet = next_packet; 14203526Sxy150489 } 14213526Sxy150489 14228850SMin.Xu@Sun.COM mutex_exit(&e1000g_rx_detach_lock); 14238850SMin.Xu@Sun.COM } 14243526Sxy150489 14253526Sxy150489 14263526Sxy150489 static void 14273526Sxy150489 e1000g_free_tx_packets(e1000g_tx_ring_t *tx_ring) 14283526Sxy150489 { 14293526Sxy150489 int j; 14303526Sxy150489 struct e1000g *Adapter; 14314919Sxy150489 p_tx_sw_packet_t packet; 14323526Sxy150489 dma_buffer_t *tx_buf; 14333526Sxy150489 14343526Sxy150489 Adapter = tx_ring->adapter; 14353526Sxy150489 14363526Sxy150489 for (j = 0, packet = tx_ring->packet_area; 14374919Sxy150489 j < Adapter->tx_freelist_num; j++, packet++) { 14383526Sxy150489 14393526Sxy150489 if (packet == NULL) 14403526Sxy150489 break; 14413526Sxy150489 14423526Sxy150489 /* Free the Tx DMA handle for dynamical binding */ 14433526Sxy150489 if (packet->tx_dma_handle != NULL) { 14443526Sxy150489 switch (packet->dma_type) { 14453526Sxy150489 #ifdef __sparc 14463526Sxy150489 case USE_DVMA: 14473526Sxy150489 dvma_release(packet->tx_dma_handle); 14483526Sxy150489 break; 14493526Sxy150489 #endif 14503526Sxy150489 case USE_DMA: 14513526Sxy150489 ddi_dma_free_handle(&packet->tx_dma_handle); 14523526Sxy150489 break; 14533526Sxy150489 default: 14543526Sxy150489 ASSERT(B_FALSE); 14553526Sxy150489 break; 14563526Sxy150489 } 14573526Sxy150489 packet->tx_dma_handle = NULL; 14583526Sxy150489 } else { 14593526Sxy150489 /* 14603526Sxy150489 * If the dma handle is NULL, then we don't 14613526Sxy150489 * need to check the packets left. For they 14623526Sxy150489 * have not been initialized or have been freed. 14633526Sxy150489 */ 14643526Sxy150489 break; 14653526Sxy150489 } 14663526Sxy150489 14673526Sxy150489 tx_buf = packet->tx_buf; 14683526Sxy150489 14693526Sxy150489 switch (packet->dma_type) { 14703526Sxy150489 #ifdef __sparc 14713526Sxy150489 case USE_DVMA: 14723526Sxy150489 e1000g_free_dvma_buffer(tx_buf); 14733526Sxy150489 break; 14743526Sxy150489 #endif 14753526Sxy150489 case USE_DMA: 14763526Sxy150489 e1000g_free_dma_buffer(tx_buf); 14773526Sxy150489 break; 14783526Sxy150489 default: 14793526Sxy150489 ASSERT(B_FALSE); 14803526Sxy150489 break; 14813526Sxy150489 } 14823526Sxy150489 14833526Sxy150489 packet->dma_type = USE_NONE; 14843526Sxy150489 } 14853526Sxy150489 if (tx_ring->packet_area != NULL) { 14863526Sxy150489 kmem_free(tx_ring->packet_area, TX_SW_PKT_AREA_SZ); 14873526Sxy150489 tx_ring->packet_area = NULL; 14883526Sxy150489 } 14893526Sxy150489 } 14903526Sxy150489 14913526Sxy150489 /* 14924919Sxy150489 * e1000g_release_dma_resources - release allocated DMA resources 14934919Sxy150489 * 14944919Sxy150489 * This function releases any pending buffers that has been 14954919Sxy150489 * previously allocated 14963526Sxy150489 */ 14973526Sxy150489 void 14984919Sxy150489 e1000g_release_dma_resources(struct e1000g *Adapter) 14993526Sxy150489 { 15004919Sxy150489 e1000g_free_descriptors(Adapter); 15014919Sxy150489 e1000g_free_packets(Adapter); 15023526Sxy150489 } 15035273Sgl147354 15047426SChenliang.Xu@Sun.COM /* ARGSUSED */ 15055273Sgl147354 void 150611236SStephen.Hanson@Sun.COM e1000g_set_fma_flags(int dma_flag) 15075273Sgl147354 { 15085273Sgl147354 if (dma_flag) { 15095273Sgl147354 e1000g_tx_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 15105273Sgl147354 e1000g_buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 15115273Sgl147354 e1000g_desc_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 15125273Sgl147354 } else { 15135273Sgl147354 e1000g_tx_dma_attr.dma_attr_flags = 0; 15145273Sgl147354 e1000g_buf_dma_attr.dma_attr_flags = 0; 15155273Sgl147354 e1000g_desc_dma_attr.dma_attr_flags = 0; 15165273Sgl147354 } 15175273Sgl147354 } 1518