1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  *  Copyright (c) 2002-2005 Neterion, Inc.
24  *  All right Reserved.
25  *
26  *  FileName :    xgehal-channel.h
27  *
28  *  Description:  HAL channel object functionality
29  *
30  *  Created:      19 May 2004
31  */
32 
33 #ifndef XGE_HAL_CHANNEL_H
34 #define XGE_HAL_CHANNEL_H
35 
36 #include "xge-os-pal.h"
37 #include "xge-list.h"
38 #include "xgehal-types.h"
39 #include "xgehal-stats.h"
40 
41 /**
42  * enum xge_hal_channel_type_e - Enumerated channel types.
43  * @XGE_HAL_CHANNEL_TYPE_FIFO: fifo.
44  * @XGE_HAL_CHANNEL_TYPE_RING: ring.
45  * @XGE_HAL_CHANNEL_TYPE_MAX: Maximum number of HAL-supported
46  * (and recognized) channel types. Currently: two.
47  *
48  * Enumerated channel types. Currently there are only two link-layer
49  * channels - Xframe fifo and Xframe ring. In the future the list will grow.
50  */
51 typedef enum xge_hal_channel_type_e {
52 	XGE_HAL_CHANNEL_TYPE_FIFO,
53 	XGE_HAL_CHANNEL_TYPE_RING,
54 	XGE_HAL_CHANNEL_TYPE_MAX
55 } xge_hal_channel_type_e;
56 
57 /**
58  * enum xge_hal_channel_flag_e - Channel flags.
59  * @XGE_HAL_CHANNEL_FLAG_NONE: zero (nil) flag.
60  * @XGE_HAL_CHANNEL_FLAG_USE_TX_LOCK: use lock when posting transmit
61  * descriptor.
62  * @XGE_HAL_CHANNEL_FLAG_FREE_RXD: to-be-defined.
63  *
64  * Channel opening flags. Reserved for future usage.
65  */
66 typedef enum xge_hal_channel_flag_e {
67 	XGE_HAL_CHANNEL_FLAG_NONE		= 0x0,
68 	XGE_HAL_CHANNEL_FLAG_USE_TX_LOCK	= 0x1,
69 	XGE_HAL_CHANNEL_FLAG_FREE_RXD	        = 0x2
70 } xge_hal_channel_flag_e;
71 
72 /**
73  * enum xge_hal_dtr_state_e - Descriptor (DTR) state.
74  * @XGE_HAL_DTR_STATE_NONE: Invalid state.
75  * @XGE_HAL_DTR_STATE_AVAIL: Descriptor is available for reservation
76  * (via xge_hal_fifo_dtr_reserve(), xge_hal_ring_dtr_reserve(), etc.).
77  * @XGE_HAL_DTR_STATE_POSTED: Descriptor is posted for processing by the
78  * device.
79  * @XGE_HAL_DTR_STATE_FREED: Descriptor is free and can be reused for
80  * filling-in and posting later.
81  *
82  * Xframe/HAL descriptor states. For more on descriptor states and transitions
83  * please refer to ch_intern{}.
84  *
85  * See also: xge_hal_channel_dtr_term_f{}.
86  */
87 typedef enum xge_hal_dtr_state_e {
88 	XGE_HAL_DTR_STATE_NONE		= 0,
89 	XGE_HAL_DTR_STATE_AVAIL		= 1,
90 	XGE_HAL_DTR_STATE_POSTED	= 2,
91 	XGE_HAL_DTR_STATE_FREED		= 3
92 } xge_hal_dtr_state_e;
93 
94 /**
95  * enum xge_hal_channel_reopen_e - Channel open, close, or reopen option.
96  * @XGE_HAL_CHANNEL_RESET_ONLY: Do not (de)allocate channel; used with
97  * xge_hal_channel_open(), xge_hal_channel_close().
98  * @XGE_HAL_CHANNEL_OC_NORMAL: Do (de)allocate channel; used with
99  * xge_hal_channel_open(), xge_hal_channel_close().
100  *
101  * Enumerates options used with channel open and close operations.
102  * The @XGE_HAL_CHANNEL_RESET_ONLY can be used when resetting the device;
103  * in this case there is actually no need to free and then again malloc
104  * the memory (including DMA-able memory) used for channel operation.
105  */
106 typedef enum xge_hal_channel_reopen_e {
107 	XGE_HAL_CHANNEL_RESET_ONLY	= 1,
108 	XGE_HAL_CHANNEL_OC_NORMAL	= 2
109 } xge_hal_channel_reopen_e;
110 
111 /**
112  * function xge_hal_channel_callback_f - Channel callback.
113  * @channelh: Channel "containing" 1 or more completed descriptors.
114  * @dtrh: First completed descriptor.
115  * @t_code: Transfer code, as per Xframe User Guide.
116  *          Returned by HAL.
117  * @host_control: Opaque 64bit data stored by ULD inside the Xframe
118  *            descriptor prior to posting the latter on the channel
119  *            via xge_hal_fifo_dtr_post() or xge_hal_ring_dtr_post().
120  *            The @host_control is returned as is to the ULD with each
121  *            completed descriptor.
122  * @userdata: Opaque per-channel data specified at channel open
123  *            time, via xge_hal_channel_open().
124  *
125  * Channel completion callback (type declaration). A single per-channel
126  * callback is specified at channel open time, via
127  * xge_hal_channel_open().
128  * Typically gets called as part of the processing of the Interrupt
129  * Service Routine.
130  *
131  * Channel callback gets called by HAL if, and only if, there is at least
132  * one new completion on a given ring or fifo channel. Upon processing the
133  * first @dtrh ULD is _supposed_ to continue consuming completions
134  * using�one of the following HAL APIs:
135  *    - xge_hal_fifo_dtr_next_completed()
136  *      or
137  *    - xge_hal_ring_dtr_next_completed().
138  *
139  * Note that failure to process new completions in a timely fashion
140  * leads to XGE_HAL_INF_OUT_OF_DESCRIPTORS condition.
141  *
142  * Non-zero @t_code means failure to process (transmit or receive, depending
143  * on the channel type) the descriptor.
144  *
145  * In the "transmit" case the failure could happen, for instance, when the
146  * link is down, in which case Xframe completes the descriptor because it
147  * is not able to send the data out.
148  *
149  * For details please refer to Xframe User Guide.
150  *
151  * See also: xge_hal_fifo_dtr_next_completed(),
152  * xge_hal_ring_dtr_next_completed(), xge_hal_channel_dtr_term_f{}.
153  */
154 typedef xge_hal_status_e (*xge_hal_channel_callback_f)
155 				(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
156 				 u8 t_code, void *userdata);
157 
158 /**
159  * function xge_hal_channel_dtr_init_f - Initialize descriptor callback.
160  * @channelh: Channel "containing" the @dtrh descriptor.
161  * @dtrh: Descriptor.
162  * @index: Index of the descriptor in the channel's set of descriptors.
163  * @userdata: Per-channel user data (a.k.a. context) specified at
164  * channel open time, via xge_hal_channel_open().
165  * @reopen: See  xge_hal_channel_reopen_e{}.
166  *
167  * Initialize descriptor callback. Unless NULL is specified in the
168  * xge_hal_channel_attr_t{} structure passed to xge_hal_channel_open()),
169  * HAL invokes the callback as part of the xge_hal_channel_open()
170  * implementation.
171  * For the ring type of channel the ULD is expected to fill in this descriptor
172  * with buffer(s) and control information.
173  * For the fifo type of channel the ULD could use the callback to
174  * pre-set DMA mappings and/or alignment buffers.
175  *
176  * See also: xge_hal_channel_attr_t{}, xge_hal_channel_dtr_term_f{}.
177  */
178 typedef xge_hal_status_e (*xge_hal_channel_dtr_init_f)
179 				(xge_hal_channel_h channelh,
180 				 xge_hal_dtr_h dtrh,
181 				 int index,
182 				 void *userdata,
183 				 xge_hal_channel_reopen_e reopen);
184 
185 /**
186  * function xge_hal_channel_dtr_term_f - Terminate descriptor callback.
187  * @channelh: Channel "containing" the @dtrh descriptor.
188  * @dtrh: First completed descriptor.
189  * @state: One of the xge_hal_dtr_state_e{} enumerated states.
190  * @userdata: Per-channel user data (a.k.a. context) specified at
191  * channel open time, via xge_hal_channel_open().
192  * @reopen: See  xge_hal_channel_reopen_e{}.
193  *
194  * Terminate descriptor callback. Unless NULL is specified in the
195  * xge_hal_channel_attr_t{} structure passed to xge_hal_channel_open()),
196  * HAL invokes the callback as part of closing the corresponding
197  * channel, prior to de-allocating the channel and associated data
198  * structures (including descriptors).
199  * ULD should utilize the callback to (for instance) unmap
200  * and free DMA data buffers associated with the posted (state =
201  * XGE_HAL_DTR_STATE_POSTED) descriptors,
202  * as well as other relevant cleanup functions.
203  *
204  * See also: xge_hal_channel_attr_t{}, xge_hal_channel_dtr_init_f{}.
205  */
206 typedef void (*xge_hal_channel_dtr_term_f) (xge_hal_channel_h channelh,
207 					    xge_hal_dtr_h dtrh,
208 					    xge_hal_dtr_state_e	state,
209 					    void *userdata,
210 					    xge_hal_channel_reopen_e reopen);
211 
212 
213 /**
214  * struct xge_hal_channel_attr_t - Channel open "template".
215  * @type: xge_hal_channel_type_e channel type.
216  * @post_qid: Queue ID to post descriptors. For the link layer this
217  *            number should be in the 0..7 range.
218  * @compl_qid: Completion queue ID. Must be set to zero for the link layer.
219  * @callback: Channel completion callback. HAL invokes the callback when there
220  *            are new completions on that channel. In many implementations
221  *            the @callback executes in the hw interrupt context.
222  * @dtr_init: Channel's descriptor-initialize callback.
223  *            See xge_hal_channel_dtr_init_f{}.
224  *            If not NULL, HAL invokes the callback when opening
225  *            the channel via xge_hal_channel_open().
226  * @dtr_term: Channel's descriptor-terminate callback. If not NULL,
227  *          HAL invokes the callback when closing the corresponding channel.
228  *          See also xge_hal_channel_dtr_term_f{}.
229  * @userdata: User-defined "context" of _that_ channel. Passed back to the
230  *            user as one of the @callback, @dtr_init, and @dtr_term arguments.
231  * @per_dtr_space: If specified (i.e., greater than zero): extra space
232  *              reserved by HAL per each transmit or receive (depending on the
233  *              channel type) descriptor. Can be used to store,
234  *              and retrieve on completion, information specific
235  *              to the upper-layer.
236  * @flags: xge_hal_channel_flag_e enumerated flags.
237  *
238  * Channel open "template". User fills the structure with channel
239  * attributes and passes it to xge_hal_channel_open().
240  * Usage: See ex_open{}.
241  */
242 typedef struct xge_hal_channel_attr_t {
243 	xge_hal_channel_type_e		type;
244 	int				post_qid;
245 	int				compl_qid;
246 	xge_hal_channel_callback_f	callback;
247 	xge_hal_channel_dtr_init_f	dtr_init;
248 	xge_hal_channel_dtr_term_f	dtr_term;
249 	void				*userdata;
250 	int				per_dtr_space;
251 	xge_hal_channel_flag_e		flags;
252 } xge_hal_channel_attr_t;
253 
254 /*
255  * xge_hal_channel_t
256  * ---------- complete/free section ---------------
257  * @item: List item; used to maintain a list of open channels.
258  * @callback: Channel completion callback. See
259  * xge_hal_channel_callback_f.
260  * @compl_index: Completion index. At any point in time points on the
261  *               position in the channel, which will contain next
262  *               to-be-completed descriptor.
263  * @length: Channel length. Currently allocated number of descriptors.
264  *          The channel length "grows" when more descriptors get allocated.
265  *          See _hal_mempool_grow.
266  * @free_arr: Free array. Contains completed descriptors that were freed
267  *            (i.e., handed over back to HAL) by ULD.
268  *            See xge_hal_fifo_dtr_free(), xge_hal_ring_dtr_free().
269  * @free_lock: Lock to protect @free_arr.
270  * ----------- reserve/post section ---------------
271  * @post_index: Post index. At any point in time points on the
272  *              position in the channel, which'll contain next to-be-posted
273  *              descriptor.
274  * @post_lock: Lock to serialize multiple concurrent "posters" of descriptors
275  *             on the given channel.
276  * @reserve_arr: Reserve array. Contains descriptors that can be reserved
277  *               by ULD for the subsequent send or receive operation.
278  *               See xge_hal_fifo_dtr_reserve(),
279  *               xge_hal_ring_dtr_reserve().
280  * @reserve_length: Length of the @reserve_arr. The length dynamically
281  *                  changes: it decrements each time descriptor is reserved.
282  * @reserve_lock: Lock to serialize multiple concurrent threads accessing
283  *                @reserve_arr.
284  * @reserve_threshold: Reserve threshold. Minimal number of free descriptors
285  *                     that ought to be preserved in the channel at all times.
286  *                     Note that @reserve_threshold >= 0 &&
287  *                     @reserve_threshold < @reserve_max.
288  * ------------ common section --------------------
289  * @devh: Device handle. HAL device object that contains _this_ channel.
290  * @dmah: Channel's DMA address. Used to synchronize (to/from device)
291  *        descriptors.
292  * @regh0: Base address of the device memory space handle. Copied from HAL device
293  *         at channel open time.
294  * @regh1: Base address of the device memory space handle. Copied from HAL device
295  *         at channel open time.
296  * @userdata: Per-channel opaque (void*) user-defined context, which may be
297  *            upper-layer driver object, ULP connection, etc.
298  *            Once channel is open, @userdata is passed back to user via
299  *            xge_hal_channel_callback_f.
300  * @work_arr: Work array. Contains descriptors posted to the channel.
301  *            Note that at any point in time @work_arr contains 3 types of
302  *            descriptors:
303  *            1) posted but not yet consumed by Xframe device;
304  *            2) consumed but not yet completed;
305  *            3) completed but not yet freed
306  *            (via xge_hal_fifo_dtr_free() or xge_hal_ring_dtr_free())
307  * @saved_arr: Array used internally to optimize channel full-duplex
308  *             operation.
309  * @stats: Channel statistcis. Includes HAL internal counters, including
310  *         for instance, number of times out-of-descriptors
311  *         (see XGE_HAL_INF_OUT_OF_DESCRIPTORS) condition happened.
312  * ------------- "slow" section  ------------------
313  * @type: Channel type. See xge_hal_channel_type_e{}.
314  * @post_qid: Identifies Xframe queue used for posting descriptors.
315  * @compl_qid: Identifies Xframe completion queue.
316  * @flags: Channel flags. See xge_hal_channel_flag_e{}.
317  * @reserve_initial: Initial number of descriptors allocated at channel open
318  *                   time (see xge_hal_channel_open()). The number of
319  *                   channel descriptors can grow at runtime
320  *                   up to @reserve_max value.
321  * @reserve_max: Maximum number of channel descriptors. See @reserve_initial.
322  * @is_open: True, if channel is open; false - otherwise.
323  * @per_dtr_space: Per-descriptor space (in bytes) that channel user can utilize
324  *                 to store per-operation control information.
325  *
326  * HAL channel object. HAL devices (see xge_hal_device_t{}) contains
327  * zero or more channels. HAL channel contains zero or more descriptors. The
328  * latter are used by ULD(s) to manage the device and/or send and receive data
329  * to remote peer(s) via the channel.
330  *
331  * See also: xge_hal_channel_type_e{}, xge_hal_channel_flag_e,
332  * xge_hal_channel_callback_f{}
333  */
334 typedef struct {
335 	/* complete/free section */
336 	xge_list_t			item;
337 	xge_hal_channel_callback_f	callback;
338 	void				**free_arr;
339 	int				length;
340 	int				free_length;
341 	spinlock_t			free_lock;
342 	int				compl_index;
343 
344 	/* reserve/post data path section */
345 #ifdef __XGE_WIN__
346 	int				__xge_os_attr_cacheline_aligned
347 					post_index;
348 #else
349 	int				post_index
350 					__xge_os_attr_cacheline_aligned;
351 #endif
352 	spinlock_t			reserve_lock;
353 	spinlock_t			post_lock;
354 
355 	void				**reserve_arr;
356 	int				reserve_length;
357 	int				reserve_threshold;
358 	int				reserve_top;
359 	int                             unused1;
360 
361 	/* common section */
362 	xge_hal_device_h		devh;
363 	pci_dev_h                       pdev;
364 	pci_reg_h			regh0;
365 	pci_reg_h			regh1;
366 	void				*userdata;
367 	void				**work_arr;
368 	void				**saved_arr;
369 	void				**orig_arr;
370 	xge_hal_stats_channel_info_t	stats;
371 
372 	/* slow section */
373 	xge_hal_channel_type_e		type;
374 	int				post_qid;
375 	int				compl_qid;
376 	xge_hal_channel_flag_e		flags;
377 	int				reserve_initial;
378 	int				reserve_max;
379 	int				is_open;
380 	int				per_dtr_space;
381 	xge_hal_channel_dtr_term_f	dtr_term;
382 	xge_hal_channel_dtr_init_f	dtr_init;
383 	xge_hal_msix_vector_t		msix_vect;
384 #if defined(XGE_HAL_MSI)
385 	u32				msi_msg;
386 	u8				rti;
387 	u8				tti;
388 	u16                             unused2;
389 #endif
390 #if defined(XGE_HAL_MSI_X)
391 	u64				msix_address;
392 	u32				msix_data;
393 	int				msix_idx;
394 #endif
395         int				magic;
396 #ifdef __XGE_WIN__
397 } __xge_os_attr_cacheline_aligned xge_hal_channel_t ;
398 #else
399 } xge_hal_channel_t __xge_os_attr_cacheline_aligned;
400 #endif
401 
402 /* ========================== CHANNEL PRIVATE API ========================= */
403 
404 xge_hal_status_e
405 __hal_channel_initialize(xge_hal_channel_h channelh,
406 		xge_hal_channel_attr_t *attr, void **reserve_arr,
407 		int reserve_initial, int reserve_max, int reserve_threshold);
408 
409 void __hal_channel_terminate(xge_hal_channel_h channelh);
410 
411 xge_hal_channel_t*
412 __hal_channel_allocate(xge_hal_device_h devh, int post_qid,
413 		xge_hal_channel_type_e	type);
414 
415 void __hal_channel_free(xge_hal_channel_t *channel);
416 
417 void __hal_channel_xmsi_set(xge_hal_channel_h channelh);
418 
419 static inline int
420 __hal_channel_msix_idx(xge_hal_channel_h channelh)
421 {
422 	return ((xge_hal_channel_t*)channelh)->msix_vect.idx;
423 }
424 
425 int __hal_channel_dtr_count(xge_hal_channel_h channelh);
426 
427 #if defined(XGE_DEBUG_FP) && (XGE_DEBUG_FP & XGE_DEBUG_FP_CHANNEL)
428 #define __HAL_STATIC_CHANNEL
429 #define __HAL_INLINE_CHANNEL
430 
431 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
432 __hal_channel_dtr_alloc(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh);
433 
434 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
435 __hal_channel_dtr_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh);
436 
437 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
438 __hal_channel_dtr_try_complete(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh);
439 
440 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
441 __hal_channel_dtr_complete(xge_hal_channel_h channelh);
442 
443 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
444 __hal_channel_dtr_free(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh);
445 
446 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
447 __hal_channel_dtr_dealloc(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh);
448 
449 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
450 __hal_channel_dtr_restore(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
451 			  int offset);
452 
453 /* ========================== CHANNEL PUBLIC API ========================= */
454 
455 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void*
456 xge_hal_channel_userdata(xge_hal_channel_h channelh);
457 
458 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int
459 xge_hal_channel_id(xge_hal_channel_h channelh);
460 
461 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int
462 xge_hal_check_alignment(dma_addr_t dma_pointer, int size, int alignment,
463 		int copy_size);
464 
465 #else /* XGE_FASTPATH_EXTERN */
466 #define __HAL_STATIC_CHANNEL static
467 #define __HAL_INLINE_CHANNEL inline
468 #include "xgehal-channel-fp.c"
469 #endif /* XGE_FASTPATH_INLINE */
470 
471 xge_hal_status_e
472 xge_hal_channel_open(xge_hal_device_h hldev, xge_hal_channel_attr_t *attr,
473 		     xge_hal_channel_h *channel,
474 		     xge_hal_channel_reopen_e reopen);
475 
476 void xge_hal_channel_close(xge_hal_channel_h channelh,
477                            xge_hal_channel_reopen_e reopen);
478 
479 void xge_hal_channel_abort(xge_hal_channel_h channelh,
480                            xge_hal_channel_reopen_e reopen);
481 
482 #endif /* XGE_HAL_CHANNEL_H */
483