15779Sxy150489 /* 25779Sxy150489 * CDDL HEADER START 35779Sxy150489 * 4*8571SChenlu.Chen@Sun.COM * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. 55779Sxy150489 * The contents of this file are subject to the terms of the 65779Sxy150489 * Common Development and Distribution License (the "License"). 75779Sxy150489 * You may not use this file except in compliance with the License. 85779Sxy150489 * 95779Sxy150489 * You can obtain a copy of the license at: 105779Sxy150489 * http://www.opensolaris.org/os/licensing. 115779Sxy150489 * See the License for the specific language governing permissions 125779Sxy150489 * and limitations under the License. 135779Sxy150489 * 145779Sxy150489 * When using or redistributing this file, you may do so under the 155779Sxy150489 * License only. No other modification of this header is permitted. 165779Sxy150489 * 175779Sxy150489 * If applicable, add the following below this CDDL HEADER, with the 185779Sxy150489 * fields enclosed by brackets "[]" replaced with your own identifying 195779Sxy150489 * information: Portions Copyright [yyyy] [name of copyright owner] 205779Sxy150489 * 215779Sxy150489 * CDDL HEADER END 225779Sxy150489 */ 235779Sxy150489 245779Sxy150489 /* 25*8571SChenlu.Chen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 265779Sxy150489 * Use is subject to license terms of the CDDL. 275779Sxy150489 */ 285779Sxy150489 295779Sxy150489 #include "igb_sw.h" 305779Sxy150489 315779Sxy150489 static int igb_alloc_tbd_ring(igb_tx_ring_t *); 325779Sxy150489 static void igb_free_tbd_ring(igb_tx_ring_t *); 335779Sxy150489 static int igb_alloc_rbd_ring(igb_rx_ring_t *); 345779Sxy150489 static void igb_free_rbd_ring(igb_rx_ring_t *); 355779Sxy150489 static int igb_alloc_dma_buffer(igb_t *, dma_buffer_t *, size_t); 365779Sxy150489 static void igb_free_dma_buffer(dma_buffer_t *); 375779Sxy150489 static int igb_alloc_tcb_lists(igb_tx_ring_t *); 385779Sxy150489 static void igb_free_tcb_lists(igb_tx_ring_t *); 395779Sxy150489 static int igb_alloc_rcb_lists(igb_rx_ring_t *); 405779Sxy150489 static void igb_free_rcb_lists(igb_rx_ring_t *); 415779Sxy150489 425779Sxy150489 #ifdef __sparc 435779Sxy150489 #define IGB_DMA_ALIGNMENT 0x0000000000002000ull 445779Sxy150489 #else 455779Sxy150489 #define IGB_DMA_ALIGNMENT 0x0000000000001000ull 465779Sxy150489 #endif 475779Sxy150489 485779Sxy150489 /* 495779Sxy150489 * DMA attributes for tx/rx descriptors 505779Sxy150489 */ 515779Sxy150489 static ddi_dma_attr_t igb_desc_dma_attr = { 525779Sxy150489 DMA_ATTR_V0, /* version number */ 535779Sxy150489 0x0000000000000000ull, /* low address */ 545779Sxy150489 0xFFFFFFFFFFFFFFFFull, /* high address */ 555779Sxy150489 0x00000000FFFFFFFFull, /* dma counter max */ 565779Sxy150489 IGB_DMA_ALIGNMENT, /* alignment */ 575779Sxy150489 0x00000FFF, /* burst sizes */ 585779Sxy150489 0x00000001, /* minimum transfer size */ 595779Sxy150489 0x00000000FFFFFFFFull, /* maximum transfer size */ 605779Sxy150489 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */ 615779Sxy150489 1, /* scatter/gather list length */ 625779Sxy150489 0x00000001, /* granularity */ 636624Sgl147354 DDI_DMA_FLAGERR, /* DMA flags */ 645779Sxy150489 }; 655779Sxy150489 665779Sxy150489 /* 675779Sxy150489 * DMA attributes for tx/rx buffers 685779Sxy150489 */ 695779Sxy150489 static ddi_dma_attr_t igb_buf_dma_attr = { 705779Sxy150489 DMA_ATTR_V0, /* version number */ 715779Sxy150489 0x0000000000000000ull, /* low address */ 725779Sxy150489 0xFFFFFFFFFFFFFFFFull, /* high address */ 735779Sxy150489 0x00000000FFFFFFFFull, /* dma counter max */ 745779Sxy150489 IGB_DMA_ALIGNMENT, /* alignment */ 755779Sxy150489 0x00000FFF, /* burst sizes */ 765779Sxy150489 0x00000001, /* minimum transfer size */ 775779Sxy150489 0x00000000FFFFFFFFull, /* maximum transfer size */ 785779Sxy150489 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */ 795779Sxy150489 1, /* scatter/gather list length */ 805779Sxy150489 0x00000001, /* granularity */ 816624Sgl147354 DDI_DMA_FLAGERR, /* DMA flags */ 825779Sxy150489 }; 835779Sxy150489 845779Sxy150489 /* 855779Sxy150489 * DMA attributes for transmit 865779Sxy150489 */ 875779Sxy150489 static ddi_dma_attr_t igb_tx_dma_attr = { 885779Sxy150489 DMA_ATTR_V0, /* version number */ 895779Sxy150489 0x0000000000000000ull, /* low address */ 905779Sxy150489 0xFFFFFFFFFFFFFFFFull, /* high address */ 915779Sxy150489 0x00000000FFFFFFFFull, /* dma counter max */ 925779Sxy150489 1, /* alignment */ 935779Sxy150489 0x00000FFF, /* burst sizes */ 945779Sxy150489 0x00000001, /* minimum transfer size */ 955779Sxy150489 0x00000000FFFFFFFFull, /* maximum transfer size */ 965779Sxy150489 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */ 975779Sxy150489 MAX_COOKIE, /* scatter/gather list length */ 985779Sxy150489 0x00000001, /* granularity */ 996624Sgl147354 DDI_DMA_FLAGERR, /* DMA flags */ 1005779Sxy150489 }; 1015779Sxy150489 1025779Sxy150489 /* 1035779Sxy150489 * DMA access attributes for descriptors. 1045779Sxy150489 */ 1055779Sxy150489 static ddi_device_acc_attr_t igb_desc_acc_attr = { 1065779Sxy150489 DDI_DEVICE_ATTR_V0, 1075779Sxy150489 DDI_STRUCTURE_LE_ACC, 1086624Sgl147354 DDI_STRICTORDER_ACC, 1096624Sgl147354 DDI_FLAGERR_ACC 1105779Sxy150489 }; 1115779Sxy150489 1125779Sxy150489 /* 1135779Sxy150489 * DMA access attributes for buffers. 1145779Sxy150489 */ 1155779Sxy150489 static ddi_device_acc_attr_t igb_buf_acc_attr = { 1165779Sxy150489 DDI_DEVICE_ATTR_V0, 1175779Sxy150489 DDI_NEVERSWAP_ACC, 1185779Sxy150489 DDI_STRICTORDER_ACC 1195779Sxy150489 }; 1205779Sxy150489 1215779Sxy150489 1225779Sxy150489 /* 1235779Sxy150489 * igb_alloc_dma - Allocate DMA resources for all rx/tx rings 1245779Sxy150489 */ 1255779Sxy150489 int 1265779Sxy150489 igb_alloc_dma(igb_t *igb) 1275779Sxy150489 { 1285779Sxy150489 igb_rx_ring_t *rx_ring; 1295779Sxy150489 igb_tx_ring_t *tx_ring; 1305779Sxy150489 int i; 1315779Sxy150489 1325779Sxy150489 for (i = 0; i < igb->num_rx_rings; i++) { 1335779Sxy150489 /* 1345779Sxy150489 * Allocate receive desciptor ring and control block lists 1355779Sxy150489 */ 1365779Sxy150489 rx_ring = &igb->rx_rings[i]; 1375779Sxy150489 1385779Sxy150489 if (igb_alloc_rbd_ring(rx_ring) != IGB_SUCCESS) 1395779Sxy150489 goto alloc_dma_failure; 1405779Sxy150489 1415779Sxy150489 if (igb_alloc_rcb_lists(rx_ring) != IGB_SUCCESS) 1425779Sxy150489 goto alloc_dma_failure; 1435779Sxy150489 } 1445779Sxy150489 1455779Sxy150489 for (i = 0; i < igb->num_tx_rings; i++) { 1465779Sxy150489 /* 1475779Sxy150489 * Allocate transmit desciptor ring and control block lists 1485779Sxy150489 */ 1495779Sxy150489 tx_ring = &igb->tx_rings[i]; 1505779Sxy150489 1515779Sxy150489 if (igb_alloc_tbd_ring(tx_ring) != IGB_SUCCESS) 1525779Sxy150489 goto alloc_dma_failure; 1535779Sxy150489 1545779Sxy150489 if (igb_alloc_tcb_lists(tx_ring) != IGB_SUCCESS) 1555779Sxy150489 goto alloc_dma_failure; 1565779Sxy150489 } 1575779Sxy150489 1585779Sxy150489 return (IGB_SUCCESS); 1595779Sxy150489 1605779Sxy150489 alloc_dma_failure: 1615779Sxy150489 igb_free_dma(igb); 1625779Sxy150489 1635779Sxy150489 return (IGB_FAILURE); 1645779Sxy150489 } 1655779Sxy150489 1665779Sxy150489 1675779Sxy150489 /* 1685779Sxy150489 * igb_free_dma - Free all the DMA resources of all rx/tx rings 1695779Sxy150489 */ 1705779Sxy150489 void 1715779Sxy150489 igb_free_dma(igb_t *igb) 1725779Sxy150489 { 1735779Sxy150489 igb_rx_ring_t *rx_ring; 1745779Sxy150489 igb_tx_ring_t *tx_ring; 1755779Sxy150489 int i; 1765779Sxy150489 1775779Sxy150489 /* 1785779Sxy150489 * Free DMA resources of rx rings 1795779Sxy150489 */ 1805779Sxy150489 for (i = 0; i < igb->num_rx_rings; i++) { 1815779Sxy150489 rx_ring = &igb->rx_rings[i]; 1825779Sxy150489 igb_free_rbd_ring(rx_ring); 1835779Sxy150489 igb_free_rcb_lists(rx_ring); 1845779Sxy150489 } 1855779Sxy150489 1865779Sxy150489 /* 1875779Sxy150489 * Free DMA resources of tx rings 1885779Sxy150489 */ 1895779Sxy150489 for (i = 0; i < igb->num_tx_rings; i++) { 1905779Sxy150489 tx_ring = &igb->tx_rings[i]; 1915779Sxy150489 igb_free_tbd_ring(tx_ring); 1925779Sxy150489 igb_free_tcb_lists(tx_ring); 1935779Sxy150489 } 1945779Sxy150489 } 1955779Sxy150489 1965779Sxy150489 /* 1975779Sxy150489 * igb_alloc_tbd_ring - Memory allocation for the tx descriptors of one ring. 1985779Sxy150489 */ 1995779Sxy150489 static int 2005779Sxy150489 igb_alloc_tbd_ring(igb_tx_ring_t *tx_ring) 2015779Sxy150489 { 2025779Sxy150489 int ret; 2035779Sxy150489 size_t size; 2045779Sxy150489 size_t len; 2055779Sxy150489 uint_t cookie_num; 2065779Sxy150489 dev_info_t *devinfo; 2075779Sxy150489 ddi_dma_cookie_t cookie; 2085779Sxy150489 igb_t *igb = tx_ring->igb; 2095779Sxy150489 2105779Sxy150489 devinfo = igb->dip; 2115779Sxy150489 size = sizeof (union e1000_adv_tx_desc) * tx_ring->ring_size; 2125779Sxy150489 2135779Sxy150489 /* 2145779Sxy150489 * If tx head write-back is enabled, an extra tbd is allocated 2155779Sxy150489 * to save the head write-back value 2165779Sxy150489 */ 2175779Sxy150489 if (igb->tx_head_wb_enable) { 2185779Sxy150489 size += sizeof (union e1000_adv_tx_desc); 2195779Sxy150489 } 2205779Sxy150489 2215779Sxy150489 /* 2225779Sxy150489 * Allocate a DMA handle for the transmit descriptor 2235779Sxy150489 * memory area. 2245779Sxy150489 */ 2255779Sxy150489 ret = ddi_dma_alloc_handle(devinfo, &igb_desc_dma_attr, 2265779Sxy150489 DDI_DMA_DONTWAIT, NULL, 2275779Sxy150489 &tx_ring->tbd_area.dma_handle); 2285779Sxy150489 2295779Sxy150489 if (ret != DDI_SUCCESS) { 2305779Sxy150489 igb_error(igb, 2315779Sxy150489 "Could not allocate tbd dma handle: %x", ret); 2325779Sxy150489 tx_ring->tbd_area.dma_handle = NULL; 2335779Sxy150489 2345779Sxy150489 return (IGB_FAILURE); 2355779Sxy150489 } 2365779Sxy150489 2375779Sxy150489 /* 2385779Sxy150489 * Allocate memory to DMA data to and from the transmit 2395779Sxy150489 * descriptors. 2405779Sxy150489 */ 2415779Sxy150489 ret = ddi_dma_mem_alloc(tx_ring->tbd_area.dma_handle, 2425779Sxy150489 size, &igb_desc_acc_attr, DDI_DMA_CONSISTENT, 2435779Sxy150489 DDI_DMA_DONTWAIT, NULL, 2445779Sxy150489 (caddr_t *)&tx_ring->tbd_area.address, 2455779Sxy150489 &len, &tx_ring->tbd_area.acc_handle); 2465779Sxy150489 2475779Sxy150489 if (ret != DDI_SUCCESS) { 2485779Sxy150489 igb_error(igb, 2495779Sxy150489 "Could not allocate tbd dma memory: %x", ret); 2505779Sxy150489 tx_ring->tbd_area.acc_handle = NULL; 2515779Sxy150489 tx_ring->tbd_area.address = NULL; 2525779Sxy150489 if (tx_ring->tbd_area.dma_handle != NULL) { 2535779Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle); 2545779Sxy150489 tx_ring->tbd_area.dma_handle = NULL; 2555779Sxy150489 } 2565779Sxy150489 return (IGB_FAILURE); 2575779Sxy150489 } 2585779Sxy150489 2595779Sxy150489 /* 2605779Sxy150489 * Initialize the entire transmit buffer descriptor area to zero 2615779Sxy150489 */ 2625779Sxy150489 bzero(tx_ring->tbd_area.address, len); 2635779Sxy150489 2645779Sxy150489 /* 2655779Sxy150489 * Allocates DMA resources for the memory that was allocated by 2665779Sxy150489 * the ddi_dma_mem_alloc call. The DMA resources then get bound to the 2675779Sxy150489 * the memory address 2685779Sxy150489 */ 2695779Sxy150489 ret = ddi_dma_addr_bind_handle(tx_ring->tbd_area.dma_handle, 2705779Sxy150489 NULL, (caddr_t)tx_ring->tbd_area.address, 2715779Sxy150489 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 2725779Sxy150489 DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num); 2735779Sxy150489 2745779Sxy150489 if (ret != DDI_DMA_MAPPED) { 2755779Sxy150489 igb_error(igb, 2765779Sxy150489 "Could not bind tbd dma resource: %x", ret); 2775779Sxy150489 tx_ring->tbd_area.dma_address = NULL; 2785779Sxy150489 if (tx_ring->tbd_area.acc_handle != NULL) { 2795779Sxy150489 ddi_dma_mem_free(&tx_ring->tbd_area.acc_handle); 2805779Sxy150489 tx_ring->tbd_area.acc_handle = NULL; 2815779Sxy150489 tx_ring->tbd_area.address = NULL; 2825779Sxy150489 } 2835779Sxy150489 if (tx_ring->tbd_area.dma_handle != NULL) { 2845779Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle); 2855779Sxy150489 tx_ring->tbd_area.dma_handle = NULL; 2865779Sxy150489 } 2875779Sxy150489 return (IGB_FAILURE); 2885779Sxy150489 } 2895779Sxy150489 2905779Sxy150489 ASSERT(cookie_num == 1); 2915779Sxy150489 2925779Sxy150489 tx_ring->tbd_area.dma_address = cookie.dmac_laddress; 2935779Sxy150489 tx_ring->tbd_area.size = len; 2945779Sxy150489 2955779Sxy150489 tx_ring->tbd_ring = (union e1000_adv_tx_desc *)(uintptr_t) 2965779Sxy150489 tx_ring->tbd_area.address; 2975779Sxy150489 2985779Sxy150489 return (IGB_SUCCESS); 2995779Sxy150489 } 3005779Sxy150489 3015779Sxy150489 /* 3025779Sxy150489 * igb_free_tbd_ring - Free the tx descriptors of one ring. 3035779Sxy150489 */ 3045779Sxy150489 static void 3055779Sxy150489 igb_free_tbd_ring(igb_tx_ring_t *tx_ring) 3065779Sxy150489 { 3075779Sxy150489 if (tx_ring->tbd_area.dma_handle != NULL) { 3085779Sxy150489 (void) ddi_dma_unbind_handle(tx_ring->tbd_area.dma_handle); 3095779Sxy150489 } 3105779Sxy150489 if (tx_ring->tbd_area.acc_handle != NULL) { 3115779Sxy150489 ddi_dma_mem_free(&tx_ring->tbd_area.acc_handle); 3125779Sxy150489 tx_ring->tbd_area.acc_handle = NULL; 3135779Sxy150489 } 3145779Sxy150489 if (tx_ring->tbd_area.dma_handle != NULL) { 3155779Sxy150489 ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle); 3165779Sxy150489 tx_ring->tbd_area.dma_handle = NULL; 3175779Sxy150489 } 3185779Sxy150489 tx_ring->tbd_area.address = NULL; 3195779Sxy150489 tx_ring->tbd_area.dma_address = NULL; 3205779Sxy150489 tx_ring->tbd_area.size = 0; 3215779Sxy150489 3225779Sxy150489 tx_ring->tbd_ring = NULL; 3235779Sxy150489 } 3245779Sxy150489 3255779Sxy150489 /* 3265779Sxy150489 * igb_alloc_rbd_ring - Memory allocation for the rx descriptors of one ring. 3275779Sxy150489 */ 3285779Sxy150489 static int 3295779Sxy150489 igb_alloc_rbd_ring(igb_rx_ring_t *rx_ring) 3305779Sxy150489 { 3315779Sxy150489 int ret; 3325779Sxy150489 size_t size; 3335779Sxy150489 size_t len; 3345779Sxy150489 uint_t cookie_num; 3355779Sxy150489 dev_info_t *devinfo; 3365779Sxy150489 ddi_dma_cookie_t cookie; 3375779Sxy150489 igb_t *igb = rx_ring->igb; 3385779Sxy150489 3395779Sxy150489 devinfo = igb->dip; 3405779Sxy150489 size = sizeof (union e1000_adv_rx_desc) * rx_ring->ring_size; 3415779Sxy150489 3425779Sxy150489 /* 3435779Sxy150489 * Allocate a new DMA handle for the receive descriptor 3445779Sxy150489 * memory area. 3455779Sxy150489 */ 3465779Sxy150489 ret = ddi_dma_alloc_handle(devinfo, &igb_desc_dma_attr, 3475779Sxy150489 DDI_DMA_DONTWAIT, NULL, 3485779Sxy150489 &rx_ring->rbd_area.dma_handle); 3495779Sxy150489 3505779Sxy150489 if (ret != DDI_SUCCESS) { 3515779Sxy150489 igb_error(igb, 3525779Sxy150489 "Could not allocate rbd dma handle: %x", ret); 3535779Sxy150489 rx_ring->rbd_area.dma_handle = NULL; 3545779Sxy150489 return (IGB_FAILURE); 3555779Sxy150489 } 3565779Sxy150489 3575779Sxy150489 /* 3585779Sxy150489 * Allocate memory to DMA data to and from the receive 3595779Sxy150489 * descriptors. 3605779Sxy150489 */ 3615779Sxy150489 ret = ddi_dma_mem_alloc(rx_ring->rbd_area.dma_handle, 3625779Sxy150489 size, &igb_desc_acc_attr, DDI_DMA_CONSISTENT, 3635779Sxy150489 DDI_DMA_DONTWAIT, NULL, 3645779Sxy150489 (caddr_t *)&rx_ring->rbd_area.address, 3655779Sxy150489 &len, &rx_ring->rbd_area.acc_handle); 3665779Sxy150489 3675779Sxy150489 if (ret != DDI_SUCCESS) { 3685779Sxy150489 igb_error(igb, 3695779Sxy150489 "Could not allocate rbd dma memory: %x", ret); 3705779Sxy150489 rx_ring->rbd_area.acc_handle = NULL; 3715779Sxy150489 rx_ring->rbd_area.address = NULL; 3725779Sxy150489 if (rx_ring->rbd_area.dma_handle != NULL) { 3735779Sxy150489 ddi_dma_free_handle(&rx_ring->rbd_area.dma_handle); 3745779Sxy150489 rx_ring->rbd_area.dma_handle = NULL; 3755779Sxy150489 } 3765779Sxy150489 return (IGB_FAILURE); 3775779Sxy150489 } 3785779Sxy150489 3795779Sxy150489 /* 3805779Sxy150489 * Initialize the entire transmit buffer descriptor area to zero 3815779Sxy150489 */ 3825779Sxy150489 bzero(rx_ring->rbd_area.address, len); 3835779Sxy150489 3845779Sxy150489 /* 3855779Sxy150489 * Allocates DMA resources for the memory that was allocated by 3865779Sxy150489 * the ddi_dma_mem_alloc call. 3875779Sxy150489 */ 3885779Sxy150489 ret = ddi_dma_addr_bind_handle(rx_ring->rbd_area.dma_handle, 3895779Sxy150489 NULL, (caddr_t)rx_ring->rbd_area.address, 3905779Sxy150489 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 3915779Sxy150489 DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num); 3925779Sxy150489 3935779Sxy150489 if (ret != DDI_DMA_MAPPED) { 3945779Sxy150489 igb_error(igb, 3955779Sxy150489 "Could not bind rbd dma resource: %x", ret); 3965779Sxy150489 rx_ring->rbd_area.dma_address = NULL; 3975779Sxy150489 if (rx_ring->rbd_area.acc_handle != NULL) { 3985779Sxy150489 ddi_dma_mem_free(&rx_ring->rbd_area.acc_handle); 3995779Sxy150489 rx_ring->rbd_area.acc_handle = NULL; 4005779Sxy150489 rx_ring->rbd_area.address = NULL; 4015779Sxy150489 } 4025779Sxy150489 if (rx_ring->rbd_area.dma_handle != NULL) { 4035779Sxy150489 ddi_dma_free_handle(&rx_ring->rbd_area.dma_handle); 4045779Sxy150489 rx_ring->rbd_area.dma_handle = NULL; 4055779Sxy150489 } 4065779Sxy150489 return (IGB_FAILURE); 4075779Sxy150489 } 4085779Sxy150489 4095779Sxy150489 ASSERT(cookie_num == 1); 4105779Sxy150489 4115779Sxy150489 rx_ring->rbd_area.dma_address = cookie.dmac_laddress; 4125779Sxy150489 rx_ring->rbd_area.size = len; 4135779Sxy150489 4145779Sxy150489 rx_ring->rbd_ring = (union e1000_adv_rx_desc *)(uintptr_t) 4155779Sxy150489 rx_ring->rbd_area.address; 4165779Sxy150489 4175779Sxy150489 return (IGB_SUCCESS); 4185779Sxy150489 } 4195779Sxy150489 4205779Sxy150489 /* 4215779Sxy150489 * igb_free_rbd_ring - Free the rx descriptors of one ring. 4225779Sxy150489 */ 4235779Sxy150489 static void 4245779Sxy150489 igb_free_rbd_ring(igb_rx_ring_t *rx_ring) 4255779Sxy150489 { 4265779Sxy150489 if (rx_ring->rbd_area.dma_handle != NULL) { 4275779Sxy150489 (void) ddi_dma_unbind_handle(rx_ring->rbd_area.dma_handle); 4285779Sxy150489 } 4295779Sxy150489 if (rx_ring->rbd_area.acc_handle != NULL) { 4305779Sxy150489 ddi_dma_mem_free(&rx_ring->rbd_area.acc_handle); 4315779Sxy150489 rx_ring->rbd_area.acc_handle = NULL; 4325779Sxy150489 } 4335779Sxy150489 if (rx_ring->rbd_area.dma_handle != NULL) { 4345779Sxy150489 ddi_dma_free_handle(&rx_ring->rbd_area.dma_handle); 4355779Sxy150489 rx_ring->rbd_area.dma_handle = NULL; 4365779Sxy150489 } 4375779Sxy150489 rx_ring->rbd_area.address = NULL; 4385779Sxy150489 rx_ring->rbd_area.dma_address = NULL; 4395779Sxy150489 rx_ring->rbd_area.size = 0; 4405779Sxy150489 4415779Sxy150489 rx_ring->rbd_ring = NULL; 4425779Sxy150489 } 4435779Sxy150489 4445779Sxy150489 4455779Sxy150489 /* 4465779Sxy150489 * igb_alloc_dma_buffer - Allocate DMA resources for a DMA buffer 4475779Sxy150489 */ 4485779Sxy150489 static int 4495779Sxy150489 igb_alloc_dma_buffer(igb_t *igb, 4505779Sxy150489 dma_buffer_t *buf, size_t size) 4515779Sxy150489 { 4525779Sxy150489 int ret; 4535779Sxy150489 dev_info_t *devinfo = igb->dip; 4545779Sxy150489 ddi_dma_cookie_t cookie; 4555779Sxy150489 size_t len; 4565779Sxy150489 uint_t cookie_num; 4575779Sxy150489 4585779Sxy150489 ret = ddi_dma_alloc_handle(devinfo, 4595779Sxy150489 &igb_buf_dma_attr, DDI_DMA_DONTWAIT, 4605779Sxy150489 NULL, &buf->dma_handle); 4615779Sxy150489 4625779Sxy150489 if (ret != DDI_SUCCESS) { 4635779Sxy150489 buf->dma_handle = NULL; 4645779Sxy150489 igb_error(igb, 4655779Sxy150489 "Could not allocate dma buffer handle: %x", ret); 4665779Sxy150489 return (IGB_FAILURE); 4675779Sxy150489 } 4685779Sxy150489 4695779Sxy150489 ret = ddi_dma_mem_alloc(buf->dma_handle, 4705779Sxy150489 size, &igb_buf_acc_attr, DDI_DMA_STREAMING, 4715779Sxy150489 DDI_DMA_DONTWAIT, NULL, &buf->address, 4725779Sxy150489 &len, &buf->acc_handle); 4735779Sxy150489 4745779Sxy150489 if (ret != DDI_SUCCESS) { 4755779Sxy150489 buf->acc_handle = NULL; 4765779Sxy150489 buf->address = NULL; 4775779Sxy150489 if (buf->dma_handle != NULL) { 4785779Sxy150489 ddi_dma_free_handle(&buf->dma_handle); 4795779Sxy150489 buf->dma_handle = NULL; 4805779Sxy150489 } 4815779Sxy150489 igb_error(igb, 4825779Sxy150489 "Could not allocate dma buffer memory: %x", ret); 4835779Sxy150489 return (IGB_FAILURE); 4845779Sxy150489 } 4855779Sxy150489 4865779Sxy150489 ret = ddi_dma_addr_bind_handle(buf->dma_handle, NULL, 4875779Sxy150489 buf->address, 4885779Sxy150489 len, DDI_DMA_RDWR | DDI_DMA_STREAMING, 4895779Sxy150489 DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num); 4905779Sxy150489 4915779Sxy150489 if (ret != DDI_DMA_MAPPED) { 4925779Sxy150489 buf->dma_address = NULL; 4935779Sxy150489 if (buf->acc_handle != NULL) { 4945779Sxy150489 ddi_dma_mem_free(&buf->acc_handle); 4955779Sxy150489 buf->acc_handle = NULL; 4965779Sxy150489 buf->address = NULL; 4975779Sxy150489 } 4985779Sxy150489 if (buf->dma_handle != NULL) { 4995779Sxy150489 ddi_dma_free_handle(&buf->dma_handle); 5005779Sxy150489 buf->dma_handle = NULL; 5015779Sxy150489 } 5025779Sxy150489 igb_error(igb, 5035779Sxy150489 "Could not bind dma buffer handle: %x", ret); 5045779Sxy150489 return (IGB_FAILURE); 5055779Sxy150489 } 5065779Sxy150489 5075779Sxy150489 ASSERT(cookie_num == 1); 5085779Sxy150489 5095779Sxy150489 buf->dma_address = cookie.dmac_laddress; 5105779Sxy150489 buf->size = len; 5115779Sxy150489 buf->len = 0; 5125779Sxy150489 5135779Sxy150489 return (IGB_SUCCESS); 5145779Sxy150489 } 5155779Sxy150489 5165779Sxy150489 /* 5175779Sxy150489 * igb_free_dma_buffer - Free one allocated area of dma memory and handle 5185779Sxy150489 */ 5195779Sxy150489 static void 5205779Sxy150489 igb_free_dma_buffer(dma_buffer_t *buf) 5215779Sxy150489 { 5225779Sxy150489 if (buf->dma_handle != NULL) { 5235779Sxy150489 (void) ddi_dma_unbind_handle(buf->dma_handle); 5245779Sxy150489 buf->dma_address = NULL; 5255779Sxy150489 } else { 5265779Sxy150489 return; 5275779Sxy150489 } 5285779Sxy150489 5295779Sxy150489 if (buf->acc_handle != NULL) { 5305779Sxy150489 ddi_dma_mem_free(&buf->acc_handle); 5315779Sxy150489 buf->acc_handle = NULL; 5325779Sxy150489 buf->address = NULL; 5335779Sxy150489 } 5345779Sxy150489 5355779Sxy150489 if (buf->dma_handle != NULL) { 5365779Sxy150489 ddi_dma_free_handle(&buf->dma_handle); 5375779Sxy150489 buf->dma_handle = NULL; 5385779Sxy150489 } 5395779Sxy150489 5405779Sxy150489 buf->size = 0; 5415779Sxy150489 buf->len = 0; 5425779Sxy150489 } 5435779Sxy150489 5445779Sxy150489 /* 5455779Sxy150489 * igb_alloc_tcb_lists - Memory allocation for the transmit control bolcks 5465779Sxy150489 * of one ring. 5475779Sxy150489 */ 5485779Sxy150489 static int 5495779Sxy150489 igb_alloc_tcb_lists(igb_tx_ring_t *tx_ring) 5505779Sxy150489 { 5515779Sxy150489 int i; 5525779Sxy150489 int ret; 5535779Sxy150489 tx_control_block_t *tcb; 5545779Sxy150489 dma_buffer_t *tx_buf; 5555779Sxy150489 igb_t *igb = tx_ring->igb; 5565779Sxy150489 dev_info_t *devinfo = igb->dip; 5575779Sxy150489 5585779Sxy150489 /* 5595779Sxy150489 * Allocate memory for the work list. 5605779Sxy150489 */ 5615779Sxy150489 tx_ring->work_list = kmem_zalloc(sizeof (tx_control_block_t *) * 5625779Sxy150489 tx_ring->ring_size, KM_NOSLEEP); 5635779Sxy150489 5645779Sxy150489 if (tx_ring->work_list == NULL) { 5655779Sxy150489 igb_error(igb, 5665779Sxy150489 "Cound not allocate memory for tx work list"); 5675779Sxy150489 return (IGB_FAILURE); 5685779Sxy150489 } 5695779Sxy150489 5705779Sxy150489 /* 5715779Sxy150489 * Allocate memory for the free list. 5725779Sxy150489 */ 5735779Sxy150489 tx_ring->free_list = kmem_zalloc(sizeof (tx_control_block_t *) * 5745779Sxy150489 tx_ring->free_list_size, KM_NOSLEEP); 5755779Sxy150489 5765779Sxy150489 if (tx_ring->free_list == NULL) { 5775779Sxy150489 kmem_free(tx_ring->work_list, 5785779Sxy150489 sizeof (tx_control_block_t *) * tx_ring->ring_size); 5795779Sxy150489 tx_ring->work_list = NULL; 5805779Sxy150489 5815779Sxy150489 igb_error(igb, 5825779Sxy150489 "Cound not allocate memory for tx free list"); 5835779Sxy150489 return (IGB_FAILURE); 5845779Sxy150489 } 5855779Sxy150489 5865779Sxy150489 /* 5875779Sxy150489 * Allocate memory for the tx control blocks of free list. 5885779Sxy150489 */ 5895779Sxy150489 tx_ring->tcb_area = 5905779Sxy150489 kmem_zalloc(sizeof (tx_control_block_t) * 5915779Sxy150489 tx_ring->free_list_size, KM_NOSLEEP); 5925779Sxy150489 5935779Sxy150489 if (tx_ring->tcb_area == NULL) { 5945779Sxy150489 kmem_free(tx_ring->work_list, 5955779Sxy150489 sizeof (tx_control_block_t *) * tx_ring->ring_size); 5965779Sxy150489 tx_ring->work_list = NULL; 5975779Sxy150489 5985779Sxy150489 kmem_free(tx_ring->free_list, 5995779Sxy150489 sizeof (tx_control_block_t *) * tx_ring->free_list_size); 6005779Sxy150489 tx_ring->free_list = NULL; 6015779Sxy150489 6025779Sxy150489 igb_error(igb, 6035779Sxy150489 "Cound not allocate memory for tx control blocks"); 6045779Sxy150489 return (IGB_FAILURE); 6055779Sxy150489 } 6065779Sxy150489 6075779Sxy150489 /* 6085779Sxy150489 * Allocate dma memory for the tx control block of free list. 6095779Sxy150489 */ 6105779Sxy150489 tcb = tx_ring->tcb_area; 6115779Sxy150489 for (i = 0; i < tx_ring->free_list_size; i++, tcb++) { 6125779Sxy150489 ASSERT(tcb != NULL); 6135779Sxy150489 6145779Sxy150489 tx_ring->free_list[i] = tcb; 6155779Sxy150489 6165779Sxy150489 /* 6175779Sxy150489 * Pre-allocate dma handles for transmit. These dma handles 6185779Sxy150489 * will be dynamically bound to the data buffers passed down 6195779Sxy150489 * from the upper layers at the time of transmitting. 6205779Sxy150489 */ 6215779Sxy150489 ret = ddi_dma_alloc_handle(devinfo, 6225779Sxy150489 &igb_tx_dma_attr, 6235779Sxy150489 DDI_DMA_DONTWAIT, NULL, 6245779Sxy150489 &tcb->tx_dma_handle); 6255779Sxy150489 if (ret != DDI_SUCCESS) { 6265779Sxy150489 tcb->tx_dma_handle = NULL; 6275779Sxy150489 igb_error(igb, 6285779Sxy150489 "Could not allocate tx dma handle: %x", ret); 6295779Sxy150489 goto alloc_tcb_lists_fail; 6305779Sxy150489 } 6315779Sxy150489 6325779Sxy150489 /* 6335779Sxy150489 * Pre-allocate transmit buffers for packets that the 6345779Sxy150489 * size is less than bcopy_thresh. 6355779Sxy150489 */ 6365779Sxy150489 tx_buf = &tcb->tx_buf; 6375779Sxy150489 6385779Sxy150489 ret = igb_alloc_dma_buffer(igb, 6395779Sxy150489 tx_buf, igb->tx_buf_size); 6405779Sxy150489 6415779Sxy150489 if (ret != IGB_SUCCESS) { 6425779Sxy150489 ASSERT(tcb->tx_dma_handle != NULL); 6435779Sxy150489 ddi_dma_free_handle(&tcb->tx_dma_handle); 6445779Sxy150489 tcb->tx_dma_handle = NULL; 6455779Sxy150489 igb_error(igb, "Allocate tx dma buffer failed"); 6465779Sxy150489 goto alloc_tcb_lists_fail; 6475779Sxy150489 } 6485779Sxy150489 } 6495779Sxy150489 6505779Sxy150489 return (IGB_SUCCESS); 6515779Sxy150489 6525779Sxy150489 alloc_tcb_lists_fail: 6535779Sxy150489 igb_free_tcb_lists(tx_ring); 6545779Sxy150489 6555779Sxy150489 return (IGB_FAILURE); 6565779Sxy150489 } 6575779Sxy150489 6585779Sxy150489 /* 6595779Sxy150489 * igb_free_tcb_lists - Release the memory allocated for 6605779Sxy150489 * the transmit control bolcks of one ring. 6615779Sxy150489 */ 6625779Sxy150489 static void 6635779Sxy150489 igb_free_tcb_lists(igb_tx_ring_t *tx_ring) 6645779Sxy150489 { 6655779Sxy150489 int i; 6665779Sxy150489 tx_control_block_t *tcb; 6675779Sxy150489 6685779Sxy150489 tcb = tx_ring->tcb_area; 6695779Sxy150489 if (tcb == NULL) 6705779Sxy150489 return; 6715779Sxy150489 6725779Sxy150489 for (i = 0; i < tx_ring->free_list_size; i++, tcb++) { 6735779Sxy150489 ASSERT(tcb != NULL); 6745779Sxy150489 6755779Sxy150489 /* Free the tx dma handle for dynamical binding */ 6765779Sxy150489 if (tcb->tx_dma_handle != NULL) { 6775779Sxy150489 ddi_dma_free_handle(&tcb->tx_dma_handle); 6785779Sxy150489 tcb->tx_dma_handle = NULL; 6795779Sxy150489 } else { 6805779Sxy150489 /* 6815779Sxy150489 * If the dma handle is NULL, then we don't 6825779Sxy150489 * have to check the remaining. 6835779Sxy150489 */ 6845779Sxy150489 break; 6855779Sxy150489 } 6865779Sxy150489 6875779Sxy150489 igb_free_dma_buffer(&tcb->tx_buf); 6885779Sxy150489 } 6895779Sxy150489 6905779Sxy150489 if (tx_ring->tcb_area != NULL) { 6915779Sxy150489 kmem_free(tx_ring->tcb_area, 6925779Sxy150489 sizeof (tx_control_block_t) * tx_ring->free_list_size); 6935779Sxy150489 tx_ring->tcb_area = NULL; 6945779Sxy150489 } 6955779Sxy150489 6965779Sxy150489 if (tx_ring->work_list != NULL) { 6975779Sxy150489 kmem_free(tx_ring->work_list, 6985779Sxy150489 sizeof (tx_control_block_t *) * tx_ring->ring_size); 6995779Sxy150489 tx_ring->work_list = NULL; 7005779Sxy150489 } 7015779Sxy150489 7025779Sxy150489 if (tx_ring->free_list != NULL) { 7035779Sxy150489 kmem_free(tx_ring->free_list, 7045779Sxy150489 sizeof (tx_control_block_t *) * tx_ring->free_list_size); 7055779Sxy150489 tx_ring->free_list = NULL; 7065779Sxy150489 } 7075779Sxy150489 } 7085779Sxy150489 7095779Sxy150489 /* 7105779Sxy150489 * igb_alloc_rcb_lists - Memory allocation for the receive control blocks 7115779Sxy150489 * of one ring. 7125779Sxy150489 */ 7135779Sxy150489 static int 7145779Sxy150489 igb_alloc_rcb_lists(igb_rx_ring_t *rx_ring) 7155779Sxy150489 { 7165779Sxy150489 int i; 7175779Sxy150489 int ret; 7185779Sxy150489 rx_control_block_t *rcb; 7195779Sxy150489 igb_t *igb = rx_ring->igb; 7205779Sxy150489 dma_buffer_t *rx_buf; 7215779Sxy150489 uint32_t rcb_count; 7225779Sxy150489 7235779Sxy150489 /* 7245779Sxy150489 * Allocate memory for the work list. 7255779Sxy150489 */ 7265779Sxy150489 rx_ring->work_list = kmem_zalloc(sizeof (rx_control_block_t *) * 7275779Sxy150489 rx_ring->ring_size, KM_NOSLEEP); 7285779Sxy150489 7295779Sxy150489 if (rx_ring->work_list == NULL) { 7305779Sxy150489 igb_error(igb, 7315779Sxy150489 "Could not allocate memory for rx work list"); 7325779Sxy150489 return (IGB_FAILURE); 7335779Sxy150489 } 7345779Sxy150489 7355779Sxy150489 /* 7365779Sxy150489 * Allocate memory for the free list. 7375779Sxy150489 */ 7385779Sxy150489 rx_ring->free_list = kmem_zalloc(sizeof (rx_control_block_t *) * 7395779Sxy150489 rx_ring->free_list_size, KM_NOSLEEP); 7405779Sxy150489 7415779Sxy150489 if (rx_ring->free_list == NULL) { 7425779Sxy150489 kmem_free(rx_ring->work_list, 7435779Sxy150489 sizeof (rx_control_block_t *) * rx_ring->ring_size); 7445779Sxy150489 rx_ring->work_list = NULL; 7455779Sxy150489 7465779Sxy150489 igb_error(igb, 7475779Sxy150489 "Cound not allocate memory for rx free list"); 7485779Sxy150489 return (IGB_FAILURE); 7495779Sxy150489 } 7505779Sxy150489 7515779Sxy150489 /* 7525779Sxy150489 * Allocate memory for the rx control blocks for work list and 7535779Sxy150489 * free list. 7545779Sxy150489 */ 7555779Sxy150489 rcb_count = rx_ring->ring_size + rx_ring->free_list_size; 7565779Sxy150489 rx_ring->rcb_area = 7575779Sxy150489 kmem_zalloc(sizeof (rx_control_block_t) * rcb_count, 7585779Sxy150489 KM_NOSLEEP); 7595779Sxy150489 7605779Sxy150489 if (rx_ring->rcb_area == NULL) { 7615779Sxy150489 kmem_free(rx_ring->work_list, 7625779Sxy150489 sizeof (rx_control_block_t *) * rx_ring->ring_size); 7635779Sxy150489 rx_ring->work_list = NULL; 7645779Sxy150489 7655779Sxy150489 kmem_free(rx_ring->free_list, 7665779Sxy150489 sizeof (rx_control_block_t *) * rx_ring->free_list_size); 7675779Sxy150489 rx_ring->free_list = NULL; 7685779Sxy150489 7695779Sxy150489 igb_error(igb, 7705779Sxy150489 "Cound not allocate memory for rx control blocks"); 7715779Sxy150489 return (IGB_FAILURE); 7725779Sxy150489 } 7735779Sxy150489 7745779Sxy150489 /* 7755779Sxy150489 * Allocate dma memory for the rx control blocks 7765779Sxy150489 */ 7775779Sxy150489 rcb = rx_ring->rcb_area; 7785779Sxy150489 for (i = 0; i < rcb_count; i++, rcb++) { 7795779Sxy150489 ASSERT(rcb != NULL); 7805779Sxy150489 7815779Sxy150489 if (i < rx_ring->ring_size) { 7825779Sxy150489 /* Attach the rx control block to the work list */ 7835779Sxy150489 rx_ring->work_list[i] = rcb; 7845779Sxy150489 } else { 7855779Sxy150489 /* Attach the rx control block to the free list */ 7865779Sxy150489 rx_ring->free_list[i - rx_ring->ring_size] = rcb; 7875779Sxy150489 } 7885779Sxy150489 7895779Sxy150489 rx_buf = &rcb->rx_buf; 7905779Sxy150489 ret = igb_alloc_dma_buffer(igb, 7915779Sxy150489 rx_buf, igb->rx_buf_size); 7925779Sxy150489 7935779Sxy150489 if (ret != IGB_SUCCESS) { 7945779Sxy150489 igb_error(igb, "Allocate rx dma buffer failed"); 7955779Sxy150489 goto alloc_rcb_lists_fail; 7965779Sxy150489 } 7975779Sxy150489 7985779Sxy150489 rx_buf->size -= IPHDR_ALIGN_ROOM; 7995779Sxy150489 rx_buf->address += IPHDR_ALIGN_ROOM; 8005779Sxy150489 rx_buf->dma_address += IPHDR_ALIGN_ROOM; 8015779Sxy150489 8025779Sxy150489 rcb->state = RCB_FREE; 8035779Sxy150489 rcb->rx_ring = (igb_rx_ring_t *)rx_ring; 8045779Sxy150489 rcb->free_rtn.free_func = igb_rx_recycle; 8055779Sxy150489 rcb->free_rtn.free_arg = (char *)rcb; 8065779Sxy150489 8075779Sxy150489 rcb->mp = desballoc((unsigned char *) 808*8571SChenlu.Chen@Sun.COM rx_buf->address, 809*8571SChenlu.Chen@Sun.COM rx_buf->size, 8105779Sxy150489 0, &rcb->free_rtn); 8115779Sxy150489 } 8125779Sxy150489 8135779Sxy150489 return (IGB_SUCCESS); 8145779Sxy150489 8155779Sxy150489 alloc_rcb_lists_fail: 8165779Sxy150489 igb_free_rcb_lists(rx_ring); 8175779Sxy150489 8185779Sxy150489 return (IGB_FAILURE); 8195779Sxy150489 } 8205779Sxy150489 8215779Sxy150489 /* 8225779Sxy150489 * igb_free_rcb_lists - Free the receive control blocks of one ring. 8235779Sxy150489 */ 8245779Sxy150489 static void 8255779Sxy150489 igb_free_rcb_lists(igb_rx_ring_t *rx_ring) 8265779Sxy150489 { 8275779Sxy150489 int i; 8285779Sxy150489 rx_control_block_t *rcb; 8295779Sxy150489 uint32_t rcb_count; 8305779Sxy150489 8315779Sxy150489 rcb = rx_ring->rcb_area; 8325779Sxy150489 if (rcb == NULL) 8335779Sxy150489 return; 8345779Sxy150489 8355779Sxy150489 rcb_count = rx_ring->ring_size + rx_ring->free_list_size; 8365779Sxy150489 for (i = 0; i < rcb_count; i++, rcb++) { 8375779Sxy150489 ASSERT(rcb != NULL); 8385779Sxy150489 ASSERT(rcb->state == RCB_FREE); 8395779Sxy150489 8405779Sxy150489 if (rcb->mp != NULL) { 8415779Sxy150489 freemsg(rcb->mp); 8425779Sxy150489 rcb->mp = NULL; 8435779Sxy150489 } 8445779Sxy150489 8455779Sxy150489 igb_free_dma_buffer(&rcb->rx_buf); 8465779Sxy150489 } 8475779Sxy150489 8485779Sxy150489 if (rx_ring->rcb_area != NULL) { 8495779Sxy150489 kmem_free(rx_ring->rcb_area, 8505779Sxy150489 sizeof (rx_control_block_t) * rcb_count); 8515779Sxy150489 rx_ring->rcb_area = NULL; 8525779Sxy150489 } 8535779Sxy150489 8545779Sxy150489 if (rx_ring->work_list != NULL) { 8555779Sxy150489 kmem_free(rx_ring->work_list, 8565779Sxy150489 sizeof (rx_control_block_t *) * rx_ring->ring_size); 8575779Sxy150489 rx_ring->work_list = NULL; 8585779Sxy150489 } 8595779Sxy150489 8605779Sxy150489 if (rx_ring->free_list != NULL) { 8615779Sxy150489 kmem_free(rx_ring->free_list, 8625779Sxy150489 sizeof (rx_control_block_t *) * rx_ring->free_list_size); 8635779Sxy150489 rx_ring->free_list = NULL; 8645779Sxy150489 } 8655779Sxy150489 } 8666624Sgl147354 8676624Sgl147354 void 8686624Sgl147354 igb_set_fma_flags(int acc_flag, int dma_flag) 8696624Sgl147354 { 8706624Sgl147354 if (acc_flag) { 8716624Sgl147354 igb_desc_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC; 8726624Sgl147354 } else { 8736624Sgl147354 igb_desc_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC; 8746624Sgl147354 } 8756624Sgl147354 8766624Sgl147354 if (dma_flag) { 8776624Sgl147354 igb_tx_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 8786624Sgl147354 igb_buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 8796624Sgl147354 igb_desc_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 8806624Sgl147354 } else { 8816624Sgl147354 igb_tx_dma_attr.dma_attr_flags = 0; 8826624Sgl147354 igb_buf_dma_attr.dma_attr_flags = 0; 8836624Sgl147354 igb_desc_dma_attr.dma_attr_flags = 0; 8846624Sgl147354 } 8856624Sgl147354 } 886