xref: /onnv-gate/usr/src/uts/common/io/xge/hal/xgehal/xge-queue.c (revision 6937:a5e2c8b5c817)
11256Syl150051 /*
21256Syl150051  * CDDL HEADER START
31256Syl150051  *
41256Syl150051  * The contents of this file are subject to the terms of the
51256Syl150051  * Common Development and Distribution License (the "License").
61256Syl150051  * You may not use this file except in compliance with the License.
71256Syl150051  *
81256Syl150051  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91256Syl150051  * or http://www.opensolaris.org/os/licensing.
101256Syl150051  * See the License for the specific language governing permissions
111256Syl150051  * and limitations under the License.
121256Syl150051  *
131256Syl150051  * When distributing Covered Code, include this CDDL HEADER in each
141256Syl150051  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151256Syl150051  * If applicable, add the following below this CDDL HEADER, with the
161256Syl150051  * fields enclosed by brackets "[]" replaced with your own identifying
171256Syl150051  * information: Portions Copyright [yyyy] [name of copyright owner]
181256Syl150051  *
191256Syl150051  * CDDL HEADER END
201256Syl150051  *
213115Syl150051  * Copyright (c) 2002-2006 Neterion, Inc.
221256Syl150051  */
231256Syl150051 
241256Syl150051 #include "xge-queue.h"
251256Syl150051 
261256Syl150051 /**
271256Syl150051  * xge_queue_item_data - Get item's data.
281256Syl150051  * @item: Queue item.
291256Syl150051  *
301256Syl150051  * Returns:  item data(variable size). Note that xge_queue_t
311256Syl150051  * contains items comprized of a fixed xge_queue_item_t "header"
321256Syl150051  * and a variable size data. This function returns the variable
331256Syl150051  * user-defined portion of the queue item.
341256Syl150051  */
xge_queue_item_data(xge_queue_item_t * item)351256Syl150051 void* xge_queue_item_data(xge_queue_item_t *item)
361256Syl150051 {
371256Syl150051 	return (char *)item + sizeof(xge_queue_item_t);
381256Syl150051 }
391256Syl150051 
401256Syl150051 /*
411256Syl150051  * __queue_consume - (Lockless) dequeue an item from the specified queue.
421256Syl150051  *
431256Syl150051  * @queue: Event queue.
441256Syl150051  * See xge_queue_consume().
451256Syl150051  */
461256Syl150051 static xge_queue_status_e
__queue_consume(xge_queue_t * queue,int data_max_size,xge_queue_item_t * item)471256Syl150051 __queue_consume(xge_queue_t *queue, int data_max_size, xge_queue_item_t *item)
481256Syl150051 {
491256Syl150051 	int real_size;
501256Syl150051 	xge_queue_item_t *elem;
511256Syl150051 
521256Syl150051 	if (xge_list_is_empty(&queue->list_head))
531256Syl150051 		return XGE_QUEUE_IS_EMPTY;
541256Syl150051 
551256Syl150051 	elem = (xge_queue_item_t *)queue->list_head.next;
561256Syl150051 	if (elem->data_size > data_max_size)
571256Syl150051 		return XGE_QUEUE_NOT_ENOUGH_SPACE;
581256Syl150051 
591256Syl150051 	xge_list_remove(&elem->item);
601256Syl150051 	real_size = elem->data_size + sizeof(xge_queue_item_t);
611256Syl150051 	if (queue->head_ptr == elem) {
621256Syl150051 		queue->head_ptr = (char *)queue->head_ptr + real_size;
631256Syl150051 		xge_debug_queue(XGE_TRACE,
641256Syl150051 			"event_type: %d removing from the head: "
653115Syl150051 			"0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT
663115Syl150051 			":0x"XGE_OS_LLXFMT" elem 0x"XGE_OS_LLXFMT" length %d",
671256Syl150051 			elem->event_type,
681256Syl150051 			(u64)(ulong_t)queue->start_ptr,
691256Syl150051 			(u64)(ulong_t)queue->head_ptr,
701256Syl150051 			(u64)(ulong_t)queue->tail_ptr,
711256Syl150051 			(u64)(ulong_t)queue->end_ptr,
721256Syl150051 			(u64)(ulong_t)elem,
731256Syl150051 			real_size);
741256Syl150051 	} else if ((char *)queue->tail_ptr - real_size == (char*)elem) {
751256Syl150051 		queue->tail_ptr = (char *)queue->tail_ptr - real_size;
761256Syl150051 		xge_debug_queue(XGE_TRACE,
771256Syl150051 			"event_type: %d removing from the tail: "
783115Syl150051 			"0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT
793115Syl150051 			":0x"XGE_OS_LLXFMT" elem 0x"XGE_OS_LLXFMT" length %d",
801256Syl150051 			elem->event_type,
811256Syl150051 			(u64)(ulong_t)queue->start_ptr,
821256Syl150051 			(u64)(ulong_t)queue->head_ptr,
831256Syl150051 			(u64)(ulong_t)queue->tail_ptr,
841256Syl150051 			(u64)(ulong_t)queue->end_ptr,
851256Syl150051 			(u64)(ulong_t)elem,
861256Syl150051 			real_size);
871256Syl150051 	} else {
881256Syl150051 		xge_debug_queue(XGE_TRACE,
891256Syl150051 			"event_type: %d removing from the list: "
903115Syl150051 			"0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT
913115Syl150051 			":0x"XGE_OS_LLXFMT" elem 0x"XGE_OS_LLXFMT" length %d",
921256Syl150051 			elem->event_type,
931256Syl150051 			(u64)(ulong_t)queue->start_ptr,
941256Syl150051 			(u64)(ulong_t)queue->head_ptr,
951256Syl150051 			(u64)(ulong_t)queue->tail_ptr,
961256Syl150051 			(u64)(ulong_t)queue->end_ptr,
971256Syl150051 			(u64)(ulong_t)elem,
981256Syl150051 			real_size);
991256Syl150051 	}
1001256Syl150051 	xge_assert(queue->tail_ptr >= queue->head_ptr);
1011256Syl150051 	xge_assert(queue->tail_ptr >= queue->start_ptr &&
1021256Syl150051 		    queue->tail_ptr <= queue->end_ptr);
1031256Syl150051 	xge_assert(queue->head_ptr >= queue->start_ptr &&
1041256Syl150051 		    queue->head_ptr < queue->end_ptr);
1051256Syl150051 	xge_os_memcpy(item, elem, sizeof(xge_queue_item_t));
1061256Syl150051 	xge_os_memcpy(xge_queue_item_data(item), xge_queue_item_data(elem),
1071256Syl150051 		    elem->data_size);
1081256Syl150051 
1091256Syl150051 	if (xge_list_is_empty(&queue->list_head)) {
1101256Syl150051 		/* reset buffer pointers just to be clean */
1111256Syl150051 		queue->head_ptr = queue->tail_ptr = queue->start_ptr;
1121256Syl150051 	}
1131256Syl150051 	return XGE_QUEUE_OK;
1141256Syl150051 }
1151256Syl150051 
1161256Syl150051 /**
1171256Syl150051  * xge_queue_produce - Enqueue an item (see xge_queue_item_t{})
1181256Syl150051  *                      into the specified queue.
1191256Syl150051  * @queueh: Queue handle.
1201256Syl150051  * @event_type: Event type. One of the enumerated event types
1211256Syl150051  *              that both consumer and producer "understand".
1221256Syl150051  *              For an example, please refer to xge_hal_event_e.
1231256Syl150051  * @context: Opaque (void*) "context", for instance event producer object.
1241256Syl150051  * @is_critical: For critical event, e.g. ECC.
1251256Syl150051  * @data_size: Size of the @data.
1261256Syl150051  * @data: User data of variable @data_size that is _copied_ into
1271256Syl150051  *        the new queue item (see xge_queue_item_t{}). Upon return
1281256Syl150051  *        from the call the @data memory can be re-used or released.
1291256Syl150051  *
1301256Syl150051  * Enqueue a new item.
1311256Syl150051  *
1321256Syl150051  * Returns: XGE_QUEUE_OK - success.
1331256Syl150051  * XGE_QUEUE_IS_FULL - Queue is full.
1341256Syl150051  * XGE_QUEUE_OUT_OF_MEMORY - Memory allocation failed.
1351256Syl150051  *
1361256Syl150051  * See also: xge_queue_item_t{}, xge_queue_consume().
1371256Syl150051  */
1381256Syl150051 xge_queue_status_e
xge_queue_produce(xge_queue_h queueh,int event_type,void * context,int is_critical,const int data_size,void * data)1391256Syl150051 xge_queue_produce(xge_queue_h queueh, int event_type, void *context,
1401256Syl150051 		int is_critical, const int data_size, void *data)
1411256Syl150051 {
1421256Syl150051 	xge_queue_t *queue = (xge_queue_t *)queueh;
1431256Syl150051 	int real_size = data_size + sizeof(xge_queue_item_t);
1441256Syl150051 	xge_queue_item_t *elem;
1451256Syl150051 	unsigned long flags = 0;
1461256Syl150051 
1471256Syl150051 	xge_assert(real_size <= XGE_QUEUE_BUF_SIZE);
1481256Syl150051 
1491256Syl150051 	xge_os_spin_lock_irq(&queue->lock, flags);
1501256Syl150051 
1511256Syl150051 	if (is_critical && !queue->has_critical_event)  {
1521256Syl150051 		unsigned char item_buf[sizeof(xge_queue_item_t) +
1531256Syl150051 				XGE_DEFAULT_EVENT_MAX_DATA_SIZE];
1541256Syl150051 		xge_queue_item_t *item = (xge_queue_item_t *)(void *)item_buf;
155*6937Sxw161283     xge_os_memzero(item_buf, (sizeof(xge_queue_item_t) +
156*6937Sxw161283                              XGE_DEFAULT_EVENT_MAX_DATA_SIZE));
157*6937Sxw161283 
1581256Syl150051 	        while (__queue_consume(queue,
1591256Syl150051 				       XGE_DEFAULT_EVENT_MAX_DATA_SIZE,
1601256Syl150051 				       item) != XGE_QUEUE_IS_EMPTY)
1611256Syl150051 		        ; /* do nothing */
1621256Syl150051 	}
1631256Syl150051 
1641256Syl150051 try_again:
1651256Syl150051 	if ((char *)queue->tail_ptr + real_size <= (char *)queue->end_ptr) {
1663115Syl150051         elem = (xge_queue_item_t *) queue->tail_ptr;
1671256Syl150051 		queue->tail_ptr = (void *)((char *)queue->tail_ptr + real_size);
1681256Syl150051 		xge_debug_queue(XGE_TRACE,
1691256Syl150051 			"event_type: %d adding to the tail: "
1703115Syl150051 			"0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT
1713115Syl150051 			":0x"XGE_OS_LLXFMT" elem 0x"XGE_OS_LLXFMT" length %d",
1721256Syl150051 			event_type,
1731256Syl150051 			(u64)(ulong_t)queue->start_ptr,
1741256Syl150051 			(u64)(ulong_t)queue->head_ptr,
1751256Syl150051 			(u64)(ulong_t)queue->tail_ptr,
1761256Syl150051 			(u64)(ulong_t)queue->end_ptr,
1771256Syl150051 			(u64)(ulong_t)elem,
1781256Syl150051 			real_size);
1791256Syl150051 	} else if ((char *)queue->head_ptr - real_size >=
1801256Syl150051 					(char *)queue->start_ptr) {
1813115Syl150051         elem = (xge_queue_item_t *) ((char *)queue->head_ptr - real_size);
1821256Syl150051 		queue->head_ptr = elem;
1831256Syl150051 		xge_debug_queue(XGE_TRACE,
1841256Syl150051 			"event_type: %d adding to the head: "
1853115Syl150051 			"0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT":0x"XGE_OS_LLXFMT
1863115Syl150051 			":0x"XGE_OS_LLXFMT" length %d",
1871256Syl150051 			event_type,
1881256Syl150051 			(u64)(ulong_t)queue->start_ptr,
1891256Syl150051 			(u64)(ulong_t)queue->head_ptr,
1901256Syl150051 			(u64)(ulong_t)queue->tail_ptr,
1911256Syl150051 			(u64)(ulong_t)queue->end_ptr,
1921256Syl150051 			real_size);
1931256Syl150051 	} else {
1941256Syl150051 		xge_queue_status_e status;
1951256Syl150051 
1961256Syl150051 		if (queue->pages_current >= queue->pages_max) {
1971256Syl150051 			xge_os_spin_unlock_irq(&queue->lock, flags);
1981256Syl150051 			return XGE_QUEUE_IS_FULL;
1991256Syl150051 		}
2001256Syl150051 
201*6937Sxw161283 		if (queue->has_critical_event) {
202*6937Sxw161283    		xge_os_spin_unlock_irq(&queue->lock, flags);
2031256Syl150051 			return XGE_QUEUE_IS_FULL;
204*6937Sxw161283     }
2051256Syl150051 
2061256Syl150051 		/* grow */
2071256Syl150051 		status = __io_queue_grow(queueh);
2081256Syl150051 		if (status != XGE_QUEUE_OK) {
2091256Syl150051 			xge_os_spin_unlock_irq(&queue->lock, flags);
2101256Syl150051 			return status;
2111256Syl150051 		}
2121256Syl150051 
2131256Syl150051 		goto try_again;
2141256Syl150051 	}
2151256Syl150051 	xge_assert(queue->tail_ptr >= queue->head_ptr);
2161256Syl150051 	xge_assert(queue->tail_ptr >= queue->start_ptr &&
2171256Syl150051 		    queue->tail_ptr <= queue->end_ptr);
2181256Syl150051 	xge_assert(queue->head_ptr >= queue->start_ptr &&
2191256Syl150051 		    queue->head_ptr < queue->end_ptr);
2201256Syl150051 	elem->data_size = data_size;
2213115Syl150051     elem->event_type = (xge_hal_event_e) event_type;
2221256Syl150051 	elem->is_critical = is_critical;
2231256Syl150051 	if (is_critical)
2241256Syl150051 	        queue->has_critical_event = 1;
2251256Syl150051 	elem->context = context;
2261256Syl150051 	xge_os_memcpy(xge_queue_item_data(elem), data, data_size);
2271256Syl150051 	xge_list_insert_before(&elem->item, &queue->list_head);
2281256Syl150051 	xge_os_spin_unlock_irq(&queue->lock, flags);
2291256Syl150051 
2301256Syl150051 	/* no lock taken! */
2311256Syl150051 	queue->queued_func(queue->queued_data, event_type);
2321256Syl150051 
2331256Syl150051 	return XGE_QUEUE_OK;
2341256Syl150051 }
2351256Syl150051 
2361256Syl150051 
2371256Syl150051 /**
2381256Syl150051  * xge_queue_create - Create protected first-in-first-out queue.
2391256Syl150051  * @pdev: PCI device handle.
2401256Syl150051  * @irqh: PCI device IRQ handle.
2411256Syl150051  * @pages_initial: Number of pages to be initially allocated at the
2421256Syl150051  * time of queue creation.
2431256Syl150051  * @pages_max: Max number of pages that can be allocated in the queue.
2441256Syl150051  * @queued: Optional callback function to be called each time a new item is
2451256Syl150051  * added to the queue.
2461256Syl150051  * @queued_data: Argument to the callback function.
2471256Syl150051  *
2481256Syl150051  * Create protected (fifo) queue.
2491256Syl150051  *
2501256Syl150051  * Returns: Pointer to xge_queue_t structure,
2511256Syl150051  * NULL - on failure.
2521256Syl150051  *
2531256Syl150051  * See also: xge_queue_item_t{}, xge_queue_destroy().
2541256Syl150051  */
2551256Syl150051 xge_queue_h
xge_queue_create(pci_dev_h pdev,pci_irq_h irqh,int pages_initial,int pages_max,xge_queued_f queued,void * queued_data)2561256Syl150051 xge_queue_create(pci_dev_h pdev, pci_irq_h irqh, int pages_initial,
2571256Syl150051 		int pages_max, xge_queued_f queued, void *queued_data)
2581256Syl150051 {
2591256Syl150051 	xge_queue_t *queue;
2601256Syl150051 
2613115Syl150051     if ((queue = (xge_queue_t *) xge_os_malloc(pdev, sizeof(xge_queue_t))) == NULL)
2621256Syl150051 		return NULL;
2631256Syl150051 
2641256Syl150051 	queue->queued_func = queued;
2651256Syl150051 	queue->queued_data = queued_data;
2661256Syl150051 	queue->pdev = pdev;
2671256Syl150051 	queue->irqh = irqh;
2681256Syl150051 	queue->pages_current = pages_initial;
2691256Syl150051 	queue->start_ptr = xge_os_malloc(pdev, queue->pages_current *
2701256Syl150051 	                               XGE_QUEUE_BUF_SIZE);
2711256Syl150051 	if (queue->start_ptr == NULL) {
2721256Syl150051 		xge_os_free(pdev, queue, sizeof(xge_queue_t));
2731256Syl150051 		return NULL;
2741256Syl150051 	}
2751256Syl150051 	queue->head_ptr = queue->tail_ptr = queue->start_ptr;
2761256Syl150051 	queue->end_ptr = (char *)queue->start_ptr +
2771256Syl150051 		queue->pages_current * XGE_QUEUE_BUF_SIZE;
2781256Syl150051 	xge_os_spin_lock_init_irq(&queue->lock, irqh);
2791256Syl150051 	queue->pages_initial = pages_initial;
2801256Syl150051 	queue->pages_max = pages_max;
2811256Syl150051 	xge_list_init(&queue->list_head);
2821256Syl150051 
2831256Syl150051 	return queue;
2841256Syl150051 }
2851256Syl150051 
2861256Syl150051 /**
2871256Syl150051  * xge_queue_destroy - Destroy xge_queue_t object.
2881256Syl150051  * @queueh: Queue handle.
2891256Syl150051  *
2901256Syl150051  * Destroy the specified xge_queue_t object.
2911256Syl150051  *
2921256Syl150051  * See also: xge_queue_item_t{}, xge_queue_create().
2931256Syl150051  */
xge_queue_destroy(xge_queue_h queueh)2941256Syl150051 void xge_queue_destroy(xge_queue_h queueh)
2951256Syl150051 {
2961256Syl150051 	xge_queue_t *queue = (xge_queue_t *)queueh;
297*6937Sxw161283 	xge_os_spin_lock_destroy_irq(&queue->lock, queue->irqh);
2981256Syl150051 	if (!xge_list_is_empty(&queue->list_head)) {
2993115Syl150051 		xge_debug_queue(XGE_ERR, "destroying non-empty queue 0x"
3003115Syl150051 				XGE_OS_LLXFMT, (u64)(ulong_t)queue);
3011256Syl150051 	}
3021256Syl150051 	xge_os_free(queue->pdev, queue->start_ptr, queue->pages_current *
3031256Syl150051 	          XGE_QUEUE_BUF_SIZE);
3041256Syl150051 
3051256Syl150051 	xge_os_free(queue->pdev, queue, sizeof(xge_queue_t));
3061256Syl150051 }
3071256Syl150051 
3081256Syl150051 /*
3091256Syl150051  * __io_queue_grow - Dynamically increases the size of the queue.
3101256Syl150051  * @queueh: Queue handle.
3111256Syl150051  *
3121256Syl150051  * This function is called in the case of no slot avaialble in the queue
3131256Syl150051  * to accomodate the newly received event.
3141256Syl150051  * Note that queue cannot grow beyond the max size specified for the
3151256Syl150051  * queue.
3161256Syl150051  *
3171256Syl150051  * Returns XGE_QUEUE_OK: On success.
3181256Syl150051  * XGE_QUEUE_OUT_OF_MEMORY : No memory is available.
3191256Syl150051  */
3201256Syl150051 xge_queue_status_e
__io_queue_grow(xge_queue_h queueh)3211256Syl150051 __io_queue_grow(xge_queue_h queueh)
3221256Syl150051 {
3231256Syl150051 	xge_queue_t *queue = (xge_queue_t *)queueh;
3241256Syl150051 	void *newbuf, *oldbuf;
3251256Syl150051 	xge_list_t *item;
3261256Syl150051 	xge_queue_item_t *elem;
3271256Syl150051 
3283115Syl150051 	xge_debug_queue(XGE_TRACE, "queue 0x"XGE_OS_LLXFMT":%d is growing",
3291256Syl150051 			 (u64)(ulong_t)queue, queue->pages_current);
3301256Syl150051 
3311256Syl150051 	newbuf = xge_os_malloc(queue->pdev,
3321256Syl150051 	        (queue->pages_current + 1) * XGE_QUEUE_BUF_SIZE);
3331256Syl150051 	if (newbuf == NULL)
3341256Syl150051 		return XGE_QUEUE_OUT_OF_MEMORY;
3351256Syl150051 
3361256Syl150051 	xge_os_memcpy(newbuf, queue->start_ptr,
3371256Syl150051 	       queue->pages_current * XGE_QUEUE_BUF_SIZE);
3381256Syl150051 	oldbuf = queue->start_ptr;
3391256Syl150051 
3401256Syl150051 	/* adjust queue sizes */
3411256Syl150051 	queue->start_ptr = newbuf;
3421256Syl150051 	queue->end_ptr = (char *)newbuf +
3431256Syl150051 			(queue->pages_current + 1) * XGE_QUEUE_BUF_SIZE;
3441256Syl150051 	queue->tail_ptr = (char *)newbuf + ((char *)queue->tail_ptr -
3451256Syl150051 					    (char *)oldbuf);
3461256Syl150051 	queue->head_ptr = (char *)newbuf + ((char *)queue->head_ptr -
3471256Syl150051 					    (char *)oldbuf);
3481256Syl150051 	xge_assert(!xge_list_is_empty(&queue->list_head));
3491256Syl150051 	queue->list_head.next = (xge_list_t *) (void *)((char *)newbuf +
3501256Syl150051 			((char *)queue->list_head.next - (char *)oldbuf));
3511256Syl150051 	queue->list_head.prev = (xge_list_t *) (void *)((char *)newbuf +
3521256Syl150051 			((char *)queue->list_head.prev - (char *)oldbuf));
3531256Syl150051 	/* adjust queue list */
3541256Syl150051 	xge_list_for_each(item, &queue->list_head) {
3551256Syl150051 		elem = xge_container_of(item, xge_queue_item_t, item);
3561256Syl150051 		if (elem->item.next != &queue->list_head) {
3571256Syl150051 			elem->item.next =
3581256Syl150051 				(xge_list_t*)(void *)((char *)newbuf +
3591256Syl150051 				 ((char *)elem->item.next - (char *)oldbuf));
3601256Syl150051 		}
3611256Syl150051 		if (elem->item.prev != &queue->list_head) {
3621256Syl150051 			elem->item.prev =
3631256Syl150051 				(xge_list_t*) (void *)((char *)newbuf +
3641256Syl150051 				 ((char *)elem->item.prev - (char *)oldbuf));
3651256Syl150051 		}
3661256Syl150051 	}
3671256Syl150051 	xge_os_free(queue->pdev, oldbuf,
3681256Syl150051 		  queue->pages_current * XGE_QUEUE_BUF_SIZE);
3691256Syl150051 	queue->pages_current++;
3701256Syl150051 
3711256Syl150051 	return XGE_QUEUE_OK;
3721256Syl150051 }
3731256Syl150051 
3741256Syl150051 /**
3751256Syl150051  * xge_queue_consume - Dequeue an item from the specified queue.
3761256Syl150051  * @queueh: Queue handle.
3771256Syl150051  * @data_max_size: Maximum expected size of the item.
3781256Syl150051  * @item: Memory area into which the item is _copied_ upon return
3791256Syl150051  *        from the function.
3801256Syl150051  *
3811256Syl150051  * Dequeue an item from the queue. The caller is required to provide
3821256Syl150051  * enough space for the item.
3831256Syl150051  *
3841256Syl150051  * Returns: XGE_QUEUE_OK - success.
3851256Syl150051  * XGE_QUEUE_IS_EMPTY - Queue is empty.
3861256Syl150051  * XGE_QUEUE_NOT_ENOUGH_SPACE - Requested item size(@data_max_size)
3871256Syl150051  * is too small to accomodate an item from the queue.
3881256Syl150051  *
3891256Syl150051  * See also: xge_queue_item_t{}, xge_queue_produce().
3901256Syl150051  */
3911256Syl150051 xge_queue_status_e
xge_queue_consume(xge_queue_h queueh,int data_max_size,xge_queue_item_t * item)3921256Syl150051 xge_queue_consume(xge_queue_h queueh, int data_max_size, xge_queue_item_t *item)
3931256Syl150051 {
3941256Syl150051 	xge_queue_t *queue = (xge_queue_t *)queueh;
3951256Syl150051 	unsigned long flags = 0;
3961256Syl150051 	xge_queue_status_e status;
3971256Syl150051 
3981256Syl150051 	xge_os_spin_lock_irq(&queue->lock, flags);
3991256Syl150051 	status = __queue_consume(queue, data_max_size, item);
4001256Syl150051 	xge_os_spin_unlock_irq(&queue->lock, flags);
4011256Syl150051 
4021256Syl150051 	return status;
4031256Syl150051 }
4041256Syl150051 
4051256Syl150051 
4061256Syl150051 /**
4071256Syl150051  * xge_queue_flush - Flush, or empty, the queue.
4081256Syl150051  * @queueh: Queue handle.
4091256Syl150051  *
4101256Syl150051  * Flush the queue, i.e. make it empty by consuming all events
4111256Syl150051  * without invoking the event processing logic (callbacks, etc.)
4121256Syl150051  */
xge_queue_flush(xge_queue_h queueh)4131256Syl150051 void xge_queue_flush(xge_queue_h queueh)
4141256Syl150051 {
4151256Syl150051 	unsigned char item_buf[sizeof(xge_queue_item_t) +
4161256Syl150051 				XGE_DEFAULT_EVENT_MAX_DATA_SIZE];
4171256Syl150051 	xge_queue_item_t *item = (xge_queue_item_t *)(void *)item_buf;
418*6937Sxw161283   xge_os_memzero(item_buf, (sizeof(xge_queue_item_t) +
419*6937Sxw161283                              XGE_DEFAULT_EVENT_MAX_DATA_SIZE));
420*6937Sxw161283 
4211256Syl150051 	/* flush queue by consuming all enqueued items */
4221256Syl150051 	while (xge_queue_consume(queueh,
4231256Syl150051 				    XGE_DEFAULT_EVENT_MAX_DATA_SIZE,
4241256Syl150051 				    item) != XGE_QUEUE_IS_EMPTY) {
4251256Syl150051 		/* do nothing */
4263115Syl150051 		xge_debug_queue(XGE_TRACE, "item "XGE_OS_LLXFMT"(%d) flushed",
4271256Syl150051 				 item, item->event_type);
4281256Syl150051 	}
4291256Syl150051 	(void) __queue_get_reset_critical (queueh);
4301256Syl150051 }
4311256Syl150051 
4321256Syl150051 /*
4331256Syl150051  * __queue_get_reset_critical - Check for critical events in the queue,
4341256Syl150051  * @qh: Queue handle.
4351256Syl150051  *
4361256Syl150051  * Check for critical event(s) in the queue, and reset the
4371256Syl150051  * "has-critical-event" flag upon return.
4381256Syl150051  * Returns: 1 - if the queue contains atleast one critical event.
4391256Syl150051  * 0 - If there are no critical events in the queue.
4401256Syl150051  */
__queue_get_reset_critical(xge_queue_h qh)4411256Syl150051 int __queue_get_reset_critical (xge_queue_h qh) {
4421256Syl150051 	xge_queue_t* queue = (xge_queue_t*)qh;
4431256Syl150051 	int c = queue->has_critical_event;
4441256Syl150051 
4451256Syl150051 	queue->has_critical_event = 0;
4461256Syl150051         return c;
4471256Syl150051 }
448