xref: /onnv-gate/usr/src/uts/common/io/xge/hal/xgehal/xgehal-fifo.c (revision 6937:a5e2c8b5c817)
11256Syl150051 /*
21256Syl150051  * CDDL HEADER START
31256Syl150051  *
41256Syl150051  * The contents of this file are subject to the terms of the
51256Syl150051  * Common Development and Distribution License (the "License").
61256Syl150051  * You may not use this file except in compliance with the License.
71256Syl150051  *
81256Syl150051  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91256Syl150051  * or http://www.opensolaris.org/os/licensing.
101256Syl150051  * See the License for the specific language governing permissions
111256Syl150051  * and limitations under the License.
121256Syl150051  *
131256Syl150051  * When distributing Covered Code, include this CDDL HEADER in each
141256Syl150051  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151256Syl150051  * If applicable, add the following below this CDDL HEADER, with the
161256Syl150051  * fields enclosed by brackets "[]" replaced with your own identifying
171256Syl150051  * information: Portions Copyright [yyyy] [name of copyright owner]
181256Syl150051  *
191256Syl150051  * CDDL HEADER END
201256Syl150051  *
213115Syl150051  * Copyright (c) 2002-2006 Neterion, Inc.
221256Syl150051  */
231256Syl150051 
241256Syl150051 #include "xgehal-fifo.h"
251256Syl150051 #include "xgehal-device.h"
261256Syl150051 
271256Syl150051 static xge_hal_status_e
__hal_fifo_mempool_item_alloc(xge_hal_mempool_h mempoolh,void * memblock,int memblock_index,xge_hal_mempool_dma_t * dma_object,void * item,int index,int is_last,void * userdata)281256Syl150051 __hal_fifo_mempool_item_alloc(xge_hal_mempool_h mempoolh,
291256Syl150051 			      void *memblock,
301256Syl150051 			      int memblock_index,
311256Syl150051 			      xge_hal_mempool_dma_t *dma_object,
321256Syl150051 			      void *item,
331256Syl150051 			      int index,
341256Syl150051 			      int is_last,
351256Syl150051 			      void *userdata)
361256Syl150051 {
371256Syl150051 	int memblock_item_idx;
381256Syl150051 	xge_hal_fifo_txdl_priv_t *txdl_priv;
391256Syl150051 	xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)item;
401256Syl150051 	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)userdata;
411256Syl150051 
421256Syl150051 	xge_assert(item);
433115Syl150051 	txdl_priv = (xge_hal_fifo_txdl_priv_t *) \
443115Syl150051                 __hal_mempool_item_priv((xge_hal_mempool_t *) mempoolh,
453115Syl150051                                         memblock_index,
463115Syl150051                                         item,
473115Syl150051                                         &memblock_item_idx);
481256Syl150051 	xge_assert(txdl_priv);
491256Syl150051 
501256Syl150051 	/* pre-format HAL's TxDL's private */
511256Syl150051 	txdl_priv->dma_offset = (char*)item - (char*)memblock;
521256Syl150051 	txdl_priv->dma_addr = dma_object->addr + txdl_priv->dma_offset;
531256Syl150051 	txdl_priv->dma_handle = dma_object->handle;
541256Syl150051 	txdl_priv->memblock   = memblock;
551256Syl150051 	txdl_priv->first_txdp = (xge_hal_fifo_txd_t *)item;
561256Syl150051 	txdl_priv->next_txdl_priv = NULL;
571256Syl150051 	txdl_priv->dang_txdl = NULL;
581256Syl150051 	txdl_priv->dang_frags = 0;
591256Syl150051 	txdl_priv->alloc_frags = 0;
601256Syl150051 
611256Syl150051 #ifdef XGE_DEBUG_ASSERT
621256Syl150051 	txdl_priv->dma_object = dma_object;
631256Syl150051 #endif
641256Syl150051 	txdp->host_control = (u64)(ulong_t)txdl_priv;
651256Syl150051 
661256Syl150051 #ifdef XGE_HAL_ALIGN_XMIT
671256Syl150051 	txdl_priv->align_vaddr = NULL;
681256Syl150051 	txdl_priv->align_dma_addr = (dma_addr_t)0;
691256Syl150051 
701256Syl150051 #ifndef XGE_HAL_ALIGN_XMIT_ALLOC_RT
711256Syl150051 	{
721256Syl150051 	xge_hal_status_e status;
731256Syl150051 	if (fifo->config->alignment_size) {
741256Syl150051 	        status =__hal_fifo_dtr_align_alloc_map(fifo, txdp);
751256Syl150051 		if (status != XGE_HAL_OK)  {
761256Syl150051 		        xge_debug_mm(XGE_ERR,
771256Syl150051 		              "align buffer[%d] %d bytes, status %d",
781256Syl150051 			      index,
793115Syl150051 			      fifo->align_size,
801256Syl150051 			      status);
811256Syl150051 		        return status;
821256Syl150051 		}
831256Syl150051 	}
841256Syl150051 	}
851256Syl150051 #endif
861256Syl150051 #endif
871256Syl150051 
881256Syl150051 	if (fifo->channel.dtr_init) {
891256Syl150051 		fifo->channel.dtr_init(fifo, (xge_hal_dtr_h)txdp, index,
901256Syl150051 			   fifo->channel.userdata, XGE_HAL_CHANNEL_OC_NORMAL);
911256Syl150051 	}
921256Syl150051 
931256Syl150051 	return XGE_HAL_OK;
941256Syl150051 }
951256Syl150051 
961256Syl150051 
971256Syl150051 static xge_hal_status_e
__hal_fifo_mempool_item_free(xge_hal_mempool_h mempoolh,void * memblock,int memblock_index,xge_hal_mempool_dma_t * dma_object,void * item,int index,int is_last,void * userdata)981256Syl150051 __hal_fifo_mempool_item_free(xge_hal_mempool_h mempoolh,
991256Syl150051 			      void *memblock,
1001256Syl150051 			      int memblock_index,
1011256Syl150051 			      xge_hal_mempool_dma_t *dma_object,
1021256Syl150051 			      void *item,
1031256Syl150051 			      int index,
1041256Syl150051 			      int is_last,
1051256Syl150051 			      void *userdata)
1061256Syl150051 {
1071256Syl150051 	int memblock_item_idx;
1081256Syl150051 	xge_hal_fifo_txdl_priv_t *txdl_priv;
1091256Syl150051 #ifdef XGE_HAL_ALIGN_XMIT
1101256Syl150051 	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)userdata;
1111256Syl150051 #endif
1121256Syl150051 
1131256Syl150051 	xge_assert(item);
1141256Syl150051 
1153115Syl150051 	txdl_priv = (xge_hal_fifo_txdl_priv_t *) \
1163115Syl150051                 __hal_mempool_item_priv((xge_hal_mempool_t *) mempoolh,
1173115Syl150051                                         memblock_index,
1183115Syl150051                                         item,
1193115Syl150051                                         &memblock_item_idx);
1201256Syl150051 	xge_assert(txdl_priv);
1211256Syl150051 
1221256Syl150051 #ifdef XGE_HAL_ALIGN_XMIT
1231256Syl150051 	if (fifo->config->alignment_size) {
1241256Syl150051 		if (txdl_priv->align_dma_addr != 0) {
1251256Syl150051 			xge_os_dma_unmap(fifo->channel.pdev,
1261256Syl150051 			       txdl_priv->align_dma_handle,
1271256Syl150051 			       txdl_priv->align_dma_addr,
1283115Syl150051 			       fifo->align_size,
1291256Syl150051 			       XGE_OS_DMA_DIR_TODEVICE);
1301256Syl150051 
1311256Syl150051 			txdl_priv->align_dma_addr = 0;
1321256Syl150051 		}
1331256Syl150051 
1341256Syl150051 		if (txdl_priv->align_vaddr != NULL) {
1351256Syl150051 			xge_os_dma_free(fifo->channel.pdev,
1361256Syl150051 			      txdl_priv->align_vaddr,
1373115Syl150051 			      fifo->align_size,
1381256Syl150051 			      &txdl_priv->align_dma_acch,
1391256Syl150051 			      &txdl_priv->align_dma_handle);
1401256Syl150051 
1411256Syl150051 			txdl_priv->align_vaddr = NULL;
1421256Syl150051 		}
1431256Syl150051 	}
1441256Syl150051 #endif
1451256Syl150051 
1461256Syl150051 	return XGE_HAL_OK;
1471256Syl150051 }
1481256Syl150051 
1491256Syl150051 xge_hal_status_e
__hal_fifo_open(xge_hal_channel_h channelh,xge_hal_channel_attr_t * attr)1501256Syl150051 __hal_fifo_open(xge_hal_channel_h channelh, xge_hal_channel_attr_t *attr)
1511256Syl150051 {
1521256Syl150051 	xge_hal_device_t *hldev;
1531256Syl150051 	xge_hal_status_e status;
1541256Syl150051 	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
1551256Syl150051 	xge_hal_fifo_queue_t *queue;
1561256Syl150051 	int i, txdl_size, max_arr_index, mid_point;
1571256Syl150051 	xge_hal_dtr_h  dtrh;
1581256Syl150051 
1591256Syl150051 	hldev = (xge_hal_device_t *)fifo->channel.devh;
1601256Syl150051 	fifo->config = &hldev->config.fifo;
1611256Syl150051 	queue = &fifo->config->queue[attr->post_qid];
1621256Syl150051 
1631256Syl150051 #if defined(XGE_HAL_TX_MULTI_RESERVE)
1641256Syl150051 	xge_os_spin_lock_init(&fifo->channel.reserve_lock, hldev->pdev);
1651256Syl150051 #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
1661256Syl150051 	xge_os_spin_lock_init_irq(&fifo->channel.reserve_lock, hldev->irqh);
1671256Syl150051 #endif
1681256Syl150051 #if defined(XGE_HAL_TX_MULTI_POST)
1691256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA)  {
1701256Syl150051                 fifo->post_lock_ptr = &hldev->xena_post_lock;
1711256Syl150051 	} else {
1721256Syl150051 	        xge_os_spin_lock_init(&fifo->channel.post_lock, hldev->pdev);
1731256Syl150051                 fifo->post_lock_ptr = &fifo->channel.post_lock;
1741256Syl150051 	}
1751256Syl150051 #elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
1761256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA)  {
1771256Syl150051                 fifo->post_lock_ptr = &hldev->xena_post_lock;
1781256Syl150051 	} else {
1791256Syl150051 	        xge_os_spin_lock_init_irq(&fifo->channel.post_lock,
1801256Syl150051 					hldev->irqh);
1811256Syl150051                 fifo->post_lock_ptr = &fifo->channel.post_lock;
1821256Syl150051 	}
1831256Syl150051 #endif
1841256Syl150051 
1853115Syl150051 	fifo->align_size =
1863115Syl150051 		fifo->config->alignment_size * fifo->config->max_aligned_frags;
1873115Syl150051 
1881256Syl150051 	/* Initializing the BAR1 address as the start of
1891256Syl150051 	 * the FIFO queue pointer and as a location of FIFO control
1901256Syl150051 	 * word. */
1911256Syl150051 	fifo->hw_pair =
1921256Syl150051 	        (xge_hal_fifo_hw_pair_t *) (void *)(hldev->bar1 +
1931256Syl150051 		        (attr->post_qid * XGE_HAL_FIFO_HW_PAIR_OFFSET));
1941256Syl150051 
1951256Syl150051 	/* apply "interrupts per txdl" attribute */
1961256Syl150051 	fifo->interrupt_type = XGE_HAL_TXD_INT_TYPE_UTILZ;
1971256Syl150051 	if (queue->intr) {
1981256Syl150051 		fifo->interrupt_type = XGE_HAL_TXD_INT_TYPE_PER_LIST;
1991256Syl150051 	}
2001256Syl150051 	fifo->no_snoop_bits =
2011256Syl150051 		(int)(XGE_HAL_TX_FIFO_NO_SNOOP(queue->no_snoop_bits));
2021256Syl150051 
2031256Syl150051 	/*
2041256Syl150051 	 * FIFO memory management strategy:
2051256Syl150051 	 *
2061256Syl150051 	 * TxDL splitted into three independent parts:
2071256Syl150051 	 *	- set of TxD's
2081256Syl150051 	 *	- TxD HAL private part
2091256Syl150051 	 *	- upper layer private part
2101256Syl150051 	 *
2111256Syl150051 	 * Adaptative memory allocation used. i.e. Memory allocated on
2121256Syl150051 	 * demand with the size which will fit into one memory block.
2131256Syl150051 	 * One memory block may contain more than one TxDL. In simple case
2141256Syl150051 	 * memory block size can be equal to CPU page size. On more
2151256Syl150051 	 * sophisticated OS's memory block can be contigious across
2161256Syl150051 	 * several pages.
2171256Syl150051 	 *
2181256Syl150051 	 * During "reserve" operations more memory can be allocated on demand
2191256Syl150051 	 * for example due to FIFO full condition.
2201256Syl150051 	 *
2211256Syl150051 	 * Pool of memory memblocks never shrinks except __hal_fifo_close
2221256Syl150051 	 * routine which will essentially stop channel and free the resources.
2231256Syl150051 	 */
2241256Syl150051 
2251256Syl150051 	/* TxDL common private size == TxDL private + ULD private */
2261256Syl150051 	fifo->priv_size = sizeof(xge_hal_fifo_txdl_priv_t) +
2271256Syl150051 	attr->per_dtr_space;
2281256Syl150051 	fifo->priv_size = ((fifo->priv_size + __xge_os_cacheline_size -1) /
2291256Syl150051                                __xge_os_cacheline_size) *
2301256Syl150051                                __xge_os_cacheline_size;
2311256Syl150051 
2321256Syl150051 	/* recompute txdl size to be cacheline aligned */
2331256Syl150051 	fifo->txdl_size = fifo->config->max_frags * sizeof(xge_hal_fifo_txd_t);
2341256Syl150051 	txdl_size = ((fifo->txdl_size + __xge_os_cacheline_size - 1) /
2351256Syl150051 			__xge_os_cacheline_size) * __xge_os_cacheline_size;
2361256Syl150051 
2371256Syl150051 	if (fifo->txdl_size != txdl_size)
238*6937Sxw161283 	        xge_debug_fifo(XGE_ERR, "cacheline > 128 ( ?? ): %d, %d, %d, %d",
2391256Syl150051 		fifo->config->max_frags, fifo->txdl_size, txdl_size,
2401256Syl150051 		__xge_os_cacheline_size);
2411256Syl150051 
2421256Syl150051 	fifo->txdl_size = txdl_size;
2431256Syl150051 
2441256Syl150051 	/* since dtr_init() callback will be called from item_alloc(),
2451256Syl150051 	 * the same way channels userdata might be used prior to
2461256Syl150051 	 * channel_initialize() */
2471256Syl150051 	fifo->channel.dtr_init = attr->dtr_init;
2481256Syl150051 	fifo->channel.userdata = attr->userdata;
2491256Syl150051 	fifo->txdl_per_memblock = fifo->config->memblock_size /
2501256Syl150051 		fifo->txdl_size;
2511256Syl150051 
2521256Syl150051 	fifo->mempool = __hal_mempool_create(hldev->pdev,
2531256Syl150051 					     fifo->config->memblock_size,
2541256Syl150051 					     fifo->txdl_size,
2551256Syl150051 					     fifo->priv_size,
2561256Syl150051 					     queue->initial,
2571256Syl150051 					     queue->max,
2581256Syl150051 					     __hal_fifo_mempool_item_alloc,
2591256Syl150051 					     __hal_fifo_mempool_item_free,
2601256Syl150051 					     fifo);
2611256Syl150051 	if (fifo->mempool == NULL) {
2621256Syl150051 		return XGE_HAL_ERR_OUT_OF_MEMORY;
2631256Syl150051 	}
2641256Syl150051 
2651256Syl150051 	status = __hal_channel_initialize(channelh, attr,
2663115Syl150051 					(void **) __hal_mempool_items_arr(fifo->mempool),
2671256Syl150051 					queue->initial, queue->max,
2681256Syl150051 					fifo->config->reserve_threshold);
2691256Syl150051 	if (status != XGE_HAL_OK) {
2701256Syl150051 		__hal_fifo_close(channelh);
2711256Syl150051 		return status;
2721256Syl150051 	}
2731256Syl150051 	xge_debug_fifo(XGE_TRACE,
2741256Syl150051 		"DTR  reserve_length:%d reserve_top:%d\n"
2751256Syl150051 		"max_frags:%d reserve_threshold:%d\n"
276*6937Sxw161283 		"memblock_size:%d alignment_size:%d max_aligned_frags:%d",
2771256Syl150051 		fifo->channel.reserve_length, fifo->channel.reserve_top,
2781256Syl150051 		fifo->config->max_frags, fifo->config->reserve_threshold,
2791256Syl150051 		fifo->config->memblock_size, fifo->config->alignment_size,
2801256Syl150051 		fifo->config->max_aligned_frags);
2811256Syl150051 
2821256Syl150051 #ifdef XGE_DEBUG_ASSERT
2831256Syl150051 	for ( i = 0; i < fifo->channel.reserve_length; i++) {
2841256Syl150051 		xge_debug_fifo(XGE_TRACE, "DTR before reversing index:%d"
285*6937Sxw161283 		" handle:%p", i, fifo->channel.reserve_arr[i]);
2861256Syl150051 	}
2871256Syl150051 #endif
2881256Syl150051 
2891256Syl150051 	xge_assert(fifo->channel.reserve_length);
2901256Syl150051 	/* reverse the FIFO dtr array */
2911256Syl150051 	max_arr_index	= fifo->channel.reserve_length - 1;
2921256Syl150051 	max_arr_index	-=fifo->channel.reserve_top;
2931256Syl150051 	xge_assert(max_arr_index);
2941256Syl150051 	mid_point = (fifo->channel.reserve_length - fifo->channel.reserve_top)/2;
2951256Syl150051 	for (i = 0; i < mid_point; i++) {
296*6937Sxw161283 		dtrh =	fifo->channel.reserve_arr[i];
297*6937Sxw161283 		fifo->channel.reserve_arr[i] =
2981256Syl150051 			fifo->channel.reserve_arr[max_arr_index - i];
2991256Syl150051 		fifo->channel.reserve_arr[max_arr_index  - i] = dtrh;
3001256Syl150051 	}
3011256Syl150051 
3021256Syl150051 #ifdef XGE_DEBUG_ASSERT
3031256Syl150051 	for ( i = 0; i < fifo->channel.reserve_length; i++) {
3041256Syl150051 		xge_debug_fifo(XGE_TRACE, "DTR after reversing index:%d"
305*6937Sxw161283 		" handle:%p", i, fifo->channel.reserve_arr[i]);
3061256Syl150051 	}
3071256Syl150051 #endif
3081256Syl150051 
3091256Syl150051 	return XGE_HAL_OK;
3101256Syl150051 }
3111256Syl150051 
3121256Syl150051 void
__hal_fifo_close(xge_hal_channel_h channelh)3131256Syl150051 __hal_fifo_close(xge_hal_channel_h channelh)
3141256Syl150051 {
3151256Syl150051 	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
3161256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)fifo->channel.devh;
3171256Syl150051 
3181256Syl150051 	if (fifo->mempool) {
3191256Syl150051 		__hal_mempool_destroy(fifo->mempool);
3201256Syl150051 	}
3211256Syl150051 
3221256Syl150051 	__hal_channel_terminate(channelh);
3231256Syl150051 
3241256Syl150051 #if defined(XGE_HAL_TX_MULTI_RESERVE)
3251256Syl150051 	xge_os_spin_lock_destroy(&fifo->channel.reserve_lock, hldev->pdev);
3261256Syl150051 #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
3271256Syl150051 	xge_os_spin_lock_destroy_irq(&fifo->channel.reserve_lock, hldev->pdev);
3281256Syl150051 #endif
3291256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)  {
3301256Syl150051 #if defined(XGE_HAL_TX_MULTI_POST)
3311256Syl150051 		xge_os_spin_lock_destroy(&fifo->channel.post_lock, hldev->pdev);
3321256Syl150051 #elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
3331256Syl150051 		xge_os_spin_lock_destroy_irq(&fifo->channel.post_lock,
3341256Syl150051 					     hldev->pdev);
3351256Syl150051 #endif
3361256Syl150051 	}
3371256Syl150051 }
3381256Syl150051 
3391256Syl150051 void
__hal_fifo_hw_initialize(xge_hal_device_h devh)3401256Syl150051 __hal_fifo_hw_initialize(xge_hal_device_h devh)
3411256Syl150051 {
3421256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
343*6937Sxw161283 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
3441256Syl150051 	u64* tx_fifo_partitions[4];
3451256Syl150051 	u64* tx_fifo_wrr[5];
346*6937Sxw161283 	u64  tx_fifo_wrr_value[5];
3471256Syl150051 	u64 val64, part0;
3481256Syl150051 	int i;
3491256Syl150051 
3501256Syl150051 	/*  Tx DMA Initialization */
3511256Syl150051 
3521256Syl150051 	tx_fifo_partitions[0] = &bar0->tx_fifo_partition_0;
3531256Syl150051 	tx_fifo_partitions[1] = &bar0->tx_fifo_partition_1;
3541256Syl150051 	tx_fifo_partitions[2] = &bar0->tx_fifo_partition_2;
3551256Syl150051 	tx_fifo_partitions[3] = &bar0->tx_fifo_partition_3;
3561256Syl150051 
3571256Syl150051 	tx_fifo_wrr[0] = &bar0->tx_w_round_robin_0;
3581256Syl150051 	tx_fifo_wrr[1] = &bar0->tx_w_round_robin_1;
3591256Syl150051 	tx_fifo_wrr[2] = &bar0->tx_w_round_robin_2;
3601256Syl150051 	tx_fifo_wrr[3] = &bar0->tx_w_round_robin_3;
3611256Syl150051 	tx_fifo_wrr[4] = &bar0->tx_w_round_robin_4;
3621256Syl150051 
363*6937Sxw161283 	tx_fifo_wrr_value[0] = XGE_HAL_FIFO_WRR_0;
364*6937Sxw161283 	tx_fifo_wrr_value[1] = XGE_HAL_FIFO_WRR_1;
365*6937Sxw161283 	tx_fifo_wrr_value[2] = XGE_HAL_FIFO_WRR_2;
366*6937Sxw161283 	tx_fifo_wrr_value[3] = XGE_HAL_FIFO_WRR_3;
367*6937Sxw161283 	tx_fifo_wrr_value[4] = XGE_HAL_FIFO_WRR_4;
368*6937Sxw161283 
3691256Syl150051 	/* Note: WRR calendar must be configured before the transmit
370*6937Sxw161283 	 *       FIFOs are enabled! page 6-77 user guide */
3711256Syl150051 
372*6937Sxw161283 	if (!hldev->config.rts_qos_en) {
373*6937Sxw161283 		/* all zeroes for Round-Robin */
374*6937Sxw161283 		for (i = 0; i < XGE_HAL_FIFO_MAX_WRR; i++) {
375*6937Sxw161283 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0,
376*6937Sxw161283 					       tx_fifo_wrr[i]);
377*6937Sxw161283 		}
3781256Syl150051 
379*6937Sxw161283 		/* reset all of them but '0' */
380*6937Sxw161283 		for (i=1; i < XGE_HAL_FIFO_MAX_PARTITION; i++) {
381*6937Sxw161283 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0ULL,
382*6937Sxw161283 					       tx_fifo_partitions[i]);
383*6937Sxw161283 		}
384*6937Sxw161283 	} else { /* Change the default settings */
385*6937Sxw161283 
386*6937Sxw161283 		for (i = 0; i < XGE_HAL_FIFO_MAX_WRR; i++) {
387*6937Sxw161283 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
388*6937Sxw161283 				       tx_fifo_wrr_value[i], tx_fifo_wrr[i]);
389*6937Sxw161283 		}
3901256Syl150051 	}
3911256Syl150051 
3921256Syl150051 	/* configure only configured FIFOs */
3931256Syl150051 	val64 = 0; part0 = 0;
3941256Syl150051 	for (i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) {
3951256Syl150051 		int reg_half = i % 2;
3961256Syl150051 		int reg_num = i / 2;
3971256Syl150051 
3981256Syl150051 		if (hldev->config.fifo.queue[i].configured) {
3993115Syl150051 			int priority = hldev->config.fifo.queue[i].priority;
4001256Syl150051 			val64 |=
4011256Syl150051 			    vBIT((hldev->config.fifo.queue[i].max-1),
4021256Syl150051 				(((reg_half) * 32) + 19),
4031256Syl150051 				13) | vBIT(priority, (((reg_half)*32) + 5), 3);
4041256Syl150051 		}
4051256Syl150051 
4061256Syl150051 		/* NOTE: do write operation for each second u64 half
407*6937Sxw161283 		 *       or force for first one if configured number
408*6937Sxw161283 		 *	 is even */
4091256Syl150051 		if (reg_half) {
4101256Syl150051 			if (reg_num == 0) {
4111256Syl150051 				/* skip partition '0', must write it once at
4121256Syl150051 				 * the end */
4131256Syl150051 				part0 = val64;
4141256Syl150051 			} else {
4151256Syl150051 				xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
4161256Syl150051 				     val64, tx_fifo_partitions[reg_num]);
4171256Syl150051 				xge_debug_fifo(XGE_TRACE,
4181256Syl150051 					"fifo partition_%d at: "
4193115Syl150051 					"0x"XGE_OS_LLXFMT" is: 0x"XGE_OS_LLXFMT,
4203115Syl150051 					reg_num, (unsigned long long)(ulong_t)
4213115Syl150051 					tx_fifo_partitions[reg_num],
4221256Syl150051 					(unsigned long long)val64);
4231256Syl150051 			}
4241256Syl150051 			val64 = 0;
4251256Syl150051 		}
4261256Syl150051 	}
4271256Syl150051 
4281256Syl150051 	part0 |= BIT(0); /* to enable the FIFO partition. */
4291256Syl150051 	__hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, (u32)part0,
4301256Syl150051 	                     tx_fifo_partitions[0]);
4311256Syl150051 	xge_os_wmb();
4321256Syl150051 	__hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, (u32)(part0>>32),
4331256Syl150051 	                     tx_fifo_partitions[0]);
4341256Syl150051 	xge_debug_fifo(XGE_TRACE, "fifo partition_0 at: "
4353115Syl150051 			"0x"XGE_OS_LLXFMT" is: 0x"XGE_OS_LLXFMT,
4361256Syl150051 			(unsigned long long)(ulong_t)
4371256Syl150051 				tx_fifo_partitions[0],
4381256Syl150051 			(unsigned long long) part0);
4391256Syl150051 
4401256Syl150051 	/*
4411256Syl150051 	 * Initialization of Tx_PA_CONFIG register to ignore packet
4421256Syl150051 	 * integrity checking.
4431256Syl150051 	 */
4441256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
4451256Syl150051 	                            &bar0->tx_pa_cfg);
4461256Syl150051 	val64 |= XGE_HAL_TX_PA_CFG_IGNORE_FRM_ERR |
4471256Syl150051 		 XGE_HAL_TX_PA_CFG_IGNORE_SNAP_OUI |
4481256Syl150051 		 XGE_HAL_TX_PA_CFG_IGNORE_LLC_CTRL |
4491256Syl150051 		 XGE_HAL_TX_PA_CFG_IGNORE_L2_ERR;
4501256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
4511256Syl150051 	                     &bar0->tx_pa_cfg);
452*6937Sxw161283 
453*6937Sxw161283 	if (hldev->config.intr_mode != XGE_HAL_INTR_MODE_MSIX)
454*6937Sxw161283 		return;
455*6937Sxw161283 
456*6937Sxw161283 	/*
457*6937Sxw161283 	 * Assign MSI-X vectors
458*6937Sxw161283 	 */
459*6937Sxw161283 	for (i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) {
460*6937Sxw161283 		xge_list_t *item;
461*6937Sxw161283 		xge_hal_channel_t *channel = NULL;
462*6937Sxw161283 
463*6937Sxw161283 		if (!hldev->config.fifo.queue[i].configured ||
464*6937Sxw161283 		    !hldev->config.fifo.queue[i].intr_vector)
465*6937Sxw161283 			continue;
466*6937Sxw161283 
467*6937Sxw161283 		/* find channel */
468*6937Sxw161283 		xge_list_for_each(item, &hldev->free_channels) {
469*6937Sxw161283 			xge_hal_channel_t *tmp;
470*6937Sxw161283 			tmp = xge_container_of(item, xge_hal_channel_t,
471*6937Sxw161283 						   item);
472*6937Sxw161283 			if (tmp->type == XGE_HAL_CHANNEL_TYPE_FIFO &&
473*6937Sxw161283 			    tmp->post_qid == i) {
474*6937Sxw161283 				channel = tmp;
475*6937Sxw161283 				break;
476*6937Sxw161283 			}
477*6937Sxw161283 		}
478*6937Sxw161283 
479*6937Sxw161283 		if (channel) {
480*6937Sxw161283 			(void) xge_hal_channel_msix_set(channel,
481*6937Sxw161283 				hldev->config.fifo.queue[i].intr_vector);
482*6937Sxw161283 		}
483*6937Sxw161283 	}
484*6937Sxw161283 
4851256Syl150051 	xge_debug_fifo(XGE_TRACE, "%s", "fifo channels initialized");
4861256Syl150051 }
4871256Syl150051 
4881256Syl150051 #ifdef XGE_HAL_ALIGN_XMIT
4891256Syl150051 void
__hal_fifo_dtr_align_free_unmap(xge_hal_channel_h channelh,xge_hal_dtr_h dtrh)4901256Syl150051 __hal_fifo_dtr_align_free_unmap(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh)
4911256Syl150051 {
4921256Syl150051         xge_hal_fifo_txdl_priv_t *txdl_priv;
4931256Syl150051 	xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh;
4941256Syl150051 	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
4951256Syl150051 
4961256Syl150051 	txdl_priv = __hal_fifo_txdl_priv(txdp);
4971256Syl150051 
4981256Syl150051 	if (txdl_priv->align_dma_addr != 0) {
4991256Syl150051 		xge_os_dma_unmap(fifo->channel.pdev,
5001256Syl150051 		       txdl_priv->align_dma_handle,
5011256Syl150051 		       txdl_priv->align_dma_addr,
5023115Syl150051 		       fifo->align_size,
5031256Syl150051 		       XGE_OS_DMA_DIR_TODEVICE);
5041256Syl150051 
5051256Syl150051                 txdl_priv->align_dma_addr = 0;
5061256Syl150051 	}
5071256Syl150051 
5081256Syl150051         if (txdl_priv->align_vaddr != NULL) {
5091256Syl150051 	        xge_os_dma_free(fifo->channel.pdev,
5101256Syl150051 	              txdl_priv->align_vaddr,
5113115Syl150051 	              fifo->align_size,
5121256Syl150051 	              &txdl_priv->align_dma_acch,
5131256Syl150051 	              &txdl_priv->align_dma_handle);
5141256Syl150051 
5151256Syl150051 
5161256Syl150051 	        txdl_priv->align_vaddr = NULL;
5171256Syl150051         }
5181256Syl150051  }
5191256Syl150051 
5201256Syl150051 xge_hal_status_e
__hal_fifo_dtr_align_alloc_map(xge_hal_channel_h channelh,xge_hal_dtr_h dtrh)5211256Syl150051 __hal_fifo_dtr_align_alloc_map(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh)
5221256Syl150051 {
5231256Syl150051         xge_hal_fifo_txdl_priv_t *txdl_priv;
5241256Syl150051 	xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh;
5251256Syl150051 	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
5261256Syl150051 
5271256Syl150051 	xge_assert(txdp);
5281256Syl150051 
5291256Syl150051 	txdl_priv = __hal_fifo_txdl_priv(txdp);
5301256Syl150051 
5311256Syl150051 	/* allocate alignment DMA-buffer */
532*6937Sxw161283 	txdl_priv->align_vaddr = (char *)xge_os_dma_malloc(fifo->channel.pdev,
5333115Syl150051 				fifo->align_size,
5341256Syl150051 				XGE_OS_DMA_CACHELINE_ALIGNED |
5351256Syl150051 				XGE_OS_DMA_STREAMING,
5361256Syl150051 				&txdl_priv->align_dma_handle,
5371256Syl150051 				&txdl_priv->align_dma_acch);
5381256Syl150051 	if (txdl_priv->align_vaddr == NULL) {
5391256Syl150051 		return XGE_HAL_ERR_OUT_OF_MEMORY;
5401256Syl150051 	}
5411256Syl150051 
5421256Syl150051 	/* map it */
5431256Syl150051 	txdl_priv->align_dma_addr = xge_os_dma_map(fifo->channel.pdev,
5441256Syl150051 		txdl_priv->align_dma_handle, txdl_priv->align_vaddr,
5453115Syl150051 		fifo->align_size,
5461256Syl150051 		XGE_OS_DMA_DIR_TODEVICE, XGE_OS_DMA_STREAMING);
5471256Syl150051 
5481256Syl150051 	if (txdl_priv->align_dma_addr == XGE_OS_INVALID_DMA_ADDR) {
5491256Syl150051                 __hal_fifo_dtr_align_free_unmap(channelh, dtrh);
5501256Syl150051 		return XGE_HAL_ERR_OUT_OF_MAPPING;
5511256Syl150051 	}
5521256Syl150051 
5531256Syl150051 	return XGE_HAL_OK;
5541256Syl150051 }
5551256Syl150051 #endif
5561256Syl150051 
5571256Syl150051 
558