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 *
21*3115Syl150051 * Copyright (c) 2002-2006 Neterion, Inc.
221256Syl150051 */
231256Syl150051
241256Syl150051 #ifdef XGE_DEBUG_FP
251256Syl150051 #include "xgehal-fifo.h"
261256Syl150051 #endif
271256Syl150051
281256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_fifo_txdl_priv_t*
__hal_fifo_txdl_priv(xge_hal_dtr_h dtrh)291256Syl150051 __hal_fifo_txdl_priv(xge_hal_dtr_h dtrh)
301256Syl150051 {
311256Syl150051 xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t*)dtrh;
321256Syl150051 xge_hal_fifo_txdl_priv_t *txdl_priv;
331256Syl150051
341256Syl150051 xge_assert(txdp);
351256Syl150051 txdl_priv = (xge_hal_fifo_txdl_priv_t *)
361256Syl150051 (ulong_t)txdp->host_control;
371256Syl150051
381256Syl150051 xge_assert(txdl_priv);
391256Syl150051 xge_assert(txdl_priv->dma_object);
401256Syl150051 xge_assert(txdl_priv->dma_addr);
411256Syl150051
421256Syl150051 xge_assert(txdl_priv->dma_object->handle == txdl_priv->dma_handle);
431256Syl150051
441256Syl150051 return txdl_priv;
451256Syl150051 }
461256Syl150051
471256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
__hal_fifo_dtr_post_single(xge_hal_channel_h channelh,xge_hal_dtr_h dtrh,u64 ctrl_1)481256Syl150051 __hal_fifo_dtr_post_single(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
491256Syl150051 u64 ctrl_1)
501256Syl150051 {
511256Syl150051 xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
521256Syl150051 xge_hal_fifo_hw_pair_t *hw_pair = fifo->hw_pair;
531256Syl150051 xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh;
541256Syl150051 xge_hal_fifo_txdl_priv_t *txdl_priv;
551256Syl150051 u64 ctrl;
561256Syl150051
571256Syl150051 txdp->control_1 |= XGE_HAL_TXD_LIST_OWN_XENA;
581256Syl150051
591256Syl150051 #ifdef XGE_DEBUG_ASSERT
601256Syl150051 /* make sure Xena overwrites the (illegal) t_code value on completion */
611256Syl150051 XGE_HAL_SET_TXD_T_CODE(txdp->control_1, XGE_HAL_TXD_T_CODE_UNUSED_5);
621256Syl150051 #endif
631256Syl150051
641256Syl150051 txdl_priv = __hal_fifo_txdl_priv(dtrh);
651256Syl150051
661256Syl150051 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING)
671256Syl150051 /* sync the TxDL to device */
681256Syl150051 xge_os_dma_sync(fifo->channel.pdev,
691256Syl150051 txdl_priv->dma_handle,
701256Syl150051 txdl_priv->dma_addr,
711256Syl150051 txdl_priv->dma_offset,
721256Syl150051 txdl_priv->frags << 5 /* sizeof(xge_hal_fifo_txd_t) */,
731256Syl150051 XGE_OS_DMA_DIR_TODEVICE);
741256Syl150051 #endif
751256Syl150051 /* write the pointer first */
761256Syl150051 xge_os_pio_mem_write64(fifo->channel.pdev,
771256Syl150051 fifo->channel.regh1,
781256Syl150051 txdl_priv->dma_addr,
791256Syl150051 &hw_pair->txdl_pointer);
801256Syl150051
811256Syl150051 /* spec: 0x00 = 1 TxD in the list */
821256Syl150051 ctrl = XGE_HAL_TX_FIFO_LAST_TXD_NUM(txdl_priv->frags - 1);
831256Syl150051 ctrl |= ctrl_1;
841256Syl150051 ctrl |= fifo->no_snoop_bits;
851256Syl150051
861256Syl150051 if (txdp->control_1 & XGE_HAL_TXD_LSO_COF_CTRL(XGE_HAL_TXD_TCP_LSO)) {
871256Syl150051 ctrl |= XGE_HAL_TX_FIFO_SPECIAL_FUNC;
881256Syl150051 }
891256Syl150051
901256Syl150051 /*
911256Syl150051 * according to the XENA spec:
921256Syl150051 *
931256Syl150051 * It is important to note that pointers and list control words are
941256Syl150051 * always written in pairs: in the first write, the host must write a
951256Syl150051 * pointer, and in the second write, it must write the list control
961256Syl150051 * word. Any other access will result in an error. Also, all 16 bytes
971256Syl150051 * of the pointer/control structure must be written, including any
981256Syl150051 * reserved bytes.
991256Syl150051 */
1001256Syl150051 xge_os_wmb();
1011256Syl150051
1021256Syl150051 /*
1031256Syl150051 * we want touch work_arr in order with ownership bit set to HW
1041256Syl150051 */
1051256Syl150051 __hal_channel_dtr_post(channelh, dtrh);
1061256Syl150051
1071256Syl150051 xge_os_pio_mem_write64(fifo->channel.pdev, fifo->channel.regh1,
1081256Syl150051 ctrl, &hw_pair->list_control);
1091256Syl150051
110*3115Syl150051 xge_debug_fifo(XGE_TRACE, "posted txdl 0x"XGE_OS_LLXFMT" ctrl 0x"XGE_OS_LLXFMT" "
111*3115Syl150051 "into 0x"XGE_OS_LLXFMT"", (unsigned long long)txdl_priv->dma_addr,
1121256Syl150051 (unsigned long long)ctrl,
1131256Syl150051 (unsigned long long)(ulong_t)&hw_pair->txdl_pointer);
1141256Syl150051
1151256Syl150051 #ifdef XGE_HAL_FIFO_DUMP_TXD
116*3115Syl150051 xge_os_printf(""XGE_OS_LLXFMT":"XGE_OS_LLXFMT":"XGE_OS_LLXFMT":"
117*3115Syl150051 XGE_OS_LLXFMT" dma "XGE_OS_LLXFMT,
118*3115Syl150051 txdp->control_1, txdp->control_2, txdp->buffer_pointer,
119*3115Syl150051 txdp->host_control, txdl_priv->dma_addr);
1201256Syl150051 #endif
1211256Syl150051
1221256Syl150051 fifo->channel.stats.total_posts++;
123*3115Syl150051 fifo->channel.usage_cnt++;
124*3115Syl150051 if (fifo->channel.stats.usage_max < fifo->channel.usage_cnt)
125*3115Syl150051 fifo->channel.stats.usage_max = fifo->channel.usage_cnt;
1261256Syl150051 }
1271256Syl150051
1281256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
__hal_fifo_txdl_free_many(xge_hal_channel_h channelh,xge_hal_fifo_txd_t * txdp,int list_size,int frags)1291256Syl150051 __hal_fifo_txdl_free_many(xge_hal_channel_h channelh,
1301256Syl150051 xge_hal_fifo_txd_t *txdp, int list_size, int frags)
1311256Syl150051 {
1321256Syl150051 xge_hal_fifo_txdl_priv_t *current_txdl_priv;
1331256Syl150051 xge_hal_fifo_txdl_priv_t *next_txdl_priv;
1341256Syl150051 int invalid_frags = frags % list_size;
1351256Syl150051 if (invalid_frags){
1361256Syl150051 xge_debug_fifo(XGE_ERR,
1371256Syl150051 "freeing corrupt dtrh %p, fragments %d list size %d",
1381256Syl150051 txdp, frags, list_size);
1391256Syl150051 xge_assert(invalid_frags == 0);
1401256Syl150051 }
1411256Syl150051 while(txdp){
1421256Syl150051 xge_debug_fifo(XGE_TRACE,
1431256Syl150051 "freeing linked dtrh %p, fragments %d list size %d",
1441256Syl150051 txdp, frags, list_size);
1451256Syl150051 current_txdl_priv = __hal_fifo_txdl_priv(txdp);
1461256Syl150051 #if defined(XGE_DEBUG_ASSERT) && defined(XGE_OS_MEMORY_CHECK)
1471256Syl150051 current_txdl_priv->allocated = 0;
1481256Syl150051 #endif
1491256Syl150051 __hal_channel_dtr_free(channelh, txdp);
1501256Syl150051 next_txdl_priv = current_txdl_priv->next_txdl_priv;
1511256Syl150051 xge_assert(frags);
1521256Syl150051 frags -= list_size;
1531256Syl150051 if (next_txdl_priv) {
1541256Syl150051 current_txdl_priv->next_txdl_priv = NULL;
1551256Syl150051 txdp = next_txdl_priv->first_txdp;
1561256Syl150051 }
1571256Syl150051 else {
1581256Syl150051 xge_debug_fifo(XGE_TRACE,
1591256Syl150051 "freed linked dtrh fragments %d list size %d",
1601256Syl150051 frags, list_size);
1611256Syl150051 break;
1621256Syl150051 }
1631256Syl150051 }
1641256Syl150051 xge_assert(frags == 0)
1651256Syl150051 }
1661256Syl150051
1671256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
__hal_fifo_txdl_restore_many(xge_hal_channel_h channelh,xge_hal_fifo_txd_t * txdp,int txdl_count)1681256Syl150051 __hal_fifo_txdl_restore_many(xge_hal_channel_h channelh,
1691256Syl150051 xge_hal_fifo_txd_t *txdp, int txdl_count)
1701256Syl150051 {
1711256Syl150051 xge_hal_fifo_txdl_priv_t *current_txdl_priv;
1721256Syl150051 xge_hal_fifo_txdl_priv_t *next_txdl_priv;
1731256Syl150051 int i = txdl_count;
1741256Syl150051
1751256Syl150051 xge_assert(((xge_hal_channel_t *)channelh)->reserve_length +
1761256Syl150051 txdl_count <= ((xge_hal_channel_t *)channelh)->reserve_initial);
1771256Syl150051
1781256Syl150051 current_txdl_priv = __hal_fifo_txdl_priv(txdp);
1791256Syl150051 do{
1801256Syl150051 xge_assert(i);
1811256Syl150051 #if defined(XGE_DEBUG_ASSERT) && defined(XGE_OS_MEMORY_CHECK)
1821256Syl150051 current_txdl_priv->allocated = 0;
1831256Syl150051 #endif
1841256Syl150051 next_txdl_priv = current_txdl_priv->next_txdl_priv;
1851256Syl150051 txdp = current_txdl_priv->first_txdp;
1861256Syl150051 current_txdl_priv->next_txdl_priv = NULL;
1871256Syl150051 __hal_channel_dtr_restore(channelh, (xge_hal_dtr_h )txdp, --i);
1881256Syl150051 xge_debug_fifo(XGE_TRACE,
1891256Syl150051 "dtrh %p restored at offset %d", txdp, i);
1901256Syl150051 current_txdl_priv = next_txdl_priv;
1911256Syl150051 } while(current_txdl_priv);
1921256Syl150051 __hal_channel_dtr_restore(channelh, NULL, txdl_count);
1931256Syl150051 }
1941256Syl150051 /**
1951256Syl150051 * xge_hal_fifo_dtr_private - Retrieve per-descriptor private data.
1961256Syl150051 * @channelh: Channel handle.
1971256Syl150051 * @dtrh: Descriptor handle.
1981256Syl150051 *
1991256Syl150051 * Retrieve per-descriptor private data.
2001256Syl150051 * Note that ULD requests per-descriptor space via
2011256Syl150051 * xge_hal_channel_open().
2021256Syl150051 *
2031256Syl150051 * Returns: private ULD data associated with the descriptor.
2041256Syl150051 * Usage: See ex_xmit{} and ex_tx_compl{}.
2051256Syl150051 */
2061256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void*
xge_hal_fifo_dtr_private(xge_hal_dtr_h dtrh)2071256Syl150051 xge_hal_fifo_dtr_private(xge_hal_dtr_h dtrh)
2081256Syl150051 {
2091256Syl150051 xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh;
2101256Syl150051
2111256Syl150051 return ((char *)(ulong_t)txdp->host_control) +
2121256Syl150051 sizeof(xge_hal_fifo_txdl_priv_t);
2131256Syl150051 }
2141256Syl150051
2151256Syl150051 /**
2161256Syl150051 * xge_hal_fifo_dtr_buffer_cnt - Get number of buffers carried by the
2171256Syl150051 * descriptor.
2181256Syl150051 * @dtrh: Descriptor handle.
2191256Syl150051 *
2201256Syl150051 * Returns: Number of buffers stored in the given descriptor. Can be used
2211256Syl150051 * _after_ the descriptor is set up for posting (see
2221256Syl150051 * xge_hal_fifo_dtr_post()) and _before_ it is deallocated (see
2231256Syl150051 * xge_hal_fifo_dtr_free()).
2241256Syl150051 *
2251256Syl150051 */
2261256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO int
xge_hal_fifo_dtr_buffer_cnt(xge_hal_dtr_h dtrh)2271256Syl150051 xge_hal_fifo_dtr_buffer_cnt(xge_hal_dtr_h dtrh)
2281256Syl150051 {
2291256Syl150051 xge_hal_fifo_txdl_priv_t *txdl_priv;
2301256Syl150051
2311256Syl150051 txdl_priv = __hal_fifo_txdl_priv(dtrh);
2321256Syl150051
2331256Syl150051 return txdl_priv->frags;
2341256Syl150051 }
2351256Syl150051 /**
2361256Syl150051 * xge_hal_fifo_dtr_reserve_many- Reserve fifo descriptors which span more
2371256Syl150051 * than single txdl.
2381256Syl150051 * @channelh: Channel handle.
2391256Syl150051 * @dtrh: Reserved descriptor. On success HAL fills this "out" parameter
2401256Syl150051 * with a valid handle.
2411256Syl150051 * @frags: minimum number of fragments to be reserved.
2421256Syl150051 *
2431256Syl150051 * Reserve TxDL(s) (that is, fifo descriptor)
2441256Syl150051 * for the subsequent filling-in by upper layerdriver (ULD))
2451256Syl150051 * and posting on the corresponding channel (@channelh)
2461256Syl150051 * via xge_hal_fifo_dtr_post().
2471256Syl150051 *
2481256Syl150051 * Returns: XGE_HAL_OK - success;
2491256Syl150051 * XGE_HAL_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available
2501256Syl150051 *
2511256Syl150051 * See also: xge_hal_fifo_dtr_reserve_sp(), xge_hal_fifo_dtr_free(),
2521256Syl150051 * xge_hal_ring_dtr_reserve(), xge_hal_status_e{}.
2531256Syl150051 * Usage: See ex_xmit{}.
2541256Syl150051 */
2551256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e
xge_hal_fifo_dtr_reserve_many(xge_hal_channel_h channelh,xge_hal_dtr_h * dtrh,const int frags)2561256Syl150051 xge_hal_fifo_dtr_reserve_many(xge_hal_channel_h channelh,
2571256Syl150051 xge_hal_dtr_h *dtrh, const int frags)
2581256Syl150051 {
2591256Syl150051 xge_hal_status_e status = XGE_HAL_OK;
2601256Syl150051 int alloc_frags = 0, dang_frags = 0;
2611256Syl150051 xge_hal_fifo_txd_t *curr_txdp = NULL;
2621256Syl150051 xge_hal_fifo_txd_t *next_txdp;
2631256Syl150051 xge_hal_fifo_txdl_priv_t *next_txdl_priv, *curr_txdl_priv = NULL;
2641256Syl150051 xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
2651256Syl150051 int max_frags = fifo->config->max_frags;
2661256Syl150051 xge_hal_dtr_h dang_dtrh = NULL;
2671256Syl150051 #if defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
2681256Syl150051 unsigned long flags=0;
2691256Syl150051 #endif
2701256Syl150051 xge_debug_fifo(XGE_TRACE, "dtr_reserve_many called for frags %d",
2711256Syl150051 frags);
2721256Syl150051 xge_assert(frags < (fifo->txdl_per_memblock * max_frags));
2731256Syl150051 #if defined(XGE_HAL_TX_MULTI_RESERVE)
2741256Syl150051 xge_os_spin_lock(&fifo->channel.reserve_lock);
2751256Syl150051 #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
2761256Syl150051 xge_os_spin_lock_irq(&fifo->channel.reserve_lock, flags);
2771256Syl150051 #endif
2781256Syl150051 while(alloc_frags < frags) {
2791256Syl150051 status = __hal_channel_dtr_alloc(channelh,
280*3115Syl150051 (xge_hal_dtr_h *)(void*)&next_txdp);
2811256Syl150051 if (status != XGE_HAL_OK){
2821256Syl150051 xge_debug_fifo(XGE_ERR,
2831256Syl150051 "failed to allocate linked fragments rc %d",
2841256Syl150051 status);
2851256Syl150051 xge_assert(status == XGE_HAL_INF_OUT_OF_DESCRIPTORS);
2861256Syl150051 if (*dtrh) {
2871256Syl150051 xge_assert(alloc_frags/max_frags);
2881256Syl150051 __hal_fifo_txdl_restore_many(channelh,
289*3115Syl150051 (xge_hal_fifo_txd_t *) *dtrh, alloc_frags/max_frags);
2901256Syl150051 }
2911256Syl150051 if (dang_dtrh) {
2921256Syl150051 xge_assert(dang_frags/max_frags);
2931256Syl150051 __hal_fifo_txdl_restore_many(channelh,
294*3115Syl150051 (xge_hal_fifo_txd_t *) dang_dtrh, dang_frags/max_frags);
2951256Syl150051 }
2961256Syl150051 break;
2971256Syl150051 }
2981256Syl150051 xge_debug_fifo(XGE_TRACE, "allocated linked dtrh %p"
2991256Syl150051 " for frags %d", next_txdp, frags);
3001256Syl150051 next_txdl_priv = __hal_fifo_txdl_priv(next_txdp);
3011256Syl150051 xge_assert(next_txdl_priv);
3021256Syl150051 xge_assert(next_txdl_priv->first_txdp == next_txdp);
3031256Syl150051 next_txdl_priv->dang_txdl = NULL;
3041256Syl150051 next_txdl_priv->dang_frags = 0;
3051256Syl150051 next_txdl_priv->next_txdl_priv = NULL;
3061256Syl150051 #if defined(XGE_OS_MEMORY_CHECK)
3071256Syl150051 next_txdl_priv->allocated = 1;
3081256Syl150051 #endif
3091256Syl150051 if (!curr_txdp || !curr_txdl_priv) {
3101256Syl150051 curr_txdp = next_txdp;
3111256Syl150051 curr_txdl_priv = next_txdl_priv;
3121256Syl150051 *dtrh = (xge_hal_dtr_h)next_txdp;
3131256Syl150051 alloc_frags = max_frags;
3141256Syl150051 continue;
3151256Syl150051 }
3161256Syl150051 if (curr_txdl_priv->memblock ==
3171256Syl150051 next_txdl_priv->memblock) {
3181256Syl150051 xge_debug_fifo(XGE_TRACE,
3191256Syl150051 "linking dtrh %p, with %p",
3201256Syl150051 *dtrh, next_txdp);
3211256Syl150051 xge_assert (next_txdp ==
3221256Syl150051 curr_txdp + max_frags);
3231256Syl150051 alloc_frags += max_frags;
3241256Syl150051 curr_txdl_priv->next_txdl_priv = next_txdl_priv;
3251256Syl150051 }
3261256Syl150051 else {
3271256Syl150051 xge_assert(*dtrh);
3281256Syl150051 xge_assert(dang_dtrh == NULL);
3291256Syl150051 dang_dtrh = *dtrh;
3301256Syl150051 dang_frags = alloc_frags;
3311256Syl150051 xge_debug_fifo(XGE_TRACE,
3321256Syl150051 "dangling dtrh %p, linked with dtrh %p",
3331256Syl150051 *dtrh, next_txdp);
334*3115Syl150051 next_txdl_priv->dang_txdl = (xge_hal_fifo_txd_t *) *dtrh;
3351256Syl150051 next_txdl_priv->dang_frags = alloc_frags;
3361256Syl150051 alloc_frags = max_frags;
3371256Syl150051 *dtrh = next_txdp;
3381256Syl150051 }
3391256Syl150051 curr_txdp = next_txdp;
3401256Syl150051 curr_txdl_priv = next_txdl_priv;
3411256Syl150051 }
3421256Syl150051
3431256Syl150051 #if defined(XGE_HAL_TX_MULTI_RESERVE)
3441256Syl150051 xge_os_spin_unlock(&fifo->channel.reserve_lock);
3451256Syl150051 #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
3461256Syl150051 xge_os_spin_unlock_irq(&fifo->channel.reserve_lock, flags);
3471256Syl150051 #endif
3481256Syl150051
3491256Syl150051 if (status == XGE_HAL_OK) {
3501256Syl150051 xge_hal_fifo_txdl_priv_t * txdl_priv;
3511256Syl150051 xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)*dtrh;
3521256Syl150051 xge_hal_stats_channel_info_t *statsp = &fifo->channel.stats;
3531256Syl150051 txdl_priv = __hal_fifo_txdl_priv(txdp);
3541256Syl150051 /* reset the TxDL's private */
3551256Syl150051 txdl_priv->align_dma_offset = 0;
3561256Syl150051 txdl_priv->align_vaddr_start = txdl_priv->align_vaddr;
3571256Syl150051 txdl_priv->align_used_frags = 0;
3581256Syl150051 txdl_priv->frags = 0;
359*3115Syl150051 txdl_priv->bytes_sent = 0;
3601256Syl150051 txdl_priv->alloc_frags = alloc_frags;
3611256Syl150051 /* reset TxD0 */
3621256Syl150051 txdp->control_1 = txdp->control_2 = 0;
3631256Syl150051
3641256Syl150051 #if defined(XGE_OS_MEMORY_CHECK)
3651256Syl150051 txdl_priv->allocated = 1;
3661256Syl150051 #endif
3671256Syl150051 /* update statistics */
3681256Syl150051 statsp->total_posts_dtrs_many++;
3691256Syl150051 statsp->total_posts_frags_many += txdl_priv->alloc_frags;
3701256Syl150051 if (txdl_priv->dang_frags){
3711256Syl150051 statsp->total_posts_dang_dtrs++;
3721256Syl150051 statsp->total_posts_dang_frags += txdl_priv->dang_frags;
3731256Syl150051 }
3741256Syl150051 }
3751256Syl150051
3761256Syl150051 return status;
3771256Syl150051 }
3781256Syl150051
3791256Syl150051 /**
3801256Syl150051 * xge_hal_fifo_dtr_reserve - Reserve fifo descriptor.
3811256Syl150051 * @channelh: Channel handle.
3821256Syl150051 * @dtrh: Reserved descriptor. On success HAL fills this "out" parameter
3831256Syl150051 * with a valid handle.
3841256Syl150051 *
3851256Syl150051 * Reserve a single TxDL (that is, fifo descriptor)
3861256Syl150051 * for the subsequent filling-in by upper layerdriver (ULD))
3871256Syl150051 * and posting on the corresponding channel (@channelh)
3881256Syl150051 * via xge_hal_fifo_dtr_post().
3891256Syl150051 *
3901256Syl150051 * Note: it is the responsibility of ULD to reserve multiple descriptors
3911256Syl150051 * for lengthy (e.g., LSO) transmit operation. A single fifo descriptor
3921256Syl150051 * carries up to configured number (fifo.max_frags) of contiguous buffers.
3931256Syl150051 *
3941256Syl150051 * Returns: XGE_HAL_OK - success;
3951256Syl150051 * XGE_HAL_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available
3961256Syl150051 *
3971256Syl150051 * See also: xge_hal_fifo_dtr_reserve_sp(), xge_hal_fifo_dtr_free(),
3981256Syl150051 * xge_hal_ring_dtr_reserve(), xge_hal_status_e{}.
3991256Syl150051 * Usage: See ex_xmit{}.
4001256Syl150051 */
4011256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e
xge_hal_fifo_dtr_reserve(xge_hal_channel_h channelh,xge_hal_dtr_h * dtrh)4021256Syl150051 xge_hal_fifo_dtr_reserve(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh)
4031256Syl150051 {
4041256Syl150051 xge_hal_status_e status;
4051256Syl150051 #if defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
4061256Syl150051 unsigned long flags=0;
4071256Syl150051 #endif
4081256Syl150051
4091256Syl150051 #if defined(XGE_HAL_TX_MULTI_RESERVE)
4101256Syl150051 xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->reserve_lock);
4111256Syl150051 #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
4121256Syl150051 xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->reserve_lock,
4131256Syl150051 flags);
4141256Syl150051 #endif
4151256Syl150051
4161256Syl150051 status = __hal_channel_dtr_alloc(channelh, dtrh);
4171256Syl150051
4181256Syl150051 #if defined(XGE_HAL_TX_MULTI_RESERVE)
4191256Syl150051 xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->reserve_lock);
4201256Syl150051 #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
4211256Syl150051 xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->reserve_lock,
4221256Syl150051 flags);
4231256Syl150051 #endif
4241256Syl150051
4251256Syl150051 if (status == XGE_HAL_OK) {
4261256Syl150051 xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)*dtrh;
4271256Syl150051 xge_hal_fifo_txdl_priv_t *txdl_priv;
4281256Syl150051
4291256Syl150051 txdl_priv = __hal_fifo_txdl_priv(txdp);
4301256Syl150051
4311256Syl150051 /* reset the TxDL's private */
4321256Syl150051 txdl_priv->align_dma_offset = 0;
4331256Syl150051 txdl_priv->align_vaddr_start = txdl_priv->align_vaddr;
4341256Syl150051 txdl_priv->align_used_frags = 0;
4351256Syl150051 txdl_priv->frags = 0;
4361256Syl150051 txdl_priv->alloc_frags =
4371256Syl150051 ((xge_hal_fifo_t *)channelh)->config->max_frags;
4381256Syl150051 txdl_priv->dang_txdl = NULL;
4391256Syl150051 txdl_priv->dang_frags = 0;
4401256Syl150051 txdl_priv->next_txdl_priv = NULL;
441*3115Syl150051 txdl_priv->bytes_sent = 0;
4421256Syl150051
4431256Syl150051 /* reset TxD0 */
4441256Syl150051 txdp->control_1 = txdp->control_2 = 0;
4451256Syl150051
4461256Syl150051 #if defined(XGE_OS_MEMORY_CHECK)
4471256Syl150051 txdl_priv->allocated = 1;
4481256Syl150051 #endif
4491256Syl150051 }
4501256Syl150051
4511256Syl150051 return status;
4521256Syl150051 }
4531256Syl150051
4541256Syl150051 /**
4551256Syl150051 * xge_hal_fifo_dtr_reserve_sp - Reserve fifo descriptor and store it in
4561256Syl150051 * the ULD-provided "scratch" memory.
4571256Syl150051 * @channelh: Channel handle.
4581256Syl150051 * @dtr_sp_size: Size of the %dtr_sp "scratch pad" that HAL can use for TxDL.
4591256Syl150051 * @dtr_sp: "Scratch pad" supplied by upper-layer driver (ULD).
4601256Syl150051 *
4611256Syl150051 * Reserve TxDL and fill-in ULD supplied "scratch pad". The difference
4621256Syl150051 * between this API and xge_hal_fifo_dtr_reserve() is (possibly) -
4631256Syl150051 * performance.
4641256Syl150051 *
4651256Syl150051 * If upper-layer uses ULP-defined commands, and if those commands have enough
4661256Syl150051 * space for HAL/Xframe descriptors - tnan it is better (read: faster) to fit
4671256Syl150051 * all the per-command information into one command, which is typically
4681256Syl150051 * one contiguous block.
4691256Syl150051 *
4701256Syl150051 * Note: Unlike xge_hal_fifo_dtr_reserve(), this function can be used to
4711256Syl150051 * allocate a single descriptor for transmit operation.
4721256Syl150051 *
4731256Syl150051 * See also: xge_hal_fifo_dtr_reserve(), xge_hal_fifo_dtr_free(),
4741256Syl150051 * xge_hal_ring_dtr_reserve(), xge_hal_status_e{}.
4751256Syl150051 */
4761256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e
xge_hal_fifo_dtr_reserve_sp(xge_hal_channel_h channelh,int dtr_sp_size,xge_hal_dtr_h dtr_sp)4771256Syl150051 xge_hal_fifo_dtr_reserve_sp(xge_hal_channel_h channelh, int dtr_sp_size,
4781256Syl150051 xge_hal_dtr_h dtr_sp)
4791256Syl150051 {
4801256Syl150051 /* FIXME: implement */
4811256Syl150051 return XGE_HAL_OK;
4821256Syl150051 }
4831256Syl150051
4841256Syl150051 /**
4851256Syl150051 * xge_hal_fifo_dtr_post - Post descriptor on the fifo channel.
4861256Syl150051 * @channelh: Channel handle.
4871256Syl150051 * @dtrh: Descriptor obtained via xge_hal_fifo_dtr_reserve() or
4881256Syl150051 * xge_hal_fifo_dtr_reserve_sp()
4891256Syl150051 * @frags: Number of contiguous buffers that are part of a single
4901256Syl150051 * transmit operation.
4911256Syl150051 *
4921256Syl150051 * Post descriptor on the 'fifo' type channel for transmission.
4931256Syl150051 * Prior to posting the descriptor should be filled in accordance with
4941256Syl150051 * Host/Xframe interface specification for a given service (LL, etc.).
4951256Syl150051 *
4961256Syl150051 * See also: xge_hal_fifo_dtr_post_many(), xge_hal_ring_dtr_post().
4971256Syl150051 * Usage: See ex_xmit{}.
4981256Syl150051 */
4991256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
xge_hal_fifo_dtr_post(xge_hal_channel_h channelh,xge_hal_dtr_h dtrh)5001256Syl150051 xge_hal_fifo_dtr_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh)
5011256Syl150051 {
5021256Syl150051 xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
5031256Syl150051 xge_hal_fifo_txdl_priv_t *txdl_priv;
5041256Syl150051 xge_hal_fifo_txd_t *txdp_last;
5051256Syl150051 xge_hal_fifo_txd_t *txdp_first;
5061256Syl150051 #if defined(XGE_HAL_TX_MULTI_POST_IRQ)
5071256Syl150051 unsigned long flags = 0;
5081256Syl150051 #endif
5091256Syl150051
5101256Syl150051 txdl_priv = __hal_fifo_txdl_priv(dtrh);
5111256Syl150051
5121256Syl150051 txdp_first = (xge_hal_fifo_txd_t *)dtrh;
5131256Syl150051 txdp_first->control_1 |= XGE_HAL_TXD_GATHER_CODE_FIRST;
5141256Syl150051 txdp_first->control_2 |= fifo->interrupt_type;
5151256Syl150051
5161256Syl150051 txdp_last = (xge_hal_fifo_txd_t *)dtrh + (txdl_priv->frags - 1);
5171256Syl150051 txdp_last->control_1 |= XGE_HAL_TXD_GATHER_CODE_LAST;
5181256Syl150051
5191256Syl150051 #if defined(XGE_HAL_TX_MULTI_POST)
5201256Syl150051 xge_os_spin_lock(fifo->post_lock_ptr);
5211256Syl150051 #elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
5221256Syl150051 xge_os_spin_lock_irq(fifo->post_lock_ptr, flags);
5231256Syl150051 #endif
5241256Syl150051
5251256Syl150051 __hal_fifo_dtr_post_single(channelh, dtrh,
5261256Syl150051 (u64)(XGE_HAL_TX_FIFO_FIRST_LIST | XGE_HAL_TX_FIFO_LAST_LIST));
5271256Syl150051
5281256Syl150051 #if defined(XGE_HAL_TX_MULTI_POST)
5291256Syl150051 xge_os_spin_unlock(fifo->post_lock_ptr);
5301256Syl150051 #elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
5311256Syl150051 xge_os_spin_unlock_irq(fifo->post_lock_ptr, flags);
5321256Syl150051 #endif
5331256Syl150051 }
5341256Syl150051
5351256Syl150051 /**
5361256Syl150051 * xge_hal_fifo_dtr_post_many - Post multiple descriptors on fifo
5371256Syl150051 * channel.
5381256Syl150051 * @channelh: Channel to post descriptor.
5391256Syl150051 * @num: Number of descriptors (i.e., fifo TxDLs) in the %dtrs[].
5401256Syl150051 * @dtrs: Descriptors obtained via xge_hal_fifo_dtr_reserve().
5411256Syl150051 * @frags_arr: Number of fragments carried @dtrs descriptors.
5421256Syl150051 * Note that frag_arr[i] corresponds to descriptor dtrs[i].
5431256Syl150051 *
5441256Syl150051 * Post multi-descriptor on the fifo channel. The operation is atomic:
5451256Syl150051 * all descriptrs are posted on the channel "back-to-back' without
5461256Syl150051 * letting other posts (possibly driven by multiple transmitting threads)
5471256Syl150051 * to interleave.
5481256Syl150051 *
5491256Syl150051 * See also: xge_hal_fifo_dtr_post(), xge_hal_ring_dtr_post().
5501256Syl150051 */
5511256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
xge_hal_fifo_dtr_post_many(xge_hal_channel_h channelh,int num,xge_hal_dtr_h dtrs[])5521256Syl150051 xge_hal_fifo_dtr_post_many(xge_hal_channel_h channelh, int num,
5531256Syl150051 xge_hal_dtr_h dtrs[])
5541256Syl150051 {
5551256Syl150051 int i;
5561256Syl150051 xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
5571256Syl150051 xge_hal_fifo_txd_t *txdp_last;
5581256Syl150051 xge_hal_fifo_txd_t *txdp_first;
5591256Syl150051 xge_hal_fifo_txdl_priv_t *txdl_priv_last;
5601256Syl150051 #if defined(XGE_HAL_TX_MULTI_POST_IRQ)
5611256Syl150051 unsigned long flags = 0;
5621256Syl150051 #endif
5631256Syl150051
5641256Syl150051 xge_assert(num > 1);
5651256Syl150051
5661256Syl150051 txdp_first = (xge_hal_fifo_txd_t *)dtrs[0];
5671256Syl150051 txdp_first->control_1 |= XGE_HAL_TXD_GATHER_CODE_FIRST;
5681256Syl150051 txdp_first->control_2 |= fifo->interrupt_type;
5691256Syl150051
5701256Syl150051 txdl_priv_last = __hal_fifo_txdl_priv(dtrs[num-1]);
5711256Syl150051 txdp_last = (xge_hal_fifo_txd_t *)dtrs[num-1] +
5721256Syl150051 (txdl_priv_last->frags - 1);
5731256Syl150051 txdp_last->control_1 |= XGE_HAL_TXD_GATHER_CODE_LAST;
5741256Syl150051
5751256Syl150051 #if defined(XGE_HAL_TX_MULTI_POST)
5761256Syl150051 xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->post_lock);
5771256Syl150051 #elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
5781256Syl150051 xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->post_lock,
5791256Syl150051 flags);
5801256Syl150051 #endif
5811256Syl150051
5821256Syl150051 for (i=0; i<num; i++) {
5831256Syl150051 xge_hal_fifo_txdl_priv_t *txdl_priv;
5841256Syl150051 u64 val64;
5851256Syl150051 xge_hal_dtr_h dtrh = dtrs[i];
5861256Syl150051
5871256Syl150051 txdl_priv = __hal_fifo_txdl_priv(dtrh);
5881256Syl150051 txdl_priv = txdl_priv; /* Cheat lint */
5891256Syl150051
5901256Syl150051 val64 = 0;
5911256Syl150051 if (i == 0) {
5921256Syl150051 val64 |= XGE_HAL_TX_FIFO_FIRST_LIST;
5931256Syl150051 } else if (i == num -1) {
5941256Syl150051 val64 |= XGE_HAL_TX_FIFO_LAST_LIST;
5951256Syl150051 }
5961256Syl150051
5971256Syl150051 val64 |= XGE_HAL_TX_FIFO_SPECIAL_FUNC;
5981256Syl150051 __hal_fifo_dtr_post_single(channelh, dtrh, val64);
5991256Syl150051 }
6001256Syl150051
6011256Syl150051 #if defined(XGE_HAL_TX_MULTI_POST)
6021256Syl150051 xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->post_lock);
6031256Syl150051 #elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
6041256Syl150051 xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->post_lock,
6051256Syl150051 flags);
6061256Syl150051 #endif
6071256Syl150051
6081256Syl150051 fifo->channel.stats.total_posts_many++;
6091256Syl150051 }
6101256Syl150051
6111256Syl150051 /**
6121256Syl150051 * xge_hal_fifo_dtr_next_completed - Retrieve next completed descriptor.
6131256Syl150051 * @channelh: Channel handle.
6141256Syl150051 * @dtrh: Descriptor handle. Returned by HAL.
6151256Syl150051 * @t_code: Transfer code, as per Xframe User Guide,
6161256Syl150051 * Transmit Descriptor Format.
6171256Syl150051 * Returned by HAL.
6181256Syl150051 *
6191256Syl150051 * Retrieve the _next_ completed descriptor.
6201256Syl150051 * HAL uses channel callback (*xge_hal_channel_callback_f) to notifiy
6211256Syl150051 * upper-layer driver (ULD) of new completed descriptors. After that
6221256Syl150051 * the ULD can use xge_hal_fifo_dtr_next_completed to retrieve the rest
6231256Syl150051 * completions (the very first completion is passed by HAL via
6241256Syl150051 * xge_hal_channel_callback_f).
6251256Syl150051 *
6261256Syl150051 * Implementation-wise, the upper-layer driver is free to call
6271256Syl150051 * xge_hal_fifo_dtr_next_completed either immediately from inside the
6281256Syl150051 * channel callback, or in a deferred fashion and separate (from HAL)
6291256Syl150051 * context.
6301256Syl150051 *
6311256Syl150051 * Non-zero @t_code means failure to process the descriptor.
6321256Syl150051 * The failure could happen, for instance, when the link is
6331256Syl150051 * down, in which case Xframe completes the descriptor because it
6341256Syl150051 * is not able to send the data out.
6351256Syl150051 *
6361256Syl150051 * For details please refer to Xframe User Guide.
6371256Syl150051 *
6381256Syl150051 * Returns: XGE_HAL_OK - success.
6391256Syl150051 * XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed descriptors
6401256Syl150051 * are currently available for processing.
6411256Syl150051 *
6421256Syl150051 * See also: xge_hal_channel_callback_f{},
6431256Syl150051 * xge_hal_ring_dtr_next_completed().
6441256Syl150051 * Usage: See ex_tx_compl{}.
6451256Syl150051 */
6461256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e
xge_hal_fifo_dtr_next_completed(xge_hal_channel_h channelh,xge_hal_dtr_h * dtrh,u8 * t_code)6471256Syl150051 xge_hal_fifo_dtr_next_completed(xge_hal_channel_h channelh,
6481256Syl150051 xge_hal_dtr_h *dtrh, u8 *t_code)
6491256Syl150051 {
6501256Syl150051 xge_hal_fifo_txd_t *txdp;
651*3115Syl150051 xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
6521256Syl150051 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING)
6531256Syl150051 xge_hal_fifo_txdl_priv_t *txdl_priv;
6541256Syl150051 #endif
6551256Syl150051
6561256Syl150051 __hal_channel_dtr_try_complete(channelh, dtrh);
6571256Syl150051 txdp = (xge_hal_fifo_txd_t *)*dtrh;
6581256Syl150051 if (txdp == NULL) {
6591256Syl150051 return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
6601256Syl150051 }
6611256Syl150051
6621256Syl150051 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING)
6631256Syl150051 txdl_priv = __hal_fifo_txdl_priv(txdp);
6641256Syl150051
6651256Syl150051 /* sync TxDL to read the ownership
6661256Syl150051 *
6671256Syl150051 * Note: 16bytes means Control_1 & Control_2 */
6681256Syl150051 xge_os_dma_sync(fifo->channel.pdev,
6691256Syl150051 txdl_priv->dma_handle,
6701256Syl150051 txdl_priv->dma_addr,
6711256Syl150051 txdl_priv->dma_offset,
6721256Syl150051 16,
6731256Syl150051 XGE_OS_DMA_DIR_FROMDEVICE);
6741256Syl150051 #endif
6751256Syl150051
6761256Syl150051 /* check whether host owns it */
6771256Syl150051 if ( !(txdp->control_1 & XGE_HAL_TXD_LIST_OWN_XENA) ) {
6781256Syl150051
6791256Syl150051 xge_assert(txdp->host_control!=0);
6801256Syl150051
6811256Syl150051 __hal_channel_dtr_complete(channelh);
6821256Syl150051
6831256Syl150051 *t_code = (u8)XGE_HAL_GET_TXD_T_CODE(txdp->control_1);
6841256Syl150051
6851256Syl150051 /* see XGE_HAL_SET_TXD_T_CODE() above.. */
6861256Syl150051 xge_assert(*t_code != XGE_HAL_TXD_T_CODE_UNUSED_5);
6871256Syl150051
688*3115Syl150051 if (fifo->channel.usage_cnt > 0)
689*3115Syl150051 fifo->channel.usage_cnt--;
690*3115Syl150051
6911256Syl150051 return XGE_HAL_OK;
6921256Syl150051 }
6931256Syl150051
6941256Syl150051 /* no more completions */
6951256Syl150051 *dtrh = 0;
6961256Syl150051 return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
6971256Syl150051 }
6981256Syl150051
6991256Syl150051 /**
7001256Syl150051 * xge_hal_fifo_dtr_free - Free descriptor.
7011256Syl150051 * @channelh: Channel handle.
7021256Syl150051 * @dtr: Descriptor handle.
7031256Syl150051 *
7041256Syl150051 * Free the reserved descriptor. This operation is "symmetrical" to
7051256Syl150051 * xge_hal_fifo_dtr_reserve or xge_hal_fifo_dtr_reserve_sp.
7061256Syl150051 * The "free-ing" completes the descriptor's lifecycle.
7071256Syl150051 *
7081256Syl150051 * After free-ing (see xge_hal_fifo_dtr_free()) the descriptor again can
7091256Syl150051 * be:
7101256Syl150051 *
7111256Syl150051 * - reserved (xge_hal_fifo_dtr_reserve);
7121256Syl150051 *
7131256Syl150051 * - posted (xge_hal_fifo_dtr_post);
7141256Syl150051 *
7151256Syl150051 * - completed (xge_hal_fifo_dtr_next_completed);
7161256Syl150051 *
7171256Syl150051 * - and recycled again (xge_hal_fifo_dtr_free).
7181256Syl150051 *
7191256Syl150051 * For alternative state transitions and more details please refer to
7201256Syl150051 * the design doc.
7211256Syl150051 *
7221256Syl150051 * See also: xge_hal_ring_dtr_free(), xge_hal_fifo_dtr_reserve().
7231256Syl150051 * Usage: See ex_tx_compl{}.
7241256Syl150051 */
7251256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
xge_hal_fifo_dtr_free(xge_hal_channel_h channelh,xge_hal_dtr_h dtr)7261256Syl150051 xge_hal_fifo_dtr_free(xge_hal_channel_h channelh, xge_hal_dtr_h dtr)
7271256Syl150051 {
7281256Syl150051 #if defined(XGE_HAL_TX_MULTI_FREE_IRQ)
7291256Syl150051 unsigned long flags = 0;
7301256Syl150051 #endif
7311256Syl150051 xge_hal_fifo_txdl_priv_t *txdl_priv = __hal_fifo_txdl_priv(
7321256Syl150051 (xge_hal_fifo_txd_t *)dtr);
7331256Syl150051 int max_frags = ((xge_hal_fifo_t *)channelh)->config->max_frags;
7341256Syl150051 #if defined(XGE_HAL_TX_MULTI_FREE)
7351256Syl150051 xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->free_lock);
7361256Syl150051 #elif defined(XGE_HAL_TX_MULTI_FREE_IRQ)
7371256Syl150051 xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->free_lock,
7381256Syl150051 flags);
7391256Syl150051 #endif
7401256Syl150051
7411256Syl150051 if (txdl_priv->alloc_frags > max_frags) {
7421256Syl150051 xge_hal_fifo_txd_t *dang_txdp = (xge_hal_fifo_txd_t *)
7431256Syl150051 txdl_priv->dang_txdl;
7441256Syl150051 int dang_frags = txdl_priv->dang_frags;
7451256Syl150051 int alloc_frags = txdl_priv->alloc_frags;
7461256Syl150051 txdl_priv->dang_txdl = NULL;
7471256Syl150051 txdl_priv->dang_frags = 0;
7481256Syl150051 txdl_priv->alloc_frags = 0;
7491256Syl150051 /* dtrh must have a linked list of dtrh */
7501256Syl150051 xge_assert(txdl_priv->next_txdl_priv);
7511256Syl150051
7521256Syl150051 /* free any dangling dtrh first */
7531256Syl150051 if (dang_txdp) {
7541256Syl150051 xge_debug_fifo(XGE_TRACE,
7551256Syl150051 "freeing dangled dtrh %p for %d fragments",
7561256Syl150051 dang_txdp, dang_frags);
7571256Syl150051 __hal_fifo_txdl_free_many(channelh, dang_txdp,
7581256Syl150051 max_frags, dang_frags);
7591256Syl150051 }
7601256Syl150051
7611256Syl150051 /* now free the reserved dtrh list */
7621256Syl150051 xge_debug_fifo(XGE_TRACE,
7631256Syl150051 "freeing dtrh %p list of %d fragments", dtr,
7641256Syl150051 alloc_frags);
7651256Syl150051 __hal_fifo_txdl_free_many(channelh,
7661256Syl150051 (xge_hal_fifo_txd_t *)dtr, max_frags,
7671256Syl150051 alloc_frags);
7681256Syl150051 }
7691256Syl150051 else
7701256Syl150051 __hal_channel_dtr_free(channelh, dtr);
7711256Syl150051
772*3115Syl150051 ((xge_hal_channel_t *)channelh)->poll_bytes += txdl_priv->bytes_sent;
773*3115Syl150051
7741256Syl150051 #if defined(XGE_DEBUG_ASSERT) && defined(XGE_OS_MEMORY_CHECK)
7751256Syl150051 __hal_fifo_txdl_priv(dtr)->allocated = 0;
7761256Syl150051 #endif
7771256Syl150051
7781256Syl150051 #if defined(XGE_HAL_TX_MULTI_FREE)
7791256Syl150051 xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->free_lock);
7801256Syl150051 #elif defined(XGE_HAL_TX_MULTI_FREE_IRQ)
7811256Syl150051 xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->free_lock,
7821256Syl150051 flags);
7831256Syl150051 #endif
7841256Syl150051 }
7851256Syl150051
7861256Syl150051
7871256Syl150051 /**
7881256Syl150051 * xge_hal_fifo_dtr_buffer_set_aligned - Align transmit buffer and fill
7891256Syl150051 * in fifo descriptor.
7901256Syl150051 * @channelh: Channel handle.
7911256Syl150051 * @dtrh: Descriptor handle.
792*3115Syl150051 * @frag_idx: Index of the data buffer in the caller's scatter-gather list�
7931256Syl150051 * (of buffers).
7941256Syl150051 * @vaddr: Virtual address of the data buffer.
7951256Syl150051 * @dma_pointer: DMA address of the data buffer referenced by @frag_idx.
7961256Syl150051 * @size: Size of the data buffer (in bytes).
7971256Syl150051 * @misaligned_size: Size (in bytes) of the misaligned portion of the
7981256Syl150051 * data buffer. Calculated by the caller, based on the platform/OS/other
7991256Syl150051 * specific criteria, which is outside of HAL's domain. See notes below.
8001256Syl150051 *
8011256Syl150051 * This API is part of the transmit descriptor preparation for posting
8021256Syl150051 * (via xge_hal_fifo_dtr_post()). The related "preparation" APIs include
8031256Syl150051 * xge_hal_fifo_dtr_mss_set() and xge_hal_fifo_dtr_cksum_set_bits().
8041256Syl150051 * All three APIs fill in the fields of the fifo descriptor,
8051256Syl150051 * in accordance with the Xframe specification.
8061256Syl150051 * On the PCI-X based systems aligning transmit data typically provides better
8071256Syl150051 * transmit performance. The typical alignment granularity: L2 cacheline size.
8081256Syl150051 * However, HAL does not make assumptions in terms of the alignment granularity;
8091256Syl150051 * this is specified via additional @misaligned_size parameter described above.
8101256Syl150051 * Prior to calling xge_hal_fifo_dtr_buffer_set_aligned(),
8111256Syl150051 * ULD is supposed to check alignment of a given fragment/buffer. For this HAL
8121256Syl150051 * provides a separate xge_hal_check_alignment() API sufficient to cover
8131256Syl150051 * most (but not all) possible alignment criteria.
8141256Syl150051 * If the buffer appears to be aligned, the ULD calls
8151256Syl150051 * xge_hal_fifo_dtr_buffer_set().
8161256Syl150051 * Otherwise, ULD calls xge_hal_fifo_dtr_buffer_set_aligned().
8171256Syl150051 *
8181256Syl150051 * Note; This API is a "superset" of xge_hal_fifo_dtr_buffer_set(). In
8191256Syl150051 * addition to filling in the specified descriptor it aligns transmit data on
8201256Syl150051 * the specified boundary.
8211256Syl150051 * Note: Decision on whether to align or not to align a given contiguous
8221256Syl150051 * transmit buffer is outside of HAL's domain. To this end ULD can use any
8231256Syl150051 * programmable criteria, which can help to 1) boost transmit performance,
8241256Syl150051 * and/or 2) provide a workaround for PCI bridge bugs, if any.
8251256Syl150051 *
8261256Syl150051 * See also: xge_hal_fifo_dtr_buffer_set(),
8271256Syl150051 * xge_hal_check_alignment().
8281256Syl150051 *
8291256Syl150051 * See also: xge_hal_fifo_dtr_reserve(), xge_hal_fifo_dtr_post(),
8301256Syl150051 * xge_hal_fifo_dtr_mss_set(), xge_hal_fifo_dtr_cksum_set_bits()
8311256Syl150051 */
8321256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e
xge_hal_fifo_dtr_buffer_set_aligned(xge_hal_channel_h channelh,xge_hal_dtr_h dtrh,int frag_idx,void * vaddr,dma_addr_t dma_pointer,int size,int misaligned_size)8331256Syl150051 xge_hal_fifo_dtr_buffer_set_aligned(xge_hal_channel_h channelh,
8341256Syl150051 xge_hal_dtr_h dtrh, int frag_idx, void *vaddr,
8351256Syl150051 dma_addr_t dma_pointer, int size, int misaligned_size)
8361256Syl150051 {
8371256Syl150051 xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
8381256Syl150051 xge_hal_fifo_txdl_priv_t *txdl_priv;
8391256Syl150051 xge_hal_fifo_txd_t *txdp;
8401256Syl150051 int remaining_size;
8411256Syl150051 ptrdiff_t prev_boff;
8421256Syl150051
8431256Syl150051 txdl_priv = __hal_fifo_txdl_priv(dtrh);
8441256Syl150051 txdp = (xge_hal_fifo_txd_t *)dtrh + txdl_priv->frags;
8451256Syl150051
8461256Syl150051 if (frag_idx != 0) {
8471256Syl150051 txdp->control_1 = txdp->control_2 = 0;
8481256Syl150051 }
8491256Syl150051
8501256Syl150051 /* On some systems buffer size could be zero.
8511256Syl150051 * It is the responsibility of ULD and *not HAL* to
8521256Syl150051 * detect it and skip it. */
8531256Syl150051 xge_assert(size > 0);
8541256Syl150051 xge_assert(frag_idx < txdl_priv->alloc_frags);
8551256Syl150051 xge_assert(misaligned_size != 0 &&
8561256Syl150051 misaligned_size <= fifo->config->alignment_size);
8571256Syl150051
8581256Syl150051 remaining_size = size - misaligned_size;
8591256Syl150051 xge_assert(remaining_size >= 0);
8601256Syl150051
8611256Syl150051 xge_os_memcpy((char*)txdl_priv->align_vaddr_start,
8621256Syl150051 vaddr, misaligned_size);
8631256Syl150051
8641256Syl150051 if (txdl_priv->align_used_frags >= fifo->config->max_aligned_frags) {
8651256Syl150051 return XGE_HAL_ERR_OUT_ALIGNED_FRAGS;
8661256Syl150051 }
8671256Syl150051
8681256Syl150051 /* setup new buffer */
8691256Syl150051 prev_boff = txdl_priv->align_vaddr_start - txdl_priv->align_vaddr;
8701256Syl150051 txdp->buffer_pointer = (u64)txdl_priv->align_dma_addr + prev_boff;
8711256Syl150051 txdp->control_1 |= XGE_HAL_TXD_BUFFER0_SIZE(misaligned_size);
872*3115Syl150051 txdl_priv->bytes_sent += misaligned_size;
8731256Syl150051 fifo->channel.stats.total_buffers++;
8741256Syl150051 txdl_priv->frags++;
8751256Syl150051 txdl_priv->align_used_frags++;
8761256Syl150051 txdl_priv->align_vaddr_start += fifo->config->alignment_size;
8771256Syl150051 txdl_priv->align_dma_offset = 0;
8781256Syl150051
8791256Syl150051 #if defined(XGE_OS_DMA_REQUIRES_SYNC)
8801256Syl150051 /* sync new buffer */
8811256Syl150051 xge_os_dma_sync(fifo->channel.pdev,
8821256Syl150051 txdl_priv->align_dma_handle,
8831256Syl150051 txdp->buffer_pointer,
8841256Syl150051 0,
8851256Syl150051 misaligned_size,
8861256Syl150051 XGE_OS_DMA_DIR_TODEVICE);
8871256Syl150051 #endif
8881256Syl150051
8891256Syl150051 if (remaining_size) {
8901256Syl150051 xge_assert(frag_idx < txdl_priv->alloc_frags);
8911256Syl150051 txdp++;
8921256Syl150051 txdp->buffer_pointer = (u64)dma_pointer +
8931256Syl150051 misaligned_size;
8941256Syl150051 txdp->control_1 =
8951256Syl150051 XGE_HAL_TXD_BUFFER0_SIZE(remaining_size);
896*3115Syl150051 txdl_priv->bytes_sent += remaining_size;
8971256Syl150051 txdp->control_2 = 0;
8981256Syl150051 fifo->channel.stats.total_buffers++;
8991256Syl150051 txdl_priv->frags++;
9001256Syl150051 }
9011256Syl150051
9021256Syl150051 return XGE_HAL_OK;
9031256Syl150051 }
9041256Syl150051
9051256Syl150051 /**
9061256Syl150051 * xge_hal_fifo_dtr_buffer_append - Append the contents of virtually
9071256Syl150051 * contiguous data buffer to a single physically contiguous buffer.
9081256Syl150051 * @channelh: Channel handle.
9091256Syl150051 * @dtrh: Descriptor handle.
9101256Syl150051 * @vaddr: Virtual address of the data buffer.
9111256Syl150051 * @size: Size of the data buffer (in bytes).
9121256Syl150051 *
9131256Syl150051 * This API is part of the transmit descriptor preparation for posting
9141256Syl150051 * (via xge_hal_fifo_dtr_post()).
9151256Syl150051 * The main difference of this API wrt to the APIs
9161256Syl150051 * xge_hal_fifo_dtr_buffer_set_aligned() is that this API appends the
9171256Syl150051 * contents of virtually contiguous data buffers received from
9181256Syl150051 * upper layer into a single physically contiguous data buffer and the
9191256Syl150051 * device will do a DMA from this buffer.
9201256Syl150051 *
9211256Syl150051 * See Also: xge_hal_fifo_dtr_buffer_finalize(), xge_hal_fifo_dtr_buffer_set(),
9221256Syl150051 * xge_hal_fifo_dtr_buffer_set_aligned().
9231256Syl150051 */
9241256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e
xge_hal_fifo_dtr_buffer_append(xge_hal_channel_h channelh,xge_hal_dtr_h dtrh,void * vaddr,int size)9251256Syl150051 xge_hal_fifo_dtr_buffer_append(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
9261256Syl150051 void *vaddr, int size)
9271256Syl150051 {
9281256Syl150051 xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
9291256Syl150051 xge_hal_fifo_txdl_priv_t *txdl_priv;
930*3115Syl150051 ptrdiff_t used;
9311256Syl150051
9321256Syl150051 xge_assert(size > 0);
9331256Syl150051
9341256Syl150051 txdl_priv = __hal_fifo_txdl_priv(dtrh);
9351256Syl150051
936*3115Syl150051 used = txdl_priv->align_vaddr_start - txdl_priv->align_vaddr;
937*3115Syl150051 used += txdl_priv->align_dma_offset;
938*3115Syl150051 if (used + (unsigned int)size > (unsigned int)fifo->align_size)
9391256Syl150051 return XGE_HAL_ERR_OUT_ALIGNED_FRAGS;
9401256Syl150051
9411256Syl150051 xge_os_memcpy((char*)txdl_priv->align_vaddr_start +
9421256Syl150051 txdl_priv->align_dma_offset, vaddr, size);
9431256Syl150051
944*3115Syl150051 fifo->channel.stats.copied_frags++;
945*3115Syl150051
9461256Syl150051 txdl_priv->align_dma_offset += size;
9471256Syl150051 return XGE_HAL_OK;
9481256Syl150051 }
9491256Syl150051
9501256Syl150051 /**
9511256Syl150051 * xge_hal_fifo_dtr_buffer_finalize - Prepares a descriptor that contains the
9521256Syl150051 * single physically contiguous buffer.
9531256Syl150051 *
9541256Syl150051 * @channelh: Channel handle.
9551256Syl150051 * @dtrh: Descriptor handle.
9561256Syl150051 * @frag_idx: Index of the data buffer in the Txdl list.
9571256Syl150051 *
9581256Syl150051 * This API in conjuction with xge_hal_fifo_dtr_buffer_append() prepares
9591256Syl150051 * a descriptor that consists of a single physically contiguous buffer
9601256Syl150051 * which inturn contains the contents of one or more virtually contiguous
9611256Syl150051 * buffers received from the upper layer.
9621256Syl150051 *
9631256Syl150051 * See Also: xge_hal_fifo_dtr_buffer_append().
9641256Syl150051 */
9651256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
xge_hal_fifo_dtr_buffer_finalize(xge_hal_channel_h channelh,xge_hal_dtr_h dtrh,int frag_idx)9661256Syl150051 xge_hal_fifo_dtr_buffer_finalize(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
9671256Syl150051 int frag_idx)
9681256Syl150051 {
9691256Syl150051 xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
9701256Syl150051 xge_hal_fifo_txdl_priv_t *txdl_priv;
9711256Syl150051 xge_hal_fifo_txd_t *txdp;
9721256Syl150051 ptrdiff_t prev_boff;
9731256Syl150051
974*3115Syl150051 xge_assert(frag_idx < fifo->config->max_frags);
975*3115Syl150051
9761256Syl150051 txdl_priv = __hal_fifo_txdl_priv(dtrh);
9771256Syl150051 txdp = (xge_hal_fifo_txd_t *)dtrh + txdl_priv->frags;
9781256Syl150051
9791256Syl150051 if (frag_idx != 0) {
9801256Syl150051 txdp->control_1 = txdp->control_2 = 0;
9811256Syl150051 }
9821256Syl150051
9831256Syl150051 prev_boff = txdl_priv->align_vaddr_start - txdl_priv->align_vaddr;
9841256Syl150051 txdp->buffer_pointer = (u64)txdl_priv->align_dma_addr + prev_boff;
9851256Syl150051 txdp->control_1 |=
9861256Syl150051 XGE_HAL_TXD_BUFFER0_SIZE(txdl_priv->align_dma_offset);
987*3115Syl150051 txdl_priv->bytes_sent += (unsigned int)txdl_priv->align_dma_offset;
9881256Syl150051 fifo->channel.stats.total_buffers++;
989*3115Syl150051 fifo->channel.stats.copied_buffers++;
9901256Syl150051 txdl_priv->frags++;
9911256Syl150051 txdl_priv->align_used_frags++;
9921256Syl150051
9931256Syl150051 #if defined(XGE_OS_DMA_REQUIRES_SYNC)
9941256Syl150051 /* sync pre-mapped buffer */
9951256Syl150051 xge_os_dma_sync(fifo->channel.pdev,
9961256Syl150051 txdl_priv->align_dma_handle,
9971256Syl150051 txdp->buffer_pointer,
9981256Syl150051 0,
9991256Syl150051 txdl_priv->align_dma_offset,
10001256Syl150051 XGE_OS_DMA_DIR_TODEVICE);
10011256Syl150051 #endif
10021256Syl150051
10031256Syl150051 /* increment vaddr_start for the next buffer_append() iteration */
10041256Syl150051 txdl_priv->align_vaddr_start += txdl_priv->align_dma_offset;
10051256Syl150051 txdl_priv->align_dma_offset = 0;
10061256Syl150051 }
10071256Syl150051
10081256Syl150051 /**
10091256Syl150051 * xge_hal_fifo_dtr_buffer_set - Set transmit buffer pointer in the
10101256Syl150051 * descriptor.
10111256Syl150051 * @channelh: Channel handle.
10121256Syl150051 * @dtrh: Descriptor handle.
1013*3115Syl150051 * @frag_idx: Index of the data buffer in the caller's scatter-gather list�
10141256Syl150051 * (of buffers).
10151256Syl150051 * @dma_pointer: DMA address of the data buffer referenced by @frag_idx.
10161256Syl150051 * @size: Size of the data buffer (in bytes).
10171256Syl150051 *
10181256Syl150051 * This API is part of the preparation of the transmit descriptor for posting
10191256Syl150051 * (via xge_hal_fifo_dtr_post()). The related "preparation" APIs include
10201256Syl150051 * xge_hal_fifo_dtr_mss_set() and xge_hal_fifo_dtr_cksum_set_bits().
10211256Syl150051 * All three APIs fill in the fields of the fifo descriptor,
10221256Syl150051 * in accordance with the Xframe specification.
10231256Syl150051 *
10241256Syl150051 * See also: xge_hal_fifo_dtr_buffer_set_aligned(),
10251256Syl150051 * xge_hal_check_alignment().
10261256Syl150051 *
10271256Syl150051 * See also: xge_hal_fifo_dtr_reserve(), xge_hal_fifo_dtr_post(),
10281256Syl150051 * xge_hal_fifo_dtr_mss_set(), xge_hal_fifo_dtr_cksum_set_bits()
10291256Syl150051 * Prepare transmit descriptor for transmission (via
10301256Syl150051 * xge_hal_fifo_dtr_post()).
10311256Syl150051 * See also: xge_hal_fifo_dtr_vlan_set().
10321256Syl150051 * Note: Compare with xge_hal_fifo_dtr_buffer_set_aligned().
10331256Syl150051 *
10341256Syl150051 * Usage: See ex_xmit{}.
10351256Syl150051 */
10361256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
xge_hal_fifo_dtr_buffer_set(xge_hal_channel_h channelh,xge_hal_dtr_h dtrh,int frag_idx,dma_addr_t dma_pointer,int size)10371256Syl150051 xge_hal_fifo_dtr_buffer_set(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
10381256Syl150051 int frag_idx, dma_addr_t dma_pointer, int size)
10391256Syl150051 {
10401256Syl150051 xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
10411256Syl150051 xge_hal_fifo_txdl_priv_t *txdl_priv;
10421256Syl150051 xge_hal_fifo_txd_t *txdp;
10431256Syl150051
10441256Syl150051 txdl_priv = __hal_fifo_txdl_priv(dtrh);
10451256Syl150051 txdp = (xge_hal_fifo_txd_t *)dtrh + txdl_priv->frags;
10461256Syl150051
10471256Syl150051 if (frag_idx != 0) {
10481256Syl150051 txdp->control_1 = txdp->control_2 = 0;
10491256Syl150051 }
10501256Syl150051
10511256Syl150051 /* Note:
10521256Syl150051 * it is the responsibility of upper layers and not HAL
10531256Syl150051 * detect it and skip zero-size fragment
10541256Syl150051 */
10551256Syl150051 xge_assert(size > 0);
10561256Syl150051 xge_assert(frag_idx < txdl_priv->alloc_frags);
10571256Syl150051
10581256Syl150051 txdp->buffer_pointer = (u64)dma_pointer;
10591256Syl150051 txdp->control_1 |= XGE_HAL_TXD_BUFFER0_SIZE(size);
1060*3115Syl150051 txdl_priv->bytes_sent += size;
10611256Syl150051 fifo->channel.stats.total_buffers++;
10621256Syl150051 txdl_priv->frags++;
10631256Syl150051 }
10641256Syl150051
10651256Syl150051 /**
10661256Syl150051 * xge_hal_fifo_dtr_mss_set - Set MSS.
10671256Syl150051 * @dtrh: Descriptor handle.
10681256Syl150051 * @mss: MSS size for _this_ TCP connection. Passed by TCP stack down to the
10691256Syl150051 * ULD, which in turn inserts the MSS into the @dtrh.
10701256Syl150051 *
10711256Syl150051 * This API is part of the preparation of the transmit descriptor for posting
10721256Syl150051 * (via xge_hal_fifo_dtr_post()). The related "preparation" APIs include
10731256Syl150051 * xge_hal_fifo_dtr_buffer_set(), xge_hal_fifo_dtr_buffer_set_aligned(),
10741256Syl150051 * and xge_hal_fifo_dtr_cksum_set_bits().
10751256Syl150051 * All these APIs fill in the fields of the fifo descriptor,
10761256Syl150051 * in accordance with the Xframe specification.
10771256Syl150051 *
10781256Syl150051 * See also: xge_hal_fifo_dtr_reserve(),
10791256Syl150051 * xge_hal_fifo_dtr_post(), xge_hal_fifo_dtr_vlan_set().
10801256Syl150051 * Usage: See ex_xmit{}.
10811256Syl150051 */
10821256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
xge_hal_fifo_dtr_mss_set(xge_hal_dtr_h dtrh,int mss)10831256Syl150051 xge_hal_fifo_dtr_mss_set(xge_hal_dtr_h dtrh, int mss)
10841256Syl150051 {
10851256Syl150051 xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh;
10861256Syl150051
10871256Syl150051 txdp->control_1 |= XGE_HAL_TXD_LSO_COF_CTRL(XGE_HAL_TXD_TCP_LSO);
10881256Syl150051 txdp->control_1 |= XGE_HAL_TXD_TCP_LSO_MSS(mss);
10891256Syl150051 }
10901256Syl150051
10911256Syl150051 /**
10921256Syl150051 * xge_hal_fifo_dtr_cksum_set_bits - Offload checksum.
10931256Syl150051 * @dtrh: Descriptor handle.
10941256Syl150051 * @cksum_bits: Specifies which checksums are to be offloaded: IPv4,
10951256Syl150051 * and/or TCP and/or UDP.
10961256Syl150051 *
10971256Syl150051 * Ask Xframe to calculate IPv4 & transport checksums for _this_ transmit
10981256Syl150051 * descriptor.
10991256Syl150051 * This API is part of the preparation of the transmit descriptor for posting
11001256Syl150051 * (via xge_hal_fifo_dtr_post()). The related "preparation" APIs include
11011256Syl150051 * xge_hal_fifo_dtr_mss_set(), xge_hal_fifo_dtr_buffer_set_aligned(),
11021256Syl150051 * and xge_hal_fifo_dtr_buffer_set().
11031256Syl150051 * All these APIs fill in the fields of the fifo descriptor,
11041256Syl150051 * in accordance with the Xframe specification.
11051256Syl150051 *
11061256Syl150051 * See also: xge_hal_fifo_dtr_reserve(),
11071256Syl150051 * xge_hal_fifo_dtr_post(), XGE_HAL_TXD_TX_CKO_IPV4_EN,
11081256Syl150051 * XGE_HAL_TXD_TX_CKO_TCP_EN.
11091256Syl150051 * Usage: See ex_xmit{}.
11101256Syl150051 */
11111256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
xge_hal_fifo_dtr_cksum_set_bits(xge_hal_dtr_h dtrh,u64 cksum_bits)11121256Syl150051 xge_hal_fifo_dtr_cksum_set_bits(xge_hal_dtr_h dtrh, u64 cksum_bits)
11131256Syl150051 {
11141256Syl150051 xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh;
11151256Syl150051
11161256Syl150051 txdp->control_2 |= cksum_bits;
11171256Syl150051 }
11181256Syl150051
11191256Syl150051
11201256Syl150051 /**
11211256Syl150051 * xge_hal_fifo_dtr_vlan_set - Set VLAN tag.
11221256Syl150051 * @dtrh: Descriptor handle.
11231256Syl150051 * @vlan_tag: 16bit VLAN tag.
11241256Syl150051 *
11251256Syl150051 * Insert VLAN tag into specified transmit descriptor.
11261256Syl150051 * The actual insertion of the tag into outgoing frame is done by the hardware.
11271256Syl150051 * See also: xge_hal_fifo_dtr_buffer_set(), xge_hal_fifo_dtr_mss_set().
11281256Syl150051 */
11291256Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
xge_hal_fifo_dtr_vlan_set(xge_hal_dtr_h dtrh,u16 vlan_tag)11301256Syl150051 xge_hal_fifo_dtr_vlan_set(xge_hal_dtr_h dtrh, u16 vlan_tag)
11311256Syl150051 {
11321256Syl150051 xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh;
11331256Syl150051
11341256Syl150051 txdp->control_2 |= XGE_HAL_TXD_VLAN_ENABLE;
11351256Syl150051 txdp->control_2 |= XGE_HAL_TXD_VLAN_TAG(vlan_tag);
11361256Syl150051 }
11371256Syl150051
1138*3115Syl150051 /**
1139*3115Syl150051 * xge_hal_fifo_is_next_dtr_completed - Checks if the next dtr is completed
1140*3115Syl150051 * @channelh: Channel handle.
1141*3115Syl150051 */
1142*3115Syl150051 __HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e
xge_hal_fifo_is_next_dtr_completed(xge_hal_channel_h channelh)1143*3115Syl150051 xge_hal_fifo_is_next_dtr_completed(xge_hal_channel_h channelh)
1144*3115Syl150051 {
1145*3115Syl150051 xge_hal_fifo_txd_t *txdp;
1146*3115Syl150051 xge_hal_dtr_h dtrh;
11471256Syl150051
1148*3115Syl150051 __hal_channel_dtr_try_complete(channelh, &dtrh);
1149*3115Syl150051 txdp = (xge_hal_fifo_txd_t *)dtrh;
1150*3115Syl150051 if (txdp == NULL) {
1151*3115Syl150051 return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
1152*3115Syl150051 }
1153*3115Syl150051
1154*3115Syl150051 /* check whether host owns it */
1155*3115Syl150051 if ( !(txdp->control_1 & XGE_HAL_TXD_LIST_OWN_XENA) ) {
1156*3115Syl150051 xge_assert(txdp->host_control!=0);
1157*3115Syl150051 return XGE_HAL_OK;
1158*3115Syl150051 }
1159*3115Syl150051
1160*3115Syl150051 /* no more completions */
1161*3115Syl150051 return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
1162*3115Syl150051 }
1163