1 /*-
2 * Copyright(c) 2002-2011 Exar Corp.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification are permitted provided the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the Exar Corporation nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 /*$FreeBSD$*/
32
33 #include <dev/vxge/vxgehal/vxgehal.h>
34
35 /*
36 * __hal_ring_block_memblock_idx - Return the memblock index
37 * @block: Virtual address of memory block
38 *
39 * This function returns the index of memory block
40 */
41 static inline u32
__hal_ring_block_memblock_idx(vxge_hal_ring_block_t block)42 __hal_ring_block_memblock_idx(
43 vxge_hal_ring_block_t block)
44 {
45 return (u32)*((u64 *) ((void *)((u8 *) block +
46 VXGE_HAL_RING_MEMBLOCK_IDX_OFFSET)));
47 }
48
49 /*
50 * __hal_ring_block_memblock_idx_set - Sets the memblock index
51 * @block: Virtual address of memory block
52 * @memblock_idx: Index of memory block
53 *
54 * This function sets index to a memory block
55 */
56 static inline void
__hal_ring_block_memblock_idx_set(vxge_hal_ring_block_t block,u32 memblock_idx)57 __hal_ring_block_memblock_idx_set(
58 vxge_hal_ring_block_t block,
59 u32 memblock_idx)
60 {
61 *((u64 *) ((void *)((u8 *) block +
62 VXGE_HAL_RING_MEMBLOCK_IDX_OFFSET))) = memblock_idx;
63 }
64
65 #if 0
66 /*
67 * __hal_ring_block_next_pointer - Returns the dma address of next block
68 * @block: RxD block
69 *
70 * Returns the dma address of next block stored in the RxD block
71 */
72 static inline dma_addr_t
73 /* LINTED */
74 __hal_ring_block_next_pointer(
75 vxge_hal_ring_block_t *block)
76 {
77 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 */
89 static inline void
__hal_ring_block_next_pointer_set(vxge_hal_ring_block_t * block,dma_addr_t dma_next)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 */
105 u64
__hal_ring_first_block_address_get(vxge_hal_ring_h ringh)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 */
128 static ptrdiff_t
__hal_ring_item_dma_offset(vxge_hal_mempool_h mempoolh,void * item)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 */
171 static dma_addr_t
__hal_ring_item_dma_addr(vxge_hal_mempool_h mempoolh,void * item,pci_dma_h * dma_handle)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 */
229 static void
__hal_ring_rxdblock_link(vxge_hal_mempool_h mempoolh,__hal_ring_t * ring,u32 from,u32 to)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 */
309 static vxge_hal_status_e
__hal_ring_mempool_item_alloc(vxge_hal_mempool_h mempoolh,void * memblock,u32 memblock_index,vxge_hal_mempool_dma_t * dma_object,void * item,u32 item_index,u32 is_last,void * userdata)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 */
424 static vxge_hal_status_e
__hal_ring_mempool_item_free(vxge_hal_mempool_h mempoolh,void * memblock,u32 memblock_index,vxge_hal_mempool_dma_t * dma_object,void * item,u32 item_index,u32 is_last,void * userdata)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 */
466 static vxge_hal_status_e
__hal_ring_initial_replenish(__hal_ring_t * ring,vxge_hal_reopen_e reopen)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 */
521 vxge_hal_status_e
__hal_ring_create(vxge_hal_vpath_h vpath_handle,vxge_hal_ring_attr_t * attr)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 */
683 void
__hal_ring_abort(vxge_hal_ring_h ringh,vxge_hal_reopen_e reopen)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 */
743 vxge_hal_status_e
__hal_ring_reset(vxge_hal_ring_h ringh)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 */
800 void
__hal_ring_delete(vxge_hal_vpath_h vpath_handle)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 */
856 vxge_hal_status_e
__hal_ring_frame_length_set(__hal_virtualpath_t * vpath,u32 new_frmlen)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 */
931 vxge_hal_status_e
vxge_hal_ring_rxd_reserve(vxge_hal_vpath_h vpath_handle,vxge_hal_rxd_h * rxdh,void ** rxd_priv)932 vxge_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 */
1001 void
vxge_hal_ring_rxd_pre_post(vxge_hal_vpath_h vpath_handle,vxge_hal_rxd_h rxdh)1002 vxge_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 */
1095 void
vxge_hal_ring_rxd_post_post(vxge_hal_vpath_h vpath_handle,vxge_hal_rxd_h rxdh)1096 vxge_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 */
1156 void
vxge_hal_ring_rxd_post(vxge_hal_vpath_h vpath_handle,vxge_hal_rxd_h rxdh)1157 vxge_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 */
1260 void
vxge_hal_ring_rxd_post_post_wmb(vxge_hal_vpath_h vpath_handle,vxge_hal_rxd_h rxdh)1261 vxge_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 */
1294 void
vxge_hal_ring_rxd_post_post_db(vxge_hal_vpath_h vpath_handle)1295 vxge_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 */
1350 vxge_hal_status_e
vxge_hal_ring_is_next_rxd_completed(vxge_hal_vpath_h vpath_handle)1351 vxge_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 */
1441 vxge_hal_status_e
vxge_hal_ring_rxd_next_completed(vxge_hal_vpath_h vpath_handle,vxge_hal_rxd_h * rxdh,void ** rxd_priv,u8 * t_code)1442 vxge_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 */
1603 vxge_hal_status_e
vxge_hal_ring_handle_tcode(vxge_hal_vpath_h vpath_handle,vxge_hal_rxd_h rxdh,u8 t_code)1604 vxge_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 */
1732 void *
vxge_hal_ring_rxd_private_get(vxge_hal_vpath_h vpath_handle,vxge_hal_rxd_h rxdh)1733 vxge_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 */
1768 void
vxge_hal_ring_rxd_free(vxge_hal_vpath_h vpath_handle,vxge_hal_rxd_h rxdh)1769 vxge_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