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 /*
25*11486SZhen.W@Sun.COM * Copyright 2010 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,
10711236SStephen.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
ixgbe_alloc_dma(ixgbe_t * ixgbe)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
ixgbe_free_dma(ixgbe_t * ixgbe)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
ixgbe_alloc_rx_ring_data(ixgbe_rx_ring_t * rx_ring)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
ixgbe_free_rx_ring_data(ixgbe_rx_data_t * rx_data)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
ixgbe_alloc_tbd_ring(ixgbe_tx_ring_t * tx_ring)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
ixgbe_free_tbd_ring(ixgbe_tx_ring_t * tx_ring)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
ixgbe_alloc_rbd_ring(ixgbe_rx_data_t * rx_data)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
ixgbe_free_rbd_ring(ixgbe_rx_data_t * rx_data)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
ixgbe_alloc_dma_buffer(ixgbe_t * ixgbe,dma_buffer_t * buf,size_t size)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
ixgbe_free_dma_buffer(dma_buffer_t * buf)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
ixgbe_alloc_tcb_lists(ixgbe_tx_ring_t * tx_ring)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
ixgbe_free_tcb_lists(ixgbe_tx_ring_t * tx_ring)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
ixgbe_alloc_rcb_lists(ixgbe_rx_data_t * rx_data)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;
867*11486SZhen.W@Sun.COM rcb->lro_prev = -1;
868*11486SZhen.W@Sun.COM rcb->lro_next = -1;
869*11486SZhen.W@Sun.COM rcb->lro_pkt = B_FALSE;
8706621Sbt150084 rcb->mp = desballoc((unsigned char *)
8719353SSamuel.Tu@Sun.COM rx_buf->address,
8729353SSamuel.Tu@Sun.COM rx_buf->size,
8736621Sbt150084 0, &rcb->free_rtn);
8746621Sbt150084 }
8756621Sbt150084
8766621Sbt150084 return (IXGBE_SUCCESS);
8776621Sbt150084
8786621Sbt150084 alloc_rcb_lists_fail:
87910376SChenlu.Chen@Sun.COM ixgbe_free_rcb_lists(rx_data);
8806621Sbt150084
8816621Sbt150084 return (IXGBE_FAILURE);
8826621Sbt150084 }
8836621Sbt150084
8846621Sbt150084 /*
8856621Sbt150084 * ixgbe_free_rcb_lists - Free the receive control blocks of one ring.
8866621Sbt150084 */
8876621Sbt150084 static void
ixgbe_free_rcb_lists(ixgbe_rx_data_t * rx_data)88810376SChenlu.Chen@Sun.COM ixgbe_free_rcb_lists(ixgbe_rx_data_t *rx_data)
8896621Sbt150084 {
89010376SChenlu.Chen@Sun.COM ixgbe_t *ixgbe;
8916621Sbt150084 rx_control_block_t *rcb;
8926621Sbt150084 uint32_t rcb_count;
89310376SChenlu.Chen@Sun.COM uint32_t ref_cnt;
89410376SChenlu.Chen@Sun.COM int i;
8956621Sbt150084
89610376SChenlu.Chen@Sun.COM ixgbe = rx_data->rx_ring->ixgbe;
89710376SChenlu.Chen@Sun.COM
89810376SChenlu.Chen@Sun.COM mutex_enter(&ixgbe->rx_pending_lock);
8996621Sbt150084
90010376SChenlu.Chen@Sun.COM rcb = rx_data->rcb_area;
90110376SChenlu.Chen@Sun.COM rcb_count = rx_data->ring_size + rx_data->free_list_size;
90210376SChenlu.Chen@Sun.COM
9036621Sbt150084 for (i = 0; i < rcb_count; i++, rcb++) {
9046621Sbt150084 ASSERT(rcb != NULL);
9056621Sbt150084
90610376SChenlu.Chen@Sun.COM ref_cnt = atomic_dec_32_nv(&rcb->ref_cnt);
90710376SChenlu.Chen@Sun.COM if (ref_cnt == 0) {
90810376SChenlu.Chen@Sun.COM if (rcb->mp != NULL) {
90910376SChenlu.Chen@Sun.COM freemsg(rcb->mp);
91010376SChenlu.Chen@Sun.COM rcb->mp = NULL;
91110376SChenlu.Chen@Sun.COM }
91210376SChenlu.Chen@Sun.COM ixgbe_free_dma_buffer(&rcb->rx_buf);
91310376SChenlu.Chen@Sun.COM } else {
91410376SChenlu.Chen@Sun.COM atomic_inc_32(&rx_data->rcb_pending);
91510376SChenlu.Chen@Sun.COM atomic_inc_32(&ixgbe->rcb_pending);
9166621Sbt150084 }
9176621Sbt150084 }
9186621Sbt150084
91910376SChenlu.Chen@Sun.COM mutex_exit(&ixgbe->rx_pending_lock);
9206621Sbt150084 }
9216621Sbt150084
9226621Sbt150084 /*
9236621Sbt150084 * ixgbe_set_fma_flags - Set the attribute for fma support.
9246621Sbt150084 */
9256621Sbt150084 void
ixgbe_set_fma_flags(int dma_flag)92611236SStephen.Hanson@Sun.COM ixgbe_set_fma_flags(int dma_flag)
9276621Sbt150084 {
9286621Sbt150084 if (dma_flag) {
9296621Sbt150084 ixgbe_tx_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
9306621Sbt150084 ixgbe_buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
9316621Sbt150084 ixgbe_desc_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR;
9326621Sbt150084 } else {
9336621Sbt150084 ixgbe_tx_dma_attr.dma_attr_flags = 0;
9346621Sbt150084 ixgbe_buf_dma_attr.dma_attr_flags = 0;
9356621Sbt150084 ixgbe_desc_dma_attr.dma_attr_flags = 0;
9366621Sbt150084 }
9376621Sbt150084 }
938