16621Sbt150084 /* 26621Sbt150084 * CDDL HEADER START 36621Sbt150084 * 49353SSamuel.Tu@Sun.COM * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. 56621Sbt150084 * The contents of this file are subject to the terms of the 66621Sbt150084 * Common Development and Distribution License (the "License"). 76621Sbt150084 * You may not use this file except in compliance with the License. 86621Sbt150084 * 96621Sbt150084 * You can obtain a copy of the license at: 106621Sbt150084 * http://www.opensolaris.org/os/licensing. 116621Sbt150084 * See the License for the specific language governing permissions 126621Sbt150084 * and limitations under the License. 136621Sbt150084 * 146621Sbt150084 * When using or redistributing this file, you may do so under the 156621Sbt150084 * License only. No other modification of this header is permitted. 166621Sbt150084 * 176621Sbt150084 * If applicable, add the following below this CDDL HEADER, with the 186621Sbt150084 * fields enclosed by brackets "[]" replaced with your own identifying 196621Sbt150084 * information: Portions Copyright [yyyy] [name of copyright owner] 206621Sbt150084 * 216621Sbt150084 * CDDL HEADER END 226621Sbt150084 */ 236621Sbt150084 246621Sbt150084 /* 259353SSamuel.Tu@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 269353SSamuel.Tu@Sun.COM * Use is subject to license terms. 276621Sbt150084 */ 286621Sbt150084 296621Sbt150084 #include "ixgbe_sw.h" 306621Sbt150084 316621Sbt150084 static int ixgbe_alloc_tbd_ring(ixgbe_tx_ring_t *); 326621Sbt150084 static void ixgbe_free_tbd_ring(ixgbe_tx_ring_t *); 3310376SChenlu.Chen@Sun.COM static int ixgbe_alloc_rbd_ring(ixgbe_rx_data_t *); 3410376SChenlu.Chen@Sun.COM static void ixgbe_free_rbd_ring(ixgbe_rx_data_t *); 356621Sbt150084 static int ixgbe_alloc_dma_buffer(ixgbe_t *, dma_buffer_t *, size_t); 366621Sbt150084 static int ixgbe_alloc_tcb_lists(ixgbe_tx_ring_t *); 376621Sbt150084 static void ixgbe_free_tcb_lists(ixgbe_tx_ring_t *); 3810376SChenlu.Chen@Sun.COM static int ixgbe_alloc_rcb_lists(ixgbe_rx_data_t *); 3910376SChenlu.Chen@Sun.COM static void ixgbe_free_rcb_lists(ixgbe_rx_data_t *); 406621Sbt150084 416621Sbt150084 #ifdef __sparc 426621Sbt150084 #define IXGBE_DMA_ALIGNMENT 0x0000000000002000ull 436621Sbt150084 #else 446621Sbt150084 #define IXGBE_DMA_ALIGNMENT 0x0000000000001000ull 456621Sbt150084 #endif 466621Sbt150084 476621Sbt150084 /* 486621Sbt150084 * DMA attributes for tx/rx descriptors. 496621Sbt150084 */ 506621Sbt150084 static ddi_dma_attr_t ixgbe_desc_dma_attr = { 516621Sbt150084 DMA_ATTR_V0, /* version number */ 526621Sbt150084 0x0000000000000000ull, /* low address */ 536621Sbt150084 0xFFFFFFFFFFFFFFFFull, /* high address */ 546621Sbt150084 0x00000000FFFFFFFFull, /* dma counter max */ 556621Sbt150084 IXGBE_DMA_ALIGNMENT, /* alignment */ 566621Sbt150084 0x00000FFF, /* burst sizes */ 576621Sbt150084 0x00000001, /* minimum transfer size */ 586621Sbt150084 0x00000000FFFFFFFFull, /* maximum transfer size */ 596621Sbt150084 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */ 606621Sbt150084 1, /* scatter/gather list length */ 616621Sbt150084 0x00000001, /* granularity */ 626621Sbt150084 DDI_DMA_FLAGERR /* DMA flags */ 636621Sbt150084 }; 646621Sbt150084 656621Sbt150084 /* 666621Sbt150084 * DMA attributes for tx/rx buffers. 676621Sbt150084 */ 686621Sbt150084 static ddi_dma_attr_t ixgbe_buf_dma_attr = { 696621Sbt150084 DMA_ATTR_V0, /* version number */ 706621Sbt150084 0x0000000000000000ull, /* low address */ 716621Sbt150084 0xFFFFFFFFFFFFFFFFull, /* high address */ 726621Sbt150084 0x00000000FFFFFFFFull, /* dma counter max */ 736621Sbt150084 IXGBE_DMA_ALIGNMENT, /* alignment */ 746621Sbt150084 0x00000FFF, /* burst sizes */ 756621Sbt150084 0x00000001, /* minimum transfer size */ 766621Sbt150084 0x00000000FFFFFFFFull, /* maximum transfer size */ 776621Sbt150084 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */ 786621Sbt150084 1, /* scatter/gather list length */ 796621Sbt150084 0x00000001, /* granularity */ 806621Sbt150084 DDI_DMA_FLAGERR /* DMA flags */ 816621Sbt150084 }; 826621Sbt150084 836621Sbt150084 /* 846621Sbt150084 * DMA attributes for transmit. 856621Sbt150084 */ 866621Sbt150084 static ddi_dma_attr_t ixgbe_tx_dma_attr = { 876621Sbt150084 DMA_ATTR_V0, /* version number */ 886621Sbt150084 0x0000000000000000ull, /* low address */ 896621Sbt150084 0xFFFFFFFFFFFFFFFFull, /* high address */ 906621Sbt150084 0x00000000FFFFFFFFull, /* dma counter max */ 916621Sbt150084 1, /* alignment */ 926621Sbt150084 0x00000FFF, /* burst sizes */ 936621Sbt150084 0x00000001, /* minimum transfer size */ 946621Sbt150084 0x00000000FFFFFFFFull, /* maximum transfer size */ 956621Sbt150084 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */ 966621Sbt150084 MAX_COOKIE, /* scatter/gather list length */ 976621Sbt150084 0x00000001, /* granularity */ 986621Sbt150084 DDI_DMA_FLAGERR /* DMA flags */ 996621Sbt150084 }; 1006621Sbt150084 1016621Sbt150084 /* 1026621Sbt150084 * DMA access attributes for descriptors. 1036621Sbt150084 */ 1046621Sbt150084 static ddi_device_acc_attr_t ixgbe_desc_acc_attr = { 1056621Sbt150084 DDI_DEVICE_ATTR_V0, 1066621Sbt150084 DDI_STRUCTURE_LE_ACC, 107*11236SStephen.Hanson@Sun.COM DDI_STRICTORDER_ACC 1086621Sbt150084 }; 1096621Sbt150084 1106621Sbt150084 /* 1116621Sbt150084 * DMA access attributes for buffers. 1126621Sbt150084 */ 1136621Sbt150084 static ddi_device_acc_attr_t ixgbe_buf_acc_attr = { 1146621Sbt150084 DDI_DEVICE_ATTR_V0, 1156621Sbt150084 DDI_NEVERSWAP_ACC, 1166621Sbt150084 DDI_STRICTORDER_ACC 1176621Sbt150084 }; 1186621Sbt150084 1196621Sbt150084 /* 1206621Sbt150084 * ixgbe_alloc_dma - Allocate DMA resources for all rx/tx rings. 1216621Sbt150084 */ 1226621Sbt150084 int 1236621Sbt150084 ixgbe_alloc_dma(ixgbe_t *ixgbe) 1246621Sbt150084 { 12510376SChenlu.Chen@Sun.COM ixgbe_rx_ring_t *rx_ring; 12610376SChenlu.Chen@Sun.COM ixgbe_rx_data_t *rx_data; 1276621Sbt150084 ixgbe_tx_ring_t *tx_ring; 1286621Sbt150084 int i; 1296621Sbt150084 1306621Sbt150084 for (i = 0; i < ixgbe->num_rx_rings; i++) { 1316621Sbt150084 /* 1326621Sbt150084 * Allocate receive desciptor ring and control block lists 1336621Sbt150084 */ 1346621Sbt150084 rx_ring = &ixgbe->rx_rings[i]; 13510376SChenlu.Chen@Sun.COM rx_data = rx_ring->rx_data; 1366621Sbt150084 13710376SChenlu.Chen@Sun.COM if (ixgbe_alloc_rbd_ring(rx_data) != IXGBE_SUCCESS) 1386621Sbt150084 goto alloc_dma_failure; 1396621Sbt150084 14010376SChenlu.Chen@Sun.COM if (ixgbe_alloc_rcb_lists(rx_data) != IXGBE_SUCCESS) 1416621Sbt150084 goto alloc_dma_failure; 1426621Sbt150084 } 1436621Sbt150084 1446621Sbt150084 for (i = 0; i < ixgbe->num_tx_rings; i++) { 1456621Sbt150084 /* 1466621Sbt150084 * Allocate transmit desciptor ring and control block lists 1476621Sbt150084 */ 1486621Sbt150084 tx_ring = &ixgbe->tx_rings[i]; 1496621Sbt150084 1506621Sbt150084 if (ixgbe_alloc_tbd_ring(tx_ring) != IXGBE_SUCCESS) 1516621Sbt150084 goto alloc_dma_failure; 1526621Sbt150084 1536621Sbt150084 if (ixgbe_alloc_tcb_lists(tx_ring) != IXGBE_SUCCESS) 1546621Sbt150084 goto alloc_dma_failure; 1556621Sbt150084 } 1566621Sbt150084 1576621Sbt150084 return (IXGBE_SUCCESS); 1586621Sbt150084 1596621Sbt150084 alloc_dma_failure: 1606621Sbt150084 ixgbe_free_dma(ixgbe); 1616621Sbt150084 1626621Sbt150084 return (IXGBE_FAILURE); 1636621Sbt150084 } 1646621Sbt150084 1656621Sbt150084 /* 1666621Sbt150084 * ixgbe_free_dma - Free all the DMA resources of all rx/tx rings. 1676621Sbt150084 */ 1686621Sbt150084 void 1696621Sbt150084 ixgbe_free_dma(ixgbe_t *ixgbe) 1706621Sbt150084 { 1716621Sbt150084 ixgbe_rx_ring_t *rx_ring; 17210376SChenlu.Chen@Sun.COM ixgbe_rx_data_t *rx_data; 1736621Sbt150084 ixgbe_tx_ring_t *tx_ring; 1746621Sbt150084 int i; 1756621Sbt150084 1766621Sbt150084 /* 1776621Sbt150084 * Free DMA resources of rx rings 1786621Sbt150084 */ 1796621Sbt150084 for (i = 0; i < ixgbe->num_rx_rings; i++) { 1806621Sbt150084 rx_ring = &ixgbe->rx_rings[i]; 18110376SChenlu.Chen@Sun.COM rx_data = rx_ring->rx_data; 18210376SChenlu.Chen@Sun.COM 18310376SChenlu.Chen@Sun.COM ixgbe_free_rbd_ring(rx_data); 18410376SChenlu.Chen@Sun.COM ixgbe_free_rcb_lists(rx_data); 1856621Sbt150084 } 1866621Sbt150084 1876621Sbt150084 /* 1886621Sbt150084 * Free DMA resources of tx rings 1896621Sbt150084 */ 1906621Sbt150084 for (i = 0; i < ixgbe->num_tx_rings; i++) { 1916621Sbt150084 tx_ring = &ixgbe->tx_rings[i]; 1926621Sbt150084 ixgbe_free_tbd_ring(tx_ring); 1936621Sbt150084 ixgbe_free_tcb_lists(tx_ring); 1946621Sbt150084 } 1956621Sbt150084 } 1966621Sbt150084 19710376SChenlu.Chen@Sun.COM int 19810376SChenlu.Chen@Sun.COM ixgbe_alloc_rx_ring_data(ixgbe_rx_ring_t *rx_ring) 19910376SChenlu.Chen@Sun.COM { 20010376SChenlu.Chen@Sun.COM ixgbe_rx_data_t *rx_data; 20110376SChenlu.Chen@Sun.COM ixgbe_t *ixgbe = rx_ring->ixgbe; 20210376SChenlu.Chen@Sun.COM uint32_t rcb_count; 20310376SChenlu.Chen@Sun.COM 20410376SChenlu.Chen@Sun.COM /* 20510376SChenlu.Chen@Sun.COM * Allocate memory for software receive rings 20610376SChenlu.Chen@Sun.COM */ 20710376SChenlu.Chen@Sun.COM rx_data = kmem_zalloc(sizeof (ixgbe_rx_data_t), KM_NOSLEEP); 20810376SChenlu.Chen@Sun.COM 20910376SChenlu.Chen@Sun.COM if (rx_data == NULL) { 21010376SChenlu.Chen@Sun.COM ixgbe_error(ixgbe, "Allocate software receive rings failed"); 21110376SChenlu.Chen@Sun.COM return (IXGBE_FAILURE); 21210376SChenlu.Chen@Sun.COM } 21310376SChenlu.Chen@Sun.COM 21410376SChenlu.Chen@Sun.COM rx_data->rx_ring = rx_ring; 21510376SChenlu.Chen@Sun.COM mutex_init(&rx_data->recycle_lock, NULL, 21610376SChenlu.Chen@Sun.COM MUTEX_DRIVER, DDI_INTR_PRI(ixgbe->intr_pri)); 21710376SChenlu.Chen@Sun.COM 21810376SChenlu.Chen@Sun.COM rx_data->ring_size = ixgbe->rx_ring_size; 21910376SChenlu.Chen@Sun.COM rx_data->free_list_size = ixgbe->rx_ring_size; 22010376SChenlu.Chen@Sun.COM 22110376SChenlu.Chen@Sun.COM rx_data->rcb_head = 0; 22210376SChenlu.Chen@Sun.COM rx_data->rcb_tail = 0; 22310376SChenlu.Chen@Sun.COM rx_data->rcb_free = rx_data->free_list_size; 22410376SChenlu.Chen@Sun.COM 22510376SChenlu.Chen@Sun.COM /* 22610376SChenlu.Chen@Sun.COM * Allocate memory for the work list. 22710376SChenlu.Chen@Sun.COM */ 22810376SChenlu.Chen@Sun.COM rx_data->work_list = kmem_zalloc(sizeof (rx_control_block_t *) * 22910376SChenlu.Chen@Sun.COM rx_data->ring_size, KM_NOSLEEP); 23010376SChenlu.Chen@Sun.COM 23110376SChenlu.Chen@Sun.COM if (rx_data->work_list == NULL) { 23210376SChenlu.Chen@Sun.COM ixgbe_error(ixgbe, 23310376SChenlu.Chen@Sun.COM "Could not allocate memory for rx work list"); 23410376SChenlu.Chen@Sun.COM goto alloc_rx_data_failure; 23510376SChenlu.Chen@Sun.COM } 23610376SChenlu.Chen@Sun.COM 23710376SChenlu.Chen@Sun.COM /* 23810376SChenlu.Chen@Sun.COM * Allocate memory for the free list. 23910376SChenlu.Chen@Sun.COM */ 24010376SChenlu.Chen@Sun.COM rx_data->free_list = kmem_zalloc(sizeof (rx_control_block_t *) * 24110376SChenlu.Chen@Sun.COM rx_data->free_list_size, KM_NOSLEEP); 24210376SChenlu.Chen@Sun.COM 24310376SChenlu.Chen@Sun.COM if (rx_data->free_list == NULL) { 24410376SChenlu.Chen@Sun.COM ixgbe_error(ixgbe, 24510376SChenlu.Chen@Sun.COM "Cound not allocate memory for rx free list"); 24610376SChenlu.Chen@Sun.COM goto alloc_rx_data_failure; 24710376SChenlu.Chen@Sun.COM } 24810376SChenlu.Chen@Sun.COM 24910376SChenlu.Chen@Sun.COM /* 25010376SChenlu.Chen@Sun.COM * Allocate memory for the rx control blocks for work list and 25110376SChenlu.Chen@Sun.COM * free list. 25210376SChenlu.Chen@Sun.COM */ 25310376SChenlu.Chen@Sun.COM rcb_count = rx_data->ring_size + rx_data->free_list_size; 25410376SChenlu.Chen@Sun.COM rx_data->rcb_area = 25510376SChenlu.Chen@Sun.COM kmem_zalloc(sizeof (rx_control_block_t) * rcb_count, 25610376SChenlu.Chen@Sun.COM KM_NOSLEEP); 25710376SChenlu.Chen@Sun.COM 25810376SChenlu.Chen@Sun.COM if (rx_data->rcb_area == NULL) { 25910376SChenlu.Chen@Sun.COM ixgbe_error(ixgbe, 26010376SChenlu.Chen@Sun.COM "Cound not allocate memory for rx control blocks"); 26110376SChenlu.Chen@Sun.COM goto alloc_rx_data_failure; 26210376SChenlu.Chen@Sun.COM } 26310376SChenlu.Chen@Sun.COM 26410376SChenlu.Chen@Sun.COM rx_ring->rx_data = rx_data; 26510376SChenlu.Chen@Sun.COM return (IXGBE_SUCCESS); 26610376SChenlu.Chen@Sun.COM 26710376SChenlu.Chen@Sun.COM alloc_rx_data_failure: 26810376SChenlu.Chen@Sun.COM ixgbe_free_rx_ring_data(rx_data); 26910376SChenlu.Chen@Sun.COM return (IXGBE_FAILURE); 27010376SChenlu.Chen@Sun.COM } 27110376SChenlu.Chen@Sun.COM 27210376SChenlu.Chen@Sun.COM void 27310376SChenlu.Chen@Sun.COM ixgbe_free_rx_ring_data(ixgbe_rx_data_t *rx_data) 27410376SChenlu.Chen@Sun.COM { 27510376SChenlu.Chen@Sun.COM uint32_t rcb_count; 27610376SChenlu.Chen@Sun.COM 27710376SChenlu.Chen@Sun.COM if (rx_data == NULL) 27810376SChenlu.Chen@Sun.COM return; 27910376SChenlu.Chen@Sun.COM 28010376SChenlu.Chen@Sun.COM ASSERT(rx_data->rcb_pending == 0); 28110376SChenlu.Chen@Sun.COM 28210376SChenlu.Chen@Sun.COM rcb_count = rx_data->ring_size + rx_data->free_list_size; 28310376SChenlu.Chen@Sun.COM if (rx_data->rcb_area != NULL) { 28410376SChenlu.Chen@Sun.COM kmem_free(rx_data->rcb_area, 28510376SChenlu.Chen@Sun.COM sizeof (rx_control_block_t) * rcb_count); 28610376SChenlu.Chen@Sun.COM rx_data->rcb_area = NULL; 28710376SChenlu.Chen@Sun.COM } 28810376SChenlu.Chen@Sun.COM 28910376SChenlu.Chen@Sun.COM if (rx_data->work_list != NULL) { 29010376SChenlu.Chen@Sun.COM kmem_free(rx_data->work_list, 29110376SChenlu.Chen@Sun.COM sizeof (rx_control_block_t *) * rx_data->ring_size); 29210376SChenlu.Chen@Sun.COM rx_data->work_list = NULL; 29310376SChenlu.Chen@Sun.COM } 29410376SChenlu.Chen@Sun.COM 29510376SChenlu.Chen@Sun.COM if (rx_data->free_list != NULL) { 29610376SChenlu.Chen@Sun.COM kmem_free(rx_data->free_list, 29710376SChenlu.Chen@Sun.COM sizeof (rx_control_block_t *) * rx_data->free_list_size); 29810376SChenlu.Chen@Sun.COM rx_data->free_list = NULL; 29910376SChenlu.Chen@Sun.COM } 30010376SChenlu.Chen@Sun.COM 30110376SChenlu.Chen@Sun.COM mutex_destroy(&rx_data->recycle_lock); 30210376SChenlu.Chen@Sun.COM kmem_free(rx_data, sizeof (ixgbe_rx_data_t)); 30310376SChenlu.Chen@Sun.COM } 30410376SChenlu.Chen@Sun.COM 3056621Sbt150084 /* 3066621Sbt150084 * ixgbe_alloc_tbd_ring - Memory allocation for the tx descriptors of one ring. 3076621Sbt150084 */ 3086621Sbt150084 static int 3096621Sbt150084 ixgbe_alloc_tbd_ring(ixgbe_tx_ring_t *tx_ring) 3106621Sbt150084 { 3116621Sbt150084 int ret; 3126621Sbt150084 size_t size; 3136621Sbt150084 size_t len; 3146621Sbt150084 uint_t cookie_num; 3156621Sbt150084 dev_info_t *devinfo; 3166621Sbt150084 ddi_dma_cookie_t cookie; 3176621Sbt150084 ixgbe_t *ixgbe = tx_ring->ixgbe; 3186621Sbt150084 3196621Sbt150084 devinfo = ixgbe->dip; 3206621Sbt150084 size = sizeof (union ixgbe_adv_tx_desc) * tx_ring->ring_size; 3216621Sbt150084 3226621Sbt150084 /* 3236621Sbt150084 * If tx head write-back is enabled, an extra tbd is allocated 3246621Sbt150084 * to save the head write-back value 3256621Sbt150084 */ 3266621Sbt150084 if (ixgbe->tx_head_wb_enable) { 3276621Sbt150084 size += sizeof (union ixgbe_adv_tx_desc); 3286621Sbt150084 } 3296621Sbt150084 3306621Sbt150084 /* 3316621Sbt150084 * Allocate a DMA handle for the transmit descriptor 3326621Sbt150084 * memory area. 3336621Sbt150084 */ 3346621Sbt150084 ret = ddi_dma_alloc_handle(devinfo, &ixgbe_desc_dma_attr, 3356621Sbt150084 DDI_DMA_DONTWAIT, NULL, 3366621Sbt150084 &tx_ring->tbd_area.dma_handle); 3376621Sbt150084 3386621Sbt150084 if (ret != DDI_SUCCESS) { 3396621Sbt150084 ixgbe_error(ixgbe, 3406621Sbt150084 "Could not allocate tbd dma handle: %x", ret); 3416621Sbt150084 tx_ring->tbd_area.dma_handle = NULL; 3426621Sbt150084 3436621Sbt150084 return (IXGBE_FAILURE); 3446621Sbt150084 } 3456621Sbt150084 3466621Sbt150084 /* 3476621Sbt150084 * Allocate memory to DMA data to and from the transmit 3486621Sbt150084 * descriptors. 3496621Sbt150084 */ 3506621Sbt150084 ret = ddi_dma_mem_alloc(tx_ring->tbd_area.dma_handle, 3516621Sbt150084 size, &ixgbe_desc_acc_attr, DDI_DMA_CONSISTENT, 3526621Sbt150084 DDI_DMA_DONTWAIT, NULL, 3536621Sbt150084 (caddr_t *)&tx_ring->tbd_area.address, 3546621Sbt150084 &len, &tx_ring->tbd_area.acc_handle); 3556621Sbt150084 3566621Sbt150084 if (ret != DDI_SUCCESS) { 3576621Sbt150084 ixgbe_error(ixgbe, 3586621Sbt150084 "Could not allocate tbd dma memory: %x", ret); 3596621Sbt150084 tx_ring->tbd_area.acc_handle = NULL; 3606621Sbt150084 tx_ring->tbd_area.address = NULL; 3616621Sbt150084 if (tx_ring->tbd_area.dma_handle != NULL) { 3626621Sbt150084 ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle); 3636621Sbt150084 tx_ring->tbd_area.dma_handle = NULL; 3646621Sbt150084 } 3656621Sbt150084 return (IXGBE_FAILURE); 3666621Sbt150084 } 3676621Sbt150084 3686621Sbt150084 /* 3696621Sbt150084 * Initialize the entire transmit buffer descriptor area to zero 3706621Sbt150084 */ 3716621Sbt150084 bzero(tx_ring->tbd_area.address, len); 3726621Sbt150084 3736621Sbt150084 /* 3746621Sbt150084 * Allocates DMA resources for the memory that was allocated by 3756621Sbt150084 * the ddi_dma_mem_alloc call. The DMA resources then get bound to the 3766621Sbt150084 * the memory address 3776621Sbt150084 */ 3786621Sbt150084 ret = ddi_dma_addr_bind_handle(tx_ring->tbd_area.dma_handle, 3796621Sbt150084 NULL, (caddr_t)tx_ring->tbd_area.address, 3806621Sbt150084 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 3816621Sbt150084 DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num); 3826621Sbt150084 3836621Sbt150084 if (ret != DDI_DMA_MAPPED) { 3846621Sbt150084 ixgbe_error(ixgbe, 3856621Sbt150084 "Could not bind tbd dma resource: %x", ret); 3866621Sbt150084 tx_ring->tbd_area.dma_address = NULL; 3876621Sbt150084 if (tx_ring->tbd_area.acc_handle != NULL) { 3886621Sbt150084 ddi_dma_mem_free(&tx_ring->tbd_area.acc_handle); 3896621Sbt150084 tx_ring->tbd_area.acc_handle = NULL; 3906621Sbt150084 tx_ring->tbd_area.address = NULL; 3916621Sbt150084 } 3926621Sbt150084 if (tx_ring->tbd_area.dma_handle != NULL) { 3936621Sbt150084 ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle); 3946621Sbt150084 tx_ring->tbd_area.dma_handle = NULL; 3956621Sbt150084 } 3966621Sbt150084 return (IXGBE_FAILURE); 3976621Sbt150084 } 3986621Sbt150084 3996621Sbt150084 ASSERT(cookie_num == 1); 4006621Sbt150084 4016621Sbt150084 tx_ring->tbd_area.dma_address = cookie.dmac_laddress; 4026621Sbt150084 tx_ring->tbd_area.size = len; 4036621Sbt150084 4046621Sbt150084 tx_ring->tbd_ring = (union ixgbe_adv_tx_desc *)(uintptr_t) 4056621Sbt150084 tx_ring->tbd_area.address; 4066621Sbt150084 4076621Sbt150084 return (IXGBE_SUCCESS); 4086621Sbt150084 } 4096621Sbt150084 4106621Sbt150084 /* 4116621Sbt150084 * ixgbe_free_tbd_ring - Free the tx descriptors of one ring. 4126621Sbt150084 */ 4136621Sbt150084 static void 4146621Sbt150084 ixgbe_free_tbd_ring(ixgbe_tx_ring_t *tx_ring) 4156621Sbt150084 { 4166621Sbt150084 if (tx_ring->tbd_area.dma_handle != NULL) { 4176621Sbt150084 (void) ddi_dma_unbind_handle(tx_ring->tbd_area.dma_handle); 4186621Sbt150084 } 4196621Sbt150084 if (tx_ring->tbd_area.acc_handle != NULL) { 4206621Sbt150084 ddi_dma_mem_free(&tx_ring->tbd_area.acc_handle); 4216621Sbt150084 tx_ring->tbd_area.acc_handle = NULL; 4226621Sbt150084 } 4236621Sbt150084 if (tx_ring->tbd_area.dma_handle != NULL) { 4246621Sbt150084 ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle); 4256621Sbt150084 tx_ring->tbd_area.dma_handle = NULL; 4266621Sbt150084 } 4276621Sbt150084 tx_ring->tbd_area.address = NULL; 4286621Sbt150084 tx_ring->tbd_area.dma_address = NULL; 4296621Sbt150084 tx_ring->tbd_area.size = 0; 4306621Sbt150084 4316621Sbt150084 tx_ring->tbd_ring = NULL; 4326621Sbt150084 } 4336621Sbt150084 4346621Sbt150084 /* 4356621Sbt150084 * ixgbe_alloc_rbd_ring - Memory allocation for the rx descriptors of one ring. 4366621Sbt150084 */ 4376621Sbt150084 static int 43810376SChenlu.Chen@Sun.COM ixgbe_alloc_rbd_ring(ixgbe_rx_data_t *rx_data) 4396621Sbt150084 { 4406621Sbt150084 int ret; 4416621Sbt150084 size_t size; 4426621Sbt150084 size_t len; 4436621Sbt150084 uint_t cookie_num; 4446621Sbt150084 dev_info_t *devinfo; 4456621Sbt150084 ddi_dma_cookie_t cookie; 44610376SChenlu.Chen@Sun.COM ixgbe_t *ixgbe = rx_data->rx_ring->ixgbe; 4476621Sbt150084 4486621Sbt150084 devinfo = ixgbe->dip; 44910376SChenlu.Chen@Sun.COM size = sizeof (union ixgbe_adv_rx_desc) * rx_data->ring_size; 4506621Sbt150084 4516621Sbt150084 /* 4526621Sbt150084 * Allocate a new DMA handle for the receive descriptor 4536621Sbt150084 * memory area. 4546621Sbt150084 */ 4556621Sbt150084 ret = ddi_dma_alloc_handle(devinfo, &ixgbe_desc_dma_attr, 4566621Sbt150084 DDI_DMA_DONTWAIT, NULL, 45710376SChenlu.Chen@Sun.COM &rx_data->rbd_area.dma_handle); 4586621Sbt150084 4596621Sbt150084 if (ret != DDI_SUCCESS) { 4606621Sbt150084 ixgbe_error(ixgbe, 4616621Sbt150084 "Could not allocate rbd dma handle: %x", ret); 46210376SChenlu.Chen@Sun.COM rx_data->rbd_area.dma_handle = NULL; 4636621Sbt150084 return (IXGBE_FAILURE); 4646621Sbt150084 } 4656621Sbt150084 4666621Sbt150084 /* 4676621Sbt150084 * Allocate memory to DMA data to and from the receive 4686621Sbt150084 * descriptors. 4696621Sbt150084 */ 47010376SChenlu.Chen@Sun.COM ret = ddi_dma_mem_alloc(rx_data->rbd_area.dma_handle, 4716621Sbt150084 size, &ixgbe_desc_acc_attr, DDI_DMA_CONSISTENT, 4726621Sbt150084 DDI_DMA_DONTWAIT, NULL, 47310376SChenlu.Chen@Sun.COM (caddr_t *)&rx_data->rbd_area.address, 47410376SChenlu.Chen@Sun.COM &len, &rx_data->rbd_area.acc_handle); 4756621Sbt150084 4766621Sbt150084 if (ret != DDI_SUCCESS) { 4776621Sbt150084 ixgbe_error(ixgbe, 4786621Sbt150084 "Could not allocate rbd dma memory: %x", ret); 47910376SChenlu.Chen@Sun.COM rx_data->rbd_area.acc_handle = NULL; 48010376SChenlu.Chen@Sun.COM rx_data->rbd_area.address = NULL; 48110376SChenlu.Chen@Sun.COM if (rx_data->rbd_area.dma_handle != NULL) { 48210376SChenlu.Chen@Sun.COM ddi_dma_free_handle(&rx_data->rbd_area.dma_handle); 48310376SChenlu.Chen@Sun.COM rx_data->rbd_area.dma_handle = NULL; 4846621Sbt150084 } 4856621Sbt150084 return (IXGBE_FAILURE); 4866621Sbt150084 } 4876621Sbt150084 4886621Sbt150084 /* 4896621Sbt150084 * Initialize the entire transmit buffer descriptor area to zero 4906621Sbt150084 */ 49110376SChenlu.Chen@Sun.COM bzero(rx_data->rbd_area.address, len); 4926621Sbt150084 4936621Sbt150084 /* 4946621Sbt150084 * Allocates DMA resources for the memory that was allocated by 4956621Sbt150084 * the ddi_dma_mem_alloc call. 4966621Sbt150084 */ 49710376SChenlu.Chen@Sun.COM ret = ddi_dma_addr_bind_handle(rx_data->rbd_area.dma_handle, 49810376SChenlu.Chen@Sun.COM NULL, (caddr_t)rx_data->rbd_area.address, 4996621Sbt150084 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 5006621Sbt150084 DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num); 5016621Sbt150084 5026621Sbt150084 if (ret != DDI_DMA_MAPPED) { 5036621Sbt150084 ixgbe_error(ixgbe, 5046621Sbt150084 "Could not bind rbd dma resource: %x", ret); 50510376SChenlu.Chen@Sun.COM rx_data->rbd_area.dma_address = NULL; 50610376SChenlu.Chen@Sun.COM if (rx_data->rbd_area.acc_handle != NULL) { 50710376SChenlu.Chen@Sun.COM ddi_dma_mem_free(&rx_data->rbd_area.acc_handle); 50810376SChenlu.Chen@Sun.COM rx_data->rbd_area.acc_handle = NULL; 50910376SChenlu.Chen@Sun.COM rx_data->rbd_area.address = NULL; 5106621Sbt150084 } 51110376SChenlu.Chen@Sun.COM if (rx_data->rbd_area.dma_handle != NULL) { 51210376SChenlu.Chen@Sun.COM ddi_dma_free_handle(&rx_data->rbd_area.dma_handle); 51310376SChenlu.Chen@Sun.COM rx_data->rbd_area.dma_handle = NULL; 5146621Sbt150084 } 5156621Sbt150084 return (IXGBE_FAILURE); 5166621Sbt150084 } 5176621Sbt150084 5186621Sbt150084 ASSERT(cookie_num == 1); 5196621Sbt150084 52010376SChenlu.Chen@Sun.COM rx_data->rbd_area.dma_address = cookie.dmac_laddress; 52110376SChenlu.Chen@Sun.COM rx_data->rbd_area.size = len; 5226621Sbt150084 52310376SChenlu.Chen@Sun.COM rx_data->rbd_ring = (union ixgbe_adv_rx_desc *)(uintptr_t) 52410376SChenlu.Chen@Sun.COM rx_data->rbd_area.address; 5256621Sbt150084 5266621Sbt150084 return (IXGBE_SUCCESS); 5276621Sbt150084 } 5286621Sbt150084 5296621Sbt150084 /* 5306621Sbt150084 * ixgbe_free_rbd_ring - Free the rx descriptors of one ring. 5316621Sbt150084 */ 5326621Sbt150084 static void 53310376SChenlu.Chen@Sun.COM ixgbe_free_rbd_ring(ixgbe_rx_data_t *rx_data) 5346621Sbt150084 { 53510376SChenlu.Chen@Sun.COM if (rx_data->rbd_area.dma_handle != NULL) { 53610376SChenlu.Chen@Sun.COM (void) ddi_dma_unbind_handle(rx_data->rbd_area.dma_handle); 5376621Sbt150084 } 53810376SChenlu.Chen@Sun.COM if (rx_data->rbd_area.acc_handle != NULL) { 53910376SChenlu.Chen@Sun.COM ddi_dma_mem_free(&rx_data->rbd_area.acc_handle); 54010376SChenlu.Chen@Sun.COM rx_data->rbd_area.acc_handle = NULL; 5416621Sbt150084 } 54210376SChenlu.Chen@Sun.COM if (rx_data->rbd_area.dma_handle != NULL) { 54310376SChenlu.Chen@Sun.COM ddi_dma_free_handle(&rx_data->rbd_area.dma_handle); 54410376SChenlu.Chen@Sun.COM rx_data->rbd_area.dma_handle = NULL; 5456621Sbt150084 } 54610376SChenlu.Chen@Sun.COM rx_data->rbd_area.address = NULL; 54710376SChenlu.Chen@Sun.COM rx_data->rbd_area.dma_address = NULL; 54810376SChenlu.Chen@Sun.COM rx_data->rbd_area.size = 0; 5496621Sbt150084 55010376SChenlu.Chen@Sun.COM rx_data->rbd_ring = NULL; 5516621Sbt150084 } 5526621Sbt150084 5536621Sbt150084 /* 5546621Sbt150084 * ixgbe_alloc_dma_buffer - Allocate DMA resources for a DMA buffer. 5556621Sbt150084 */ 5566621Sbt150084 static int 5576621Sbt150084 ixgbe_alloc_dma_buffer(ixgbe_t *ixgbe, dma_buffer_t *buf, size_t size) 5586621Sbt150084 { 5596621Sbt150084 int ret; 5606621Sbt150084 dev_info_t *devinfo = ixgbe->dip; 5616621Sbt150084 ddi_dma_cookie_t cookie; 5626621Sbt150084 size_t len; 5636621Sbt150084 uint_t cookie_num; 5646621Sbt150084 5656621Sbt150084 ret = ddi_dma_alloc_handle(devinfo, 5666621Sbt150084 &ixgbe_buf_dma_attr, DDI_DMA_DONTWAIT, 5676621Sbt150084 NULL, &buf->dma_handle); 5686621Sbt150084 5696621Sbt150084 if (ret != DDI_SUCCESS) { 5706621Sbt150084 buf->dma_handle = NULL; 5716621Sbt150084 ixgbe_error(ixgbe, 5726621Sbt150084 "Could not allocate dma buffer handle: %x", ret); 5736621Sbt150084 return (IXGBE_FAILURE); 5746621Sbt150084 } 5756621Sbt150084 5766621Sbt150084 ret = ddi_dma_mem_alloc(buf->dma_handle, 5776621Sbt150084 size, &ixgbe_buf_acc_attr, DDI_DMA_STREAMING, 5786621Sbt150084 DDI_DMA_DONTWAIT, NULL, &buf->address, 5796621Sbt150084 &len, &buf->acc_handle); 5806621Sbt150084 5816621Sbt150084 if (ret != DDI_SUCCESS) { 5826621Sbt150084 buf->acc_handle = NULL; 5836621Sbt150084 buf->address = NULL; 5846621Sbt150084 if (buf->dma_handle != NULL) { 5856621Sbt150084 ddi_dma_free_handle(&buf->dma_handle); 5866621Sbt150084 buf->dma_handle = NULL; 5876621Sbt150084 } 5886621Sbt150084 ixgbe_error(ixgbe, 5896621Sbt150084 "Could not allocate dma buffer memory: %x", ret); 5906621Sbt150084 return (IXGBE_FAILURE); 5916621Sbt150084 } 5926621Sbt150084 5936621Sbt150084 ret = ddi_dma_addr_bind_handle(buf->dma_handle, NULL, 5946621Sbt150084 buf->address, 5956621Sbt150084 len, DDI_DMA_RDWR | DDI_DMA_STREAMING, 5966621Sbt150084 DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num); 5976621Sbt150084 5986621Sbt150084 if (ret != DDI_DMA_MAPPED) { 5996621Sbt150084 buf->dma_address = NULL; 6006621Sbt150084 if (buf->acc_handle != NULL) { 6016621Sbt150084 ddi_dma_mem_free(&buf->acc_handle); 6026621Sbt150084 buf->acc_handle = NULL; 6036621Sbt150084 buf->address = NULL; 6046621Sbt150084 } 6056621Sbt150084 if (buf->dma_handle != NULL) { 6066621Sbt150084 ddi_dma_free_handle(&buf->dma_handle); 6076621Sbt150084 buf->dma_handle = NULL; 6086621Sbt150084 } 6096621Sbt150084 ixgbe_error(ixgbe, 6106621Sbt150084 "Could not bind dma buffer handle: %x", ret); 6116621Sbt150084 return (IXGBE_FAILURE); 6126621Sbt150084 } 6136621Sbt150084 6146621Sbt150084 ASSERT(cookie_num == 1); 6156621Sbt150084 6166621Sbt150084 buf->dma_address = cookie.dmac_laddress; 6176621Sbt150084 buf->size = len; 6186621Sbt150084 buf->len = 0; 6196621Sbt150084 6206621Sbt150084 return (IXGBE_SUCCESS); 6216621Sbt150084 } 6226621Sbt150084 6236621Sbt150084 /* 6246621Sbt150084 * ixgbe_free_dma_buffer - Free one allocated area of dma memory and handle. 6256621Sbt150084 */ 62610376SChenlu.Chen@Sun.COM void 6276621Sbt150084 ixgbe_free_dma_buffer(dma_buffer_t *buf) 6286621Sbt150084 { 6296621Sbt150084 if (buf->dma_handle != NULL) { 6306621Sbt150084 (void) ddi_dma_unbind_handle(buf->dma_handle); 6316621Sbt150084 buf->dma_address = NULL; 6326621Sbt150084 } else { 6336621Sbt150084 return; 6346621Sbt150084 } 6356621Sbt150084 6366621Sbt150084 if (buf->acc_handle != NULL) { 6376621Sbt150084 ddi_dma_mem_free(&buf->acc_handle); 6386621Sbt150084 buf->acc_handle = NULL; 6396621Sbt150084 buf->address = NULL; 6406621Sbt150084 } 6416621Sbt150084 6426621Sbt150084 if (buf->dma_handle != NULL) { 6436621Sbt150084 ddi_dma_free_handle(&buf->dma_handle); 6446621Sbt150084 buf->dma_handle = NULL; 6456621Sbt150084 } 6466621Sbt150084 6476621Sbt150084 buf->size = 0; 6486621Sbt150084 buf->len = 0; 6496621Sbt150084 } 6506621Sbt150084 6516621Sbt150084 /* 6526621Sbt150084 * ixgbe_alloc_tcb_lists - Memory allocation for the transmit control bolcks 6536621Sbt150084 * of one ring. 6546621Sbt150084 */ 6556621Sbt150084 static int 6566621Sbt150084 ixgbe_alloc_tcb_lists(ixgbe_tx_ring_t *tx_ring) 6576621Sbt150084 { 6586621Sbt150084 int i; 6596621Sbt150084 int ret; 6606621Sbt150084 tx_control_block_t *tcb; 6616621Sbt150084 dma_buffer_t *tx_buf; 6626621Sbt150084 ixgbe_t *ixgbe = tx_ring->ixgbe; 6636621Sbt150084 dev_info_t *devinfo = ixgbe->dip; 6646621Sbt150084 6656621Sbt150084 /* 6666621Sbt150084 * Allocate memory for the work list. 6676621Sbt150084 */ 6686621Sbt150084 tx_ring->work_list = kmem_zalloc(sizeof (tx_control_block_t *) * 6696621Sbt150084 tx_ring->ring_size, KM_NOSLEEP); 6706621Sbt150084 6716621Sbt150084 if (tx_ring->work_list == NULL) { 6726621Sbt150084 ixgbe_error(ixgbe, 6736621Sbt150084 "Cound not allocate memory for tx work list"); 6746621Sbt150084 return (IXGBE_FAILURE); 6756621Sbt150084 } 6766621Sbt150084 6776621Sbt150084 /* 6786621Sbt150084 * Allocate memory for the free list. 6796621Sbt150084 */ 6806621Sbt150084 tx_ring->free_list = kmem_zalloc(sizeof (tx_control_block_t *) * 6816621Sbt150084 tx_ring->free_list_size, KM_NOSLEEP); 6826621Sbt150084 6836621Sbt150084 if (tx_ring->free_list == NULL) { 6846621Sbt150084 kmem_free(tx_ring->work_list, 6856621Sbt150084 sizeof (tx_control_block_t *) * tx_ring->ring_size); 6866621Sbt150084 tx_ring->work_list = NULL; 6876621Sbt150084 6886621Sbt150084 ixgbe_error(ixgbe, 6896621Sbt150084 "Cound not allocate memory for tx free list"); 6906621Sbt150084 return (IXGBE_FAILURE); 6916621Sbt150084 } 6926621Sbt150084 6936621Sbt150084 /* 6946621Sbt150084 * Allocate memory for the tx control blocks of free list. 6956621Sbt150084 */ 6966621Sbt150084 tx_ring->tcb_area = 6976621Sbt150084 kmem_zalloc(sizeof (tx_control_block_t) * 6986621Sbt150084 tx_ring->free_list_size, KM_NOSLEEP); 6996621Sbt150084 7006621Sbt150084 if (tx_ring->tcb_area == NULL) { 7016621Sbt150084 kmem_free(tx_ring->work_list, 7026621Sbt150084 sizeof (tx_control_block_t *) * tx_ring->ring_size); 7036621Sbt150084 tx_ring->work_list = NULL; 7046621Sbt150084 7056621Sbt150084 kmem_free(tx_ring->free_list, 7066621Sbt150084 sizeof (tx_control_block_t *) * tx_ring->free_list_size); 7076621Sbt150084 tx_ring->free_list = NULL; 7086621Sbt150084 7096621Sbt150084 ixgbe_error(ixgbe, 7106621Sbt150084 "Cound not allocate memory for tx control blocks"); 7116621Sbt150084 return (IXGBE_FAILURE); 7126621Sbt150084 } 7136621Sbt150084 7146621Sbt150084 /* 7156621Sbt150084 * Allocate dma memory for the tx control block of free list. 7166621Sbt150084 */ 7176621Sbt150084 tcb = tx_ring->tcb_area; 7186621Sbt150084 for (i = 0; i < tx_ring->free_list_size; i++, tcb++) { 7196621Sbt150084 ASSERT(tcb != NULL); 7206621Sbt150084 7216621Sbt150084 tx_ring->free_list[i] = tcb; 7226621Sbt150084 7236621Sbt150084 /* 7246621Sbt150084 * Pre-allocate dma handles for transmit. These dma handles 7256621Sbt150084 * will be dynamically bound to the data buffers passed down 7266621Sbt150084 * from the upper layers at the time of transmitting. 7276621Sbt150084 */ 7286621Sbt150084 ret = ddi_dma_alloc_handle(devinfo, 7296621Sbt150084 &ixgbe_tx_dma_attr, 7306621Sbt150084 DDI_DMA_DONTWAIT, NULL, 7316621Sbt150084 &tcb->tx_dma_handle); 7326621Sbt150084 if (ret != DDI_SUCCESS) { 7336621Sbt150084 tcb->tx_dma_handle = NULL; 7346621Sbt150084 ixgbe_error(ixgbe, 7356621Sbt150084 "Could not allocate tx dma handle: %x", ret); 7366621Sbt150084 goto alloc_tcb_lists_fail; 7376621Sbt150084 } 7386621Sbt150084 7396621Sbt150084 /* 7406621Sbt150084 * Pre-allocate transmit buffers for packets that the 7416621Sbt150084 * size is less than bcopy_thresh. 7426621Sbt150084 */ 7436621Sbt150084 tx_buf = &tcb->tx_buf; 7446621Sbt150084 7456621Sbt150084 ret = ixgbe_alloc_dma_buffer(ixgbe, 7466621Sbt150084 tx_buf, ixgbe->tx_buf_size); 7476621Sbt150084 7486621Sbt150084 if (ret != IXGBE_SUCCESS) { 7496621Sbt150084 ASSERT(tcb->tx_dma_handle != NULL); 7506621Sbt150084 ddi_dma_free_handle(&tcb->tx_dma_handle); 7516621Sbt150084 tcb->tx_dma_handle = NULL; 7526621Sbt150084 ixgbe_error(ixgbe, "Allocate tx dma buffer failed"); 7536621Sbt150084 goto alloc_tcb_lists_fail; 7546621Sbt150084 } 7559681SPaul.Guo@Sun.COM 7569681SPaul.Guo@Sun.COM tcb->last_index = MAX_TX_RING_SIZE; 7576621Sbt150084 } 7586621Sbt150084 7596621Sbt150084 return (IXGBE_SUCCESS); 7606621Sbt150084 7616621Sbt150084 alloc_tcb_lists_fail: 7626621Sbt150084 ixgbe_free_tcb_lists(tx_ring); 7636621Sbt150084 7646621Sbt150084 return (IXGBE_FAILURE); 7656621Sbt150084 } 7666621Sbt150084 7676621Sbt150084 /* 7686621Sbt150084 * ixgbe_free_tcb_lists - Release the memory allocated for 7696621Sbt150084 * the transmit control bolcks of one ring. 7706621Sbt150084 */ 7716621Sbt150084 static void 7726621Sbt150084 ixgbe_free_tcb_lists(ixgbe_tx_ring_t *tx_ring) 7736621Sbt150084 { 7746621Sbt150084 int i; 7756621Sbt150084 tx_control_block_t *tcb; 7766621Sbt150084 7776621Sbt150084 tcb = tx_ring->tcb_area; 7786621Sbt150084 if (tcb == NULL) 7796621Sbt150084 return; 7806621Sbt150084 7816621Sbt150084 for (i = 0; i < tx_ring->free_list_size; i++, tcb++) { 7826621Sbt150084 ASSERT(tcb != NULL); 7836621Sbt150084 7846621Sbt150084 /* Free the tx dma handle for dynamical binding */ 7856621Sbt150084 if (tcb->tx_dma_handle != NULL) { 7866621Sbt150084 ddi_dma_free_handle(&tcb->tx_dma_handle); 7876621Sbt150084 tcb->tx_dma_handle = NULL; 7886621Sbt150084 } else { 7896621Sbt150084 /* 7906621Sbt150084 * If the dma handle is NULL, then we don't 7916621Sbt150084 * have to check the remaining. 7926621Sbt150084 */ 7936621Sbt150084 break; 7946621Sbt150084 } 7956621Sbt150084 7966621Sbt150084 ixgbe_free_dma_buffer(&tcb->tx_buf); 7976621Sbt150084 } 7986621Sbt150084 7996621Sbt150084 if (tx_ring->tcb_area != NULL) { 8006621Sbt150084 kmem_free(tx_ring->tcb_area, 8016621Sbt150084 sizeof (tx_control_block_t) * tx_ring->free_list_size); 8026621Sbt150084 tx_ring->tcb_area = NULL; 8036621Sbt150084 } 8046621Sbt150084 8056621Sbt150084 if (tx_ring->work_list != NULL) { 8066621Sbt150084 kmem_free(tx_ring->work_list, 8076621Sbt150084 sizeof (tx_control_block_t *) * tx_ring->ring_size); 8086621Sbt150084 tx_ring->work_list = NULL; 8096621Sbt150084 } 8106621Sbt150084 8116621Sbt150084 if (tx_ring->free_list != NULL) { 8126621Sbt150084 kmem_free(tx_ring->free_list, 8136621Sbt150084 sizeof (tx_control_block_t *) * tx_ring->free_list_size); 8146621Sbt150084 tx_ring->free_list = NULL; 8156621Sbt150084 } 8166621Sbt150084 } 8176621Sbt150084 8186621Sbt150084 /* 8196621Sbt150084 * ixgbe_alloc_rcb_lists - Memory allocation for the receive control blocks 8206621Sbt150084 * of one ring. 8216621Sbt150084 */ 8226621Sbt150084 static int 82310376SChenlu.Chen@Sun.COM ixgbe_alloc_rcb_lists(ixgbe_rx_data_t *rx_data) 8246621Sbt150084 { 8256621Sbt150084 int i; 8266621Sbt150084 int ret; 8276621Sbt150084 rx_control_block_t *rcb; 82810376SChenlu.Chen@Sun.COM ixgbe_t *ixgbe = rx_data->rx_ring->ixgbe; 8296621Sbt150084 dma_buffer_t *rx_buf; 8306621Sbt150084 uint32_t rcb_count; 8316621Sbt150084 8326621Sbt150084 /* 8336621Sbt150084 * Allocate memory for the rx control blocks for work list and 8346621Sbt150084 * free list. 8356621Sbt150084 */ 83610376SChenlu.Chen@Sun.COM rcb_count = rx_data->ring_size + rx_data->free_list_size; 83710376SChenlu.Chen@Sun.COM rcb = rx_data->rcb_area; 8386621Sbt150084 8396621Sbt150084 for (i = 0; i < rcb_count; i++, rcb++) { 8406621Sbt150084 ASSERT(rcb != NULL); 8416621Sbt150084 84210376SChenlu.Chen@Sun.COM if (i < rx_data->ring_size) { 8436621Sbt150084 /* Attach the rx control block to the work list */ 84410376SChenlu.Chen@Sun.COM rx_data->work_list[i] = rcb; 8456621Sbt150084 } else { 8466621Sbt150084 /* Attach the rx control block to the free list */ 84710376SChenlu.Chen@Sun.COM rx_data->free_list[i - rx_data->ring_size] = rcb; 8486621Sbt150084 } 8496621Sbt150084 8506621Sbt150084 rx_buf = &rcb->rx_buf; 8516621Sbt150084 ret = ixgbe_alloc_dma_buffer(ixgbe, 8526621Sbt150084 rx_buf, ixgbe->rx_buf_size); 8536621Sbt150084 8546621Sbt150084 if (ret != IXGBE_SUCCESS) { 8556621Sbt150084 ixgbe_error(ixgbe, "Allocate rx dma buffer failed"); 8566621Sbt150084 goto alloc_rcb_lists_fail; 8576621Sbt150084 } 8586621Sbt150084 8596621Sbt150084 rx_buf->size -= IPHDR_ALIGN_ROOM; 8606621Sbt150084 rx_buf->address += IPHDR_ALIGN_ROOM; 8616621Sbt150084 rx_buf->dma_address += IPHDR_ALIGN_ROOM; 8626621Sbt150084 86310376SChenlu.Chen@Sun.COM rcb->ref_cnt = 1; 86410376SChenlu.Chen@Sun.COM rcb->rx_data = (ixgbe_rx_data_t *)rx_data; 8656621Sbt150084 rcb->free_rtn.free_func = ixgbe_rx_recycle; 8666621Sbt150084 rcb->free_rtn.free_arg = (char *)rcb; 8676621Sbt150084 8686621Sbt150084 rcb->mp = desballoc((unsigned char *) 8699353SSamuel.Tu@Sun.COM rx_buf->address, 8709353SSamuel.Tu@Sun.COM rx_buf->size, 8716621Sbt150084 0, &rcb->free_rtn); 8726621Sbt150084 } 8736621Sbt150084 8746621Sbt150084 return (IXGBE_SUCCESS); 8756621Sbt150084 8766621Sbt150084 alloc_rcb_lists_fail: 87710376SChenlu.Chen@Sun.COM ixgbe_free_rcb_lists(rx_data); 8786621Sbt150084 8796621Sbt150084 return (IXGBE_FAILURE); 8806621Sbt150084 } 8816621Sbt150084 8826621Sbt150084 /* 8836621Sbt150084 * ixgbe_free_rcb_lists - Free the receive control blocks of one ring. 8846621Sbt150084 */ 8856621Sbt150084 static void 88610376SChenlu.Chen@Sun.COM ixgbe_free_rcb_lists(ixgbe_rx_data_t *rx_data) 8876621Sbt150084 { 88810376SChenlu.Chen@Sun.COM ixgbe_t *ixgbe; 8896621Sbt150084 rx_control_block_t *rcb; 8906621Sbt150084 uint32_t rcb_count; 89110376SChenlu.Chen@Sun.COM uint32_t ref_cnt; 89210376SChenlu.Chen@Sun.COM int i; 8936621Sbt150084 89410376SChenlu.Chen@Sun.COM ixgbe = rx_data->rx_ring->ixgbe; 89510376SChenlu.Chen@Sun.COM 89610376SChenlu.Chen@Sun.COM mutex_enter(&ixgbe->rx_pending_lock); 8976621Sbt150084 89810376SChenlu.Chen@Sun.COM rcb = rx_data->rcb_area; 89910376SChenlu.Chen@Sun.COM rcb_count = rx_data->ring_size + rx_data->free_list_size; 90010376SChenlu.Chen@Sun.COM 9016621Sbt150084 for (i = 0; i < rcb_count; i++, rcb++) { 9026621Sbt150084 ASSERT(rcb != NULL); 9036621Sbt150084 90410376SChenlu.Chen@Sun.COM ref_cnt = atomic_dec_32_nv(&rcb->ref_cnt); 90510376SChenlu.Chen@Sun.COM if (ref_cnt == 0) { 90610376SChenlu.Chen@Sun.COM if (rcb->mp != NULL) { 90710376SChenlu.Chen@Sun.COM freemsg(rcb->mp); 90810376SChenlu.Chen@Sun.COM rcb->mp = NULL; 90910376SChenlu.Chen@Sun.COM } 91010376SChenlu.Chen@Sun.COM ixgbe_free_dma_buffer(&rcb->rx_buf); 91110376SChenlu.Chen@Sun.COM } else { 91210376SChenlu.Chen@Sun.COM atomic_inc_32(&rx_data->rcb_pending); 91310376SChenlu.Chen@Sun.COM atomic_inc_32(&ixgbe->rcb_pending); 9146621Sbt150084 } 9156621Sbt150084 } 9166621Sbt150084 91710376SChenlu.Chen@Sun.COM mutex_exit(&ixgbe->rx_pending_lock); 9186621Sbt150084 } 9196621Sbt150084 9206621Sbt150084 /* 9216621Sbt150084 * ixgbe_set_fma_flags - Set the attribute for fma support. 9226621Sbt150084 */ 9236621Sbt150084 void 924*11236SStephen.Hanson@Sun.COM ixgbe_set_fma_flags(int dma_flag) 9256621Sbt150084 { 9266621Sbt150084 if (dma_flag) { 9276621Sbt150084 ixgbe_tx_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 9286621Sbt150084 ixgbe_buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 9296621Sbt150084 ixgbe_desc_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 9306621Sbt150084 } else { 9316621Sbt150084 ixgbe_tx_dma_attr.dma_attr_flags = 0; 9326621Sbt150084 ixgbe_buf_dma_attr.dma_attr_flags = 0; 9336621Sbt150084 ixgbe_desc_dma_attr.dma_attr_flags = 0; 9346621Sbt150084 } 9356621Sbt150084 } 936