180708Sjake/*- 282899Sjake * Copyright(c) 2002-2011 Exar Corp. 380708Sjake * All rights reserved. 482899Sjake * 582899Sjake * Redistribution and use in source and binary forms, with or without 680708Sjake * modification are permitted provided the following conditions are met: 782899Sjake * 882899Sjake * 1. Redistributions of source code must retain the above copyright notice, 982899Sjake * this list of conditions and the following disclaimer. 1080708Sjake * 1180708Sjake * 2. Redistributions in binary form must reproduce the above copyright 1280708Sjake * notice, this list of conditions and the following disclaimer in the 1380708Sjake * documentation and/or other materials provided with the distribution. 1480708Sjake * 1580708Sjake * 3. Neither the name of the Exar Corporation nor the names of its 1680708Sjake * contributors may be used to endorse or promote products derived from 1780708Sjake * this software without specific prior written permission. 1882899Sjake * 1982899Sjake * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2082899Sjake * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2182899Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2282899Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2382899Sjake * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2482899Sjake * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2580708Sjake * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2682899Sjake * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2780708Sjake * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2880708Sjake * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2982899Sjake * POSSIBILITY OF SUCH DAMAGE. 3080708Sjake */ 3180708Sjake/*$FreeBSD: releng/10.3/sys/dev/vxge/vxgehal/vxgehal-channel.c 221167 2011-04-28 14:33:15Z gnn $*/ 3280708Sjake 3380708Sjake#include <dev/vxge/vxgehal/vxgehal.h> 3480708Sjake 3580708Sjake 3680708Sjake/* 3780708Sjake * vxge_hal_channel_allocate - Allocate memory for channel 3882899Sjake * @devh: Handle to the device object 3982899Sjake * @vph: Handle to Virtual Path 4080708Sjake * @type: Type of channel 4180708Sjake * @length: Lengths of arrays 4280708Sjake * @per_dtr_space: ULD requested per dtr space to be allocated in priv 4382899Sjake * @userdata: User data to be passed back in the callback 4480708Sjake * 4580708Sjake * This function allocates required memory for the channel and various arrays 4680708Sjake * in the channel 4780708Sjake */ 4880708Sjake__hal_channel_t * 4980708Sjakevxge_hal_channel_allocate( 5080708Sjake vxge_hal_device_h devh, 5180708Sjake vxge_hal_vpath_h vph, 5280708Sjake __hal_channel_type_e type, 5380708Sjake u32 length, 5480708Sjake u32 per_dtr_space, 5580708Sjake void *userdata) 5680708Sjake{ 5780708Sjake vxge_hal_device_t *hldev = (vxge_hal_device_t *) devh; 5880708Sjake __hal_channel_t *channel; 5980708Sjake u32 i, size = 0; 6080708Sjake 6180708Sjake vxge_assert((devh != NULL) && (vph != NULL)); 6280708Sjake 6380708Sjake vxge_hal_trace_log_channel("==> %s:%s:%d", 6480708Sjake __FILE__, __func__, __LINE__); 6580708Sjake 6680708Sjake vxge_hal_trace_log_channel("devh = 0x"VXGE_OS_STXFMT", vph = " 6780708Sjake "0x"VXGE_OS_STXFMT", type = %d, length = %d, " 6880708Sjake "per_dtr_space = %d, userdata = 0x"VXGE_OS_STXFMT, 6980708Sjake (ptr_t) devh, (ptr_t) vph, type, length, per_dtr_space, 7080708Sjake (ptr_t) userdata); 7180708Sjake 7280708Sjake switch (type) { 7380708Sjake case VXGE_HAL_CHANNEL_TYPE_FIFO: 7480708Sjake size = sizeof(__hal_fifo_t); 7580708Sjake break; 7680708Sjake case VXGE_HAL_CHANNEL_TYPE_RING: 7780708Sjake size = sizeof(__hal_ring_t); 7880708Sjake break; 7980708Sjake 8088653Sjake 81169291Salc default: 82169291Salc vxge_assert(size); 83169291Salc break; 84169291Salc 85169291Salc } 86108245Sjake 87108245Sjake channel = (__hal_channel_t *) vxge_os_malloc(hldev->pdev, size); 88108245Sjake if (channel == NULL) { 89108245Sjake vxge_hal_trace_log_channel("<== %s:%s:%d Result: %d", 90108245Sjake __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY); 91108245Sjake return (NULL); 92108245Sjake } 93108245Sjake 94108245Sjake vxge_os_memzero(channel, size); 95108245Sjake vxge_list_init(&channel->item); 96108245Sjake 97108245Sjake channel->pdev = hldev->pdev; 98108245Sjake channel->type = type; 99108245Sjake channel->devh = devh; 100108245Sjake channel->vph = vph; 101108245Sjake 102108245Sjake channel->userdata = userdata; 103108245Sjake channel->per_dtr_space = per_dtr_space; 104108245Sjake 105108245Sjake channel->length = length; 106108245Sjake 107108245Sjake channel->dtr_arr = (__hal_dtr_item_t *) vxge_os_malloc(hldev->pdev, 108108245Sjake sizeof(__hal_dtr_item_t)*length); 109108245Sjake if (channel->dtr_arr == NULL) { 110108245Sjake vxge_hal_channel_free(channel); 111108245Sjake vxge_hal_trace_log_channel("<== %s:%s:%d Result: %d", 112108245Sjake __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY); 113108245Sjake return (NULL); 114108245Sjake } 115108245Sjake 116108245Sjake vxge_os_memzero(channel->dtr_arr, sizeof(__hal_dtr_item_t)*length); 117108245Sjake 118108245Sjake channel->compl_index = 0; 119108245Sjake channel->reserve_index = 0; 120108245Sjake 121108245Sjake for (i = 0; i < length; i++) 122108245Sjake channel->dtr_arr[i].state = VXGE_HAL_CHANNEL_DTR_FREE; 123108245Sjake 124108245Sjake vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0", 125108245Sjake __FILE__, __func__, __LINE__); 126108245Sjake return (channel); 127108245Sjake} 128108245Sjake 129108245Sjake/* 130108245Sjake * __hal_channel_free - Free memory allocated for channel 131108245Sjake * @channel: channel to be freed 132108245Sjake * 133108245Sjake * This function deallocates memory from the channel and various arrays 134108245Sjake * in the channel 135108245Sjake */ 136108245Sjakevoid 137108245Sjakevxge_hal_channel_free( 138108245Sjake __hal_channel_t *channel) 139108245Sjake{ 14088653Sjake int size = 0; 141108245Sjake vxge_hal_device_t *hldev; 142108245Sjake 14380708Sjake vxge_assert(channel != NULL); 144108245Sjake 145108245Sjake hldev = (vxge_hal_device_t *) channel->devh; 14688653Sjake 147108245Sjake vxge_hal_trace_log_channel("==> %s:%s:%d", 148108245Sjake __FILE__, __func__, __LINE__); 14980708Sjake 150108245Sjake vxge_hal_trace_log_channel("channel = 0x"VXGE_OS_STXFMT, 151108245Sjake (ptr_t) channel); 152108245Sjake 153108245Sjake vxge_assert(channel->pdev); 154108245Sjake 155108245Sjake if (channel->dtr_arr) { 156108245Sjake vxge_os_free(channel->pdev, channel->dtr_arr, 157108245Sjake sizeof(__hal_dtr_item_t)*channel->length); 158108245Sjake channel->dtr_arr = NULL; 159108245Sjake } 160108245Sjake 161108245Sjake switch (channel->type) { 16280708Sjake case VXGE_HAL_CHANNEL_TYPE_FIFO: 16380708Sjake size = sizeof(__hal_fifo_t); 16480708Sjake break; 16580708Sjake case VXGE_HAL_CHANNEL_TYPE_RING: 16691974Sjake size = sizeof(__hal_ring_t); 16780708Sjake break; 16880708Sjake default: 16985241Sjake break; 17091974Sjake } 171168920Ssepotvin 172168920Ssepotvin vxge_os_free(channel->pdev, channel, size); 17391974Sjake 17491974Sjake vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0", 17591974Sjake __FILE__, __func__, __LINE__); 17691974Sjake} 17791974Sjake 17891974Sjake/* 17991974Sjake * __hal_channel_initialize - Initialize a channel 18080708Sjake * @channel: channel to be initialized 18180708Sjake * 18280708Sjake * This function initializes a channel by properly 18380708Sjake * setting the various references 18480708Sjake */ 18580708Sjakevxge_hal_status_e 186108332Sjakevxge_hal_channel_initialize( 187108332Sjake __hal_channel_t *channel) 188101653Sjake{ 189101653Sjake vxge_hal_device_t *hldev; 19080708Sjake __hal_virtualpath_t *vpath; 191 192 vxge_assert(channel != NULL); 193 194 hldev = (vxge_hal_device_t *) channel->devh; 195 vpath = (__hal_virtualpath_t *) 196 ((__hal_vpath_handle_t *) channel->vph)->vpath; 197 198 vxge_assert(vpath != NULL); 199 200 vxge_hal_trace_log_channel("==> %s:%s:%d", 201 __FILE__, __func__, __LINE__); 202 203 vxge_hal_trace_log_channel("channel = 0x"VXGE_OS_STXFMT, 204 (ptr_t) channel); 205 206 switch (channel->type) { 207 case VXGE_HAL_CHANNEL_TYPE_FIFO: 208 vpath->fifoh = (vxge_hal_fifo_h) channel; 209 channel->stats = 210 &((__hal_fifo_t *) channel)->stats->common_stats; 211 break; 212 case VXGE_HAL_CHANNEL_TYPE_RING: 213 vpath->ringh = (vxge_hal_ring_h) channel; 214 channel->stats = 215 &((__hal_ring_t *) channel)->stats->common_stats; 216 break; 217 218 219 default: 220 break; 221 } 222 223 channel->is_initd = 1; 224 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0", 225 __FILE__, __func__, __LINE__); 226 227 return (VXGE_HAL_OK); 228} 229 230/* 231 * __hal_channel_reset - Resets a channel 232 * @channel: channel to be reset 233 * 234 * This function resets a channel by properly setting the various references 235 */ 236vxge_hal_status_e 237__hal_channel_reset( 238 __hal_channel_t *channel) 239{ 240 u32 i; 241 __hal_device_t *hldev; 242 243 vxge_assert(channel != NULL); 244 245 hldev = (__hal_device_t *) channel->devh; 246 247 vxge_hal_trace_log_channel("==> %s:%s:%d", 248 __FILE__, __func__, __LINE__); 249 250 vxge_hal_trace_log_channel("channel = 0x"VXGE_OS_STXFMT, 251 (ptr_t) channel); 252 253 vxge_assert(channel->pdev); 254 255 channel->compl_index = 0; 256 channel->reserve_index = 0; 257 258 for (i = 0; i < channel->length; i++) { 259 channel->dtr_arr[i].state = 260 VXGE_HAL_CHANNEL_DTR_FREE; 261 } 262 263 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0", 264 __FILE__, __func__, __LINE__); 265 266 return (VXGE_HAL_OK); 267} 268 269/* 270 * vxge_hal_channel_terminate - Deinitializes a channel 271 * @channel: channel to be deinitialized 272 * 273 * This function deinitializes a channel by properly 274 * setting the various references 275 */ 276void 277vxge_hal_channel_terminate( 278 __hal_channel_t *channel) 279{ 280 __hal_device_t *hldev; 281 __hal_virtualpath_t *vpath; 282 283 vxge_assert(channel != NULL); 284 285 if (!channel || !channel->is_initd) 286 return; 287 288 hldev = (__hal_device_t *) channel->devh; 289 vpath = (__hal_virtualpath_t *) 290 ((__hal_vpath_handle_t *) channel->vph)->vpath; 291 292 vxge_assert(vpath != NULL); 293 294 vxge_hal_trace_log_channel("==> %s:%s:%d", 295 __FILE__, __func__, __LINE__); 296 297 vxge_hal_trace_log_channel("channel = 0x"VXGE_OS_STXFMT, 298 (ptr_t) channel); 299 300 switch (channel->type) { 301 case VXGE_HAL_CHANNEL_TYPE_FIFO: 302 vpath->fifoh = 0; 303 break; 304 case VXGE_HAL_CHANNEL_TYPE_RING: 305 vpath->ringh = 0; 306 break; 307 case VXGE_HAL_CHANNEL_TYPE_SEND_QUEUE: 308 vxge_list_remove(&channel->item); 309 vpath->sw_stats->obj_counts.no_sqs--; 310 break; 311 case VXGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE: 312 vxge_list_remove(&channel->item); 313 vpath->sw_stats->obj_counts.no_srqs--; 314 break; 315 case VXGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE: 316 vxge_list_remove(&channel->item); 317 vpath->sw_stats->obj_counts.no_cqrqs--; 318 break; 319 default: 320 break; 321 } 322 323 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0", 324 __FILE__, __func__, __LINE__); 325} 326 327void 328__hal_channel_init_pending_list( 329 vxge_hal_device_h devh) 330{ 331 __hal_device_t *hldev = (__hal_device_t *) devh; 332 333 vxge_assert(devh != NULL); 334 335 vxge_hal_trace_log_channel("==> %s:%s:%d", 336 __FILE__, __func__, __LINE__); 337 338 vxge_hal_trace_log_channel("devh = 0x"VXGE_OS_STXFMT, 339 (ptr_t) devh); 340 vxge_list_init(&hldev->pending_channel_list); 341 342#if defined(VXGE_HAL_VP_CHANNELS) 343 vxge_os_spin_lock_init(&hldev->pending_channel_lock, hldev->pdev); 344#elif defined(VXGE_HAL_VP_CHANNELS_IRQ) 345 vxge_os_spin_lock_init_irq(&hldev->pending_channel_lock, hldev->irqh); 346#endif 347 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0", 348 __FILE__, __func__, __LINE__); 349} 350 351void 352__hal_channel_insert_pending_list( 353 __hal_channel_t * channel) 354{ 355 __hal_device_t *hldev = (__hal_device_t *) channel->devh; 356 357 vxge_assert(channel != NULL); 358 359 vxge_hal_trace_log_channel("==> %s:%s:%d", 360 __FILE__, __func__, __LINE__); 361 362 vxge_hal_trace_log_channel("channel = 0x"VXGE_OS_STXFMT, 363 (ptr_t) channel); 364 365#if defined(VXGE_HAL_PENDING_CHANNELS) 366 vxge_os_spin_lock(&hldev->pending_channel_lock); 367#elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ) 368 vxge_os_spin_lock_irq(&hldev->pending_channel_lock, flags); 369#endif 370 371 vxge_list_insert_before(&channel->item, &hldev->pending_channel_list); 372 373#if defined(VXGE_HAL_PENDING_CHANNELS) 374 vxge_os_spin_unlock(&hldev->pending_channel_lock); 375#elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ) 376 vxge_os_spin_unlock_irq(&hldev->pending_channel_lock, flags); 377#endif 378 379 __hal_channel_process_pending_list(channel->devh); 380 381 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0", 382 __FILE__, __func__, __LINE__); 383} 384 385void 386__hal_channel_process_pending_list( 387 vxge_hal_device_h devh) 388{ 389 vxge_hal_status_e status; 390 __hal_channel_t *channel; 391 __hal_device_t *hldev = (__hal_device_t *) devh; 392 393 vxge_assert(devh != NULL); 394 395 vxge_hal_trace_log_channel("==> %s:%s:%d", 396 __FILE__, __func__, __LINE__); 397 398 vxge_hal_trace_log_channel("devh = 0x"VXGE_OS_STXFMT, 399 (ptr_t) devh); 400 401 for (;;) { 402#if defined(VXGE_HAL_PENDING_CHANNELS) 403 vxge_os_spin_lock(&hldev->pending_channel_lock); 404#elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ) 405 vxge_os_spin_lock_irq(&hldev->pending_channel_lock, flags); 406#endif 407 408 channel = (__hal_channel_t *) 409 vxge_list_first_get(&hldev->pending_channel_list); 410 411 if (channel != NULL) 412 vxge_list_remove(&channel->item); 413 414#if defined(VXGE_HAL_PENDING_CHANNELS) 415 vxge_os_spin_unlock(&hldev->pending_channel_lock); 416#elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ) 417 vxge_os_spin_unlock_irq(&hldev->pending_channel_lock, flags); 418#endif 419 420 if (channel == NULL) { 421 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0", 422 __FILE__, __func__, __LINE__); 423 return; 424 } 425 426 switch (channel->type) { 427 default: 428 status = VXGE_HAL_OK; 429 break; 430 } 431 432 if (status == VXGE_HAL_ERR_OUT_OF_MEMORY) { 433#if defined(VXGE_HAL_PENDING_CHANNELS) 434 vxge_os_spin_lock(&hldev->pending_channel_lock); 435#elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ) 436 vxge_os_spin_lock_irq(&hldev->pending_channel_lock, 437 flags); 438#endif 439 440 vxge_list_insert(&channel->item, 441 &hldev->pending_channel_list); 442 443#if defined(VXGE_HAL_PENDING_CHANNELS) 444 vxge_os_spin_unlock(&hldev->pending_channel_lock); 445#elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ) 446 vxge_os_spin_unlock_irq(&hldev->pending_channel_lock, 447 flags); 448#endif 449 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0", 450 __FILE__, __func__, __LINE__); 451 452 return; 453 } 454 455 } 456} 457 458void 459__hal_channel_destroy_pending_list( 460 vxge_hal_device_h devh) 461{ 462 vxge_list_t *p, *n; 463 __hal_device_t *hldev = (__hal_device_t *) devh; 464 465 vxge_assert(devh != NULL); 466 467 vxge_hal_trace_log_channel("==> %s:%s:%d", 468 __FILE__, __func__, __LINE__); 469 470 vxge_hal_trace_log_channel("devh = 0x"VXGE_OS_STXFMT, 471 (ptr_t) devh); 472 473 vxge_list_for_each_safe(p, n, &hldev->pending_channel_list) { 474 475 vxge_list_remove(p); 476 477 switch (((__hal_channel_t *) p)->type) { 478 default: 479 break; 480 } 481 482 } 483 484#if defined(VXGE_HAL_PENDING_CHANNELS) 485 vxge_os_spin_lock_destroy(&hldev->pending_channel_lock, 486 hldev->header.pdev); 487#elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ) 488 vxge_os_spin_lock_destroy_irq(&hldev->pending_channel_lock, 489 hldev->header.pdev); 490#endif 491 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0", 492 __FILE__, __func__, __LINE__); 493} 494