19da57d7bSbt150084 /* 29da57d7bSbt150084 * CDDL HEADER START 39da57d7bSbt150084 * 473cd555cSBin Tu - Sun Microsystems - Beijing China * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. 59da57d7bSbt150084 * The contents of this file are subject to the terms of the 69da57d7bSbt150084 * Common Development and Distribution License (the "License"). 79da57d7bSbt150084 * You may not use this file except in compliance with the License. 89da57d7bSbt150084 * 99da57d7bSbt150084 * You can obtain a copy of the license at: 109da57d7bSbt150084 * http://www.opensolaris.org/os/licensing. 119da57d7bSbt150084 * See the License for the specific language governing permissions 129da57d7bSbt150084 * and limitations under the License. 139da57d7bSbt150084 * 149da57d7bSbt150084 * When using or redistributing this file, you may do so under the 159da57d7bSbt150084 * License only. No other modification of this header is permitted. 169da57d7bSbt150084 * 179da57d7bSbt150084 * If applicable, add the following below this CDDL HEADER, with the 189da57d7bSbt150084 * fields enclosed by brackets "[]" replaced with your own identifying 199da57d7bSbt150084 * information: Portions Copyright [yyyy] [name of copyright owner] 209da57d7bSbt150084 * 219da57d7bSbt150084 * CDDL HEADER END 229da57d7bSbt150084 */ 239da57d7bSbt150084 249da57d7bSbt150084 /* 25*ffd8e883SWinson Wang - Sun Microsystems - Beijing China * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 2673cd555cSBin Tu - Sun Microsystems - Beijing China * Use is subject to license terms. 279da57d7bSbt150084 */ 289da57d7bSbt150084 299da57d7bSbt150084 #include "ixgbe_sw.h" 309da57d7bSbt150084 319da57d7bSbt150084 static int ixgbe_alloc_tbd_ring(ixgbe_tx_ring_t *); 329da57d7bSbt150084 static void ixgbe_free_tbd_ring(ixgbe_tx_ring_t *); 33ea65739eSchenlu chen - Sun Microsystems - Beijing China static int ixgbe_alloc_rbd_ring(ixgbe_rx_data_t *); 34ea65739eSchenlu chen - Sun Microsystems - Beijing China static void ixgbe_free_rbd_ring(ixgbe_rx_data_t *); 359da57d7bSbt150084 static int ixgbe_alloc_dma_buffer(ixgbe_t *, dma_buffer_t *, size_t); 369da57d7bSbt150084 static int ixgbe_alloc_tcb_lists(ixgbe_tx_ring_t *); 379da57d7bSbt150084 static void ixgbe_free_tcb_lists(ixgbe_tx_ring_t *); 38ea65739eSchenlu chen - Sun Microsystems - Beijing China static int ixgbe_alloc_rcb_lists(ixgbe_rx_data_t *); 39ea65739eSchenlu chen - Sun Microsystems - Beijing China static void ixgbe_free_rcb_lists(ixgbe_rx_data_t *); 409da57d7bSbt150084 419da57d7bSbt150084 #ifdef __sparc 429da57d7bSbt150084 #define IXGBE_DMA_ALIGNMENT 0x0000000000002000ull 439da57d7bSbt150084 #else 449da57d7bSbt150084 #define IXGBE_DMA_ALIGNMENT 0x0000000000001000ull 459da57d7bSbt150084 #endif 469da57d7bSbt150084 479da57d7bSbt150084 /* 489da57d7bSbt150084 * DMA attributes for tx/rx descriptors. 499da57d7bSbt150084 */ 509da57d7bSbt150084 static ddi_dma_attr_t ixgbe_desc_dma_attr = { 519da57d7bSbt150084 DMA_ATTR_V0, /* version number */ 529da57d7bSbt150084 0x0000000000000000ull, /* low address */ 539da57d7bSbt150084 0xFFFFFFFFFFFFFFFFull, /* high address */ 549da57d7bSbt150084 0x00000000FFFFFFFFull, /* dma counter max */ 559da57d7bSbt150084 IXGBE_DMA_ALIGNMENT, /* alignment */ 569da57d7bSbt150084 0x00000FFF, /* burst sizes */ 579da57d7bSbt150084 0x00000001, /* minimum transfer size */ 589da57d7bSbt150084 0x00000000FFFFFFFFull, /* maximum transfer size */ 599da57d7bSbt150084 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */ 609da57d7bSbt150084 1, /* scatter/gather list length */ 619da57d7bSbt150084 0x00000001, /* granularity */ 629da57d7bSbt150084 DDI_DMA_FLAGERR /* DMA flags */ 639da57d7bSbt150084 }; 649da57d7bSbt150084 659da57d7bSbt150084 /* 669da57d7bSbt150084 * DMA attributes for tx/rx buffers. 679da57d7bSbt150084 */ 689da57d7bSbt150084 static ddi_dma_attr_t ixgbe_buf_dma_attr = { 699da57d7bSbt150084 DMA_ATTR_V0, /* version number */ 709da57d7bSbt150084 0x0000000000000000ull, /* low address */ 719da57d7bSbt150084 0xFFFFFFFFFFFFFFFFull, /* high address */ 729da57d7bSbt150084 0x00000000FFFFFFFFull, /* dma counter max */ 739da57d7bSbt150084 IXGBE_DMA_ALIGNMENT, /* alignment */ 749da57d7bSbt150084 0x00000FFF, /* burst sizes */ 759da57d7bSbt150084 0x00000001, /* minimum transfer size */ 769da57d7bSbt150084 0x00000000FFFFFFFFull, /* maximum transfer size */ 779da57d7bSbt150084 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */ 789da57d7bSbt150084 1, /* scatter/gather list length */ 799da57d7bSbt150084 0x00000001, /* granularity */ 809da57d7bSbt150084 DDI_DMA_FLAGERR /* DMA flags */ 819da57d7bSbt150084 }; 829da57d7bSbt150084 839da57d7bSbt150084 /* 849da57d7bSbt150084 * DMA attributes for transmit. 859da57d7bSbt150084 */ 869da57d7bSbt150084 static ddi_dma_attr_t ixgbe_tx_dma_attr = { 879da57d7bSbt150084 DMA_ATTR_V0, /* version number */ 889da57d7bSbt150084 0x0000000000000000ull, /* low address */ 899da57d7bSbt150084 0xFFFFFFFFFFFFFFFFull, /* high address */ 909da57d7bSbt150084 0x00000000FFFFFFFFull, /* dma counter max */ 919da57d7bSbt150084 1, /* alignment */ 929da57d7bSbt150084 0x00000FFF, /* burst sizes */ 939da57d7bSbt150084 0x00000001, /* minimum transfer size */ 949da57d7bSbt150084 0x00000000FFFFFFFFull, /* maximum transfer size */ 959da57d7bSbt150084 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */ 969da57d7bSbt150084 MAX_COOKIE, /* scatter/gather list length */ 979da57d7bSbt150084 0x00000001, /* granularity */ 989da57d7bSbt150084 DDI_DMA_FLAGERR /* DMA flags */ 999da57d7bSbt150084 }; 1009da57d7bSbt150084 1019da57d7bSbt150084 /* 1029da57d7bSbt150084 * DMA access attributes for descriptors. 1039da57d7bSbt150084 */ 1049da57d7bSbt150084 static ddi_device_acc_attr_t ixgbe_desc_acc_attr = { 1059da57d7bSbt150084 DDI_DEVICE_ATTR_V0, 1069da57d7bSbt150084 DDI_STRUCTURE_LE_ACC, 107837c1ac4SStephen Hanson DDI_STRICTORDER_ACC 1089da57d7bSbt150084 }; 1099da57d7bSbt150084 1109da57d7bSbt150084 /* 1119da57d7bSbt150084 * DMA access attributes for buffers. 1129da57d7bSbt150084 */ 1139da57d7bSbt150084 static ddi_device_acc_attr_t ixgbe_buf_acc_attr = { 1149da57d7bSbt150084 DDI_DEVICE_ATTR_V0, 1159da57d7bSbt150084 DDI_NEVERSWAP_ACC, 1169da57d7bSbt150084 DDI_STRICTORDER_ACC 1179da57d7bSbt150084 }; 1189da57d7bSbt150084 1199da57d7bSbt150084 /* 1209da57d7bSbt150084 * ixgbe_alloc_dma - Allocate DMA resources for all rx/tx rings. 1219da57d7bSbt150084 */ 1229da57d7bSbt150084 int 1239da57d7bSbt150084 ixgbe_alloc_dma(ixgbe_t *ixgbe) 1249da57d7bSbt150084 { 1259da57d7bSbt150084 ixgbe_rx_ring_t *rx_ring; 126ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_rx_data_t *rx_data; 1279da57d7bSbt150084 ixgbe_tx_ring_t *tx_ring; 1289da57d7bSbt150084 int i; 1299da57d7bSbt150084 1309da57d7bSbt150084 for (i = 0; i < ixgbe->num_rx_rings; i++) { 1319da57d7bSbt150084 /* 1329da57d7bSbt150084 * Allocate receive desciptor ring and control block lists 1339da57d7bSbt150084 */ 1349da57d7bSbt150084 rx_ring = &ixgbe->rx_rings[i]; 135ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data = rx_ring->rx_data; 1369da57d7bSbt150084 137ea65739eSchenlu chen - Sun Microsystems - Beijing China if (ixgbe_alloc_rbd_ring(rx_data) != IXGBE_SUCCESS) 1389da57d7bSbt150084 goto alloc_dma_failure; 1399da57d7bSbt150084 140ea65739eSchenlu chen - Sun Microsystems - Beijing China if (ixgbe_alloc_rcb_lists(rx_data) != IXGBE_SUCCESS) 1419da57d7bSbt150084 goto alloc_dma_failure; 1429da57d7bSbt150084 } 1439da57d7bSbt150084 1449da57d7bSbt150084 for (i = 0; i < ixgbe->num_tx_rings; i++) { 1459da57d7bSbt150084 /* 1469da57d7bSbt150084 * Allocate transmit desciptor ring and control block lists 1479da57d7bSbt150084 */ 1489da57d7bSbt150084 tx_ring = &ixgbe->tx_rings[i]; 1499da57d7bSbt150084 1509da57d7bSbt150084 if (ixgbe_alloc_tbd_ring(tx_ring) != IXGBE_SUCCESS) 1519da57d7bSbt150084 goto alloc_dma_failure; 1529da57d7bSbt150084 1539da57d7bSbt150084 if (ixgbe_alloc_tcb_lists(tx_ring) != IXGBE_SUCCESS) 1549da57d7bSbt150084 goto alloc_dma_failure; 1559da57d7bSbt150084 } 1569da57d7bSbt150084 1579da57d7bSbt150084 return (IXGBE_SUCCESS); 1589da57d7bSbt150084 1599da57d7bSbt150084 alloc_dma_failure: 1609da57d7bSbt150084 ixgbe_free_dma(ixgbe); 1619da57d7bSbt150084 1629da57d7bSbt150084 return (IXGBE_FAILURE); 1639da57d7bSbt150084 } 1649da57d7bSbt150084 1659da57d7bSbt150084 /* 1669da57d7bSbt150084 * ixgbe_free_dma - Free all the DMA resources of all rx/tx rings. 1679da57d7bSbt150084 */ 1689da57d7bSbt150084 void 1699da57d7bSbt150084 ixgbe_free_dma(ixgbe_t *ixgbe) 1709da57d7bSbt150084 { 1719da57d7bSbt150084 ixgbe_rx_ring_t *rx_ring; 172ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_rx_data_t *rx_data; 1739da57d7bSbt150084 ixgbe_tx_ring_t *tx_ring; 1749da57d7bSbt150084 int i; 1759da57d7bSbt150084 1769da57d7bSbt150084 /* 1779da57d7bSbt150084 * Free DMA resources of rx rings 1789da57d7bSbt150084 */ 1799da57d7bSbt150084 for (i = 0; i < ixgbe->num_rx_rings; i++) { 1809da57d7bSbt150084 rx_ring = &ixgbe->rx_rings[i]; 181ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data = rx_ring->rx_data; 182ea65739eSchenlu chen - Sun Microsystems - Beijing China 183ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_free_rbd_ring(rx_data); 184ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_free_rcb_lists(rx_data); 1859da57d7bSbt150084 } 1869da57d7bSbt150084 1879da57d7bSbt150084 /* 1889da57d7bSbt150084 * Free DMA resources of tx rings 1899da57d7bSbt150084 */ 1909da57d7bSbt150084 for (i = 0; i < ixgbe->num_tx_rings; i++) { 1919da57d7bSbt150084 tx_ring = &ixgbe->tx_rings[i]; 1929da57d7bSbt150084 ixgbe_free_tbd_ring(tx_ring); 1939da57d7bSbt150084 ixgbe_free_tcb_lists(tx_ring); 1949da57d7bSbt150084 } 1959da57d7bSbt150084 } 1969da57d7bSbt150084 197ea65739eSchenlu chen - Sun Microsystems - Beijing China int 198ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_alloc_rx_ring_data(ixgbe_rx_ring_t *rx_ring) 199ea65739eSchenlu chen - Sun Microsystems - Beijing China { 200ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_rx_data_t *rx_data; 201ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_t *ixgbe = rx_ring->ixgbe; 202ea65739eSchenlu chen - Sun Microsystems - Beijing China uint32_t rcb_count; 203ea65739eSchenlu chen - Sun Microsystems - Beijing China 204ea65739eSchenlu chen - Sun Microsystems - Beijing China /* 205ea65739eSchenlu chen - Sun Microsystems - Beijing China * Allocate memory for software receive rings 206ea65739eSchenlu chen - Sun Microsystems - Beijing China */ 207ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data = kmem_zalloc(sizeof (ixgbe_rx_data_t), KM_NOSLEEP); 208ea65739eSchenlu chen - Sun Microsystems - Beijing China 209ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data == NULL) { 210ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_error(ixgbe, "Allocate software receive rings failed"); 211ea65739eSchenlu chen - Sun Microsystems - Beijing China return (IXGBE_FAILURE); 212ea65739eSchenlu chen - Sun Microsystems - Beijing China } 213ea65739eSchenlu chen - Sun Microsystems - Beijing China 214ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rx_ring = rx_ring; 215ea65739eSchenlu chen - Sun Microsystems - Beijing China mutex_init(&rx_data->recycle_lock, NULL, 216ea65739eSchenlu chen - Sun Microsystems - Beijing China MUTEX_DRIVER, DDI_INTR_PRI(ixgbe->intr_pri)); 217ea65739eSchenlu chen - Sun Microsystems - Beijing China 218ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->ring_size = ixgbe->rx_ring_size; 219ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->free_list_size = ixgbe->rx_ring_size; 220ea65739eSchenlu chen - Sun Microsystems - Beijing China 221ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rcb_head = 0; 222ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rcb_tail = 0; 223ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rcb_free = rx_data->free_list_size; 224ea65739eSchenlu chen - Sun Microsystems - Beijing China 225ea65739eSchenlu chen - Sun Microsystems - Beijing China /* 226ea65739eSchenlu chen - Sun Microsystems - Beijing China * Allocate memory for the work list. 227ea65739eSchenlu chen - Sun Microsystems - Beijing China */ 228ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->work_list = kmem_zalloc(sizeof (rx_control_block_t *) * 229ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->ring_size, KM_NOSLEEP); 230ea65739eSchenlu chen - Sun Microsystems - Beijing China 231ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data->work_list == NULL) { 232ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_error(ixgbe, 233ea65739eSchenlu chen - Sun Microsystems - Beijing China "Could not allocate memory for rx work list"); 234ea65739eSchenlu chen - Sun Microsystems - Beijing China goto alloc_rx_data_failure; 235ea65739eSchenlu chen - Sun Microsystems - Beijing China } 236ea65739eSchenlu chen - Sun Microsystems - Beijing China 237ea65739eSchenlu chen - Sun Microsystems - Beijing China /* 238ea65739eSchenlu chen - Sun Microsystems - Beijing China * Allocate memory for the free list. 239ea65739eSchenlu chen - Sun Microsystems - Beijing China */ 240ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->free_list = kmem_zalloc(sizeof (rx_control_block_t *) * 241ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->free_list_size, KM_NOSLEEP); 242ea65739eSchenlu chen - Sun Microsystems - Beijing China 243ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data->free_list == NULL) { 244ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_error(ixgbe, 245ea65739eSchenlu chen - Sun Microsystems - Beijing China "Cound not allocate memory for rx free list"); 246ea65739eSchenlu chen - Sun Microsystems - Beijing China goto alloc_rx_data_failure; 247ea65739eSchenlu chen - Sun Microsystems - Beijing China } 248ea65739eSchenlu chen - Sun Microsystems - Beijing China 249ea65739eSchenlu chen - Sun Microsystems - Beijing China /* 250ea65739eSchenlu chen - Sun Microsystems - Beijing China * Allocate memory for the rx control blocks for work list and 251ea65739eSchenlu chen - Sun Microsystems - Beijing China * free list. 252ea65739eSchenlu chen - Sun Microsystems - Beijing China */ 253ea65739eSchenlu chen - Sun Microsystems - Beijing China rcb_count = rx_data->ring_size + rx_data->free_list_size; 254ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rcb_area = 255ea65739eSchenlu chen - Sun Microsystems - Beijing China kmem_zalloc(sizeof (rx_control_block_t) * rcb_count, 256ea65739eSchenlu chen - Sun Microsystems - Beijing China KM_NOSLEEP); 257ea65739eSchenlu chen - Sun Microsystems - Beijing China 258ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data->rcb_area == NULL) { 259ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_error(ixgbe, 260ea65739eSchenlu chen - Sun Microsystems - Beijing China "Cound not allocate memory for rx control blocks"); 261ea65739eSchenlu chen - Sun Microsystems - Beijing China goto alloc_rx_data_failure; 262ea65739eSchenlu chen - Sun Microsystems - Beijing China } 263ea65739eSchenlu chen - Sun Microsystems - Beijing China 264ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_ring->rx_data = rx_data; 265ea65739eSchenlu chen - Sun Microsystems - Beijing China return (IXGBE_SUCCESS); 266ea65739eSchenlu chen - Sun Microsystems - Beijing China 267ea65739eSchenlu chen - Sun Microsystems - Beijing China alloc_rx_data_failure: 268ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_free_rx_ring_data(rx_data); 269ea65739eSchenlu chen - Sun Microsystems - Beijing China return (IXGBE_FAILURE); 270ea65739eSchenlu chen - Sun Microsystems - Beijing China } 271ea65739eSchenlu chen - Sun Microsystems - Beijing China 272ea65739eSchenlu chen - Sun Microsystems - Beijing China void 273ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_free_rx_ring_data(ixgbe_rx_data_t *rx_data) 274ea65739eSchenlu chen - Sun Microsystems - Beijing China { 275ea65739eSchenlu chen - Sun Microsystems - Beijing China uint32_t rcb_count; 276ea65739eSchenlu chen - Sun Microsystems - Beijing China 277ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data == NULL) 278ea65739eSchenlu chen - Sun Microsystems - Beijing China return; 279ea65739eSchenlu chen - Sun Microsystems - Beijing China 280ea65739eSchenlu chen - Sun Microsystems - Beijing China ASSERT(rx_data->rcb_pending == 0); 281ea65739eSchenlu chen - Sun Microsystems - Beijing China 282ea65739eSchenlu chen - Sun Microsystems - Beijing China rcb_count = rx_data->ring_size + rx_data->free_list_size; 283ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data->rcb_area != NULL) { 284ea65739eSchenlu chen - Sun Microsystems - Beijing China kmem_free(rx_data->rcb_area, 285ea65739eSchenlu chen - Sun Microsystems - Beijing China sizeof (rx_control_block_t) * rcb_count); 286ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rcb_area = NULL; 287ea65739eSchenlu chen - Sun Microsystems - Beijing China } 288ea65739eSchenlu chen - Sun Microsystems - Beijing China 289ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data->work_list != NULL) { 290ea65739eSchenlu chen - Sun Microsystems - Beijing China kmem_free(rx_data->work_list, 291ea65739eSchenlu chen - Sun Microsystems - Beijing China sizeof (rx_control_block_t *) * rx_data->ring_size); 292ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->work_list = NULL; 293ea65739eSchenlu chen - Sun Microsystems - Beijing China } 294ea65739eSchenlu chen - Sun Microsystems - Beijing China 295ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data->free_list != NULL) { 296ea65739eSchenlu chen - Sun Microsystems - Beijing China kmem_free(rx_data->free_list, 297ea65739eSchenlu chen - Sun Microsystems - Beijing China sizeof (rx_control_block_t *) * rx_data->free_list_size); 298ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->free_list = NULL; 299ea65739eSchenlu chen - Sun Microsystems - Beijing China } 300ea65739eSchenlu chen - Sun Microsystems - Beijing China 301ea65739eSchenlu chen - Sun Microsystems - Beijing China mutex_destroy(&rx_data->recycle_lock); 302ea65739eSchenlu chen - Sun Microsystems - Beijing China kmem_free(rx_data, sizeof (ixgbe_rx_data_t)); 303ea65739eSchenlu chen - Sun Microsystems - Beijing China } 304ea65739eSchenlu chen - Sun Microsystems - Beijing China 3059da57d7bSbt150084 /* 3069da57d7bSbt150084 * ixgbe_alloc_tbd_ring - Memory allocation for the tx descriptors of one ring. 3079da57d7bSbt150084 */ 3089da57d7bSbt150084 static int 3099da57d7bSbt150084 ixgbe_alloc_tbd_ring(ixgbe_tx_ring_t *tx_ring) 3109da57d7bSbt150084 { 3119da57d7bSbt150084 int ret; 3129da57d7bSbt150084 size_t size; 3139da57d7bSbt150084 size_t len; 3149da57d7bSbt150084 uint_t cookie_num; 3159da57d7bSbt150084 dev_info_t *devinfo; 3169da57d7bSbt150084 ddi_dma_cookie_t cookie; 3179da57d7bSbt150084 ixgbe_t *ixgbe = tx_ring->ixgbe; 3189da57d7bSbt150084 3199da57d7bSbt150084 devinfo = ixgbe->dip; 3209da57d7bSbt150084 size = sizeof (union ixgbe_adv_tx_desc) * tx_ring->ring_size; 3219da57d7bSbt150084 3229da57d7bSbt150084 /* 3239da57d7bSbt150084 * If tx head write-back is enabled, an extra tbd is allocated 3249da57d7bSbt150084 * to save the head write-back value 3259da57d7bSbt150084 */ 3269da57d7bSbt150084 if (ixgbe->tx_head_wb_enable) { 3279da57d7bSbt150084 size += sizeof (union ixgbe_adv_tx_desc); 3289da57d7bSbt150084 } 3299da57d7bSbt150084 3309da57d7bSbt150084 /* 3319da57d7bSbt150084 * Allocate a DMA handle for the transmit descriptor 3329da57d7bSbt150084 * memory area. 3339da57d7bSbt150084 */ 3349da57d7bSbt150084 ret = ddi_dma_alloc_handle(devinfo, &ixgbe_desc_dma_attr, 3359da57d7bSbt150084 DDI_DMA_DONTWAIT, NULL, 3369da57d7bSbt150084 &tx_ring->tbd_area.dma_handle); 3379da57d7bSbt150084 3389da57d7bSbt150084 if (ret != DDI_SUCCESS) { 3399da57d7bSbt150084 ixgbe_error(ixgbe, 3409da57d7bSbt150084 "Could not allocate tbd dma handle: %x", ret); 3419da57d7bSbt150084 tx_ring->tbd_area.dma_handle = NULL; 3429da57d7bSbt150084 3439da57d7bSbt150084 return (IXGBE_FAILURE); 3449da57d7bSbt150084 } 3459da57d7bSbt150084 3469da57d7bSbt150084 /* 3479da57d7bSbt150084 * Allocate memory to DMA data to and from the transmit 3489da57d7bSbt150084 * descriptors. 3499da57d7bSbt150084 */ 3509da57d7bSbt150084 ret = ddi_dma_mem_alloc(tx_ring->tbd_area.dma_handle, 3519da57d7bSbt150084 size, &ixgbe_desc_acc_attr, DDI_DMA_CONSISTENT, 3529da57d7bSbt150084 DDI_DMA_DONTWAIT, NULL, 3539da57d7bSbt150084 (caddr_t *)&tx_ring->tbd_area.address, 3549da57d7bSbt150084 &len, &tx_ring->tbd_area.acc_handle); 3559da57d7bSbt150084 3569da57d7bSbt150084 if (ret != DDI_SUCCESS) { 3579da57d7bSbt150084 ixgbe_error(ixgbe, 3589da57d7bSbt150084 "Could not allocate tbd dma memory: %x", ret); 3599da57d7bSbt150084 tx_ring->tbd_area.acc_handle = NULL; 3609da57d7bSbt150084 tx_ring->tbd_area.address = NULL; 3619da57d7bSbt150084 if (tx_ring->tbd_area.dma_handle != NULL) { 3629da57d7bSbt150084 ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle); 3639da57d7bSbt150084 tx_ring->tbd_area.dma_handle = NULL; 3649da57d7bSbt150084 } 3659da57d7bSbt150084 return (IXGBE_FAILURE); 3669da57d7bSbt150084 } 3679da57d7bSbt150084 3689da57d7bSbt150084 /* 3699da57d7bSbt150084 * Initialize the entire transmit buffer descriptor area to zero 3709da57d7bSbt150084 */ 3719da57d7bSbt150084 bzero(tx_ring->tbd_area.address, len); 3729da57d7bSbt150084 3739da57d7bSbt150084 /* 3749da57d7bSbt150084 * Allocates DMA resources for the memory that was allocated by 3759da57d7bSbt150084 * the ddi_dma_mem_alloc call. The DMA resources then get bound to the 3769da57d7bSbt150084 * the memory address 3779da57d7bSbt150084 */ 3789da57d7bSbt150084 ret = ddi_dma_addr_bind_handle(tx_ring->tbd_area.dma_handle, 3799da57d7bSbt150084 NULL, (caddr_t)tx_ring->tbd_area.address, 3809da57d7bSbt150084 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 3819da57d7bSbt150084 DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num); 3829da57d7bSbt150084 3839da57d7bSbt150084 if (ret != DDI_DMA_MAPPED) { 3849da57d7bSbt150084 ixgbe_error(ixgbe, 3859da57d7bSbt150084 "Could not bind tbd dma resource: %x", ret); 3869da57d7bSbt150084 tx_ring->tbd_area.dma_address = NULL; 3879da57d7bSbt150084 if (tx_ring->tbd_area.acc_handle != NULL) { 3889da57d7bSbt150084 ddi_dma_mem_free(&tx_ring->tbd_area.acc_handle); 3899da57d7bSbt150084 tx_ring->tbd_area.acc_handle = NULL; 3909da57d7bSbt150084 tx_ring->tbd_area.address = NULL; 3919da57d7bSbt150084 } 3929da57d7bSbt150084 if (tx_ring->tbd_area.dma_handle != NULL) { 3939da57d7bSbt150084 ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle); 3949da57d7bSbt150084 tx_ring->tbd_area.dma_handle = NULL; 3959da57d7bSbt150084 } 3969da57d7bSbt150084 return (IXGBE_FAILURE); 3979da57d7bSbt150084 } 3989da57d7bSbt150084 3999da57d7bSbt150084 ASSERT(cookie_num == 1); 4009da57d7bSbt150084 4019da57d7bSbt150084 tx_ring->tbd_area.dma_address = cookie.dmac_laddress; 4029da57d7bSbt150084 tx_ring->tbd_area.size = len; 4039da57d7bSbt150084 4049da57d7bSbt150084 tx_ring->tbd_ring = (union ixgbe_adv_tx_desc *)(uintptr_t) 4059da57d7bSbt150084 tx_ring->tbd_area.address; 4069da57d7bSbt150084 4079da57d7bSbt150084 return (IXGBE_SUCCESS); 4089da57d7bSbt150084 } 4099da57d7bSbt150084 4109da57d7bSbt150084 /* 4119da57d7bSbt150084 * ixgbe_free_tbd_ring - Free the tx descriptors of one ring. 4129da57d7bSbt150084 */ 4139da57d7bSbt150084 static void 4149da57d7bSbt150084 ixgbe_free_tbd_ring(ixgbe_tx_ring_t *tx_ring) 4159da57d7bSbt150084 { 4169da57d7bSbt150084 if (tx_ring->tbd_area.dma_handle != NULL) { 4179da57d7bSbt150084 (void) ddi_dma_unbind_handle(tx_ring->tbd_area.dma_handle); 4189da57d7bSbt150084 } 4199da57d7bSbt150084 if (tx_ring->tbd_area.acc_handle != NULL) { 4209da57d7bSbt150084 ddi_dma_mem_free(&tx_ring->tbd_area.acc_handle); 4219da57d7bSbt150084 tx_ring->tbd_area.acc_handle = NULL; 4229da57d7bSbt150084 } 4239da57d7bSbt150084 if (tx_ring->tbd_area.dma_handle != NULL) { 4249da57d7bSbt150084 ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle); 4259da57d7bSbt150084 tx_ring->tbd_area.dma_handle = NULL; 4269da57d7bSbt150084 } 4279da57d7bSbt150084 tx_ring->tbd_area.address = NULL; 4289da57d7bSbt150084 tx_ring->tbd_area.dma_address = NULL; 4299da57d7bSbt150084 tx_ring->tbd_area.size = 0; 4309da57d7bSbt150084 4319da57d7bSbt150084 tx_ring->tbd_ring = NULL; 4329da57d7bSbt150084 } 4339da57d7bSbt150084 4349da57d7bSbt150084 /* 4359da57d7bSbt150084 * ixgbe_alloc_rbd_ring - Memory allocation for the rx descriptors of one ring. 4369da57d7bSbt150084 */ 4379da57d7bSbt150084 static int 438ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_alloc_rbd_ring(ixgbe_rx_data_t *rx_data) 4399da57d7bSbt150084 { 4409da57d7bSbt150084 int ret; 4419da57d7bSbt150084 size_t size; 4429da57d7bSbt150084 size_t len; 4439da57d7bSbt150084 uint_t cookie_num; 4449da57d7bSbt150084 dev_info_t *devinfo; 4459da57d7bSbt150084 ddi_dma_cookie_t cookie; 446ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_t *ixgbe = rx_data->rx_ring->ixgbe; 4479da57d7bSbt150084 4489da57d7bSbt150084 devinfo = ixgbe->dip; 449ea65739eSchenlu chen - Sun Microsystems - Beijing China size = sizeof (union ixgbe_adv_rx_desc) * rx_data->ring_size; 4509da57d7bSbt150084 4519da57d7bSbt150084 /* 4529da57d7bSbt150084 * Allocate a new DMA handle for the receive descriptor 4539da57d7bSbt150084 * memory area. 4549da57d7bSbt150084 */ 4559da57d7bSbt150084 ret = ddi_dma_alloc_handle(devinfo, &ixgbe_desc_dma_attr, 4569da57d7bSbt150084 DDI_DMA_DONTWAIT, NULL, 457ea65739eSchenlu chen - Sun Microsystems - Beijing China &rx_data->rbd_area.dma_handle); 4589da57d7bSbt150084 4599da57d7bSbt150084 if (ret != DDI_SUCCESS) { 4609da57d7bSbt150084 ixgbe_error(ixgbe, 4619da57d7bSbt150084 "Could not allocate rbd dma handle: %x", ret); 462ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_handle = NULL; 4639da57d7bSbt150084 return (IXGBE_FAILURE); 4649da57d7bSbt150084 } 4659da57d7bSbt150084 4669da57d7bSbt150084 /* 4679da57d7bSbt150084 * Allocate memory to DMA data to and from the receive 4689da57d7bSbt150084 * descriptors. 4699da57d7bSbt150084 */ 470ea65739eSchenlu chen - Sun Microsystems - Beijing China ret = ddi_dma_mem_alloc(rx_data->rbd_area.dma_handle, 4719da57d7bSbt150084 size, &ixgbe_desc_acc_attr, DDI_DMA_CONSISTENT, 4729da57d7bSbt150084 DDI_DMA_DONTWAIT, NULL, 473ea65739eSchenlu chen - Sun Microsystems - Beijing China (caddr_t *)&rx_data->rbd_area.address, 474ea65739eSchenlu chen - Sun Microsystems - Beijing China &len, &rx_data->rbd_area.acc_handle); 4759da57d7bSbt150084 4769da57d7bSbt150084 if (ret != DDI_SUCCESS) { 4779da57d7bSbt150084 ixgbe_error(ixgbe, 4789da57d7bSbt150084 "Could not allocate rbd dma memory: %x", ret); 479ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.acc_handle = NULL; 480ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.address = NULL; 481ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data->rbd_area.dma_handle != NULL) { 482ea65739eSchenlu chen - Sun Microsystems - Beijing China ddi_dma_free_handle(&rx_data->rbd_area.dma_handle); 483ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_handle = NULL; 4849da57d7bSbt150084 } 4859da57d7bSbt150084 return (IXGBE_FAILURE); 4869da57d7bSbt150084 } 4879da57d7bSbt150084 4889da57d7bSbt150084 /* 4899da57d7bSbt150084 * Initialize the entire transmit buffer descriptor area to zero 4909da57d7bSbt150084 */ 491ea65739eSchenlu chen - Sun Microsystems - Beijing China bzero(rx_data->rbd_area.address, len); 4929da57d7bSbt150084 4939da57d7bSbt150084 /* 4949da57d7bSbt150084 * Allocates DMA resources for the memory that was allocated by 4959da57d7bSbt150084 * the ddi_dma_mem_alloc call. 4969da57d7bSbt150084 */ 497ea65739eSchenlu chen - Sun Microsystems - Beijing China ret = ddi_dma_addr_bind_handle(rx_data->rbd_area.dma_handle, 498ea65739eSchenlu chen - Sun Microsystems - Beijing China NULL, (caddr_t)rx_data->rbd_area.address, 4999da57d7bSbt150084 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 5009da57d7bSbt150084 DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num); 5019da57d7bSbt150084 5029da57d7bSbt150084 if (ret != DDI_DMA_MAPPED) { 5039da57d7bSbt150084 ixgbe_error(ixgbe, 5049da57d7bSbt150084 "Could not bind rbd dma resource: %x", ret); 505ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_address = NULL; 506ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data->rbd_area.acc_handle != NULL) { 507ea65739eSchenlu chen - Sun Microsystems - Beijing China ddi_dma_mem_free(&rx_data->rbd_area.acc_handle); 508ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.acc_handle = NULL; 509ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.address = NULL; 5109da57d7bSbt150084 } 511ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data->rbd_area.dma_handle != NULL) { 512ea65739eSchenlu chen - Sun Microsystems - Beijing China ddi_dma_free_handle(&rx_data->rbd_area.dma_handle); 513ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_handle = NULL; 5149da57d7bSbt150084 } 5159da57d7bSbt150084 return (IXGBE_FAILURE); 5169da57d7bSbt150084 } 5179da57d7bSbt150084 5189da57d7bSbt150084 ASSERT(cookie_num == 1); 5199da57d7bSbt150084 520ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_address = cookie.dmac_laddress; 521ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.size = len; 5229da57d7bSbt150084 523ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_ring = (union ixgbe_adv_rx_desc *)(uintptr_t) 524ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.address; 5259da57d7bSbt150084 5269da57d7bSbt150084 return (IXGBE_SUCCESS); 5279da57d7bSbt150084 } 5289da57d7bSbt150084 5299da57d7bSbt150084 /* 5309da57d7bSbt150084 * ixgbe_free_rbd_ring - Free the rx descriptors of one ring. 5319da57d7bSbt150084 */ 5329da57d7bSbt150084 static void 533ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_free_rbd_ring(ixgbe_rx_data_t *rx_data) 5349da57d7bSbt150084 { 535ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data->rbd_area.dma_handle != NULL) { 536ea65739eSchenlu chen - Sun Microsystems - Beijing China (void) ddi_dma_unbind_handle(rx_data->rbd_area.dma_handle); 5379da57d7bSbt150084 } 538ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data->rbd_area.acc_handle != NULL) { 539ea65739eSchenlu chen - Sun Microsystems - Beijing China ddi_dma_mem_free(&rx_data->rbd_area.acc_handle); 540ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.acc_handle = NULL; 5419da57d7bSbt150084 } 542ea65739eSchenlu chen - Sun Microsystems - Beijing China if (rx_data->rbd_area.dma_handle != NULL) { 543ea65739eSchenlu chen - Sun Microsystems - Beijing China ddi_dma_free_handle(&rx_data->rbd_area.dma_handle); 544ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_handle = NULL; 5459da57d7bSbt150084 } 546ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.address = NULL; 547ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_address = NULL; 548ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.size = 0; 5499da57d7bSbt150084 550ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->rbd_ring = NULL; 5519da57d7bSbt150084 } 5529da57d7bSbt150084 5539da57d7bSbt150084 /* 5549da57d7bSbt150084 * ixgbe_alloc_dma_buffer - Allocate DMA resources for a DMA buffer. 5559da57d7bSbt150084 */ 5569da57d7bSbt150084 static int 5579da57d7bSbt150084 ixgbe_alloc_dma_buffer(ixgbe_t *ixgbe, dma_buffer_t *buf, size_t size) 5589da57d7bSbt150084 { 5599da57d7bSbt150084 int ret; 5609da57d7bSbt150084 dev_info_t *devinfo = ixgbe->dip; 5619da57d7bSbt150084 ddi_dma_cookie_t cookie; 5629da57d7bSbt150084 size_t len; 5639da57d7bSbt150084 uint_t cookie_num; 5649da57d7bSbt150084 5659da57d7bSbt150084 ret = ddi_dma_alloc_handle(devinfo, 5669da57d7bSbt150084 &ixgbe_buf_dma_attr, DDI_DMA_DONTWAIT, 5679da57d7bSbt150084 NULL, &buf->dma_handle); 5689da57d7bSbt150084 5699da57d7bSbt150084 if (ret != DDI_SUCCESS) { 5709da57d7bSbt150084 buf->dma_handle = NULL; 5719da57d7bSbt150084 ixgbe_error(ixgbe, 5729da57d7bSbt150084 "Could not allocate dma buffer handle: %x", ret); 5739da57d7bSbt150084 return (IXGBE_FAILURE); 5749da57d7bSbt150084 } 5759da57d7bSbt150084 5769da57d7bSbt150084 ret = ddi_dma_mem_alloc(buf->dma_handle, 5779da57d7bSbt150084 size, &ixgbe_buf_acc_attr, DDI_DMA_STREAMING, 5789da57d7bSbt150084 DDI_DMA_DONTWAIT, NULL, &buf->address, 5799da57d7bSbt150084 &len, &buf->acc_handle); 5809da57d7bSbt150084 5819da57d7bSbt150084 if (ret != DDI_SUCCESS) { 5829da57d7bSbt150084 buf->acc_handle = NULL; 5839da57d7bSbt150084 buf->address = NULL; 5849da57d7bSbt150084 if (buf->dma_handle != NULL) { 5859da57d7bSbt150084 ddi_dma_free_handle(&buf->dma_handle); 5869da57d7bSbt150084 buf->dma_handle = NULL; 5879da57d7bSbt150084 } 5889da57d7bSbt150084 ixgbe_error(ixgbe, 5899da57d7bSbt150084 "Could not allocate dma buffer memory: %x", ret); 5909da57d7bSbt150084 return (IXGBE_FAILURE); 5919da57d7bSbt150084 } 5929da57d7bSbt150084 5939da57d7bSbt150084 ret = ddi_dma_addr_bind_handle(buf->dma_handle, NULL, 5949da57d7bSbt150084 buf->address, 5959da57d7bSbt150084 len, DDI_DMA_RDWR | DDI_DMA_STREAMING, 5969da57d7bSbt150084 DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num); 5979da57d7bSbt150084 5989da57d7bSbt150084 if (ret != DDI_DMA_MAPPED) { 5999da57d7bSbt150084 buf->dma_address = NULL; 6009da57d7bSbt150084 if (buf->acc_handle != NULL) { 6019da57d7bSbt150084 ddi_dma_mem_free(&buf->acc_handle); 6029da57d7bSbt150084 buf->acc_handle = NULL; 6039da57d7bSbt150084 buf->address = NULL; 6049da57d7bSbt150084 } 6059da57d7bSbt150084 if (buf->dma_handle != NULL) { 6069da57d7bSbt150084 ddi_dma_free_handle(&buf->dma_handle); 6079da57d7bSbt150084 buf->dma_handle = NULL; 6089da57d7bSbt150084 } 6099da57d7bSbt150084 ixgbe_error(ixgbe, 6109da57d7bSbt150084 "Could not bind dma buffer handle: %x", ret); 6119da57d7bSbt150084 return (IXGBE_FAILURE); 6129da57d7bSbt150084 } 6139da57d7bSbt150084 6149da57d7bSbt150084 ASSERT(cookie_num == 1); 6159da57d7bSbt150084 6169da57d7bSbt150084 buf->dma_address = cookie.dmac_laddress; 6179da57d7bSbt150084 buf->size = len; 6189da57d7bSbt150084 buf->len = 0; 6199da57d7bSbt150084 6209da57d7bSbt150084 return (IXGBE_SUCCESS); 6219da57d7bSbt150084 } 6229da57d7bSbt150084 6239da57d7bSbt150084 /* 6249da57d7bSbt150084 * ixgbe_free_dma_buffer - Free one allocated area of dma memory and handle. 6259da57d7bSbt150084 */ 626ea65739eSchenlu chen - Sun Microsystems - Beijing China void 6279da57d7bSbt150084 ixgbe_free_dma_buffer(dma_buffer_t *buf) 6289da57d7bSbt150084 { 6299da57d7bSbt150084 if (buf->dma_handle != NULL) { 6309da57d7bSbt150084 (void) ddi_dma_unbind_handle(buf->dma_handle); 6319da57d7bSbt150084 buf->dma_address = NULL; 6329da57d7bSbt150084 } else { 6339da57d7bSbt150084 return; 6349da57d7bSbt150084 } 6359da57d7bSbt150084 6369da57d7bSbt150084 if (buf->acc_handle != NULL) { 6379da57d7bSbt150084 ddi_dma_mem_free(&buf->acc_handle); 6389da57d7bSbt150084 buf->acc_handle = NULL; 6399da57d7bSbt150084 buf->address = NULL; 6409da57d7bSbt150084 } 6419da57d7bSbt150084 6429da57d7bSbt150084 if (buf->dma_handle != NULL) { 6439da57d7bSbt150084 ddi_dma_free_handle(&buf->dma_handle); 6449da57d7bSbt150084 buf->dma_handle = NULL; 6459da57d7bSbt150084 } 6469da57d7bSbt150084 6479da57d7bSbt150084 buf->size = 0; 6489da57d7bSbt150084 buf->len = 0; 6499da57d7bSbt150084 } 6509da57d7bSbt150084 6519da57d7bSbt150084 /* 6529da57d7bSbt150084 * ixgbe_alloc_tcb_lists - Memory allocation for the transmit control bolcks 6539da57d7bSbt150084 * of one ring. 6549da57d7bSbt150084 */ 6559da57d7bSbt150084 static int 6569da57d7bSbt150084 ixgbe_alloc_tcb_lists(ixgbe_tx_ring_t *tx_ring) 6579da57d7bSbt150084 { 6589da57d7bSbt150084 int i; 6599da57d7bSbt150084 int ret; 6609da57d7bSbt150084 tx_control_block_t *tcb; 6619da57d7bSbt150084 dma_buffer_t *tx_buf; 6629da57d7bSbt150084 ixgbe_t *ixgbe = tx_ring->ixgbe; 6639da57d7bSbt150084 dev_info_t *devinfo = ixgbe->dip; 6649da57d7bSbt150084 6659da57d7bSbt150084 /* 6669da57d7bSbt150084 * Allocate memory for the work list. 6679da57d7bSbt150084 */ 6689da57d7bSbt150084 tx_ring->work_list = kmem_zalloc(sizeof (tx_control_block_t *) * 6699da57d7bSbt150084 tx_ring->ring_size, KM_NOSLEEP); 6709da57d7bSbt150084 6719da57d7bSbt150084 if (tx_ring->work_list == NULL) { 6729da57d7bSbt150084 ixgbe_error(ixgbe, 6739da57d7bSbt150084 "Cound not allocate memory for tx work list"); 6749da57d7bSbt150084 return (IXGBE_FAILURE); 6759da57d7bSbt150084 } 6769da57d7bSbt150084 6779da57d7bSbt150084 /* 6789da57d7bSbt150084 * Allocate memory for the free list. 6799da57d7bSbt150084 */ 6809da57d7bSbt150084 tx_ring->free_list = kmem_zalloc(sizeof (tx_control_block_t *) * 6819da57d7bSbt150084 tx_ring->free_list_size, KM_NOSLEEP); 6829da57d7bSbt150084 6839da57d7bSbt150084 if (tx_ring->free_list == NULL) { 6849da57d7bSbt150084 kmem_free(tx_ring->work_list, 6859da57d7bSbt150084 sizeof (tx_control_block_t *) * tx_ring->ring_size); 6869da57d7bSbt150084 tx_ring->work_list = NULL; 6879da57d7bSbt150084 6889da57d7bSbt150084 ixgbe_error(ixgbe, 6899da57d7bSbt150084 "Cound not allocate memory for tx free list"); 6909da57d7bSbt150084 return (IXGBE_FAILURE); 6919da57d7bSbt150084 } 6929da57d7bSbt150084 6939da57d7bSbt150084 /* 6949da57d7bSbt150084 * Allocate memory for the tx control blocks of free list. 6959da57d7bSbt150084 */ 6969da57d7bSbt150084 tx_ring->tcb_area = 6979da57d7bSbt150084 kmem_zalloc(sizeof (tx_control_block_t) * 6989da57d7bSbt150084 tx_ring->free_list_size, KM_NOSLEEP); 6999da57d7bSbt150084 7009da57d7bSbt150084 if (tx_ring->tcb_area == NULL) { 7019da57d7bSbt150084 kmem_free(tx_ring->work_list, 7029da57d7bSbt150084 sizeof (tx_control_block_t *) * tx_ring->ring_size); 7039da57d7bSbt150084 tx_ring->work_list = NULL; 7049da57d7bSbt150084 7059da57d7bSbt150084 kmem_free(tx_ring->free_list, 7069da57d7bSbt150084 sizeof (tx_control_block_t *) * tx_ring->free_list_size); 7079da57d7bSbt150084 tx_ring->free_list = NULL; 7089da57d7bSbt150084 7099da57d7bSbt150084 ixgbe_error(ixgbe, 7109da57d7bSbt150084 "Cound not allocate memory for tx control blocks"); 7119da57d7bSbt150084 return (IXGBE_FAILURE); 7129da57d7bSbt150084 } 7139da57d7bSbt150084 7149da57d7bSbt150084 /* 7159da57d7bSbt150084 * Allocate dma memory for the tx control block of free list. 7169da57d7bSbt150084 */ 7179da57d7bSbt150084 tcb = tx_ring->tcb_area; 7189da57d7bSbt150084 for (i = 0; i < tx_ring->free_list_size; i++, tcb++) { 7199da57d7bSbt150084 ASSERT(tcb != NULL); 7209da57d7bSbt150084 7219da57d7bSbt150084 tx_ring->free_list[i] = tcb; 7229da57d7bSbt150084 7239da57d7bSbt150084 /* 7249da57d7bSbt150084 * Pre-allocate dma handles for transmit. These dma handles 7259da57d7bSbt150084 * will be dynamically bound to the data buffers passed down 7269da57d7bSbt150084 * from the upper layers at the time of transmitting. 7279da57d7bSbt150084 */ 7289da57d7bSbt150084 ret = ddi_dma_alloc_handle(devinfo, 7299da57d7bSbt150084 &ixgbe_tx_dma_attr, 7309da57d7bSbt150084 DDI_DMA_DONTWAIT, NULL, 7319da57d7bSbt150084 &tcb->tx_dma_handle); 7329da57d7bSbt150084 if (ret != DDI_SUCCESS) { 7339da57d7bSbt150084 tcb->tx_dma_handle = NULL; 7349da57d7bSbt150084 ixgbe_error(ixgbe, 7359da57d7bSbt150084 "Could not allocate tx dma handle: %x", ret); 7369da57d7bSbt150084 goto alloc_tcb_lists_fail; 7379da57d7bSbt150084 } 7389da57d7bSbt150084 7399da57d7bSbt150084 /* 7409da57d7bSbt150084 * Pre-allocate transmit buffers for packets that the 7419da57d7bSbt150084 * size is less than bcopy_thresh. 7429da57d7bSbt150084 */ 7439da57d7bSbt150084 tx_buf = &tcb->tx_buf; 7449da57d7bSbt150084 7459da57d7bSbt150084 ret = ixgbe_alloc_dma_buffer(ixgbe, 7469da57d7bSbt150084 tx_buf, ixgbe->tx_buf_size); 7479da57d7bSbt150084 7489da57d7bSbt150084 if (ret != IXGBE_SUCCESS) { 7499da57d7bSbt150084 ASSERT(tcb->tx_dma_handle != NULL); 7509da57d7bSbt150084 ddi_dma_free_handle(&tcb->tx_dma_handle); 7519da57d7bSbt150084 tcb->tx_dma_handle = NULL; 7529da57d7bSbt150084 ixgbe_error(ixgbe, "Allocate tx dma buffer failed"); 7539da57d7bSbt150084 goto alloc_tcb_lists_fail; 7549da57d7bSbt150084 } 755edf70dc9SPaul Guo 756edf70dc9SPaul Guo tcb->last_index = MAX_TX_RING_SIZE; 7579da57d7bSbt150084 } 7589da57d7bSbt150084 7599da57d7bSbt150084 return (IXGBE_SUCCESS); 7609da57d7bSbt150084 7619da57d7bSbt150084 alloc_tcb_lists_fail: 7629da57d7bSbt150084 ixgbe_free_tcb_lists(tx_ring); 7639da57d7bSbt150084 7649da57d7bSbt150084 return (IXGBE_FAILURE); 7659da57d7bSbt150084 } 7669da57d7bSbt150084 7679da57d7bSbt150084 /* 7689da57d7bSbt150084 * ixgbe_free_tcb_lists - Release the memory allocated for 7699da57d7bSbt150084 * the transmit control bolcks of one ring. 7709da57d7bSbt150084 */ 7719da57d7bSbt150084 static void 7729da57d7bSbt150084 ixgbe_free_tcb_lists(ixgbe_tx_ring_t *tx_ring) 7739da57d7bSbt150084 { 7749da57d7bSbt150084 int i; 7759da57d7bSbt150084 tx_control_block_t *tcb; 7769da57d7bSbt150084 7779da57d7bSbt150084 tcb = tx_ring->tcb_area; 7789da57d7bSbt150084 if (tcb == NULL) 7799da57d7bSbt150084 return; 7809da57d7bSbt150084 7819da57d7bSbt150084 for (i = 0; i < tx_ring->free_list_size; i++, tcb++) { 7829da57d7bSbt150084 ASSERT(tcb != NULL); 7839da57d7bSbt150084 7849da57d7bSbt150084 /* Free the tx dma handle for dynamical binding */ 7859da57d7bSbt150084 if (tcb->tx_dma_handle != NULL) { 7869da57d7bSbt150084 ddi_dma_free_handle(&tcb->tx_dma_handle); 7879da57d7bSbt150084 tcb->tx_dma_handle = NULL; 7889da57d7bSbt150084 } else { 7899da57d7bSbt150084 /* 7909da57d7bSbt150084 * If the dma handle is NULL, then we don't 7919da57d7bSbt150084 * have to check the remaining. 7929da57d7bSbt150084 */ 7939da57d7bSbt150084 break; 7949da57d7bSbt150084 } 7959da57d7bSbt150084 7969da57d7bSbt150084 ixgbe_free_dma_buffer(&tcb->tx_buf); 7979da57d7bSbt150084 } 7989da57d7bSbt150084 7999da57d7bSbt150084 if (tx_ring->tcb_area != NULL) { 8009da57d7bSbt150084 kmem_free(tx_ring->tcb_area, 8019da57d7bSbt150084 sizeof (tx_control_block_t) * tx_ring->free_list_size); 8029da57d7bSbt150084 tx_ring->tcb_area = NULL; 8039da57d7bSbt150084 } 8049da57d7bSbt150084 8059da57d7bSbt150084 if (tx_ring->work_list != NULL) { 8069da57d7bSbt150084 kmem_free(tx_ring->work_list, 8079da57d7bSbt150084 sizeof (tx_control_block_t *) * tx_ring->ring_size); 8089da57d7bSbt150084 tx_ring->work_list = NULL; 8099da57d7bSbt150084 } 8109da57d7bSbt150084 8119da57d7bSbt150084 if (tx_ring->free_list != NULL) { 8129da57d7bSbt150084 kmem_free(tx_ring->free_list, 8139da57d7bSbt150084 sizeof (tx_control_block_t *) * tx_ring->free_list_size); 8149da57d7bSbt150084 tx_ring->free_list = NULL; 8159da57d7bSbt150084 } 8169da57d7bSbt150084 } 8179da57d7bSbt150084 8189da57d7bSbt150084 /* 8199da57d7bSbt150084 * ixgbe_alloc_rcb_lists - Memory allocation for the receive control blocks 8209da57d7bSbt150084 * of one ring. 8219da57d7bSbt150084 */ 8229da57d7bSbt150084 static int 823ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_alloc_rcb_lists(ixgbe_rx_data_t *rx_data) 8249da57d7bSbt150084 { 8259da57d7bSbt150084 int i; 8269da57d7bSbt150084 int ret; 8279da57d7bSbt150084 rx_control_block_t *rcb; 828ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_t *ixgbe = rx_data->rx_ring->ixgbe; 8299da57d7bSbt150084 dma_buffer_t *rx_buf; 8309da57d7bSbt150084 uint32_t rcb_count; 8319da57d7bSbt150084 8329da57d7bSbt150084 /* 8339da57d7bSbt150084 * Allocate memory for the rx control blocks for work list and 8349da57d7bSbt150084 * free list. 8359da57d7bSbt150084 */ 836ea65739eSchenlu chen - Sun Microsystems - Beijing China rcb_count = rx_data->ring_size + rx_data->free_list_size; 837ea65739eSchenlu chen - Sun Microsystems - Beijing China rcb = rx_data->rcb_area; 8389da57d7bSbt150084 8399da57d7bSbt150084 for (i = 0; i < rcb_count; i++, rcb++) { 8409da57d7bSbt150084 ASSERT(rcb != NULL); 8419da57d7bSbt150084 842ea65739eSchenlu chen - Sun Microsystems - Beijing China if (i < rx_data->ring_size) { 8439da57d7bSbt150084 /* Attach the rx control block to the work list */ 844ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->work_list[i] = rcb; 8459da57d7bSbt150084 } else { 8469da57d7bSbt150084 /* Attach the rx control block to the free list */ 847ea65739eSchenlu chen - Sun Microsystems - Beijing China rx_data->free_list[i - rx_data->ring_size] = rcb; 8489da57d7bSbt150084 } 8499da57d7bSbt150084 8509da57d7bSbt150084 rx_buf = &rcb->rx_buf; 8519da57d7bSbt150084 ret = ixgbe_alloc_dma_buffer(ixgbe, 8529da57d7bSbt150084 rx_buf, ixgbe->rx_buf_size); 8539da57d7bSbt150084 8549da57d7bSbt150084 if (ret != IXGBE_SUCCESS) { 8559da57d7bSbt150084 ixgbe_error(ixgbe, "Allocate rx dma buffer failed"); 8569da57d7bSbt150084 goto alloc_rcb_lists_fail; 8579da57d7bSbt150084 } 8589da57d7bSbt150084 8599da57d7bSbt150084 rx_buf->size -= IPHDR_ALIGN_ROOM; 8609da57d7bSbt150084 rx_buf->address += IPHDR_ALIGN_ROOM; 8619da57d7bSbt150084 rx_buf->dma_address += IPHDR_ALIGN_ROOM; 8629da57d7bSbt150084 863ea65739eSchenlu chen - Sun Microsystems - Beijing China rcb->ref_cnt = 1; 864ea65739eSchenlu chen - Sun Microsystems - Beijing China rcb->rx_data = (ixgbe_rx_data_t *)rx_data; 8659da57d7bSbt150084 rcb->free_rtn.free_func = ixgbe_rx_recycle; 8669da57d7bSbt150084 rcb->free_rtn.free_arg = (char *)rcb; 867*ffd8e883SWinson Wang - Sun Microsystems - Beijing China rcb->lro_prev = -1; 868*ffd8e883SWinson Wang - Sun Microsystems - Beijing China rcb->lro_next = -1; 869*ffd8e883SWinson Wang - Sun Microsystems - Beijing China rcb->lro_pkt = B_FALSE; 8709da57d7bSbt150084 rcb->mp = desballoc((unsigned char *) 87173cd555cSBin Tu - Sun Microsystems - Beijing China rx_buf->address, 87273cd555cSBin Tu - Sun Microsystems - Beijing China rx_buf->size, 8739da57d7bSbt150084 0, &rcb->free_rtn); 8749da57d7bSbt150084 } 8759da57d7bSbt150084 8769da57d7bSbt150084 return (IXGBE_SUCCESS); 8779da57d7bSbt150084 8789da57d7bSbt150084 alloc_rcb_lists_fail: 879ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_free_rcb_lists(rx_data); 8809da57d7bSbt150084 8819da57d7bSbt150084 return (IXGBE_FAILURE); 8829da57d7bSbt150084 } 8839da57d7bSbt150084 8849da57d7bSbt150084 /* 8859da57d7bSbt150084 * ixgbe_free_rcb_lists - Free the receive control blocks of one ring. 8869da57d7bSbt150084 */ 8879da57d7bSbt150084 static void 888ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_free_rcb_lists(ixgbe_rx_data_t *rx_data) 8899da57d7bSbt150084 { 890ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe_t *ixgbe; 8919da57d7bSbt150084 rx_control_block_t *rcb; 8929da57d7bSbt150084 uint32_t rcb_count; 893ea65739eSchenlu chen - Sun Microsystems - Beijing China uint32_t ref_cnt; 894ea65739eSchenlu chen - Sun Microsystems - Beijing China int i; 8959da57d7bSbt150084 896ea65739eSchenlu chen - Sun Microsystems - Beijing China ixgbe = rx_data->rx_ring->ixgbe; 8979da57d7bSbt150084 898ea65739eSchenlu chen - Sun Microsystems - Beijing China mutex_enter(&ixgbe->rx_pending_lock); 899ea65739eSchenlu chen - Sun Microsystems - Beijing China 900ea65739eSchenlu chen - Sun Microsystems - Beijing China rcb = rx_data->rcb_area; 901ea65739eSchenlu chen - Sun Microsystems - Beijing China rcb_count = rx_data->ring_size + rx_data->free_list_size; 902ea65739eSchenlu chen - Sun Microsystems - Beijing China 9039da57d7bSbt150084 for (i = 0; i < rcb_count; i++, rcb++) { 9049da57d7bSbt150084 ASSERT(rcb != NULL); 9059da57d7bSbt150084 906ea65739eSchenlu chen - Sun Microsystems - Beijing China ref_cnt = atomic_dec_32_nv(&rcb->ref_cnt); 907ea65739eSchenlu chen - Sun Microsystems - Beijing China if (ref_cnt == 0) { 9089da57d7bSbt150084 if (rcb->mp != NULL) { 9099da57d7bSbt150084 freemsg(rcb->mp); 9109da57d7bSbt150084 rcb->mp = NULL; 9119da57d7bSbt150084 } 9129da57d7bSbt150084 ixgbe_free_dma_buffer(&rcb->rx_buf); 913ea65739eSchenlu chen - Sun Microsystems - Beijing China } else { 914ea65739eSchenlu chen - Sun Microsystems - Beijing China atomic_inc_32(&rx_data->rcb_pending); 915ea65739eSchenlu chen - Sun Microsystems - Beijing China atomic_inc_32(&ixgbe->rcb_pending); 916ea65739eSchenlu chen - Sun Microsystems - Beijing China } 9179da57d7bSbt150084 } 9189da57d7bSbt150084 919ea65739eSchenlu chen - Sun Microsystems - Beijing China mutex_exit(&ixgbe->rx_pending_lock); 9209da57d7bSbt150084 } 9219da57d7bSbt150084 9229da57d7bSbt150084 /* 9239da57d7bSbt150084 * ixgbe_set_fma_flags - Set the attribute for fma support. 9249da57d7bSbt150084 */ 9259da57d7bSbt150084 void 926837c1ac4SStephen Hanson ixgbe_set_fma_flags(int dma_flag) 9279da57d7bSbt150084 { 9289da57d7bSbt150084 if (dma_flag) { 9299da57d7bSbt150084 ixgbe_tx_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 9309da57d7bSbt150084 ixgbe_buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 9319da57d7bSbt150084 ixgbe_desc_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 9329da57d7bSbt150084 } else { 9339da57d7bSbt150084 ixgbe_tx_dma_attr.dma_attr_flags = 0; 9349da57d7bSbt150084 ixgbe_buf_dma_attr.dma_attr_flags = 0; 9359da57d7bSbt150084 ixgbe_desc_dma_attr.dma_attr_flags = 0; 9369da57d7bSbt150084 } 9379da57d7bSbt150084 } 938