1c869993eSxy150489 /* 2c869993eSxy150489 * CDDL HEADER START 3c869993eSxy150489 * 4c869993eSxy150489 * The contents of this file are subject to the terms of the 5c869993eSxy150489 * Common Development and Distribution License (the "License"). 6c869993eSxy150489 * You may not use this file except in compliance with the License. 7c869993eSxy150489 * 869b2d733SGuoqing Zhu * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 969b2d733SGuoqing Zhu * or http://www.opensolaris.org/os/licensing. 10c869993eSxy150489 * See the License for the specific language governing permissions 11c869993eSxy150489 * and limitations under the License. 12c869993eSxy150489 * 1369b2d733SGuoqing Zhu * When distributing Covered Code, include this CDDL HEADER in each 1469b2d733SGuoqing Zhu * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15c869993eSxy150489 * If applicable, add the following below this CDDL HEADER, with the 16c869993eSxy150489 * fields enclosed by brackets "[]" replaced with your own identifying 17c869993eSxy150489 * information: Portions Copyright [yyyy] [name of copyright owner] 18c869993eSxy150489 * 19c869993eSxy150489 * CDDL HEADER END 20c869993eSxy150489 */ 21c869993eSxy150489 22c869993eSxy150489 /* 2369b2d733SGuoqing Zhu * Copyright(c) 2007-2010 Intel Corporation. All rights reserved. 2469b2d733SGuoqing Zhu */ 2569b2d733SGuoqing Zhu 2669b2d733SGuoqing Zhu /* 2769b2d733SGuoqing Zhu * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 28c869993eSxy150489 */ 29c869993eSxy150489 30c869993eSxy150489 #include "igb_sw.h" 31c869993eSxy150489 32c869993eSxy150489 static int igb_alloc_tbd_ring(igb_tx_ring_t *); 33c869993eSxy150489 static void igb_free_tbd_ring(igb_tx_ring_t *); 34ac7f5757Schenlu chen - Sun Microsystems - Beijing China static int igb_alloc_rbd_ring(igb_rx_data_t *); 35ac7f5757Schenlu chen - Sun Microsystems - Beijing China static void igb_free_rbd_ring(igb_rx_data_t *); 36c869993eSxy150489 static int igb_alloc_dma_buffer(igb_t *, dma_buffer_t *, size_t); 37c869993eSxy150489 static int igb_alloc_tcb_lists(igb_tx_ring_t *); 38c869993eSxy150489 static void igb_free_tcb_lists(igb_tx_ring_t *); 39ac7f5757Schenlu chen - Sun Microsystems - Beijing China static int igb_alloc_rcb_lists(igb_rx_data_t *); 40ac7f5757Schenlu chen - Sun Microsystems - Beijing China static void igb_free_rcb_lists(igb_rx_data_t *); 41c869993eSxy150489 42c869993eSxy150489 #ifdef __sparc 43c869993eSxy150489 #define IGB_DMA_ALIGNMENT 0x0000000000002000ull 44c869993eSxy150489 #else 45c869993eSxy150489 #define IGB_DMA_ALIGNMENT 0x0000000000001000ull 46c869993eSxy150489 #endif 47c869993eSxy150489 48c869993eSxy150489 /* 49c869993eSxy150489 * DMA attributes for tx/rx descriptors 50c869993eSxy150489 */ 51c869993eSxy150489 static ddi_dma_attr_t igb_desc_dma_attr = { 52c869993eSxy150489 DMA_ATTR_V0, /* version number */ 53c869993eSxy150489 0x0000000000000000ull, /* low address */ 54c869993eSxy150489 0xFFFFFFFFFFFFFFFFull, /* high address */ 55c869993eSxy150489 0x00000000FFFFFFFFull, /* dma counter max */ 56c869993eSxy150489 IGB_DMA_ALIGNMENT, /* alignment */ 57c869993eSxy150489 0x00000FFF, /* burst sizes */ 58c869993eSxy150489 0x00000001, /* minimum transfer size */ 59c869993eSxy150489 0x00000000FFFFFFFFull, /* maximum transfer size */ 60c869993eSxy150489 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */ 61c869993eSxy150489 1, /* scatter/gather list length */ 62c869993eSxy150489 0x00000001, /* granularity */ 638bb4b220Sgl147354 DDI_DMA_FLAGERR, /* DMA flags */ 64c869993eSxy150489 }; 65c869993eSxy150489 66c869993eSxy150489 /* 67c869993eSxy150489 * DMA attributes for tx/rx buffers 68c869993eSxy150489 */ 69c869993eSxy150489 static ddi_dma_attr_t igb_buf_dma_attr = { 70c869993eSxy150489 DMA_ATTR_V0, /* version number */ 71c869993eSxy150489 0x0000000000000000ull, /* low address */ 72c869993eSxy150489 0xFFFFFFFFFFFFFFFFull, /* high address */ 73c869993eSxy150489 0x00000000FFFFFFFFull, /* dma counter max */ 74c869993eSxy150489 IGB_DMA_ALIGNMENT, /* alignment */ 75c869993eSxy150489 0x00000FFF, /* burst sizes */ 76c869993eSxy150489 0x00000001, /* minimum transfer size */ 77c869993eSxy150489 0x00000000FFFFFFFFull, /* maximum transfer size */ 78c869993eSxy150489 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */ 79c869993eSxy150489 1, /* scatter/gather list length */ 80c869993eSxy150489 0x00000001, /* granularity */ 818bb4b220Sgl147354 DDI_DMA_FLAGERR, /* DMA flags */ 82c869993eSxy150489 }; 83c869993eSxy150489 84c869993eSxy150489 /* 85c869993eSxy150489 * DMA attributes for transmit 86c869993eSxy150489 */ 87c869993eSxy150489 static ddi_dma_attr_t igb_tx_dma_attr = { 88c869993eSxy150489 DMA_ATTR_V0, /* version number */ 89c869993eSxy150489 0x0000000000000000ull, /* low address */ 90c869993eSxy150489 0xFFFFFFFFFFFFFFFFull, /* high address */ 91c869993eSxy150489 0x00000000FFFFFFFFull, /* dma counter max */ 92c869993eSxy150489 1, /* alignment */ 93c869993eSxy150489 0x00000FFF, /* burst sizes */ 94c869993eSxy150489 0x00000001, /* minimum transfer size */ 95c869993eSxy150489 0x00000000FFFFFFFFull, /* maximum transfer size */ 96c869993eSxy150489 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */ 97c869993eSxy150489 MAX_COOKIE, /* scatter/gather list length */ 98c869993eSxy150489 0x00000001, /* granularity */ 998bb4b220Sgl147354 DDI_DMA_FLAGERR, /* DMA flags */ 100c869993eSxy150489 }; 101c869993eSxy150489 102c869993eSxy150489 /* 103c869993eSxy150489 * DMA access attributes for descriptors. 104c869993eSxy150489 */ 105c869993eSxy150489 static ddi_device_acc_attr_t igb_desc_acc_attr = { 106c869993eSxy150489 DDI_DEVICE_ATTR_V0, 107c869993eSxy150489 DDI_STRUCTURE_LE_ACC, 108837c1ac4SStephen Hanson DDI_STRICTORDER_ACC 109c869993eSxy150489 }; 110c869993eSxy150489 111c869993eSxy150489 /* 112c869993eSxy150489 * DMA access attributes for buffers. 113c869993eSxy150489 */ 114c869993eSxy150489 static ddi_device_acc_attr_t igb_buf_acc_attr = { 115c869993eSxy150489 DDI_DEVICE_ATTR_V0, 116c869993eSxy150489 DDI_NEVERSWAP_ACC, 117c869993eSxy150489 DDI_STRICTORDER_ACC 118c869993eSxy150489 }; 119c869993eSxy150489 120c869993eSxy150489 121c869993eSxy150489 /* 122c869993eSxy150489 * igb_alloc_dma - Allocate DMA resources for all rx/tx rings 123c869993eSxy150489 */ 124c869993eSxy150489 int 125c869993eSxy150489 igb_alloc_dma(igb_t *igb) 126c869993eSxy150489 { 127c869993eSxy150489 igb_rx_ring_t *rx_ring; 128ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_rx_data_t *rx_data; 129c869993eSxy150489 igb_tx_ring_t *tx_ring; 130c869993eSxy150489 int i; 131c869993eSxy150489 132c869993eSxy150489 for (i = 0; i < igb->num_rx_rings; i++) { 133c869993eSxy150489 /* 134c869993eSxy150489 * Allocate receive desciptor ring and control block lists 135c869993eSxy150489 */ 136c869993eSxy150489 rx_ring = &igb->rx_rings[i]; 137ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data = rx_ring->rx_data; 138c869993eSxy150489 139ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (igb_alloc_rbd_ring(rx_data) != IGB_SUCCESS) 140c869993eSxy150489 goto alloc_dma_failure; 141c869993eSxy150489 142ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (igb_alloc_rcb_lists(rx_data) != IGB_SUCCESS) 143c869993eSxy150489 goto alloc_dma_failure; 144c869993eSxy150489 } 145c869993eSxy150489 146c869993eSxy150489 for (i = 0; i < igb->num_tx_rings; i++) { 147c869993eSxy150489 /* 148c869993eSxy150489 * Allocate transmit desciptor ring and control block lists 149c869993eSxy150489 */ 150c869993eSxy150489 tx_ring = &igb->tx_rings[i]; 151c869993eSxy150489 152c869993eSxy150489 if (igb_alloc_tbd_ring(tx_ring) != IGB_SUCCESS) 153c869993eSxy150489 goto alloc_dma_failure; 154c869993eSxy150489 155c869993eSxy150489 if (igb_alloc_tcb_lists(tx_ring) != IGB_SUCCESS) 156c869993eSxy150489 goto alloc_dma_failure; 157c869993eSxy150489 } 158c869993eSxy150489 159c869993eSxy150489 return (IGB_SUCCESS); 160c869993eSxy150489 161c869993eSxy150489 alloc_dma_failure: 162c869993eSxy150489 igb_free_dma(igb); 163c869993eSxy150489 164c869993eSxy150489 return (IGB_FAILURE); 165c869993eSxy150489 } 166c869993eSxy150489 167c869993eSxy150489 168c869993eSxy150489 /* 169c869993eSxy150489 * igb_free_dma - Free all the DMA resources of all rx/tx rings 170c869993eSxy150489 */ 171c869993eSxy150489 void 172c869993eSxy150489 igb_free_dma(igb_t *igb) 173c869993eSxy150489 { 174c869993eSxy150489 igb_rx_ring_t *rx_ring; 175ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_rx_data_t *rx_data; 176c869993eSxy150489 igb_tx_ring_t *tx_ring; 177c869993eSxy150489 int i; 178c869993eSxy150489 179c869993eSxy150489 /* 180c869993eSxy150489 * Free DMA resources of rx rings 181c869993eSxy150489 */ 182c869993eSxy150489 for (i = 0; i < igb->num_rx_rings; i++) { 183c869993eSxy150489 rx_ring = &igb->rx_rings[i]; 184ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data = rx_ring->rx_data; 185ac7f5757Schenlu chen - Sun Microsystems - Beijing China 186ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_free_rbd_ring(rx_data); 187ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_free_rcb_lists(rx_data); 188c869993eSxy150489 } 189c869993eSxy150489 190c869993eSxy150489 /* 191c869993eSxy150489 * Free DMA resources of tx rings 192c869993eSxy150489 */ 193c869993eSxy150489 for (i = 0; i < igb->num_tx_rings; i++) { 194c869993eSxy150489 tx_ring = &igb->tx_rings[i]; 195c869993eSxy150489 igb_free_tbd_ring(tx_ring); 196c869993eSxy150489 igb_free_tcb_lists(tx_ring); 197c869993eSxy150489 } 198c869993eSxy150489 } 199c869993eSxy150489 200c869993eSxy150489 /* 201c869993eSxy150489 * igb_alloc_tbd_ring - Memory allocation for the tx descriptors of one ring. 202c869993eSxy150489 */ 203c869993eSxy150489 static int 204c869993eSxy150489 igb_alloc_tbd_ring(igb_tx_ring_t *tx_ring) 205c869993eSxy150489 { 206c869993eSxy150489 int ret; 207c869993eSxy150489 size_t size; 208c869993eSxy150489 size_t len; 209c869993eSxy150489 uint_t cookie_num; 210c869993eSxy150489 dev_info_t *devinfo; 211c869993eSxy150489 ddi_dma_cookie_t cookie; 212c869993eSxy150489 igb_t *igb = tx_ring->igb; 213c869993eSxy150489 214c869993eSxy150489 devinfo = igb->dip; 215c869993eSxy150489 size = sizeof (union e1000_adv_tx_desc) * tx_ring->ring_size; 216c869993eSxy150489 217c869993eSxy150489 /* 218c869993eSxy150489 * If tx head write-back is enabled, an extra tbd is allocated 219c869993eSxy150489 * to save the head write-back value 220c869993eSxy150489 */ 221c869993eSxy150489 if (igb->tx_head_wb_enable) { 222c869993eSxy150489 size += sizeof (union e1000_adv_tx_desc); 223c869993eSxy150489 } 224c869993eSxy150489 225c869993eSxy150489 /* 226c869993eSxy150489 * Allocate a DMA handle for the transmit descriptor 227c869993eSxy150489 * memory area. 228c869993eSxy150489 */ 229c869993eSxy150489 ret = ddi_dma_alloc_handle(devinfo, &igb_desc_dma_attr, 230c869993eSxy150489 DDI_DMA_DONTWAIT, NULL, 231c869993eSxy150489 &tx_ring->tbd_area.dma_handle); 232c869993eSxy150489 233c869993eSxy150489 if (ret != DDI_SUCCESS) { 234*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 235c869993eSxy150489 "Could not allocate tbd dma handle: %x", ret); 236c869993eSxy150489 tx_ring->tbd_area.dma_handle = NULL; 237c869993eSxy150489 238c869993eSxy150489 return (IGB_FAILURE); 239c869993eSxy150489 } 240c869993eSxy150489 241c869993eSxy150489 /* 242c869993eSxy150489 * Allocate memory to DMA data to and from the transmit 243c869993eSxy150489 * descriptors. 244c869993eSxy150489 */ 245c869993eSxy150489 ret = ddi_dma_mem_alloc(tx_ring->tbd_area.dma_handle, 246c869993eSxy150489 size, &igb_desc_acc_attr, DDI_DMA_CONSISTENT, 247c869993eSxy150489 DDI_DMA_DONTWAIT, NULL, 248c869993eSxy150489 (caddr_t *)&tx_ring->tbd_area.address, 249c869993eSxy150489 &len, &tx_ring->tbd_area.acc_handle); 250c869993eSxy150489 251c869993eSxy150489 if (ret != DDI_SUCCESS) { 252*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 253c869993eSxy150489 "Could not allocate tbd dma memory: %x", ret); 254c869993eSxy150489 tx_ring->tbd_area.acc_handle = NULL; 255c869993eSxy150489 tx_ring->tbd_area.address = NULL; 256c869993eSxy150489 if (tx_ring->tbd_area.dma_handle != NULL) { 257c869993eSxy150489 ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle); 258c869993eSxy150489 tx_ring->tbd_area.dma_handle = NULL; 259c869993eSxy150489 } 260c869993eSxy150489 return (IGB_FAILURE); 261c869993eSxy150489 } 262c869993eSxy150489 263c869993eSxy150489 /* 264c869993eSxy150489 * Initialize the entire transmit buffer descriptor area to zero 265c869993eSxy150489 */ 266c869993eSxy150489 bzero(tx_ring->tbd_area.address, len); 267c869993eSxy150489 268c869993eSxy150489 /* 269c869993eSxy150489 * Allocates DMA resources for the memory that was allocated by 270c869993eSxy150489 * the ddi_dma_mem_alloc call. The DMA resources then get bound to the 271c869993eSxy150489 * the memory address 272c869993eSxy150489 */ 273c869993eSxy150489 ret = ddi_dma_addr_bind_handle(tx_ring->tbd_area.dma_handle, 274c869993eSxy150489 NULL, (caddr_t)tx_ring->tbd_area.address, 275c869993eSxy150489 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 276c869993eSxy150489 DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num); 277c869993eSxy150489 278c869993eSxy150489 if (ret != DDI_DMA_MAPPED) { 279*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 280c869993eSxy150489 "Could not bind tbd dma resource: %x", ret); 281c869993eSxy150489 tx_ring->tbd_area.dma_address = NULL; 282c869993eSxy150489 if (tx_ring->tbd_area.acc_handle != NULL) { 283c869993eSxy150489 ddi_dma_mem_free(&tx_ring->tbd_area.acc_handle); 284c869993eSxy150489 tx_ring->tbd_area.acc_handle = NULL; 285c869993eSxy150489 tx_ring->tbd_area.address = NULL; 286c869993eSxy150489 } 287c869993eSxy150489 if (tx_ring->tbd_area.dma_handle != NULL) { 288c869993eSxy150489 ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle); 289c869993eSxy150489 tx_ring->tbd_area.dma_handle = NULL; 290c869993eSxy150489 } 291c869993eSxy150489 return (IGB_FAILURE); 292c869993eSxy150489 } 293c869993eSxy150489 294c869993eSxy150489 ASSERT(cookie_num == 1); 295c869993eSxy150489 296c869993eSxy150489 tx_ring->tbd_area.dma_address = cookie.dmac_laddress; 297c869993eSxy150489 tx_ring->tbd_area.size = len; 298c869993eSxy150489 299c869993eSxy150489 tx_ring->tbd_ring = (union e1000_adv_tx_desc *)(uintptr_t) 300c869993eSxy150489 tx_ring->tbd_area.address; 301c869993eSxy150489 302c869993eSxy150489 return (IGB_SUCCESS); 303c869993eSxy150489 } 304c869993eSxy150489 305c869993eSxy150489 /* 306c869993eSxy150489 * igb_free_tbd_ring - Free the tx descriptors of one ring. 307c869993eSxy150489 */ 308c869993eSxy150489 static void 309c869993eSxy150489 igb_free_tbd_ring(igb_tx_ring_t *tx_ring) 310c869993eSxy150489 { 311c869993eSxy150489 if (tx_ring->tbd_area.dma_handle != NULL) { 312c869993eSxy150489 (void) ddi_dma_unbind_handle(tx_ring->tbd_area.dma_handle); 313c869993eSxy150489 } 314c869993eSxy150489 if (tx_ring->tbd_area.acc_handle != NULL) { 315c869993eSxy150489 ddi_dma_mem_free(&tx_ring->tbd_area.acc_handle); 316c869993eSxy150489 tx_ring->tbd_area.acc_handle = NULL; 317c869993eSxy150489 } 318c869993eSxy150489 if (tx_ring->tbd_area.dma_handle != NULL) { 319c869993eSxy150489 ddi_dma_free_handle(&tx_ring->tbd_area.dma_handle); 320c869993eSxy150489 tx_ring->tbd_area.dma_handle = NULL; 321c869993eSxy150489 } 322c869993eSxy150489 tx_ring->tbd_area.address = NULL; 323c869993eSxy150489 tx_ring->tbd_area.dma_address = NULL; 324c869993eSxy150489 tx_ring->tbd_area.size = 0; 325c869993eSxy150489 326c869993eSxy150489 tx_ring->tbd_ring = NULL; 327c869993eSxy150489 } 328c869993eSxy150489 329ac7f5757Schenlu chen - Sun Microsystems - Beijing China int 330ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_alloc_rx_ring_data(igb_rx_ring_t *rx_ring) 331ac7f5757Schenlu chen - Sun Microsystems - Beijing China { 332ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_rx_data_t *rx_data; 333ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_t *igb = rx_ring->igb; 334ac7f5757Schenlu chen - Sun Microsystems - Beijing China uint32_t rcb_count; 335ac7f5757Schenlu chen - Sun Microsystems - Beijing China 336ac7f5757Schenlu chen - Sun Microsystems - Beijing China /* 337ac7f5757Schenlu chen - Sun Microsystems - Beijing China * Allocate memory for software receive rings 338ac7f5757Schenlu chen - Sun Microsystems - Beijing China */ 339ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data = kmem_zalloc(sizeof (igb_rx_data_t), KM_NOSLEEP); 340ac7f5757Schenlu chen - Sun Microsystems - Beijing China 341ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data == NULL) { 342*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 343*e5513923SYuri Pankov "Allocate software receive rings failed"); 344ac7f5757Schenlu chen - Sun Microsystems - Beijing China return (IGB_FAILURE); 345ac7f5757Schenlu chen - Sun Microsystems - Beijing China } 346ac7f5757Schenlu chen - Sun Microsystems - Beijing China 347ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rx_ring = rx_ring; 348ac7f5757Schenlu chen - Sun Microsystems - Beijing China mutex_init(&rx_data->recycle_lock, NULL, 349ac7f5757Schenlu chen - Sun Microsystems - Beijing China MUTEX_DRIVER, DDI_INTR_PRI(igb->intr_pri)); 350ac7f5757Schenlu chen - Sun Microsystems - Beijing China 351ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->ring_size = igb->rx_ring_size; 352ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->free_list_size = igb->rx_ring_size; 353ac7f5757Schenlu chen - Sun Microsystems - Beijing China 354ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rcb_head = 0; 355ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rcb_tail = 0; 356ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rcb_free = rx_data->free_list_size; 357ac7f5757Schenlu chen - Sun Microsystems - Beijing China 358ac7f5757Schenlu chen - Sun Microsystems - Beijing China /* 359ac7f5757Schenlu chen - Sun Microsystems - Beijing China * Allocate memory for the work list. 360ac7f5757Schenlu chen - Sun Microsystems - Beijing China */ 361ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->work_list = kmem_zalloc(sizeof (rx_control_block_t *) * 362ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->ring_size, KM_NOSLEEP); 363ac7f5757Schenlu chen - Sun Microsystems - Beijing China 364ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data->work_list == NULL) { 365*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 366ac7f5757Schenlu chen - Sun Microsystems - Beijing China "Could not allocate memory for rx work list"); 367ac7f5757Schenlu chen - Sun Microsystems - Beijing China goto alloc_rx_data_failure; 368ac7f5757Schenlu chen - Sun Microsystems - Beijing China } 369ac7f5757Schenlu chen - Sun Microsystems - Beijing China 370ac7f5757Schenlu chen - Sun Microsystems - Beijing China /* 371ac7f5757Schenlu chen - Sun Microsystems - Beijing China * Allocate memory for the free list. 372ac7f5757Schenlu chen - Sun Microsystems - Beijing China */ 373ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->free_list = kmem_zalloc(sizeof (rx_control_block_t *) * 374ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->free_list_size, KM_NOSLEEP); 375ac7f5757Schenlu chen - Sun Microsystems - Beijing China 376ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data->free_list == NULL) { 377*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 378ac7f5757Schenlu chen - Sun Microsystems - Beijing China "Cound not allocate memory for rx free list"); 379ac7f5757Schenlu chen - Sun Microsystems - Beijing China goto alloc_rx_data_failure; 380ac7f5757Schenlu chen - Sun Microsystems - Beijing China } 381ac7f5757Schenlu chen - Sun Microsystems - Beijing China 382ac7f5757Schenlu chen - Sun Microsystems - Beijing China /* 383ac7f5757Schenlu chen - Sun Microsystems - Beijing China * Allocate memory for the rx control blocks for work list and 384ac7f5757Schenlu chen - Sun Microsystems - Beijing China * free list. 385ac7f5757Schenlu chen - Sun Microsystems - Beijing China */ 386ac7f5757Schenlu chen - Sun Microsystems - Beijing China rcb_count = rx_data->ring_size + rx_data->free_list_size; 387ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rcb_area = 388ac7f5757Schenlu chen - Sun Microsystems - Beijing China kmem_zalloc(sizeof (rx_control_block_t) * rcb_count, 389ac7f5757Schenlu chen - Sun Microsystems - Beijing China KM_NOSLEEP); 390ac7f5757Schenlu chen - Sun Microsystems - Beijing China 391ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data->rcb_area == NULL) { 392*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 393ac7f5757Schenlu chen - Sun Microsystems - Beijing China "Cound not allocate memory for rx control blocks"); 394ac7f5757Schenlu chen - Sun Microsystems - Beijing China goto alloc_rx_data_failure; 395ac7f5757Schenlu chen - Sun Microsystems - Beijing China } 396ac7f5757Schenlu chen - Sun Microsystems - Beijing China 397ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_ring->rx_data = rx_data; 398ac7f5757Schenlu chen - Sun Microsystems - Beijing China return (IGB_SUCCESS); 399ac7f5757Schenlu chen - Sun Microsystems - Beijing China 400ac7f5757Schenlu chen - Sun Microsystems - Beijing China alloc_rx_data_failure: 401ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_free_rx_ring_data(rx_data); 402ac7f5757Schenlu chen - Sun Microsystems - Beijing China return (IGB_FAILURE); 403ac7f5757Schenlu chen - Sun Microsystems - Beijing China } 404ac7f5757Schenlu chen - Sun Microsystems - Beijing China 405ac7f5757Schenlu chen - Sun Microsystems - Beijing China void 406ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_free_rx_ring_data(igb_rx_data_t *rx_data) 407ac7f5757Schenlu chen - Sun Microsystems - Beijing China { 408ac7f5757Schenlu chen - Sun Microsystems - Beijing China uint32_t rcb_count; 409ac7f5757Schenlu chen - Sun Microsystems - Beijing China 410ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data == NULL) 411ac7f5757Schenlu chen - Sun Microsystems - Beijing China return; 412ac7f5757Schenlu chen - Sun Microsystems - Beijing China 413ac7f5757Schenlu chen - Sun Microsystems - Beijing China ASSERT(rx_data->rcb_pending == 0); 414ac7f5757Schenlu chen - Sun Microsystems - Beijing China 415ac7f5757Schenlu chen - Sun Microsystems - Beijing China rcb_count = rx_data->ring_size + rx_data->free_list_size; 416ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data->rcb_area != NULL) { 417ac7f5757Schenlu chen - Sun Microsystems - Beijing China kmem_free(rx_data->rcb_area, 418ac7f5757Schenlu chen - Sun Microsystems - Beijing China sizeof (rx_control_block_t) * rcb_count); 419ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rcb_area = NULL; 420ac7f5757Schenlu chen - Sun Microsystems - Beijing China } 421ac7f5757Schenlu chen - Sun Microsystems - Beijing China 422ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data->work_list != NULL) { 423ac7f5757Schenlu chen - Sun Microsystems - Beijing China kmem_free(rx_data->work_list, 424ac7f5757Schenlu chen - Sun Microsystems - Beijing China sizeof (rx_control_block_t *) * rx_data->ring_size); 425ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->work_list = NULL; 426ac7f5757Schenlu chen - Sun Microsystems - Beijing China } 427ac7f5757Schenlu chen - Sun Microsystems - Beijing China 428ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data->free_list != NULL) { 429ac7f5757Schenlu chen - Sun Microsystems - Beijing China kmem_free(rx_data->free_list, 430ac7f5757Schenlu chen - Sun Microsystems - Beijing China sizeof (rx_control_block_t *) * rx_data->free_list_size); 431ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->free_list = NULL; 432ac7f5757Schenlu chen - Sun Microsystems - Beijing China } 433ac7f5757Schenlu chen - Sun Microsystems - Beijing China 434ac7f5757Schenlu chen - Sun Microsystems - Beijing China mutex_destroy(&rx_data->recycle_lock); 435ac7f5757Schenlu chen - Sun Microsystems - Beijing China kmem_free(rx_data, sizeof (igb_rx_data_t)); 436ac7f5757Schenlu chen - Sun Microsystems - Beijing China } 437ac7f5757Schenlu chen - Sun Microsystems - Beijing China 438c869993eSxy150489 /* 439c869993eSxy150489 * igb_alloc_rbd_ring - Memory allocation for the rx descriptors of one ring. 440c869993eSxy150489 */ 441c869993eSxy150489 static int 442ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_alloc_rbd_ring(igb_rx_data_t *rx_data) 443c869993eSxy150489 { 444c869993eSxy150489 int ret; 445c869993eSxy150489 size_t size; 446c869993eSxy150489 size_t len; 447c869993eSxy150489 uint_t cookie_num; 448c869993eSxy150489 dev_info_t *devinfo; 449c869993eSxy150489 ddi_dma_cookie_t cookie; 450ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_t *igb = rx_data->rx_ring->igb; 451c869993eSxy150489 452c869993eSxy150489 devinfo = igb->dip; 453ac7f5757Schenlu chen - Sun Microsystems - Beijing China size = sizeof (union e1000_adv_rx_desc) * rx_data->ring_size; 454c869993eSxy150489 455c869993eSxy150489 /* 456c869993eSxy150489 * Allocate a new DMA handle for the receive descriptor 457c869993eSxy150489 * memory area. 458c869993eSxy150489 */ 459c869993eSxy150489 ret = ddi_dma_alloc_handle(devinfo, &igb_desc_dma_attr, 460c869993eSxy150489 DDI_DMA_DONTWAIT, NULL, 461ac7f5757Schenlu chen - Sun Microsystems - Beijing China &rx_data->rbd_area.dma_handle); 462c869993eSxy150489 463c869993eSxy150489 if (ret != DDI_SUCCESS) { 464*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 465c869993eSxy150489 "Could not allocate rbd dma handle: %x", ret); 466ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_handle = NULL; 467c869993eSxy150489 return (IGB_FAILURE); 468c869993eSxy150489 } 469c869993eSxy150489 470c869993eSxy150489 /* 471c869993eSxy150489 * Allocate memory to DMA data to and from the receive 472c869993eSxy150489 * descriptors. 473c869993eSxy150489 */ 474ac7f5757Schenlu chen - Sun Microsystems - Beijing China ret = ddi_dma_mem_alloc(rx_data->rbd_area.dma_handle, 475c869993eSxy150489 size, &igb_desc_acc_attr, DDI_DMA_CONSISTENT, 476c869993eSxy150489 DDI_DMA_DONTWAIT, NULL, 477ac7f5757Schenlu chen - Sun Microsystems - Beijing China (caddr_t *)&rx_data->rbd_area.address, 478ac7f5757Schenlu chen - Sun Microsystems - Beijing China &len, &rx_data->rbd_area.acc_handle); 479c869993eSxy150489 480c869993eSxy150489 if (ret != DDI_SUCCESS) { 481*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 482c869993eSxy150489 "Could not allocate rbd dma memory: %x", ret); 483ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.acc_handle = NULL; 484ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.address = NULL; 485ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data->rbd_area.dma_handle != NULL) { 486ac7f5757Schenlu chen - Sun Microsystems - Beijing China ddi_dma_free_handle(&rx_data->rbd_area.dma_handle); 487ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_handle = NULL; 488c869993eSxy150489 } 489c869993eSxy150489 return (IGB_FAILURE); 490c869993eSxy150489 } 491c869993eSxy150489 492c869993eSxy150489 /* 493c869993eSxy150489 * Initialize the entire transmit buffer descriptor area to zero 494c869993eSxy150489 */ 495ac7f5757Schenlu chen - Sun Microsystems - Beijing China bzero(rx_data->rbd_area.address, len); 496c869993eSxy150489 497c869993eSxy150489 /* 498c869993eSxy150489 * Allocates DMA resources for the memory that was allocated by 499c869993eSxy150489 * the ddi_dma_mem_alloc call. 500c869993eSxy150489 */ 501ac7f5757Schenlu chen - Sun Microsystems - Beijing China ret = ddi_dma_addr_bind_handle(rx_data->rbd_area.dma_handle, 502ac7f5757Schenlu chen - Sun Microsystems - Beijing China NULL, (caddr_t)rx_data->rbd_area.address, 503c869993eSxy150489 len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 504c869993eSxy150489 DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num); 505c869993eSxy150489 506c869993eSxy150489 if (ret != DDI_DMA_MAPPED) { 507*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 508c869993eSxy150489 "Could not bind rbd dma resource: %x", ret); 509ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_address = NULL; 510ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data->rbd_area.acc_handle != NULL) { 511ac7f5757Schenlu chen - Sun Microsystems - Beijing China ddi_dma_mem_free(&rx_data->rbd_area.acc_handle); 512ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.acc_handle = NULL; 513ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.address = NULL; 514c869993eSxy150489 } 515ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data->rbd_area.dma_handle != NULL) { 516ac7f5757Schenlu chen - Sun Microsystems - Beijing China ddi_dma_free_handle(&rx_data->rbd_area.dma_handle); 517ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_handle = NULL; 518c869993eSxy150489 } 519c869993eSxy150489 return (IGB_FAILURE); 520c869993eSxy150489 } 521c869993eSxy150489 522c869993eSxy150489 ASSERT(cookie_num == 1); 523c869993eSxy150489 524ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_address = cookie.dmac_laddress; 525ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.size = len; 526c869993eSxy150489 527ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_ring = (union e1000_adv_rx_desc *)(uintptr_t) 528ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.address; 529c869993eSxy150489 530c869993eSxy150489 return (IGB_SUCCESS); 531c869993eSxy150489 } 532c869993eSxy150489 533c869993eSxy150489 /* 534c869993eSxy150489 * igb_free_rbd_ring - Free the rx descriptors of one ring. 535c869993eSxy150489 */ 536c869993eSxy150489 static void 537ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_free_rbd_ring(igb_rx_data_t *rx_data) 538c869993eSxy150489 { 539ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data->rbd_area.dma_handle != NULL) { 540ac7f5757Schenlu chen - Sun Microsystems - Beijing China (void) ddi_dma_unbind_handle(rx_data->rbd_area.dma_handle); 541c869993eSxy150489 } 542ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data->rbd_area.acc_handle != NULL) { 543ac7f5757Schenlu chen - Sun Microsystems - Beijing China ddi_dma_mem_free(&rx_data->rbd_area.acc_handle); 544ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.acc_handle = NULL; 545c869993eSxy150489 } 546ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (rx_data->rbd_area.dma_handle != NULL) { 547ac7f5757Schenlu chen - Sun Microsystems - Beijing China ddi_dma_free_handle(&rx_data->rbd_area.dma_handle); 548ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_handle = NULL; 549c869993eSxy150489 } 550ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.address = NULL; 551ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.dma_address = NULL; 552ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_area.size = 0; 553c869993eSxy150489 554ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->rbd_ring = NULL; 555c869993eSxy150489 } 556c869993eSxy150489 557c869993eSxy150489 558c869993eSxy150489 /* 559c869993eSxy150489 * igb_alloc_dma_buffer - Allocate DMA resources for a DMA buffer 560c869993eSxy150489 */ 561c869993eSxy150489 static int 562c869993eSxy150489 igb_alloc_dma_buffer(igb_t *igb, 563c869993eSxy150489 dma_buffer_t *buf, size_t size) 564c869993eSxy150489 { 565c869993eSxy150489 int ret; 566c869993eSxy150489 dev_info_t *devinfo = igb->dip; 567c869993eSxy150489 ddi_dma_cookie_t cookie; 568c869993eSxy150489 size_t len; 569c869993eSxy150489 uint_t cookie_num; 570c869993eSxy150489 571c869993eSxy150489 ret = ddi_dma_alloc_handle(devinfo, 572c869993eSxy150489 &igb_buf_dma_attr, DDI_DMA_DONTWAIT, 573c869993eSxy150489 NULL, &buf->dma_handle); 574c869993eSxy150489 575c869993eSxy150489 if (ret != DDI_SUCCESS) { 576c869993eSxy150489 buf->dma_handle = NULL; 577*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 578c869993eSxy150489 "Could not allocate dma buffer handle: %x", ret); 579c869993eSxy150489 return (IGB_FAILURE); 580c869993eSxy150489 } 581c869993eSxy150489 582c869993eSxy150489 ret = ddi_dma_mem_alloc(buf->dma_handle, 583c869993eSxy150489 size, &igb_buf_acc_attr, DDI_DMA_STREAMING, 584c869993eSxy150489 DDI_DMA_DONTWAIT, NULL, &buf->address, 585c869993eSxy150489 &len, &buf->acc_handle); 586c869993eSxy150489 587c869993eSxy150489 if (ret != DDI_SUCCESS) { 588c869993eSxy150489 buf->acc_handle = NULL; 589c869993eSxy150489 buf->address = NULL; 590c869993eSxy150489 if (buf->dma_handle != NULL) { 591c869993eSxy150489 ddi_dma_free_handle(&buf->dma_handle); 592c869993eSxy150489 buf->dma_handle = NULL; 593c869993eSxy150489 } 594*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 595c869993eSxy150489 "Could not allocate dma buffer memory: %x", ret); 596c869993eSxy150489 return (IGB_FAILURE); 597c869993eSxy150489 } 598c869993eSxy150489 599c869993eSxy150489 ret = ddi_dma_addr_bind_handle(buf->dma_handle, NULL, 600c869993eSxy150489 buf->address, 601c869993eSxy150489 len, DDI_DMA_RDWR | DDI_DMA_STREAMING, 602c869993eSxy150489 DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num); 603c869993eSxy150489 604c869993eSxy150489 if (ret != DDI_DMA_MAPPED) { 605c869993eSxy150489 buf->dma_address = NULL; 606c869993eSxy150489 if (buf->acc_handle != NULL) { 607c869993eSxy150489 ddi_dma_mem_free(&buf->acc_handle); 608c869993eSxy150489 buf->acc_handle = NULL; 609c869993eSxy150489 buf->address = NULL; 610c869993eSxy150489 } 611c869993eSxy150489 if (buf->dma_handle != NULL) { 612c869993eSxy150489 ddi_dma_free_handle(&buf->dma_handle); 613c869993eSxy150489 buf->dma_handle = NULL; 614c869993eSxy150489 } 615*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 616c869993eSxy150489 "Could not bind dma buffer handle: %x", ret); 617c869993eSxy150489 return (IGB_FAILURE); 618c869993eSxy150489 } 619c869993eSxy150489 620c869993eSxy150489 ASSERT(cookie_num == 1); 621c869993eSxy150489 622c869993eSxy150489 buf->dma_address = cookie.dmac_laddress; 623c869993eSxy150489 buf->size = len; 624c869993eSxy150489 buf->len = 0; 625c869993eSxy150489 626c869993eSxy150489 return (IGB_SUCCESS); 627c869993eSxy150489 } 628c869993eSxy150489 629c869993eSxy150489 /* 630c869993eSxy150489 * igb_free_dma_buffer - Free one allocated area of dma memory and handle 631c869993eSxy150489 */ 632ac7f5757Schenlu chen - Sun Microsystems - Beijing China void 633c869993eSxy150489 igb_free_dma_buffer(dma_buffer_t *buf) 634c869993eSxy150489 { 635c869993eSxy150489 if (buf->dma_handle != NULL) { 636c869993eSxy150489 (void) ddi_dma_unbind_handle(buf->dma_handle); 637c869993eSxy150489 buf->dma_address = NULL; 638c869993eSxy150489 } else { 639c869993eSxy150489 return; 640c869993eSxy150489 } 641c869993eSxy150489 642c869993eSxy150489 if (buf->acc_handle != NULL) { 643c869993eSxy150489 ddi_dma_mem_free(&buf->acc_handle); 644c869993eSxy150489 buf->acc_handle = NULL; 645c869993eSxy150489 buf->address = NULL; 646c869993eSxy150489 } 647c869993eSxy150489 648c869993eSxy150489 if (buf->dma_handle != NULL) { 649c869993eSxy150489 ddi_dma_free_handle(&buf->dma_handle); 650c869993eSxy150489 buf->dma_handle = NULL; 651c869993eSxy150489 } 652c869993eSxy150489 653c869993eSxy150489 buf->size = 0; 654c869993eSxy150489 buf->len = 0; 655c869993eSxy150489 } 656c869993eSxy150489 657c869993eSxy150489 /* 658c869993eSxy150489 * igb_alloc_tcb_lists - Memory allocation for the transmit control bolcks 659c869993eSxy150489 * of one ring. 660c869993eSxy150489 */ 661c869993eSxy150489 static int 662c869993eSxy150489 igb_alloc_tcb_lists(igb_tx_ring_t *tx_ring) 663c869993eSxy150489 { 664c869993eSxy150489 int i; 665c869993eSxy150489 int ret; 666c869993eSxy150489 tx_control_block_t *tcb; 667c869993eSxy150489 dma_buffer_t *tx_buf; 668c869993eSxy150489 igb_t *igb = tx_ring->igb; 669c869993eSxy150489 dev_info_t *devinfo = igb->dip; 670c869993eSxy150489 671c869993eSxy150489 /* 672c869993eSxy150489 * Allocate memory for the work list. 673c869993eSxy150489 */ 674c869993eSxy150489 tx_ring->work_list = kmem_zalloc(sizeof (tx_control_block_t *) * 675c869993eSxy150489 tx_ring->ring_size, KM_NOSLEEP); 676c869993eSxy150489 677c869993eSxy150489 if (tx_ring->work_list == NULL) { 678*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 679c869993eSxy150489 "Cound not allocate memory for tx work list"); 680c869993eSxy150489 return (IGB_FAILURE); 681c869993eSxy150489 } 682c869993eSxy150489 683c869993eSxy150489 /* 684c869993eSxy150489 * Allocate memory for the free list. 685c869993eSxy150489 */ 686c869993eSxy150489 tx_ring->free_list = kmem_zalloc(sizeof (tx_control_block_t *) * 687c869993eSxy150489 tx_ring->free_list_size, KM_NOSLEEP); 688c869993eSxy150489 689c869993eSxy150489 if (tx_ring->free_list == NULL) { 690c869993eSxy150489 kmem_free(tx_ring->work_list, 691c869993eSxy150489 sizeof (tx_control_block_t *) * tx_ring->ring_size); 692c869993eSxy150489 tx_ring->work_list = NULL; 693c869993eSxy150489 694*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 695c869993eSxy150489 "Cound not allocate memory for tx free list"); 696c869993eSxy150489 return (IGB_FAILURE); 697c869993eSxy150489 } 698c869993eSxy150489 699c869993eSxy150489 /* 700c869993eSxy150489 * Allocate memory for the tx control blocks of free list. 701c869993eSxy150489 */ 702c869993eSxy150489 tx_ring->tcb_area = 703c869993eSxy150489 kmem_zalloc(sizeof (tx_control_block_t) * 704c869993eSxy150489 tx_ring->free_list_size, KM_NOSLEEP); 705c869993eSxy150489 706c869993eSxy150489 if (tx_ring->tcb_area == NULL) { 707c869993eSxy150489 kmem_free(tx_ring->work_list, 708c869993eSxy150489 sizeof (tx_control_block_t *) * tx_ring->ring_size); 709c869993eSxy150489 tx_ring->work_list = NULL; 710c869993eSxy150489 711c869993eSxy150489 kmem_free(tx_ring->free_list, 712c869993eSxy150489 sizeof (tx_control_block_t *) * tx_ring->free_list_size); 713c869993eSxy150489 tx_ring->free_list = NULL; 714c869993eSxy150489 715*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 716c869993eSxy150489 "Cound not allocate memory for tx control blocks"); 717c869993eSxy150489 return (IGB_FAILURE); 718c869993eSxy150489 } 719c869993eSxy150489 720c869993eSxy150489 /* 721c869993eSxy150489 * Allocate dma memory for the tx control block of free list. 722c869993eSxy150489 */ 723c869993eSxy150489 tcb = tx_ring->tcb_area; 724c869993eSxy150489 for (i = 0; i < tx_ring->free_list_size; i++, tcb++) { 725c869993eSxy150489 ASSERT(tcb != NULL); 726c869993eSxy150489 727c869993eSxy150489 tx_ring->free_list[i] = tcb; 728c869993eSxy150489 729c869993eSxy150489 /* 730c869993eSxy150489 * Pre-allocate dma handles for transmit. These dma handles 731c869993eSxy150489 * will be dynamically bound to the data buffers passed down 732c869993eSxy150489 * from the upper layers at the time of transmitting. 733c869993eSxy150489 */ 734c869993eSxy150489 ret = ddi_dma_alloc_handle(devinfo, 735c869993eSxy150489 &igb_tx_dma_attr, 736c869993eSxy150489 DDI_DMA_DONTWAIT, NULL, 737c869993eSxy150489 &tcb->tx_dma_handle); 738c869993eSxy150489 if (ret != DDI_SUCCESS) { 739c869993eSxy150489 tcb->tx_dma_handle = NULL; 740*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 741c869993eSxy150489 "Could not allocate tx dma handle: %x", ret); 742c869993eSxy150489 goto alloc_tcb_lists_fail; 743c869993eSxy150489 } 744c869993eSxy150489 745c869993eSxy150489 /* 746c869993eSxy150489 * Pre-allocate transmit buffers for packets that the 747c869993eSxy150489 * size is less than bcopy_thresh. 748c869993eSxy150489 */ 749c869993eSxy150489 tx_buf = &tcb->tx_buf; 750c869993eSxy150489 751c869993eSxy150489 ret = igb_alloc_dma_buffer(igb, 752c869993eSxy150489 tx_buf, igb->tx_buf_size); 753c869993eSxy150489 754c869993eSxy150489 if (ret != IGB_SUCCESS) { 755c869993eSxy150489 ASSERT(tcb->tx_dma_handle != NULL); 756c869993eSxy150489 ddi_dma_free_handle(&tcb->tx_dma_handle); 757c869993eSxy150489 tcb->tx_dma_handle = NULL; 758*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 759*e5513923SYuri Pankov "Allocate tx dma buffer failed"); 760c869993eSxy150489 goto alloc_tcb_lists_fail; 761c869993eSxy150489 } 76269b2d733SGuoqing Zhu tcb->last_index = MAX_TX_RING_SIZE; 763c869993eSxy150489 } 764c869993eSxy150489 765c869993eSxy150489 return (IGB_SUCCESS); 766c869993eSxy150489 767c869993eSxy150489 alloc_tcb_lists_fail: 768c869993eSxy150489 igb_free_tcb_lists(tx_ring); 769c869993eSxy150489 770c869993eSxy150489 return (IGB_FAILURE); 771c869993eSxy150489 } 772c869993eSxy150489 773c869993eSxy150489 /* 774c869993eSxy150489 * igb_free_tcb_lists - Release the memory allocated for 775c869993eSxy150489 * the transmit control bolcks of one ring. 776c869993eSxy150489 */ 777c869993eSxy150489 static void 778c869993eSxy150489 igb_free_tcb_lists(igb_tx_ring_t *tx_ring) 779c869993eSxy150489 { 780c869993eSxy150489 int i; 781c869993eSxy150489 tx_control_block_t *tcb; 782c869993eSxy150489 783c869993eSxy150489 tcb = tx_ring->tcb_area; 784c869993eSxy150489 if (tcb == NULL) 785c869993eSxy150489 return; 786c869993eSxy150489 787c869993eSxy150489 for (i = 0; i < tx_ring->free_list_size; i++, tcb++) { 788c869993eSxy150489 ASSERT(tcb != NULL); 789c869993eSxy150489 790c869993eSxy150489 /* Free the tx dma handle for dynamical binding */ 791c869993eSxy150489 if (tcb->tx_dma_handle != NULL) { 792c869993eSxy150489 ddi_dma_free_handle(&tcb->tx_dma_handle); 793c869993eSxy150489 tcb->tx_dma_handle = NULL; 794c869993eSxy150489 } else { 795c869993eSxy150489 /* 796c869993eSxy150489 * If the dma handle is NULL, then we don't 797c869993eSxy150489 * have to check the remaining. 798c869993eSxy150489 */ 799c869993eSxy150489 break; 800c869993eSxy150489 } 801c869993eSxy150489 802c869993eSxy150489 igb_free_dma_buffer(&tcb->tx_buf); 803c869993eSxy150489 } 804c869993eSxy150489 805c869993eSxy150489 if (tx_ring->tcb_area != NULL) { 806c869993eSxy150489 kmem_free(tx_ring->tcb_area, 807c869993eSxy150489 sizeof (tx_control_block_t) * tx_ring->free_list_size); 808c869993eSxy150489 tx_ring->tcb_area = NULL; 809c869993eSxy150489 } 810c869993eSxy150489 811c869993eSxy150489 if (tx_ring->work_list != NULL) { 812c869993eSxy150489 kmem_free(tx_ring->work_list, 813c869993eSxy150489 sizeof (tx_control_block_t *) * tx_ring->ring_size); 814c869993eSxy150489 tx_ring->work_list = NULL; 815c869993eSxy150489 } 816c869993eSxy150489 817c869993eSxy150489 if (tx_ring->free_list != NULL) { 818c869993eSxy150489 kmem_free(tx_ring->free_list, 819c869993eSxy150489 sizeof (tx_control_block_t *) * tx_ring->free_list_size); 820c869993eSxy150489 tx_ring->free_list = NULL; 821c869993eSxy150489 } 822c869993eSxy150489 } 823c869993eSxy150489 824c869993eSxy150489 /* 825c869993eSxy150489 * igb_alloc_rcb_lists - Memory allocation for the receive control blocks 826c869993eSxy150489 * of one ring. 827c869993eSxy150489 */ 828c869993eSxy150489 static int 829ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_alloc_rcb_lists(igb_rx_data_t *rx_data) 830c869993eSxy150489 { 831c869993eSxy150489 int i; 832c869993eSxy150489 int ret; 833c869993eSxy150489 rx_control_block_t *rcb; 834ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_t *igb = rx_data->rx_ring->igb; 835c869993eSxy150489 dma_buffer_t *rx_buf; 836c869993eSxy150489 uint32_t rcb_count; 837c869993eSxy150489 838c869993eSxy150489 /* 839c869993eSxy150489 * Allocate memory for the rx control blocks for work list and 840c869993eSxy150489 * free list. 841c869993eSxy150489 */ 842ac7f5757Schenlu chen - Sun Microsystems - Beijing China rcb_count = rx_data->ring_size + rx_data->free_list_size; 843ac7f5757Schenlu chen - Sun Microsystems - Beijing China rcb = rx_data->rcb_area; 844c869993eSxy150489 845c869993eSxy150489 for (i = 0; i < rcb_count; i++, rcb++) { 846c869993eSxy150489 ASSERT(rcb != NULL); 847c869993eSxy150489 848ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (i < rx_data->ring_size) { 849c869993eSxy150489 /* Attach the rx control block to the work list */ 850ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->work_list[i] = rcb; 851c869993eSxy150489 } else { 852c869993eSxy150489 /* Attach the rx control block to the free list */ 853ac7f5757Schenlu chen - Sun Microsystems - Beijing China rx_data->free_list[i - rx_data->ring_size] = rcb; 854c869993eSxy150489 } 855c869993eSxy150489 856c869993eSxy150489 rx_buf = &rcb->rx_buf; 857c869993eSxy150489 ret = igb_alloc_dma_buffer(igb, 858c869993eSxy150489 rx_buf, igb->rx_buf_size); 859c869993eSxy150489 860c869993eSxy150489 if (ret != IGB_SUCCESS) { 861*e5513923SYuri Pankov igb_log(igb, IGB_LOG_ERROR, 862*e5513923SYuri Pankov "Allocate rx dma buffer failed"); 863c869993eSxy150489 goto alloc_rcb_lists_fail; 864c869993eSxy150489 } 865c869993eSxy150489 866c869993eSxy150489 rx_buf->size -= IPHDR_ALIGN_ROOM; 867c869993eSxy150489 rx_buf->address += IPHDR_ALIGN_ROOM; 868c869993eSxy150489 rx_buf->dma_address += IPHDR_ALIGN_ROOM; 869c869993eSxy150489 870ac7f5757Schenlu chen - Sun Microsystems - Beijing China rcb->ref_cnt = 1; 871ac7f5757Schenlu chen - Sun Microsystems - Beijing China rcb->rx_data = (igb_rx_data_t *)rx_data; 872c869993eSxy150489 rcb->free_rtn.free_func = igb_rx_recycle; 873c869993eSxy150489 rcb->free_rtn.free_arg = (char *)rcb; 874c869993eSxy150489 875c869993eSxy150489 rcb->mp = desballoc((unsigned char *) 87680a11ad2Schenlu chen - Sun Microsystems - Beijing China rx_buf->address, 87780a11ad2Schenlu chen - Sun Microsystems - Beijing China rx_buf->size, 878c869993eSxy150489 0, &rcb->free_rtn); 879c869993eSxy150489 } 880c869993eSxy150489 881c869993eSxy150489 return (IGB_SUCCESS); 882c869993eSxy150489 883c869993eSxy150489 alloc_rcb_lists_fail: 884ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_free_rcb_lists(rx_data); 885c869993eSxy150489 886c869993eSxy150489 return (IGB_FAILURE); 887c869993eSxy150489 } 888c869993eSxy150489 889c869993eSxy150489 /* 890c869993eSxy150489 * igb_free_rcb_lists - Free the receive control blocks of one ring. 891c869993eSxy150489 */ 892c869993eSxy150489 static void 893ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_free_rcb_lists(igb_rx_data_t *rx_data) 894c869993eSxy150489 { 895ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb_t *igb; 896c869993eSxy150489 rx_control_block_t *rcb; 897c869993eSxy150489 uint32_t rcb_count; 898ac7f5757Schenlu chen - Sun Microsystems - Beijing China uint32_t ref_cnt; 899ac7f5757Schenlu chen - Sun Microsystems - Beijing China int i; 900c869993eSxy150489 901ac7f5757Schenlu chen - Sun Microsystems - Beijing China igb = rx_data->rx_ring->igb; 902c869993eSxy150489 903ac7f5757Schenlu chen - Sun Microsystems - Beijing China mutex_enter(&igb->rx_pending_lock); 904ac7f5757Schenlu chen - Sun Microsystems - Beijing China 905ac7f5757Schenlu chen - Sun Microsystems - Beijing China rcb = rx_data->rcb_area; 906ac7f5757Schenlu chen - Sun Microsystems - Beijing China rcb_count = rx_data->ring_size + rx_data->free_list_size; 907ac7f5757Schenlu chen - Sun Microsystems - Beijing China 908c869993eSxy150489 for (i = 0; i < rcb_count; i++, rcb++) { 909c869993eSxy150489 ASSERT(rcb != NULL); 910c869993eSxy150489 911ac7f5757Schenlu chen - Sun Microsystems - Beijing China ref_cnt = atomic_dec_32_nv(&rcb->ref_cnt); 912ac7f5757Schenlu chen - Sun Microsystems - Beijing China if (ref_cnt == 0) { 913c869993eSxy150489 if (rcb->mp != NULL) { 914c869993eSxy150489 freemsg(rcb->mp); 915c869993eSxy150489 rcb->mp = NULL; 916c869993eSxy150489 } 917c869993eSxy150489 igb_free_dma_buffer(&rcb->rx_buf); 918ac7f5757Schenlu chen - Sun Microsystems - Beijing China } else { 919ac7f5757Schenlu chen - Sun Microsystems - Beijing China atomic_inc_32(&rx_data->rcb_pending); 920ac7f5757Schenlu chen - Sun Microsystems - Beijing China atomic_inc_32(&igb->rcb_pending); 921ac7f5757Schenlu chen - Sun Microsystems - Beijing China } 922c869993eSxy150489 } 923c869993eSxy150489 924ac7f5757Schenlu chen - Sun Microsystems - Beijing China mutex_exit(&igb->rx_pending_lock); 925c869993eSxy150489 } 9268bb4b220Sgl147354 9278bb4b220Sgl147354 void 928837c1ac4SStephen Hanson igb_set_fma_flags(int dma_flag) 9298bb4b220Sgl147354 { 9308bb4b220Sgl147354 if (dma_flag) { 9318bb4b220Sgl147354 igb_tx_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 9328bb4b220Sgl147354 igb_buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 9338bb4b220Sgl147354 igb_desc_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; 9348bb4b220Sgl147354 } else { 9358bb4b220Sgl147354 igb_tx_dma_attr.dma_attr_flags = 0; 9368bb4b220Sgl147354 igb_buf_dma_attr.dma_attr_flags = 0; 9378bb4b220Sgl147354 igb_desc_dma_attr.dma_attr_flags = 0; 9388bb4b220Sgl147354 } 9398bb4b220Sgl147354 } 940