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_CHANNEL_H
34221167Sgnn#define	VXGE_HAL_CHANNEL_H
35221167Sgnn
36221167Sgnn__EXTERN_BEGIN_DECLS
37221167Sgnn
38221167Sgnn/*
39221167Sgnn * __hal_dtr_h - Handle to the desriptor object used for nonoffload
40221167Sgnn *		send or receive. Generic handle which can be with txd or rxd
41221167Sgnn */
42221167Sgnntypedef void *__hal_dtr_h;
43221167Sgnn
44221167Sgnn/*
45221167Sgnn * enum __hal_channel_type_e - Enumerated channel types.
46221167Sgnn * @VXGE_HAL_CHANNEL_TYPE_UNKNOWN: Unknown channel.
47221167Sgnn * @VXGE_HAL_CHANNEL_TYPE_FIFO: fifo.
48221167Sgnn * @VXGE_HAL_CHANNEL_TYPE_RING: ring.
49221167Sgnn * @VXGE_HAL_CHANNEL_TYPE_SQ: Send Queue
50221167Sgnn * @VXGE_HAL_CHANNEL_TYPE_SRQ: Receive Queue
51221167Sgnn * @VXGE_HAL_CHANNEL_TYPE_CQRQ: Receive queue completion queue
52221167Sgnn * @VXGE_HAL_CHANNEL_TYPE_UMQ: Up message queue
53221167Sgnn * @VXGE_HAL_CHANNEL_TYPE_DMQ: Down message queue
54221167Sgnn * @VXGE_HAL_CHANNEL_TYPE_MAX: Maximum number of HAL-supported
55221167Sgnn * (and recognized) channel types. Currently: 7.
56221167Sgnn *
57221167Sgnn * Enumerated channel types. Currently there are only two link-layer
58221167Sgnn * channels - X3100 fifo and X3100 ring. In the future the list will grow.
59221167Sgnn */
60221167Sgnntypedef enum __hal_channel_type_e {
61221167Sgnn	VXGE_HAL_CHANNEL_TYPE_UNKNOWN			= 0,
62221167Sgnn	VXGE_HAL_CHANNEL_TYPE_FIFO			= 1,
63221167Sgnn	VXGE_HAL_CHANNEL_TYPE_RING			= 2,
64221167Sgnn	VXGE_HAL_CHANNEL_TYPE_SEND_QUEUE		= 3,
65221167Sgnn	VXGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE		= 4,
66221167Sgnn	VXGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE		= 5,
67221167Sgnn	VXGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE		= 6,
68221167Sgnn	VXGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE	= 7,
69221167Sgnn	VXGE_HAL_CHANNEL_TYPE_MAX			= 8
70221167Sgnn} __hal_channel_type_e;
71221167Sgnn
72221167Sgnn/*
73221167Sgnn * __hal_dtr_item_t
74221167Sgnn * @dtr: Pointer to the descriptors that contains the dma data
75221167Sgnn *		to/from the device.
76221167Sgnn * @hal_priv: HAL Private data related to the dtr.
77221167Sgnn * @uld_priv: ULD Private data related to the dtr.
78221167Sgnn */
79221167Sgnntypedef struct __hal_dtr_item_t {
80221167Sgnn	void   *dtr;
81221167Sgnn	void   *hal_priv;
82221167Sgnn	void   *uld_priv;
83221167Sgnn	u32	state;
84221167Sgnn#define	VXGE_HAL_CHANNEL_DTR_FREE	0
85221167Sgnn#define	VXGE_HAL_CHANNEL_DTR_RESERVED	1
86221167Sgnn#define	VXGE_HAL_CHANNEL_DTR_POSTED	2
87221167Sgnn#define	VXGE_HAL_CHANNEL_DTR_COMPLETED	3
88221167Sgnn} __hal_dtr_item_t;
89221167Sgnn
90221167Sgnn/*
91221167Sgnn * __hal_channel_t
92221167Sgnn * @item: List item; used to maintain a list of open channels.
93221167Sgnn * @type: Channel type. See vxge_hal_channel_type_e {}.
94221167Sgnn * @devh: Device handle. HAL device object that contains _this_ channel.
95221167Sgnn * @pdev: PCI Device object
96221167Sgnn * @vph: Virtual path handle. Virtual Path Object that contains _this_ channel.
97221167Sgnn * @length: Channel length. Currently allocated number of descriptors.
98221167Sgnn *	The channel length "grows" when more descriptors get allocated.
99221167Sgnn *	See _hal_mempool_grow.
100221167Sgnn * @dtr_arr: Dtr array. Contains descriptors posted to the channel and their
101221167Sgnn *	private data.
102221167Sgnn *	Note that at any point in time @dtr_arr contains 3 types of
103221167Sgnn *	descriptors:
104221167Sgnn *	1) posted but not yet consumed by X3100 device;
105221167Sgnn *	2) consumed but not yet completed;
106221167Sgnn *	3) completed.
107221167Sgnn * @post_index: Post index. At any point in time points on the
108221167Sgnn *	position in the channel, which'll contain next to-be-posted
109221167Sgnn *	descriptor.
110221167Sgnn * @compl_index: Completion index. At any point in time points on the
111221167Sgnn *	position in the channel, which will contain next
112221167Sgnn *	to-be-completed descriptor.
113221167Sgnn * @reserve_index: Reserve index. At any point in time points on the
114221167Sgnn *	position in the channel, which will contain next
115221167Sgnn *	to-be-reserved descriptor.
116221167Sgnn * @free_dtr_count: Number of dtrs free.
117221167Sgnn * @posted_dtr_count: Number of dtrs posted
118221167Sgnn * @post_lock: Lock to serialize multiple concurrent "posters" of descriptors
119221167Sgnn *		on the given channel.
120221167Sgnn * @poll_bytes: Poll bytes.
121221167Sgnn * @per_dtr_space: Per-descriptor space (in bytes) that channel user can utilize
122221167Sgnn *		to store per-operation control information.
123221167Sgnn * @stats: Pointer to common statistics
124221167Sgnn * @userdata: Per-channel opaque (void *) user-defined context, which may be
125221167Sgnn *	upper-layer driver object, ULP connection, etc.
126221167Sgnn *	Once channel is open, @userdata is passed back to user via
127221167Sgnn *	vxge_hal_channel_callback_f.
128221167Sgnn *
129221167Sgnn * HAL channel object.
130221167Sgnn *
131221167Sgnn * See also: vxge_hal_channel_type_e {}, vxge_hal_channel_flag_e
132221167Sgnn */
133221167Sgnntypedef struct __hal_channel_t {
134221167Sgnn	vxge_list_t		item;
135221167Sgnn	__hal_channel_type_e	type;
136221167Sgnn	vxge_hal_device_h	devh;
137221167Sgnn	pci_dev_h		pdev;
138221167Sgnn	vxge_hal_vpath_h	vph;
139221167Sgnn	u32			length;
140221167Sgnn	u32			is_initd;
141221167Sgnn	__hal_dtr_item_t	*dtr_arr;
142221167Sgnn	u32			compl_index __vxge_os_attr_cacheline_aligned;
143221167Sgnn	u32			reserve_index __vxge_os_attr_cacheline_aligned;
144221167Sgnn	spinlock_t		post_lock;
145221167Sgnn	u32			poll_bytes;
146221167Sgnn	u32			per_dtr_space;
147221167Sgnn	vxge_hal_vpath_stats_sw_common_info_t *stats;
148221167Sgnn	void			*userdata;
149221167Sgnn} __hal_channel_t __vxge_os_attr_cacheline_aligned;
150221167Sgnn
151221167Sgnn#define	__hal_channel_is_posted_dtr(channel, index) \
152221167Sgnn	    ((channel)->dtr_arr[index].state == VXGE_HAL_CHANNEL_DTR_POSTED)
153221167Sgnn
154221167Sgnn#define	__hal_channel_for_each_posted_dtr(channel, dtrh, index) \
155221167Sgnn	for (index = (channel)->compl_index,\
156221167Sgnn	    dtrh = (channel)->dtr_arr[index].dtr; \
157221167Sgnn	    (index < (channel)->reserve_index) && \
158221167Sgnn	    ((channel)->dtr_arr[index].state == VXGE_HAL_CHANNEL_DTR_POSTED); \
159221167Sgnn	    index = (++index == (channel)->length)? 0 : index, \
160221167Sgnn	    dtrh = (channel)->dtr_arr[index].dtr)
161221167Sgnn
162221167Sgnn#define	__hal_channel_for_each_dtr(channel, dtrh, index) \
163221167Sgnn	for (index = 0, dtrh = (channel)->dtr_arr[index].dtr; \
164221167Sgnn	    index < (channel)->length; \
165221167Sgnn	    dtrh = ((++index == (channel)->length)? 0 : \
166221167Sgnn	    (channel)->dtr_arr[index].dtr))
167221167Sgnn
168221167Sgnn#define	__hal_channel_free_dtr_count(channel)			\
169221167Sgnn	(((channel)->reserve_index < (channel)->compl_index) ?	\
170221167Sgnn	((channel)->compl_index - (channel)->reserve_index) :	\
171221167Sgnn	(((channel)->length - (channel)->reserve_index) + \
172221167Sgnn	(channel)->reserve_index))
173221167Sgnn
174221167Sgnn/* ========================== CHANNEL PRIVATE API ========================= */
175221167Sgnn
176221167Sgnn__hal_channel_t *
177221167Sgnnvxge_hal_channel_allocate(
178221167Sgnn    vxge_hal_device_h devh,
179221167Sgnn    vxge_hal_vpath_h vph,
180221167Sgnn    __hal_channel_type_e type,
181221167Sgnn    u32 length,
182221167Sgnn    u32 per_dtr_space,
183221167Sgnn    void *userdata);
184221167Sgnn
185221167Sgnnvoid
186221167Sgnnvxge_hal_channel_free(
187221167Sgnn    __hal_channel_t *channel);
188221167Sgnn
189221167Sgnnvxge_hal_status_e
190221167Sgnnvxge_hal_channel_initialize(
191221167Sgnn    __hal_channel_t *channel);
192221167Sgnn
193221167Sgnnvxge_hal_status_e
194221167Sgnn__hal_channel_reset(
195221167Sgnn    __hal_channel_t *channel);
196221167Sgnn
197221167Sgnnvoid
198221167Sgnnvxge_hal_channel_terminate(
199221167Sgnn    __hal_channel_t *channel);
200221167Sgnn
201221167Sgnnvoid
202221167Sgnn__hal_channel_init_pending_list(
203221167Sgnn    vxge_hal_device_h devh);
204221167Sgnn
205221167Sgnnvoid
206221167Sgnn__hal_channel_insert_pending_list(
207221167Sgnn    __hal_channel_t * channel);
208221167Sgnn
209221167Sgnnvoid
210221167Sgnn__hal_channel_process_pending_list(
211221167Sgnn    vxge_hal_device_h devhv);
212221167Sgnn
213221167Sgnnvoid
214221167Sgnn__hal_channel_destroy_pending_list(
215221167Sgnn    vxge_hal_device_h devh);
216221167Sgnn
217221167Sgnn#if defined(VXGE_DEBUG_FP) && (VXGE_DEBUG_FP & VXGE_DEBUG_FP_CHANNEL)
218221167Sgnn#define	__HAL_STATIC_CHANNEL
219221167Sgnn#define	__HAL_INLINE_CHANNEL
220221167Sgnn#else	/* VXGE_FASTPATH_EXTERN */
221221167Sgnn#define	__HAL_STATIC_CHANNEL static
222221167Sgnn#define	__HAL_INLINE_CHANNEL inline
223221167Sgnn#endif	/* VXGE_FASTPATH_INLINE */
224221167Sgnn
225221167Sgnn/* ========================== CHANNEL Fast Path API ========================= */
226221167Sgnn/*
227221167Sgnn * __hal_channel_dtr_reserve- Reserve a dtr from the channel
228221167Sgnn * @channelh: Channel
229221167Sgnn * @dtrh: Buffer to return the DTR pointer
230221167Sgnn *
231221167Sgnn * Reserve a dtr from the reserve array.
232221167Sgnn *
233221167Sgnn */
234221167Sgnn__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL vxge_hal_status_e
235221167Sgnn/* LINTED */
236221167Sgnn__hal_channel_dtr_reserve(__hal_channel_t *channel, __hal_dtr_h *dtrh)
237221167Sgnn{
238221167Sgnn	vxge_hal_status_e status = VXGE_HAL_INF_OUT_OF_DESCRIPTORS;
239221167Sgnn
240221167Sgnn	*dtrh = NULL;
241221167Sgnn
242221167Sgnn	if (channel->dtr_arr[channel->reserve_index].state ==
243221167Sgnn	    VXGE_HAL_CHANNEL_DTR_FREE) {
244221167Sgnn
245221167Sgnn		*dtrh = channel->dtr_arr[channel->reserve_index].dtr;
246221167Sgnn
247221167Sgnn		channel->dtr_arr[channel->reserve_index].state =
248221167Sgnn		    VXGE_HAL_CHANNEL_DTR_RESERVED;
249221167Sgnn
250221167Sgnn		if (++channel->reserve_index == channel->length)
251221167Sgnn			channel->reserve_index = 0;
252221167Sgnn
253221167Sgnn		status = VXGE_HAL_OK;
254221167Sgnn
255221167Sgnn	} else {
256221167Sgnn
257221167Sgnn#if (VXGE_COMPONENT_HAL_CHANNEL & VXGE_DEBUG_MODULE_MASK)
258221167Sgnn		__hal_device_t *hldev = (__hal_device_t *) channel->devh;
259221167Sgnn
260221167Sgnn		vxge_hal_info_log_channel("channel %d is full!", channel->type);
261221167Sgnn#endif
262221167Sgnn
263221167Sgnn		channel->stats->full_cnt++;
264221167Sgnn	}
265221167Sgnn
266221167Sgnn	return (status);
267221167Sgnn}
268221167Sgnn
269221167Sgnn/*
270221167Sgnn * __hal_channel_dtr_restore - Restores a dtr to the channel
271221167Sgnn * @channelh: Channel
272221167Sgnn * @dtr: DTR pointer
273221167Sgnn *
274221167Sgnn * Returns a dtr back to reserve array.
275221167Sgnn *
276221167Sgnn */
277221167Sgnn__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
278221167Sgnn/* LINTED */
279221167Sgnn__hal_channel_dtr_restore(__hal_channel_t *channel, __hal_dtr_h dtrh)
280221167Sgnn{
281221167Sgnn	u32 dtr_index;
282221167Sgnn
283221167Sgnn	/*
284221167Sgnn	 * restore a previously allocated dtrh at current offset and update
285221167Sgnn	 * the available reserve length accordingly. If dtrh is null just
286221167Sgnn	 * update the reserve length, only
287221167Sgnn	 */
288221167Sgnn
289221167Sgnn	if (channel->reserve_index == 0)
290221167Sgnn		dtr_index = channel->length;
291221167Sgnn	else
292221167Sgnn		dtr_index = channel->reserve_index - 1;
293221167Sgnn
294236377Seadler	if ((channel->dtr_arr[dtr_index].dtr = dtrh) != NULL) {
295221167Sgnn
296221167Sgnn		channel->reserve_index = dtr_index;
297221167Sgnn		channel->dtr_arr[dtr_index].state = VXGE_HAL_CHANNEL_DTR_FREE;
298221167Sgnn
299221167Sgnn#if (VXGE_COMPONENT_HAL_CHANNEL & VXGE_DEBUG_MODULE_MASK)
300221167Sgnn
301221167Sgnn		__hal_device_t *hldev = (__hal_device_t *) channel->devh;
302221167Sgnn		vxge_hal_info_log_channel("dtrh 0x"VXGE_OS_STXFMT" \
303221167Sgnn		    restored for " "channel %d at reserve index %d, ",
304221167Sgnn		    (ptr_t) dtrh, channel->type,
305221167Sgnn		    channel->reserve_index);
306221167Sgnn#endif
307221167Sgnn	}
308221167Sgnn}
309221167Sgnn
310221167Sgnn/*
311221167Sgnn * __hal_channel_dtr_post - Post a dtr to the channel
312221167Sgnn * @channelh: Channel
313221167Sgnn * @dtr: DTR pointer
314221167Sgnn *
315221167Sgnn * Posts a dtr to work array.
316221167Sgnn *
317221167Sgnn */
318221167Sgnn__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
319221167Sgnn/* LINTED */
320221167Sgnn__hal_channel_dtr_post(__hal_channel_t *channel, u32 dtr_index)
321221167Sgnn{
322221167Sgnn	channel->dtr_arr[dtr_index].state =
323221167Sgnn	    VXGE_HAL_CHANNEL_DTR_POSTED;
324221167Sgnn}
325221167Sgnn
326221167Sgnn/*
327221167Sgnn * __hal_channel_dtr_try_complete - Returns next completed dtr
328221167Sgnn * @channelh: Channel
329221167Sgnn * @dtr: Buffer to return the next completed DTR pointer
330221167Sgnn *
331221167Sgnn * Returns the next completed dtr with out removing it from work array
332221167Sgnn *
333221167Sgnn */
334221167Sgnn__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
335221167Sgnn/* LINTED */
336221167Sgnn__hal_channel_dtr_try_complete(__hal_channel_t *channel, __hal_dtr_h *dtrh)
337221167Sgnn{
338221167Sgnn	vxge_assert(channel->dtr_arr);
339221167Sgnn	vxge_assert(channel->compl_index < channel->length);
340221167Sgnn
341221167Sgnn	if (channel->dtr_arr[channel->compl_index].state ==
342221167Sgnn	    VXGE_HAL_CHANNEL_DTR_POSTED)
343221167Sgnn		*dtrh = channel->dtr_arr[channel->compl_index].dtr;
344221167Sgnn	else
345221167Sgnn		*dtrh = NULL;
346221167Sgnn}
347221167Sgnn
348221167Sgnn/*
349221167Sgnn * __hal_channel_dtr_complete - Removes next completed dtr from the work array
350221167Sgnn * @channelh: Channel
351221167Sgnn *
352221167Sgnn * Removes the next completed dtr from work array
353221167Sgnn *
354221167Sgnn */
355221167Sgnn__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
356221167Sgnn/* LINTED */
357221167Sgnn__hal_channel_dtr_complete(__hal_channel_t *channel)
358221167Sgnn{
359221167Sgnn	channel->dtr_arr[channel->compl_index].state =
360221167Sgnn	VXGE_HAL_CHANNEL_DTR_COMPLETED;
361221167Sgnn
362221167Sgnn	if (++channel->compl_index == channel->length)
363221167Sgnn		channel->compl_index = 0;
364221167Sgnn
365221167Sgnn	channel->stats->total_compl_cnt++;
366221167Sgnn}
367221167Sgnn
368221167Sgnn/*
369221167Sgnn * __hal_channel_dtr_free - Frees a dtr
370221167Sgnn * @channelh: Channel
371221167Sgnn * @index:  Index of DTR
372221167Sgnn *
373221167Sgnn * Returns the dtr to free array
374221167Sgnn *
375221167Sgnn */
376221167Sgnn__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
377221167Sgnn/* LINTED */
378221167Sgnn__hal_channel_dtr_free(__hal_channel_t *channel, u32 dtr_index)
379221167Sgnn{
380221167Sgnn	channel->dtr_arr[dtr_index].state =
381221167Sgnn	    VXGE_HAL_CHANNEL_DTR_FREE;
382221167Sgnn}
383221167Sgnn
384221167Sgnn__EXTERN_END_DECLS
385221167Sgnn
386221167Sgnn#endif	/* VXGE_HAL_CHANNEL_H */
387