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#include <dev/vxge/vxgehal/vxgehal.h> 34221167Sgnn 35221167Sgnn/* 36221167Sgnn * vxge_queue_item_data - Get item's data. 37221167Sgnn * @item: Queue item. 38221167Sgnn * 39221167Sgnn * Returns: item data(variable size). Note that vxge_queue_t 40221167Sgnn * contains items comprized of a fixed vxge_queue_item_t "header" 41221167Sgnn * and a variable size data. This function returns the variable 42221167Sgnn * user-defined portion of the queue item. 43221167Sgnn */ 44221167Sgnnvoid * 45221167Sgnnvxge_queue_item_data(vxge_queue_item_t *item) 46221167Sgnn{ 47221167Sgnn return (char *) item + sizeof(vxge_queue_item_t); 48221167Sgnn} 49221167Sgnn 50221167Sgnn/* 51221167Sgnn * __queue_consume - (Lockless) dequeue an item from the specified queue. 52221167Sgnn * 53221167Sgnn * @queue: Event queue. 54221167Sgnn * @data_max_size: Maximum size of the data 55221167Sgnn * @item: Queue item 56221167Sgnn * See vxge_queue_consume(). 57221167Sgnn */ 58221167Sgnnstatic vxge_queue_status_e 59221167Sgnn__queue_consume(vxge_queue_t *queue, 60221167Sgnn u32 data_max_size, 61221167Sgnn vxge_queue_item_t *item) 62221167Sgnn{ 63221167Sgnn int real_size; 64221167Sgnn vxge_queue_item_t *elem; 65221167Sgnn __hal_device_t *hldev; 66221167Sgnn 67221167Sgnn vxge_assert(queue != NULL); 68221167Sgnn 69221167Sgnn hldev = (__hal_device_t *) queue->hldev; 70221167Sgnn 71221167Sgnn vxge_hal_trace_log_queue("==> %s:%s:%d", 72221167Sgnn __FILE__, __func__, __LINE__); 73221167Sgnn 74221167Sgnn vxge_hal_trace_log_queue( 75221167Sgnn "queue = 0x"VXGE_OS_STXFMT", size = %d, item = 0x"VXGE_OS_STXFMT, 76221167Sgnn (ptr_t) queue, data_max_size, (ptr_t) item); 77221167Sgnn 78221167Sgnn if (vxge_list_is_empty(&queue->list_head)) { 79221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = %d", 80221167Sgnn __FILE__, __func__, __LINE__, VXGE_QUEUE_IS_EMPTY); 81221167Sgnn return (VXGE_QUEUE_IS_EMPTY); 82221167Sgnn } 83221167Sgnn 84221167Sgnn elem = (vxge_queue_item_t *) queue->list_head.next; 85221167Sgnn if (elem->data_size > data_max_size) { 86221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = %d", 87221167Sgnn __FILE__, __func__, __LINE__, VXGE_QUEUE_NOT_ENOUGH_SPACE); 88221167Sgnn return (VXGE_QUEUE_NOT_ENOUGH_SPACE); 89221167Sgnn } 90221167Sgnn 91221167Sgnn vxge_list_remove(&elem->item); 92221167Sgnn real_size = elem->data_size + sizeof(vxge_queue_item_t); 93221167Sgnn if (queue->head_ptr == elem) { 94221167Sgnn queue->head_ptr = (char *) queue->head_ptr + real_size; 95221167Sgnn vxge_hal_info_log_queue("event_type: %d \ 96221167Sgnn removing from the head: " 97221167Sgnn "0x"VXGE_OS_STXFMT":0x"VXGE_OS_STXFMT":0x"VXGE_OS_STXFMT 98221167Sgnn ":0x0x"VXGE_OS_STXFMT" elem 0x0x"VXGE_OS_STXFMT" length %d", 99221167Sgnn elem->event_type, (ptr_t) queue->start_ptr, 100221167Sgnn (ptr_t) queue->head_ptr, (ptr_t) queue->tail_ptr, 101221167Sgnn (ptr_t) queue->end_ptr, (ptr_t) elem, real_size); 102221167Sgnn } else if ((char *) queue->tail_ptr - real_size == (char *) elem) { 103221167Sgnn queue->tail_ptr = (char *) queue->tail_ptr - real_size; 104221167Sgnn vxge_hal_info_log_queue("event_type: %d \ 105221167Sgnn removing from the tail: " 106221167Sgnn "0x"VXGE_OS_STXFMT":0x"VXGE_OS_STXFMT":0x"VXGE_OS_STXFMT 107221167Sgnn ":0x"VXGE_OS_STXFMT" elem 0x"VXGE_OS_STXFMT" length %d", 108221167Sgnn elem->event_type, (ptr_t) queue->start_ptr, 109221167Sgnn (ptr_t) queue->head_ptr, (ptr_t) queue->tail_ptr, 110221167Sgnn (ptr_t) queue->end_ptr, (ptr_t) elem, real_size); 111221167Sgnn } else { 112221167Sgnn vxge_hal_info_log_queue("event_type: %d \ 113221167Sgnn removing from the list: " 114221167Sgnn "0x"VXGE_OS_STXFMT":0x"VXGE_OS_STXFMT":0x"VXGE_OS_STXFMT 115221167Sgnn ":0x"VXGE_OS_STXFMT" elem 0x"VXGE_OS_STXFMT" length %d", 116221167Sgnn elem->event_type, (ptr_t) queue->start_ptr, 117221167Sgnn (ptr_t) queue->head_ptr, (ptr_t) queue->tail_ptr, 118221167Sgnn (ptr_t) queue->end_ptr, (ptr_t) elem, real_size); 119221167Sgnn } 120221167Sgnn vxge_assert(queue->tail_ptr >= queue->head_ptr); 121221167Sgnn vxge_assert(queue->tail_ptr >= queue->start_ptr && 122221167Sgnn queue->tail_ptr <= queue->end_ptr); 123221167Sgnn vxge_assert(queue->head_ptr >= queue->start_ptr && 124221167Sgnn queue->head_ptr < queue->end_ptr); 125221167Sgnn vxge_os_memcpy(item, elem, sizeof(vxge_queue_item_t)); 126221167Sgnn vxge_os_memcpy(vxge_queue_item_data(item), vxge_queue_item_data(elem), 127221167Sgnn elem->data_size); 128221167Sgnn 129221167Sgnn if (vxge_list_is_empty(&queue->list_head)) { 130221167Sgnn /* reset buffer pointers just to be clean */ 131221167Sgnn queue->head_ptr = queue->tail_ptr = queue->start_ptr; 132221167Sgnn } 133221167Sgnn 134221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = 0", 135221167Sgnn __FILE__, __func__, __LINE__); 136221167Sgnn 137221167Sgnn return (VXGE_QUEUE_OK); 138221167Sgnn} 139221167Sgnn 140221167Sgnn/* 141221167Sgnn * vxge_queue_produce - Enqueue an item (see vxge_queue_item_t {}) 142221167Sgnn * into the specified queue. 143221167Sgnn * @queueh: Queue handle. 144221167Sgnn * @event_type: Event type. One of the enumerated event types 145221167Sgnn * that both consumer and producer "understand". 146221167Sgnn * For an example, please refer to vxge_hal_event_e. 147221167Sgnn * @context: Opaque (void *) "context", for instance event producer object. 148221167Sgnn * @is_critical: For critical event, e.g. ECC. 149221167Sgnn * @data_size: Size of the @data. 150221167Sgnn * @data: User data of variable @data_size that is _copied_ into 151221167Sgnn * the new queue item (see vxge_queue_item_t {}). Upon return 152221167Sgnn * from the call the @data memory can be re-used or released. 153221167Sgnn * 154221167Sgnn * Enqueue a new item. 155221167Sgnn * 156221167Sgnn * Returns: VXGE_QUEUE_OK - success. 157221167Sgnn * VXGE_QUEUE_IS_FULL - Queue is full. 158221167Sgnn * VXGE_QUEUE_OUT_OF_MEMORY - Memory allocation failed. 159221167Sgnn * 160221167Sgnn * See also: vxge_queue_item_t {}, vxge_queue_consume(). 161221167Sgnn */ 162221167Sgnnvxge_queue_status_e 163221167Sgnnvxge_queue_produce(vxge_queue_h queueh, 164221167Sgnn u32 event_type, 165221167Sgnn void *context, 166221167Sgnn u32 is_critical, 167221167Sgnn const u32 data_size, 168221167Sgnn void *data) 169221167Sgnn{ 170221167Sgnn vxge_queue_t *queue = (vxge_queue_t *) queueh; 171221167Sgnn int real_size = data_size + sizeof(vxge_queue_item_t); 172221167Sgnn __hal_device_t *hldev; 173221167Sgnn vxge_queue_item_t *elem; 174221167Sgnn unsigned long flags = 0; 175221167Sgnn 176221167Sgnn vxge_assert(queueh != NULL); 177221167Sgnn 178221167Sgnn hldev = (__hal_device_t *) queue->hldev; 179221167Sgnn 180221167Sgnn vxge_hal_trace_log_queue("==> %s:%s:%d", 181221167Sgnn __FILE__, __func__, __LINE__); 182221167Sgnn 183221167Sgnn vxge_hal_trace_log_queue( 184221167Sgnn "queueh = 0x"VXGE_OS_STXFMT", event_type = %d, " 185221167Sgnn "context = 0x"VXGE_OS_STXFMT", is_critical = %d, " 186221167Sgnn "data_size = %d, data = 0x"VXGE_OS_STXFMT, 187221167Sgnn (ptr_t) queueh, event_type, (ptr_t) context, 188221167Sgnn is_critical, data_size, (ptr_t) data); 189221167Sgnn 190221167Sgnn vxge_assert(real_size <= VXGE_QUEUE_BUF_SIZE); 191221167Sgnn 192221167Sgnn vxge_os_spin_lock_irq(&queue->lock, flags); 193221167Sgnn 194221167Sgnn if (is_critical && !queue->has_critical_event) { 195221167Sgnn unsigned char item_buf[sizeof(vxge_queue_item_t) + 196221167Sgnn VXGE_DEFAULT_EVENT_MAX_DATA_SIZE]; 197221167Sgnn vxge_queue_item_t *item = 198221167Sgnn (vxge_queue_item_t *) (void *)item_buf; 199221167Sgnn 200221167Sgnn while (__queue_consume(queue, VXGE_DEFAULT_EVENT_MAX_DATA_SIZE, 201221167Sgnn item) != VXGE_QUEUE_IS_EMPTY) { 202221167Sgnn } /* do nothing */ 203221167Sgnn } 204221167Sgnn 205221167Sgnntry_again: 206221167Sgnn if ((char *) queue->tail_ptr + real_size <= (char *) queue->end_ptr) { 207221167Sgnn elem = (vxge_queue_item_t *) queue->tail_ptr; 208221167Sgnn queue->tail_ptr = (void *)((char *) queue->tail_ptr + real_size); 209221167Sgnn vxge_hal_info_log_queue("event_type: %d adding to the tail: " 210221167Sgnn "0x"VXGE_OS_STXFMT":0x"VXGE_OS_STXFMT":0x"VXGE_OS_STXFMT 211221167Sgnn ":0x"VXGE_OS_STXFMT" elem 0x"VXGE_OS_STXFMT" length %d", 212221167Sgnn event_type, (ptr_t) queue->start_ptr, 213221167Sgnn (ptr_t) queue->head_ptr, (ptr_t) queue->tail_ptr, 214221167Sgnn (ptr_t) queue->end_ptr, (ptr_t) elem, real_size); 215221167Sgnn } else if ((char *) queue->head_ptr - real_size >= 216221167Sgnn (char *) queue->start_ptr) { 217221167Sgnn elem = (vxge_queue_item_t *) 218221167Sgnn ((void *)((char *) queue->head_ptr - real_size)); 219221167Sgnn queue->head_ptr = elem; 220221167Sgnn vxge_hal_info_log_queue("event_type: %d adding to the head: " 221221167Sgnn "0x"VXGE_OS_STXFMT":0x"VXGE_OS_STXFMT":" 222221167Sgnn "0x"VXGE_OS_STXFMT":0x"VXGE_OS_STXFMT" length %d", 223221167Sgnn event_type, (ptr_t) queue->start_ptr, 224221167Sgnn (ptr_t) queue->head_ptr, (ptr_t) queue->tail_ptr, 225221167Sgnn (ptr_t) queue->end_ptr, real_size); 226221167Sgnn } else { 227221167Sgnn vxge_queue_status_e status; 228221167Sgnn 229221167Sgnn if (queue->pages_current >= queue->pages_max) { 230221167Sgnn vxge_os_spin_unlock_irq(&queue->lock, flags); 231221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = %d", 232221167Sgnn __FILE__, __func__, __LINE__, VXGE_QUEUE_IS_FULL); 233221167Sgnn return (VXGE_QUEUE_IS_FULL); 234221167Sgnn } 235221167Sgnn 236221167Sgnn if (queue->has_critical_event) { 237221167Sgnn vxge_os_spin_unlock_irq(&queue->lock, flags); 238221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = %d", 239221167Sgnn __FILE__, __func__, __LINE__, VXGE_QUEUE_IS_FULL); 240221167Sgnn return (VXGE_QUEUE_IS_FULL); 241221167Sgnn } 242221167Sgnn 243221167Sgnn /* grow */ 244221167Sgnn status = vxge_io_queue_grow(queueh); 245221167Sgnn if (status != VXGE_QUEUE_OK) { 246221167Sgnn vxge_os_spin_unlock_irq(&queue->lock, flags); 247221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = %d", 248221167Sgnn __FILE__, __func__, __LINE__, status); 249221167Sgnn return (status); 250221167Sgnn } 251221167Sgnn 252221167Sgnn goto try_again; 253221167Sgnn } 254221167Sgnn vxge_assert(queue->tail_ptr >= queue->head_ptr); 255221167Sgnn vxge_assert(queue->tail_ptr >= queue->start_ptr && 256221167Sgnn queue->tail_ptr <= queue->end_ptr); 257221167Sgnn vxge_assert(queue->head_ptr >= queue->start_ptr && 258221167Sgnn queue->head_ptr < queue->end_ptr); 259221167Sgnn elem->data_size = data_size; 260221167Sgnn elem->event_type = (vxge_hal_event_e) event_type; 261221167Sgnn elem->is_critical = is_critical; 262221167Sgnn if (is_critical) 263221167Sgnn queue->has_critical_event = 1; 264221167Sgnn elem->context = context; 265221167Sgnn vxge_os_memcpy(vxge_queue_item_data(elem), data, data_size); 266221167Sgnn vxge_list_insert_before(&elem->item, &queue->list_head); 267221167Sgnn vxge_os_spin_unlock_irq(&queue->lock, flags); 268221167Sgnn 269221167Sgnn /* no lock taken! */ 270221167Sgnn queue->queued_func(queue->queued_data, event_type); 271221167Sgnn 272221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = 0", 273221167Sgnn __FILE__, __func__, __LINE__); 274221167Sgnn 275221167Sgnn return (VXGE_QUEUE_OK); 276221167Sgnn} 277221167Sgnn 278221167Sgnn 279221167Sgnn/* 280221167Sgnn * vxge_queue_create - Create protected first-in-first-out queue. 281221167Sgnn * @devh: HAL device handle. 282221167Sgnn * @pages_initial: Number of pages to be initially allocated at the 283221167Sgnn * time of queue creation. 284221167Sgnn * @pages_max: Max number of pages that can be allocated in the queue. 285221167Sgnn * @queued_func: Optional callback function to be called each time a new item is 286221167Sgnn * added to the queue. 287221167Sgnn * @queued_data: Argument to the callback function. 288221167Sgnn * 289221167Sgnn * Create protected (fifo) queue. 290221167Sgnn * 291221167Sgnn * Returns: Pointer to vxge_queue_t structure, 292221167Sgnn * NULL - on failure. 293221167Sgnn * 294221167Sgnn * See also: vxge_queue_item_t {}, vxge_queue_destroy(). 295221167Sgnn */ 296221167Sgnnvxge_queue_h 297221167Sgnnvxge_queue_create(vxge_hal_device_h devh, 298221167Sgnn u32 pages_initial, 299221167Sgnn u32 pages_max, 300221167Sgnn vxge_queued_f queued_func, 301221167Sgnn void *queued_data) 302221167Sgnn{ 303221167Sgnn vxge_queue_t *queue; 304221167Sgnn __hal_device_t *hldev = (__hal_device_t *) devh; 305221167Sgnn 306221167Sgnn vxge_assert(devh != NULL); 307221167Sgnn 308221167Sgnn vxge_hal_trace_log_queue("==> %s:%s:%d", 309221167Sgnn __FILE__, __func__, __LINE__); 310221167Sgnn 311221167Sgnn vxge_hal_trace_log_queue( 312221167Sgnn "devh = 0x"VXGE_OS_STXFMT", pages_initial = %d, " 313221167Sgnn "pages_max = %d, queued_func = 0x"VXGE_OS_STXFMT", " 314221167Sgnn "queued_data = 0x"VXGE_OS_STXFMT, (ptr_t) devh, pages_initial, 315221167Sgnn pages_max, (ptr_t) queued_func, (ptr_t) queued_data); 316221167Sgnn 317221167Sgnn if ((queue = (vxge_queue_t *) vxge_os_malloc(hldev->header.pdev, 318221167Sgnn sizeof(vxge_queue_t))) == NULL) { 319221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = %d", 320221167Sgnn __FILE__, __func__, __LINE__, VXGE_QUEUE_OUT_OF_MEMORY); 321221167Sgnn return (NULL); 322221167Sgnn } 323221167Sgnn 324221167Sgnn queue->queued_func = queued_func; 325221167Sgnn queue->queued_data = queued_data; 326221167Sgnn queue->hldev = devh; 327221167Sgnn queue->pdev = hldev->header.pdev; 328221167Sgnn queue->irqh = hldev->header.irqh; 329221167Sgnn queue->pages_current = pages_initial; 330221167Sgnn queue->start_ptr = vxge_os_malloc(hldev->header.pdev, 331221167Sgnn queue->pages_current * VXGE_QUEUE_BUF_SIZE); 332221167Sgnn if (queue->start_ptr == NULL) { 333221167Sgnn vxge_os_free(hldev->header.pdev, queue, sizeof(vxge_queue_t)); 334221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = %d", 335221167Sgnn __FILE__, __func__, __LINE__, VXGE_QUEUE_OUT_OF_MEMORY); 336221167Sgnn return (NULL); 337221167Sgnn } 338221167Sgnn queue->head_ptr = queue->tail_ptr = queue->start_ptr; 339221167Sgnn queue->end_ptr = (char *) queue->start_ptr + 340221167Sgnn queue->pages_current * VXGE_QUEUE_BUF_SIZE; 341221167Sgnn vxge_os_spin_lock_init_irq(&queue->lock, queue->irqh); 342221167Sgnn queue->pages_initial = pages_initial; 343221167Sgnn queue->pages_max = pages_max; 344221167Sgnn vxge_list_init(&queue->list_head); 345221167Sgnn 346221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = 0", 347221167Sgnn __FILE__, __func__, __LINE__); 348221167Sgnn 349221167Sgnn return (queue); 350221167Sgnn} 351221167Sgnn 352221167Sgnn/* 353221167Sgnn * vxge_queue_destroy - Destroy vxge_queue_t object. 354221167Sgnn * @queueh: Queue handle. 355221167Sgnn * 356221167Sgnn * Destroy the specified vxge_queue_t object. 357221167Sgnn * 358221167Sgnn * See also: vxge_queue_item_t {}, vxge_queue_create(). 359221167Sgnn */ 360221167Sgnnvoid 361221167Sgnnvxge_queue_destroy(vxge_queue_h queueh) 362221167Sgnn{ 363221167Sgnn vxge_queue_t *queue = (vxge_queue_t *) queueh; 364221167Sgnn __hal_device_t *hldev; 365221167Sgnn 366221167Sgnn vxge_assert(queueh != NULL); 367221167Sgnn 368221167Sgnn hldev = (__hal_device_t *) queue->hldev; 369221167Sgnn 370221167Sgnn vxge_hal_trace_log_queue("==> %s:%s:%d", 371221167Sgnn __FILE__, __func__, __LINE__); 372221167Sgnn 373221167Sgnn vxge_hal_trace_log_queue("queueh = 0x"VXGE_OS_STXFMT, 374221167Sgnn (ptr_t) queueh); 375221167Sgnn 376221167Sgnn vxge_os_spin_lock_destroy_irq(&queue->lock, queue->irqh); 377221167Sgnn if (!vxge_list_is_empty(&queue->list_head)) { 378221167Sgnn vxge_hal_trace_log_queue("destroying non-empty queue 0x" 379221167Sgnn VXGE_OS_STXFMT, (ptr_t) queue); 380221167Sgnn } 381221167Sgnn vxge_os_free(queue->pdev, queue->start_ptr, queue->pages_current * 382221167Sgnn VXGE_QUEUE_BUF_SIZE); 383221167Sgnn 384221167Sgnn vxge_os_free(queue->pdev, queue, sizeof(vxge_queue_t)); 385221167Sgnn 386221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = 0", 387221167Sgnn __FILE__, __func__, __LINE__); 388221167Sgnn} 389221167Sgnn 390221167Sgnn/* 391221167Sgnn * vxge_io_queue_grow - Dynamically increases the size of the queue. 392221167Sgnn * @queueh: Queue handle. 393221167Sgnn * 394221167Sgnn * This function is called in the case of no slot avaialble in the queue 395221167Sgnn * to accomodate the newly received event. 396221167Sgnn * Note that queue cannot grow beyond the max size specified for the 397221167Sgnn * queue. 398221167Sgnn * 399221167Sgnn * Returns VXGE_QUEUE_OK: On success. 400221167Sgnn * VXGE_QUEUE_OUT_OF_MEMORY : No memory is available. 401221167Sgnn */ 402221167Sgnnvxge_queue_status_e 403221167Sgnnvxge_io_queue_grow(vxge_queue_h queueh) 404221167Sgnn{ 405221167Sgnn vxge_queue_t *queue = (vxge_queue_t *) queueh; 406221167Sgnn __hal_device_t *hldev; 407221167Sgnn void *newbuf, *oldbuf; 408221167Sgnn vxge_list_t *item; 409221167Sgnn vxge_queue_item_t *elem; 410221167Sgnn 411221167Sgnn vxge_assert(queueh != NULL); 412221167Sgnn 413221167Sgnn hldev = (__hal_device_t *) queue->hldev; 414221167Sgnn 415221167Sgnn vxge_hal_trace_log_queue("==> %s:%s:%d", 416221167Sgnn __FILE__, __func__, __LINE__); 417221167Sgnn 418221167Sgnn vxge_hal_trace_log_queue("queueh = 0x"VXGE_OS_STXFMT, 419221167Sgnn (ptr_t) queueh); 420221167Sgnn 421221167Sgnn vxge_hal_info_log_queue("queue 0x"VXGE_OS_STXFMT":%d is growing", 422221167Sgnn (ptr_t) queue, queue->pages_current); 423221167Sgnn 424221167Sgnn newbuf = vxge_os_malloc(queue->pdev, 425221167Sgnn (queue->pages_current + 1) * VXGE_QUEUE_BUF_SIZE); 426221167Sgnn if (newbuf == NULL) { 427221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = %d", 428221167Sgnn __FILE__, __func__, __LINE__, VXGE_QUEUE_OUT_OF_MEMORY); 429221167Sgnn return (VXGE_QUEUE_OUT_OF_MEMORY); 430221167Sgnn } 431221167Sgnn 432221167Sgnn vxge_os_memcpy(newbuf, queue->start_ptr, 433221167Sgnn queue->pages_current * VXGE_QUEUE_BUF_SIZE); 434221167Sgnn oldbuf = queue->start_ptr; 435221167Sgnn 436221167Sgnn /* adjust queue sizes */ 437221167Sgnn queue->start_ptr = newbuf; 438221167Sgnn queue->end_ptr = (char *) newbuf + 439221167Sgnn (queue->pages_current + 1) * VXGE_QUEUE_BUF_SIZE; 440221167Sgnn queue->tail_ptr = (char *) newbuf + 441221167Sgnn /* LINTED */ 442221167Sgnn ((char *) queue->tail_ptr - (char *) oldbuf); 443221167Sgnn queue->head_ptr = (char *) newbuf + 444221167Sgnn /* LINTED */ 445221167Sgnn ((char *) queue->head_ptr - (char *) oldbuf); 446221167Sgnn vxge_assert(!vxge_list_is_empty(&queue->list_head)); 447221167Sgnn queue->list_head.next = (vxge_list_t *) (void *)((char *) newbuf + 448221167Sgnn /* LINTED */ 449221167Sgnn ((char *) queue->list_head.next - (char *) oldbuf)); 450221167Sgnn queue->list_head.prev = (vxge_list_t *) (void *)((char *) newbuf + 451221167Sgnn /* LINTED */ 452221167Sgnn ((char *) queue->list_head.prev - (char *) oldbuf)); 453221167Sgnn /* adjust queue list */ 454221167Sgnn vxge_list_for_each(item, &queue->list_head) { 455221167Sgnn elem = vxge_container_of(item, vxge_queue_item_t, item); 456221167Sgnn if (elem->item.next != &queue->list_head) { 457221167Sgnn elem->item.next = 458221167Sgnn (vxge_list_t *) (void *)((char *) newbuf + 459221167Sgnn /* LINTED */ 460221167Sgnn ((char *) elem->item.next - (char *) oldbuf)); 461221167Sgnn } 462221167Sgnn if (elem->item.prev != &queue->list_head) { 463221167Sgnn elem->item.prev = 464221167Sgnn (vxge_list_t *) (void *)((char *) newbuf + 465221167Sgnn /* LINTED */ 466221167Sgnn ((char *) elem->item.prev - (char *) oldbuf)); 467221167Sgnn } 468221167Sgnn } 469221167Sgnn vxge_os_free(queue->pdev, oldbuf, 470221167Sgnn queue->pages_current * VXGE_QUEUE_BUF_SIZE); 471221167Sgnn queue->pages_current++; 472221167Sgnn 473221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = 0", 474221167Sgnn __FILE__, __func__, __LINE__); 475221167Sgnn return (VXGE_QUEUE_OK); 476221167Sgnn} 477221167Sgnn 478221167Sgnn/* 479221167Sgnn * vxge_queue_consume - Dequeue an item from the specified queue. 480221167Sgnn * @queueh: Queue handle. 481221167Sgnn * @data_max_size: Maximum expected size of the item. 482221167Sgnn * @item: Memory area into which the item is _copied_ upon return 483221167Sgnn * from the function. 484221167Sgnn * 485221167Sgnn * Dequeue an item from the queue. The caller is required to provide 486221167Sgnn * enough space for the item. 487221167Sgnn * 488221167Sgnn * Returns: VXGE_QUEUE_OK - success. 489221167Sgnn * VXGE_QUEUE_IS_EMPTY - Queue is empty. 490221167Sgnn * VXGE_QUEUE_NOT_ENOUGH_SPACE - Requested item size(@data_max_size) 491221167Sgnn * is too small to accomodate an item from the queue. 492221167Sgnn * 493221167Sgnn * See also: vxge_queue_item_t {}, vxge_queue_produce(). 494221167Sgnn */ 495221167Sgnnvxge_queue_status_e 496221167Sgnnvxge_queue_consume(vxge_queue_h queueh, 497221167Sgnn u32 data_max_size, 498221167Sgnn vxge_queue_item_t *item) 499221167Sgnn{ 500221167Sgnn vxge_queue_t *queue = (vxge_queue_t *) queueh; 501221167Sgnn __hal_device_t *hldev; 502221167Sgnn unsigned long flags = 0; 503221167Sgnn vxge_queue_status_e status; 504221167Sgnn 505221167Sgnn vxge_assert(queueh != NULL); 506221167Sgnn 507221167Sgnn hldev = (__hal_device_t *) queue->hldev; 508221167Sgnn 509221167Sgnn vxge_hal_trace_log_queue("==> %s:%s:%d", 510221167Sgnn __FILE__, __func__, __LINE__); 511221167Sgnn 512221167Sgnn vxge_hal_trace_log_queue( 513221167Sgnn "queueh = 0x"VXGE_OS_STXFMT", data_max_size = %d, " 514221167Sgnn "item = 0x"VXGE_OS_STXFMT, (ptr_t) queueh, 515221167Sgnn data_max_size, (ptr_t) item); 516221167Sgnn 517221167Sgnn vxge_os_spin_lock_irq(&queue->lock, flags); 518221167Sgnn status = __queue_consume(queue, data_max_size, item); 519221167Sgnn vxge_os_spin_unlock_irq(&queue->lock, flags); 520221167Sgnn 521221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = %d", 522221167Sgnn __FILE__, __func__, __LINE__, status); 523221167Sgnn return (status); 524221167Sgnn} 525221167Sgnn 526221167Sgnn 527221167Sgnn/* 528221167Sgnn * vxge_queue_flush - Flush, or empty, the queue. 529221167Sgnn * @queueh: Queue handle. 530221167Sgnn * 531221167Sgnn * Flush the queue, i.e. make it empty by consuming all events 532221167Sgnn * without invoking the event processing logic (callbacks, etc.) 533221167Sgnn */ 534221167Sgnnvoid 535221167Sgnnvxge_queue_flush(vxge_queue_h queueh) 536221167Sgnn{ 537221167Sgnn unsigned char item_buf[sizeof(vxge_queue_item_t) + 538221167Sgnn VXGE_DEFAULT_EVENT_MAX_DATA_SIZE]; 539221167Sgnn vxge_queue_item_t *item = (vxge_queue_item_t *) (void *)item_buf; 540221167Sgnn vxge_queue_t *queue = (vxge_queue_t *) queueh; 541221167Sgnn __hal_device_t *hldev; 542221167Sgnn 543221167Sgnn vxge_assert(queueh != NULL); 544221167Sgnn 545221167Sgnn hldev = (__hal_device_t *) queue->hldev; 546221167Sgnn 547221167Sgnn vxge_hal_trace_log_queue("==> %s:%s:%d", 548221167Sgnn __FILE__, __func__, __LINE__); 549221167Sgnn 550221167Sgnn vxge_hal_trace_log_queue("queueh = 0x"VXGE_OS_STXFMT, 551221167Sgnn (ptr_t) queueh); 552221167Sgnn 553221167Sgnn /* flush queue by consuming all enqueued items */ 554221167Sgnn while (vxge_queue_consume(queueh, VXGE_DEFAULT_EVENT_MAX_DATA_SIZE, 555221167Sgnn item) != VXGE_QUEUE_IS_EMPTY) { 556221167Sgnn /* do nothing */ 557221167Sgnn vxge_hal_trace_log_queue("item 0x"VXGE_OS_STXFMT"(%d) flushed", 558221167Sgnn (ptr_t) item, item->event_type); 559221167Sgnn } 560221167Sgnn 561221167Sgnn (void) vxge_queue_get_reset_critical(queueh); 562221167Sgnn 563221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = 0", 564221167Sgnn __FILE__, __func__, __LINE__); 565221167Sgnn} 566221167Sgnn 567221167Sgnn/* 568221167Sgnn * vxge_queue_get_reset_critical - Check for critical events in the queue, 569221167Sgnn * @queueh: Queue handle. 570221167Sgnn * 571221167Sgnn * Check for critical event(s) in the queue, and reset the 572221167Sgnn * "has-critical-event" flag upon return. 573221167Sgnn * Returns: 1 - if the queue contains atleast one critical event. 574221167Sgnn * 0 - If there are no critical events in the queue. 575221167Sgnn */ 576221167Sgnnu32 577221167Sgnnvxge_queue_get_reset_critical(vxge_queue_h queueh) 578221167Sgnn{ 579221167Sgnn vxge_queue_t *queue = (vxge_queue_t *) queueh; 580221167Sgnn int c = queue->has_critical_event; 581221167Sgnn __hal_device_t *hldev; 582221167Sgnn 583221167Sgnn vxge_assert(queueh != NULL); 584221167Sgnn 585221167Sgnn hldev = (__hal_device_t *) queue->hldev; 586221167Sgnn 587221167Sgnn vxge_hal_trace_log_queue("==> %s:%s:%d", 588221167Sgnn __FILE__, __func__, __LINE__); 589221167Sgnn 590221167Sgnn vxge_hal_trace_log_queue("queueh = 0x"VXGE_OS_STXFMT, 591221167Sgnn (ptr_t) queueh); 592221167Sgnn 593221167Sgnn queue->has_critical_event = 0; 594221167Sgnn 595221167Sgnn vxge_hal_trace_log_queue("<== %s:%s:%d Result = 0", 596221167Sgnn __FILE__, __func__, __LINE__); 597221167Sgnn return (c); 598221167Sgnn} 599