1171095Ssam/*-
2171095Ssam * Copyright (c) 2002-2007 Neterion, Inc.
3171095Ssam * All rights reserved.
4171095Ssam *
5171095Ssam * Redistribution and use in source and binary forms, with or without
6171095Ssam * modification, are permitted provided that the following conditions
7171095Ssam * are met:
8171095Ssam * 1. Redistributions of source code must retain the above copyright
9171095Ssam *    notice, this list of conditions and the following disclaimer.
10171095Ssam * 2. Redistributions in binary form must reproduce the above copyright
11171095Ssam *    notice, this list of conditions and the following disclaimer in the
12171095Ssam *    documentation and/or other materials provided with the distribution.
13171095Ssam *
14171095Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15171095Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16171095Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17171095Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18171095Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19171095Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20171095Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21171095Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22171095Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23171095Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24171095Ssam * SUCH DAMAGE.
25171095Ssam *
26171095Ssam * $FreeBSD: releng/10.3/sys/dev/nxge/xgehal/xgehal-fifo.c 173139 2007-10-29 14:19:32Z rwatson $
27171095Ssam */
28171095Ssam
29171095Ssam#include <dev/nxge/include/xgehal-fifo.h>
30171095Ssam#include <dev/nxge/include/xgehal-device.h>
31171095Ssam
32171095Ssamstatic xge_hal_status_e
33171095Ssam__hal_fifo_mempool_item_alloc(xge_hal_mempool_h mempoolh,
34173139Srwatson	              void *memblock,
35173139Srwatson	              int memblock_index,
36173139Srwatson	              xge_hal_mempool_dma_t *dma_object,
37173139Srwatson	              void *item,
38173139Srwatson	              int index,
39173139Srwatson	              int is_last,
40173139Srwatson	              void *userdata)
41171095Ssam{
42171095Ssam	int memblock_item_idx;
43171095Ssam	xge_hal_fifo_txdl_priv_t *txdl_priv;
44171095Ssam	xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)item;
45171095Ssam	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)userdata;
46171095Ssam
47171095Ssam	xge_assert(item);
48171095Ssam	txdl_priv = (xge_hal_fifo_txdl_priv_t *) \
49173139Srwatson	            __hal_mempool_item_priv((xge_hal_mempool_t *) mempoolh,
50173139Srwatson	                                    memblock_index,
51173139Srwatson	                                    item,
52173139Srwatson	                                    &memblock_item_idx);
53171095Ssam	xge_assert(txdl_priv);
54171095Ssam
55171095Ssam	/* pre-format HAL's TxDL's private */
56171095Ssam	txdl_priv->dma_offset = (char*)item - (char*)memblock;
57171095Ssam	txdl_priv->dma_addr = dma_object->addr + txdl_priv->dma_offset;
58171095Ssam	txdl_priv->dma_handle = dma_object->handle;
59171095Ssam	txdl_priv->memblock   = memblock;
60171095Ssam	txdl_priv->first_txdp = (xge_hal_fifo_txd_t *)item;
61171095Ssam	txdl_priv->next_txdl_priv = NULL;
62171095Ssam	txdl_priv->dang_txdl = NULL;
63171095Ssam	txdl_priv->dang_frags = 0;
64171095Ssam	txdl_priv->alloc_frags = 0;
65171095Ssam
66171095Ssam#ifdef XGE_DEBUG_ASSERT
67171095Ssam	txdl_priv->dma_object = dma_object;
68171095Ssam#endif
69171095Ssam	txdp->host_control = (u64)(ulong_t)txdl_priv;
70171095Ssam
71171095Ssam#ifdef XGE_HAL_ALIGN_XMIT
72171095Ssam	txdl_priv->align_vaddr = NULL;
73171095Ssam	txdl_priv->align_dma_addr = (dma_addr_t)0;
74171095Ssam
75171095Ssam#ifndef XGE_HAL_ALIGN_XMIT_ALLOC_RT
76171095Ssam	{
77171095Ssam	xge_hal_status_e status;
78171095Ssam	if (fifo->config->alignment_size) {
79171095Ssam	        status =__hal_fifo_dtr_align_alloc_map(fifo, txdp);
80173139Srwatson	    if (status != XGE_HAL_OK)  {
81173139Srwatson	            xge_debug_mm(XGE_ERR,
82173139Srwatson	                  "align buffer[%d] %d bytes, status %d",
83173139Srwatson	              index,
84173139Srwatson	              fifo->align_size,
85173139Srwatson	              status);
86173139Srwatson	            return status;
87173139Srwatson	    }
88171095Ssam	}
89171095Ssam	}
90171095Ssam#endif
91171095Ssam#endif
92171095Ssam
93171095Ssam	if (fifo->channel.dtr_init) {
94173139Srwatson	    fifo->channel.dtr_init(fifo, (xge_hal_dtr_h)txdp, index,
95173139Srwatson	           fifo->channel.userdata, XGE_HAL_CHANNEL_OC_NORMAL);
96171095Ssam	}
97171095Ssam
98171095Ssam	return XGE_HAL_OK;
99171095Ssam}
100171095Ssam
101171095Ssam
102171095Ssamstatic xge_hal_status_e
103171095Ssam__hal_fifo_mempool_item_free(xge_hal_mempool_h mempoolh,
104173139Srwatson	              void *memblock,
105173139Srwatson	              int memblock_index,
106173139Srwatson	              xge_hal_mempool_dma_t *dma_object,
107173139Srwatson	              void *item,
108173139Srwatson	              int index,
109173139Srwatson	              int is_last,
110173139Srwatson	              void *userdata)
111171095Ssam{
112171095Ssam	int memblock_item_idx;
113171095Ssam	xge_hal_fifo_txdl_priv_t *txdl_priv;
114171095Ssam#ifdef XGE_HAL_ALIGN_XMIT
115171095Ssam	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)userdata;
116171095Ssam#endif
117171095Ssam
118171095Ssam	xge_assert(item);
119171095Ssam
120171095Ssam	txdl_priv = (xge_hal_fifo_txdl_priv_t *) \
121173139Srwatson	            __hal_mempool_item_priv((xge_hal_mempool_t *) mempoolh,
122173139Srwatson	                                    memblock_index,
123173139Srwatson	                                    item,
124173139Srwatson	                                    &memblock_item_idx);
125171095Ssam	xge_assert(txdl_priv);
126171095Ssam
127171095Ssam#ifdef XGE_HAL_ALIGN_XMIT
128171095Ssam	if (fifo->config->alignment_size) {
129173139Srwatson	    if (txdl_priv->align_dma_addr != 0) {
130173139Srwatson	        xge_os_dma_unmap(fifo->channel.pdev,
131173139Srwatson	               txdl_priv->align_dma_handle,
132173139Srwatson	               txdl_priv->align_dma_addr,
133173139Srwatson	               fifo->align_size,
134173139Srwatson	               XGE_OS_DMA_DIR_TODEVICE);
135171095Ssam
136173139Srwatson	        txdl_priv->align_dma_addr = 0;
137173139Srwatson	    }
138171095Ssam
139173139Srwatson	    if (txdl_priv->align_vaddr != NULL) {
140173139Srwatson	        xge_os_dma_free(fifo->channel.pdev,
141173139Srwatson	              txdl_priv->align_vaddr,
142173139Srwatson	              fifo->align_size,
143173139Srwatson	              &txdl_priv->align_dma_acch,
144173139Srwatson	              &txdl_priv->align_dma_handle);
145171095Ssam
146173139Srwatson	        txdl_priv->align_vaddr = NULL;
147173139Srwatson	    }
148171095Ssam	}
149171095Ssam#endif
150171095Ssam
151171095Ssam	return XGE_HAL_OK;
152171095Ssam}
153171095Ssam
154171095Ssamxge_hal_status_e
155171095Ssam__hal_fifo_open(xge_hal_channel_h channelh, xge_hal_channel_attr_t *attr)
156171095Ssam{
157171095Ssam	xge_hal_device_t *hldev;
158171095Ssam	xge_hal_status_e status;
159171095Ssam	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
160171095Ssam	xge_hal_fifo_queue_t *queue;
161171095Ssam	int i, txdl_size, max_arr_index, mid_point;
162171095Ssam	xge_hal_dtr_h  dtrh;
163171095Ssam
164171095Ssam	hldev = (xge_hal_device_t *)fifo->channel.devh;
165171095Ssam	fifo->config = &hldev->config.fifo;
166171095Ssam	queue = &fifo->config->queue[attr->post_qid];
167171095Ssam
168171095Ssam#if defined(XGE_HAL_TX_MULTI_RESERVE)
169171095Ssam	xge_os_spin_lock_init(&fifo->channel.reserve_lock, hldev->pdev);
170171095Ssam#elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
171171095Ssam	xge_os_spin_lock_init_irq(&fifo->channel.reserve_lock, hldev->irqh);
172171095Ssam#endif
173171095Ssam#if defined(XGE_HAL_TX_MULTI_POST)
174171095Ssam	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA)  {
175173139Srwatson	            fifo->post_lock_ptr = &hldev->xena_post_lock;
176171095Ssam	} else {
177171095Ssam	        xge_os_spin_lock_init(&fifo->channel.post_lock, hldev->pdev);
178173139Srwatson	            fifo->post_lock_ptr = &fifo->channel.post_lock;
179171095Ssam	}
180171095Ssam#elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
181171095Ssam	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA)  {
182173139Srwatson	            fifo->post_lock_ptr = &hldev->xena_post_lock;
183171095Ssam	} else {
184171095Ssam	        xge_os_spin_lock_init_irq(&fifo->channel.post_lock,
185173139Srwatson	                hldev->irqh);
186173139Srwatson	            fifo->post_lock_ptr = &fifo->channel.post_lock;
187171095Ssam	}
188171095Ssam#endif
189171095Ssam
190171095Ssam	fifo->align_size =
191173139Srwatson	    fifo->config->alignment_size * fifo->config->max_aligned_frags;
192171095Ssam
193171095Ssam	/* Initializing the BAR1 address as the start of
194171095Ssam	 * the FIFO queue pointer and as a location of FIFO control
195171095Ssam	 * word. */
196171095Ssam	fifo->hw_pair =
197171095Ssam	        (xge_hal_fifo_hw_pair_t *) (void *)(hldev->bar1 +
198173139Srwatson	            (attr->post_qid * XGE_HAL_FIFO_HW_PAIR_OFFSET));
199171095Ssam
200171095Ssam	/* apply "interrupts per txdl" attribute */
201171095Ssam	fifo->interrupt_type = XGE_HAL_TXD_INT_TYPE_UTILZ;
202171095Ssam	if (queue->intr) {
203173139Srwatson	    fifo->interrupt_type = XGE_HAL_TXD_INT_TYPE_PER_LIST;
204171095Ssam	}
205171095Ssam	fifo->no_snoop_bits =
206173139Srwatson	    (int)(XGE_HAL_TX_FIFO_NO_SNOOP(queue->no_snoop_bits));
207171095Ssam
208171095Ssam	/*
209171095Ssam	 * FIFO memory management strategy:
210171095Ssam	 *
211171095Ssam	 * TxDL splitted into three independent parts:
212173139Srwatson	 *  - set of TxD's
213173139Srwatson	 *  - TxD HAL private part
214173139Srwatson	 *  - upper layer private part
215171095Ssam	 *
216171095Ssam	 * Adaptative memory allocation used. i.e. Memory allocated on
217171095Ssam	 * demand with the size which will fit into one memory block.
218171095Ssam	 * One memory block may contain more than one TxDL. In simple case
219171095Ssam	 * memory block size can be equal to CPU page size. On more
220171095Ssam	 * sophisticated OS's memory block can be contigious across
221171095Ssam	 * several pages.
222171095Ssam	 *
223171095Ssam	 * During "reserve" operations more memory can be allocated on demand
224171095Ssam	 * for example due to FIFO full condition.
225171095Ssam	 *
226171095Ssam	 * Pool of memory memblocks never shrinks except __hal_fifo_close
227171095Ssam	 * routine which will essentially stop channel and free the resources.
228171095Ssam	 */
229171095Ssam
230171095Ssam	/* TxDL common private size == TxDL private + ULD private */
231171095Ssam	fifo->priv_size = sizeof(xge_hal_fifo_txdl_priv_t) +
232171095Ssam	attr->per_dtr_space;
233171095Ssam	fifo->priv_size = ((fifo->priv_size + __xge_os_cacheline_size -1) /
234173139Srwatson	                           __xge_os_cacheline_size) *
235173139Srwatson	                           __xge_os_cacheline_size;
236171095Ssam
237171095Ssam	/* recompute txdl size to be cacheline aligned */
238171095Ssam	fifo->txdl_size = fifo->config->max_frags * sizeof(xge_hal_fifo_txd_t);
239171095Ssam	txdl_size = ((fifo->txdl_size + __xge_os_cacheline_size - 1) /
240173139Srwatson	        __xge_os_cacheline_size) * __xge_os_cacheline_size;
241171095Ssam
242171095Ssam	if (fifo->txdl_size != txdl_size)
243171095Ssam	        xge_debug_fifo(XGE_ERR, "cacheline > 128 ( ?? ): %d, %d, %d, %d",
244173139Srwatson	    fifo->config->max_frags, fifo->txdl_size, txdl_size,
245173139Srwatson	    __xge_os_cacheline_size);
246171095Ssam
247171095Ssam	fifo->txdl_size = txdl_size;
248171095Ssam
249171095Ssam	/* since dtr_init() callback will be called from item_alloc(),
250171095Ssam	 * the same way channels userdata might be used prior to
251171095Ssam	 * channel_initialize() */
252171095Ssam	fifo->channel.dtr_init = attr->dtr_init;
253171095Ssam	fifo->channel.userdata = attr->userdata;
254171095Ssam	fifo->txdl_per_memblock = fifo->config->memblock_size /
255173139Srwatson	    fifo->txdl_size;
256171095Ssam
257171095Ssam	fifo->mempool = __hal_mempool_create(hldev->pdev,
258173139Srwatson	                     fifo->config->memblock_size,
259173139Srwatson	                     fifo->txdl_size,
260173139Srwatson	                     fifo->priv_size,
261173139Srwatson	                     queue->initial,
262173139Srwatson	                     queue->max,
263173139Srwatson	                     __hal_fifo_mempool_item_alloc,
264173139Srwatson	                     __hal_fifo_mempool_item_free,
265173139Srwatson	                     fifo);
266171095Ssam	if (fifo->mempool == NULL) {
267173139Srwatson	    return XGE_HAL_ERR_OUT_OF_MEMORY;
268171095Ssam	}
269171095Ssam
270171095Ssam	status = __hal_channel_initialize(channelh, attr,
271173139Srwatson	                (void **) __hal_mempool_items_arr(fifo->mempool),
272173139Srwatson	                queue->initial, queue->max,
273173139Srwatson	                fifo->config->reserve_threshold);
274171095Ssam	if (status != XGE_HAL_OK) {
275173139Srwatson	    __hal_fifo_close(channelh);
276173139Srwatson	    return status;
277171095Ssam	}
278171095Ssam	xge_debug_fifo(XGE_TRACE,
279173139Srwatson	    "DTR  reserve_length:%d reserve_top:%d\n"
280173139Srwatson	    "max_frags:%d reserve_threshold:%d\n"
281173139Srwatson	    "memblock_size:%d alignment_size:%d max_aligned_frags:%d",
282173139Srwatson	    fifo->channel.reserve_length, fifo->channel.reserve_top,
283173139Srwatson	    fifo->config->max_frags, fifo->config->reserve_threshold,
284173139Srwatson	    fifo->config->memblock_size, fifo->config->alignment_size,
285173139Srwatson	    fifo->config->max_aligned_frags);
286171095Ssam
287171095Ssam#ifdef XGE_DEBUG_ASSERT
288171095Ssam	for ( i = 0; i < fifo->channel.reserve_length; i++) {
289173139Srwatson	    xge_debug_fifo(XGE_TRACE, "DTR before reversing index:%d"
290173139Srwatson	    " handle:%p", i, fifo->channel.reserve_arr[i]);
291171095Ssam	}
292171095Ssam#endif
293171095Ssam
294171095Ssam	xge_assert(fifo->channel.reserve_length);
295171095Ssam	/* reverse the FIFO dtr array */
296173139Srwatson	max_arr_index   = fifo->channel.reserve_length - 1;
297173139Srwatson	max_arr_index   -=fifo->channel.reserve_top;
298171095Ssam	xge_assert(max_arr_index);
299171095Ssam	mid_point = (fifo->channel.reserve_length - fifo->channel.reserve_top)/2;
300171095Ssam	for (i = 0; i < mid_point; i++) {
301173139Srwatson	    dtrh =  fifo->channel.reserve_arr[i];
302173139Srwatson	    fifo->channel.reserve_arr[i] =
303173139Srwatson	        fifo->channel.reserve_arr[max_arr_index - i];
304173139Srwatson	    fifo->channel.reserve_arr[max_arr_index  - i] = dtrh;
305171095Ssam	}
306171095Ssam
307171095Ssam#ifdef XGE_DEBUG_ASSERT
308171095Ssam	for ( i = 0; i < fifo->channel.reserve_length; i++) {
309173139Srwatson	    xge_debug_fifo(XGE_TRACE, "DTR after reversing index:%d"
310173139Srwatson	    " handle:%p", i, fifo->channel.reserve_arr[i]);
311171095Ssam	}
312171095Ssam#endif
313171095Ssam
314171095Ssam	return XGE_HAL_OK;
315171095Ssam}
316171095Ssam
317171095Ssamvoid
318171095Ssam__hal_fifo_close(xge_hal_channel_h channelh)
319171095Ssam{
320171095Ssam	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
321171095Ssam	xge_hal_device_t *hldev = (xge_hal_device_t *)fifo->channel.devh;
322171095Ssam
323171095Ssam	if (fifo->mempool) {
324173139Srwatson	    __hal_mempool_destroy(fifo->mempool);
325171095Ssam	}
326171095Ssam
327171095Ssam	__hal_channel_terminate(channelh);
328171095Ssam
329171095Ssam#if defined(XGE_HAL_TX_MULTI_RESERVE)
330171095Ssam	xge_os_spin_lock_destroy(&fifo->channel.reserve_lock, hldev->pdev);
331171095Ssam#elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
332171095Ssam	xge_os_spin_lock_destroy_irq(&fifo->channel.reserve_lock, hldev->pdev);
333171095Ssam#endif
334171095Ssam	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)  {
335171095Ssam#if defined(XGE_HAL_TX_MULTI_POST)
336173139Srwatson	    xge_os_spin_lock_destroy(&fifo->channel.post_lock, hldev->pdev);
337171095Ssam#elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
338173139Srwatson	    xge_os_spin_lock_destroy_irq(&fifo->channel.post_lock,
339173139Srwatson	                     hldev->pdev);
340171095Ssam#endif
341171095Ssam	}
342171095Ssam}
343171095Ssam
344171095Ssamvoid
345171095Ssam__hal_fifo_hw_initialize(xge_hal_device_h devh)
346171095Ssam{
347171095Ssam	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
348171095Ssam	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
349171095Ssam	u64* tx_fifo_partitions[4];
350171095Ssam	u64* tx_fifo_wrr[5];
351171095Ssam	u64  tx_fifo_wrr_value[5];
352171095Ssam	u64 val64, part0;
353171095Ssam	int i;
354171095Ssam
355171095Ssam	/*  Tx DMA Initialization */
356171095Ssam
357171095Ssam	tx_fifo_partitions[0] = &bar0->tx_fifo_partition_0;
358171095Ssam	tx_fifo_partitions[1] = &bar0->tx_fifo_partition_1;
359171095Ssam	tx_fifo_partitions[2] = &bar0->tx_fifo_partition_2;
360171095Ssam	tx_fifo_partitions[3] = &bar0->tx_fifo_partition_3;
361171095Ssam
362171095Ssam	tx_fifo_wrr[0] = &bar0->tx_w_round_robin_0;
363171095Ssam	tx_fifo_wrr[1] = &bar0->tx_w_round_robin_1;
364171095Ssam	tx_fifo_wrr[2] = &bar0->tx_w_round_robin_2;
365171095Ssam	tx_fifo_wrr[3] = &bar0->tx_w_round_robin_3;
366171095Ssam	tx_fifo_wrr[4] = &bar0->tx_w_round_robin_4;
367171095Ssam
368171095Ssam	tx_fifo_wrr_value[0] = XGE_HAL_FIFO_WRR_0;
369171095Ssam	tx_fifo_wrr_value[1] = XGE_HAL_FIFO_WRR_1;
370171095Ssam	tx_fifo_wrr_value[2] = XGE_HAL_FIFO_WRR_2;
371171095Ssam	tx_fifo_wrr_value[3] = XGE_HAL_FIFO_WRR_3;
372171095Ssam	tx_fifo_wrr_value[4] = XGE_HAL_FIFO_WRR_4;
373171095Ssam
374171095Ssam	/* Note: WRR calendar must be configured before the transmit
375171095Ssam	 *       FIFOs are enabled! page 6-77 user guide */
376171095Ssam
377171095Ssam	if (!hldev->config.rts_qos_en) {
378173139Srwatson	    /* all zeroes for Round-Robin */
379173139Srwatson	    for (i = 0; i < XGE_HAL_FIFO_MAX_WRR; i++) {
380173139Srwatson	        xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0,
381173139Srwatson	                       tx_fifo_wrr[i]);
382173139Srwatson	    }
383171095Ssam
384173139Srwatson	    /* reset all of them but '0' */
385173139Srwatson	    for (i=1; i < XGE_HAL_FIFO_MAX_PARTITION; i++) {
386173139Srwatson	        xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0ULL,
387173139Srwatson	                       tx_fifo_partitions[i]);
388173139Srwatson	    }
389171095Ssam	} else { /* Change the default settings */
390171095Ssam
391173139Srwatson	    for (i = 0; i < XGE_HAL_FIFO_MAX_WRR; i++) {
392173139Srwatson	        xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
393173139Srwatson	                   tx_fifo_wrr_value[i], tx_fifo_wrr[i]);
394173139Srwatson	    }
395171095Ssam	}
396171095Ssam
397171095Ssam	/* configure only configured FIFOs */
398171095Ssam	val64 = 0; part0 = 0;
399171095Ssam	for (i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) {
400173139Srwatson	    int reg_half = i % 2;
401173139Srwatson	    int reg_num = i / 2;
402171095Ssam
403173139Srwatson	    if (hldev->config.fifo.queue[i].configured) {
404173139Srwatson	        int priority = hldev->config.fifo.queue[i].priority;
405173139Srwatson	        val64 |=
406173139Srwatson	            vBIT((hldev->config.fifo.queue[i].max-1),
407173139Srwatson	            (((reg_half) * 32) + 19),
408173139Srwatson	            13) | vBIT(priority, (((reg_half)*32) + 5), 3);
409173139Srwatson	    }
410171095Ssam
411173139Srwatson	    /* NOTE: do write operation for each second u64 half
412173139Srwatson	     *       or force for first one if configured number
413173139Srwatson	     *   is even */
414173139Srwatson	    if (reg_half) {
415173139Srwatson	        if (reg_num == 0) {
416173139Srwatson	            /* skip partition '0', must write it once at
417173139Srwatson	             * the end */
418173139Srwatson	            part0 = val64;
419173139Srwatson	        } else {
420173139Srwatson	            xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
421173139Srwatson	                 val64, tx_fifo_partitions[reg_num]);
422173139Srwatson	            xge_debug_fifo(XGE_TRACE,
423173139Srwatson	                "fifo partition_%d at: "
424173139Srwatson	                "0x"XGE_OS_LLXFMT" is: 0x"XGE_OS_LLXFMT,
425173139Srwatson	                reg_num, (unsigned long long)(ulong_t)
426173139Srwatson	                tx_fifo_partitions[reg_num],
427173139Srwatson	                (unsigned long long)val64);
428173139Srwatson	        }
429173139Srwatson	        val64 = 0;
430173139Srwatson	    }
431171095Ssam	}
432171095Ssam
433171095Ssam	part0 |= BIT(0); /* to enable the FIFO partition. */
434171095Ssam	__hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, (u32)part0,
435171095Ssam	                     tx_fifo_partitions[0]);
436171095Ssam	xge_os_wmb();
437171095Ssam	__hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, (u32)(part0>>32),
438171095Ssam	                     tx_fifo_partitions[0]);
439171095Ssam	xge_debug_fifo(XGE_TRACE, "fifo partition_0 at: "
440173139Srwatson	        "0x"XGE_OS_LLXFMT" is: 0x"XGE_OS_LLXFMT,
441173139Srwatson	        (unsigned long long)(ulong_t)
442173139Srwatson	            tx_fifo_partitions[0],
443173139Srwatson	        (unsigned long long) part0);
444171095Ssam
445171095Ssam	/*
446171095Ssam	 * Initialization of Tx_PA_CONFIG register to ignore packet
447171095Ssam	 * integrity checking.
448171095Ssam	 */
449171095Ssam	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
450171095Ssam	                            &bar0->tx_pa_cfg);
451171095Ssam	val64 |= XGE_HAL_TX_PA_CFG_IGNORE_FRM_ERR |
452173139Srwatson	     XGE_HAL_TX_PA_CFG_IGNORE_SNAP_OUI |
453173139Srwatson	     XGE_HAL_TX_PA_CFG_IGNORE_LLC_CTRL |
454173139Srwatson	     XGE_HAL_TX_PA_CFG_IGNORE_L2_ERR;
455171095Ssam	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
456171095Ssam	                     &bar0->tx_pa_cfg);
457171095Ssam
458171095Ssam	/*
459171095Ssam	 * Assign MSI-X vectors
460171095Ssam	 */
461171095Ssam	for (i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) {
462173139Srwatson	    xge_list_t *item;
463173139Srwatson	    xge_hal_channel_t *channel = NULL;
464171095Ssam
465173139Srwatson	    if (!hldev->config.fifo.queue[i].configured ||
466173139Srwatson	        !hldev->config.fifo.queue[i].intr_vector ||
467173139Srwatson	        !hldev->config.intr_mode != XGE_HAL_INTR_MODE_MSIX)
468173139Srwatson	        continue;
469171095Ssam
470173139Srwatson	    /* find channel */
471173139Srwatson	    xge_list_for_each(item, &hldev->free_channels) {
472173139Srwatson	        xge_hal_channel_t *tmp;
473173139Srwatson	        tmp = xge_container_of(item, xge_hal_channel_t,
474173139Srwatson	                       item);
475173139Srwatson	        if (tmp->type == XGE_HAL_CHANNEL_TYPE_FIFO &&
476173139Srwatson	            tmp->post_qid == i) {
477173139Srwatson	            channel = tmp;
478173139Srwatson	            break;
479173139Srwatson	        }
480173139Srwatson	    }
481171095Ssam
482173139Srwatson	    if (channel) {
483173139Srwatson	        xge_hal_channel_msix_set(channel,
484173139Srwatson	            hldev->config.fifo.queue[i].intr_vector);
485173139Srwatson	    }
486171095Ssam	}
487171095Ssam
488171095Ssam	xge_debug_fifo(XGE_TRACE, "%s", "fifo channels initialized");
489171095Ssam}
490171095Ssam
491171095Ssam#ifdef XGE_HAL_ALIGN_XMIT
492171095Ssamvoid
493171095Ssam__hal_fifo_dtr_align_free_unmap(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh)
494171095Ssam{
495173139Srwatson	    xge_hal_fifo_txdl_priv_t *txdl_priv;
496171095Ssam	xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh;
497171095Ssam	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
498171095Ssam
499171095Ssam	txdl_priv = __hal_fifo_txdl_priv(txdp);
500171095Ssam
501171095Ssam	if (txdl_priv->align_dma_addr != 0) {
502173139Srwatson	    xge_os_dma_unmap(fifo->channel.pdev,
503173139Srwatson	           txdl_priv->align_dma_handle,
504173139Srwatson	           txdl_priv->align_dma_addr,
505173139Srwatson	           fifo->align_size,
506173139Srwatson	           XGE_OS_DMA_DIR_TODEVICE);
507171095Ssam
508173139Srwatson	            txdl_priv->align_dma_addr = 0;
509171095Ssam	}
510171095Ssam
511173139Srwatson	    if (txdl_priv->align_vaddr != NULL) {
512171095Ssam	        xge_os_dma_free(fifo->channel.pdev,
513171095Ssam	              txdl_priv->align_vaddr,
514171095Ssam	              fifo->align_size,
515171095Ssam	              &txdl_priv->align_dma_acch,
516171095Ssam	              &txdl_priv->align_dma_handle);
517171095Ssam
518171095Ssam
519171095Ssam	        txdl_priv->align_vaddr = NULL;
520173139Srwatson	    }
521171095Ssam }
522171095Ssam
523171095Ssamxge_hal_status_e
524171095Ssam__hal_fifo_dtr_align_alloc_map(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh)
525171095Ssam{
526173139Srwatson	    xge_hal_fifo_txdl_priv_t *txdl_priv;
527171095Ssam	xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh;
528171095Ssam	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
529171095Ssam
530171095Ssam	xge_assert(txdp);
531171095Ssam
532171095Ssam	txdl_priv = __hal_fifo_txdl_priv(txdp);
533171095Ssam
534171095Ssam	/* allocate alignment DMA-buffer */
535173139Srwatson	txdl_priv->align_vaddr = (char *)xge_os_dma_malloc(fifo->channel.pdev,
536173139Srwatson	            fifo->align_size,
537173139Srwatson	            XGE_OS_DMA_CACHELINE_ALIGNED |
538173139Srwatson	            XGE_OS_DMA_STREAMING,
539173139Srwatson	            &txdl_priv->align_dma_handle,
540173139Srwatson	            &txdl_priv->align_dma_acch);
541171095Ssam	if (txdl_priv->align_vaddr == NULL) {
542173139Srwatson	    return XGE_HAL_ERR_OUT_OF_MEMORY;
543171095Ssam	}
544171095Ssam
545171095Ssam	/* map it */
546171095Ssam	txdl_priv->align_dma_addr = xge_os_dma_map(fifo->channel.pdev,
547173139Srwatson	    txdl_priv->align_dma_handle, txdl_priv->align_vaddr,
548173139Srwatson	    fifo->align_size,
549173139Srwatson	    XGE_OS_DMA_DIR_TODEVICE, XGE_OS_DMA_STREAMING);
550171095Ssam
551171095Ssam	if (txdl_priv->align_dma_addr == XGE_OS_INVALID_DMA_ADDR) {
552173139Srwatson	            __hal_fifo_dtr_align_free_unmap(channelh, dtrh);
553173139Srwatson	    return XGE_HAL_ERR_OUT_OF_MAPPING;
554171095Ssam	}
555171095Ssam
556171095Ssam	return XGE_HAL_OK;
557171095Ssam}
558171095Ssam#endif
559171095Ssam
560171095Ssam
561