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