/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * Copyright (c) 2002-2006 Neterion, Inc. */ #ifndef XGE_HAL_CHANNEL_H #define XGE_HAL_CHANNEL_H #include "xge-os-pal.h" #include "xge-list.h" #include "xgehal-types.h" #include "xgehal-stats.h" __EXTERN_BEGIN_DECLS /** * enum xge_hal_channel_type_e - Enumerated channel types. * @XGE_HAL_CHANNEL_TYPE_FIFO: fifo. * @XGE_HAL_CHANNEL_TYPE_RING: ring. * @XGE_HAL_CHANNEL_TYPE_SEND_QUEUE: TBD. * @XGE_HAL_CHANNEL_TYPE_HW_RECEIVE_QUEUE: TBD. * @XGE_HAL_CHANNEL_TYPE_HW_COMPLETION_QUEUE: TBD. * @XGE_HAL_CHANNEL_TYPE_LRO_RECEIVE_QUEUE: TBD. * @XGE_HAL_CHANNEL_TYPE_LRO_COMPLETION_QUEUE: TBD. * @XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE: TBD. * @XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE: TBD. * @XGE_HAL_CHANNEL_TYPE_MAX: Maximum number of HAL-supported * (and recognized) channel types. Currently: two. * * Enumerated channel types. Currently there are only two link-layer * channels - Xframe fifo and Xframe ring. In the future the list will grow. */ typedef enum xge_hal_channel_type_e { XGE_HAL_CHANNEL_TYPE_FIFO, XGE_HAL_CHANNEL_TYPE_RING, XGE_HAL_CHANNEL_TYPE_SEND_QUEUE, XGE_HAL_CHANNEL_TYPE_HW_RECEIVE_QUEUE, XGE_HAL_CHANNEL_TYPE_HW_COMPLETION_QUEUE, XGE_HAL_CHANNEL_TYPE_LRO_RECEIVE_QUEUE, XGE_HAL_CHANNEL_TYPE_LRO_COMPLETION_QUEUE, XGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE, XGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE, XGE_HAL_CHANNEL_TYPE_MAX } xge_hal_channel_type_e; /** * enum xge_hal_channel_flag_e - Channel flags. * @XGE_HAL_CHANNEL_FLAG_NONE: zero (nil) flag. * @XGE_HAL_CHANNEL_FLAG_USE_TX_LOCK: use lock when posting transmit * descriptor. * @XGE_HAL_CHANNEL_FLAG_FREE_RXD: to-be-defined. * * Channel opening flags. Reserved for future usage. */ typedef enum xge_hal_channel_flag_e { XGE_HAL_CHANNEL_FLAG_NONE = 0x0, XGE_HAL_CHANNEL_FLAG_USE_TX_LOCK = 0x1, XGE_HAL_CHANNEL_FLAG_FREE_RXD = 0x2 } xge_hal_channel_flag_e; /** * enum xge_hal_dtr_state_e - Descriptor (DTR) state. * @XGE_HAL_DTR_STATE_NONE: Invalid state. * @XGE_HAL_DTR_STATE_AVAIL: Descriptor is available for reservation * (via xge_hal_fifo_dtr_reserve(), xge_hal_ring_dtr_reserve(), etc.). * @XGE_HAL_DTR_STATE_POSTED: Descriptor is posted for processing by the * device. * @XGE_HAL_DTR_STATE_FREED: Descriptor is free and can be reused for * filling-in and posting later. * * Xframe/HAL descriptor states. For more on descriptor states and transitions * please refer to ch_intern{}. * * See also: xge_hal_channel_dtr_term_f{}. */ typedef enum xge_hal_dtr_state_e { XGE_HAL_DTR_STATE_NONE = 0, XGE_HAL_DTR_STATE_AVAIL = 1, XGE_HAL_DTR_STATE_POSTED = 2, XGE_HAL_DTR_STATE_FREED = 3 } xge_hal_dtr_state_e; /** * enum xge_hal_channel_reopen_e - Channel open, close, or reopen option. * @XGE_HAL_CHANNEL_RESET_ONLY: Do not (de)allocate channel; used with * xge_hal_channel_open(), xge_hal_channel_close(). * @XGE_HAL_CHANNEL_OC_NORMAL: Do (de)allocate channel; used with * xge_hal_channel_open(), xge_hal_channel_close(). * * Enumerates options used with channel open and close operations. * The @XGE_HAL_CHANNEL_RESET_ONLY can be used when resetting the device; * in this case there is actually no need to free and then again malloc * the memory (including DMA-able memory) used for channel operation. */ typedef enum xge_hal_channel_reopen_e { XGE_HAL_CHANNEL_RESET_ONLY = 1, XGE_HAL_CHANNEL_OC_NORMAL = 2 } xge_hal_channel_reopen_e; /** * function xge_hal_channel_callback_f - Channel callback. * @channelh: Channel "containing" 1 or more completed descriptors. * @dtrh: First completed descriptor. * @t_code: Transfer code, as per Xframe User Guide. * Returned by HAL. * @host_control: Opaque 64bit data stored by ULD inside the Xframe * descriptor prior to posting the latter on the channel * via xge_hal_fifo_dtr_post() or xge_hal_ring_dtr_post(). * The @host_control is returned as is to the ULD with each * completed descriptor. * @userdata: Opaque per-channel data specified at channel open * time, via xge_hal_channel_open(). * * Channel completion callback (type declaration). A single per-channel * callback is specified at channel open time, via * xge_hal_channel_open(). * Typically gets called as part of the processing of the Interrupt * Service Routine. * * Channel callback gets called by HAL if, and only if, there is at least * one new completion on a given ring or fifo channel. Upon processing the * first @dtrh ULD is _supposed_ to continue consuming completions * usingáone of the following HAL APIs: * - xge_hal_fifo_dtr_next_completed() * or * - xge_hal_ring_dtr_next_completed(). * * Note that failure to process new completions in a timely fashion * leads to XGE_HAL_INF_OUT_OF_DESCRIPTORS condition. * * Non-zero @t_code means failure to process (transmit or receive, depending * on the channel type) the descriptor. * * In the "transmit" case the failure could happen, for instance, when the * link is down, in which case Xframe completes the descriptor because it * is not able to send the data out. * * For details please refer to Xframe User Guide. * * See also: xge_hal_fifo_dtr_next_completed(), * xge_hal_ring_dtr_next_completed(), xge_hal_channel_dtr_term_f{}. */ typedef xge_hal_status_e (*xge_hal_channel_callback_f) (xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, u8 t_code, void *userdata); /** * function xge_hal_channel_dtr_init_f - Initialize descriptor callback. * @channelh: Channel "containing" the @dtrh descriptor. * @dtrh: Descriptor. * @index: Index of the descriptor in the channel's set of descriptors. * @userdata: Per-channel user data (a.k.a. context) specified at * channel open time, via xge_hal_channel_open(). * @reopen: See xge_hal_channel_reopen_e{}. * * Initialize descriptor callback. Unless NULL is specified in the * xge_hal_channel_attr_t{} structure passed to xge_hal_channel_open()), * HAL invokes the callback as part of the xge_hal_channel_open() * implementation. * For the ring type of channel the ULD is expected to fill in this descriptor * with buffer(s) and control information. * For the fifo type of channel the ULD could use the callback to * pre-set DMA mappings and/or alignment buffers. * * See also: xge_hal_channel_attr_t{}, xge_hal_channel_dtr_term_f{}. */ typedef xge_hal_status_e (*xge_hal_channel_dtr_init_f) (xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, int index, void *userdata, xge_hal_channel_reopen_e reopen); /** * function xge_hal_channel_dtr_term_f - Terminate descriptor callback. * @channelh: Channel "containing" the @dtrh descriptor. * @dtrh: First completed descriptor. * @state: One of the xge_hal_dtr_state_e{} enumerated states. * @userdata: Per-channel user data (a.k.a. context) specified at * channel open time, via xge_hal_channel_open(). * @reopen: See xge_hal_channel_reopen_e{}. * * Terminate descriptor callback. Unless NULL is specified in the * xge_hal_channel_attr_t{} structure passed to xge_hal_channel_open()), * HAL invokes the callback as part of closing the corresponding * channel, prior to de-allocating the channel and associated data * structures (including descriptors). * ULD should utilize the callback to (for instance) unmap * and free DMA data buffers associated with the posted (state = * XGE_HAL_DTR_STATE_POSTED) descriptors, * as well as other relevant cleanup functions. * * See also: xge_hal_channel_attr_t{}, xge_hal_channel_dtr_init_f{}. */ typedef void (*xge_hal_channel_dtr_term_f) (xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, xge_hal_dtr_state_e state, void *userdata, xge_hal_channel_reopen_e reopen); /** * struct xge_hal_channel_attr_t - Channel open "template". * @type: xge_hal_channel_type_e channel type. * @post_qid: Queue ID to post descriptors. For the link layer this * number should be in the 0..7 range. * @compl_qid: Completion queue ID. Must be set to zero for the link layer. * @callback: Channel completion callback. HAL invokes the callback when there * are new completions on that channel. In many implementations * the @callback executes in the hw interrupt context. * @dtr_init: Channel's descriptor-initialize callback. * See xge_hal_channel_dtr_init_f{}. * If not NULL, HAL invokes the callback when opening * the channel via xge_hal_channel_open(). * @dtr_term: Channel's descriptor-terminate callback. If not NULL, * HAL invokes the callback when closing the corresponding channel. * See also xge_hal_channel_dtr_term_f{}. * @userdata: User-defined "context" of _that_ channel. Passed back to the * user as one of the @callback, @dtr_init, and @dtr_term arguments. * @sq_config: Send queue config * @hrq_config: HW receive queue config * @hcq_config: HW completion queue config * @lrq_config: LRO receive queue config * @lcq_config: LRO completion queue config * @dmq_config: Down Message queue config * @umq_config: Up Message queue config * * @per_dtr_space: If specified (i.e., greater than zero): extra space * reserved by HAL per each transmit or receive (depending on the * channel type) descriptor. Can be used to store, * and retrieve on completion, information specific * to the upper-layer. * @flags: xge_hal_channel_flag_e enumerated flags. * * Channel open "template". User fills the structure with channel * attributes and passes it to xge_hal_channel_open(). * Usage: See ex_open{}. */ typedef struct xge_hal_channel_attr_t { xge_hal_channel_type_e type; int post_qid; int compl_qid; xge_hal_channel_callback_f callback; xge_hal_channel_dtr_init_f dtr_init; xge_hal_channel_dtr_term_f dtr_term; void *userdata; int per_dtr_space; xge_hal_channel_flag_e flags; } xge_hal_channel_attr_t; /* * xge_hal_channel_t * ---------- complete/free section --------------- * @item: List item; used to maintain a list of open channels. * @callback: Channel completion callback. See * xge_hal_channel_callback_f. * @compl_index: Completion index. At any point in time points on the * position in the channel, which will contain next * to-be-completed descriptor. * @length: Channel length. Currently allocated number of descriptors. * The channel length "grows" when more descriptors get allocated. * See _hal_mempool_grow. * @free_arr: Free array. Contains completed descriptors that were freed * (i.e., handed over back to HAL) by ULD. * See xge_hal_fifo_dtr_free(), xge_hal_ring_dtr_free(). * @free_lock: Lock to protect @free_arr. * ----------- reserve/post section --------------- * @post_index: Post index. At any point in time points on the * position in the channel, which'll contain next to-be-posted * descriptor. * @post_lock: Lock to serialize multiple concurrent "posters" of descriptors * on the given channel. * @reserve_arr: Reserve array. Contains descriptors that can be reserved * by ULD for the subsequent send or receive operation. * See xge_hal_fifo_dtr_reserve(), * xge_hal_ring_dtr_reserve(). * @reserve_length: Length of the @reserve_arr. The length dynamically * changes: it decrements each time descriptor is reserved. * @reserve_lock: Lock to serialize multiple concurrent threads accessing * @reserve_arr. * @reserve_threshold: Reserve threshold. Minimal number of free descriptors * that ought to be preserved in the channel at all times. * Note that @reserve_threshold >= 0 && * @reserve_threshold < @reserve_max. * ------------ common section -------------------- * @devh: Device handle. HAL device object that contains _this_ channel. * @dmah: Channel's DMA address. Used to synchronize (to/from device) * descriptors. * @regh0: Base address of the device memory space handle. Copied from HAL device * at channel open time. * @regh1: Base address of the device memory space handle. Copied from HAL device * at channel open time. * @userdata: Per-channel opaque (void*) user-defined context, which may be * upper-layer driver object, ULP connection, etc. * Once channel is open, @userdata is passed back to user via * xge_hal_channel_callback_f. * @work_arr: Work array. Contains descriptors posted to the channel. * Note that at any point in time @work_arr contains 3 types of * descriptors: * 1) posted but not yet consumed by Xframe device; * 2) consumed but not yet completed; * 3) completed but not yet freed * (via xge_hal_fifo_dtr_free() or xge_hal_ring_dtr_free()) * @saved_arr: Array used internally to optimize channel full-duplex * operation. * @stats: Channel statistcis. Includes HAL internal counters, including * for instance, number of times out-of-descriptors * (see XGE_HAL_INF_OUT_OF_DESCRIPTORS) condition happened. * ------------- "slow" section ------------------ * @type: Channel type. See xge_hal_channel_type_e{}. * @post_qid: Identifies Xframe queue used for posting descriptors. * @compl_qid: Identifies Xframe completion queue. * @flags: Channel flags. See xge_hal_channel_flag_e{}. * @reserve_initial: Initial number of descriptors allocated at channel open * time (see xge_hal_channel_open()). The number of * channel descriptors can grow at runtime * up to @reserve_max value. * @reserve_max: Maximum number of channel descriptors. See @reserve_initial. * @is_open: True, if channel is open; false - otherwise. * @per_dtr_space: Per-descriptor space (in bytes) that channel user can utilize * to store per-operation control information. * HAL channel object. HAL devices (see xge_hal_device_t{}) contains * zero or more channels. HAL channel contains zero or more descriptors. The * latter are used by ULD(s) to manage the device and/or send and receive data * to remote peer(s) via the channel. * * See also: xge_hal_channel_type_e{}, xge_hal_channel_flag_e, * xge_hal_channel_callback_f{} */ typedef struct { /* complete/free section */ xge_list_t item; xge_hal_channel_callback_f callback; void **free_arr; int length; int free_length; #if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ) || \ defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE) spinlock_t free_lock; #endif int compl_index; unsigned int usage_cnt; unsigned int poll_bytes; int unused0; /* reserve/post data path section */ #ifdef __XGE_WIN__ int __xge_os_attr_cacheline_aligned post_index; #else int post_index __xge_os_attr_cacheline_aligned; #endif spinlock_t reserve_lock; spinlock_t post_lock; void **reserve_arr; int reserve_length; int reserve_threshold; int reserve_top; int unused1; /* common section */ xge_hal_device_h devh; pci_dev_h pdev; pci_reg_h regh0; pci_reg_h regh1; void *userdata; void **work_arr; void **saved_arr; void **orig_arr; xge_hal_stats_channel_info_t stats; /* slow section */ xge_hal_channel_type_e type; int post_qid; int compl_qid; xge_hal_channel_flag_e flags; int reserve_initial; int reserve_max; int is_open; int per_dtr_space; xge_hal_channel_dtr_term_f dtr_term; xge_hal_channel_dtr_init_f dtr_init; xge_hal_msix_vector_t msix_vect; #if defined(XGE_HAL_MSI) u32 msi_msg; u8 rti; u8 tti; u16 unused2; #endif #if defined(XGE_HAL_MSI_X) u64 msix_address; u32 msix_data; int msix_idx; #endif unsigned int magic; #ifdef __XGE_WIN__ } __xge_os_attr_cacheline_aligned xge_hal_channel_t ; #else } xge_hal_channel_t __xge_os_attr_cacheline_aligned; #endif /* ========================== CHANNEL PRIVATE API ========================= */ xge_hal_status_e __hal_channel_initialize(xge_hal_channel_h channelh, xge_hal_channel_attr_t *attr, void **reserve_arr, int reserve_initial, int reserve_max, int reserve_threshold); void __hal_channel_terminate(xge_hal_channel_h channelh); xge_hal_channel_t* __hal_channel_allocate(xge_hal_device_h devh, int post_qid, xge_hal_channel_type_e type); void __hal_channel_free(xge_hal_channel_t *channel); void __hal_channel_xmsi_set(xge_hal_channel_h channelh); static inline int __hal_channel_msix_idx(xge_hal_channel_h channelh) { return ((xge_hal_channel_t*)channelh)->msix_vect.idx; } #if defined(XGE_DEBUG_FP) && (XGE_DEBUG_FP & XGE_DEBUG_FP_CHANNEL) #define __HAL_STATIC_CHANNEL #define __HAL_INLINE_CHANNEL __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e __hal_channel_dtr_alloc(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh); __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void __hal_channel_dtr_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void __hal_channel_dtr_try_complete(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh); __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void __hal_channel_dtr_complete(xge_hal_channel_h channelh); __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void __hal_channel_dtr_free(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void __hal_channel_dtr_dealloc(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh); __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void __hal_channel_dtr_restore(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, int offset); /* ========================== CHANNEL PUBLIC API ========================= */ __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int xge_hal_channel_dtr_count(xge_hal_channel_h channelh); __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void* xge_hal_channel_userdata(xge_hal_channel_h channelh); __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int xge_hal_channel_id(xge_hal_channel_h channelh); __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int xge_hal_check_alignment(dma_addr_t dma_pointer, int size, int alignment, int copy_size); #else /* XGE_FASTPATH_EXTERN */ #define __HAL_STATIC_CHANNEL static #define __HAL_INLINE_CHANNEL inline #include "xgehal-channel-fp.c" #endif /* XGE_FASTPATH_INLINE */ xge_hal_status_e xge_hal_channel_open(xge_hal_device_h hldev, xge_hal_channel_attr_t *attr, xge_hal_channel_h *channel, xge_hal_channel_reopen_e reopen); void xge_hal_channel_close(xge_hal_channel_h channelh, xge_hal_channel_reopen_e reopen); void xge_hal_channel_abort(xge_hal_channel_h channelh, xge_hal_channel_reopen_e reopen); __EXTERN_END_DECLS #endif /* XGE_HAL_CHANNEL_H */