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