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