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