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
igb_alloc_dma(igb_t * igb)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
igb_free_dma(igb_t * igb)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
igb_alloc_tbd_ring(igb_tx_ring_t * tx_ring)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*913f7a52SYuri 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*913f7a52SYuri 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*913f7a52SYuri 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
igb_free_tbd_ring(igb_tx_ring_t * tx_ring)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
igb_alloc_rx_ring_data(igb_rx_ring_t * rx_ring)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*913f7a52SYuri Pankov igb_log(igb, IGB_LOG_ERROR,
343*913f7a52SYuri 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*913f7a52SYuri 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*913f7a52SYuri 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*913f7a52SYuri 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
igb_free_rx_ring_data(igb_rx_data_t * rx_data)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
igb_alloc_rbd_ring(igb_rx_data_t * rx_data)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*913f7a52SYuri 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*913f7a52SYuri 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*913f7a52SYuri 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
igb_free_rbd_ring(igb_rx_data_t * rx_data)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
igb_alloc_dma_buffer(igb_t * igb,dma_buffer_t * buf,size_t size)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*913f7a52SYuri 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*913f7a52SYuri 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*913f7a52SYuri 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
igb_free_dma_buffer(dma_buffer_t * buf)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
igb_alloc_tcb_lists(igb_tx_ring_t * tx_ring)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*913f7a52SYuri 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*913f7a52SYuri 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*913f7a52SYuri 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*913f7a52SYuri 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*913f7a52SYuri Pankov igb_log(igb, IGB_LOG_ERROR,
759*913f7a52SYuri 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
igb_free_tcb_lists(igb_tx_ring_t * tx_ring)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
igb_alloc_rcb_lists(igb_rx_data_t * rx_data)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*913f7a52SYuri Pankov igb_log(igb, IGB_LOG_ERROR,
862*913f7a52SYuri 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
igb_free_rcb_lists(igb_rx_data_t * rx_data)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
igb_set_fma_flags(int dma_flag)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