1da14cebeSEric Cheng /*
2da14cebeSEric Cheng  * CDDL HEADER START
3da14cebeSEric Cheng  *
4da14cebeSEric Cheng  * The contents of this file are subject to the terms of the
5da14cebeSEric Cheng  * Common Development and Distribution License (the "License").
6da14cebeSEric Cheng  * You may not use this file except in compliance with the License.
7da14cebeSEric Cheng  *
8da14cebeSEric Cheng  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da14cebeSEric Cheng  * or http://www.opensolaris.org/os/licensing.
10da14cebeSEric Cheng  * See the License for the specific language governing permissions
11da14cebeSEric Cheng  * and limitations under the License.
12da14cebeSEric Cheng  *
13da14cebeSEric Cheng  * When distributing Covered Code, include this CDDL HEADER in each
14da14cebeSEric Cheng  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da14cebeSEric Cheng  * If applicable, add the following below this CDDL HEADER, with the
16da14cebeSEric Cheng  * fields enclosed by brackets "[]" replaced with your own identifying
17da14cebeSEric Cheng  * information: Portions Copyright [yyyy] [name of copyright owner]
18da14cebeSEric Cheng  *
19da14cebeSEric Cheng  * CDDL HEADER END
20da14cebeSEric Cheng  */
21da14cebeSEric Cheng 
22da14cebeSEric Cheng /*
23ae6aa22aSVenugopal Iyer  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24da14cebeSEric Cheng  * Use is subject to license terms.
25da14cebeSEric Cheng  */
26da14cebeSEric Cheng 
27da14cebeSEric Cheng #ifndef	_SYS_MAC_SOFT_RING_H
28da14cebeSEric Cheng #define	_SYS_MAC_SOFT_RING_H
29da14cebeSEric Cheng 
30da14cebeSEric Cheng #ifdef	__cplusplus
31da14cebeSEric Cheng extern "C" {
32da14cebeSEric Cheng #endif
33da14cebeSEric Cheng 
34da14cebeSEric Cheng #include <sys/types.h>
35da14cebeSEric Cheng #include <sys/cpuvar.h>
36da14cebeSEric Cheng #include <sys/processor.h>
37da14cebeSEric Cheng #include <sys/stream.h>
38da14cebeSEric Cheng #include <sys/squeue.h>
39da14cebeSEric Cheng #include <sys/dlpi.h>
40da14cebeSEric Cheng #include <sys/mac_impl.h>
41da14cebeSEric Cheng 
42da14cebeSEric Cheng #define	S_RING_NAMELEN 64
43da14cebeSEric Cheng 
44*2b24ab6bSSebastien Roy #define	MAX_SR_FANOUT	24
45da14cebeSEric Cheng 
46da14cebeSEric Cheng extern boolean_t mac_soft_ring_enable;
47da14cebeSEric Cheng extern boolean_t mac_latency_optimize;
48da14cebeSEric Cheng 
49da14cebeSEric Cheng typedef struct mac_soft_ring_s mac_soft_ring_t;
50da14cebeSEric Cheng typedef struct mac_soft_ring_set_s mac_soft_ring_set_t;
51da14cebeSEric Cheng 
52da14cebeSEric Cheng typedef void (*mac_soft_ring_drain_func_t)(mac_soft_ring_t *);
53da14cebeSEric Cheng typedef mac_tx_cookie_t (*mac_tx_func_t)(mac_soft_ring_set_t *, mblk_t *,
54da14cebeSEric Cheng     uintptr_t, uint16_t, mblk_t **);
55da14cebeSEric Cheng 
56da14cebeSEric Cheng 
57da14cebeSEric Cheng /* Tx notify callback */
58da14cebeSEric Cheng typedef struct mac_tx_notify_cb_s {
59da14cebeSEric Cheng 	mac_cb_t		mtnf_link;	/* Linked list of callbacks */
60da14cebeSEric Cheng 	mac_tx_notify_t		mtnf_fn;	/* The callback function */
61da14cebeSEric Cheng 	void			*mtnf_arg;	/* Callback function argument */
62da14cebeSEric Cheng } mac_tx_notify_cb_t;
63da14cebeSEric Cheng 
64da14cebeSEric Cheng struct mac_soft_ring_s {
65da14cebeSEric Cheng 	/* Keep the most used members 64bytes cache aligned */
66da14cebeSEric Cheng 	kmutex_t	s_ring_lock;	/* lock before using any member */
67da14cebeSEric Cheng 	uint16_t	s_ring_type;	/* processing model of the sq */
68da14cebeSEric Cheng 	uint16_t	s_ring_state;	/* state flags and message count */
69da14cebeSEric Cheng 	int		s_ring_count;	/* # of mblocks in mac_soft_ring */
70da14cebeSEric Cheng 	size_t		s_ring_size;	/* Size of data queued */
71da14cebeSEric Cheng 	mblk_t		*s_ring_first;	/* first mblk chain or NULL */
72da14cebeSEric Cheng 	mblk_t		*s_ring_last;	/* last mblk chain or NULL */
73da14cebeSEric Cheng 
74da14cebeSEric Cheng 	mac_direct_rx_t	s_ring_rx_func;
75da14cebeSEric Cheng 	void		*s_ring_rx_arg1;
76da14cebeSEric Cheng 	mac_resource_handle_t  s_ring_rx_arg2;
77da14cebeSEric Cheng 
78da14cebeSEric Cheng 	/*
79da14cebeSEric Cheng 	 * Threshold after which packets get dropped.
80da14cebeSEric Cheng 	 * Is always greater than s_ring_tx_hiwat
81da14cebeSEric Cheng 	 */
82da14cebeSEric Cheng 	int		s_ring_tx_max_q_cnt;
83da14cebeSEric Cheng 	/* # of mblocks after which to apply flow control */
84da14cebeSEric Cheng 	int		s_ring_tx_hiwat;
85da14cebeSEric Cheng 	/* # of mblocks after which to relieve flow control */
86da14cebeSEric Cheng 	int		s_ring_tx_lowat;
87da14cebeSEric Cheng 	boolean_t	s_ring_tx_woken_up;
88da14cebeSEric Cheng 	uint32_t	s_ring_blocked_cnt;	/* times blocked for Tx descs */
89da14cebeSEric Cheng 	uint32_t	s_ring_unblocked_cnt;	/* unblock calls from driver */
90da14cebeSEric Cheng 	uint32_t	s_ring_hiwat_cnt;	/* times blocked for Tx descs */
91da14cebeSEric Cheng 
92da14cebeSEric Cheng 	void		*s_ring_tx_arg1;
93da14cebeSEric Cheng 	void		*s_ring_tx_arg2;
94da14cebeSEric Cheng 
95da14cebeSEric Cheng 	/* Tx notify callback */
96da14cebeSEric Cheng 	mac_cb_info_t	s_ring_notify_cb_info;		/* cb list info */
97da14cebeSEric Cheng 	mac_cb_t	*s_ring_notify_cb_list;		/* The cb list */
98da14cebeSEric Cheng 
99da14cebeSEric Cheng 	clock_t		s_ring_awaken;	/* time async thread was awakened */
100da14cebeSEric Cheng 
101da14cebeSEric Cheng 	kthread_t	*s_ring_run;	/* Current thread processing sq */
102da14cebeSEric Cheng 	processorid_t	s_ring_cpuid;	/* processor to bind to */
103da14cebeSEric Cheng 	processorid_t	s_ring_cpuid_save;	/* saved cpuid during offline */
104da14cebeSEric Cheng 	kcondvar_t	s_ring_async;	/* async thread blocks on */
105da14cebeSEric Cheng 	clock_t		s_ring_wait;	/* lbolts to wait after a fill() */
106da14cebeSEric Cheng 	timeout_id_t	s_ring_tid;	/* timer id of pending timeout() */
107da14cebeSEric Cheng 	kthread_t	*s_ring_worker;	/* kernel thread id */
108da14cebeSEric Cheng 	char		s_ring_name[S_RING_NAMELEN + 1];
109da14cebeSEric Cheng 	uint32_t	s_ring_total_inpkt;
110da14cebeSEric Cheng 	uint32_t	s_ring_drops;
111da14cebeSEric Cheng 	struct mac_client_impl_s *s_ring_mcip;
112da14cebeSEric Cheng 	void		*s_ring_flent;
113da14cebeSEric Cheng 	kstat_t		*s_ring_ksp;
114da14cebeSEric Cheng 
115da14cebeSEric Cheng 	/* Teardown, poll disable control ops */
116da14cebeSEric Cheng 	kcondvar_t	s_ring_client_cv; /* Client wait for control op */
117da14cebeSEric Cheng 
118da14cebeSEric Cheng 	mac_soft_ring_set_t *s_ring_set;   /* The SRS this ring belongs to */
119da14cebeSEric Cheng 	mac_soft_ring_t	*s_ring_next;
120da14cebeSEric Cheng 	mac_soft_ring_t	*s_ring_prev;
121da14cebeSEric Cheng 	mac_soft_ring_drain_func_t s_ring_drain_func;
122da14cebeSEric Cheng };
123da14cebeSEric Cheng 
124da14cebeSEric Cheng typedef void (*mac_srs_drain_proc_t)(mac_soft_ring_set_t *, uint_t);
125da14cebeSEric Cheng 
126da14cebeSEric Cheng /* Transmit side Soft Ring Set */
127da14cebeSEric Cheng typedef struct mac_srs_tx_s {
128da14cebeSEric Cheng 	/* Members for Tx size processing */
129da14cebeSEric Cheng 	uint32_t	st_mode;
130da14cebeSEric Cheng 	mac_tx_func_t	st_func;
131da14cebeSEric Cheng 	void		*st_arg1;
132da14cebeSEric Cheng 	void		*st_arg2;
133da14cebeSEric Cheng 	mac_group_t	*st_group;	/* TX group for share */
13463f531d1SSriharsha Basavapatna 	uint32_t	st_ring_count;	/* no. of tx rings */
13563f531d1SSriharsha Basavapatna 	mac_ring_handle_t	*st_rings;
13663f531d1SSriharsha Basavapatna 
137da14cebeSEric Cheng 	boolean_t	st_woken_up;
138da14cebeSEric Cheng 
139da14cebeSEric Cheng 	/*
140da14cebeSEric Cheng 	 * st_max_q_cnt is the queue depth threshold to limit
141da14cebeSEric Cheng 	 * outstanding packets on the Tx SRS. Once the limit
142da14cebeSEric Cheng 	 * is reached, Tx SRS will drop packets until the
143da14cebeSEric Cheng 	 * limit goes below the threshold.
144da14cebeSEric Cheng 	 */
145da14cebeSEric Cheng 	uint32_t	st_max_q_cnt;	/* max. outstanding packets */
146da14cebeSEric Cheng 	/*
147da14cebeSEric Cheng 	 * st_hiwat is used Tx serializer and bandwidth mode.
148da14cebeSEric Cheng 	 * This is the queue depth threshold upto which
149da14cebeSEric Cheng 	 * packets will get buffered with no flow-control
150da14cebeSEric Cheng 	 * back pressure applied to the caller. Once this
151da14cebeSEric Cheng 	 * threshold is reached, back pressure will be
152da14cebeSEric Cheng 	 * applied to the caller of mac_tx() (mac_tx() starts
153da14cebeSEric Cheng 	 * returning a cookie to indicate a blocked SRS).
154da14cebeSEric Cheng 	 * st_hiwat should always be lesser than or equal to
155da14cebeSEric Cheng 	 * st_max_q_cnt.
156da14cebeSEric Cheng 	 */
157da14cebeSEric Cheng 	uint32_t	st_hiwat;	/* mblk cnt to apply flow control */
158da14cebeSEric Cheng 	uint32_t	st_lowat;	/* mblk cnt to relieve flow control */
159da14cebeSEric Cheng 	uint32_t	st_drop_count;
160da14cebeSEric Cheng 	/*
161da14cebeSEric Cheng 	 * Number of times the srs gets blocked due to lack of Tx
162da14cebeSEric Cheng 	 * desc is noted down. Corresponding wakeup from driver
163da14cebeSEric Cheng 	 * to unblock is also noted down. They should match in a
164da14cebeSEric Cheng 	 * correctly working setup. If there is less unblocks
165da14cebeSEric Cheng 	 * than blocks, then Tx side waits forever for a wakeup
166da14cebeSEric Cheng 	 * from below. The following protected by srs_lock.
167da14cebeSEric Cheng 	 */
168da14cebeSEric Cheng 	uint32_t	st_blocked_cnt; /* times blocked for Tx descs */
169da14cebeSEric Cheng 	uint32_t	st_unblocked_cnt; /* unblock calls from driver */
170da14cebeSEric Cheng 	uint32_t	st_hiwat_cnt; /* times blocked for Tx descs */
171da14cebeSEric Cheng } mac_srs_tx_t;
172da14cebeSEric Cheng 
173da14cebeSEric Cheng /* Receive side Soft Ring Set */
174da14cebeSEric Cheng typedef struct mac_srs_rx_s {
175da14cebeSEric Cheng 	/*
176da14cebeSEric Cheng 	 * Upcall Function for fanout, Rx processing etc. Perhaps
177da14cebeSEric Cheng 	 * the same 3 members below can be used for Tx
178da14cebeSEric Cheng 	 * processing, but looking around, mac_rx_func_t has
179da14cebeSEric Cheng 	 * proliferated too much into various files at different
180da14cebeSEric Cheng 	 * places. I am leaving the consolidation battle for
181da14cebeSEric Cheng 	 * another day.
182da14cebeSEric Cheng 	 */
183da14cebeSEric Cheng 	mac_direct_rx_t		sr_func;	/* srs_lock */
184da14cebeSEric Cheng 	void			*sr_arg1;	/* srs_lock */
185da14cebeSEric Cheng 	mac_resource_handle_t 	sr_arg2;	/* srs_lock */
186da14cebeSEric Cheng 	mac_rx_func_t		sr_lower_proc;	/* Atomically changed */
187da14cebeSEric Cheng 	uint32_t		sr_poll_pkt_cnt;
188da14cebeSEric Cheng 	uint32_t		sr_poll_thres;
189da14cebeSEric Cheng 
190da14cebeSEric Cheng 	/* mblk cnt to apply flow control */
191da14cebeSEric Cheng 	uint32_t		sr_hiwat;
192da14cebeSEric Cheng 	/* mblk cnt to relieve flow control */
193da14cebeSEric Cheng 	uint32_t		sr_lowat;
194da14cebeSEric Cheng 	uint32_t		sr_poll_count;
195da14cebeSEric Cheng 	uint32_t		sr_intr_count;
196da14cebeSEric Cheng 	uint32_t		sr_drop_count;
197da14cebeSEric Cheng 
198da14cebeSEric Cheng 	/* Times polling was enabled */
199da14cebeSEric Cheng 	uint32_t		sr_poll_on;
200da14cebeSEric Cheng 	/* Times polling was enabled by worker thread */
201da14cebeSEric Cheng 	uint32_t		sr_worker_poll_on;
202da14cebeSEric Cheng 	/* Times polling was disabled */
203da14cebeSEric Cheng 	uint32_t		sr_poll_off;
204da14cebeSEric Cheng 	/* Poll thread signalled count */
205da14cebeSEric Cheng 	uint32_t		sr_poll_thr_sig;
206da14cebeSEric Cheng 	/* Poll thread busy */
207da14cebeSEric Cheng 	uint32_t		sr_poll_thr_busy;
208da14cebeSEric Cheng 	/* SRS drains, stays in poll mode but doesn't poll */
209da14cebeSEric Cheng 	uint32_t		sr_poll_drain_no_poll;
210da14cebeSEric Cheng 	/*
211da14cebeSEric Cheng 	 * SRS has nothing to do and no packets in H/W but
212da14cebeSEric Cheng 	 * there is a backlog in softrings. SRS stays in
213da14cebeSEric Cheng 	 * poll mode but doesn't do polling.
214da14cebeSEric Cheng 	 */
215da14cebeSEric Cheng 	uint32_t		sr_poll_no_poll;
216da14cebeSEric Cheng 	/* Active polling restarted */
217da14cebeSEric Cheng 	uint32_t		sr_below_hiwat;
218da14cebeSEric Cheng 	/* Found packets in last poll so try and poll again */
219da14cebeSEric Cheng 	uint32_t		sr_poll_again;
220da14cebeSEric Cheng 	/*
221da14cebeSEric Cheng 	 * Packets in queue but poll thread not allowed to process so
222da14cebeSEric Cheng 	 * signal the worker thread.
223da14cebeSEric Cheng 	 */
224da14cebeSEric Cheng 	uint32_t		sr_poll_sig_worker;
225da14cebeSEric Cheng 	/*
226da14cebeSEric Cheng 	 * Poll thread has nothing to do and H/W has nothing so
227da14cebeSEric Cheng 	 * reenable the interrupts.
228da14cebeSEric Cheng 	 */
229da14cebeSEric Cheng 	uint32_t		sr_poll_intr_enable;
230da14cebeSEric Cheng 	/*
231da14cebeSEric Cheng 	 * Poll thread has nothing to do and worker thread was already
232da14cebeSEric Cheng 	 * running so it can decide to reenable interrupt or poll again.
233da14cebeSEric Cheng 	 */
234da14cebeSEric Cheng 	uint32_t		sr_poll_goto_sleep;
235da14cebeSEric Cheng 	/* Worker thread goes back to draining the queue */
236da14cebeSEric Cheng 	uint32_t		sr_drain_again;
2378ac29891SEric Cheng 	/* More Packets in queue so signal the poll thread to drain */
238ae6aa22aSVenugopal Iyer 	uint32_t		sr_drain_poll_sig;
2398ac29891SEric Cheng 	/* More Packets in queue so signal the worker thread to drain */
2408ac29891SEric Cheng 	uint32_t		sr_drain_worker_sig;
241da14cebeSEric Cheng 	/* Poll thread is already running so worker has nothing to do */
242da14cebeSEric Cheng 	uint32_t		sr_drain_poll_running;
243da14cebeSEric Cheng 	/* We have packets already queued so keep polling */
244da14cebeSEric Cheng 	uint32_t		sr_drain_keep_polling;
245da14cebeSEric Cheng 	/* Drain is done and interrupts are reenabled */
246da14cebeSEric Cheng 	uint32_t		sr_drain_finish_intr;
247da14cebeSEric Cheng 	/* Polling thread needs to schedule worker wakeup */
248da14cebeSEric Cheng 	uint32_t		sr_poll_worker_wakeup;
249da14cebeSEric Cheng 
250da14cebeSEric Cheng 	/* Chains less than 10 pkts */
251da14cebeSEric Cheng 	uint32_t		sr_chain_cnt_undr10;
252da14cebeSEric Cheng 	/* Chains between 10 & 50 pkts */
253da14cebeSEric Cheng 	uint32_t		sr_chain_cnt_10to50;
254da14cebeSEric Cheng 	/* Chains over 50 pkts */
255da14cebeSEric Cheng 	uint32_t		sr_chain_cnt_over50;
256da14cebeSEric Cheng } mac_srs_rx_t;
257da14cebeSEric Cheng 
258da14cebeSEric Cheng /*
259da14cebeSEric Cheng  * mac_soft_ring_set_s:
260da14cebeSEric Cheng  * This is used both for Tx and Rx side. The srs_type identifies Rx or
261da14cebeSEric Cheng  * Tx type.
262da14cebeSEric Cheng  *
263da14cebeSEric Cheng  * Note that the structure is carefully crafted, with Rx elements coming
264da14cebeSEric Cheng  * first followed by Tx specific members. Future additions to this
265da14cebeSEric Cheng  * structure should follow the same guidelines.
266da14cebeSEric Cheng  *
267da14cebeSEric Cheng  * Rx-side notes:
268da14cebeSEric Cheng  * mac_rx_classify_flow_add() always creates a mac_soft_ring_set_t and fn_flow
269da14cebeSEric Cheng  * points to info from it (func = srs_lower_proc, arg = soft_ring_set). On
270da14cebeSEric Cheng  * interrupt path, srs_lower_proc does B/W adjustment and switch to polling mode
271da14cebeSEric Cheng  * (if poll capable) and feeds the packets to soft_ring_list via choosen
272da14cebeSEric Cheng  * fanout type (specified by srs_type). In poll mode, the poll thread which is
273da14cebeSEric Cheng  * also a pointer can pick up the packets and feed them to various
274da14cebeSEric Cheng  * soft_ring_list.
275da14cebeSEric Cheng  *
276da14cebeSEric Cheng  * The srs_type can either be protocol based or fanout based where fanout itelf
277da14cebeSEric Cheng  * can be various types
278da14cebeSEric Cheng  *
279da14cebeSEric Cheng  * The polling works by turning off interrupts as soon as a packets
280da14cebeSEric Cheng  * are queued on the soft ring set. Once the backlog is clear and poll
281da14cebeSEric Cheng  * thread return empty handed i.e. Rx ring doesn't have anything, the
282da14cebeSEric Cheng  * interrupt is turned back on. For this purpose we keep a separate
283da14cebeSEric Cheng  * srs_poll_pkt_cnt counter which tracks the packets queued between SRS
284da14cebeSEric Cheng  * and the soft rings as well. The counter is incremented when packets
285da14cebeSEric Cheng  * are queued and decremented when SRS processes them (in case it has
286da14cebeSEric Cheng  * no soft rings) or the soft ring process them. Its important that
287da14cebeSEric Cheng  * in case SRS has softrings, the decrement doesn't happen till the
288da14cebeSEric Cheng  * packet is processed by the soft rings since it takes very little time
289da14cebeSEric Cheng  * for SRS to queue packet from SRS to soft rings and it will keep
290da14cebeSEric Cheng  * bringing more packets in the system faster than soft rings can
291da14cebeSEric Cheng  * process them.
292da14cebeSEric Cheng  *
293da14cebeSEric Cheng  * Tx side notes:
294da14cebeSEric Cheng  * The srs structure acts as a serializer with a worker thread. The
295da14cebeSEric Cheng  * default behavior of srs though is to act as a pass-thru. The queues
296da14cebeSEric Cheng  * (srs_first, srs_last, srs_count) get used when Tx ring runs out of Tx
297da14cebeSEric Cheng  * descriptors or to enforce bandwidth limits.
298da14cebeSEric Cheng  *
299da14cebeSEric Cheng  * When multiple Tx rings are present, the SRS state will be set to
300da14cebeSEric Cheng  * SRS_FANOUT_OTH. Outgoing packets coming into mac_tx_srs_process()
301da14cebeSEric Cheng  * function will be fanned out to one of the Tx side soft rings based on
302da14cebeSEric Cheng  * a hint passed in mac_tx_srs_process(). Each soft ring, in turn, will
303da14cebeSEric Cheng  * be associated with a distinct h/w Tx ring.
304da14cebeSEric Cheng  */
305da14cebeSEric Cheng 
306da14cebeSEric Cheng struct mac_soft_ring_set_s {
307da14cebeSEric Cheng 	/*
308da14cebeSEric Cheng 	 * Common elements, common to both Rx and Tx SRS type.
309da14cebeSEric Cheng 	 * The following block of fields are protected by srs_lock
310da14cebeSEric Cheng 	 */
311da14cebeSEric Cheng 	kmutex_t	srs_lock;
312da14cebeSEric Cheng 	uint32_t	srs_type;
313da14cebeSEric Cheng 	uint32_t	srs_state;	/* state flags */
314da14cebeSEric Cheng 	uint32_t	srs_count;
315da14cebeSEric Cheng 	mblk_t		*srs_first;	/* first mblk chain or NULL */
316da14cebeSEric Cheng 	mblk_t		*srs_last;	/* last mblk chain or NULL */
317da14cebeSEric Cheng 	kcondvar_t	srs_async;	/* cv for worker thread */
318da14cebeSEric Cheng 	kcondvar_t	srs_cv;		/* cv for poll thread */
319da14cebeSEric Cheng 	kcondvar_t	srs_quiesce_done_cv;	/* cv for removal */
320da14cebeSEric Cheng 	timeout_id_t	srs_tid;	/* timeout id for pending timeout */
321da14cebeSEric Cheng 
322da14cebeSEric Cheng 	/*
323da14cebeSEric Cheng 	 * List of soft rings & processing function.
324da14cebeSEric Cheng 	 * The following block is protected by Rx quiescence.
325da14cebeSEric Cheng 	 * i.e. they can be changed only after quiescing the SRS
326da14cebeSEric Cheng 	 * Protected by srs_lock.
327da14cebeSEric Cheng 	 */
328da14cebeSEric Cheng 	mac_soft_ring_t	*srs_soft_ring_head;
329da14cebeSEric Cheng 	mac_soft_ring_t	*srs_soft_ring_tail;
330da14cebeSEric Cheng 	int		srs_soft_ring_count;
331da14cebeSEric Cheng 	int		srs_soft_ring_quiesced_count;
332da14cebeSEric Cheng 	int		srs_soft_ring_condemned_count;
333da14cebeSEric Cheng 	mac_soft_ring_t	**srs_tcp_soft_rings;
334da14cebeSEric Cheng 	int		srs_tcp_ring_count;
335da14cebeSEric Cheng 	mac_soft_ring_t	**srs_udp_soft_rings;
336da14cebeSEric Cheng 	int		srs_udp_ring_count;
337da14cebeSEric Cheng 	/*
338da14cebeSEric Cheng 	 * srs_oth_soft_rings is also used by tx_srs in
339da14cebeSEric Cheng 	 * when operating in multi tx ring mode.
340da14cebeSEric Cheng 	 */
341da14cebeSEric Cheng 	mac_soft_ring_t	**srs_oth_soft_rings;
342da14cebeSEric Cheng 	int		srs_oth_ring_count;
343da14cebeSEric Cheng 
344da14cebeSEric Cheng 	/*
345da14cebeSEric Cheng 	 * Bandwidth control related members.
346da14cebeSEric Cheng 	 * They are common to both Rx- and Tx-side.
347da14cebeSEric Cheng 	 * Following protected by srs_lock
348da14cebeSEric Cheng 	 */
349da14cebeSEric Cheng 	mac_bw_ctl_t	*srs_bw;
350da14cebeSEric Cheng 	size_t		srs_size;	/* Size of packets queued in bytes */
351da14cebeSEric Cheng 	pri_t		srs_pri;
352da14cebeSEric Cheng 
353da14cebeSEric Cheng 	mac_soft_ring_set_t	*srs_next;	/* mac_srs_g_lock */
354da14cebeSEric Cheng 	mac_soft_ring_set_t	*srs_prev;	/* mac_srs_g_lock */
355da14cebeSEric Cheng 
356da14cebeSEric Cheng 	/* Attribute specific drain func (BW ctl vs non-BW ctl)	*/
357da14cebeSEric Cheng 	mac_srs_drain_proc_t	srs_drain_func;	/* Write once (WO) */
358da14cebeSEric Cheng 
359da14cebeSEric Cheng 	/*
360da14cebeSEric Cheng 	 * If the associated ring is exclusively used by a mac client, e.g.,
361da14cebeSEric Cheng 	 * an aggregation, this fields is used to keep a reference to the
362da14cebeSEric Cheng 	 * MAC client's pseudo ring.
363da14cebeSEric Cheng 	 */
364da14cebeSEric Cheng 	mac_resource_handle_t	srs_mrh;
365da14cebeSEric Cheng 	/*
366da14cebeSEric Cheng 	 * The following blocks are write once (WO) and valid for the life
367da14cebeSEric Cheng 	 * of the SRS
368da14cebeSEric Cheng 	 */
369da14cebeSEric Cheng 	struct mac_client_impl_s *srs_mcip;	/* back ptr to mac client */
370da14cebeSEric Cheng 	void			*srs_flent;	/* back ptr to flent */
371da14cebeSEric Cheng 	mac_ring_t		*srs_ring;	/*  Ring Descriptor */
372da14cebeSEric Cheng 
373da14cebeSEric Cheng 	/* Teardown, disable control ops */
374da14cebeSEric Cheng 	kcondvar_t	srs_client_cv;	/* Client wait for the control op */
375da14cebeSEric Cheng 
376da14cebeSEric Cheng 	kthread_t	*srs_worker;	/* WO, worker thread */
377da14cebeSEric Cheng 	kthread_t	*srs_poll_thr;	/* WO, poll thread */
378da14cebeSEric Cheng 
379da14cebeSEric Cheng 	uint_t		srs_ind;	/* Round Robin indx for picking up SR */
380da14cebeSEric Cheng 	processorid_t	srs_worker_cpuid;	/* processor to bind to */
381da14cebeSEric Cheng 	processorid_t	srs_worker_cpuid_save;	/* saved cpuid during offline */
382da14cebeSEric Cheng 	processorid_t	srs_poll_cpuid;		/* processor to bind to */
383da14cebeSEric Cheng 	processorid_t	srs_poll_cpuid_save;	/* saved cpuid during offline */
384da14cebeSEric Cheng 	uint_t		srs_fanout_state;
385da14cebeSEric Cheng 	mac_cpus_t	srs_cpu;
386da14cebeSEric Cheng 
387da14cebeSEric Cheng 	mac_srs_rx_t	srs_rx;
388da14cebeSEric Cheng 	mac_srs_tx_t	srs_tx;
389da14cebeSEric Cheng };
390da14cebeSEric Cheng 
391da14cebeSEric Cheng /*
392da14cebeSEric Cheng  * type flags - combination allowed to process and drain the queue
393da14cebeSEric Cheng  */
394da14cebeSEric Cheng #define	ST_RING_WORKER_ONLY  	0x0001	/* Worker thread only */
395da14cebeSEric Cheng #define	ST_RING_ANY		0x0002	/* Any thread can process the queue */
396da14cebeSEric Cheng #define	ST_RING_TCP		0x0004
397da14cebeSEric Cheng #define	ST_RING_UDP		0x0008
398da14cebeSEric Cheng #define	ST_RING_OTH		0x0010
399da14cebeSEric Cheng 
400da14cebeSEric Cheng #define	ST_RING_BW_CTL		0x0020
401da14cebeSEric Cheng #define	ST_RING_TX		0x0040
402da14cebeSEric Cheng 
403da14cebeSEric Cheng /*
404da14cebeSEric Cheng  * State flags.
405da14cebeSEric Cheng  */
406da14cebeSEric Cheng #define	S_RING_PROC		0x0001	/* being processed */
407da14cebeSEric Cheng #define	S_RING_BOUND		0x0002	/* Worker thread is bound to a cpu */
408da14cebeSEric Cheng #define	S_RING_BLOCK		0x0004	/* No Tx descs */
409da14cebeSEric Cheng #define	S_RING_TX_HIWAT		0x0008	/* Tx high watermark reached */
410da14cebeSEric Cheng 
411da14cebeSEric Cheng #define	S_RING_WAKEUP_CLIENT	0x0010	/* flow ctrl, client wakeup needed */
412da14cebeSEric Cheng #define	S_RING_BLANK		0x0020	/* Has been put into polling mode */
413da14cebeSEric Cheng #define	S_RING_CLIENT_WAIT	0x0040	/* Client waiting for control op */
414da14cebeSEric Cheng 
415da14cebeSEric Cheng #define	S_RING_CONDEMNED	0x0100	/* Being torn down */
416da14cebeSEric Cheng #define	S_RING_CONDEMNED_DONE	0x0200	/* Being torn down */
417da14cebeSEric Cheng #define	S_RING_QUIESCE		0x0400	/* No traffic flow, transient flag */
418da14cebeSEric Cheng #define	S_RING_QUIESCE_DONE	0x0800	/* No traffic flow, transient flag */
419da14cebeSEric Cheng 
420da14cebeSEric Cheng #define	S_RING_RESTART		0x1000	/* Go back to normal traffic flow */
421da14cebeSEric Cheng #define	S_RING_ENQUEUED		0x2000	/* Pkts enqueued in Tx soft ring */
422da14cebeSEric Cheng 
423da14cebeSEric Cheng /*
424da14cebeSEric Cheng  * arguments for processors to bind to
425da14cebeSEric Cheng  */
426da14cebeSEric Cheng #define	S_RING_BIND_NONE	-1
427da14cebeSEric Cheng 
428da14cebeSEric Cheng /*
429da14cebeSEric Cheng  * defines for srs_type - identifies a link or a sub-flow
430da14cebeSEric Cheng  * and other static characteristics of a SRS like a tx
431da14cebeSEric Cheng  * srs, tcp only srs, etc.
432da14cebeSEric Cheng  */
433da14cebeSEric Cheng #define	SRST_LINK		0x00000001
434da14cebeSEric Cheng #define	SRST_FLOW		0x00000002
435da14cebeSEric Cheng #define	SRST_NO_SOFT_RINGS	0x00000004
436da14cebeSEric Cheng #define	SRST_TCP_ONLY		0x00000008
437da14cebeSEric Cheng 
438da14cebeSEric Cheng #define	SRST_FANOUT_PROTO	0x00000010
439da14cebeSEric Cheng #define	SRST_FANOUT_SRC_IP	0x00000020
440da14cebeSEric Cheng #define	SRST_FANOUT_OTH		0x00000040
441da14cebeSEric Cheng #define	SRST_DEFAULT_GRP	0x00000080
442da14cebeSEric Cheng 
443da14cebeSEric Cheng #define	SRST_TX			0x00000100
444da14cebeSEric Cheng #define	SRST_BW_CONTROL		0x00000200
445da14cebeSEric Cheng #define	SRST_DIRECT_POLL	0x00000400
446da14cebeSEric Cheng 
447da14cebeSEric Cheng #define	SRST_DLS_BYPASS		0x00001000
448da14cebeSEric Cheng #define	SRST_CLIENT_POLL_ENABLED 0x00002000
449da14cebeSEric Cheng 
450da14cebeSEric Cheng /*
451da14cebeSEric Cheng  * soft ring set flags. These bits are dynamic in nature and get
452da14cebeSEric Cheng  * applied to srs_state. They reflect the state of SRS at any
453da14cebeSEric Cheng  * point of time
454da14cebeSEric Cheng  */
455da14cebeSEric Cheng #define	SRS_BLANK		0x00000001
456da14cebeSEric Cheng #define	SRS_WORKER_BOUND	0x00000002
457da14cebeSEric Cheng #define	SRS_POLL_BOUND		0x00000004
458da14cebeSEric Cheng #define	SRS_POLLING_CAPAB	0x00000008
459da14cebeSEric Cheng 
460da14cebeSEric Cheng #define	SRS_PROC		0x00000010
461da14cebeSEric Cheng #define	SRS_GET_PKTS		0x00000020
462da14cebeSEric Cheng #define	SRS_POLLING		0x00000040
463da14cebeSEric Cheng #define	SRS_BW_ENFORCED		0x00000080
464da14cebeSEric Cheng 
465da14cebeSEric Cheng #define	SRS_WORKER		0x00000100
466da14cebeSEric Cheng #define	SRS_ENQUEUED		0x00000200
467da14cebeSEric Cheng #define	SRS_ANY_PROCESS		0x00000400
468da14cebeSEric Cheng #define	SRS_PROC_FAST		0x00000800
469da14cebeSEric Cheng 
470da14cebeSEric Cheng #define	SRS_POLL_PROC		0x00001000
471da14cebeSEric Cheng #define	SRS_TX_BLOCKED		0x00002000	/* out of Tx descs */
472da14cebeSEric Cheng #define	SRS_TX_HIWAT		0x00004000	/* Tx count exceeds hiwat */
473da14cebeSEric Cheng #define	SRS_TX_WAKEUP_CLIENT	0x00008000	/* Flow-ctl: wakeup client */
474da14cebeSEric Cheng 
475da14cebeSEric Cheng #define	SRS_CLIENT_PROC		0x00010000
476da14cebeSEric Cheng #define	SRS_CLIENT_WAIT		0x00020000
477da14cebeSEric Cheng #define	SRS_QUIESCE		0x00040000
478da14cebeSEric Cheng #define	SRS_QUIESCE_DONE	0x00080000
479da14cebeSEric Cheng 
480da14cebeSEric Cheng #define	SRS_CONDEMNED		0x00100000
481da14cebeSEric Cheng #define	SRS_CONDEMNED_DONE	0x00200000
482da14cebeSEric Cheng #define	SRS_POLL_THR_QUIESCED	0x00400000
483da14cebeSEric Cheng #define	SRS_RESTART		0x00800000
484da14cebeSEric Cheng 
485da14cebeSEric Cheng #define	SRS_RESTART_DONE	0x01000000
486da14cebeSEric Cheng #define	SRS_POLL_THR_RESTART	0x02000000
487da14cebeSEric Cheng #define	SRS_IN_GLIST		0x04000000
488da14cebeSEric Cheng #define	SRS_POLL_THR_EXITED	0x08000000
489da14cebeSEric Cheng 
490da14cebeSEric Cheng #define	SRS_QUIESCE_PERM	0x10000000
491da14cebeSEric Cheng #define	SRS_LATENCY_OPT		0x20000000
492ae6aa22aSVenugopal Iyer #define	SRS_SOFTRING_QUEUE	0x40000000
493da14cebeSEric Cheng 
494da14cebeSEric Cheng #define	SRS_QUIESCED(srs)	(srs->srs_state & SRS_QUIESCE_DONE)
495da14cebeSEric Cheng 
496da14cebeSEric Cheng /*
497da14cebeSEric Cheng  * If the SRS_QUIESCE_PERM flag is set, the SRS worker thread will not be
498da14cebeSEric Cheng  * able to be restarted.
499da14cebeSEric Cheng  */
500da14cebeSEric Cheng #define	SRS_QUIESCED_PERMANENT(srs)	(srs->srs_state & SRS_QUIESCE_PERM)
501da14cebeSEric Cheng 
502da14cebeSEric Cheng /*
503da14cebeSEric Cheng  * soft ring set (SRS) Tx modes
504da14cebeSEric Cheng  */
505da14cebeSEric Cheng typedef enum {
506da14cebeSEric Cheng 	SRS_TX_DEFAULT = 0,
507da14cebeSEric Cheng 	SRS_TX_SERIALIZE,
508da14cebeSEric Cheng 	SRS_TX_FANOUT,
509da14cebeSEric Cheng 	SRS_TX_BW,
510da14cebeSEric Cheng 	SRS_TX_BW_FANOUT
511da14cebeSEric Cheng } mac_tx_srs_mode_t;
512da14cebeSEric Cheng 
513da14cebeSEric Cheng /*
514da14cebeSEric Cheng  * SRS fanout states
515da14cebeSEric Cheng  */
516da14cebeSEric Cheng typedef enum {
517da14cebeSEric Cheng 	SRS_FANOUT_UNINIT = 0,
518da14cebeSEric Cheng 	SRS_FANOUT_INIT,
519da14cebeSEric Cheng 	SRS_FANOUT_REINIT
520da14cebeSEric Cheng } mac_srs_fanout_state_t;
521da14cebeSEric Cheng 
522da14cebeSEric Cheng /*
523da14cebeSEric Cheng  * Structure for dls statistics
524da14cebeSEric Cheng  */
525da14cebeSEric Cheng struct dls_kstats {
526da14cebeSEric Cheng 	kstat_named_t	dlss_soft_ring_pkt_drop;
527da14cebeSEric Cheng };
528da14cebeSEric Cheng 
529da14cebeSEric Cheng extern struct dls_kstats dls_kstat;
530da14cebeSEric Cheng 
531da14cebeSEric Cheng #define	DLS_BUMP_STAT(x, y)	(dls_kstat.x.value.ui32 += y)
532da14cebeSEric Cheng 
533da14cebeSEric Cheng /* Turn dynamic polling off */
534da14cebeSEric Cheng #define	MAC_SRS_POLLING_OFF(mac_srs) {					\
535da14cebeSEric Cheng 	ASSERT(MUTEX_HELD(&(mac_srs)->srs_lock));			\
536da14cebeSEric Cheng 	if (((mac_srs)->srs_state & (SRS_POLLING_CAPAB|SRS_POLLING)) == \
537da14cebeSEric Cheng 	    (SRS_POLLING_CAPAB|SRS_POLLING)) {				\
538da14cebeSEric Cheng 		(mac_srs)->srs_state &= ~SRS_POLLING;			\
539da14cebeSEric Cheng 		(void) mac_hwring_enable_intr((mac_ring_handle_t)	\
540da14cebeSEric Cheng 		    (mac_srs)->srs_ring);				\
541da14cebeSEric Cheng 		(mac_srs)->srs_rx.sr_poll_off++;			\
542da14cebeSEric Cheng 	}								\
543da14cebeSEric Cheng }
544da14cebeSEric Cheng 
545da14cebeSEric Cheng #define	MAC_COUNT_CHAIN(mac_srs, head, tail, cnt, sz)	{	\
546da14cebeSEric Cheng 	mblk_t 		*tmp;		       			\
547da14cebeSEric Cheng 	boolean_t	bw_ctl = B_FALSE;			\
548da14cebeSEric Cheng 								\
549da14cebeSEric Cheng 	ASSERT((head) != NULL);					\
550da14cebeSEric Cheng 	cnt = 0;						\
551da14cebeSEric Cheng 	sz = 0;							\
552da14cebeSEric Cheng 	if ((mac_srs)->srs_type & SRST_BW_CONTROL)		\
553da14cebeSEric Cheng 		bw_ctl = B_TRUE;				\
554da14cebeSEric Cheng 	tmp = tail = (head);					\
555da14cebeSEric Cheng 	if ((head)->b_next == NULL) {				\
556da14cebeSEric Cheng 		cnt = 1;					\
557da14cebeSEric Cheng 		if (bw_ctl)					\
558da14cebeSEric Cheng 			sz += msgdsize(head);			\
559da14cebeSEric Cheng 	} else {						\
560da14cebeSEric Cheng 		while (tmp != NULL) {				\
561da14cebeSEric Cheng 			tail = tmp;				\
562da14cebeSEric Cheng 			cnt++;					\
563da14cebeSEric Cheng 			if (bw_ctl)				\
564da14cebeSEric Cheng 				sz += msgdsize(tmp);		\
565da14cebeSEric Cheng 			tmp = tmp->b_next;			\
566da14cebeSEric Cheng 		}						\
567da14cebeSEric Cheng 	}							\
568da14cebeSEric Cheng }
569da14cebeSEric Cheng 
570da14cebeSEric Cheng /*
571da14cebeSEric Cheng  * Decrement the cumulative packet count in SRS and its
572da14cebeSEric Cheng  * soft rings. If the srs_poll_pkt_cnt goes below lowat, then check
573da14cebeSEric Cheng  * if if the interface was left in a polling mode and no one
574da14cebeSEric Cheng  * is really processing the queue (to get the interface out
575da14cebeSEric Cheng  * of poll mode). If no one is processing the queue, then
576da14cebeSEric Cheng  * acquire the PROC and signal the poll thread to check the
577da14cebeSEric Cheng  * interface for packets and get the interface back to interrupt
578da14cebeSEric Cheng  * mode if nothing is found.
579da14cebeSEric Cheng  */
580da14cebeSEric Cheng #define	MAC_UPDATE_SRS_COUNT_LOCKED(mac_srs, cnt) {		        \
581da14cebeSEric Cheng 	mac_srs_rx_t	*srs_rx = &(mac_srs)->srs_rx;			\
582da14cebeSEric Cheng 	ASSERT(MUTEX_HELD(&(mac_srs)->srs_lock));			\
583da14cebeSEric Cheng 									\
584da14cebeSEric Cheng 	srs_rx->sr_poll_pkt_cnt -= cnt;					\
585da14cebeSEric Cheng 	if ((srs_rx->sr_poll_pkt_cnt <= srs_rx->sr_poll_thres) && 	\
586da14cebeSEric Cheng 		(((mac_srs)->srs_state &				\
587da14cebeSEric Cheng 		(SRS_POLLING|SRS_PROC|SRS_GET_PKTS)) == SRS_POLLING))	\
588da14cebeSEric Cheng 	{								\
589da14cebeSEric Cheng 		(mac_srs)->srs_state |= (SRS_PROC|SRS_GET_PKTS);	\
590da14cebeSEric Cheng 		cv_signal(&(mac_srs)->srs_cv); 				\
591da14cebeSEric Cheng 		srs_rx->sr_below_hiwat++;				\
592da14cebeSEric Cheng 	}								\
593da14cebeSEric Cheng }
594da14cebeSEric Cheng 
595da14cebeSEric Cheng /*
596da14cebeSEric Cheng  * The following two macros are used to update the inbound packet and byte.
597da14cebeSEric Cheng  * count. The packet and byte count reflect the packets and bytes that are
598da14cebeSEric Cheng  * taken out of the SRS's queue, i.e. indicating they are being delivered.
599da14cebeSEric Cheng  * The srs_count and srs_size are updated in different locations as the
600da14cebeSEric Cheng  * srs_size is also used to take into account any bandwidth limits. The
601da14cebeSEric Cheng  * srs_size is updated only when a soft ring, if any, sends a packet up,
602da14cebeSEric Cheng  * as opposed to updating it when the SRS sends a packet to the SR, i.e.
603da14cebeSEric Cheng  * the srs_size reflects the packets in the SRS and SRs. These
604da14cebeSEric Cheng  * macros decrement the srs_size and srs_count and also increment the
605da14cebeSEric Cheng  * ipackets and ibytes stats resp.
606da14cebeSEric Cheng  *
607da14cebeSEric Cheng  * xxx-venu These are done under srs_lock, for now we still update
608da14cebeSEric Cheng  * mci_stat_ibytes/mci_stat_ipackets atomically, need to check if
609da14cebeSEric Cheng  * just updating them would be accurate enough.
610da14cebeSEric Cheng  *
611da14cebeSEric Cheng  * If we are updating these for a sub-flow SRS, then we need to also
612da14cebeSEric Cheng  * updated it's MAC client bandwidth info, if the MAC client is also
613da14cebeSEric Cheng  * bandwidth regulated.
614da14cebeSEric Cheng  */
615da14cebeSEric Cheng #define	MAC_UPDATE_SRS_SIZE_LOCKED(srs, sz) {				\
616da14cebeSEric Cheng 	if ((srs)->srs_type & SRST_BW_CONTROL) {			\
617da14cebeSEric Cheng 		mutex_enter(&(srs)->srs_bw->mac_bw_lock);		\
618da14cebeSEric Cheng 		(srs)->srs_bw->mac_bw_sz -= (sz);			\
619da14cebeSEric Cheng 		(srs)->srs_bw->mac_bw_used += (sz);			\
620da14cebeSEric Cheng 		mutex_exit(&(srs)->srs_bw->mac_bw_lock);		\
621da14cebeSEric Cheng 	}								\
622da14cebeSEric Cheng }
623da14cebeSEric Cheng 
624da14cebeSEric Cheng #define	MAC_TX_UPDATE_BW_INFO(srs, sz) {				\
625da14cebeSEric Cheng 	(srs)->srs_bw->mac_bw_sz -= (sz);				\
626da14cebeSEric Cheng 	(srs)->srs_bw->mac_bw_used += (sz);				\
627da14cebeSEric Cheng }
628da14cebeSEric Cheng 
629da14cebeSEric Cheng #define	TX_MULTI_RING_MODE(mac_srs)				\
630da14cebeSEric Cheng 	((mac_srs)->srs_tx.st_mode == SRS_TX_FANOUT || 		\
631da14cebeSEric Cheng 	    (mac_srs)->srs_tx.st_mode == SRS_TX_BW_FANOUT)
632da14cebeSEric Cheng 
633da14cebeSEric Cheng /* Soft ring flags for teardown */
634da14cebeSEric Cheng #define	SRS_POLL_THR_OWNER	(SRS_PROC | SRS_POLLING | SRS_GET_PKTS)
635da14cebeSEric Cheng #define	SRS_PAUSE		(SRS_CONDEMNED | SRS_QUIESCE)
636da14cebeSEric Cheng #define	S_RING_PAUSE		(S_RING_CONDEMNED | S_RING_QUIESCE)
637da14cebeSEric Cheng 
638da14cebeSEric Cheng /* Soft rings */
639da14cebeSEric Cheng extern void mac_soft_ring_init(void);
640da14cebeSEric Cheng extern void mac_soft_ring_finish(void);
641da14cebeSEric Cheng extern void mac_fanout_setup(mac_client_impl_t *, flow_entry_t *,
642da14cebeSEric Cheng     mac_resource_props_t *, mac_direct_rx_t, void *, mac_resource_handle_t);
643da14cebeSEric Cheng 
644da14cebeSEric Cheng extern void mac_soft_ring_worker_wakeup(mac_soft_ring_t *);
645da14cebeSEric Cheng extern void mac_soft_ring_blank(void *, time_t, uint_t, int);
646da14cebeSEric Cheng extern mblk_t *mac_soft_ring_poll(mac_soft_ring_t *, int);
647da14cebeSEric Cheng extern void mac_soft_ring_destroy(mac_soft_ring_t *);
648da14cebeSEric Cheng extern void mac_soft_ring_dls_bypass(void *, mac_direct_rx_t, void *);
649da14cebeSEric Cheng 
650da14cebeSEric Cheng /* Rx SRS */
651da14cebeSEric Cheng extern mac_soft_ring_set_t *mac_srs_create(struct mac_client_impl_s *,
652da14cebeSEric Cheng     flow_entry_t *, uint32_t, mac_direct_rx_t, void *, mac_resource_handle_t,
653da14cebeSEric Cheng     mac_ring_t *);
654da14cebeSEric Cheng extern void mac_srs_free(mac_soft_ring_set_t *);
655da14cebeSEric Cheng extern void mac_srs_signal(mac_soft_ring_set_t *, uint_t);
656da14cebeSEric Cheng extern cpu_t *mac_srs_bind(mac_soft_ring_set_t *, processorid_t);
657da14cebeSEric Cheng 
658da14cebeSEric Cheng extern void mac_srs_change_upcall(void *, mac_direct_rx_t, void *);
659da14cebeSEric Cheng extern void mac_srs_quiesce_initiate(mac_soft_ring_set_t *);
660da14cebeSEric Cheng extern void mac_srs_client_poll_enable(struct mac_client_impl_s *,
661da14cebeSEric Cheng     mac_soft_ring_set_t *);
662da14cebeSEric Cheng extern void mac_srs_client_poll_disable(struct mac_client_impl_s *,
663da14cebeSEric Cheng     mac_soft_ring_set_t *);
664da14cebeSEric Cheng extern void mac_srs_client_poll_quiesce(struct mac_client_impl_s *,
665da14cebeSEric Cheng     mac_soft_ring_set_t *);
666da14cebeSEric Cheng extern void mac_srs_client_poll_restart(struct mac_client_impl_s *,
667da14cebeSEric Cheng     mac_soft_ring_set_t *);
668da14cebeSEric Cheng extern void mac_rx_srs_quiesce(mac_soft_ring_set_t *, uint_t);
669da14cebeSEric Cheng extern void mac_rx_srs_restart(mac_soft_ring_set_t *);
670da14cebeSEric Cheng extern void mac_rx_srs_subflow_process(void *, mac_resource_handle_t, mblk_t *,
671da14cebeSEric Cheng     boolean_t);
672da14cebeSEric Cheng extern void mac_tx_srs_quiesce(mac_soft_ring_set_t *, uint_t);
673da14cebeSEric Cheng 
674da14cebeSEric Cheng /* Tx SRS, Tx softring */
675da14cebeSEric Cheng extern void mac_tx_srs_wakeup(mac_soft_ring_set_t *, mac_ring_handle_t);
676da14cebeSEric Cheng extern void mac_tx_srs_setup(struct mac_client_impl_s *,
677da14cebeSEric Cheng     flow_entry_t *, uint32_t);
678da14cebeSEric Cheng extern mac_tx_func_t mac_tx_get_func(uint32_t);
679da14cebeSEric Cheng extern mblk_t *mac_tx_send(mac_client_handle_t, mac_ring_handle_t, mblk_t *,
680da14cebeSEric Cheng     mac_tx_stats_t *);
681da14cebeSEric Cheng extern boolean_t mac_tx_srs_ring_present(mac_soft_ring_set_t *, mac_ring_t *);
682da14cebeSEric Cheng extern void mac_tx_srs_add_ring(mac_soft_ring_set_t *, mac_ring_t *);
683da14cebeSEric Cheng extern void mac_tx_srs_del_ring(mac_soft_ring_set_t *, mac_ring_t *);
684da14cebeSEric Cheng extern mac_tx_cookie_t mac_tx_srs_no_desc(mac_soft_ring_set_t *, mblk_t *,
685da14cebeSEric Cheng     uint16_t, mblk_t **);
686da14cebeSEric Cheng 
687da14cebeSEric Cheng /* Subflow specific stuff */
688da14cebeSEric Cheng extern int mac_srs_flow_create(struct mac_client_impl_s *, flow_entry_t *,
689da14cebeSEric Cheng     mac_resource_props_t *, int, int, mac_direct_rx_t);
690da14cebeSEric Cheng extern void mac_srs_update_bwlimit(flow_entry_t *, mac_resource_props_t *);
691da14cebeSEric Cheng extern void mac_srs_adjust_subflow_bwlimit(struct mac_client_impl_s *);
692da14cebeSEric Cheng extern void mac_srs_update_drv(struct mac_client_impl_s *);
693da14cebeSEric Cheng extern void mac_update_srs_priority(mac_soft_ring_set_t *, pri_t);
694da14cebeSEric Cheng extern void mac_client_update_classifier(mac_client_impl_t *, boolean_t);
695da14cebeSEric Cheng 
696da14cebeSEric Cheng extern void mac_soft_ring_intr_enable(void *);
697efe28d82SRajagopal Kunhappan extern boolean_t mac_soft_ring_intr_disable(void *);
698da14cebeSEric Cheng extern mac_soft_ring_t *mac_soft_ring_create(int, clock_t, void *, uint16_t,
699da14cebeSEric Cheng     pri_t, mac_client_impl_t *, mac_soft_ring_set_t *,
700da14cebeSEric Cheng     processorid_t, mac_direct_rx_t, void *, mac_resource_handle_t);
701da14cebeSEric Cheng extern cpu_t *mac_soft_ring_bind(mac_soft_ring_t *, processorid_t);
702da14cebeSEric Cheng 	extern void mac_soft_ring_unbind(mac_soft_ring_t *);
703da14cebeSEric Cheng extern void mac_soft_ring_free(mac_soft_ring_t *, boolean_t);
704da14cebeSEric Cheng extern void mac_soft_ring_signal(mac_soft_ring_t *, uint_t);
705da14cebeSEric Cheng extern void mac_rx_soft_ring_process(mac_client_impl_t *, mac_soft_ring_t *,
706da14cebeSEric Cheng     mblk_t *, mblk_t *, int, size_t);
707da14cebeSEric Cheng extern mac_tx_cookie_t mac_tx_soft_ring_process(mac_soft_ring_t *,
708da14cebeSEric Cheng     mblk_t *, uint16_t, mblk_t **);
709da14cebeSEric Cheng extern void mac_srs_worker_quiesce(mac_soft_ring_set_t *);
710da14cebeSEric Cheng extern void mac_srs_worker_restart(mac_soft_ring_set_t *);
711da14cebeSEric Cheng extern void mac_rx_attach_flow_srs(mac_impl_t *, flow_entry_t *,
712da14cebeSEric Cheng     mac_soft_ring_set_t *, mac_ring_t *, mac_classify_type_t);
713da14cebeSEric Cheng 
714da14cebeSEric Cheng extern void mac_rx_srs_drain_bw(mac_soft_ring_set_t *, uint_t);
715da14cebeSEric Cheng extern void mac_rx_srs_drain(mac_soft_ring_set_t *, uint_t);
716da14cebeSEric Cheng extern void mac_rx_srs_process(void *, mac_resource_handle_t, mblk_t *,
717da14cebeSEric Cheng     boolean_t);
718da14cebeSEric Cheng extern void mac_srs_worker(mac_soft_ring_set_t *);
719da14cebeSEric Cheng extern void mac_rx_srs_poll_ring(mac_soft_ring_set_t *);
720da14cebeSEric Cheng extern void mac_tx_srs_drain(mac_soft_ring_set_t *, uint_t);
721da14cebeSEric Cheng 
722da14cebeSEric Cheng extern void mac_tx_srs_restart(mac_soft_ring_set_t *);
723da14cebeSEric Cheng extern void mac_rx_srs_remove(mac_soft_ring_set_t *);
724da14cebeSEric Cheng 
725da14cebeSEric Cheng #ifdef	__cplusplus
726da14cebeSEric Cheng }
727da14cebeSEric Cheng #endif
728da14cebeSEric Cheng 
729da14cebeSEric Cheng #endif	/* _SYS_MAC_SOFT_RING_H */
730