1219820Sjeff/*-
2219820Sjeff * Copyright(c) 2002-2011 Exar Corp.
3219820Sjeff * All rights reserved.
4219820Sjeff *
5219820Sjeff * Redistribution and use in source and binary forms, with or without
6219820Sjeff * modification are permitted provided the following conditions are met:
7219820Sjeff *
8219820Sjeff *    1. Redistributions of source code must retain the above copyright notice,
9219820Sjeff *       this list of conditions and the following disclaimer.
10219820Sjeff *
11219820Sjeff *    2. Redistributions in binary form must reproduce the above copyright
12219820Sjeff *       notice, this list of conditions and the following disclaimer in the
13219820Sjeff *       documentation and/or other materials provided with the distribution.
14219820Sjeff *
15219820Sjeff *    3. Neither the name of the Exar Corporation nor the names of its
16219820Sjeff *       contributors may be used to endorse or promote products derived from
17219820Sjeff *       this software without specific prior written permission.
18219820Sjeff *
19219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20219820Sjeff * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21219820Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22219820Sjeff * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23219820Sjeff * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24219820Sjeff * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25219820Sjeff * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26219820Sjeff * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27219820Sjeff * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28219820Sjeff * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29219820Sjeff * POSSIBILITY OF SUCH DAMAGE.
30219820Sjeff */
31219820Sjeff/*$FreeBSD$*/
32219820Sjeff
33219820Sjeff#include <dev/vxge/vxgehal/vxgehal.h>
34219820Sjeff
35219820Sjeff/*
36219820Sjeff * __hal_ring_block_memblock_idx - Return the memblock index
37219820Sjeff * @block: Virtual address of memory block
38219820Sjeff *
39219820Sjeff * This function returns the index of memory block
40219820Sjeff */
41219820Sjeffstatic inline u32
42219820Sjeff__hal_ring_block_memblock_idx(
43219820Sjeff    vxge_hal_ring_block_t block)
44219820Sjeff{
45219820Sjeff	return (u32)*((u64 *) ((void *)((u8 *) block +
46219820Sjeff	    VXGE_HAL_RING_MEMBLOCK_IDX_OFFSET)));
47219820Sjeff}
48219820Sjeff
49219820Sjeff/*
50219820Sjeff * __hal_ring_block_memblock_idx_set - Sets the memblock index
51219820Sjeff * @block: Virtual address of memory block
52219820Sjeff * @memblock_idx: Index of memory block
53219820Sjeff *
54219820Sjeff * This function sets index to a memory block
55219820Sjeff */
56219820Sjeffstatic inline void
57219820Sjeff__hal_ring_block_memblock_idx_set(
58219820Sjeff    vxge_hal_ring_block_t block,
59219820Sjeff    u32 memblock_idx)
60219820Sjeff{
61219820Sjeff	*((u64 *) ((void *)((u8 *) block +
62219820Sjeff	    VXGE_HAL_RING_MEMBLOCK_IDX_OFFSET))) = memblock_idx;
63219820Sjeff}
64219820Sjeff
65219820Sjeff#if 0
66219820Sjeff/*
67219820Sjeff * __hal_ring_block_next_pointer - Returns the dma address of next block
68219820Sjeff * @block: RxD block
69219820Sjeff *
70219820Sjeff * Returns the dma address of next block stored in the RxD block
71219820Sjeff */
72219820Sjeffstatic inline dma_addr_t
73219820Sjeff/* LINTED */
74219820Sjeff__hal_ring_block_next_pointer(
75219820Sjeff    vxge_hal_ring_block_t *block)
76219820Sjeff{
77219820Sjeff	return (dma_addr_t)*((u64 *) ((void *)((u8 *) block +
78	    VXGE_HAL_RING_NEXT_BLOCK_POINTER_OFFSET)));
79}
80#endif
81
82/*
83 * __hal_ring_block_next_pointer_set - Sets the next block pointer in RxD block
84 * @block: RxD block
85 * @dma_next: dma address of next block
86 *
87 * Sets the next block pointer in RxD block
88 */
89static inline void
90__hal_ring_block_next_pointer_set(
91    vxge_hal_ring_block_t *block,
92    dma_addr_t dma_next)
93{
94	*((u64 *) ((void *)((u8 *) block +
95	    VXGE_HAL_RING_NEXT_BLOCK_POINTER_OFFSET))) = dma_next;
96}
97
98/*
99 * __hal_ring_first_block_address_get - Returns the dma address of the
100 *		first block
101 * @ringh: Handle to the ring
102 *
103 * Returns the dma address of the first RxD block
104 */
105u64
106__hal_ring_first_block_address_get(
107    vxge_hal_ring_h ringh)
108{
109	__hal_ring_t *ring = (__hal_ring_t *) ringh;
110	vxge_hal_mempool_dma_t *dma_object;
111
112	dma_object = __hal_mempool_memblock_dma(ring->mempool, 0);
113
114	vxge_assert(dma_object != NULL);
115
116	return (dma_object->addr);
117}
118
119
120#if defined(VXGE_OS_DMA_REQUIRES_SYNC) && defined(VXGE_HAL_DMA_RXD_STREAMING)
121/*
122 * __hal_ring_item_dma_offset - Return the dma offset of an item
123 * @mempoolh: Handle to the memory pool of the ring
124 * @item: Item for which to get the dma offset
125 *
126 * This function returns the dma offset of a given item
127 */
128static ptrdiff_t
129__hal_ring_item_dma_offset(
130    vxge_hal_mempool_h mempoolh,
131    void *item)
132{
133	u32 memblock_idx;
134	void *memblock;
135	vxge_hal_mempool_t *mempool = (vxge_hal_mempool_t *) mempoolh;
136	__hal_device_t *hldev;
137
138	vxge_assert((mempoolh != NULL) && (item != NULL) &&
139	    (dma_handle != NULL));
140
141	hldev = (__hal_device_t *) mempool->devh;
142
143	vxge_hal_trace_log_ring("==> %s:%s:%d",
144	    __FILE__, __func__, __LINE__);
145
146	vxge_hal_trace_log_ring(
147	    "mempoolh = 0x"VXGE_OS_STXFMT", item = 0x"VXGE_OS_STXFMT,
148	    (ptr_t) mempoolh, (ptr_t) item);
149
150	/* get owner memblock index */
151	memblock_idx = __hal_ring_block_memblock_idx(item);
152
153	/* get owner memblock by memblock index */
154	memblock = __hal_mempool_memblock(mempoolh, memblock_idx);
155
156	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
157	    __FILE__, __func__, __LINE__);
158
159	return ((u8 *) item - (u8 *) memblock);
160}
161#endif
162
163/*
164 * __hal_ring_item_dma_addr - Return the dma address of an item
165 * @mempoolh: Handle to the memory pool of the ring
166 * @item: Item for which to get the dma offset
167 * @dma_handle: dma handle
168 *
169 * This function returns the dma address of a given item
170 */
171static dma_addr_t
172__hal_ring_item_dma_addr(
173    vxge_hal_mempool_h mempoolh,
174    void *item,
175    pci_dma_h *dma_handle)
176{
177	u32 memblock_idx;
178	void *memblock;
179	vxge_hal_mempool_dma_t *memblock_dma_object;
180	vxge_hal_mempool_t *mempool = (vxge_hal_mempool_t *) mempoolh;
181	__hal_device_t *hldev;
182	ptrdiff_t dma_item_offset;
183
184	vxge_assert((mempoolh != NULL) && (item != NULL) &&
185	    (dma_handle != NULL));
186
187	hldev = (__hal_device_t *) mempool->devh;
188
189	vxge_hal_trace_log_ring("==> %s:%s:%d",
190	    __FILE__, __func__, __LINE__);
191
192	vxge_hal_trace_log_ring(
193	    "mempoolh = 0x"VXGE_OS_STXFMT", item = 0x"VXGE_OS_STXFMT", "
194	    "dma_handle = 0x"VXGE_OS_STXFMT, (ptr_t) mempoolh,
195	    (ptr_t) item, (ptr_t) dma_handle);
196
197	/* get owner memblock index */
198	memblock_idx = __hal_ring_block_memblock_idx((u8 *) item);
199
200	/* get owner memblock by memblock index */
201	memblock = __hal_mempool_memblock(
202	    (vxge_hal_mempool_t *) mempoolh, memblock_idx);
203
204	/* get memblock DMA object by memblock index */
205	memblock_dma_object = __hal_mempool_memblock_dma(
206	    (vxge_hal_mempool_t *) mempoolh, memblock_idx);
207
208	/* calculate offset in the memblock of this item */
209	/* LINTED */
210	dma_item_offset = (u8 *) item - (u8 *) memblock;
211
212	*dma_handle = memblock_dma_object->handle;
213
214	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
215	    __FILE__, __func__, __LINE__);
216
217	return (memblock_dma_object->addr + dma_item_offset);
218}
219
220/*
221 * __hal_ring_rxdblock_link - Link the RxD blocks
222 * @mempoolh: Handle to the memory pool of the ring
223 * @ring: ring
224 * @from: RxD block from which to link
225 * @to: RxD block to which to link to
226 *
227 * This function returns the dma address of a given item
228 */
229static void
230__hal_ring_rxdblock_link(
231    vxge_hal_mempool_h mempoolh,
232    __hal_ring_t *ring,
233    u32 from,
234    u32 to)
235{
236	vxge_hal_ring_block_t *to_item, *from_item;
237	dma_addr_t to_dma, from_dma;
238	pci_dma_h to_dma_handle, from_dma_handle;
239	__hal_device_t *hldev;
240
241	vxge_assert((mempoolh != NULL) && (ring != NULL));
242
243	hldev = (__hal_device_t *) ring->channel.devh;
244
245	vxge_hal_trace_log_ring("==> %s:%s:%d",
246	    __FILE__, __func__, __LINE__);
247
248	vxge_hal_trace_log_ring(
249	    "mempoolh = 0x"VXGE_OS_STXFMT", ring = 0x"VXGE_OS_STXFMT", "
250	    "from = %d, to = %d", (ptr_t) mempoolh, (ptr_t) ring, from, to);
251
252	/* get "from" RxD block */
253	from_item = (vxge_hal_ring_block_t *) __hal_mempool_item(
254	    (vxge_hal_mempool_t *) mempoolh, from);
255	vxge_assert(from_item);
256
257	/* get "to" RxD block */
258	to_item = (vxge_hal_ring_block_t *) __hal_mempool_item(
259	    (vxge_hal_mempool_t *) mempoolh, to);
260	vxge_assert(to_item);
261
262	/* return address of the beginning of previous RxD block */
263	to_dma = __hal_ring_item_dma_addr(mempoolh, to_item, &to_dma_handle);
264
265	/*
266	 * set next pointer for this RxD block to point on
267	 * previous item's DMA start address
268	 */
269	__hal_ring_block_next_pointer_set(from_item, to_dma);
270
271	/* return "from" RxD block's DMA start address */
272	from_dma = __hal_ring_item_dma_addr(
273	    mempoolh, from_item, &from_dma_handle);
274
275#if defined(VXGE_OS_DMA_REQUIRES_SYNC) && defined(VXGE_HAL_DMA_RXD_STREAMING)
276	/* we must sync "from" RxD block, so hardware will see it */
277	vxge_os_dma_sync(ring->channel.pdev,
278	    from_dma_handle,
279	    from_dma + VXGE_HAL_RING_NEXT_BLOCK_POINTER_OFFSET,
280	    __hal_ring_item_dma_offset(mempoolh, from_item) +
281	    VXGE_HAL_RING_NEXT_BLOCK_POINTER_OFFSET,
282	    sizeof(u64),
283	    VXGE_OS_DMA_DIR_TODEVICE);
284#endif
285
286	vxge_hal_info_log_ring(
287	    "block%d:0x"VXGE_OS_STXFMT" => block%d:0x"VXGE_OS_STXFMT,
288	    from, (ptr_t) from_dma, to, (ptr_t) to_dma);
289
290	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
291	    __FILE__, __func__, __LINE__);
292
293}
294
295/*
296 * __hal_ring_mempool_item_alloc - Allocate List blocks for RxD block callback
297 * @mempoolh: Handle to memory pool
298 * @memblock: Address of this memory block
299 * @memblock_index: Index of this memory block
300 * @dma_object: dma object for this block
301 * @item: Pointer to this item
302 * @index: Index of this item in memory block
303 * @is_last: If this is last item in the block
304 * @userdata: Specific data of user
305 *
306 * This function is callback passed to __hal_mempool_create to create memory
307 * pool for RxD block
308 */
309static vxge_hal_status_e
310__hal_ring_mempool_item_alloc(
311    vxge_hal_mempool_h mempoolh,
312    void *memblock,
313    u32 memblock_index,
314    vxge_hal_mempool_dma_t *dma_object,
315    void *item,
316    u32 item_index,
317    u32 is_last,
318    void *userdata)
319{
320	u32 i;
321	__hal_ring_t *ring = (__hal_ring_t *) userdata;
322	__hal_device_t *hldev;
323
324	vxge_assert((item != NULL) && (ring != NULL));
325
326	hldev = (__hal_device_t *) ring->channel.devh;
327
328	vxge_hal_trace_log_pool("==> %s:%s:%d",
329	    __FILE__, __func__, __LINE__);
330
331	vxge_hal_trace_log_pool(
332	    "mempoolh = 0x"VXGE_OS_STXFMT", memblock = 0x"VXGE_OS_STXFMT", "
333	    "memblock_index = %d, dma_object = 0x"VXGE_OS_STXFMT", "
334	    "item = 0x"VXGE_OS_STXFMT", item_index = %d, is_last = %d, "
335	    "userdata = 0x"VXGE_OS_STXFMT, (ptr_t) mempoolh, (ptr_t) memblock,
336	    memblock_index, (ptr_t) dma_object, (ptr_t) item, item_index, is_last,
337	    (ptr_t) userdata);
338
339	/* format rxds array */
340	for (i = 0; i < ring->rxds_per_block; i++) {
341
342		void *uld_priv;
343		void *rxdblock_priv;
344		__hal_ring_rxd_priv_t *rxd_priv;
345		vxge_hal_ring_rxd_1_t *rxdp;
346		u32 memblock_item_idx;
347		u32 dtr_index = item_index * ring->rxds_per_block + i;
348
349		ring->channel.dtr_arr[dtr_index].dtr =
350		    ((u8 *) item) + i * ring->rxd_size;
351
352		/*
353		 * Note: memblock_item_idx is index of the item within
354		 * the memblock. For instance, in case of three RxD-blocks
355		 * per memblock this value can be 0, 1 or 2.
356		 */
357		rxdblock_priv = __hal_mempool_item_priv(
358		    (vxge_hal_mempool_t *) mempoolh,
359		    memblock_index,
360		    item,
361		    &memblock_item_idx);
362
363		rxdp = (vxge_hal_ring_rxd_1_t *)
364		    ring->channel.dtr_arr[dtr_index].dtr;
365
366		uld_priv = ((u8 *) rxdblock_priv + ring->rxd_priv_size * i);
367		rxd_priv =
368		    (__hal_ring_rxd_priv_t *) ((void *)(((char *) uld_priv) +
369		    ring->per_rxd_space));
370
371		((vxge_hal_ring_rxd_5_t *) rxdp)->host_control = dtr_index;
372
373		ring->channel.dtr_arr[dtr_index].uld_priv = (void *)uld_priv;
374		ring->channel.dtr_arr[dtr_index].hal_priv = (void *)rxd_priv;
375
376		/* pre-format per-RxD Ring's private */
377		/* LINTED */
378		rxd_priv->dma_offset = (u8 *) rxdp - (u8 *) memblock;
379		rxd_priv->dma_addr = dma_object->addr + rxd_priv->dma_offset;
380		rxd_priv->dma_handle = dma_object->handle;
381#if defined(VXGE_DEBUG_ASSERT)
382		rxd_priv->dma_object = dma_object;
383#endif
384		rxd_priv->db_bytes = ring->rxd_size;
385
386		if (i == (ring->rxds_per_block - 1)) {
387			rxd_priv->db_bytes +=
388			    (((vxge_hal_mempool_t *) mempoolh)->memblock_size -
389			    (ring->rxds_per_block * ring->rxd_size));
390		}
391	}
392
393	__hal_ring_block_memblock_idx_set((u8 *) item, memblock_index);
394	if (is_last) {
395		/* link last one with first one */
396		__hal_ring_rxdblock_link(mempoolh, ring, item_index, 0);
397	}
398
399	if (item_index > 0) {
400		/* link this RxD block with previous one */
401		__hal_ring_rxdblock_link(mempoolh, ring, item_index - 1, item_index);
402	}
403
404	vxge_hal_trace_log_pool("<== %s:%s:%d  Result: 0",
405	    __FILE__, __func__, __LINE__);
406
407	return (VXGE_HAL_OK);
408}
409
410/*
411 * __hal_ring_mempool_item_free - Free RxD blockt callback
412 * @mempoolh: Handle to memory pool
413 * @memblock: Address of this memory block
414 * @memblock_index: Index of this memory block
415 * @dma_object: dma object for this block
416 * @item: Pointer to this item
417 * @index: Index of this item in memory block
418 * @is_last: If this is last item in the block
419 * @userdata: Specific data of user
420 *
421 * This function is callback passed to __hal_mempool_free to destroy memory
422 * pool for RxD block
423 */
424static vxge_hal_status_e
425__hal_ring_mempool_item_free(
426    vxge_hal_mempool_h mempoolh,
427    void *memblock,
428    u32 memblock_index,
429    vxge_hal_mempool_dma_t *dma_object,
430    void *item,
431    u32 item_index,
432    u32 is_last,
433    void *userdata)
434{
435	__hal_ring_t *ring = (__hal_ring_t *) userdata;
436	__hal_device_t *hldev;
437
438	vxge_assert((item != NULL) && (ring != NULL));
439
440	hldev = (__hal_device_t *) ring->channel.devh;
441
442	vxge_hal_trace_log_pool("==> %s:%s:%d",
443	    __FILE__, __func__, __LINE__);
444
445	vxge_hal_trace_log_pool(
446	    "mempoolh = 0x"VXGE_OS_STXFMT", memblock = 0x"VXGE_OS_STXFMT", "
447	    "memblock_index = %d, dma_object = 0x"VXGE_OS_STXFMT", "
448	    "item = 0x"VXGE_OS_STXFMT", item_index = %d, is_last = %d, "
449	    "userdata = 0x"VXGE_OS_STXFMT, (ptr_t) mempoolh, (ptr_t) memblock,
450	    memblock_index, (ptr_t) dma_object, (ptr_t) item, item_index, is_last,
451	    (ptr_t) userdata);
452
453	vxge_hal_trace_log_pool("<== %s:%s:%d  Result: 0",
454	    __FILE__, __func__, __LINE__);
455
456	return (VXGE_HAL_OK);
457}
458
459/*
460 * __hal_ring_initial_replenish - Initial replenish of RxDs
461 * @ring: ring
462 * @reopen: Flag to denote if it is open or repopen
463 *
464 * This function replenishes the RxDs from reserve array to work array
465 */
466static vxge_hal_status_e
467__hal_ring_initial_replenish(
468    __hal_ring_t *ring,
469    vxge_hal_reopen_e reopen)
470{
471	vxge_hal_rxd_h rxd;
472	void *uld_priv;
473	__hal_device_t *hldev;
474	vxge_hal_status_e status;
475
476	vxge_assert(ring != NULL);
477
478	hldev = (__hal_device_t *) ring->channel.devh;
479
480	vxge_hal_trace_log_ring("==> %s:%s:%d",
481	    __FILE__, __func__, __LINE__);
482
483	vxge_hal_trace_log_ring("ring = 0x"VXGE_OS_STXFMT", reopen = %d",
484	    (ptr_t) ring, reopen);
485
486	while (vxge_hal_ring_rxd_reserve(ring->channel.vph, &rxd, &uld_priv) ==
487	    VXGE_HAL_OK) {
488
489		if (ring->rxd_init) {
490			status = ring->rxd_init(ring->channel.vph,
491			    rxd,
492			    uld_priv,
493			    VXGE_HAL_RING_RXD_INDEX(rxd),
494			    ring->channel.userdata,
495			    reopen);
496			if (status != VXGE_HAL_OK) {
497				vxge_hal_ring_rxd_free(ring->channel.vph, rxd);
498				vxge_hal_trace_log_ring("<== %s:%s:%d \
499				    Result: %d",
500				    __FILE__, __func__, __LINE__, status);
501				return (status);
502			}
503		}
504
505		vxge_hal_ring_rxd_post(ring->channel.vph, rxd);
506	}
507
508	vxge_hal_trace_log_ring("<== %s:%s:%d Result: 0",
509	    __FILE__, __func__, __LINE__);
510	return (VXGE_HAL_OK);
511}
512
513/*
514 * __hal_ring_create - Create a Ring
515 * @vpath_handle: Handle returned by virtual path open
516 * @attr: Ring configuration parameters structure
517 *
518 * This function creates Ring and initializes it.
519 *
520 */
521vxge_hal_status_e
522__hal_ring_create(
523    vxge_hal_vpath_h vpath_handle,
524    vxge_hal_ring_attr_t *attr)
525{
526	vxge_hal_status_e status;
527	__hal_ring_t *ring;
528	__hal_vpath_handle_t *vp = (__hal_vpath_handle_t *) vpath_handle;
529	vxge_hal_ring_config_t *config;
530	__hal_device_t *hldev;
531
532	vxge_assert((vpath_handle != NULL) && (attr != NULL));
533
534	hldev = (__hal_device_t *) vp->vpath->hldev;
535
536	vxge_hal_trace_log_ring("==> %s:%s:%d",
537	    __FILE__, __func__, __LINE__);
538
539	vxge_hal_trace_log_ring(
540	    "vpath_handle = 0x"VXGE_OS_STXFMT", attr = 0x"VXGE_OS_STXFMT,
541	    (ptr_t) vpath_handle, (ptr_t) attr);
542
543	if ((vpath_handle == NULL) || (attr == NULL)) {
544		vxge_hal_err_log_ring("null pointer passed == > %s : %d",
545		    __func__, __LINE__);
546		vxge_hal_trace_log_ring("<== %s:%s:%d  Result:1",
547		    __FILE__, __func__, __LINE__);
548		return (VXGE_HAL_FAIL);
549	}
550
551	config =
552	    &vp->vpath->hldev->header.config.vp_config[vp->vpath->vp_id].ring;
553
554	config->ring_length = ((config->ring_length +
555	    vxge_hal_ring_rxds_per_block_get(config->buffer_mode) - 1) /
556	    vxge_hal_ring_rxds_per_block_get(config->buffer_mode)) *
557	    vxge_hal_ring_rxds_per_block_get(config->buffer_mode);
558
559	ring = (__hal_ring_t *) vxge_hal_channel_allocate(
560	    (vxge_hal_device_h) vp->vpath->hldev,
561	    vpath_handle,
562	    VXGE_HAL_CHANNEL_TYPE_RING,
563	    config->ring_length,
564	    attr->per_rxd_space,
565	    attr->userdata);
566
567	if (ring == NULL) {
568		vxge_hal_err_log_ring("Memory allocation failed == > %s : %d",
569		    __func__, __LINE__);
570		vxge_hal_trace_log_ring("<== %s:%s:%d  Result: %d",
571		    __FILE__, __func__, __LINE__,
572		    VXGE_HAL_ERR_OUT_OF_MEMORY);
573		return (VXGE_HAL_ERR_OUT_OF_MEMORY);
574	}
575
576	vp->vpath->ringh = (vxge_hal_ring_h) ring;
577
578	ring->stats = &vp->vpath->sw_stats->ring_stats;
579
580	ring->config = config;
581	ring->callback = attr->callback;
582	ring->rxd_init = attr->rxd_init;
583	ring->rxd_term = attr->rxd_term;
584
585	ring->indicate_max_pkts = config->indicate_max_pkts;
586	ring->buffer_mode = config->buffer_mode;
587
588#if defined(VXGE_HAL_RX_MULTI_POST)
589	vxge_os_spin_lock_init(&ring->channel.post_lock, hldev->pdev);
590#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
591	vxge_os_spin_lock_init_irq(&ring->channel.post_lock, hldev->irqh);
592#endif
593
594	ring->rxd_size = vxge_hal_ring_rxd_size_get(config->buffer_mode);
595	ring->rxd_priv_size =
596	    sizeof(__hal_ring_rxd_priv_t) + attr->per_rxd_space;
597	ring->per_rxd_space = attr->per_rxd_space;
598
599	ring->rxd_priv_size =
600	    ((ring->rxd_priv_size + __vxge_os_cacheline_size - 1) /
601	    __vxge_os_cacheline_size) * __vxge_os_cacheline_size;
602
603	/*
604	 * how many RxDs can fit into one block. Depends on configured
605	 * buffer_mode.
606	 */
607	ring->rxds_per_block =
608	    vxge_hal_ring_rxds_per_block_get(config->buffer_mode);
609
610	/* calculate actual RxD block private size */
611	ring->rxdblock_priv_size = ring->rxd_priv_size * ring->rxds_per_block;
612
613	ring->rxd_mem_avail =
614	    ((__hal_vpath_handle_t *) ring->channel.vph)->vpath->rxd_mem_size;
615
616	ring->db_byte_count = 0;
617
618	ring->mempool = vxge_hal_mempool_create(
619	    (vxge_hal_device_h) vp->vpath->hldev,
620	    VXGE_OS_HOST_PAGE_SIZE,
621	    VXGE_OS_HOST_PAGE_SIZE,
622	    ring->rxdblock_priv_size,
623	    ring->config->ring_length / ring->rxds_per_block,
624	    ring->config->ring_length / ring->rxds_per_block,
625	    __hal_ring_mempool_item_alloc,
626	    __hal_ring_mempool_item_free,
627	    ring);
628
629	if (ring->mempool == NULL) {
630		__hal_ring_delete(vpath_handle);
631		vxge_hal_trace_log_ring("<== %s:%s:%d  Result: %d",
632		    __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY);
633		return (VXGE_HAL_ERR_OUT_OF_MEMORY);
634	}
635
636	status = vxge_hal_channel_initialize(&ring->channel);
637	if (status != VXGE_HAL_OK) {
638		__hal_ring_delete(vpath_handle);
639		vxge_hal_trace_log_ring("<== %s:%s:%d  Result: %d",
640		    __FILE__, __func__, __LINE__, status);
641		return (status);
642	}
643
644
645	/*
646	 * Note:
647	 * Specifying rxd_init callback means two things:
648	 * 1) rxds need to be initialized by ULD at channel-open time;
649	 * 2) rxds need to be posted at channel-open time
650	 *	(that's what the initial_replenish() below does)
651	 * Currently we don't have a case when the 1) is done without the 2).
652	 */
653	if (ring->rxd_init) {
654		if ((status = __hal_ring_initial_replenish(
655		    ring,
656		    VXGE_HAL_OPEN_NORMAL))
657		    != VXGE_HAL_OK) {
658			__hal_ring_delete(vpath_handle);
659			vxge_hal_trace_log_ring("<== %s:%s:%d  Result: %d",
660			    __FILE__, __func__, __LINE__, status);
661			return (status);
662		}
663	}
664
665	/*
666	 * initial replenish will increment the counter in its post() routine,
667	 * we have to reset it
668	 */
669	ring->stats->common_stats.usage_cnt = 0;
670
671	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
672	    __FILE__, __func__, __LINE__);
673	return (VXGE_HAL_OK);
674}
675
676/*
677 * __hal_ring_abort - Returns the RxD
678 * @ringh: Ring to be reset
679 * @reopen: See  vxge_hal_reopen_e {}.
680 *
681 * This function terminates the RxDs of ring
682 */
683void
684__hal_ring_abort(
685    vxge_hal_ring_h ringh,
686    vxge_hal_reopen_e reopen)
687{
688	u32 i = 0;
689	vxge_hal_rxd_h rxdh;
690
691	__hal_device_t *hldev;
692	__hal_ring_t *ring = (__hal_ring_t *) ringh;
693
694	vxge_assert(ringh != NULL);
695
696	hldev = (__hal_device_t *) ring->channel.devh;
697
698	vxge_hal_trace_log_ring("==> %s:%s:%d",
699	    __FILE__, __func__, __LINE__);
700
701	vxge_hal_trace_log_ring("ring = 0x"VXGE_OS_STXFMT", reopen = %d",
702	    (ptr_t) ringh, reopen);
703
704	if (ring->rxd_term) {
705		__hal_channel_for_each_dtr(&ring->channel, rxdh, i) {
706			if (!__hal_channel_is_posted_dtr(&ring->channel, i)) {
707				ring->rxd_term(ring->channel.vph, rxdh,
708				    VXGE_HAL_RING_ULD_PRIV(ring, rxdh),
709				    VXGE_HAL_RXD_STATE_FREED,
710				    ring->channel.userdata,
711				    reopen);
712			}
713		}
714	}
715
716	for (;;) {
717		__hal_channel_dtr_try_complete(&ring->channel, &rxdh);
718		if (rxdh == NULL)
719			break;
720
721		__hal_channel_dtr_complete(&ring->channel);
722		if (ring->rxd_term) {
723			ring->rxd_term(ring->channel.vph, rxdh,
724			    VXGE_HAL_RING_ULD_PRIV(ring, rxdh),
725			    VXGE_HAL_RXD_STATE_POSTED,
726			    ring->channel.userdata,
727			    reopen);
728		}
729		__hal_channel_dtr_free(&ring->channel,
730		    VXGE_HAL_RING_RXD_INDEX(rxdh));
731	}
732
733	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
734	    __FILE__, __func__, __LINE__);
735}
736
737/*
738 * __hal_ring_reset - Resets the ring
739 * @ringh: Ring to be reset
740 *
741 * This function resets the ring during vpath reset operation
742 */
743vxge_hal_status_e
744__hal_ring_reset(
745    vxge_hal_ring_h ringh)
746{
747	__hal_ring_t *ring = (__hal_ring_t *) ringh;
748	__hal_device_t *hldev;
749	vxge_hal_status_e status;
750	__hal_vpath_handle_t *vph = (__hal_vpath_handle_t *) ring->channel.vph;
751
752	vxge_assert(ringh != NULL);
753
754	hldev = (__hal_device_t *) ring->channel.devh;
755
756	vxge_hal_trace_log_ring("==> %s:%s:%d",
757	    __FILE__, __func__, __LINE__);
758
759	vxge_hal_trace_log_ring("ring = 0x"VXGE_OS_STXFMT,
760	    (ptr_t) ringh);
761
762	__hal_ring_abort(ringh, VXGE_HAL_RESET_ONLY);
763
764	status = __hal_channel_reset(&ring->channel);
765
766	if (status != VXGE_HAL_OK) {
767
768		vxge_hal_trace_log_ring("<== %s:%s:%d  Result: %d",
769		    __FILE__, __func__, __LINE__, status);
770		return (status);
771
772	}
773	ring->rxd_mem_avail = vph->vpath->rxd_mem_size;
774	ring->db_byte_count = 0;
775
776
777	if (ring->rxd_init) {
778		if ((status = __hal_ring_initial_replenish(
779		    ring,
780		    VXGE_HAL_RESET_ONLY))
781		    != VXGE_HAL_OK) {
782			vxge_hal_trace_log_ring("<== %s:%s:%d  Result: %d",
783			    __FILE__, __func__, __LINE__, status);
784			return (status);
785		}
786	}
787
788	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
789	    __FILE__, __func__, __LINE__);
790
791	return (VXGE_HAL_OK);
792}
793
794/*
795 * __hal_ring_delete - Removes the ring
796 * @vpath_handle: Virtual path handle to which this queue belongs
797 *
798 * This function freeup the memory pool and removes the ring
799 */
800void
801__hal_ring_delete(
802    vxge_hal_vpath_h vpath_handle)
803{
804	__hal_vpath_handle_t *vp = (__hal_vpath_handle_t *) vpath_handle;
805	__hal_device_t *hldev;
806	__hal_ring_t *ring;
807
808	vxge_assert(vpath_handle != NULL);
809
810	hldev = (__hal_device_t *) vp->vpath->hldev;
811
812	vxge_hal_trace_log_ring("==> %s:%s:%d",
813	    __FILE__, __func__, __LINE__);
814
815	vxge_hal_trace_log_ring("vpath_handle = 0x"VXGE_OS_STXFMT,
816	    (ptr_t) vpath_handle);
817
818	ring = (__hal_ring_t *) vp->vpath->ringh;
819
820	vxge_assert(ring != NULL);
821
822	vxge_assert(ring->channel.pdev);
823
824	__hal_ring_abort(vp->vpath->ringh, VXGE_HAL_OPEN_NORMAL);
825
826
827	if (ring->mempool) {
828		vxge_hal_mempool_destroy(ring->mempool);
829	}
830
831	vxge_hal_channel_terminate(&ring->channel);
832
833#if defined(VXGE_HAL_RX_MULTI_POST)
834	vxge_os_spin_lock_destroy(&ring->channel.post_lock, hldev->pdev);
835#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
836	vxge_os_spin_lock_destroy_irq(&ring->channel.post_lock, hldev->pdev);
837#endif
838
839	vxge_hal_channel_free(&ring->channel);
840
841	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
842	    __FILE__, __func__, __LINE__);
843
844}
845
846/*
847 * __hal_ring_frame_length_set	- Set the maximum frame length of recv frames.
848 * @vpath: virtual Path
849 * @new_frmlen: New frame length
850 *
851 *
852 * Returns: VXGE_HAL_OK - success.
853 * VXGE_HAL_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available.
854 *
855 */
856vxge_hal_status_e
857__hal_ring_frame_length_set(
858    __hal_virtualpath_t *vpath,
859    u32 new_frmlen)
860{
861	u64 val64;
862	__hal_device_t *hldev;
863
864	vxge_assert(vpath != NULL);
865
866	hldev = (__hal_device_t *) vpath->hldev;
867
868	vxge_hal_trace_log_ring("==> %s:%s:%d",
869	    __FILE__, __func__, __LINE__);
870
871	vxge_hal_trace_log_ring(
872	    "vpath = 0x"VXGE_OS_STXFMT", new_frmlen = %d",
873	    (ptr_t) vpath, new_frmlen);
874
875	if (vpath->vp_open == VXGE_HAL_VP_NOT_OPEN) {
876
877		vxge_hal_trace_log_ring("<== %s:%s:%d  Result: %d",
878		    __FILE__, __func__, __LINE__,
879		    VXGE_HAL_ERR_VPATH_NOT_OPEN);
880		return (VXGE_HAL_ERR_VPATH_NOT_OPEN);
881
882	}
883
884	val64 = vxge_os_pio_mem_read64(
885	    vpath->hldev->header.pdev,
886	    vpath->hldev->header.regh0,
887	    &vpath->vp_reg->rxmac_vcfg0);
888
889	val64 &= ~VXGE_HAL_RXMAC_VCFG0_RTS_MAX_FRM_LEN(0x3fff);
890
891	if (vpath->vp_config->ring.max_frm_len !=
892	    VXGE_HAL_MAX_RING_FRM_LEN_USE_MTU) {
893
894		val64 |= VXGE_HAL_RXMAC_VCFG0_RTS_MAX_FRM_LEN(
895		    vpath->vp_config->ring.max_frm_len +
896		    VXGE_HAL_MAC_HEADER_MAX_SIZE);
897
898	} else {
899
900		val64 |= VXGE_HAL_RXMAC_VCFG0_RTS_MAX_FRM_LEN(new_frmlen +
901		    VXGE_HAL_MAC_HEADER_MAX_SIZE);
902	}
903
904	vxge_os_pio_mem_write64(
905	    vpath->hldev->header.pdev,
906	    vpath->hldev->header.regh0,
907	    val64,
908	    &vpath->vp_reg->rxmac_vcfg0);
909
910	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
911	    __FILE__, __func__, __LINE__);
912
913	return (VXGE_HAL_OK);
914}
915
916/*
917 * vxge_hal_ring_rxd_reserve - Reserve ring descriptor.
918 * @vpath_handle: virtual Path handle.
919 * @rxdh: Reserved descriptor. On success HAL fills this "out" parameter
920 *		with a valid handle.
921 * @rxd_priv: Buffer to return pointer to per rxd private space
922 *
923 * Reserve Rx descriptor for the subsequent filling-in (by upper layer
924 * driver (ULD)) and posting on the corresponding channel (@channelh)
925 * via vxge_hal_ring_rxd_post().
926 *
927 * Returns: VXGE_HAL_OK - success.
928 * VXGE_HAL_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available.
929 *
930 */
931vxge_hal_status_e
932vxge_hal_ring_rxd_reserve(
933    vxge_hal_vpath_h vpath_handle,
934    vxge_hal_rxd_h * rxdh,
935    void **rxd_priv)
936{
937	vxge_hal_status_e status;
938#if defined(VXGE_HAL_RX_MULTI_POST_IRQ)
939	unsigned long flags;
940#endif
941	__hal_vpath_handle_t *vp = (__hal_vpath_handle_t *) vpath_handle;
942	__hal_device_t *hldev;
943	__hal_ring_t *ring;
944
945	vxge_assert((vpath_handle != NULL) && (rxdh != NULL) &&
946	    (rxd_priv != NULL));
947
948	hldev = (__hal_device_t *) vp->vpath->hldev;
949
950	vxge_hal_trace_log_ring("==> %s:%s:%d",
951	    __FILE__, __func__, __LINE__);
952
953	vxge_hal_trace_log_ring(
954	    "vpath_handle = 0x"VXGE_OS_STXFMT", rxdh = 0x"VXGE_OS_STXFMT", "
955	    "rxd_priv = 0x"VXGE_OS_STXFMT, (ptr_t) vpath_handle,
956	    (ptr_t) rxdh, (ptr_t) rxd_priv);
957
958	ring = (__hal_ring_t *) vp->vpath->ringh;
959
960	vxge_assert(ring != NULL);
961
962#if defined(VXGE_HAL_RX_MULTI_POST)
963	vxge_os_spin_lock(&ring->channel.post_lock);
964#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
965	vxge_os_spin_lock_irq(&ring->channel.post_lock, flags);
966#endif
967
968	status = __hal_channel_dtr_reserve(&ring->channel, rxdh);
969
970#if defined(VXGE_HAL_RX_MULTI_POST)
971	vxge_os_spin_unlock(&ring->channel.post_lock);
972#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
973	vxge_os_spin_unlock_irq(&ring->channel.post_lock, flags);
974#endif
975
976	if (status == VXGE_HAL_OK) {
977		vxge_hal_ring_rxd_1_t *rxdp = (vxge_hal_ring_rxd_1_t *)*rxdh;
978
979		/* instead of memset: reset	this RxD */
980		rxdp->control_0 = rxdp->control_1 = 0;
981
982		*rxd_priv = VXGE_HAL_RING_ULD_PRIV(ring, rxdp);
983
984#if defined(VXGE_OS_MEMORY_CHECK)
985		VXGE_HAL_RING_HAL_PRIV(ring, rxdp)->allocated = 1;
986#endif
987	}
988
989	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
990	    __FILE__, __func__, __LINE__);
991	return (status);
992}
993
994/*
995 * vxge_hal_ring_rxd_pre_post - Prepare rxd and post
996 * @vpath_handle: virtual Path handle.
997 * @rxdh: Descriptor handle.
998 *
999 * This routine prepares a rxd and posts
1000 */
1001void
1002vxge_hal_ring_rxd_pre_post(
1003    vxge_hal_vpath_h vpath_handle,
1004    vxge_hal_rxd_h rxdh)
1005{
1006
1007#if defined(VXGE_DEBUG_ASSERT)
1008	vxge_hal_ring_rxd_1_t *rxdp = (vxge_hal_ring_rxd_1_t *) rxdh;
1009
1010#endif
1011
1012#if defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1013	unsigned long flags;
1014
1015#endif
1016	__hal_vpath_handle_t *vp = (__hal_vpath_handle_t *) vpath_handle;
1017	__hal_device_t *hldev;
1018	__hal_ring_t *ring;
1019
1020	vxge_assert((vpath_handle != NULL) && (rxdh != NULL));
1021
1022	hldev = (__hal_device_t *) vp->vpath->hldev;
1023
1024	vxge_hal_trace_log_ring("==> %s:%s:%d",
1025	    __FILE__, __func__, __LINE__);
1026
1027	vxge_hal_trace_log_ring(
1028	    "vpath_handle = 0x"VXGE_OS_STXFMT", rxdh = 0x"VXGE_OS_STXFMT,
1029	    (ptr_t) vpath_handle, (ptr_t) rxdh);
1030
1031	ring = (__hal_ring_t *) vp->vpath->ringh;
1032
1033	vxge_assert(ring != NULL);
1034
1035#if defined(VXGE_DEBUG_ASSERT)
1036	/* make	sure device overwrites the (illegal) t_code on completion */
1037	rxdp->control_0 |=
1038	    VXGE_HAL_RING_RXD_T_CODE(VXGE_HAL_RING_RXD_T_CODE_UNUSED);
1039#endif
1040
1041#if defined(VXGE_HAL_RX_MULTI_POST)
1042	vxge_os_spin_lock(&ring->channel.post_lock);
1043#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1044	vxge_os_spin_lock_irq(&ring->channel.post_lock, flags);
1045#endif
1046
1047#if defined(VXGE_DEBUG_ASSERT) && defined(VXGE_HAL_RING_ENFORCE_ORDER)
1048	if (TRUE) {
1049		if (VXGE_HAL_RING_RXD_INDEX(rxdp) != 0) {
1050			vxge_hal_rxd_h prev_rxdh;
1051			__hal_ring_rxd_priv_t *rxdp_priv;
1052			u32 index;
1053
1054			rxdp_priv = VXGE_HAL_RING_HAL_PRIV(ring, rxdp);
1055
1056			if (VXGE_HAL_RING_RXD_INDEX(rxdp) == 0)
1057				index = ring->channel.length;
1058			else
1059				index = VXGE_HAL_RING_RXD_INDEX(rxdp) - 1;
1060
1061			prev_rxdh = ring->channel.dtr_arr[index].dtr;
1062
1063			if (prev_rxdh != NULL &&
1064			    (rxdp_priv->dma_offset & (~0xFFF)) !=
1065			    rxdp_priv->dma_offset) {
1066				vxge_assert((char *) prev_rxdh +
1067				    ring->rxd_size == rxdh);
1068			}
1069		}
1070	}
1071#endif
1072
1073	__hal_channel_dtr_post(&ring->channel, VXGE_HAL_RING_RXD_INDEX(rxdh));
1074
1075	ring->db_byte_count +=
1076	    VXGE_HAL_RING_HAL_PRIV(ring, rxdh)->db_bytes;
1077
1078#if defined(VXGE_HAL_RX_MULTI_POST)
1079	vxge_os_spin_unlock(&ring->channel.post_lock);
1080#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1081	vxge_os_spin_unlock_irq(&ring->channel.post_lock, flags);
1082#endif
1083
1084	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
1085	    __FILE__, __func__, __LINE__);
1086}
1087
1088/*
1089 * vxge_hal_ring_rxd_post_post - Process rxd after post.
1090 * @vpath_handle: virtual Path handle.
1091 * @rxdh: Descriptor handle.
1092 *
1093 * Processes rxd after post
1094 */
1095void
1096vxge_hal_ring_rxd_post_post(
1097    vxge_hal_vpath_h vpath_handle,
1098    vxge_hal_rxd_h rxdh)
1099{
1100	vxge_hal_ring_rxd_1_t *rxdp = (vxge_hal_ring_rxd_1_t *) rxdh;
1101
1102#if defined(VXGE_OS_DMA_REQUIRES_SYNC) && defined(VXGE_HAL_DMA_RXD_STREAMING)
1103	__hal_ring_rxd_priv_t *priv;
1104
1105#endif
1106	__hal_vpath_handle_t *vp = (__hal_vpath_handle_t *) vpath_handle;
1107	__hal_device_t *hldev;
1108	__hal_ring_t *ring;
1109
1110	vxge_assert((vpath_handle != NULL) && (rxdh != NULL));
1111
1112	hldev = (__hal_device_t *) vp->vpath->hldev;
1113
1114	vxge_hal_trace_log_ring("==> %s:%s:%d",
1115	    __FILE__, __func__, __LINE__);
1116
1117	vxge_hal_trace_log_ring(
1118	    "vpath_handle = 0x"VXGE_OS_STXFMT", rxdh = 0x"VXGE_OS_STXFMT,
1119	    (ptr_t) vpath_handle, (ptr_t) rxdh);
1120
1121	ring = (__hal_ring_t *) vp->vpath->ringh;
1122
1123	vxge_assert(ring != NULL);
1124
1125	/* do POST */
1126	rxdp->control_0 |= VXGE_HAL_RING_RXD_LIST_OWN_ADAPTER;
1127
1128	rxdp->control_1 |= VXGE_HAL_RING_RXD_LIST_TAIL_OWN_ADAPTER;
1129
1130#if defined(VXGE_OS_DMA_REQUIRES_SYNC) && defined(VXGE_HAL_DMA_RXD_STREAMING)
1131	priv = __hal_ring_rxd_priv(ring, rxdp);
1132	vxge_os_dma_sync(ring->channel.pdev,
1133	    priv->dma_handle,
1134	    priv->dma_addr,
1135	    priv->dma_offset,
1136	    ring->rxd_size,
1137	    VXGE_OS_DMA_DIR_TODEVICE);
1138#endif
1139	if (ring->stats->common_stats.usage_cnt > 0)
1140		ring->stats->common_stats.usage_cnt--;
1141
1142	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
1143	    __FILE__, __func__, __LINE__);
1144}
1145
1146/*
1147 * vxge_hal_ring_rxd_post - Post descriptor on the ring.
1148 * @vpath_handle: virtual Path handle.
1149 * @rxdh: Descriptor obtained via vxge_hal_ring_rxd_reserve().
1150 *
1151 * Post	descriptor on the ring.
1152 * Prior to posting the	descriptor should be filled in accordance with
1153 * Host/X3100 interface specification for a given service (LL, etc.).
1154 *
1155 */
1156void
1157vxge_hal_ring_rxd_post(
1158    vxge_hal_vpath_h vpath_handle,
1159    vxge_hal_rxd_h rxdh)
1160{
1161	vxge_hal_ring_rxd_1_t *rxdp = (vxge_hal_ring_rxd_1_t *) rxdh;
1162
1163#if defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1164	unsigned long flags;
1165#endif
1166
1167	__hal_vpath_handle_t *vp = (__hal_vpath_handle_t *) vpath_handle;
1168	__hal_device_t *hldev;
1169	__hal_ring_t *ring;
1170
1171	vxge_assert((vpath_handle != NULL) && (rxdh != NULL));
1172
1173	hldev = (__hal_device_t *) vp->vpath->hldev;
1174
1175	vxge_hal_trace_log_ring("==> %s:%s:%d",
1176	    __FILE__, __func__, __LINE__);
1177
1178	vxge_hal_trace_log_ring(
1179	    "vpath_handle = 0x"VXGE_OS_STXFMT", rxdh = 0x"VXGE_OS_STXFMT,
1180	    (ptr_t) vpath_handle, (ptr_t) rxdh);
1181
1182	ring = (__hal_ring_t *) vp->vpath->ringh;
1183
1184	vxge_assert(ring != NULL);
1185
1186	/* Based on Titan HW bugzilla # 3039, we need to reset the tcode */
1187	rxdp->control_0 = 0;
1188
1189#if defined(VXGE_DEBUG_ASSERT)
1190	/* make	sure device overwrites the (illegal) t_code on completion */
1191	rxdp->control_0 |=
1192	    VXGE_HAL_RING_RXD_T_CODE(VXGE_HAL_RING_RXD_T_CODE_UNUSED);
1193#endif
1194
1195	rxdp->control_1 |= VXGE_HAL_RING_RXD_LIST_TAIL_OWN_ADAPTER;
1196	rxdp->control_0 |= VXGE_HAL_RING_RXD_LIST_OWN_ADAPTER;
1197
1198#if defined(VXGE_OS_DMA_REQUIRES_SYNC) && defined(VXGE_HAL_DMA_RXD_STREAMING)
1199	{
1200		__hal_ring_rxd_priv_t *rxdp_temp1;
1201		rxdp_temp1 = VXGE_HAL_RING_HAL_PRIV(ring, rxdp);
1202		vxge_os_dma_sync(ring->channel.pdev,
1203		    rxdp_temp1->dma_handle,
1204		    rxdp_temp1->dma_addr,
1205		    rxdp_temp1->dma_offset,
1206		    ring->rxd_size,
1207		    VXGE_OS_DMA_DIR_TODEVICE);
1208	}
1209#endif
1210
1211#if defined(VXGE_HAL_RX_MULTI_POST)
1212	vxge_os_spin_lock(&ring->channel.post_lock);
1213#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1214	vxge_os_spin_lock_irq(&ring->channel.post_lock, flags);
1215#endif
1216
1217#if defined(VXGE_DEBUG_ASSERT) && defined(VXGE_HAL_RING_ENFORCE_ORDER)
1218	if (TRUE) {
1219		if (VXGE_HAL_RING_RXD_INDEX(rxdp) != 0) {
1220
1221			vxge_hal_rxd_h prev_rxdh;
1222			__hal_ring_rxd_priv_t *rxdp_temp2;
1223
1224			rxdp_temp2 = VXGE_HAL_RING_HAL_PRIV(ring, rxdp);
1225			prev_rxdh =
1226			    ring->channel.dtr_arr[VXGE_HAL_RING_RXD_INDEX(rxdp) - 1].dtr;
1227
1228			if (prev_rxdh != NULL &&
1229			    (rxdp_temp2->dma_offset & (~0xFFF)) != rxdp_temp2->dma_offset)
1230				vxge_assert((char *) prev_rxdh + ring->rxd_size == rxdh);
1231		}
1232	}
1233#endif
1234
1235	__hal_channel_dtr_post(&ring->channel, VXGE_HAL_RING_RXD_INDEX(rxdh));
1236
1237	ring->db_byte_count +=
1238	    VXGE_HAL_RING_HAL_PRIV(ring, rxdp)->db_bytes;
1239
1240#if defined(VXGE_HAL_RX_MULTI_POST)
1241	vxge_os_spin_unlock(&ring->channel.post_lock);
1242#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1243	vxge_os_spin_unlock_irq(&ring->channel.post_lock, flags);
1244#endif
1245
1246	if (ring->stats->common_stats.usage_cnt > 0)
1247		ring->stats->common_stats.usage_cnt--;
1248
1249	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
1250	    __FILE__, __func__, __LINE__);
1251}
1252
1253/*
1254 * vxge_hal_ring_rxd_post_post_wmb - Process rxd after post with memory barrier
1255 * @vpath_handle: virtual Path handle.
1256 * @rxdh: Descriptor handle.
1257 *
1258 * Processes rxd after post with memory barrier.
1259 */
1260void
1261vxge_hal_ring_rxd_post_post_wmb(
1262    vxge_hal_vpath_h vpath_handle,
1263    vxge_hal_rxd_h rxdh)
1264{
1265	__hal_vpath_handle_t *vp = (__hal_vpath_handle_t *) vpath_handle;
1266	__hal_device_t *hldev;
1267
1268	vxge_assert((vpath_handle != NULL) && (rxdh != NULL));
1269
1270	hldev = (__hal_device_t *) vp->vpath->hldev;
1271
1272	vxge_hal_trace_log_ring("==> %s:%s:%d",
1273	    __FILE__, __func__, __LINE__);
1274
1275	vxge_hal_trace_log_ring(
1276	    "vpath_handle = 0x"VXGE_OS_STXFMT", rxdh = 0x"VXGE_OS_STXFMT,
1277	    (ptr_t) vpath_handle, (ptr_t) rxdh);
1278
1279	/* Do memory barrier before changing the ownership */
1280	vxge_os_wmb();
1281
1282	vxge_hal_ring_rxd_post_post(vpath_handle, rxdh);
1283
1284	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
1285	    __FILE__, __func__, __LINE__);
1286}
1287
1288/*
1289 * vxge_hal_ring_rxd_post_post_db - Post Doorbell after posting the rxd(s).
1290 * @vpath_handle: virtual Path handle.
1291 *
1292 * Post Doorbell after posting the rxd(s).
1293 */
1294void
1295vxge_hal_ring_rxd_post_post_db(
1296    vxge_hal_vpath_h vpath_handle)
1297{
1298	__hal_vpath_handle_t *vp = (__hal_vpath_handle_t *) vpath_handle;
1299	__hal_device_t *hldev;
1300	__hal_ring_t *ring;
1301
1302	vxge_assert(vpath_handle != NULL);
1303
1304	hldev = (__hal_device_t *) vp->vpath->hldev;
1305
1306	ring = (__hal_ring_t *) vp->vpath->ringh;
1307
1308	vxge_hal_trace_log_ring("==> %s:%s:%d",
1309	    __FILE__, __func__, __LINE__);
1310
1311	vxge_hal_trace_log_ring("vpath_handle = 0x"VXGE_OS_STXFMT,
1312	    (ptr_t) vpath_handle);
1313
1314#if defined(VXGE_HAL_RX_MULTI_POST)
1315	vxge_os_spin_lock(&ring->channel.post_lock);
1316#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1317	vxge_os_spin_lock_irq(&ring->channel.post_lock, flags);
1318#endif
1319
1320	if (ring->db_byte_count <= ring->rxd_mem_avail) {
1321		__hal_rxd_db_post(vpath_handle, ring->db_byte_count);
1322		ring->rxd_mem_avail -= ring->db_byte_count;
1323		ring->db_byte_count = 0;
1324	} else {
1325		__hal_rxd_db_post(vpath_handle, ring->rxd_mem_avail);
1326		ring->db_byte_count -= ring->rxd_mem_avail;
1327		ring->rxd_mem_avail = 0;
1328	}
1329
1330#if defined(VXGE_HAL_RX_MULTI_POST)
1331	vxge_os_spin_unlock(&ring->channel.post_lock);
1332#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1333	vxge_os_spin_unlock_irq(&ring->channel.post_lock, flags);
1334#endif
1335
1336	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
1337	    __FILE__, __func__, __LINE__);
1338}
1339
1340/*
1341 * vxge_hal_ring_is_next_rxd_completed - Check if the next rxd is completed
1342 * @vpath_handle: Virtual Path handle.
1343 *
1344 * Checks if the _next_	completed descriptor is	in host	memory
1345 *
1346 * Returns: VXGE_HAL_OK - success.
1347 * VXGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed	descriptors
1348 * are currently available for processing.
1349 */
1350vxge_hal_status_e
1351vxge_hal_ring_is_next_rxd_completed(
1352    vxge_hal_vpath_h vpath_handle)
1353{
1354	__hal_ring_t *ring;
1355	vxge_hal_rxd_h rxdh;
1356	vxge_hal_ring_rxd_1_t *rxdp;	/* doesn't matter 1, 3 or 5... */
1357	__hal_device_t *hldev;
1358	vxge_hal_status_e status = VXGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
1359	__hal_vpath_handle_t *vp = (__hal_vpath_handle_t *) vpath_handle;
1360
1361	vxge_assert(vpath_handle != NULL);
1362
1363	hldev = (__hal_device_t *) vp->vpath->hldev;
1364
1365	vxge_hal_trace_log_ring("==> %s:%s:%d",
1366	    __FILE__, __func__, __LINE__);
1367
1368	vxge_hal_trace_log_ring("vpath_handle = 0x"VXGE_OS_STXFMT,
1369	    (ptr_t) vpath_handle);
1370
1371	ring = (__hal_ring_t *) vp->vpath->ringh;
1372
1373	vxge_assert(ring != NULL);
1374
1375#if defined(VXGE_HAL_RX_MULTI_POST)
1376	vxge_os_spin_lock(&ring->channel.post_lock);
1377#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1378	vxge_os_spin_lock_irq(&ring->channel.post_lock, flags);
1379#endif
1380
1381	__hal_channel_dtr_try_complete(&ring->channel, &rxdh);
1382
1383	rxdp = (vxge_hal_ring_rxd_1_t *) rxdh;
1384
1385	if (rxdp != NULL) {
1386
1387		/* check whether it is not the end */
1388		if ((!(rxdp->control_0 & VXGE_HAL_RING_RXD_LIST_OWN_ADAPTER)) &&
1389		    (!(rxdp->control_1 &
1390		    VXGE_HAL_RING_RXD_LIST_TAIL_OWN_ADAPTER))) {
1391
1392			status = VXGE_HAL_OK;
1393		}
1394	}
1395
1396#if defined(VXGE_HAL_RX_MULTI_POST)
1397	vxge_os_spin_unlock(&ring->channel.post_lock);
1398#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1399	vxge_os_spin_unlock_irq(&ring->channel.post_lock, flags);
1400#endif
1401
1402	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: %d",
1403	    __FILE__, __func__, __LINE__, status);
1404	return (status);
1405}
1406
1407/*
1408 * vxge_hal_ring_rxd_next_completed - Get the _next_ completed descriptor.
1409 * @channelh: Channel handle.
1410 * @rxdh: Descriptor handle. Returned by HAL.
1411 * @rxd_priv: Buffer to return a pointer to the per rxd space allocated
1412 * @t_code:	Transfer code, as per X3100 User Guide,
1413 *			Receive	Descriptor Format. Returned	by HAL.
1414 *
1415 * Retrieve the	_next_ completed descriptor.
1416 * HAL uses ring callback (*vxge_hal_ring_callback_f) to notifiy
1417 * upper-layer driver (ULD) of new completed descriptors. After that
1418 * the ULD can use vxge_hal_ring_rxd_next_completed to retrieve the rest
1419 * completions (the very first completion is passed by HAL via
1420 * vxge_hal_ring_callback_f).
1421 *
1422 * Implementation-wise,	the upper-layer	driver is free to call
1423 * vxge_hal_ring_rxd_next_completed either immediately from inside the
1424 * ring callback, or in a deferred fashion and separate (from HAL)
1425 * context.
1426 *
1427 * Non-zero @t_code means failure to fill-in receive buffer(s)
1428 * of the descriptor.
1429 * For instance, parity	error detected during the data transfer.
1430 * In this case	X3100 will	complete the descriptor	and	indicate
1431 * for the host	that the received data is not to be	used.
1432 * For details please refer	to X3100 User Guide.
1433 *
1434 * Returns: VXGE_HAL_OK - success.
1435 * VXGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed	descriptors
1436 * are currently available for processing.
1437 *
1438 * See also: vxge_hal_ring_callback_f {},
1439 * vxge_hal_fifo_rxd_next_completed(), vxge_hal_status_e {}.
1440 */
1441vxge_hal_status_e
1442vxge_hal_ring_rxd_next_completed(
1443    vxge_hal_vpath_h vpath_handle,
1444    vxge_hal_rxd_h *rxdh,
1445    void **rxd_priv,
1446    u8 *t_code)
1447{
1448	__hal_ring_t *ring;
1449	vxge_hal_ring_rxd_5_t *rxdp;	/* doesn't matter 1, 3 or 5... */
1450#if defined(VXGE_OS_DMA_REQUIRES_SYNC) && defined(VXGE_HAL_DMA_RXD_STREAMING)
1451	__hal_ring_rxd_priv_t *priv;
1452#endif
1453	__hal_device_t *hldev;
1454	vxge_hal_status_e status = VXGE_HAL_INF_NO_MORE_COMPLETED_DESCRIPTORS;
1455	__hal_vpath_handle_t *vp = (__hal_vpath_handle_t *) vpath_handle;
1456	u64 own, control_0, control_1;
1457
1458	vxge_assert((vpath_handle != NULL) && (rxdh != NULL) &&
1459	    (rxd_priv != NULL) && (t_code != NULL));
1460
1461	hldev = (__hal_device_t *) vp->vpath->hldev;
1462
1463	vxge_hal_trace_log_ring("==> %s:%s:%d",
1464	    __FILE__, __func__, __LINE__);
1465
1466	vxge_hal_trace_log_ring(
1467	    "vpath_handle = 0x"VXGE_OS_STXFMT", rxdh = 0x"VXGE_OS_STXFMT", "
1468	    "rxd_priv = 0x"VXGE_OS_STXFMT", t_code = 0x"VXGE_OS_STXFMT,
1469	    (ptr_t) vpath_handle, (ptr_t) rxdh, (ptr_t) rxd_priv,
1470	    (ptr_t) t_code);
1471
1472	ring = (__hal_ring_t *) vp->vpath->ringh;
1473
1474	vxge_assert(ring != NULL);
1475
1476	*rxdh = 0;
1477	*rxd_priv = NULL;
1478
1479#if defined(VXGE_HAL_RX_MULTI_POST)
1480	vxge_os_spin_lock(&ring->channel.post_lock);
1481#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1482	vxge_os_spin_lock_irq(&ring->channel.post_lock, flags);
1483#endif
1484
1485	__hal_channel_dtr_try_complete(&ring->channel, rxdh);
1486
1487	rxdp = (vxge_hal_ring_rxd_5_t *)*rxdh;
1488	if (rxdp != NULL) {
1489
1490#if defined(VXGE_OS_DMA_REQUIRES_SYNC) && defined(VXGE_HAL_DMA_RXD_STREAMING)
1491		/*
1492		 * Note: 24 bytes at most means:
1493		 *	- Control_3 in case of 5-buffer	mode
1494		 *	- Control_1 and	Control_2
1495		 *
1496		 * This is the only length needs to be invalidated
1497		 * type of channels.
1498		 */
1499		priv = __hal_ring_rxd_priv(ring, rxdp);
1500		vxge_os_dma_sync(ring->channel.pdev,
1501		    priv->dma_handle,
1502		    priv->dma_addr,
1503		    priv->dma_offset,
1504		    24,
1505		    VXGE_OS_DMA_DIR_FROMDEVICE);
1506#endif
1507		*t_code = (u8) VXGE_HAL_RING_RXD_T_CODE_GET(rxdp->control_0);
1508
1509		control_0 = rxdp->control_0;
1510		control_1 = rxdp->control_1;
1511		own = control_0 & VXGE_HAL_RING_RXD_LIST_OWN_ADAPTER;
1512
1513		/* check whether it is not the end */
1514		if ((!own && !(control_1 & VXGE_HAL_RING_RXD_LIST_TAIL_OWN_ADAPTER)) ||
1515		    (*t_code == VXGE_HAL_RING_RXD_T_CODE_FRM_DROP)) {
1516
1517#ifndef	VXGE_HAL_IRQ_POLLING
1518			if (++ring->cmpl_cnt > ring->indicate_max_pkts) {
1519				/*
1520				 * reset it. since we don't want to return
1521				 * garbage to the ULD
1522				 */
1523				*rxdh = 0;
1524				status = VXGE_HAL_COMPLETIONS_REMAIN;
1525			} else {
1526#endif
1527				__hal_channel_dtr_complete(&ring->channel);
1528
1529				*rxd_priv = VXGE_HAL_RING_ULD_PRIV(ring, rxdp);
1530
1531				ring->rxd_mem_avail +=
1532				    (VXGE_HAL_RING_HAL_PRIV(ring, rxdp))->db_bytes;
1533
1534				ring->stats->common_stats.usage_cnt++;
1535				if (ring->stats->common_stats.usage_max <
1536				    ring->stats->common_stats.usage_cnt)
1537					ring->stats->common_stats.usage_max =
1538					    ring->stats->common_stats.usage_cnt;
1539
1540				switch (ring->buffer_mode) {
1541				case VXGE_HAL_RING_RXD_BUFFER_MODE_1:
1542					ring->channel.poll_bytes +=
1543					    (u32) VXGE_HAL_RING_RXD_1_BUFFER0_SIZE_GET(
1544					    rxdp->control_1);
1545					break;
1546				case VXGE_HAL_RING_RXD_BUFFER_MODE_3:
1547					ring->channel.poll_bytes +=
1548					    (u32) VXGE_HAL_RING_RXD_3_BUFFER0_SIZE_GET(
1549					    rxdp->control_1) +
1550					    (u32) VXGE_HAL_RING_RXD_3_BUFFER1_SIZE_GET(
1551					    rxdp->control_1) +
1552					    (u32) VXGE_HAL_RING_RXD_3_BUFFER2_SIZE_GET(
1553					    rxdp->control_1);
1554					break;
1555				case VXGE_HAL_RING_RXD_BUFFER_MODE_5:
1556					ring->channel.poll_bytes +=
1557					    (u32) VXGE_HAL_RING_RXD_5_BUFFER0_SIZE_GET(
1558					    rxdp->control_1) +
1559					    (u32) VXGE_HAL_RING_RXD_5_BUFFER1_SIZE_GET(
1560					    rxdp->control_1) +
1561					    (u32) VXGE_HAL_RING_RXD_5_BUFFER2_SIZE_GET(
1562					    rxdp->control_1) +
1563					    (u32) VXGE_HAL_RING_RXD_5_BUFFER3_SIZE_GET(
1564					    rxdp->control_2) +
1565					    (u32) VXGE_HAL_RING_RXD_5_BUFFER4_SIZE_GET(
1566					    rxdp->control_2);
1567					break;
1568				}
1569
1570				status = VXGE_HAL_OK;
1571#ifndef	VXGE_HAL_IRQ_POLLING
1572			}
1573#endif
1574		}
1575	}
1576
1577#if defined(VXGE_HAL_RX_MULTI_POST)
1578	vxge_os_spin_unlock(&ring->channel.post_lock);
1579#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1580	vxge_os_spin_unlock_irq(&ring->channel.post_lock, flags);
1581#endif
1582
1583	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: %d",
1584	    __FILE__, __func__, __LINE__, status);
1585	return (status);
1586}
1587
1588
1589/*
1590 * vxge_hal_ring_handle_tcode - Handle transfer code.
1591 * @vpath_handle: Virtual Path handle.
1592 * @rxdh: Descriptor handle.
1593 * @t_code: One of the enumerated (and documented in the X3100 user guide)
1594 *	 "transfer codes".
1595 *
1596 * Handle descriptor's transfer code. The latter comes with each completed
1597 * descriptor.
1598 *
1599 * Returns: one of the vxge_hal_status_e {} enumerated types.
1600 * VXGE_HAL_OK			- for success.
1601 * VXGE_HAL_ERR_CRITICAL	- when encounters critical error.
1602 */
1603vxge_hal_status_e
1604vxge_hal_ring_handle_tcode(
1605    vxge_hal_vpath_h vpath_handle,
1606    vxge_hal_rxd_h rxdh,
1607    u8 t_code)
1608{
1609	__hal_device_t *hldev;
1610	__hal_vpath_handle_t *vp = (__hal_vpath_handle_t *) vpath_handle;
1611
1612	vxge_assert((vpath_handle != NULL) && (rxdh != NULL));
1613
1614	hldev = (__hal_device_t *) vp->vpath->hldev;
1615
1616	vxge_hal_trace_log_ring("==> %s:%s:%d",
1617	    __FILE__, __func__, __LINE__);
1618
1619	vxge_hal_trace_log_ring(
1620	    "vpath_handle = 0x"VXGE_OS_STXFMT", "
1621	    "rxdh = 0x"VXGE_OS_STXFMT", t_code = 0x%d",
1622	    (ptr_t) vpath_handle, (ptr_t) rxdh, t_code);
1623
1624	switch (t_code) {
1625	case 0x0:
1626		/* 0x0: Transfer ok. */
1627		break;
1628	case 0x1:
1629		/*
1630		 * 0x1: Layer 3 checksum presentation
1631		 *	configuration mismatch.
1632		 */
1633		break;
1634	case 0x2:
1635		/*
1636		 * 0x2: Layer 4 checksum presentation
1637		 *	configuration mismatch.
1638		 */
1639		break;
1640	case 0x3:
1641		/*
1642		 * 0x3: Layer 3 and Layer 4 checksum
1643		 *	presentation configuration mismatch.
1644		 */
1645		break;
1646	case 0x4:
1647		/* 0x4: Reserved. */
1648		break;
1649	case 0x5:
1650		/*
1651		 * 0x5: Layer 3 error unparseable packet,
1652		 *	such as unknown IPv6 header.
1653		 */
1654		break;
1655	case 0x6:
1656		/*
1657		 * 0x6: Layer 2 error frame integrity
1658		 *	error, such as FCS or ECC).
1659		 */
1660		break;
1661	case 0x7:
1662		/*
1663		 * 0x7: Buffer size error the RxD buffer(s)
1664		 *	were not appropriately sized and
1665		 *	data loss occurred.
1666		 */
1667		break;
1668	case 0x8:
1669		/* 0x8: Internal ECC error RxD corrupted. */
1670		__hal_device_handle_error(vp->vpath->hldev,
1671		    vp->vpath->vp_id, VXGE_HAL_EVENT_ECCERR);
1672		break;
1673	case 0x9:
1674		/*
1675		 * 0x9: Benign overflow the contents of
1676		 *	Segment1 exceeded the capacity of
1677		 *	Buffer1 and the remainder was placed
1678		 *	in Buffer2. Segment2 now starts in
1679		 *	Buffer3. No data loss or errors occurred.
1680		 */
1681		break;
1682	case 0xA:
1683		/*
1684		 * 0xA: Buffer size 0 one of the RxDs
1685		 *	assigned buffers has a size of 0 bytes.
1686		 */
1687		break;
1688	case 0xB:
1689		/* 0xB: Reserved. */
1690		break;
1691	case 0xC:
1692		/*
1693		 * 0xC: Frame dropped either due to
1694		 *	VPath Reset or because of a VPIN mismatch.
1695		 */
1696		break;
1697	case 0xD:
1698		/* 0xD: Reserved. */
1699		break;
1700	case 0xE:
1701		/* 0xE: Reserved. */
1702		break;
1703	case 0xF:
1704		/*
1705		 * 0xF: Multiple errors more than one
1706		 *	transfer code condition occurred.
1707		 */
1708		break;
1709	default:
1710		vxge_hal_trace_log_ring("<== %s:%s:%d  Result: %d",
1711		    __FILE__, __func__, __LINE__, VXGE_HAL_ERR_INVALID_TCODE);
1712		return (VXGE_HAL_ERR_INVALID_TCODE);
1713	}
1714
1715	vp->vpath->sw_stats->ring_stats.rxd_t_code_err_cnt[t_code]++;
1716
1717	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: %d",
1718	    __FILE__, __func__, __LINE__, VXGE_HAL_OK);
1719	return (VXGE_HAL_OK);
1720}
1721
1722
1723/*
1724 * vxge_hal_ring_rxd_private_get - Get ULD private per-descriptor data.
1725 * @vpath_handle: Virtual Path handle.
1726 * @rxdh: Descriptor handle.
1727 *
1728 * Returns: private ULD	info associated	with the descriptor.
1729 * ULD requests	per-descriptor space via vxge_hal_ring_attr.
1730 *
1731 */
1732void *
1733vxge_hal_ring_rxd_private_get(
1734    vxge_hal_vpath_h vpath_handle,
1735    vxge_hal_rxd_h rxdh)
1736{
1737	__hal_vpath_handle_t *vp = (__hal_vpath_handle_t *) vpath_handle;
1738
1739	return (VXGE_HAL_RING_ULD_PRIV(
1740	    ((__hal_ring_t *) vp->vpath->ringh), rxdh));
1741
1742}
1743
1744/*
1745 * vxge_hal_ring_rxd_free - Free descriptor.
1746 * @vpath_handle: Virtual Path handle.
1747 * @rxdh: Descriptor handle.
1748 *
1749 * Free	the reserved descriptor. This operation is "symmetrical" to
1750 * vxge_hal_ring_rxd_reserve. The "free-ing" completes the descriptor's
1751 * lifecycle.
1752 *
1753 * After free-ing (see vxge_hal_ring_rxd_free()) the descriptor again can
1754 * be:
1755 *
1756 * - reserved (vxge_hal_ring_rxd_reserve);
1757 *
1758 * - posted	(vxge_hal_ring_rxd_post);
1759 *
1760 * - completed (vxge_hal_ring_rxd_next_completed);
1761 *
1762 * - and recycled again	(vxge_hal_ring_rxd_free).
1763 *
1764 * For alternative state transitions and more details please refer to
1765 * the design doc.
1766 *
1767 */
1768void
1769vxge_hal_ring_rxd_free(
1770    vxge_hal_vpath_h vpath_handle,
1771    vxge_hal_rxd_h rxdh)
1772{
1773#if defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1774	unsigned long flags;
1775
1776#endif
1777	__hal_ring_t *ring;
1778	__hal_device_t *hldev;
1779	__hal_vpath_handle_t *vp = (__hal_vpath_handle_t *) vpath_handle;
1780
1781	vxge_assert((vpath_handle != NULL) && (rxdh != NULL));
1782
1783	hldev = (__hal_device_t *) vp->vpath->hldev;
1784
1785	vxge_hal_trace_log_ring("==> %s:%s:%d",
1786	    __FILE__, __func__, __LINE__);
1787
1788	vxge_hal_trace_log_ring(
1789	    "vpath_handle = 0x"VXGE_OS_STXFMT", rxdh = 0x"VXGE_OS_STXFMT,
1790	    (ptr_t) vpath_handle, (ptr_t) rxdh);
1791
1792	ring = (__hal_ring_t *) vp->vpath->ringh;
1793
1794	vxge_assert(ring != NULL);
1795
1796#if defined(VXGE_HAL_RX_MULTI_POST)
1797	vxge_os_spin_lock(&ring->channel.post_lock);
1798#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1799	vxge_os_spin_lock_irq(&ring->channel.post_lock, flags);
1800#endif
1801
1802	__hal_channel_dtr_free(&ring->channel, VXGE_HAL_RING_RXD_INDEX(rxdh));
1803#if defined(VXGE_OS_MEMORY_CHECK)
1804	VXGE_HAL_RING_HAL_PRIV(ring, rxdh)->allocated = 0;
1805#endif
1806
1807#if defined(VXGE_HAL_RX_MULTI_POST)
1808	vxge_os_spin_unlock(&ring->channel.post_lock);
1809#elif defined(VXGE_HAL_RX_MULTI_POST_IRQ)
1810	vxge_os_spin_unlock_irq(&ring->channel.post_lock, flags);
1811#endif
1812
1813	vxge_hal_trace_log_ring("<== %s:%s:%d  Result: 0",
1814	    __FILE__, __func__, __LINE__);
1815}
1816