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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #ifndef _SYS_SOFTMAC_IMPL_H
27 #define _SYS_SOFTMAC_IMPL_H
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>
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>
47 typedef void (*softmac_rx_t
)(void *, mac_resource_handle_t
, mblk_t
*,
50 typedef struct softmac_lower_rxinfo_s
{
53 } softmac_lower_rxinfo_t
;
55 typedef struct softmac_lower_s
{
57 struct softmac
*sl_softmac
;
59 struct softmac_upper_s
*sl_sup
;
60 softmac_lower_rxinfo_t
*sl_rxinfo
;
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.
70 t_uscalar_t sl_pending_prim
;
71 boolean_t sl_pending_ioctl
;
77 SOFTMAC_ATTACH_INPROG
,
79 SOFTMAC_DETACH_INPROG
,
82 typedef struct softmac_dev_s
{
89 #define SOFTMAC_GLDV3 0x01
90 #define SOFTMAC_NOSUPP 0x02
91 #define SOFTMAC_NEED_RECREATE 0x04
92 #define SOFTMAC_NOTIFY_QUIT 0x08
94 #define SMAC_NONZERO_NODECNT(softmac) \
95 ((softmac->smac_softmac[0] != NULL) + \
96 (softmac->smac_softmac[1] != NULL))
99 * The softmac structure allows all minor nodes (at most two, style-1 and
100 * style-2) for the same device to be processed. A softmac_dev_t will be
101 * created for each minor node.
103 * We try to "register" the mac after all the softmac_dev_t's are processed so
104 * that even if DLPI operations fail (because of driver bugs) for one minor
105 * node, the other minor node can still be used to register the mac.
106 * (Specifically, an incorrect xxx_getinfo() implementation will cause style-2
107 * minor node mac registration to fail.)
109 * Locking description:
110 * WO: write once, valid the life time.
112 typedef struct softmac
{
113 char smac_devname
[MAXNAMELEN
]; /* WO */
114 major_t smac_umajor
; /* WO */
115 int smac_uppa
; /* WO */
116 uint32_t smac_cnt
; /* WO, # of minor nodes */
120 softmac_state_t smac_state
; /* smac_mutex */
122 * The smac_hold_cnt field increases when softmac_hold_device() is
123 * called to force the dls_vlan_t of the device to be created. The
124 * device pre-detach fails if this counter is not 0.
126 uint32_t smac_hold_cnt
; /* smac_mutex */
127 uint32_t smac_flags
; /* smac_mutex */
128 int smac_attacherr
; /* smac_mutex */
129 mac_handle_t smac_mh
;
130 softmac_dev_t
*smac_softmac
[2]; /* smac_mutex */
133 * Number of minor nodes whose post-attach routine has succeeded.
134 * This should be the same as the numbers of softmac_dev_t.
135 * Note that it does not imply SOFTMAC_ATTACH_DONE as the taskq might
138 uint32_t smac_attachok_cnt
; /* smac_mutex */
140 * Number of softmac_dev_t left when pre-detach fails. This is used
141 * to indicate whether postattach is called because of a failed
144 uint32_t smac_attached_left
; /* smac_mutex */
147 * Thread handles the DL_NOTIFY_IND message from the lower stream.
149 kthread_t
*smac_notify_thread
; /* smac_mutex */
151 * Head and tail of the DL_NOTIFY_IND messsages.
153 mblk_t
*smac_notify_head
; /* smac_mutex */
154 mblk_t
*smac_notify_tail
; /* smac_mutex */
157 * The remaining fields are used to register the MAC for a legacy
158 * device. They are set in softmac_mac_register() and do not change.
159 * One can access them when mac_register() is done without locks.
163 * media type is needed for create <link name, linkid> mapping, so
164 * it is set for GLDv3 device as well
167 /* DLPI style of the underlying device */
172 uchar_t smac_unicst_addr
[MAXMACADDRLEN
];
175 uint32_t smac_margin
;
177 /* Notifications the underlying driver can support. */
178 uint32_t smac_notifications
;
181 * Capabilities of the underlying driver.
183 uint32_t smac_capab_flags
;
184 uint32_t smac_hcksum_txflags
;
185 boolean_t smac_no_capability_req
;
186 dl_capab_mdt_t smac_mdt_capab
;
190 * Lower stream structure, accessed by the MAC provider API. The GLDv3
191 * framework assures it's validity.
193 softmac_lower_t
*smac_lower
;
195 kmutex_t smac_active_mutex
;
197 * Set by xxx_active_set() when aggregation is created.
199 boolean_t smac_active
; /* smac_active_mutex */
201 * Numbers of the bounded streams in the fast-path mode.
203 uint32_t smac_nactive
; /* smac_active_mutex */
205 kmutex_t smac_fp_mutex
;
206 kcondvar_t smac_fp_cv
;
208 * numbers of clients that request to disable fastpath.
210 uint32_t smac_fp_disable_clients
; /* smac_fp_mutex */
211 boolean_t smac_fastpath_admin_disabled
; /* smac_fp_mutex */
214 * stream list over this softmac.
216 list_t smac_sup_list
; /* smac_fp_mutex */
219 typedef struct smac_ioc_start_s
{
220 softmac_lower_t
*si_slp
;
223 #define SMAC_IOC ('S' << 24 | 'M' << 16 | 'C' << 8)
224 #define SMAC_IOC_START (SMAC_IOC | 0x01)
227 * The su_mode of a non-IP/ARP stream is UNKNOWN, and the su_mode of an IP/ARP
228 * stream is either SLOWPATH or FASTPATH.
230 #define SOFTMAC_UNKNOWN 0x00
231 #define SOFTMAC_SLOWPATH 0x01
232 #define SOFTMAC_FASTPATH 0x02
234 typedef struct softmac_switch_req_s
{
235 list_node_t ssq_req_list_node
;
236 uint32_t ssq_expected_mode
;
237 } softmac_switch_req_t
;
239 #define DATAPATH_MODE(softmac) \
240 ((((softmac)->smac_fp_disable_clients != 0) || \
241 (softmac)->smac_fastpath_admin_disabled) ? SOFTMAC_SLOWPATH : \
246 * Locking description:
248 * WO: Set once and valid for life;
249 * SL: Serialized by the control path (softmac_wput_nondata_task())
251 typedef struct softmac_upper_s
{
252 softmac_t
*su_softmac
; /* WO */
253 queue_t
*su_rq
; /* WO */
254 queue_t
*su_wq
; /* WO */
257 * List of upper streams that has pending DLPI messages to be processed.
259 list_node_t su_taskq_list_node
; /* softmac_taskq_lock */
262 * non-NULL for IP/ARP streams in the fast-path mode
264 softmac_lower_t
*su_slp
; /* SL & su_mutex */
267 * List of all IP/ARP upperstreams on the same softmac (including
268 * the ones in both data-path modes).
270 list_node_t su_list_node
; /* smac_fp_mutex */
273 * List of datapath switch requests.
275 list_t su_req_list
; /* smac_fp_mutex */
278 * Place holder of RX callbacks used to handles data messages comes
279 * from the dedicated-lower-stream associated with the IP/ARP stream.
280 * Another RX callback is softmac_drop_rxinfo, which is a global
283 softmac_lower_rxinfo_t su_rxinfo
; /* WO */
284 softmac_lower_rxinfo_t su_direct_rxinfo
; /* WO */
287 * Used to serialize the DLPI operation and fastpath<->slowpath
288 * switching over operation.
290 kmutex_t su_disp_mutex
;
291 kcondvar_t su_disp_cv
;
292 mblk_t
*su_pending_head
; /* su_disp_mutex */
293 mblk_t
*su_pending_tail
; /* su_disp_mutex */
294 boolean_t su_dlpi_pending
; /* su_disp_mutex */
295 boolean_t su_closing
; /* su_disp_mutex */
297 uint32_t su_bound
: 1, /* SL */
298 su_active
: 1, /* SL */
299 su_direct
: 1, /* SL */
304 * Used for fastpath data path.
308 mblk_t
*su_tx_flow_mp
; /* su_mutex */
309 boolean_t su_tx_busy
; /* su_mutex */
311 * Number of softmac_srv() operation in fastpath processing.
313 uint32_t su_tx_inprocess
; /* su_mutex */
315 * SOFTMAC_SLOWPATH or SOFTMAC_FASTPATH
317 uint32_t su_mode
; /* SL & su_mutex */
320 * Whether this stream is already scheduled in softmac_taskq_list.
322 boolean_t su_taskq_scheduled
; /* softmac_taskq_lock */
325 * The DLD_CAPAB_DIRECT related notify callback.
327 mac_tx_notify_t su_tx_notify_func
; /* su_mutex */
328 void *su_tx_notify_arg
; /* su_mutex */
331 #define SOFTMAC_EQ_PENDING(sup, mp) { \
332 if ((sup)->su_pending_head == NULL) { \
333 (sup)->su_pending_head = (sup)->su_pending_tail = (mp); \
335 (sup)->su_pending_tail->b_next = (mp); \
336 (sup)->su_pending_tail = (mp); \
340 #define SOFTMAC_DQ_PENDING(sup, mpp) { \
341 if ((sup)->su_pending_head == NULL) { \
344 *(mpp) = (sup)->su_pending_head; \
345 if (((sup)->su_pending_head = (*(mpp))->b_next) == NULL)\
346 (sup)->su_pending_tail = NULL; \
347 (*(mpp))->b_next = NULL; \
352 * A macro to check whether the write-queue of the lower stream is full
353 * and packets need to be enqueued.
355 * Because softmac is pushed right above the underlying device and
356 * _I_INSERT/_I_REMOVE is not processed in the lower stream, it is
357 * safe to directly access the q_next pointer.
359 #define SOFTMAC_CANPUTNEXT(q) \
360 (!((q)->q_next->q_nfsrv->q_flag & QFULL) || canput((q)->q_next))
363 extern dev_info_t
*softmac_dip
;
364 #define SOFTMAC_DEV_NAME "softmac"
366 extern int softmac_send_bind_req(softmac_lower_t
*, uint_t
);
367 extern int softmac_send_unbind_req(softmac_lower_t
*);
368 extern int softmac_send_notify_req(softmac_lower_t
*, uint32_t);
369 extern int softmac_send_promisc_req(softmac_lower_t
*, t_uscalar_t
,
371 extern void softmac_init();
372 extern void softmac_fini();
373 extern void softmac_fp_init();
374 extern void softmac_fp_fini();
375 extern boolean_t
softmac_busy();
376 extern int softmac_fill_capab(ldi_handle_t
, softmac_t
*);
377 extern int softmac_capab_enable(softmac_lower_t
*);
378 extern void softmac_rput_process_notdata(queue_t
*, softmac_upper_t
*,
380 extern void softmac_rput_process_data(softmac_lower_t
*, mblk_t
*);
381 extern int softmac_output(softmac_lower_t
*, mblk_t
*, t_uscalar_t
,
382 t_uscalar_t
, mblk_t
**);
383 extern int softmac_mexchange_error_ack(mblk_t
**, t_uscalar_t
,
384 t_uscalar_t
, t_uscalar_t
);
386 extern int softmac_m_promisc(void *, boolean_t
);
387 extern int softmac_m_multicst(void *, boolean_t
, const uint8_t *);
388 extern int softmac_m_unicst(void *, const uint8_t *);
389 extern void softmac_m_ioctl(void *, queue_t
*, mblk_t
*);
390 extern int softmac_m_stat(void *, uint_t
, uint64_t *);
391 extern mblk_t
*softmac_m_tx(void *, mblk_t
*);
392 extern int softmac_proto_tx(softmac_lower_t
*, mblk_t
*, mblk_t
**);
393 extern void softmac_ioctl_tx(softmac_lower_t
*, mblk_t
*, mblk_t
**);
394 extern void softmac_notify_thread(void *);
396 extern int softmac_hold(dev_t
, softmac_t
**);
397 extern void softmac_rele(softmac_t
*);
398 extern int softmac_lower_setup(softmac_t
*, softmac_upper_t
*,
400 extern boolean_t
softmac_active_set(void *);
401 extern void softmac_active_clear(void *);
402 extern int softmac_fastpath_disable(void *);
403 extern void softmac_fastpath_enable(void *);
404 extern int softmac_datapath_switch(softmac_t
*, boolean_t
, boolean_t
);
406 extern void softmac_wput_data(softmac_upper_t
*, mblk_t
*);
407 extern void softmac_wput_nondata(softmac_upper_t
*, mblk_t
*);
408 extern void softmac_upperstream_close(softmac_upper_t
*);
414 #endif /* _SYS_SOFTMAC_IMPL_H */