softmac_impl.h revision 9073:a5a4bb23741e
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 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#ifndef	_SYS_SOFTMAC_IMPL_H
27#define	_SYS_SOFTMAC_IMPL_H
28
29#include <sys/types.h>
30#include <sys/ethernet.h>
31#include <sys/taskq.h>
32#include <sys/sunddi.h>
33#include <sys/sunldi.h>
34#include <sys/strsun.h>
35#include <sys/stream.h>
36#include <sys/dlpi.h>
37#include <sys/mac.h>
38#include <sys/mac_provider.h>
39#include <sys/mac_client.h>
40#include <sys/mac_client_priv.h>
41#include <sys/mac_ether.h>
42
43#ifdef	__cplusplus
44extern "C" {
45#endif
46
47typedef void	(*softmac_rx_t)(void *, mac_resource_handle_t, mblk_t *,
48		    mac_header_info_t *);
49
50typedef struct softmac_lower_rxinfo_s {
51	softmac_rx_t	slr_rx;
52	void		*slr_arg;
53} softmac_lower_rxinfo_t;
54
55typedef struct softmac_lower_s {
56	ldi_handle_t		sl_lh;
57	struct softmac		*sl_softmac;
58	queue_t			*sl_wq;
59	struct softmac_upper_s	*sl_sup;
60	softmac_lower_rxinfo_t	*sl_rxinfo;
61
62	/*
63	 * sl_ctl_inprogress is used to serialize the control path.  It will
64	 * be set when either an ioctl or an M_{PC,}PROTO message is received
65	 * from the upper layer, and will be cleared when processing done.
66	 */
67	kmutex_t		sl_ctl_mutex;
68	kcondvar_t		sl_ctl_cv;
69	boolean_t		sl_ctl_inprogress;
70
71	/*
72	 * When a control message is processed, either sl_pending_prim or
73	 * sl_pending_ioctl will be set.  They will be cleared when the
74	 * acknowledgement of the specific control message is received
75	 * from the underlying legacy driver.
76	 */
77	kmutex_t		sl_mutex;
78	kcondvar_t		sl_cv;
79	t_uscalar_t		sl_pending_prim;
80	boolean_t		sl_pending_ioctl;
81	mblk_t			*sl_ack_mp;
82} softmac_lower_t;
83
84typedef enum {
85	SOFTMAC_INITIALIZED,
86	SOFTMAC_READY
87} softmac_lower_state_t;
88
89typedef enum {
90	SOFTMAC_UNINIT,
91	SOFTMAC_ATTACH_INPROG,
92	SOFTMAC_ATTACH_DONE,
93	SOFTMAC_DETACH_INPROG,
94} softmac_state_t;
95
96typedef struct softmac_dev_s {
97	dev_t	sd_dev;
98} softmac_dev_t;
99
100/*
101 * smac_flag values.
102 */
103#define	SOFTMAC_GLDV3		0x01
104#define	SOFTMAC_NOSUPP		0x02
105#define	SOFTMAC_NEED_RECREATE	0x04
106#define	SOFTMAC_NOTIFY_QUIT	0x08
107
108#define	SMAC_NONZERO_NODECNT(softmac)		\
109	((softmac->smac_softmac[0] != NULL) +	\
110	(softmac->smac_softmac[1] != NULL))
111
112/*
113 * The softmac structure allows all minor nodes (at most two, style-1 and
114 * style-2) for the same device to be processed.  A softmac_dev_t will be
115 * created for each minor node.
116 *
117 * We try to "register" the mac after all the softmac_dev_t's are processed so
118 * that even if DLPI operations fail (because of driver bugs) for one minor
119 * node, the other minor node can still be used to register the mac.
120 * (Specifically, an incorrect xxx_getinfo() implementation will cause style-2
121 * minor node mac registration to fail.)
122 *
123 * Locking description:
124 *	WO: write once, valid the life time.
125 */
126typedef struct softmac {
127	char		smac_devname[MAXNAMELEN];	/* WO */
128	major_t		smac_umajor;			/* WO */
129	int		smac_uppa;			/* WO */
130	uint32_t	smac_cnt;	/* WO, # of minor nodes */
131
132	kmutex_t	smac_mutex;
133	kcondvar_t	smac_cv;
134	softmac_state_t	smac_state;		/* smac_mutex */
135	/*
136	 * The smac_hold_cnt field increases when softmac_hold_device() is
137	 * called to force the dls_vlan_t of the device to be created.  The
138	 * device pre-detach fails if this counter is not 0.
139	 */
140	uint32_t	smac_hold_cnt;		/* smac_mutex */
141	uint32_t	smac_flags;		/* smac_mutex */
142	int		smac_attacherr;		/* smac_mutex */
143	mac_handle_t	smac_mh;
144	softmac_dev_t	*smac_softmac[2];	/* smac_mutex */
145
146	/*
147	 * Number of minor nodes whose post-attach routine has succeeded.
148	 * This should be the same as the numbers of softmac_dev_t.
149	 * Note that it does not imply SOFTMAC_ATTACH_DONE as the taskq might
150	 * be still ongoing.
151	 */
152	uint32_t	smac_attachok_cnt;	/* smac_mutex */
153	/*
154	 * Number of softmac_dev_t left when pre-detach fails. This is used
155	 * to indicate whether postattach is called because of a failed
156	 * pre-detach.
157	 */
158	uint32_t	smac_attached_left;	/* smac_mutex */
159
160	/*
161	 * Thread handles the DL_NOTIFY_IND message from the lower stream.
162	 */
163	kthread_t	*smac_notify_thread;	/* smac_mutex */
164	/*
165	 * Head and tail of the DL_NOTIFY_IND messsages.
166	 */
167	mblk_t		*smac_notify_head;	/* smac_mutex */
168	mblk_t		*smac_notify_tail;	/* smac_mutex */
169
170	/*
171	 * The remaining fields are used to register the MAC for a legacy
172	 * device.  They are set in softmac_mac_register() and do not change.
173	 * One can access them when mac_register() is done without locks.
174	 */
175
176	/*
177	 * media type is needed for create <link name, linkid> mapping, so
178	 * it is set for GLDv3 device as well
179	 */
180	uint_t		smac_media;
181	/* DLPI style of the underlying device */
182	int		smac_style;
183	dev_t		smac_dev;
184	size_t		smac_saplen;
185	size_t		smac_addrlen;
186	uchar_t		smac_unicst_addr[MAXMACADDRLEN];
187	uint_t		smac_min_sdu;
188	uint_t		smac_max_sdu;
189	uint32_t	smac_margin;
190
191	/* Notifications the underlying driver can support. */
192	uint32_t	smac_notifications;
193
194	/*
195	 * Capabilities of the underlying driver.
196	 */
197	uint32_t	smac_capab_flags;
198	uint32_t	smac_hcksum_txflags;
199	boolean_t	smac_no_capability_req;
200	dl_capab_mdt_t	smac_mdt_capab;
201	boolean_t	smac_mdt;
202
203	/*
204	 * Lower stream structure, accessed by the MAC provider API. The GLDv3
205	 * framework assures it's validity.
206	 */
207	softmac_lower_t	*smac_lower;
208
209	kmutex_t	smac_active_mutex;
210	/*
211	 * Set by xxx_active_set() when aggregation is created.
212	 */
213	boolean_t	smac_active;	/* smac_active_mutex */
214	/*
215	 * Numbers of the bounded streams in the fast-path mode.
216	 */
217	uint32_t	smac_nactive;	/* smac_active_mutex */
218
219	kmutex_t	smac_fp_mutex;
220	kcondvar_t	smac_fp_cv;
221	/*
222	 * numbers of clients that request to disable fastpath.
223	 */
224	uint32_t	smac_fp_disable_clients;	/* smac_fp_mutex */
225	boolean_t	smac_fastpath_admin_disabled;	/* smac_fp_mutex */
226
227	/*
228	 * stream list over this softmac.
229	 */
230	list_t			smac_sup_list;		/* smac_fp_mutex */
231} softmac_t;
232
233typedef struct smac_ioc_start_s {
234	softmac_lower_t	*si_slp;
235} smac_ioc_start_t;
236
237#define	SMAC_IOC	('S' << 24 | 'M' << 16 | 'C' << 8)
238#define	SMAC_IOC_START	(SMAC_IOC | 0x01)
239
240/*
241 * The su_mode of a non-IP/ARP stream is UNKNOWN, and the su_mode of an IP/ARP
242 * stream is either SLOWPATH or FASTPATH.
243 */
244#define	SOFTMAC_UNKNOWN		0x00
245#define	SOFTMAC_SLOWPATH	0x01
246#define	SOFTMAC_FASTPATH	0x02
247
248typedef struct softmac_switch_req_s {
249	list_node_t	ssq_req_list_node;
250	uint32_t	ssq_expected_mode;
251} softmac_switch_req_t;
252
253#define	DATAPATH_MODE(softmac)						\
254	((((softmac)->smac_fp_disable_clients != 0) ||			\
255	(softmac)->smac_fastpath_admin_disabled) ? SOFTMAC_SLOWPATH :	\
256	SOFTMAC_FASTPATH)
257
258
259/*
260 * Locking description:
261 *
262 *	WO: Set once and valid for life;
263 *	SL: Serialized by the control path (softmac_wput_nondata_task())
264 */
265typedef struct softmac_upper_s {
266	softmac_t		*su_softmac;	/* WO */
267	queue_t			*su_rq;		/* WO */
268	queue_t			*su_wq;		/* WO */
269
270	/*
271	 * List of upper streams that has pending DLPI messages to be processed.
272	 */
273	list_node_t		su_taskq_list_node; /* softmac_taskq_lock */
274
275	/*
276	 * non-NULL for IP/ARP streams in the fast-path mode
277	 */
278	softmac_lower_t		*su_slp;	/* SL & su_mutex */
279
280	/*
281	 * List of all IP/ARP upperstreams on the same softmac (including
282	 * the ones in both data-path modes).
283	 */
284	list_node_t		su_list_node;	/* smac_fp_mutex */
285
286	/*
287	 * List of datapath switch requests.
288	 */
289	list_t			su_req_list;	/* smac_fp_mutex */
290
291	/*
292	 * Place holder of RX callbacks used to handles data messages comes
293	 * from the dedicated-lower-stream associated with the IP/ARP stream.
294	 * Another RX callback is softmac_drop_rxinfo, which is a global
295	 * variable.
296	 */
297	softmac_lower_rxinfo_t	su_rxinfo;		/* WO */
298	softmac_lower_rxinfo_t	su_direct_rxinfo;	/* WO */
299
300	/*
301	 * Used to serialize the DLPI operation and fastpath<->slowpath
302	 * switching over operation.
303	 */
304	kmutex_t		su_disp_mutex;
305	kcondvar_t		su_disp_cv;
306	mblk_t			*su_pending_head;	/* su_disp_mutex */
307	mblk_t			*su_pending_tail;	/* su_disp_mutex */
308	boolean_t		su_dlpi_pending;	/* su_disp_mutex */
309	boolean_t		su_closing;		/* su_disp_mutex */
310
311	uint32_t		su_bound : 1,		/* SL */
312				su_active : 1,		/* SL */
313				su_direct : 1;		/* SL */
314
315	/*
316	 * Used for fastpath data path.
317	 */
318	kmutex_t		su_mutex;
319	kcondvar_t		su_cv;
320	mblk_t			*su_tx_flow_mp;		/* su_mutex */
321	boolean_t		su_tx_busy;		/* su_mutex */
322	/*
323	 * Number of softmac_srv() operation in fastpath processing.
324	 */
325	uint32_t		su_tx_inprocess;	/* su_mutex */
326	/*
327	 * SOFTMAC_SLOWPATH or SOFTMAC_FASTPATH
328	 */
329	uint32_t		su_mode;		/* SL & su_mutex */
330
331	/*
332	 * Whether this stream is already scheduled in softmac_taskq_list.
333	 */
334	boolean_t		su_taskq_scheduled;	/* softmac_taskq_lock */
335} softmac_upper_t;
336
337#define	SOFTMAC_EQ_PENDING(sup, mp) {					\
338	if ((sup)->su_pending_head == NULL) {				\
339		(sup)->su_pending_head = (sup)->su_pending_tail = (mp);	\
340	} else {							\
341		(sup)->su_pending_tail->b_next = (mp);			\
342		(sup)->su_pending_tail = (mp);				\
343	}								\
344}
345
346#define	SOFTMAC_DQ_PENDING(sup, mpp) {					\
347	if ((sup)->su_pending_head == NULL) {				\
348		*(mpp) = NULL;						\
349	} else {							\
350		*(mpp) = (sup)->su_pending_head;			\
351		if (((sup)->su_pending_head = (*(mpp))->b_next) == NULL)\
352			(sup)->su_pending_tail = NULL;			\
353		(*(mpp))->b_next = NULL;				\
354	}								\
355}
356
357/*
358 * A macro to check whether the write-queue of the lower stream is full
359 * and packets need to be enqueued.
360 *
361 * Because softmac is pushed right above the underlying device and
362 * _I_INSERT/_I_REMOVE is not processed in the lower stream, it is
363 * safe to directly access the q_next pointer.
364 */
365#define	SOFTMAC_CANPUTNEXT(q)	\
366	(!((q)->q_next->q_nfsrv->q_flag & QFULL) || canput((q)->q_next))
367
368
369extern dev_info_t		*softmac_dip;
370#define	SOFTMAC_DEV_NAME	"softmac"
371
372extern int	softmac_send_bind_req(softmac_lower_t *, uint_t);
373extern int	softmac_send_unbind_req(softmac_lower_t *);
374extern int	softmac_send_notify_req(softmac_lower_t *, uint32_t);
375extern int	softmac_send_promisc_req(softmac_lower_t *, t_uscalar_t,
376    boolean_t);
377extern void	softmac_init();
378extern void	softmac_fini();
379extern void	softmac_fp_init();
380extern void	softmac_fp_fini();
381extern boolean_t softmac_busy();
382extern int	softmac_fill_capab(ldi_handle_t, softmac_t *);
383extern int	softmac_capab_enable(softmac_lower_t *);
384extern void	softmac_rput_process_notdata(queue_t *, softmac_upper_t *,
385    mblk_t *);
386extern void	softmac_rput_process_data(softmac_lower_t *, mblk_t *);
387extern int	softmac_output(softmac_lower_t *, mblk_t *, t_uscalar_t,
388    t_uscalar_t, mblk_t **);
389extern int	softmac_mexchange_error_ack(mblk_t **, t_uscalar_t,
390    t_uscalar_t, t_uscalar_t);
391
392extern int	softmac_m_promisc(void *, boolean_t);
393extern int	softmac_m_multicst(void *, boolean_t, const uint8_t *);
394extern int	softmac_m_unicst(void *, const uint8_t *);
395extern void	softmac_m_ioctl(void *, queue_t *, mblk_t *);
396extern int	softmac_m_stat(void *, uint_t, uint64_t *);
397extern mblk_t	*softmac_m_tx(void *, mblk_t *);
398extern int	softmac_proto_tx(softmac_lower_t *, mblk_t *, mblk_t **);
399extern void	softmac_ioctl_tx(softmac_lower_t *, mblk_t *, mblk_t **);
400extern void	softmac_notify_thread(void *);
401
402extern int	softmac_hold(dev_t, softmac_t **);
403extern void	softmac_rele(softmac_t *);
404extern int	softmac_lower_setup(softmac_t *, softmac_upper_t *,
405    softmac_lower_t **);
406extern boolean_t	softmac_active_set(void *);
407extern void	softmac_active_clear(void *);
408extern int	softmac_fastpath_disable(void *);
409extern void	softmac_fastpath_enable(void *);
410extern int	softmac_datapath_switch(softmac_t *, boolean_t, boolean_t);
411
412extern void	softmac_wput_data(softmac_upper_t *, mblk_t *);
413extern void	softmac_wput_nondata(softmac_upper_t *, mblk_t *);
414extern void	softmac_upperstream_close(softmac_upper_t *);
415
416#ifdef	__cplusplus
417}
418#endif
419
420#endif	/* _SYS_SOFTMAC_IMPL_H */
421