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