freebsd-dev/sys/dev/vxge/vxgehal/vxgehal-channel.h
George V. Neville-Neil 548d35fd69 Exar driver for X3100 10GbE Server/Storage adapters
Features: Jumbo frames (up to 9600), LRO (Large Receive Offload),
          TSO (TCP segmentation offload), RTH (Receive Traffic Hash).

Submitted by: Sriram Rapuru at Exar
MFC after:	2 weeks
2011-04-28 14:33:15 +00:00

387 lines
12 KiB
C

/*-
* Copyright(c) 2002-2011 Exar Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification are permitted provided the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Exar Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*$FreeBSD$*/
#ifndef VXGE_HAL_CHANNEL_H
#define VXGE_HAL_CHANNEL_H
__EXTERN_BEGIN_DECLS
/*
* __hal_dtr_h - Handle to the desriptor object used for nonoffload
* send or receive. Generic handle which can be with txd or rxd
*/
typedef void *__hal_dtr_h;
/*
* enum __hal_channel_type_e - Enumerated channel types.
* @VXGE_HAL_CHANNEL_TYPE_UNKNOWN: Unknown channel.
* @VXGE_HAL_CHANNEL_TYPE_FIFO: fifo.
* @VXGE_HAL_CHANNEL_TYPE_RING: ring.
* @VXGE_HAL_CHANNEL_TYPE_SQ: Send Queue
* @VXGE_HAL_CHANNEL_TYPE_SRQ: Receive Queue
* @VXGE_HAL_CHANNEL_TYPE_CQRQ: Receive queue completion queue
* @VXGE_HAL_CHANNEL_TYPE_UMQ: Up message queue
* @VXGE_HAL_CHANNEL_TYPE_DMQ: Down message queue
* @VXGE_HAL_CHANNEL_TYPE_MAX: Maximum number of HAL-supported
* (and recognized) channel types. Currently: 7.
*
* Enumerated channel types. Currently there are only two link-layer
* channels - X3100 fifo and X3100 ring. In the future the list will grow.
*/
typedef enum __hal_channel_type_e {
VXGE_HAL_CHANNEL_TYPE_UNKNOWN = 0,
VXGE_HAL_CHANNEL_TYPE_FIFO = 1,
VXGE_HAL_CHANNEL_TYPE_RING = 2,
VXGE_HAL_CHANNEL_TYPE_SEND_QUEUE = 3,
VXGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE = 4,
VXGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE = 5,
VXGE_HAL_CHANNEL_TYPE_UP_MESSAGE_QUEUE = 6,
VXGE_HAL_CHANNEL_TYPE_DOWN_MESSAGE_QUEUE = 7,
VXGE_HAL_CHANNEL_TYPE_MAX = 8
} __hal_channel_type_e;
/*
* __hal_dtr_item_t
* @dtr: Pointer to the descriptors that contains the dma data
* to/from the device.
* @hal_priv: HAL Private data related to the dtr.
* @uld_priv: ULD Private data related to the dtr.
*/
typedef struct __hal_dtr_item_t {
void *dtr;
void *hal_priv;
void *uld_priv;
u32 state;
#define VXGE_HAL_CHANNEL_DTR_FREE 0
#define VXGE_HAL_CHANNEL_DTR_RESERVED 1
#define VXGE_HAL_CHANNEL_DTR_POSTED 2
#define VXGE_HAL_CHANNEL_DTR_COMPLETED 3
} __hal_dtr_item_t;
/*
* __hal_channel_t
* @item: List item; used to maintain a list of open channels.
* @type: Channel type. See vxge_hal_channel_type_e {}.
* @devh: Device handle. HAL device object that contains _this_ channel.
* @pdev: PCI Device object
* @vph: Virtual path handle. Virtual Path Object that contains _this_ channel.
* @length: Channel length. Currently allocated number of descriptors.
* The channel length "grows" when more descriptors get allocated.
* See _hal_mempool_grow.
* @dtr_arr: Dtr array. Contains descriptors posted to the channel and their
* private data.
* Note that at any point in time @dtr_arr contains 3 types of
* descriptors:
* 1) posted but not yet consumed by X3100 device;
* 2) consumed but not yet completed;
* 3) completed.
* @post_index: Post index. At any point in time points on the
* position in the channel, which'll contain next to-be-posted
* descriptor.
* @compl_index: Completion index. At any point in time points on the
* position in the channel, which will contain next
* to-be-completed descriptor.
* @reserve_index: Reserve index. At any point in time points on the
* position in the channel, which will contain next
* to-be-reserved descriptor.
* @free_dtr_count: Number of dtrs free.
* @posted_dtr_count: Number of dtrs posted
* @post_lock: Lock to serialize multiple concurrent "posters" of descriptors
* on the given channel.
* @poll_bytes: Poll bytes.
* @per_dtr_space: Per-descriptor space (in bytes) that channel user can utilize
* to store per-operation control information.
* @stats: Pointer to common statistics
* @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
* vxge_hal_channel_callback_f.
*
* HAL channel object.
*
* See also: vxge_hal_channel_type_e {}, vxge_hal_channel_flag_e
*/
typedef struct __hal_channel_t {
vxge_list_t item;
__hal_channel_type_e type;
vxge_hal_device_h devh;
pci_dev_h pdev;
vxge_hal_vpath_h vph;
u32 length;
u32 is_initd;
__hal_dtr_item_t *dtr_arr;
u32 compl_index __vxge_os_attr_cacheline_aligned;
u32 reserve_index __vxge_os_attr_cacheline_aligned;
spinlock_t post_lock;
u32 poll_bytes;
u32 per_dtr_space;
vxge_hal_vpath_stats_sw_common_info_t *stats;
void *userdata;
} __hal_channel_t __vxge_os_attr_cacheline_aligned;
#define __hal_channel_is_posted_dtr(channel, index) \
((channel)->dtr_arr[index].state == VXGE_HAL_CHANNEL_DTR_POSTED)
#define __hal_channel_for_each_posted_dtr(channel, dtrh, index) \
for (index = (channel)->compl_index,\
dtrh = (channel)->dtr_arr[index].dtr; \
(index < (channel)->reserve_index) && \
((channel)->dtr_arr[index].state == VXGE_HAL_CHANNEL_DTR_POSTED); \
index = (++index == (channel)->length)? 0 : index, \
dtrh = (channel)->dtr_arr[index].dtr)
#define __hal_channel_for_each_dtr(channel, dtrh, index) \
for (index = 0, dtrh = (channel)->dtr_arr[index].dtr; \
index < (channel)->length; \
dtrh = ((++index == (channel)->length)? 0 : \
(channel)->dtr_arr[index].dtr))
#define __hal_channel_free_dtr_count(channel) \
(((channel)->reserve_index < (channel)->compl_index) ? \
((channel)->compl_index - (channel)->reserve_index) : \
(((channel)->length - (channel)->reserve_index) + \
(channel)->reserve_index))
/* ========================== CHANNEL PRIVATE API ========================= */
__hal_channel_t *
vxge_hal_channel_allocate(
vxge_hal_device_h devh,
vxge_hal_vpath_h vph,
__hal_channel_type_e type,
u32 length,
u32 per_dtr_space,
void *userdata);
void
vxge_hal_channel_free(
__hal_channel_t *channel);
vxge_hal_status_e
vxge_hal_channel_initialize(
__hal_channel_t *channel);
vxge_hal_status_e
__hal_channel_reset(
__hal_channel_t *channel);
void
vxge_hal_channel_terminate(
__hal_channel_t *channel);
void
__hal_channel_init_pending_list(
vxge_hal_device_h devh);
void
__hal_channel_insert_pending_list(
__hal_channel_t * channel);
void
__hal_channel_process_pending_list(
vxge_hal_device_h devhv);
void
__hal_channel_destroy_pending_list(
vxge_hal_device_h devh);
#if defined(VXGE_DEBUG_FP) && (VXGE_DEBUG_FP & VXGE_DEBUG_FP_CHANNEL)
#define __HAL_STATIC_CHANNEL
#define __HAL_INLINE_CHANNEL
#else /* VXGE_FASTPATH_EXTERN */
#define __HAL_STATIC_CHANNEL static
#define __HAL_INLINE_CHANNEL inline
#endif /* VXGE_FASTPATH_INLINE */
/* ========================== CHANNEL Fast Path API ========================= */
/*
* __hal_channel_dtr_reserve- Reserve a dtr from the channel
* @channelh: Channel
* @dtrh: Buffer to return the DTR pointer
*
* Reserve a dtr from the reserve array.
*
*/
__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL vxge_hal_status_e
/* LINTED */
__hal_channel_dtr_reserve(__hal_channel_t *channel, __hal_dtr_h *dtrh)
{
vxge_hal_status_e status = VXGE_HAL_INF_OUT_OF_DESCRIPTORS;
*dtrh = NULL;
if (channel->dtr_arr[channel->reserve_index].state ==
VXGE_HAL_CHANNEL_DTR_FREE) {
*dtrh = channel->dtr_arr[channel->reserve_index].dtr;
channel->dtr_arr[channel->reserve_index].state =
VXGE_HAL_CHANNEL_DTR_RESERVED;
if (++channel->reserve_index == channel->length)
channel->reserve_index = 0;
status = VXGE_HAL_OK;
} else {
#if (VXGE_COMPONENT_HAL_CHANNEL & VXGE_DEBUG_MODULE_MASK)
__hal_device_t *hldev = (__hal_device_t *) channel->devh;
vxge_hal_info_log_channel("channel %d is full!", channel->type);
#endif
channel->stats->full_cnt++;
}
return (status);
}
/*
* __hal_channel_dtr_restore - Restores a dtr to the channel
* @channelh: Channel
* @dtr: DTR pointer
*
* Returns a dtr back to reserve array.
*
*/
__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
/* LINTED */
__hal_channel_dtr_restore(__hal_channel_t *channel, __hal_dtr_h dtrh)
{
u32 dtr_index;
/*
* restore a previously allocated dtrh at current offset and update
* the available reserve length accordingly. If dtrh is null just
* update the reserve length, only
*/
if (channel->reserve_index == 0)
dtr_index = channel->length;
else
dtr_index = channel->reserve_index - 1;
if ((channel->dtr_arr[dtr_index].dtr == dtrh)) {
channel->reserve_index = dtr_index;
channel->dtr_arr[dtr_index].state = VXGE_HAL_CHANNEL_DTR_FREE;
#if (VXGE_COMPONENT_HAL_CHANNEL & VXGE_DEBUG_MODULE_MASK)
__hal_device_t *hldev = (__hal_device_t *) channel->devh;
vxge_hal_info_log_channel("dtrh 0x"VXGE_OS_STXFMT" \
restored for " "channel %d at reserve index %d, ",
(ptr_t) dtrh, channel->type,
channel->reserve_index);
#endif
}
}
/*
* __hal_channel_dtr_post - Post a dtr to the channel
* @channelh: Channel
* @dtr: DTR pointer
*
* Posts a dtr to work array.
*
*/
__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
/* LINTED */
__hal_channel_dtr_post(__hal_channel_t *channel, u32 dtr_index)
{
channel->dtr_arr[dtr_index].state =
VXGE_HAL_CHANNEL_DTR_POSTED;
}
/*
* __hal_channel_dtr_try_complete - Returns next completed dtr
* @channelh: Channel
* @dtr: Buffer to return the next completed DTR pointer
*
* Returns the next completed dtr with out removing it from work array
*
*/
__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
/* LINTED */
__hal_channel_dtr_try_complete(__hal_channel_t *channel, __hal_dtr_h *dtrh)
{
vxge_assert(channel->dtr_arr);
vxge_assert(channel->compl_index < channel->length);
if (channel->dtr_arr[channel->compl_index].state ==
VXGE_HAL_CHANNEL_DTR_POSTED)
*dtrh = channel->dtr_arr[channel->compl_index].dtr;
else
*dtrh = NULL;
}
/*
* __hal_channel_dtr_complete - Removes next completed dtr from the work array
* @channelh: Channel
*
* Removes the next completed dtr from work array
*
*/
__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
/* LINTED */
__hal_channel_dtr_complete(__hal_channel_t *channel)
{
channel->dtr_arr[channel->compl_index].state =
VXGE_HAL_CHANNEL_DTR_COMPLETED;
if (++channel->compl_index == channel->length)
channel->compl_index = 0;
channel->stats->total_compl_cnt++;
}
/*
* __hal_channel_dtr_free - Frees a dtr
* @channelh: Channel
* @index: Index of DTR
*
* Returns the dtr to free array
*
*/
__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
/* LINTED */
__hal_channel_dtr_free(__hal_channel_t *channel, u32 dtr_index)
{
channel->dtr_arr[dtr_index].state =
VXGE_HAL_CHANNEL_DTR_FREE;
}
__EXTERN_END_DECLS
#endif /* VXGE_HAL_CHANNEL_H */