1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  *  Copyright (c) 2002-2005 Neterion, Inc.
24  *  All right Reserved.
25  *
26  *  FileName :    xge-queue.h
27  *
28  *  Description:  serialized event queue
29  *
30  *  Created:      7 June 2004
31  */
32 
33 #ifndef XGE_QUEUE_H
34 #define XGE_QUEUE_H
35 
36 #include "xge-os-pal.h"
37 #include "xge-defs.h"
38 #include "xge-list.h"
39 
40 #define XGE_QUEUE_BUF_SIZE		0x1000
41 #define XGE_DEFAULT_EVENT_MAX_DATA_SIZE	16
42 
43 /**
44  * enum xge_queue_status_e - Enumerates return codes of the xge_queue
45  * manipulation APIs.
46  * @XGE_QUEUE_IS_FULL: Queue is full, need to grow.
47  * @XGE_QUEUE_IS_EMPTY: Queue is empty.
48  * @XGE_QUEUE_OUT_OF_MEMORY: Out of memory.
49  * @XGE_QUEUE_NOT_ENOUGH_SPACE: Exceeded specified event size,
50  * see xge_queue_consume().
51  * @XGE_QUEUE_OK: Neither one of the codes listed above.
52  *
53  * Enumerates return codes of xge_queue_consume()
54  * and xge_queue_produce() APIs.
55  */
56 typedef enum xge_queue_status_e {
57 	XGE_QUEUE_OK			= 0,
58 	XGE_QUEUE_IS_FULL		= 1,
59 	XGE_QUEUE_IS_EMPTY		= 2,
60 	XGE_QUEUE_OUT_OF_MEMORY	        = 3,
61 	XGE_QUEUE_NOT_ENOUGH_SPACE	= 4
62 } xge_queue_status_e;
63 
64 typedef void* xge_queue_h;
65 
66 /**
67  * struct xge_queue_item_t - Queue item.
68  * @item: List item. Note that the queue is "built" on top of
69  *        the bi-directional linked list.
70  * @event_type: Event type. Includes (but is not restricted to)
71  * one of the xge_hal_event_e{} enumerated types.
72  * @data_size: Size of the enqueued user data. Note that xge_queue_t
73  * items are allowed to have variable sizes.
74  * @is_critical: For critical events, e.g. ECC.
75  * @context: Opaque (void*) "context", for instance event producer object.
76  *
77  * Item of the xge_queue_t{}. The queue is protected
78  * in terms of multi-threaded concurrent access.
79  * See also: xge_queue_t{}.
80  */
81 typedef struct xge_queue_item_t {
82 	xge_list_t	item;
83 	int		event_type;
84 	int		data_size;
85 	int		is_critical;
86 	void		*context;
87 } xge_queue_item_t;
88 
89 /**
90  * function xge_queued_f - Item-enqueued callback.
91  * @data: Per-queue context independent of the event. E.g., device handle.
92  * @event_type: HAL or ULD-defined event type. Note that HAL own
93  *        events are enumerated by xge_hal_event_e{}.
94  *
95  * Per-queue optional callback. If not NULL, called by HAL each
96  * time an event gets added to the queue.
97  */
98 typedef void (*xge_queued_f) (void *data, int event_type);
99 
100 /**
101  * struct xge_queue_t - Protected dynamic queue of variable-size items.
102  * @start_ptr: Points to the start of the queue.
103  * @end_ptr: Points to the end of the queue.
104  * @head_ptr: Points to the head of the queue. It gets changed during queue
105  *            produce/consume operations.
106  * @tail_ptr: Points to the tail of the queue. It gets changed during queue
107  *            produce/consume operations.
108  * @lock: Lock for queue operations(syncronization purpose).
109  * @pages_initial:Number of pages to be initially allocated at the time
110  *		  of queue creation.
111  * @pages_max: Max number of pages that can be allocated in the queue.
112  * @pages_current: Number of pages currently allocated
113  * @list_head: Points to the list of queue elements that are produced, but yet
114  *             to be consumed.
115  * @signal_callback: (TODO)
116  * @pdev: PCI device handle
117  * @irqh: PCI device IRQ handle.
118  * @queued_func: Optional callback function to be called each time a new
119  * item is added to the queue.
120  * @queued_data: Arguments to the callback function.
121  * @has_critical_event: Non-zero, if the queue contains a critical event,
122  * see xge_hal_event_e{}.
123  * Protected dynamically growing queue. The queue is used to support multiple
124  * producer/consumer type scenarios. The queue is a strict FIFO: first come
125  * first served.
126  * Queue users may "produce" (see xge_queue_produce()) and "consume"
127  * (see xge_queue_consume()) items (a.k.a. events) variable sizes.
128  * See also: xge_queue_item_t{}.
129  */
130 typedef struct xge_queue_t {
131 	void				*start_ptr;
132 	void				*end_ptr;
133 	void				*head_ptr;
134 	void				*tail_ptr;
135 	spinlock_t			lock;
136 	unsigned int			pages_initial;
137 	unsigned int			pages_max;
138 	unsigned int			pages_current;
139 	xge_list_t			list_head;
140 	pci_dev_h                       pdev;
141 	pci_irq_h                       irqh;
142 	xge_queued_f			queued_func;
143 	void				*queued_data;
144 	int				has_critical_event;
145 } xge_queue_t;
146 
147 /* ========================== PUBLIC API ================================= */
148 
149 xge_queue_h xge_queue_create(pci_dev_h pdev, pci_irq_h irqh, int pages_initial,
150 		int pages_max, xge_queued_f queued_func, void *queued_data);
151 
152 void xge_queue_destroy(xge_queue_h queueh);
153 
154 void* xge_queue_item_data(xge_queue_item_t *item);
155 
156 xge_queue_status_e
157 xge_queue_produce(xge_queue_h queueh, int event_type, void *context,
158 		int is_critical, const int data_size, void *data);
159 
160 static inline xge_queue_status_e
161 xge_queue_produce_context(xge_queue_h queueh, int event_type, void *context) {
162 	return xge_queue_produce(queueh, event_type, context, 0, 0, 0);
163 }
164 
165 xge_queue_status_e xge_queue_consume(xge_queue_h queueh, int data_max_size,
166 		xge_queue_item_t *item);
167 
168 void xge_queue_flush(xge_queue_h queueh);
169 
170 /* ========================== PRIVATE API ================================= */
171 
172 xge_queue_status_e __io_queue_grow(xge_queue_h qh);
173 
174 int __queue_get_reset_critical (xge_queue_h qh);
175 
176 #endif /* XGE_QUEUE_H */
177