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