xref: /freebsd-11-stable/sys/dev/nxge/xgehal/xgehal-fifo-fp.c (revision 4ab2e064d7950be84256d671a7ae93f87cc6aa36)
1 /*-
2  * Copyright (c) 2002-2007 Neterion, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28 
29 #ifdef XGE_DEBUG_FP
30 #include <dev/nxge/include/xgehal-fifo.h>
31 #endif
32 
33 __HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_fifo_txdl_priv_t*
__hal_fifo_txdl_priv(xge_hal_dtr_h dtrh)34 __hal_fifo_txdl_priv(xge_hal_dtr_h dtrh)
35 {
36 	xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t*)dtrh;
37 	xge_hal_fifo_txdl_priv_t *txdl_priv;
38 
39 	xge_assert(txdp);
40 	txdl_priv = (xge_hal_fifo_txdl_priv_t *)
41 	            (ulong_t)txdp->host_control;
42 
43 	xge_assert(txdl_priv);
44 	xge_assert(txdl_priv->dma_object);
45 	xge_assert(txdl_priv->dma_addr);
46 
47 	xge_assert(txdl_priv->dma_object->handle == txdl_priv->dma_handle);
48 
49 	return txdl_priv;
50 }
51 
52 __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)53 __hal_fifo_dtr_post_single(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
54 	        u64 ctrl_1)
55 {
56 	xge_hal_fifo_t            *fifo    = (xge_hal_fifo_t *)channelh;
57 	xge_hal_fifo_hw_pair_t    *hw_pair = fifo->hw_pair;
58 	xge_hal_fifo_txd_t        *txdp    = (xge_hal_fifo_txd_t *)dtrh;
59 	xge_hal_fifo_txdl_priv_t  *txdl_priv;
60 	u64           ctrl;
61 
62 	txdp->control_1 |= XGE_HAL_TXD_LIST_OWN_XENA;
63 
64 #ifdef XGE_DEBUG_ASSERT
65 	    /* make sure Xena overwrites the (illegal) t_code value on completion */
66 	    XGE_HAL_SET_TXD_T_CODE(txdp->control_1, XGE_HAL_TXD_T_CODE_UNUSED_5);
67 #endif
68 
69 	txdl_priv = __hal_fifo_txdl_priv(dtrh);
70 
71 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING)
72 	/* sync the TxDL to device */
73 	xge_os_dma_sync(fifo->channel.pdev,
74 	              txdl_priv->dma_handle,
75 	          txdl_priv->dma_addr,
76 	          txdl_priv->dma_offset,
77 	          txdl_priv->frags << 5 /* sizeof(xge_hal_fifo_txd_t) */,
78 	          XGE_OS_DMA_DIR_TODEVICE);
79 #endif
80 	/* write the pointer first */
81 	xge_os_pio_mem_write64(fifo->channel.pdev,
82 	             fifo->channel.regh1,
83 	                     txdl_priv->dma_addr,
84 	                     &hw_pair->txdl_pointer);
85 
86 	/* spec: 0x00 = 1 TxD in the list */
87 	ctrl = XGE_HAL_TX_FIFO_LAST_TXD_NUM(txdl_priv->frags - 1);
88 	ctrl |= ctrl_1;
89 	ctrl |= fifo->no_snoop_bits;
90 
91 	if (txdp->control_1 & XGE_HAL_TXD_LSO_COF_CTRL(XGE_HAL_TXD_TCP_LSO)) {
92 	    ctrl |= XGE_HAL_TX_FIFO_SPECIAL_FUNC;
93 	}
94 
95 	/*
96 	 * according to the XENA spec:
97 	 *
98 	 * It is important to note that pointers and list control words are
99 	 * always written in pairs: in the first write, the host must write a
100 	 * pointer, and in the second write, it must write the list control
101 	 * word. Any other access will result in an error. Also, all 16 bytes
102 	 * of the pointer/control structure must be written, including any
103 	 * reserved bytes.
104 	 */
105 	xge_os_wmb();
106 
107 	/*
108 	 * we want touch work_arr in order with ownership bit set to HW
109 	 */
110 	__hal_channel_dtr_post(channelh, dtrh);
111 
112 	xge_os_pio_mem_write64(fifo->channel.pdev, fifo->channel.regh1,
113 	        ctrl, &hw_pair->list_control);
114 
115 	xge_debug_fifo(XGE_TRACE, "posted txdl 0x"XGE_OS_LLXFMT" ctrl 0x"XGE_OS_LLXFMT" "
116 	    "into 0x"XGE_OS_LLXFMT"", (unsigned long long)txdl_priv->dma_addr,
117 	    (unsigned long long)ctrl,
118 	    (unsigned long long)(ulong_t)&hw_pair->txdl_pointer);
119 
120 #ifdef XGE_HAL_FIFO_DUMP_TXD
121 	xge_os_printf(""XGE_OS_LLXFMT":"XGE_OS_LLXFMT":"XGE_OS_LLXFMT":"
122 	    XGE_OS_LLXFMT" dma "XGE_OS_LLXFMT,
123 	    txdp->control_1, txdp->control_2, txdp->buffer_pointer,
124 	    txdp->host_control, txdl_priv->dma_addr);
125 #endif
126 
127 	fifo->channel.stats.total_posts++;
128 	fifo->channel.usage_cnt++;
129 	if (fifo->channel.stats.usage_max < fifo->channel.usage_cnt)
130 	    fifo->channel.stats.usage_max = fifo->channel.usage_cnt;
131 }
132 
133 __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)134 __hal_fifo_txdl_free_many(xge_hal_channel_h channelh,
135 	          xge_hal_fifo_txd_t *txdp, int list_size, int frags)
136 {
137 	xge_hal_fifo_txdl_priv_t *current_txdl_priv;
138 	xge_hal_fifo_txdl_priv_t *next_txdl_priv;
139 	int invalid_frags = frags % list_size;
140 	if (invalid_frags){
141 	    xge_debug_fifo(XGE_ERR,
142 	        "freeing corrupt dtrh %p, fragments %d list size %d",
143 	        txdp, frags, list_size);
144 	    xge_assert(invalid_frags == 0);
145 	}
146 	while(txdp){
147 	    xge_debug_fifo(XGE_TRACE,
148 	        "freeing linked dtrh %p, fragments %d list size %d",
149 	        txdp, frags, list_size);
150 	    current_txdl_priv = __hal_fifo_txdl_priv(txdp);
151 #if defined(XGE_DEBUG_ASSERT) && defined(XGE_OS_MEMORY_CHECK)
152 	    current_txdl_priv->allocated = 0;
153 #endif
154 	    __hal_channel_dtr_free(channelh, txdp);
155 	    next_txdl_priv = current_txdl_priv->next_txdl_priv;
156 	    xge_assert(frags);
157 	    frags -= list_size;
158 	    if (next_txdl_priv) {
159 	        current_txdl_priv->next_txdl_priv = NULL;
160 	        txdp = next_txdl_priv->first_txdp;
161 	    }
162 	    else {
163 	        xge_debug_fifo(XGE_TRACE,
164 	        "freed linked dtrh fragments %d list size %d",
165 	        frags, list_size);
166 	        break;
167 	    }
168 	}
169 	xge_assert(frags == 0)
170 }
171 
172 __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)173 __hal_fifo_txdl_restore_many(xge_hal_channel_h channelh,
174 	          xge_hal_fifo_txd_t *txdp, int txdl_count)
175 {
176 	xge_hal_fifo_txdl_priv_t *current_txdl_priv;
177 	xge_hal_fifo_txdl_priv_t *next_txdl_priv;
178 	int i = txdl_count;
179 
180 	xge_assert(((xge_hal_channel_t *)channelh)->reserve_length +
181 	    txdl_count <= ((xge_hal_channel_t *)channelh)->reserve_initial);
182 
183 	current_txdl_priv = __hal_fifo_txdl_priv(txdp);
184 	do{
185 	    xge_assert(i);
186 #if defined(XGE_DEBUG_ASSERT) && defined(XGE_OS_MEMORY_CHECK)
187 	    current_txdl_priv->allocated = 0;
188 #endif
189 	    next_txdl_priv = current_txdl_priv->next_txdl_priv;
190 	    txdp = current_txdl_priv->first_txdp;
191 	    current_txdl_priv->next_txdl_priv = NULL;
192 	    __hal_channel_dtr_restore(channelh, (xge_hal_dtr_h )txdp, --i);
193 	    xge_debug_fifo(XGE_TRACE,
194 	        "dtrh %p restored at offset %d", txdp, i);
195 	    current_txdl_priv = next_txdl_priv;
196 	} while(current_txdl_priv);
197 	__hal_channel_dtr_restore(channelh, NULL, txdl_count);
198 }
199 /**
200  * xge_hal_fifo_dtr_private - Retrieve per-descriptor private data.
201  * @channelh: Channel handle.
202  * @dtrh: Descriptor handle.
203  *
204  * Retrieve per-descriptor private data.
205  * Note that ULD requests per-descriptor space via
206  * xge_hal_channel_open().
207  *
208  * Returns: private ULD data associated with the descriptor.
209  * Usage: See ex_xmit{} and ex_tx_compl{}.
210  */
211 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void*
xge_hal_fifo_dtr_private(xge_hal_dtr_h dtrh)212 xge_hal_fifo_dtr_private(xge_hal_dtr_h dtrh)
213 {
214 	xge_hal_fifo_txd_t *txdp    = (xge_hal_fifo_txd_t *)dtrh;
215 
216 	return ((char *)(ulong_t)txdp->host_control) +
217 	                sizeof(xge_hal_fifo_txdl_priv_t);
218 }
219 
220 /**
221  * xge_hal_fifo_dtr_buffer_cnt - Get number of buffers carried by the
222  * descriptor.
223  * @dtrh: Descriptor handle.
224  *
225  * Returns: Number of buffers stored in the given descriptor. Can be used
226  * _after_ the descriptor is set up for posting (see
227  * xge_hal_fifo_dtr_post()) and _before_ it is deallocated (see
228  * xge_hal_fifo_dtr_free()).
229  *
230  */
231 __HAL_STATIC_FIFO __HAL_INLINE_FIFO int
xge_hal_fifo_dtr_buffer_cnt(xge_hal_dtr_h dtrh)232 xge_hal_fifo_dtr_buffer_cnt(xge_hal_dtr_h dtrh)
233 {
234 	xge_hal_fifo_txdl_priv_t  *txdl_priv;
235 
236 	txdl_priv = __hal_fifo_txdl_priv(dtrh);
237 
238 	return txdl_priv->frags;
239 }
240 /**
241  * xge_hal_fifo_dtr_reserve_many- Reserve fifo descriptors which span more
242  *  than single txdl.
243  * @channelh: Channel handle.
244  * @dtrh: Reserved descriptor. On success HAL fills this "out" parameter
245  *        with a valid handle.
246  * @frags: minimum number of fragments to be reserved.
247  *
248  * Reserve TxDL(s) (that is, fifo descriptor)
249  * for the subsequent filling-in by upper layerdriver (ULD))
250  * and posting on the corresponding channel (@channelh)
251  * via xge_hal_fifo_dtr_post().
252  *
253  * Returns: XGE_HAL_OK - success;
254  * XGE_HAL_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available
255  *
256  * See also: xge_hal_fifo_dtr_reserve_sp(), xge_hal_fifo_dtr_free(),
257  * xge_hal_ring_dtr_reserve(), xge_hal_status_e{}.
258  * Usage: See ex_xmit{}.
259  */
260 __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)261 xge_hal_fifo_dtr_reserve_many(xge_hal_channel_h channelh,
262 	            xge_hal_dtr_h *dtrh, const int frags)
263 {
264 	xge_hal_status_e status = XGE_HAL_OK;
265 	int alloc_frags = 0, dang_frags = 0;
266 	xge_hal_fifo_txd_t *curr_txdp = NULL;
267 	xge_hal_fifo_txd_t *next_txdp;
268 	xge_hal_fifo_txdl_priv_t *next_txdl_priv, *curr_txdl_priv = NULL;
269 	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
270 	int max_frags = fifo->config->max_frags;
271 	xge_hal_dtr_h dang_dtrh = NULL;
272 #if defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
273 	unsigned long flags=0;
274 #endif
275 	xge_debug_fifo(XGE_TRACE, "dtr_reserve_many called for frags %d",
276 	    frags);
277 	xge_assert(frags < (fifo->txdl_per_memblock * max_frags));
278 #if defined(XGE_HAL_TX_MULTI_RESERVE)
279 	xge_os_spin_lock(&fifo->channel.reserve_lock);
280 #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
281 	xge_os_spin_lock_irq(&fifo->channel.reserve_lock, flags);
282 #endif
283 	while(alloc_frags < frags) {
284 	    status = __hal_channel_dtr_alloc(channelh,
285 	            (xge_hal_dtr_h *)(void*)&next_txdp);
286 	    if (status != XGE_HAL_OK){
287 	        xge_debug_fifo(XGE_ERR,
288 	            "failed to allocate linked fragments rc %d",
289 	             status);
290 	        xge_assert(status == XGE_HAL_INF_OUT_OF_DESCRIPTORS);
291 	        if (*dtrh) {
292 	            xge_assert(alloc_frags/max_frags);
293 	            __hal_fifo_txdl_restore_many(channelh,
294 	                (xge_hal_fifo_txd_t *) *dtrh, alloc_frags/max_frags);
295 	        }
296 	        if (dang_dtrh) {
297 	            xge_assert(dang_frags/max_frags);
298 	            __hal_fifo_txdl_restore_many(channelh,
299 	                (xge_hal_fifo_txd_t *) dang_dtrh, dang_frags/max_frags);
300 	        }
301 	        break;
302 	    }
303 	    xge_debug_fifo(XGE_TRACE, "allocated linked dtrh %p"
304 	        " for frags %d", next_txdp, frags);
305 	    next_txdl_priv = __hal_fifo_txdl_priv(next_txdp);
306 	    xge_assert(next_txdl_priv);
307 	    xge_assert(next_txdl_priv->first_txdp == next_txdp);
308 	    next_txdl_priv->dang_txdl = NULL;
309 	    next_txdl_priv->dang_frags = 0;
310 	    next_txdl_priv->next_txdl_priv = NULL;
311 #if defined(XGE_OS_MEMORY_CHECK)
312 	    next_txdl_priv->allocated = 1;
313 #endif
314 	    if (!curr_txdp || !curr_txdl_priv) {
315 	        curr_txdp = next_txdp;
316 	        curr_txdl_priv = next_txdl_priv;
317 	        *dtrh = (xge_hal_dtr_h)next_txdp;
318 	        alloc_frags = max_frags;
319 	        continue;
320 	    }
321 	    if (curr_txdl_priv->memblock ==
322 	        next_txdl_priv->memblock) {
323 	        xge_debug_fifo(XGE_TRACE,
324 	            "linking dtrh %p, with %p",
325 	            *dtrh, next_txdp);
326 	        xge_assert (next_txdp ==
327 	            curr_txdp + max_frags);
328 	        alloc_frags += max_frags;
329 	        curr_txdl_priv->next_txdl_priv = next_txdl_priv;
330 	    }
331 	    else {
332 	        xge_assert(*dtrh);
333 	        xge_assert(dang_dtrh == NULL);
334 	        dang_dtrh = *dtrh;
335 	        dang_frags = alloc_frags;
336 	        xge_debug_fifo(XGE_TRACE,
337 	            "dangling dtrh %p, linked with dtrh %p",
338 	            *dtrh, next_txdp);
339 	        next_txdl_priv->dang_txdl = (xge_hal_fifo_txd_t *) *dtrh;
340 	        next_txdl_priv->dang_frags = alloc_frags;
341 	        alloc_frags = max_frags;
342 	        *dtrh  = next_txdp;
343 	    }
344 	    curr_txdp = next_txdp;
345 	    curr_txdl_priv = next_txdl_priv;
346 	}
347 
348 #if defined(XGE_HAL_TX_MULTI_RESERVE)
349 	xge_os_spin_unlock(&fifo->channel.reserve_lock);
350 #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
351 	xge_os_spin_unlock_irq(&fifo->channel.reserve_lock, flags);
352 #endif
353 
354 	if (status == XGE_HAL_OK) {
355 	    xge_hal_fifo_txdl_priv_t * txdl_priv;
356 	    xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)*dtrh;
357 	    xge_hal_stats_channel_info_t *statsp = &fifo->channel.stats;
358 	    txdl_priv = __hal_fifo_txdl_priv(txdp);
359 	    /* reset the TxDL's private */
360 	    txdl_priv->align_dma_offset = 0;
361 	    txdl_priv->align_vaddr_start = txdl_priv->align_vaddr;
362 	    txdl_priv->align_used_frags = 0;
363 	    txdl_priv->frags = 0;
364 	    txdl_priv->bytes_sent = 0;
365 	    txdl_priv->alloc_frags = alloc_frags;
366 	    /* reset TxD0 */
367 	    txdp->control_1 = txdp->control_2 = 0;
368 
369 #if defined(XGE_OS_MEMORY_CHECK)
370 	    txdl_priv->allocated = 1;
371 #endif
372 	    /* update statistics */
373 	    statsp->total_posts_dtrs_many++;
374 	    statsp->total_posts_frags_many += txdl_priv->alloc_frags;
375 	    if (txdl_priv->dang_frags){
376 	        statsp->total_posts_dang_dtrs++;
377 	        statsp->total_posts_dang_frags += txdl_priv->dang_frags;
378 	    }
379 	}
380 
381 	return status;
382 }
383 
384 /**
385  * xge_hal_fifo_dtr_reserve - Reserve fifo descriptor.
386  * @channelh: Channel handle.
387  * @dtrh: Reserved descriptor. On success HAL fills this "out" parameter
388  *        with a valid handle.
389  *
390  * Reserve a single TxDL (that is, fifo descriptor)
391  * for the subsequent filling-in by upper layerdriver (ULD))
392  * and posting on the corresponding channel (@channelh)
393  * via xge_hal_fifo_dtr_post().
394  *
395  * Note: it is the responsibility of ULD to reserve multiple descriptors
396  * for lengthy (e.g., LSO) transmit operation. A single fifo descriptor
397  * carries up to configured number (fifo.max_frags) of contiguous buffers.
398  *
399  * Returns: XGE_HAL_OK - success;
400  * XGE_HAL_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available
401  *
402  * See also: xge_hal_fifo_dtr_reserve_sp(), xge_hal_fifo_dtr_free(),
403  * xge_hal_ring_dtr_reserve(), xge_hal_status_e{}.
404  * Usage: See ex_xmit{}.
405  */
406 __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)407 xge_hal_fifo_dtr_reserve(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh)
408 {
409 	xge_hal_status_e status;
410 #if defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
411 	unsigned long flags=0;
412 #endif
413 
414 #if defined(XGE_HAL_TX_MULTI_RESERVE)
415 	xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->reserve_lock);
416 #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
417 	xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->reserve_lock,
418 	                     flags);
419 #endif
420 
421 	status = __hal_channel_dtr_alloc(channelh, dtrh);
422 
423 #if defined(XGE_HAL_TX_MULTI_RESERVE)
424 	xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->reserve_lock);
425 #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
426 	xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->reserve_lock,
427 	                       flags);
428 #endif
429 
430 	if (status == XGE_HAL_OK) {
431 	    xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)*dtrh;
432 	    xge_hal_fifo_txdl_priv_t *txdl_priv;
433 
434 	    txdl_priv = __hal_fifo_txdl_priv(txdp);
435 
436 	    /* reset the TxDL's private */
437 	    txdl_priv->align_dma_offset = 0;
438 	    txdl_priv->align_vaddr_start = txdl_priv->align_vaddr;
439 	    txdl_priv->align_used_frags = 0;
440 	    txdl_priv->frags = 0;
441 	    txdl_priv->alloc_frags =
442 	        ((xge_hal_fifo_t *)channelh)->config->max_frags;
443 	    txdl_priv->dang_txdl = NULL;
444 	    txdl_priv->dang_frags = 0;
445 	    txdl_priv->next_txdl_priv = NULL;
446 	    txdl_priv->bytes_sent = 0;
447 
448 	    /* reset TxD0 */
449 	    txdp->control_1 = txdp->control_2 = 0;
450 
451 #if defined(XGE_OS_MEMORY_CHECK)
452 	    txdl_priv->allocated = 1;
453 #endif
454 	}
455 
456 	return status;
457 }
458 
459 /**
460  * xge_hal_fifo_dtr_reserve_sp - Reserve fifo descriptor and store it in
461  * the ULD-provided "scratch" memory.
462  * @channelh: Channel handle.
463  * @dtr_sp_size: Size of the %dtr_sp "scratch pad" that HAL can use for TxDL.
464  * @dtr_sp: "Scratch pad" supplied by upper-layer driver (ULD).
465  *
466  * Reserve TxDL and fill-in ULD supplied "scratch pad". The difference
467  * between this API and xge_hal_fifo_dtr_reserve() is (possibly) -
468  * performance.
469  *
470  * If upper-layer uses ULP-defined commands, and if those commands have enough
471  * space for HAL/Xframe descriptors - tnan it is better (read: faster) to fit
472  * all the per-command information into one command, which is typically
473  * one contiguous block.
474  *
475  * Note: Unlike xge_hal_fifo_dtr_reserve(), this function can be used to
476  * allocate a single descriptor for transmit operation.
477  *
478  * See also: xge_hal_fifo_dtr_reserve(), xge_hal_fifo_dtr_free(),
479  * xge_hal_ring_dtr_reserve(), xge_hal_status_e{}.
480  */
481 __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)482 xge_hal_fifo_dtr_reserve_sp(xge_hal_channel_h channelh, int dtr_sp_size,
483 	        xge_hal_dtr_h dtr_sp)
484 {
485 	/* FIXME: implement */
486 	return XGE_HAL_OK;
487 }
488 
489 /**
490  * xge_hal_fifo_dtr_post - Post descriptor on the fifo channel.
491  * @channelh: Channel handle.
492  * @dtrh: Descriptor obtained via xge_hal_fifo_dtr_reserve() or
493  * xge_hal_fifo_dtr_reserve_sp()
494  * @frags: Number of contiguous buffers that are part of a single
495  *         transmit operation.
496  *
497  * Post descriptor on the 'fifo' type channel for transmission.
498  * Prior to posting the descriptor should be filled in accordance with
499  * Host/Xframe interface specification for a given service (LL, etc.).
500  *
501  * See also: xge_hal_fifo_dtr_post_many(), xge_hal_ring_dtr_post().
502  * Usage: See ex_xmit{}.
503  */
504 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
xge_hal_fifo_dtr_post(xge_hal_channel_h channelh,xge_hal_dtr_h dtrh)505 xge_hal_fifo_dtr_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh)
506 {
507 	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
508 	xge_hal_fifo_txdl_priv_t *txdl_priv;
509 	xge_hal_fifo_txd_t *txdp_last;
510 	xge_hal_fifo_txd_t *txdp_first;
511 #if defined(XGE_HAL_TX_MULTI_POST_IRQ)
512 	unsigned long flags = 0;
513 #endif
514 
515 	txdl_priv = __hal_fifo_txdl_priv(dtrh);
516 
517 	txdp_first = (xge_hal_fifo_txd_t *)dtrh;
518 	txdp_first->control_1 |= XGE_HAL_TXD_GATHER_CODE_FIRST;
519 	txdp_first->control_2 |= fifo->interrupt_type;
520 
521 	txdp_last = (xge_hal_fifo_txd_t *)dtrh + (txdl_priv->frags - 1);
522 	txdp_last->control_1 |= XGE_HAL_TXD_GATHER_CODE_LAST;
523 
524 #if defined(XGE_HAL_TX_MULTI_POST)
525 	xge_os_spin_lock(fifo->post_lock_ptr);
526 #elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
527 	xge_os_spin_lock_irq(fifo->post_lock_ptr, flags);
528 #endif
529 
530 	__hal_fifo_dtr_post_single(channelh, dtrh,
531 	     (u64)(XGE_HAL_TX_FIFO_FIRST_LIST | XGE_HAL_TX_FIFO_LAST_LIST));
532 
533 #if defined(XGE_HAL_TX_MULTI_POST)
534 	xge_os_spin_unlock(fifo->post_lock_ptr);
535 #elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
536 	xge_os_spin_unlock_irq(fifo->post_lock_ptr, flags);
537 #endif
538 }
539 
540 /**
541  * xge_hal_fifo_dtr_post_many - Post multiple descriptors on fifo
542  * channel.
543  * @channelh: Channel to post descriptor.
544  * @num: Number of descriptors (i.e., fifo TxDLs) in the %dtrs[].
545  * @dtrs: Descriptors obtained via xge_hal_fifo_dtr_reserve().
546  * @frags_arr: Number of fragments carried @dtrs descriptors.
547  * Note that frag_arr[i] corresponds to descriptor dtrs[i].
548  *
549  * Post multi-descriptor on the fifo channel. The operation is atomic:
550  * all descriptrs are posted on the channel "back-to-back' without
551  * letting other posts (possibly driven by multiple transmitting threads)
552  * to interleave.
553  *
554  * See also: xge_hal_fifo_dtr_post(), xge_hal_ring_dtr_post().
555  */
556 __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[])557 xge_hal_fifo_dtr_post_many(xge_hal_channel_h channelh, int num,
558 	        xge_hal_dtr_h dtrs[])
559 {
560 	int i;
561 	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
562 	xge_hal_fifo_txd_t *txdp_last;
563 	xge_hal_fifo_txd_t *txdp_first;
564 	xge_hal_fifo_txdl_priv_t *txdl_priv_last;
565 #if defined(XGE_HAL_TX_MULTI_POST_IRQ)
566 	unsigned long flags = 0;
567 #endif
568 
569 	xge_assert(num > 1);
570 
571 	txdp_first = (xge_hal_fifo_txd_t *)dtrs[0];
572 	txdp_first->control_1 |= XGE_HAL_TXD_GATHER_CODE_FIRST;
573 	txdp_first->control_2 |= fifo->interrupt_type;
574 
575 	txdl_priv_last = __hal_fifo_txdl_priv(dtrs[num-1]);
576 	txdp_last = (xge_hal_fifo_txd_t *)dtrs[num-1] +
577 	                (txdl_priv_last->frags - 1);
578 	txdp_last->control_1 |= XGE_HAL_TXD_GATHER_CODE_LAST;
579 
580 #if defined(XGE_HAL_TX_MULTI_POST)
581 	xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->post_lock);
582 #elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
583 	xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->post_lock,
584 	flags);
585 #endif
586 
587 	for (i=0; i<num; i++) {
588 	    xge_hal_fifo_txdl_priv_t *txdl_priv;
589 	    u64 val64;
590 	    xge_hal_dtr_h dtrh = dtrs[i];
591 
592 	    txdl_priv = __hal_fifo_txdl_priv(dtrh);
593 	    txdl_priv = txdl_priv; /* Cheat lint */
594 
595 	    val64 = 0;
596 	    if (i == 0) {
597 	         val64 |= XGE_HAL_TX_FIFO_FIRST_LIST;
598 	    } else if (i == num -1) {
599 	         val64 |= XGE_HAL_TX_FIFO_LAST_LIST;
600 	    }
601 
602 	    val64 |= XGE_HAL_TX_FIFO_SPECIAL_FUNC;
603 	    __hal_fifo_dtr_post_single(channelh, dtrh, val64);
604 	}
605 
606 #if defined(XGE_HAL_TX_MULTI_POST)
607 	xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->post_lock);
608 #elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
609 	xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->post_lock,
610 	flags);
611 #endif
612 
613 	fifo->channel.stats.total_posts_many++;
614 }
615 
616 /**
617  * xge_hal_fifo_dtr_next_completed - Retrieve next completed descriptor.
618  * @channelh: Channel handle.
619  * @dtrh: Descriptor handle. Returned by HAL.
620  * @t_code: Transfer code, as per Xframe User Guide,
621  *          Transmit Descriptor Format.
622  *          Returned by HAL.
623  *
624  * Retrieve the _next_ completed descriptor.
625  * HAL uses channel callback (*xge_hal_channel_callback_f) to notifiy
626  * upper-layer driver (ULD) of new completed descriptors. After that
627  * the ULD can use xge_hal_fifo_dtr_next_completed to retrieve the rest
628  * completions (the very first completion is passed by HAL via
629  * xge_hal_channel_callback_f).
630  *
631  * Implementation-wise, the upper-layer driver is free to call
632  * xge_hal_fifo_dtr_next_completed either immediately from inside the
633  * channel callback, or in a deferred fashion and separate (from HAL)
634  * context.
635  *
636  * Non-zero @t_code means failure to process the descriptor.
637  * The failure could happen, for instance, when the link is
638  * down, in which case Xframe completes the descriptor because it
639  * is not able to send the data out.
640  *
641  * For details please refer to Xframe User Guide.
642  *
643  * Returns: XGE_HAL_OK - success.
644  * XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed descriptors
645  * are currently available for processing.
646  *
647  * See also: xge_hal_channel_callback_f{},
648  * xge_hal_ring_dtr_next_completed().
649  * Usage: See ex_tx_compl{}.
650  */
651 __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)652 xge_hal_fifo_dtr_next_completed(xge_hal_channel_h channelh,
653 	        xge_hal_dtr_h *dtrh, u8 *t_code)
654 {
655 	xge_hal_fifo_txd_t        *txdp;
656 	xge_hal_fifo_t            *fifo    = (xge_hal_fifo_t *)channelh;
657 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING)
658 	xge_hal_fifo_txdl_priv_t  *txdl_priv;
659 #endif
660 
661 	__hal_channel_dtr_try_complete(channelh, dtrh);
662 	txdp = (xge_hal_fifo_txd_t *)*dtrh;
663 	if (txdp == NULL) {
664 	    return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
665 	}
666 
667 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING)
668 	txdl_priv = __hal_fifo_txdl_priv(txdp);
669 
670 	/* sync TxDL to read the ownership
671 	 *
672 	 * Note: 16bytes means Control_1 & Control_2 */
673 	xge_os_dma_sync(fifo->channel.pdev,
674 	              txdl_priv->dma_handle,
675 	          txdl_priv->dma_addr,
676 	          txdl_priv->dma_offset,
677 	          16,
678 	          XGE_OS_DMA_DIR_FROMDEVICE);
679 #endif
680 
681 	/* check whether host owns it */
682 	if ( !(txdp->control_1 & XGE_HAL_TXD_LIST_OWN_XENA) ) {
683 
684 	    xge_assert(txdp->host_control!=0);
685 
686 	    __hal_channel_dtr_complete(channelh);
687 
688 	    *t_code = (u8)XGE_HAL_GET_TXD_T_CODE(txdp->control_1);
689 
690 	            /* see XGE_HAL_SET_TXD_T_CODE() above.. */
691 	            xge_assert(*t_code != XGE_HAL_TXD_T_CODE_UNUSED_5);
692 
693 	    if (fifo->channel.usage_cnt > 0)
694 	        fifo->channel.usage_cnt--;
695 
696 	    return XGE_HAL_OK;
697 	}
698 
699 	/* no more completions */
700 	*dtrh = 0;
701 	return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
702 }
703 
704 /**
705  * xge_hal_fifo_dtr_free - Free descriptor.
706  * @channelh: Channel handle.
707  * @dtr: Descriptor handle.
708  *
709  * Free the reserved descriptor. This operation is "symmetrical" to
710  * xge_hal_fifo_dtr_reserve or xge_hal_fifo_dtr_reserve_sp.
711  * The "free-ing" completes the descriptor's lifecycle.
712  *
713  * After free-ing (see xge_hal_fifo_dtr_free()) the descriptor again can
714  * be:
715  *
716  * - reserved (xge_hal_fifo_dtr_reserve);
717  *
718  * - posted (xge_hal_fifo_dtr_post);
719  *
720  * - completed (xge_hal_fifo_dtr_next_completed);
721  *
722  * - and recycled again (xge_hal_fifo_dtr_free).
723  *
724  * For alternative state transitions and more details please refer to
725  * the design doc.
726  *
727  * See also: xge_hal_ring_dtr_free(), xge_hal_fifo_dtr_reserve().
728  * Usage: See ex_tx_compl{}.
729  */
730 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
xge_hal_fifo_dtr_free(xge_hal_channel_h channelh,xge_hal_dtr_h dtr)731 xge_hal_fifo_dtr_free(xge_hal_channel_h channelh, xge_hal_dtr_h dtr)
732 {
733 #if defined(XGE_HAL_TX_MULTI_FREE_IRQ)
734 	unsigned long flags = 0;
735 #endif
736 	xge_hal_fifo_txdl_priv_t *txdl_priv = __hal_fifo_txdl_priv(
737 	                (xge_hal_fifo_txd_t *)dtr);
738 	int max_frags = ((xge_hal_fifo_t *)channelh)->config->max_frags;
739 #if defined(XGE_HAL_TX_MULTI_FREE)
740 	xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->free_lock);
741 #elif defined(XGE_HAL_TX_MULTI_FREE_IRQ)
742 	xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->free_lock,
743 	flags);
744 #endif
745 
746 	if (txdl_priv->alloc_frags > max_frags) {
747 	    xge_hal_fifo_txd_t *dang_txdp = (xge_hal_fifo_txd_t *)
748 	                    txdl_priv->dang_txdl;
749 	    int dang_frags = txdl_priv->dang_frags;
750 	    int alloc_frags = txdl_priv->alloc_frags;
751 	    txdl_priv->dang_txdl = NULL;
752 	    txdl_priv->dang_frags = 0;
753 	    txdl_priv->alloc_frags = 0;
754 	    /* dtrh must have a linked list of dtrh */
755 	    xge_assert(txdl_priv->next_txdl_priv);
756 
757 	    /* free any dangling dtrh first */
758 	    if (dang_txdp) {
759 	        xge_debug_fifo(XGE_TRACE,
760 	            "freeing dangled dtrh %p for %d fragments",
761 	            dang_txdp, dang_frags);
762 	        __hal_fifo_txdl_free_many(channelh, dang_txdp,
763 	            max_frags, dang_frags);
764 	    }
765 
766 	    /* now free the reserved dtrh list */
767 	    xge_debug_fifo(XGE_TRACE,
768 	            "freeing dtrh %p list of %d fragments", dtr,
769 	            alloc_frags);
770 	    __hal_fifo_txdl_free_many(channelh,
771 	            (xge_hal_fifo_txd_t *)dtr, max_frags,
772 	            alloc_frags);
773 	}
774 	else
775 	    __hal_channel_dtr_free(channelh, dtr);
776 
777 	((xge_hal_channel_t *)channelh)->poll_bytes += txdl_priv->bytes_sent;
778 
779 #if defined(XGE_DEBUG_ASSERT) && defined(XGE_OS_MEMORY_CHECK)
780 	__hal_fifo_txdl_priv(dtr)->allocated = 0;
781 #endif
782 
783 #if defined(XGE_HAL_TX_MULTI_FREE)
784 	xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->free_lock);
785 #elif defined(XGE_HAL_TX_MULTI_FREE_IRQ)
786 	xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->free_lock,
787 	flags);
788 #endif
789 }
790 
791 
792 /**
793  * xge_hal_fifo_dtr_buffer_set_aligned - Align transmit buffer and fill
794  * in fifo descriptor.
795  * @channelh: Channel handle.
796  * @dtrh: Descriptor handle.
797  * @frag_idx: Index of the data buffer in the caller's scatter-gather list
798  *            (of buffers).
799  * @vaddr: Virtual address of the data buffer.
800  * @dma_pointer: DMA address of the data buffer referenced by @frag_idx.
801  * @size: Size of the data buffer (in bytes).
802  * @misaligned_size: Size (in bytes) of the misaligned portion of the
803  * data buffer. Calculated by the caller, based on the platform/OS/other
804  * specific criteria, which is outside of HAL's domain. See notes below.
805  *
806  * This API is part of the transmit descriptor preparation for posting
807  * (via xge_hal_fifo_dtr_post()). The related "preparation" APIs include
808  * xge_hal_fifo_dtr_mss_set() and xge_hal_fifo_dtr_cksum_set_bits().
809  * All three APIs fill in the fields of the fifo descriptor,
810  * in accordance with the Xframe specification.
811  * On the PCI-X based systems aligning transmit data typically provides better
812  * transmit performance. The typical alignment granularity: L2 cacheline size.
813  * However, HAL does not make assumptions in terms of the alignment granularity;
814  * this is specified via additional @misaligned_size parameter described above.
815  * Prior to calling xge_hal_fifo_dtr_buffer_set_aligned(),
816  * ULD is supposed to check alignment of a given fragment/buffer. For this HAL
817  * provides a separate xge_hal_check_alignment() API sufficient to cover
818  * most (but not all) possible alignment criteria.
819  * If the buffer appears to be aligned, the ULD calls
820  * xge_hal_fifo_dtr_buffer_set().
821  * Otherwise, ULD calls xge_hal_fifo_dtr_buffer_set_aligned().
822  *
823  * Note; This API is a "superset" of xge_hal_fifo_dtr_buffer_set(). In
824  * addition to filling in the specified descriptor it aligns transmit data on
825  * the specified boundary.
826  * Note: Decision on whether to align or not to align a given contiguous
827  * transmit buffer is outside of HAL's domain. To this end ULD can use any
828  * programmable criteria, which can help to 1) boost transmit performance,
829  * and/or 2) provide a workaround for PCI bridge bugs, if any.
830  *
831  * See also: xge_hal_fifo_dtr_buffer_set(),
832  * xge_hal_check_alignment().
833  *
834  * See also: xge_hal_fifo_dtr_reserve(), xge_hal_fifo_dtr_post(),
835  * xge_hal_fifo_dtr_mss_set(), xge_hal_fifo_dtr_cksum_set_bits()
836  */
837 __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)838 xge_hal_fifo_dtr_buffer_set_aligned(xge_hal_channel_h channelh,
839 	        xge_hal_dtr_h dtrh, int frag_idx, void *vaddr,
840 	        dma_addr_t dma_pointer, int size, int misaligned_size)
841 {
842 	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
843 	xge_hal_fifo_txdl_priv_t *txdl_priv;
844 	xge_hal_fifo_txd_t *txdp;
845 	int remaining_size;
846 	ptrdiff_t prev_boff;
847 
848 	txdl_priv = __hal_fifo_txdl_priv(dtrh);
849 	txdp = (xge_hal_fifo_txd_t *)dtrh + txdl_priv->frags;
850 
851 	if (frag_idx != 0) {
852 	    txdp->control_1 = txdp->control_2 = 0;
853 	}
854 
855 	/* On some systems buffer size could be zero.
856 	 * It is the responsibility of ULD and *not HAL* to
857 	 * detect it and skip it. */
858 	xge_assert(size > 0);
859 	xge_assert(frag_idx < txdl_priv->alloc_frags);
860 	xge_assert(misaligned_size != 0 &&
861 	        misaligned_size <= fifo->config->alignment_size);
862 
863 	remaining_size = size - misaligned_size;
864 	xge_assert(remaining_size >= 0);
865 
866 	xge_os_memcpy((char*)txdl_priv->align_vaddr_start,
867 	                  vaddr, misaligned_size);
868 
869 	    if (txdl_priv->align_used_frags >= fifo->config->max_aligned_frags) {
870 	        return XGE_HAL_ERR_OUT_ALIGNED_FRAGS;
871 	    }
872 
873 	/* setup new buffer */
874 	prev_boff = txdl_priv->align_vaddr_start - txdl_priv->align_vaddr;
875 	txdp->buffer_pointer = (u64)txdl_priv->align_dma_addr + prev_boff;
876 	txdp->control_1 |= XGE_HAL_TXD_BUFFER0_SIZE(misaligned_size);
877 	txdl_priv->bytes_sent += misaligned_size;
878 	fifo->channel.stats.total_buffers++;
879 	txdl_priv->frags++;
880 	txdl_priv->align_used_frags++;
881 	txdl_priv->align_vaddr_start += fifo->config->alignment_size;
882 	    txdl_priv->align_dma_offset = 0;
883 
884 #if defined(XGE_OS_DMA_REQUIRES_SYNC)
885 	/* sync new buffer */
886 	xge_os_dma_sync(fifo->channel.pdev,
887 	          txdl_priv->align_dma_handle,
888 	          txdp->buffer_pointer,
889 	          0,
890 	          misaligned_size,
891 	          XGE_OS_DMA_DIR_TODEVICE);
892 #endif
893 
894 	if (remaining_size) {
895 	    xge_assert(frag_idx < txdl_priv->alloc_frags);
896 	    txdp++;
897 	    txdp->buffer_pointer = (u64)dma_pointer +
898 	                misaligned_size;
899 	    txdp->control_1 =
900 	        XGE_HAL_TXD_BUFFER0_SIZE(remaining_size);
901 	    txdl_priv->bytes_sent += remaining_size;
902 	    txdp->control_2 = 0;
903 	    fifo->channel.stats.total_buffers++;
904 	    txdl_priv->frags++;
905 	}
906 
907 	return XGE_HAL_OK;
908 }
909 
910 /**
911  * xge_hal_fifo_dtr_buffer_append - Append the contents of virtually
912  * contiguous data buffer to a single physically contiguous buffer.
913  * @channelh: Channel handle.
914  * @dtrh: Descriptor handle.
915  * @vaddr: Virtual address of the data buffer.
916  * @size: Size of the data buffer (in bytes).
917  *
918  * This API is part of the transmit descriptor preparation for posting
919  * (via xge_hal_fifo_dtr_post()).
920  * The main difference of this API wrt to the APIs
921  * xge_hal_fifo_dtr_buffer_set_aligned() is that this API appends the
922  * contents of virtually contiguous data buffers received from
923  * upper layer into a single physically contiguous data buffer and the
924  * device will do a DMA from this buffer.
925  *
926  * See Also: xge_hal_fifo_dtr_buffer_finalize(), xge_hal_fifo_dtr_buffer_set(),
927  * xge_hal_fifo_dtr_buffer_set_aligned().
928  */
929 __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)930 xge_hal_fifo_dtr_buffer_append(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
931 	    void *vaddr, int size)
932 {
933 	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
934 	xge_hal_fifo_txdl_priv_t *txdl_priv;
935 	ptrdiff_t used;
936 
937 	xge_assert(size > 0);
938 
939 	txdl_priv = __hal_fifo_txdl_priv(dtrh);
940 
941 	used = txdl_priv->align_vaddr_start - txdl_priv->align_vaddr;
942 	used += txdl_priv->align_dma_offset;
943 	if (used + (unsigned int)size > (unsigned int)fifo->align_size)
944 	        return XGE_HAL_ERR_OUT_ALIGNED_FRAGS;
945 
946 	xge_os_memcpy((char*)txdl_priv->align_vaddr_start +
947 	    txdl_priv->align_dma_offset, vaddr, size);
948 
949 	fifo->channel.stats.copied_frags++;
950 
951 	txdl_priv->align_dma_offset += size;
952 	return XGE_HAL_OK;
953 }
954 
955 /**
956  * xge_hal_fifo_dtr_buffer_finalize - Prepares a descriptor that contains the
957  * single physically contiguous buffer.
958  *
959  * @channelh: Channel handle.
960  * @dtrh: Descriptor handle.
961  * @frag_idx: Index of the data buffer in the Txdl list.
962  *
963  * This API in conjuction with xge_hal_fifo_dtr_buffer_append() prepares
964  * a descriptor that consists of a single physically contiguous buffer
965  * which inturn contains the contents of one or more virtually contiguous
966  * buffers received from the upper layer.
967  *
968  * See Also: xge_hal_fifo_dtr_buffer_append().
969 */
970 __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)971 xge_hal_fifo_dtr_buffer_finalize(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
972 	    int frag_idx)
973 {
974 	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
975 	xge_hal_fifo_txdl_priv_t *txdl_priv;
976 	xge_hal_fifo_txd_t *txdp;
977 	ptrdiff_t prev_boff;
978 
979 	xge_assert(frag_idx < fifo->config->max_frags);
980 
981 	txdl_priv = __hal_fifo_txdl_priv(dtrh);
982 	txdp = (xge_hal_fifo_txd_t *)dtrh + txdl_priv->frags;
983 
984 	if (frag_idx != 0) {
985 	    txdp->control_1 = txdp->control_2 = 0;
986 	}
987 
988 	prev_boff = txdl_priv->align_vaddr_start - txdl_priv->align_vaddr;
989 	txdp->buffer_pointer = (u64)txdl_priv->align_dma_addr + prev_boff;
990 	txdp->control_1 |=
991 	            XGE_HAL_TXD_BUFFER0_SIZE(txdl_priv->align_dma_offset);
992 	txdl_priv->bytes_sent += (unsigned int)txdl_priv->align_dma_offset;
993 	fifo->channel.stats.total_buffers++;
994 	fifo->channel.stats.copied_buffers++;
995 	txdl_priv->frags++;
996 	txdl_priv->align_used_frags++;
997 
998 #if defined(XGE_OS_DMA_REQUIRES_SYNC)
999 	/* sync pre-mapped buffer */
1000 	xge_os_dma_sync(fifo->channel.pdev,
1001 	          txdl_priv->align_dma_handle,
1002 	          txdp->buffer_pointer,
1003 	          0,
1004 	          txdl_priv->align_dma_offset,
1005 	          XGE_OS_DMA_DIR_TODEVICE);
1006 #endif
1007 
1008 	/* increment vaddr_start for the next buffer_append() iteration */
1009 	txdl_priv->align_vaddr_start += txdl_priv->align_dma_offset;
1010 	    txdl_priv->align_dma_offset = 0;
1011 }
1012 
1013 /**
1014  * xge_hal_fifo_dtr_buffer_set - Set transmit buffer pointer in the
1015  * descriptor.
1016  * @channelh: Channel handle.
1017  * @dtrh: Descriptor handle.
1018  * @frag_idx: Index of the data buffer in the caller's scatter-gather list
1019  *            (of buffers).
1020  * @dma_pointer: DMA address of the data buffer referenced by @frag_idx.
1021  * @size: Size of the data buffer (in bytes).
1022  *
1023  * This API is part of the preparation of the transmit descriptor for posting
1024  * (via xge_hal_fifo_dtr_post()). The related "preparation" APIs include
1025  * xge_hal_fifo_dtr_mss_set() and xge_hal_fifo_dtr_cksum_set_bits().
1026  * All three APIs fill in the fields of the fifo descriptor,
1027  * in accordance with the Xframe specification.
1028  *
1029  * See also: xge_hal_fifo_dtr_buffer_set_aligned(),
1030  * xge_hal_check_alignment().
1031  *
1032  * See also: xge_hal_fifo_dtr_reserve(), xge_hal_fifo_dtr_post(),
1033  * xge_hal_fifo_dtr_mss_set(), xge_hal_fifo_dtr_cksum_set_bits()
1034  * Prepare transmit descriptor for transmission (via
1035  * xge_hal_fifo_dtr_post()).
1036  * See also: xge_hal_fifo_dtr_vlan_set().
1037  * Note: Compare with xge_hal_fifo_dtr_buffer_set_aligned().
1038  *
1039  * Usage: See ex_xmit{}.
1040  */
1041 __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)1042 xge_hal_fifo_dtr_buffer_set(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
1043 	    int frag_idx, dma_addr_t dma_pointer, int size)
1044 {
1045 	xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
1046 	xge_hal_fifo_txdl_priv_t *txdl_priv;
1047 	xge_hal_fifo_txd_t *txdp;
1048 
1049 	txdl_priv = __hal_fifo_txdl_priv(dtrh);
1050 	txdp = (xge_hal_fifo_txd_t *)dtrh + txdl_priv->frags;
1051 
1052 	if (frag_idx != 0) {
1053 	    txdp->control_1 = txdp->control_2 = 0;
1054 	}
1055 
1056 	/* Note:
1057 	 * it is the responsibility of upper layers and not HAL
1058 	 * detect it and skip zero-size fragment
1059 	 */
1060 	xge_assert(size > 0);
1061 	xge_assert(frag_idx < txdl_priv->alloc_frags);
1062 
1063 	txdp->buffer_pointer = (u64)dma_pointer;
1064 	txdp->control_1 |= XGE_HAL_TXD_BUFFER0_SIZE(size);
1065 	txdl_priv->bytes_sent += size;
1066 	fifo->channel.stats.total_buffers++;
1067 	txdl_priv->frags++;
1068 }
1069 
1070 /**
1071  * xge_hal_fifo_dtr_mss_set - Set MSS.
1072  * @dtrh: Descriptor handle.
1073  * @mss: MSS size for _this_ TCP connection. Passed by TCP stack down to the
1074  *       ULD, which in turn inserts the MSS into the @dtrh.
1075  *
1076  * This API is part of the preparation of the transmit descriptor for posting
1077  * (via xge_hal_fifo_dtr_post()). The related "preparation" APIs include
1078  * xge_hal_fifo_dtr_buffer_set(), xge_hal_fifo_dtr_buffer_set_aligned(),
1079  * and xge_hal_fifo_dtr_cksum_set_bits().
1080  * All these APIs fill in the fields of the fifo descriptor,
1081  * in accordance with the Xframe specification.
1082  *
1083  * See also: xge_hal_fifo_dtr_reserve(),
1084  * xge_hal_fifo_dtr_post(), xge_hal_fifo_dtr_vlan_set().
1085  * Usage: See ex_xmit{}.
1086  */
1087 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
xge_hal_fifo_dtr_mss_set(xge_hal_dtr_h dtrh,int mss)1088 xge_hal_fifo_dtr_mss_set(xge_hal_dtr_h dtrh, int mss)
1089 {
1090 	xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh;
1091 
1092 	txdp->control_1 |= XGE_HAL_TXD_LSO_COF_CTRL(XGE_HAL_TXD_TCP_LSO);
1093 	txdp->control_1 |= XGE_HAL_TXD_TCP_LSO_MSS(mss);
1094 }
1095 
1096 /**
1097  * xge_hal_fifo_dtr_cksum_set_bits - Offload checksum.
1098  * @dtrh: Descriptor handle.
1099  * @cksum_bits: Specifies which checksums are to be offloaded: IPv4,
1100  *              and/or TCP and/or UDP.
1101  *
1102  * Ask Xframe to calculate IPv4 & transport checksums for _this_ transmit
1103  * descriptor.
1104  * This API is part of the preparation of the transmit descriptor for posting
1105  * (via xge_hal_fifo_dtr_post()). The related "preparation" APIs include
1106  * xge_hal_fifo_dtr_mss_set(), xge_hal_fifo_dtr_buffer_set_aligned(),
1107  * and xge_hal_fifo_dtr_buffer_set().
1108  * All these APIs fill in the fields of the fifo descriptor,
1109  * in accordance with the Xframe specification.
1110  *
1111  * See also: xge_hal_fifo_dtr_reserve(),
1112  * xge_hal_fifo_dtr_post(), XGE_HAL_TXD_TX_CKO_IPV4_EN,
1113  * XGE_HAL_TXD_TX_CKO_TCP_EN.
1114  * Usage: See ex_xmit{}.
1115  */
1116 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
xge_hal_fifo_dtr_cksum_set_bits(xge_hal_dtr_h dtrh,u64 cksum_bits)1117 xge_hal_fifo_dtr_cksum_set_bits(xge_hal_dtr_h dtrh, u64 cksum_bits)
1118 {
1119 	xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh;
1120 
1121 	txdp->control_2 |= cksum_bits;
1122 }
1123 
1124 
1125 /**
1126  * xge_hal_fifo_dtr_vlan_set - Set VLAN tag.
1127  * @dtrh: Descriptor handle.
1128  * @vlan_tag: 16bit VLAN tag.
1129  *
1130  * Insert VLAN tag into specified transmit descriptor.
1131  * The actual insertion of the tag into outgoing frame is done by the hardware.
1132  * See also: xge_hal_fifo_dtr_buffer_set(), xge_hal_fifo_dtr_mss_set().
1133  */
1134 __HAL_STATIC_FIFO __HAL_INLINE_FIFO void
xge_hal_fifo_dtr_vlan_set(xge_hal_dtr_h dtrh,u16 vlan_tag)1135 xge_hal_fifo_dtr_vlan_set(xge_hal_dtr_h dtrh, u16 vlan_tag)
1136 {
1137 	xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh;
1138 
1139 	txdp->control_2 |= XGE_HAL_TXD_VLAN_ENABLE;
1140 	txdp->control_2 |= XGE_HAL_TXD_VLAN_TAG(vlan_tag);
1141 }
1142 
1143 /**
1144  * xge_hal_fifo_is_next_dtr_completed - Checks if the next dtr is completed
1145  * @channelh: Channel handle.
1146  */
1147 __HAL_STATIC_FIFO __HAL_INLINE_FIFO xge_hal_status_e
xge_hal_fifo_is_next_dtr_completed(xge_hal_channel_h channelh)1148 xge_hal_fifo_is_next_dtr_completed(xge_hal_channel_h channelh)
1149 {
1150 	xge_hal_fifo_txd_t *txdp;
1151 	xge_hal_dtr_h dtrh;
1152 
1153 	__hal_channel_dtr_try_complete(channelh, &dtrh);
1154 	txdp = (xge_hal_fifo_txd_t *)dtrh;
1155 	if (txdp == NULL) {
1156 	    return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
1157 	}
1158 
1159 	/* check whether host owns it */
1160 	if ( !(txdp->control_1 & XGE_HAL_TXD_LIST_OWN_XENA) ) {
1161 	    xge_assert(txdp->host_control!=0);
1162 	    return XGE_HAL_OK;
1163 	}
1164 
1165 	/* no more completions */
1166 	return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
1167 }
1168