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_UNINIT, 77 SOFTMAC_ATTACH_INPROG, 78 SOFTMAC_ATTACH_DONE, 79 SOFTMAC_DETACH_INPROG, 80 } softmac_state_t; 81 82 typedef struct softmac_dev_s { 83 dev_t sd_dev; 84 } softmac_dev_t; 85 86 /* 87 * smac_flag values. 88 */ 89 #define SOFTMAC_GLDV3 0x01 90 #define SOFTMAC_NOSUPP 0x02 91 #define SOFTMAC_NEED_RECREATE 0x04 92 #define SOFTMAC_NOTIFY_QUIT 0x08 93 94 #define SMAC_NONZERO_NODECNT(softmac) \ 95 ((softmac->smac_softmac[0] != NULL) + \ 96 (softmac->smac_softmac[1] != NULL)) 97 98 /* 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. 102 * 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.) 108 * 109 * Locking description: 110 * WO: write once, valid the life time. 111 */ 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 */ 117 118 kmutex_t smac_mutex; 119 kcondvar_t smac_cv; 120 softmac_state_t smac_state; /* smac_mutex */ 121 /* 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. 125 */ 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 */ 131 132 /* 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 136 * be still ongoing. 137 */ 138 uint32_t smac_attachok_cnt; /* smac_mutex */ 139 /* 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 142 * pre-detach. 143 */ 144 uint32_t smac_attached_left; /* smac_mutex */ 145 146 /* 147 * Thread handles the DL_NOTIFY_IND message from the lower stream. 148 */ 149 kthread_t *smac_notify_thread; /* smac_mutex */ 150 /* 151 * Head and tail of the DL_NOTIFY_IND messsages. 152 */ 153 mblk_t *smac_notify_head; /* smac_mutex */ 154 mblk_t *smac_notify_tail; /* smac_mutex */ 155 156 /* 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. 160 */ 161 162 /* 163 * media type is needed for create <link name, linkid> mapping, so 164 * it is set for GLDv3 device as well 165 */ 166 uint_t smac_media; 167 /* DLPI style of the underlying device */ 168 int smac_style; 169 dev_t smac_dev; 170 size_t smac_saplen; 171 size_t smac_addrlen; 172 uchar_t smac_unicst_addr[MAXMACADDRLEN]; 173 uint_t smac_min_sdu; 174 uint_t smac_max_sdu; 175 uint32_t smac_margin; 176 177 /* Notifications the underlying driver can support. */ 178 uint32_t smac_notifications; 179 180 /* 181 * Capabilities of the underlying driver. 182 */ 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; 187 boolean_t smac_mdt; 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