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#ifndef	VXGE_HAL_CHANNEL_H
34#define	VXGE_HAL_CHANNEL_H
35
36__EXTERN_BEGIN_DECLS
37
38/*
39 * __hal_dtr_h - Handle to the desriptor object used for nonoffload
40 *		send or receive. Generic handle which can be with txd or rxd
41 */
42typedef void *__hal_dtr_h;
43
44/*
45 * enum __hal_channel_type_e - Enumerated channel types.
46 * @VXGE_HAL_CHANNEL_TYPE_UNKNOWN: Unknown channel.
47 * @VXGE_HAL_CHANNEL_TYPE_FIFO: fifo.
48 * @VXGE_HAL_CHANNEL_TYPE_RING: ring.
49 * @VXGE_HAL_CHANNEL_TYPE_SQ: Send Queue
50 * @VXGE_HAL_CHANNEL_TYPE_SRQ: Receive Queue
51 * @VXGE_HAL_CHANNEL_TYPE_CQRQ: Receive queue completion queue
52 * @VXGE_HAL_CHANNEL_TYPE_UMQ: Up message queue
53 * @VXGE_HAL_CHANNEL_TYPE_DMQ: Down message queue
54 * @VXGE_HAL_CHANNEL_TYPE_MAX: Maximum number of HAL-supported
55 * (and recognized) channel types. Currently: 7.
56 *
57 * Enumerated channel types. Currently there are only two link-layer
58 * channels - X3100 fifo and X3100 ring. In the future the list will grow.
59 */
60typedef enum __hal_channel_type_e {
61	VXGE_HAL_CHANNEL_TYPE_UNKNOWN			= 0,
62	VXGE_HAL_CHANNEL_TYPE_FIFO			= 1,
63	VXGE_HAL_CHANNEL_TYPE_RING			= 2,
64	VXGE_HAL_CHANNEL_TYPE_SEND_QUEUE		= 3,
65	VXGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE		= 4,
66	VXGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE		= 5,
67	VXGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE		= 6,
68	VXGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE	= 7,
69	VXGE_HAL_CHANNEL_TYPE_MAX			= 8
70} __hal_channel_type_e;
71
72/*
73 * __hal_dtr_item_t
74 * @dtr: Pointer to the descriptors that contains the dma data
75 *		to/from the device.
76 * @hal_priv: HAL Private data related to the dtr.
77 * @uld_priv: ULD Private data related to the dtr.
78 */
79typedef struct __hal_dtr_item_t {
80	void   *dtr;
81	void   *hal_priv;
82	void   *uld_priv;
83	u32	state;
84#define	VXGE_HAL_CHANNEL_DTR_FREE	0
85#define	VXGE_HAL_CHANNEL_DTR_RESERVED	1
86#define	VXGE_HAL_CHANNEL_DTR_POSTED	2
87#define	VXGE_HAL_CHANNEL_DTR_COMPLETED	3
88} __hal_dtr_item_t;
89
90/*
91 * __hal_channel_t
92 * @item: List item; used to maintain a list of open channels.
93 * @type: Channel type. See vxge_hal_channel_type_e {}.
94 * @devh: Device handle. HAL device object that contains _this_ channel.
95 * @pdev: PCI Device object
96 * @vph: Virtual path handle. Virtual Path Object that contains _this_ channel.
97 * @length: Channel length. Currently allocated number of descriptors.
98 *	The channel length "grows" when more descriptors get allocated.
99 *	See _hal_mempool_grow.
100 * @dtr_arr: Dtr array. Contains descriptors posted to the channel and their
101 *	private data.
102 *	Note that at any point in time @dtr_arr contains 3 types of
103 *	descriptors:
104 *	1) posted but not yet consumed by X3100 device;
105 *	2) consumed but not yet completed;
106 *	3) completed.
107 * @post_index: Post index. At any point in time points on the
108 *	position in the channel, which'll contain next to-be-posted
109 *	descriptor.
110 * @compl_index: Completion index. At any point in time points on the
111 *	position in the channel, which will contain next
112 *	to-be-completed descriptor.
113 * @reserve_index: Reserve index. At any point in time points on the
114 *	position in the channel, which will contain next
115 *	to-be-reserved descriptor.
116 * @free_dtr_count: Number of dtrs free.
117 * @posted_dtr_count: Number of dtrs posted
118 * @post_lock: Lock to serialize multiple concurrent "posters" of descriptors
119 *		on the given channel.
120 * @poll_bytes: Poll bytes.
121 * @per_dtr_space: Per-descriptor space (in bytes) that channel user can utilize
122 *		to store per-operation control information.
123 * @stats: Pointer to common statistics
124 * @userdata: Per-channel opaque (void *) user-defined context, which may be
125 *	upper-layer driver object, ULP connection, etc.
126 *	Once channel is open, @userdata is passed back to user via
127 *	vxge_hal_channel_callback_f.
128 *
129 * HAL channel object.
130 *
131 * See also: vxge_hal_channel_type_e {}, vxge_hal_channel_flag_e
132 */
133typedef struct __hal_channel_t {
134	vxge_list_t		item;
135	__hal_channel_type_e	type;
136	vxge_hal_device_h	devh;
137	pci_dev_h		pdev;
138	vxge_hal_vpath_h	vph;
139	u32			length;
140	u32			is_initd;
141	__hal_dtr_item_t	*dtr_arr;
142	u32			compl_index __vxge_os_attr_cacheline_aligned;
143	u32			reserve_index __vxge_os_attr_cacheline_aligned;
144	spinlock_t		post_lock;
145	u32			poll_bytes;
146	u32			per_dtr_space;
147	vxge_hal_vpath_stats_sw_common_info_t *stats;
148	void			*userdata;
149} __hal_channel_t __vxge_os_attr_cacheline_aligned;
150
151#define	__hal_channel_is_posted_dtr(channel, index) \
152	    ((channel)->dtr_arr[index].state == VXGE_HAL_CHANNEL_DTR_POSTED)
153
154#define	__hal_channel_for_each_posted_dtr(channel, dtrh, index) \
155	for (index = (channel)->compl_index,\
156	    dtrh = (channel)->dtr_arr[index].dtr; \
157	    (index < (channel)->reserve_index) && \
158	    ((channel)->dtr_arr[index].state == VXGE_HAL_CHANNEL_DTR_POSTED); \
159	    index = (++index == (channel)->length)? 0 : index, \
160	    dtrh = (channel)->dtr_arr[index].dtr)
161
162#define	__hal_channel_for_each_dtr(channel, dtrh, index) \
163	for (index = 0, dtrh = (channel)->dtr_arr[index].dtr; \
164	    index < (channel)->length; \
165	    dtrh = ((++index == (channel)->length)? 0 : \
166	    (channel)->dtr_arr[index].dtr))
167
168#define	__hal_channel_free_dtr_count(channel)			\
169	(((channel)->reserve_index < (channel)->compl_index) ?	\
170	((channel)->compl_index - (channel)->reserve_index) :	\
171	(((channel)->length - (channel)->reserve_index) + \
172	(channel)->reserve_index))
173
174/* ========================== CHANNEL PRIVATE API ========================= */
175
176__hal_channel_t *
177vxge_hal_channel_allocate(
178    vxge_hal_device_h devh,
179    vxge_hal_vpath_h vph,
180    __hal_channel_type_e type,
181    u32 length,
182    u32 per_dtr_space,
183    void *userdata);
184
185void
186vxge_hal_channel_free(
187    __hal_channel_t *channel);
188
189vxge_hal_status_e
190vxge_hal_channel_initialize(
191    __hal_channel_t *channel);
192
193vxge_hal_status_e
194__hal_channel_reset(
195    __hal_channel_t *channel);
196
197void
198vxge_hal_channel_terminate(
199    __hal_channel_t *channel);
200
201void
202__hal_channel_init_pending_list(
203    vxge_hal_device_h devh);
204
205void
206__hal_channel_insert_pending_list(
207    __hal_channel_t * channel);
208
209void
210__hal_channel_process_pending_list(
211    vxge_hal_device_h devhv);
212
213void
214__hal_channel_destroy_pending_list(
215    vxge_hal_device_h devh);
216
217#if defined(VXGE_DEBUG_FP) && (VXGE_DEBUG_FP & VXGE_DEBUG_FP_CHANNEL)
218#define	__HAL_STATIC_CHANNEL
219#define	__HAL_INLINE_CHANNEL
220#else	/* VXGE_FASTPATH_EXTERN */
221#define	__HAL_STATIC_CHANNEL static
222#define	__HAL_INLINE_CHANNEL inline
223#endif	/* VXGE_FASTPATH_INLINE */
224
225/* ========================== CHANNEL Fast Path API ========================= */
226/*
227 * __hal_channel_dtr_reserve- Reserve a dtr from the channel
228 * @channelh: Channel
229 * @dtrh: Buffer to return the DTR pointer
230 *
231 * Reserve a dtr from the reserve array.
232 *
233 */
234__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL vxge_hal_status_e
235/* LINTED */
236__hal_channel_dtr_reserve(__hal_channel_t *channel, __hal_dtr_h *dtrh)
237{
238	vxge_hal_status_e status = VXGE_HAL_INF_OUT_OF_DESCRIPTORS;
239
240	*dtrh = NULL;
241
242	if (channel->dtr_arr[channel->reserve_index].state ==
243	    VXGE_HAL_CHANNEL_DTR_FREE) {
244
245		*dtrh = channel->dtr_arr[channel->reserve_index].dtr;
246
247		channel->dtr_arr[channel->reserve_index].state =
248		    VXGE_HAL_CHANNEL_DTR_RESERVED;
249
250		if (++channel->reserve_index == channel->length)
251			channel->reserve_index = 0;
252
253		status = VXGE_HAL_OK;
254
255	} else {
256
257#if (VXGE_COMPONENT_HAL_CHANNEL & VXGE_DEBUG_MODULE_MASK)
258		__hal_device_t *hldev = (__hal_device_t *) channel->devh;
259
260		vxge_hal_info_log_channel("channel %d is full!", channel->type);
261#endif
262
263		channel->stats->full_cnt++;
264	}
265
266	return (status);
267}
268
269/*
270 * __hal_channel_dtr_restore - Restores a dtr to the channel
271 * @channelh: Channel
272 * @dtr: DTR pointer
273 *
274 * Returns a dtr back to reserve array.
275 *
276 */
277__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
278/* LINTED */
279__hal_channel_dtr_restore(__hal_channel_t *channel, __hal_dtr_h dtrh)
280{
281	u32 dtr_index;
282
283	/*
284	 * restore a previously allocated dtrh at current offset and update
285	 * the available reserve length accordingly. If dtrh is null just
286	 * update the reserve length, only
287	 */
288
289	if (channel->reserve_index == 0)
290		dtr_index = channel->length;
291	else
292		dtr_index = channel->reserve_index - 1;
293
294	if ((channel->dtr_arr[dtr_index].dtr = dtrh) != NULL) {
295
296		channel->reserve_index = dtr_index;
297		channel->dtr_arr[dtr_index].state = VXGE_HAL_CHANNEL_DTR_FREE;
298
299#if (VXGE_COMPONENT_HAL_CHANNEL & VXGE_DEBUG_MODULE_MASK)
300
301		__hal_device_t *hldev = (__hal_device_t *) channel->devh;
302		vxge_hal_info_log_channel("dtrh 0x"VXGE_OS_STXFMT" \
303		    restored for " "channel %d at reserve index %d, ",
304		    (ptr_t) dtrh, channel->type,
305		    channel->reserve_index);
306#endif
307	}
308}
309
310/*
311 * __hal_channel_dtr_post - Post a dtr to the channel
312 * @channelh: Channel
313 * @dtr: DTR pointer
314 *
315 * Posts a dtr to work array.
316 *
317 */
318__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
319/* LINTED */
320__hal_channel_dtr_post(__hal_channel_t *channel, u32 dtr_index)
321{
322	channel->dtr_arr[dtr_index].state =
323	    VXGE_HAL_CHANNEL_DTR_POSTED;
324}
325
326/*
327 * __hal_channel_dtr_try_complete - Returns next completed dtr
328 * @channelh: Channel
329 * @dtr: Buffer to return the next completed DTR pointer
330 *
331 * Returns the next completed dtr with out removing it from work array
332 *
333 */
334__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
335/* LINTED */
336__hal_channel_dtr_try_complete(__hal_channel_t *channel, __hal_dtr_h *dtrh)
337{
338	vxge_assert(channel->dtr_arr);
339	vxge_assert(channel->compl_index < channel->length);
340
341	if (channel->dtr_arr[channel->compl_index].state ==
342	    VXGE_HAL_CHANNEL_DTR_POSTED)
343		*dtrh = channel->dtr_arr[channel->compl_index].dtr;
344	else
345		*dtrh = NULL;
346}
347
348/*
349 * __hal_channel_dtr_complete - Removes next completed dtr from the work array
350 * @channelh: Channel
351 *
352 * Removes the next completed dtr from work array
353 *
354 */
355__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
356/* LINTED */
357__hal_channel_dtr_complete(__hal_channel_t *channel)
358{
359	channel->dtr_arr[channel->compl_index].state =
360	VXGE_HAL_CHANNEL_DTR_COMPLETED;
361
362	if (++channel->compl_index == channel->length)
363		channel->compl_index = 0;
364
365	channel->stats->total_compl_cnt++;
366}
367
368/*
369 * __hal_channel_dtr_free - Frees a dtr
370 * @channelh: Channel
371 * @index:  Index of DTR
372 *
373 * Returns the dtr to free array
374 *
375 */
376__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
377/* LINTED */
378__hal_channel_dtr_free(__hal_channel_t *channel, u32 dtr_index)
379{
380	channel->dtr_arr[dtr_index].state =
381	    VXGE_HAL_CHANNEL_DTR_FREE;
382}
383
384__EXTERN_END_DECLS
385
386#endif	/* VXGE_HAL_CHANNEL_H */
387