1221167Sgnn/*-
2221167Sgnn * Copyright(c) 2002-2011 Exar Corp.
3221167Sgnn * All rights reserved.
4221167Sgnn *
5221167Sgnn * Redistribution and use in source and binary forms, with or without
6221167Sgnn * modification are permitted provided the following conditions are met:
7221167Sgnn *
8221167Sgnn *    1. Redistributions of source code must retain the above copyright notice,
9221167Sgnn *       this list of conditions and the following disclaimer.
10221167Sgnn *
11221167Sgnn *    2. Redistributions in binary form must reproduce the above copyright
12221167Sgnn *       notice, this list of conditions and the following disclaimer in the
13221167Sgnn *       documentation and/or other materials provided with the distribution.
14221167Sgnn *
15221167Sgnn *    3. Neither the name of the Exar Corporation nor the names of its
16221167Sgnn *       contributors may be used to endorse or promote products derived from
17221167Sgnn *       this software without specific prior written permission.
18221167Sgnn *
19221167Sgnn * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20221167Sgnn * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21221167Sgnn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22221167Sgnn * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23221167Sgnn * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24221167Sgnn * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25221167Sgnn * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26221167Sgnn * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27221167Sgnn * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28221167Sgnn * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29221167Sgnn * POSSIBILITY OF SUCH DAMAGE.
30221167Sgnn */
31221167Sgnn/*$FreeBSD$*/
32221167Sgnn
33221167Sgnn#ifndef	VXGE_HAL_RING_H
34221167Sgnn#define	VXGE_HAL_RING_H
35221167Sgnn
36221167Sgnn__EXTERN_BEGIN_DECLS
37221167Sgnn
38221167Sgnntypedef u8 vxge_hal_ring_block_t[VXGE_OS_HOST_PAGE_SIZE];
39221167Sgnn
40221167Sgnn#define	VXGE_HAL_RING_NEXT_BLOCK_POINTER_OFFSET (VXGE_OS_HOST_PAGE_SIZE-8)
41221167Sgnn#define	VXGE_HAL_RING_MEMBLOCK_IDX_OFFSET	(VXGE_OS_HOST_PAGE_SIZE-16)
42221167Sgnn
43221167Sgnn/*
44221167Sgnn * struct __hal_ring_rxd_priv_t - Receive descriptor HAL-private data.
45221167Sgnn * @dma_addr: DMA (mapped) address of _this_ descriptor.
46221167Sgnn * @dma_handle: DMA handle used to map the descriptor onto device.
47221167Sgnn * @dma_offset: Descriptor's offset in the memory block. HAL allocates
48221167Sgnn *		descriptors in memory blocks of %VXGE_OS_HOST_PAGE_SIZE
49221167Sgnn *		bytes. Each memblock is contiguous DMA-able memory. Each
50221167Sgnn *		memblock contains 1 or more 4KB RxD blocks visible to the
51221167Sgnn *		X3100 hardware.
52221167Sgnn * @dma_object: DMA address and handle of the memory block that contains
53221167Sgnn *		the descriptor. This member is used only in the "checked"
54221167Sgnn *		version of the HAL (to enforce certain assertions);
55221167Sgnn *		otherwise it gets compiled out.
56221167Sgnn * @allocated: True if the descriptor is reserved, 0 otherwise. Internal usage.
57221167Sgnn * @db_bytes: Number of doorbell bytes to be posted for this Rxd. This includes
58221167Sgnn *		next RxD block pointers
59221167Sgnn *
60221167Sgnn * Per-receive decsriptor HAL-private data. HAL uses the space to keep DMA
61221167Sgnn * information associated with the descriptor. Note that ULD can ask HAL
62221167Sgnn * to allocate additional per-descriptor space for its own (ULD-specific)
63221167Sgnn * purposes.
64221167Sgnn */
65221167Sgnntypedef struct __hal_ring_rxd_priv_t {
66221167Sgnn	dma_addr_t		dma_addr;
67221167Sgnn	pci_dma_h		dma_handle;
68221167Sgnn	ptrdiff_t		dma_offset;
69221167Sgnn#if defined(VXGE_DEBUG_ASSERT)
70221167Sgnn	vxge_hal_mempool_dma_t	*dma_object;
71221167Sgnn#endif
72221167Sgnn#if defined(VXGE_OS_MEMORY_CHECK)
73221167Sgnn	u32			allocated;
74221167Sgnn#endif
75221167Sgnn	u32			db_bytes;
76221167Sgnn} __hal_ring_rxd_priv_t;
77221167Sgnn
78221167Sgnn
79221167Sgnn/*
80221167Sgnn * struct __hal_ring_t - Ring channel.
81221167Sgnn * @channel: Channel "base" of this ring, the common part of all HAL
82221167Sgnn *	channels.
83221167Sgnn * @mempool: Memory pool, the pool from which descriptors get allocated.
84221167Sgnn *	(See vxge_hal_mm.h).
85221167Sgnn * @config: Ring configuration, part of device configuration
86221167Sgnn *	(see vxge_hal_device_config_t {}).
87221167Sgnn * @ring_length: Length of the ring
88221167Sgnn * @buffer_mode: 1, 3, or 5. The value specifies a receive buffer mode,
89221167Sgnn *	as per X3100 User Guide.
90221167Sgnn * @indicate_max_pkts: Maximum number of packets processed within a single
91221167Sgnn *	interrupt. Can be used to limit the time spent inside hw interrupt.
92221167Sgnn * @rxd_size: RxD sizes for 1-, 3- or 5- buffer modes. As per X3100 spec,
93221167Sgnn *	1-buffer mode descriptor is 32 byte long, etc.
94221167Sgnn * @rxd_priv_size: Per RxD size reserved (by HAL) for ULD to keep per-descriptor
95221167Sgnn *		data (e.g., DMA handle for Solaris)
96221167Sgnn * @per_rxd_space: Per rxd space requested by ULD
97221167Sgnn * @rxds_per_block: Number of descriptors per hardware-defined RxD
98221167Sgnn *		block. Depends on the (1-, 3-, 5-) buffer mode.
99221167Sgnn * @rxdblock_priv_size: Reserved at the end of each RxD block. HAL internal
100221167Sgnn *			usage. Not to confuse with @rxd_priv_size.
101221167Sgnn * @rxd_mem_avail: Available RxD memory
102221167Sgnn * @db_byte_count: Number of doorbell bytes to be posted
103221167Sgnn * @cmpl_cnt: Completion counter. Is reset to zero upon entering the ISR.
104221167Sgnn *	Used in conjunction with @indicate_max_pkts.
105221167Sgnn * @active_sw_lros: List of Software LRO sessions in progess
106221167Sgnn * @active_sw_lro_count: Number of Software LRO sessions in progess
107221167Sgnn * @free_sw_lros: List of Software LRO sessions free
108221167Sgnn * @free_sw_lro_count: Number of Software LRO sessions free
109221167Sgnn * @sw_lro_lock: LRO session lists' lock
110221167Sgnn * @callback: Channel completion callback. HAL invokes the callback when there
111221167Sgnn *	    are new completions on that channel. In many implementations
112221167Sgnn *	    the @callback executes in the hw interrupt context.
113221167Sgnn * @rxd_init: Channel's descriptor-initialize callback.
114221167Sgnn *	    See vxge_hal_ring_rxd_init_f {}.
115221167Sgnn *	    If not NULL, HAL invokes the callback when opening the ring.
116221167Sgnn * @rxd_term: Channel's descriptor-terminate callback. If not NULL,
117221167Sgnn *	HAL invokes the callback when closing the corresponding channel.
118221167Sgnn *	See also vxge_hal_channel_rxd_term_f {}.
119221167Sgnn * @stats: Statistics for ring
120221167Sgnn * Ring channel.
121221167Sgnn *
122221167Sgnn * Note: The structure is cache line aligned to better utilize
123221167Sgnn *	   CPU cache performance.
124221167Sgnn */
125221167Sgnntypedef struct __hal_ring_t {
126221167Sgnn	__hal_channel_t				channel;
127221167Sgnn	vxge_hal_mempool_t			*mempool;
128221167Sgnn	vxge_hal_ring_config_t			*config;
129221167Sgnn	u32					ring_length;
130221167Sgnn	u32					buffer_mode;
131221167Sgnn	u32					indicate_max_pkts;
132221167Sgnn	u32					rxd_size;
133221167Sgnn	u32					rxd_priv_size;
134221167Sgnn	u32					per_rxd_space;
135221167Sgnn	u32					rxds_per_block;
136221167Sgnn	u32					rxdblock_priv_size;
137221167Sgnn	u32					rxd_mem_avail;
138221167Sgnn	u32					db_byte_count;
139221167Sgnn	u32					cmpl_cnt;
140221167Sgnn	vxge_hal_ring_callback_f		callback;
141221167Sgnn	vxge_hal_ring_rxd_init_f		rxd_init;
142221167Sgnn	vxge_hal_ring_rxd_term_f		rxd_term;
143221167Sgnn	vxge_hal_vpath_stats_sw_ring_info_t *stats;
144221167Sgnn} __vxge_os_attr_cacheline_aligned __hal_ring_t;
145221167Sgnn
146221167Sgnn#define	VXGE_HAL_RING_ULD_PRIV(ring, rxdh)				\
147221167Sgnn	ring->channel.dtr_arr[						\
148221167Sgnn	    ((vxge_hal_ring_rxd_5_t *)(rxdh))->host_control].uld_priv
149221167Sgnn
150221167Sgnn#define	VXGE_HAL_RING_HAL_PRIV(ring, rxdh)				\
151221167Sgnn	((__hal_ring_rxd_priv_t *)(ring->channel.dtr_arr[		\
152221167Sgnn	    ((vxge_hal_ring_rxd_5_t *)(rxdh))->host_control].hal_priv))
153221167Sgnn
154221167Sgnn#define	VXGE_HAL_RING_POST_DOORBELL(vph, ringh)				\
155221167Sgnn{									\
156221167Sgnn	if (((__hal_ring_t *)(ringh))->config->post_mode ==		\
157221167Sgnn	    VXGE_HAL_RING_POST_MODE_DOORBELL) {				\
158221167Sgnn		vxge_hal_ring_rxd_post_post_db(vph);			\
159221167Sgnn	}								\
160221167Sgnn}
161221167Sgnn
162221167Sgnn#define	VXGE_HAL_RING_RXD_INDEX(rxdp)	\
163221167Sgnn	(u32)((vxge_hal_ring_rxd_5_t *)rxdp)->host_control
164221167Sgnn
165221167Sgnn/* ========================== RING PRIVATE API ============================ */
166221167Sgnn
167221167Sgnnu64
168221167Sgnn__hal_ring_first_block_address_get(
169221167Sgnn    vxge_hal_ring_h ringh);
170221167Sgnn
171221167Sgnnvxge_hal_status_e
172221167Sgnn__hal_ring_create(
173221167Sgnn    vxge_hal_vpath_h vpath_handle,
174221167Sgnn    vxge_hal_ring_attr_t *attr);
175221167Sgnn
176221167Sgnnvoid
177221167Sgnn__hal_ring_abort(
178221167Sgnn    vxge_hal_ring_h ringh,
179221167Sgnn    vxge_hal_reopen_e reopen);
180221167Sgnn
181221167Sgnnvxge_hal_status_e
182221167Sgnn__hal_ring_reset(
183221167Sgnn    vxge_hal_ring_h ringh);
184221167Sgnn
185221167Sgnnvoid
186221167Sgnn__hal_ring_delete(
187221167Sgnn    vxge_hal_vpath_h vpath_handle);
188221167Sgnn
189221167Sgnnvxge_hal_status_e
190221167Sgnnvxge_hal_ring_initial_replenish(
191221167Sgnn    __hal_ring_t *ring,
192221167Sgnn    vxge_hal_reopen_e reopen);
193221167Sgnn
194221167Sgnnvxge_hal_status_e
195221167Sgnn__hal_ring_frame_length_set(
196221167Sgnn    __hal_virtualpath_t *vpath,
197221167Sgnn    u32 new_frmlen);
198221167Sgnn
199221167Sgnn__EXTERN_END_DECLS
200221167Sgnn
201221167Sgnn#endif	/* VXGE_HAL_RING_H */
202