xref: /illumos-gate/usr/src/uts/common/io/xge/hal/xgehal/xgehal-ring-fp.c (revision 7f7322febbcfe774b7270abc3b191c094bfcc517)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  *  Copyright (c) 2002-2005 Neterion, Inc.
24  *  All right Reserved.
25  *
26  *  FileName :    xgehal-ring-fp.c
27  *
28  *  Description:  HAL Rx ring object functionality (fast path)
29  *
30  *  Created:      10 June 2004
31  */
32 
33 #ifdef XGE_DEBUG_FP
34 #include "xgehal-ring.h"
35 #endif
36 
37 __HAL_STATIC_RING __HAL_INLINE_RING xge_hal_ring_rxd_priv_t*
38 __hal_ring_rxd_priv(xge_hal_ring_t *ring, xge_hal_dtr_h dtrh)
39 {
40 
41 	xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh;
42 	xge_hal_ring_rxd_priv_t *rxd_priv;
43 
44 	xge_assert(rxdp);
45 
46 #if defined(XGE_HAL_USE_5B_MODE)
47 	xge_assert(ring);
48 	if (ring->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_5) {
49 		xge_hal_ring_rxd_5_t *rxdp_5 = (xge_hal_ring_rxd_5_t *)dtrh;
50 #if defined (XGE_OS_PLATFORM_64BIT)
51 		int memblock_idx = rxdp_5->host_control >> 16;
52 		int i = rxdp_5->host_control & 0xFFFF;
53 		rxd_priv = (xge_hal_ring_rxd_priv_t *)
54 			((char*)ring->mempool->memblocks_priv_arr[memblock_idx] + ring->rxd_priv_size * i);
55 #else
56 		/* 32-bit case */
57 		rxd_priv = (xge_hal_ring_rxd_priv_t *)rxdp_5->host_control;
58 #endif
59 	} else
60 #endif
61 	{
62 		rxd_priv = (xge_hal_ring_rxd_priv_t *)
63 				(ulong_t)rxdp->host_control;
64 	}
65 
66 	xge_assert(rxd_priv);
67 	xge_assert(rxd_priv->dma_object);
68 
69 	xge_assert(rxd_priv->dma_object->handle == rxd_priv->dma_handle);
70 
71 	xge_assert(rxd_priv->dma_object->addr + rxd_priv->dma_offset ==
72 							rxd_priv->dma_addr);
73 
74 	return rxd_priv;
75 }
76 
77 __HAL_STATIC_RING __HAL_INLINE_RING int
78 __hal_ring_block_memblock_idx(xge_hal_ring_block_t *block)
79 {
80        return (int)*((u64 *)(void *)((char *)block +
81                                XGE_HAL_RING_MEMBLOCK_IDX_OFFSET));
82 }
83 
84 __HAL_STATIC_RING __HAL_INLINE_RING void
85 __hal_ring_block_memblock_idx_set(xge_hal_ring_block_t*block, int memblock_idx)
86 {
87        *((u64 *)(void *)((char *)block +
88                        XGE_HAL_RING_MEMBLOCK_IDX_OFFSET)) =
89                        memblock_idx;
90 }
91 
92 
93 __HAL_STATIC_RING __HAL_INLINE_RING dma_addr_t
94 __hal_ring_block_next_pointer(xge_hal_ring_block_t *block)
95 {
96 	return (dma_addr_t)*((u64 *)(void *)((char *)block +
97 			XGE_HAL_RING_NEXT_BLOCK_POINTER_OFFSET));
98 }
99 
100 __HAL_STATIC_RING __HAL_INLINE_RING void
101 __hal_ring_block_next_pointer_set(xge_hal_ring_block_t *block,
102 			dma_addr_t dma_next)
103 {
104 	*((u64 *)(void *)((char *)block +
105 			  XGE_HAL_RING_NEXT_BLOCK_POINTER_OFFSET)) = dma_next;
106 }
107 
108 /**
109  * xge_hal_ring_dtr_private - Get ULD private per-descriptor data.
110  * @channelh: Channel handle.
111  * @dtrh: Descriptor handle.
112  *
113  * Returns: private ULD info associated with the descriptor.
114  * ULD requests per-descriptor space via xge_hal_channel_open().
115  *
116  * See also: xge_hal_fifo_dtr_private().
117  * Usage: See ex_rx_compl{}.
118  */
119 __HAL_STATIC_RING __HAL_INLINE_RING void*
120 xge_hal_ring_dtr_private(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh)
121 {
122 	return (char *)__hal_ring_rxd_priv(channelh, dtrh) +
123 					sizeof(xge_hal_ring_rxd_priv_t);
124 }
125 
126 /**
127  * xge_hal_ring_dtr_reserve - Reserve ring descriptor.
128  * @channelh: Channel handle.
129  * @dtrh: Reserved descriptor. On success HAL fills this "out" parameter
130  *        with a valid handle.
131  *
132  * Reserve Rx descriptor for the subsequent filling-in (by upper layer
133  * driver (ULD)) and posting on the corresponding channel (@channelh)
134  * via xge_hal_ring_dtr_post().
135  *
136  * Returns: XGE_HAL_OK - success.
137  * XGE_HAL_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available.
138  *
139  * See also: xge_hal_fifo_dtr_reserve(), xge_hal_ring_dtr_free(),
140  * xge_hal_fifo_dtr_reserve_sp(), xge_hal_status_e{}.
141  * Usage: See ex_post_all_rx{}.
142  */
143 __HAL_STATIC_RING __HAL_INLINE_RING xge_hal_status_e
144 xge_hal_ring_dtr_reserve(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh)
145 {
146 	xge_hal_status_e status;
147 #if defined(XGE_HAL_RX_MULTI_RESERVE_IRQ)
148 	unsigned long flags;
149 #endif
150 
151 #if defined(XGE_HAL_RX_MULTI_RESERVE)
152 	xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->reserve_lock);
153 #elif defined(XGE_HAL_RX_MULTI_RESERVE_IRQ)
154 	xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->reserve_lock,
155 	flags);
156 #endif
157 
158 	status = __hal_channel_dtr_alloc(channelh, dtrh);
159 
160 #if defined(XGE_HAL_RX_MULTI_RESERVE)
161 	xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->reserve_lock);
162 #elif defined(XGE_HAL_RX_MULTI_RESERVE_IRQ)
163 	xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->reserve_lock,
164 			     flags);
165 #endif
166 
167 	if (status == XGE_HAL_OK) {
168 		xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)*dtrh;
169 
170 		/* instead of memset: reset this RxD */
171 		rxdp->control_1 = rxdp->control_2 = 0;
172 
173 #if defined(XGE_OS_MEMORY_CHECK)
174 		__hal_ring_rxd_priv(channelh, rxdp)->allocated = 1;
175 #endif
176 	}
177 
178 	return status;
179 }
180 
181 /**
182  * xge_hal_ring_dtr_info_get - Get extended information associated with
183  * a completed receive descriptor for 1b mode.
184  * @channelh: Channel handle.
185  * @dtrh: Descriptor handle.
186  * @ext_info: See xge_hal_dtr_info_t{}. Returned by HAL.
187  *
188  * Retrieve extended information associated with a completed receive descriptor.
189  *
190  * See also: xge_hal_dtr_info_t{}, xge_hal_ring_dtr_1b_get(),
191  * xge_hal_ring_dtr_5b_get().
192  */
193 __HAL_STATIC_RING __HAL_INLINE_RING void
194 xge_hal_ring_dtr_info_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
195 			xge_hal_dtr_info_t *ext_info)
196 {
197 	/* cast to 1-buffer mode RxD: the code below relies on the fact
198 	 * that control_1 and control_2 are formatted the same way.. */
199 	xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh;
200 
201 	ext_info->l3_cksum = XGE_HAL_RXD_GET_L3_CKSUM(rxdp->control_1);
202 	ext_info->l4_cksum = XGE_HAL_RXD_GET_L4_CKSUM(rxdp->control_1);
203         ext_info->frame = XGE_HAL_RXD_GET_FRAME_TYPE(rxdp->control_1);
204         ext_info->proto = XGE_HAL_RXD_GET_FRAME_PROTO(rxdp->control_1);
205 	ext_info->vlan = XGE_HAL_RXD_GET_VLAN_TAG(rxdp->control_2);
206 
207 	/* Herc only, a few extra cycles imposed on Xena and/or
208 	 * when RTH is not enabled.
209 	 * Alternatively, could check
210 	 * xge_hal_device_check_id(), hldev->config.rth_en, queue->rth_en */
211 	ext_info->rth_it_hit = XGE_HAL_RXD_GET_RTH_IT_HIT(rxdp->control_1);
212 	ext_info->rth_spdm_hit =
213 	XGE_HAL_RXD_GET_RTH_SPDM_HIT(rxdp->control_1);
214 	ext_info->rth_hash_type =
215 	XGE_HAL_RXD_GET_RTH_HASH_TYPE(rxdp->control_1);
216 	ext_info->rth_value = XGE_HAL_RXD_1_GET_RTH_VALUE(rxdp->control_2);
217 }
218 
219 /**
220  * xge_hal_ring_dtr_info_nb_get - Get extended information associated
221  * with a completed receive descriptor for 3b or 5b
222  * modes.
223  * @channelh: Channel handle.
224  * @dtrh: Descriptor handle.
225  * @ext_info: See xge_hal_dtr_info_t{}. Returned by HAL.
226  *
227  * Retrieve extended information associated with a completed receive descriptor.
228  *
229  * See also: xge_hal_dtr_info_t{}, xge_hal_ring_dtr_1b_get(),
230  *           xge_hal_ring_dtr_5b_get().
231  */
232 __HAL_STATIC_RING __HAL_INLINE_RING void
233 xge_hal_ring_dtr_info_nb_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
234 			xge_hal_dtr_info_t *ext_info)
235 {
236 	/* cast to 1-buffer mode RxD: the code below relies on the fact
237 	 * that control_1 and control_2 are formatted the same way.. */
238 	xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh;
239 
240 	ext_info->l3_cksum = XGE_HAL_RXD_GET_L3_CKSUM(rxdp->control_1);
241 	ext_info->l4_cksum = XGE_HAL_RXD_GET_L4_CKSUM(rxdp->control_1);
242         ext_info->frame = XGE_HAL_RXD_GET_FRAME_TYPE(rxdp->control_1);
243         ext_info->proto = XGE_HAL_RXD_GET_FRAME_PROTO(rxdp->control_1);
244         ext_info->vlan = XGE_HAL_RXD_GET_VLAN_TAG(rxdp->control_2);
245 	/* Herc only, a few extra cycles imposed on Xena and/or
246 	 * when RTH is not enabled. Same comment as above. */
247 	ext_info->rth_it_hit = XGE_HAL_RXD_GET_RTH_IT_HIT(rxdp->control_1);
248 	ext_info->rth_spdm_hit =
249 	XGE_HAL_RXD_GET_RTH_SPDM_HIT(rxdp->control_1);
250 	ext_info->rth_hash_type =
251 	XGE_HAL_RXD_GET_RTH_HASH_TYPE(rxdp->control_1);
252 	ext_info->rth_value = (u32)rxdp->buffer0_ptr;
253 }
254 
255 /**
256  * xge_hal_ring_dtr_1b_set - Prepare 1-buffer-mode descriptor.
257  * @dtrh: Descriptor handle.
258  * @dma_pointer: DMA address of a single receive buffer this descriptor
259  *               should carry. Note that by the time
260  *               xge_hal_ring_dtr_1b_set
261  *               is called, the receive buffer should be already mapped
262  *               to the corresponding Xframe device.
263  * @size: Size of the receive @dma_pointer buffer.
264  *
265  * Prepare 1-buffer-mode Rx descriptor for posting
266  * (via xge_hal_ring_dtr_post()).
267  *
268  * This inline helper-function does not return any parameters and always
269  * succeeds.
270  *
271  * See also: xge_hal_ring_dtr_3b_set(), xge_hal_ring_dtr_5b_set().
272  * Usage: See ex_post_all_rx{}.
273  */
274 __HAL_STATIC_RING __HAL_INLINE_RING void
275 xge_hal_ring_dtr_1b_set(xge_hal_dtr_h dtrh, dma_addr_t dma_pointer, int size)
276 {
277 	xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh;
278 	rxdp->buffer0_ptr = dma_pointer;
279 	rxdp->control_2 &= (~XGE_HAL_RXD_1_MASK_BUFFER0_SIZE);
280 	rxdp->control_2 |= XGE_HAL_RXD_1_SET_BUFFER0_SIZE(size);
281 }
282 
283 /**
284  * xge_hal_ring_dtr_1b_get - Get data from the completed 1-buf
285  * descriptor.
286  * @channelh: Channel handle.
287  * @dtrh: Descriptor handle.
288  * @dma_pointer: DMA address of a single receive buffer _this_ descriptor
289  *               carries. Returned by HAL.
290  * @pkt_length: Length (in bytes) of the data in the buffer pointed by
291  *              @dma_pointer. Returned by HAL.
292  *
293  * Retrieve protocol data from the completed 1-buffer-mode Rx descriptor.
294  * This inline helper-function uses completed descriptor to populate receive
295  * buffer pointer and other "out" parameters. The function always succeeds.
296  *
297  * See also: xge_hal_ring_dtr_3b_get(), xge_hal_ring_dtr_5b_get().
298  * Usage: See ex_rx_compl{}.
299  */
300 __HAL_STATIC_RING __HAL_INLINE_RING void
301 xge_hal_ring_dtr_1b_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
302 		dma_addr_t *dma_pointer, int *pkt_length)
303 {
304 	xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh;
305 
306 	*pkt_length = XGE_HAL_RXD_1_GET_BUFFER0_SIZE(rxdp->control_2);
307 	*dma_pointer = rxdp->buffer0_ptr;
308 }
309 
310 /**
311  * xge_hal_ring_dtr_3b_set - Prepare 3-buffer-mode descriptor.
312  * @dtrh: Descriptor handle.
313  * @dma_pointers: Array of DMA addresses. Contains exactly 3 receive buffers
314  *               _this_ descriptor should carry.
315  *               Note that by the time xge_hal_ring_dtr_3b_set
316  *               is called, the receive buffers should be mapped
317  *               to the corresponding Xframe device.
318  * @sizes: Array of receive buffer sizes. Contains 3 sizes: one size per
319  *         buffer from @dma_pointers.
320  *
321  * Prepare 3-buffer-mode Rx descriptor for posting (via
322  * xge_hal_ring_dtr_post()).
323  * This inline helper-function does not return any parameters and always
324  * succeeds.
325  *
326  * See also: xge_hal_ring_dtr_1b_set(), xge_hal_ring_dtr_5b_set().
327  */
328 __HAL_STATIC_RING __HAL_INLINE_RING void
329 xge_hal_ring_dtr_3b_set(xge_hal_dtr_h dtrh, dma_addr_t dma_pointers[],
330 			int sizes[])
331 {
332 	xge_hal_ring_rxd_3_t *rxdp = (xge_hal_ring_rxd_3_t *)dtrh;
333 	rxdp->buffer0_ptr = dma_pointers[0];
334 	rxdp->control_2 &= (~XGE_HAL_RXD_3_MASK_BUFFER0_SIZE);
335 	rxdp->control_2 |= XGE_HAL_RXD_3_SET_BUFFER0_SIZE(sizes[0]);
336 	rxdp->buffer1_ptr = dma_pointers[1];
337 	rxdp->control_2 &= (~XGE_HAL_RXD_3_MASK_BUFFER1_SIZE);
338 	rxdp->control_2 |= XGE_HAL_RXD_3_SET_BUFFER1_SIZE(sizes[1]);
339 	rxdp->buffer2_ptr = dma_pointers[2];
340 	rxdp->control_2 &= (~XGE_HAL_RXD_3_MASK_BUFFER2_SIZE);
341 	rxdp->control_2 |= XGE_HAL_RXD_3_SET_BUFFER2_SIZE(sizes[2]);
342 }
343 
344 /**
345  * xge_hal_ring_dtr_3b_get - Get data from the completed 3-buf
346  * descriptor.
347  * @channelh: Channel handle.
348  * @dtrh: Descriptor handle.
349  * @dma_pointers: DMA addresses of the 3 receive buffers _this_ descriptor
350  *                carries. The first two buffers contain ethernet and
351  *                (IP + transport) headers. The 3rd buffer contains packet
352  *                data.
353  *                Returned by HAL.
354  * @sizes: Array of receive buffer sizes. Contains 3 sizes: one size per
355  * buffer from @dma_pointers. Returned by HAL.
356  *
357  * Retrieve protocol data from the completed 3-buffer-mode Rx descriptor.
358  * This inline helper-function uses completed descriptor to populate receive
359  * buffer pointer and other "out" parameters. The function always succeeds.
360  *
361  * See also: xge_hal_ring_dtr_3b_get(), xge_hal_ring_dtr_5b_get().
362  */
363 __HAL_STATIC_RING __HAL_INLINE_RING void
364 xge_hal_ring_dtr_3b_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
365 		dma_addr_t dma_pointers[], int sizes[])
366 {
367 	xge_hal_ring_rxd_3_t *rxdp = (xge_hal_ring_rxd_3_t *)dtrh;
368 
369 	dma_pointers[0] = rxdp->buffer0_ptr;
370 	sizes[0] = XGE_HAL_RXD_3_GET_BUFFER0_SIZE(rxdp->control_2);
371 
372 	dma_pointers[1] = rxdp->buffer1_ptr;
373 	sizes[1] = XGE_HAL_RXD_3_GET_BUFFER1_SIZE(rxdp->control_2);
374 
375 	dma_pointers[2] = rxdp->buffer2_ptr;
376 	sizes[2] = XGE_HAL_RXD_3_GET_BUFFER2_SIZE(rxdp->control_2);
377 }
378 
379 /**
380  * xge_hal_ring_dtr_5b_set - Prepare 5-buffer-mode descriptor.
381  * @dtrh: Descriptor handle.
382  * @dma_pointers: Array of DMA addresses. Contains exactly 5 receive buffers
383  *               _this_ descriptor should carry.
384  *               Note that by the time xge_hal_ring_dtr_5b_set
385  *               is called, the receive buffers should be mapped
386  *               to the corresponding Xframe device.
387  * @sizes: Array of receive buffer sizes. Contains 5 sizes: one size per
388  *         buffer from @dma_pointers.
389  *
390  * Prepare 3-buffer-mode Rx descriptor for posting (via
391  * xge_hal_ring_dtr_post()).
392  * This inline helper-function does not return any parameters and always
393  * succeeds.
394  *
395  * See also: xge_hal_ring_dtr_1b_set(), xge_hal_ring_dtr_3b_set().
396  */
397 __HAL_STATIC_RING __HAL_INLINE_RING void
398 xge_hal_ring_dtr_5b_set(xge_hal_dtr_h dtrh, dma_addr_t dma_pointers[],
399 			int sizes[])
400 {
401 	xge_hal_ring_rxd_5_t *rxdp = (xge_hal_ring_rxd_5_t *)dtrh;
402 	rxdp->buffer0_ptr = dma_pointers[0];
403 	rxdp->control_2 &= (~XGE_HAL_RXD_5_MASK_BUFFER0_SIZE);
404 	rxdp->control_2 |= XGE_HAL_RXD_5_SET_BUFFER0_SIZE(sizes[0]);
405 	rxdp->buffer1_ptr = dma_pointers[1];
406 	rxdp->control_2 &= (~XGE_HAL_RXD_5_MASK_BUFFER1_SIZE);
407 	rxdp->control_2 |= XGE_HAL_RXD_5_SET_BUFFER1_SIZE(sizes[1]);
408 	rxdp->buffer2_ptr = dma_pointers[2];
409 	rxdp->control_2 &= (~XGE_HAL_RXD_5_MASK_BUFFER2_SIZE);
410 	rxdp->control_2 |= XGE_HAL_RXD_5_SET_BUFFER2_SIZE(sizes[2]);
411 	rxdp->buffer3_ptr = dma_pointers[3];
412 	rxdp->control_3 &= (~XGE_HAL_RXD_5_MASK_BUFFER3_SIZE);
413 	rxdp->control_3 |= XGE_HAL_RXD_5_SET_BUFFER3_SIZE(sizes[3]);
414 	rxdp->buffer4_ptr = dma_pointers[4];
415 	rxdp->control_3 &= (~XGE_HAL_RXD_5_MASK_BUFFER4_SIZE);
416 	rxdp->control_3 |= XGE_HAL_RXD_5_SET_BUFFER3_SIZE(sizes[4]);
417 }
418 
419 /**
420  * xge_hal_ring_dtr_5b_get - Get data from the completed 5-buf
421  * descriptor.
422  * @channelh: Channel handle.
423  * @dtrh: Descriptor handle.
424  * @dma_pointers: DMA addresses of the 5 receive buffers _this_ descriptor
425  *                carries. The first 4 buffers contains L2 (ethernet) through
426  *                L5 headers. The 5th buffer contain received (applicaion)
427  *                data. Returned by HAL.
428  * @sizes: Array of receive buffer sizes. Contains 5 sizes: one size per
429  * buffer from @dma_pointers. Returned by HAL.
430  *
431  * Retrieve protocol data from the completed 5-buffer-mode Rx descriptor.
432  * This inline helper-function uses completed descriptor to populate receive
433  * buffer pointer and other "out" parameters. The function always succeeds.
434  *
435  * See also: xge_hal_ring_dtr_3b_get(), xge_hal_ring_dtr_5b_get().
436  */
437 __HAL_STATIC_RING __HAL_INLINE_RING void
438 xge_hal_ring_dtr_5b_get(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
439 		dma_addr_t dma_pointers[], int sizes[])
440 {
441 	xge_hal_ring_rxd_5_t *rxdp = (xge_hal_ring_rxd_5_t *)dtrh;
442 
443 	dma_pointers[0] = rxdp->buffer0_ptr;
444 	sizes[0] = XGE_HAL_RXD_5_GET_BUFFER0_SIZE(rxdp->control_2);
445 
446 	dma_pointers[1] = rxdp->buffer1_ptr;
447 	sizes[1] = XGE_HAL_RXD_5_GET_BUFFER1_SIZE(rxdp->control_2);
448 
449 	dma_pointers[2] = rxdp->buffer2_ptr;
450 	sizes[2] = XGE_HAL_RXD_5_GET_BUFFER2_SIZE(rxdp->control_2);
451 
452 	dma_pointers[3] = rxdp->buffer3_ptr;
453 	sizes[3] = XGE_HAL_RXD_5_GET_BUFFER3_SIZE(rxdp->control_3);
454 
455 	dma_pointers[4] = rxdp->buffer4_ptr;
456 	sizes[4] = XGE_HAL_RXD_5_GET_BUFFER4_SIZE(rxdp->control_3);
457 }
458 
459 
460 /**
461  * FIXME - document
462  */
463 __HAL_STATIC_RING __HAL_INLINE_RING void
464 xge_hal_ring_dtr_pre_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh)
465 {
466 	xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh;
467 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING)
468 	xge_hal_ring_rxd_priv_t *priv;
469 	xge_hal_ring_t *ring = (xge_hal_ring_t *)channelh;
470 #endif
471 #if defined(XGE_HAL_RX_MULTI_POST_IRQ)
472 	unsigned long flags;
473 #endif
474 
475 	rxdp->control_2 |= XGE_HAL_RXD_NOT_COMPLETED;
476 
477 #ifdef XGE_DEBUG_ASSERT
478         /* make sure Xena overwrites the (illegal) t_code on completion */
479         XGE_HAL_RXD_SET_T_CODE(rxdp->control_1,	XGE_HAL_RXD_T_CODE_UNUSED_C);
480 #endif
481 
482 	xge_debug_ring(XGE_TRACE, "posted %d rxd 0x%llx post_qid %d",
483 			((xge_hal_ring_t *)channelh)->channel.post_index,
484 			(unsigned long long)(ulong_t)dtrh,
485 			((xge_hal_ring_t *)channelh)->channel.post_qid);
486 
487 #if defined(XGE_HAL_RX_MULTI_POST)
488 	xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->post_lock);
489 #elif defined(XGE_HAL_RX_MULTI_POST_IRQ)
490 	xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->post_lock,
491 	flags);
492 #endif
493 
494 #if defined(XGE_DEBUG_ASSERT) && defined(XGE_HAL_RING_ENFORCE_ORDER)
495 	{
496 		xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
497 
498 		if (channel->post_index != 0) {
499 			xge_hal_dtr_h prev_dtrh;
500 			xge_hal_ring_rxd_priv_t *rxdp_priv;
501 
502 			rxdp_priv = __hal_ring_rxd_priv(channelh, rxdp);
503 			prev_dtrh = channel->work_arr[channel->post_index - 1];
504 
505 			if ((rxdp_priv->dma_offset & (~0xFFF)) !=
506 						rxdp_priv->dma_offset) {
507 				xge_assert((char *)prev_dtrh +
508 				    ((xge_hal_ring_t*)channel)->rxd_size == dtrh);
509 			}
510 		}
511 	}
512 #endif
513 
514 	__hal_channel_dtr_post(channelh, dtrh);
515 
516 #if defined(XGE_HAL_RX_MULTI_POST)
517 	xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->post_lock);
518 #elif defined(XGE_HAL_RX_MULTI_POST_IRQ)
519 	xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->post_lock,
520 			       flags);
521 #endif
522 }
523 
524 
525 /**
526  * FIXME - document
527  */
528 __HAL_STATIC_RING __HAL_INLINE_RING void
529 xge_hal_ring_dtr_post_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh)
530 {
531 	xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh;
532 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING)
533 	xge_hal_ring_rxd_priv_t *priv;
534 	xge_hal_ring_t *ring = (xge_hal_ring_t *)channelh;
535 #endif
536 	/* do POST */
537 	rxdp->control_1 |= XGE_HAL_RXD_POSTED_4_XFRAME;
538 
539 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING)
540 	priv = __hal_ring_rxd_priv(ring, rxdp);
541 	xge_os_dma_sync(ring->channel.pdev,
542 	              priv->dma_handle, priv->dma_addr,
543 		      priv->dma_offset, ring->rxd_size,
544 		      XGE_OS_DMA_DIR_TODEVICE);
545 #endif
546 }
547 
548 /**
549  * xge_hal_ring_dtr_post - Post descriptor on the ring channel.
550  * @channelh: Channel handle.
551  * @dtrh: Descriptor obtained via xge_hal_ring_dtr_reserve().
552  *
553  * Post descriptor on the 'ring' type channel.
554  * Prior to posting the descriptor should be filled in accordance with
555  * Host/Xframe interface specification for a given service (LL, etc.).
556  *
557  * See also: xge_hal_fifo_dtr_post_many(), xge_hal_fifo_dtr_post().
558  * Usage: See ex_post_all_rx{}.
559  */
560 __HAL_STATIC_RING __HAL_INLINE_RING void
561 xge_hal_ring_dtr_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh)
562 {
563 	xge_hal_ring_dtr_pre_post(channelh, dtrh);
564 	xge_hal_ring_dtr_post_post(channelh, dtrh);
565 }
566 
567 /**
568  * xge_hal_ring_dtr_next_completed - Get the _next_ completed
569  * descriptor.
570  * @channelh: Channel handle.
571  * @dtrh: Descriptor handle. Returned by HAL.
572  * @t_code: Transfer code, as per Xframe User Guide,
573  *          Receive Descriptor Format. Returned by HAL.
574  *
575  * Retrieve the _next_ completed descriptor.
576  * HAL uses channel callback (*xge_hal_channel_callback_f) to notifiy
577  * upper-layer driver (ULD) of new completed descriptors. After that
578  * the ULD can use xge_hal_ring_dtr_next_completed to retrieve the rest
579  * completions (the very first completion is passed by HAL via
580  * xge_hal_channel_callback_f).
581  *
582  * Implementation-wise, the upper-layer driver is free to call
583  * xge_hal_ring_dtr_next_completed either immediately from inside the
584  * channel callback, or in a deferred fashion and separate (from HAL)
585  * context.
586  *
587  * Non-zero @t_code means failure to fill-in receive buffer(s)
588  * of the descriptor.
589  * For instance, parity error detected during the data transfer.
590  * In this case Xframe will complete the descriptor and indicate
591  * for the host that the received data is not to be used.
592  * For details please refer to Xframe User Guide.
593  *
594  * Returns: XGE_HAL_OK - success.
595  * XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed descriptors
596  * are currently available for processing.
597  *
598  * See also: xge_hal_channel_callback_f{},
599  * xge_hal_fifo_dtr_next_completed(), xge_hal_status_e{}.
600  * Usage: See ex_rx_compl{}.
601  */
602 __HAL_STATIC_RING __HAL_INLINE_RING xge_hal_status_e
603 xge_hal_ring_dtr_next_completed(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh,
604 				u8 *t_code)
605 {
606 	xge_hal_ring_rxd_1_t *rxdp; /* doesn't matter 1, 3 or 5... */
607 	xge_hal_ring_t *ring = (xge_hal_ring_t *)channelh;
608 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING)
609 	xge_hal_ring_rxd_priv_t *priv;
610 #endif
611 
612 	__hal_channel_dtr_try_complete(ring, dtrh);
613 	rxdp = (xge_hal_ring_rxd_1_t *)*dtrh;
614 	if (rxdp == NULL) {
615 		return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
616 	}
617 
618 #if defined(XGE_OS_DMA_REQUIRES_SYNC) && defined(XGE_HAL_DMA_DTR_STREAMING)
619 	/* Note: 24 bytes at most means:
620 	 *	- Control_3 in case of 5-buffer mode
621 	 *	- Control_1 and Control_2
622 	 *
623 	 * This is the only length needs to be invalidated
624 	 * type of channels.*/
625 	priv = __hal_ring_rxd_priv(ring, rxdp);
626 	xge_os_dma_sync(ring->channel.pdev,
627 	              priv->dma_handle, priv->dma_addr,
628 		      priv->dma_offset, 24,
629 		      XGE_OS_DMA_DIR_FROMDEVICE);
630 #endif
631 
632 	/* check whether it is not the end */
633 	if (!(rxdp->control_2 & XGE_HAL_RXD_NOT_COMPLETED) &&
634 		!(rxdp->control_1 & XGE_HAL_RXD_POSTED_4_XFRAME)) {
635 #ifndef XGE_HAL_IRQ_POLLING
636 		if (++ring->cmpl_cnt > ring->indicate_max_pkts) {
637 			/* reset it. since we don't want to return
638 			 * garbage to the ULD */
639 			*dtrh = 0;
640 			return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
641 		}
642 #endif
643 
644 #ifdef XGE_DEBUG_ASSERT
645 #if defined(XGE_HAL_USE_5B_MODE)
646 #if !defined(XGE_OS_PLATFORM_64BIT)
647 		if (ring->buffer_mode == XGE_HAL_RING_QUEUE_BUFFER_MODE_5) {
648 			xge_assert(((xge_hal_ring_rxd_5_t *)
649 					rxdp)->host_control!=0);
650 		}
651 #endif
652 
653 #else
654 		xge_assert(rxdp->host_control!=0);
655 #endif
656 #endif
657 
658 		__hal_channel_dtr_complete(ring);
659 
660 		*t_code = (u8)XGE_HAL_RXD_GET_T_CODE(rxdp->control_1);
661 
662                 /* see XGE_HAL_SET_RXD_T_CODE() above.. */
663 		xge_assert(*t_code != XGE_HAL_RXD_T_CODE_UNUSED_C);
664 
665 		xge_debug_ring(XGE_TRACE,
666 			"compl_index %d post_qid %d rxd 0x%llx",
667 			((xge_hal_channel_t*)ring)->compl_index,
668 			((xge_hal_channel_t*)ring)->post_qid,
669 			(unsigned long long)(ulong_t)rxdp);
670 
671 		return XGE_HAL_OK;
672 	}
673 
674 	/* reset it. since we don't want to return
675 	 * garbage to the ULD */
676 	*dtrh = 0;
677 	return XGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
678 }
679 
680 /**
681  * xge_hal_ring_dtr_free - Free descriptor.
682  * @channelh: Channel handle.
683  * @dtrh: Descriptor handle.
684  *
685  * Free the reserved descriptor. This operation is "symmetrical" to
686  * xge_hal_ring_dtr_reserve. The "free-ing" completes the descriptor's
687  * lifecycle.
688  *
689  * After free-ing (see xge_hal_ring_dtr_free()) the descriptor again can
690  * be:
691  *
692  * - reserved (xge_hal_ring_dtr_reserve);
693  *
694  * - posted (xge_hal_ring_dtr_post);
695  *
696  * - completed (xge_hal_ring_dtr_next_completed);
697  *
698  * - and recycled again (xge_hal_ring_dtr_free).
699  *
700  * For alternative state transitions and more details please refer to
701  * the design doc.
702  *
703  * See also: xge_hal_ring_dtr_reserve(), xge_hal_fifo_dtr_free().
704  * Usage: See ex_rx_compl{}.
705  */
706 __HAL_STATIC_RING __HAL_INLINE_RING void
707 xge_hal_ring_dtr_free(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh)
708 {
709 #if defined(XGE_HAL_RX_MULTI_FREE_IRQ)
710 	unsigned long flags;
711 #endif
712 
713 #if defined(XGE_HAL_RX_MULTI_FREE)
714 	xge_os_spin_lock(&((xge_hal_channel_t*)channelh)->free_lock);
715 #elif defined(XGE_HAL_RX_MULTI_FREE_IRQ)
716 	xge_os_spin_lock_irq(&((xge_hal_channel_t*)channelh)->free_lock,
717 	flags);
718 #endif
719 
720 	__hal_channel_dtr_free(channelh, dtrh);
721 #if defined(XGE_OS_MEMORY_CHECK)
722 	__hal_ring_rxd_priv(channelh, dtrh)->allocated = 0;
723 #endif
724 
725 #if defined(XGE_HAL_RX_MULTI_FREE)
726 	xge_os_spin_unlock(&((xge_hal_channel_t*)channelh)->free_lock);
727 #elif defined(XGE_HAL_RX_MULTI_FREE_IRQ)
728 	xge_os_spin_unlock_irq(&((xge_hal_channel_t*)channelh)->free_lock,
729 	flags);
730 #endif
731 }
732