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 * 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 84 typedef enum { 85 SOFTMAC_INITIALIZED, 86 SOFTMAC_READY 87 } softmac_lower_state_t; 88 89 typedef enum { 90 SOFTMAC_UNINIT, 91 SOFTMAC_ATTACH_INPROG, 92 SOFTMAC_ATTACH_DONE, 93 SOFTMAC_DETACH_INPROG, 94 } softmac_state_t; 95 96 typedef 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 */ 126 typedef 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 233 typedef 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 248 typedef 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 */ 265 typedef 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 369 extern dev_info_t *softmac_dip; 370 #define SOFTMAC_DEV_NAME "softmac" 371 372 extern int softmac_send_bind_req(softmac_lower_t *, uint_t); 373 extern int softmac_send_unbind_req(softmac_lower_t *); 374 extern int softmac_send_notify_req(softmac_lower_t *, uint32_t); 375 extern int softmac_send_promisc_req(softmac_lower_t *, t_uscalar_t, 376 boolean_t); 377 extern void softmac_init(); 378 extern void softmac_fini(); 379 extern void softmac_fp_init(); 380 extern void softmac_fp_fini(); 381 extern boolean_t softmac_busy(); 382 extern int softmac_fill_capab(ldi_handle_t, softmac_t *); 383 extern int softmac_capab_enable(softmac_lower_t *); 384 extern void softmac_rput_process_notdata(queue_t *, softmac_upper_t *, 385 mblk_t *); 386 extern void softmac_rput_process_data(softmac_lower_t *, mblk_t *); 387 extern int softmac_output(softmac_lower_t *, mblk_t *, t_uscalar_t, 388 t_uscalar_t, mblk_t **); 389 extern int softmac_mexchange_error_ack(mblk_t **, t_uscalar_t, 390 t_uscalar_t, t_uscalar_t); 391 392 extern int softmac_m_promisc(void *, boolean_t); 393 extern int softmac_m_multicst(void *, boolean_t, const uint8_t *); 394 extern int softmac_m_unicst(void *, const uint8_t *); 395 extern void softmac_m_ioctl(void *, queue_t *, mblk_t *); 396 extern int softmac_m_stat(void *, uint_t, uint64_t *); 397 extern mblk_t *softmac_m_tx(void *, mblk_t *); 398 extern int softmac_proto_tx(softmac_lower_t *, mblk_t *, mblk_t **); 399 extern void softmac_ioctl_tx(softmac_lower_t *, mblk_t *, mblk_t **); 400 extern void softmac_notify_thread(void *); 401 402 extern int softmac_hold(dev_t, softmac_t **); 403 extern void softmac_rele(softmac_t *); 404 extern int softmac_lower_setup(softmac_t *, softmac_upper_t *, 405 softmac_lower_t **); 406 extern boolean_t softmac_active_set(void *); 407 extern void softmac_active_clear(void *); 408 extern int softmac_fastpath_disable(void *); 409 extern void softmac_fastpath_enable(void *); 410 extern int softmac_datapath_switch(softmac_t *, boolean_t, boolean_t); 411 412 extern void softmac_wput_data(softmac_upper_t *, mblk_t *); 413 extern void softmac_wput_nondata(softmac_upper_t *, mblk_t *); 414 extern void softmac_upperstream_close(softmac_upper_t *); 415 416 #ifdef __cplusplus 417 } 418 #endif 419 420 #endif /* _SYS_SOFTMAC_IMPL_H */ 421